Pokazywanie postów oznaczonych etykietą JavaScript. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą JavaScript. Pokaż wszystkie posty

poniedziałek, 30 czerwca 2014

get nested property of object

Function that allows to get nested property of object. If it is not defined, function will return undefined.

var getProperty = function(obj, propertySrc) {
    var src = propertySrc.split('.');
    var res = obj;

    for (var i = 0, l = src.length; i < l; ++i) {
        if (!(src[i] in res)) {
            return void(0);
        }
        res = res[src[i]];
    }
    return res;
};
Working example: http://jsfiddle.net/gkucmierz/5Df5D/

niedziela, 23 lutego 2014

sort - stabilność sortowania

Kod JavaScript, którym można sprawdzić czy zaimplementowany algorytm sortowania jest stabilny czy nie.

var a = [
    {n: 1, str: 'first'},
    {n: 2, str: 'stable check 1'},
    {n: 2, str: 'stable check 2'},
    {n: 3, str: 'last'}
];

a.sort(function(a, b) {
    return a.n - b.n;
});

Przykład jsfiddle: http://jsfiddle.net/gkucmierz/WWGa8/1/

wtorek, 28 stycznia 2014

recursiveEach

recursiveEach - rekursywna iteracja po obiekcie. Funkcja do prawidłowego działania wymaga również 2 innych funkcji znajdujących się na tym blogu: getType oraz each.
Funkcję można dodatkowo rozbudować. Np. idealnie byłoby, gdyby w docelowej funkcji zamiast samej wartości klucza zwracała tablicę stringów wskazujących na ścieżkę do tego klucza w głównym obiekcie.

var recursiveEach = function recur(obj, fn, depth) {
  if (typeof depth === 'undefined')
    depth = -1;

  var res = {};

  if (getType(obj) === 'Object' && depth !== 0) {
    each(obj, function (el, key) {
      res[key] = recur(el, fn, depth - 1);
    });
    return res;
  }
  return fn(obj);
};

var getType = function (obj) {
  return ({}).toString.call(obj).slice(8, -1);
};

var each = function (obj, fn) {
  var res = {};
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      res[i] = fn.call(obj, obj[i], i);
    }
  }
  return res;
};

Przy pomocy tej funkcji łatwo zaimplementować funkcję flatten. Do funkcji flatten można przekazać zarówno obiekt jak i tablicę.
var flatten = function(obj) {
  var res = [];
  recursiveEach(obj, function(val) {
    res.push(val);
  });
  return res;
};

środa, 22 stycznia 2014

asyncMap - asynchroniczne iterowanie po tablicy

Funkcja pozwalająca na iterację po tablicy w sposób asynchroniczny. Można dzięki niej w genialnie prosty sposób wykonać np. kolejkę zadań, które wymagają wykonania asynchronicznych akcji np. zapytanie do innego serwera.

var asyncMap = function(arr, fn, endFn) {
 var i = 0,
  len = arr.length,
  res = [];

 (function callee() {
  fn(arr[i], i, function(singleRes) {
   res.push(singleRes);
   if (++i < len) {
    callee();
   } else {
    endFn(res);
   }
  }, arr);
 })();
};
prosty przykład użycia: http://jsfiddle.net/gkucmierz/QzLP5/

niedziela, 29 września 2013

DialogsControl - kontrolowanie domyślnych okien dialogowych

Prosta funkcja/klasa pozwalająca kontrolować (udawać) okna dialogowe.
Przy pomocy metody disable możemy wyłączyć wyświetlanie wszystkich okien dialogowych. oba parametry tej metody pozwalają ustawić wartości zwracane przez funkcje confirm oraz prompt. Domyślne ich wartości to odpowiednio true oraz '' (pusty string).
Metoda restore pozwala przywrócić domyślne wartości tych funkcji czyli oryginalne okna dialogowe w obiekcie window. Domyślne pod warunkiem, że nie były one modyfikowane przez inny skrypt.

var DialogsControl = function(w){
  w = w || window;
  var d = {
    alert: w.alert,
    confirm: w.confirm,
    prompt: w.prompt
  };

  return {
    disable: function(confirmRet, promptRet){
      if (typeof confirmRet === 'undefined')
        confirmRet = true;
      if (typeof promptRet === 'undefined')
        promptRet = '';
      w.alert = function(){};
      w.confirm = function(){return confirmRet;};
      w.prompt = function(){return promptRet;};
    },
    restore: function(){
      w.alert = d.alert;
      w.confirm = d.confirm;
      w.prompt = d.prompt;
    }
  };    
};

Gotowy kod z przykładami wywołania można przetestować tutaj http://jsfiddle.net/a8BvR/

onContentChange

Troszkę słabe rozwiązanie, ale pozwala wykryć zdarzenie zmiany treści na dowolnej stronie.

var onContentChange = function(htmlEl, fn) {
  var content = htmlEl.innerHTML;
  (function callee(){
    if (htmlEl.innerHTML !== content) {
      fn(htmlEl.innerHTML, content);
      return;
    }
    setTimeout(callee, 50);
  })();
};

Zdarzenie po wykryciu odpina się automatycznie.

Przykład wywołania:

onContentChange(document.querySelector('div'), function(n, o){
  alert(
    'changed'+"\n"+
    'old value: '+o+"\n"+
    'new value: '+n
  );
});

jsfiddle: http://jsfiddle.net/f82Um/1/

czwartek, 12 września 2013

waitFor - zaczekaj na pojawienie się obiektu

Funkcja, która w bardzo prymitywny sposób czeka na pojawienie się oczekiwanego obiektu w bliżej nie określonym czasie. Czasami takie coś może się przydać jeśli inny skrypt tworzy obiekty i nie wiemy kiedy się pojawią.

var waitFor = function(obj, srcArr, fn, opt){
  opt = opt || {t: 50};

  (function callee(){
    var tmp = obj;
    var tid = setTimeout(callee, opt.t);
    for (var i = 0; i < srcArr.length; ++i) {
      if (typeof tmp[srcArr[i]] !== 'undefined') {
        tmp = tmp[srcArr[i]];
      } else {
        return;
      }
    }
    clearTimeout(tid);
    fn(tmp, obj);
  })();
};
Poniżej przykład użycia:
waitFor(window, 'abc.def'.split('.'), function(data, obj){
  alert('jest: ' + data);
});

setTimeout(function(){
  window.abc = {};
  
  setTimeout(function(){
    window.abc.def = 'obiekt/dane';
  }, 1e3);
}, 1e3);

uruchamianie chrome script w oryginalnym window

Jak wiadomo w rozszerzeniach google chrome, kiedy chcemy użyć obiektu window i wykonać interakcję z istniejącymi skryptami na stronie, lub zostawić dostęp do funkcji tak aby była widoczna z konsoli mamy mocno utrudnione zadanie ponieważ przeglądarka tworzy specjalnie dla skryptu nowy wirtualny obiekt window.

Poniżej stworzyłem kawałek kodu - hack, który pozwala na wykonanie naszego userscript w oryginalnym scope.
Może da się to zrobić jakoś lepiej. Zapraszam do komentowania.

"use strict";

(function main(w){
  if (chrome.extension) {
    var s = document.createElement('script');
    s.src = 'data:text/javascript;base64,' + btoa('('+main.toString()+')(window);');
    document.getElementsByTagName('head')[0].appendChild(s);
    return;
  }

  w.test = "ta zmienna powinna byc widoczna z konsoli";

})(window);

niedziela, 10 lutego 2013

Odblokowanie prawego klawisza myszy

Niektóre strony blokują prawy klawisz myszy w dokumencie. Przykładowy, kod który to realizuje znajduje się pod adresem pastebin.com/jyKeaZpZ.

Aby sobie z tym poradzić bez wyłączania JavaScript wystarczy wkleić poniższy kod do paska adresu.

javascript:document.oncontextmenu=function(){};

środa, 6 lutego 2013

Global scope

Przydatne do sprawdzania co jest w przeglądarce. Co zostało dodane przez skrypty a nie jest natywnym elementem JavaScript`u czy DOM.

(function(){
  var w = window.open('about:blank');
  var res = [];
  for( var i in window ){
    if( typeof w[i] === 'undefined' ){
      res.push(i);
    }
  }
  w.close();
  return res;
})().join('\n');

środa, 23 stycznia 2013

odpowiednik htmlspecialchars w js

Odpowiednik funkcji htmlspecialchars znanej z PHP.
var htmlspecialchars = function(html){
  return [
    [/&/g, '&amp;'],
    [/</g, '&lt;'],
    [/>/g, '&gt;'],
    [/"/g, '&quot;'],
    [/'/g, '&#39;']
  ].reduce(function(h, r){
    return h.replace(r[0], r[1]);
  }, html);
};
Funkcja przydatna np. do umieszczania kodu na tym blogu. Przykład użycia:
prompt('skopiuj kod HTML', htmlspecialchars(prompt('podaj kod HTML')));

poniedziałek, 21 stycznia 2013

Binary - operacje na bitach

Funkcja upraszczająca operacje na bitach w JavaScript.
var Binary = function(val){
  val = val || 0;

  return {
    value: function(v){
      if( typeof v === 'undefined' )
        return val;
      val = v;
    },
    bit: function(n, v){
      if( typeof v === 'undefined' )
        return val & (1<<n) ? 1 : 0;
      if( v ){
        val |= 1<<n;
      }else{
        val &= ~(1<<n);
      }
    },
    toString: function(){
      return val.toString(2);
    }
  };
};
Warto pamiętać, że operacje bitowe w JavaScript są powolne, ponieważ JavaScript przechowuje wszystkie liczby (Number) jako double. W związku z tym każda operacja bitowa (przesunięcie bitowe, suma bitowa czy iloczyn bitowy) wymusza konwersję double na int.
// utworz nowa wartosc 5
var b = new Binary(5);
// odczytaj drugi bit
console.log(b.bit(2));
// ustaw pierwszy bit na 1
b.bit(1, true);
// odczytaj wartosc liczbowa
console.log(b.value());

sobota, 5 stycznia 2013

getForm oraz getFormInputs

Dwie przydatne funkcje przy sprawdzaniu pól formularza na stronie. Pierwsza funkcja getForm wyszukuje formularz zawierający podany jako argument element.
var getForm = function(htmlObj){
  return htmlObj.form || (function callee(o){
    return o.tagName === 'FORM' ? o : o.parentNode && callee(o.parentNode);
  })(htmlObj);
};
Kolejna funkcja getFormInputs znajduje wszystkie pola wysyłane do serwera. Zwraca obiekt z kluczami zawierającymi name pola oraz im odpowiadającymi wartościami zawierającymi value pola.
var getFormInputs = function(form){
  var res = {};
  [].concat(
    [].slice.call(document.getElementsByTagName('textarea')),
    [].slice.call(document.getElementsByTagName('input'))
  ).map(function(obj){
    if( typeof obj.name !== 'undefined' ){
      res[obj.name] = obj.value;
    }
  });
  return res;
};

piątek, 28 grudnia 2012

Breakpoint js

Breakpoint - przydatna funkcja do przerywania asynchronicznego kodu. Wymaga obecności DOM (Document Object Model). Tworzy w nim przycisk, który umożliwia ręczne wywołanie zatrzymanych fragmentów kodu. Funkcja pozwala sprawnie śledzić błędy w ekstremalnych warunkach :)
var Breakpoint = (function(doc){
  doc = doc || document;
  var fns = [];

  var btn = doc.createElement('button');
  btn.innerHTML = 'Breakpoint';

  btn.addEventListener('click', function(e){
    fns.shift().call();
    update();
  });

  doc.body.appendChild(btn);

  var update = function(){
    btn.disabled = !fns.length;
  };

  update();

  return {
    add: function(fn){
      fns.push(fn);
      update();
    }
  };
})();
Przykład użycia:
// bez Breakpoint:
var test = function(){
  // czynnosc A
  // czynnosc B
};

// to samo z Breakpoint:
var test = function(){
  // czynnosc A
  Breakpoint.add(function(){
    // czynnosc B
  });
};

sobota, 3 marca 2012

Array unique - czyli pozbywamy się duplikatów

Funkcja jako argument przyjmuje tablicę z danymi dowolnego typu. W rezultacie funkcja zwraca tablicę zawierającą tylko unikalne elementy tablicy źródłowej.
var unique = function(arr){
  return arr.filter(function(el, i){
    return arr.indexOf(el, i+1) === -1;
  });
};
Poniżej zamieszczam funkcję robiącą to samo co powyższa funkcja z drobnym wyjątkiem. Poniższa funkcja zawiera dwa dodatkowe wykonania funkcji reverse co pozwoliło na zachowanie naturalnej kolejności elementów występujących w tablicy. Pierwsze wystąpienie danego elementu pozostaje w tym samym miejscu, kolejne wystąpienia tego samego elementu są ignorowane. W poprzedniej wersji funkcji to ostatni element zostałby zachowany.
var unique = function(arr){
  return arr.reverse().filter(function(el, i){
    return arr.indexOf(el, i+1) === -1;
  }).reverse();
};

let unique = [...new Set(myArray)];

środa, 22 lutego 2012

getType - sprawdzenie typu, pewniejsze od typeof

Poniżej zamieszczam funkcję zwracającą typ danej. Funkcja w przeciwieństwie do operatora typeof znacznie skuteczniej oddaje typ przekazanej danej. Pomysł został zaczerpnięty z serwisu JavaScript Garden. Funkcja do sprawdzenia typu wykorzystuje generyczną funkcję toString podstawowego obiektu.
var getType = function(obj){
  return ({}).toString.call(obj).slice(8, -1);
};
Poniżej szybkie sprawdzenie różnic funkcji getType oraz operatora typeof. Pomaga on uświadomić sobie, z jakimi problemami mamy do czynienia, jeśli używamy operatora typeof.
[{}, [], '', 0, 1/0, false, function(){}, /./, null, undefined].map(function(obj){
  return [getType(obj), typeof obj];
});
Tak naprawdę operator typeof JavaScriptu ma tylko jedno uzasadnione zastosowanie.
typeof variable === 'undefined';

wtorek, 14 lutego 2012

Object each - iteracja po obiekcie

Poniżej zamieszczam bardzo przydatną funkcję pozwalającą w prosty sposób iterować po obiekcie.
var each = function(obj, fn){
  var res = {};
  for( var i in obj ){
    if( obj.hasOwnProperty(i) ){
      res[i] = fn.call(obj, obj[i], i);
    }
  }
  return res;
};
Przykład zastosowania:
each({
  name: 'Grzegorz',
  job: 'web developer',
  website: 'gkucmierz.blogspot.com'
}, function(value, key){
  alert([key, ': ', value].join(''));
});

poniedziałek, 13 lutego 2012

Twoja przeglądarka nie obsługuje JavaScript

Przeglądając kod źródłowy pewnej strony natknąłem się na ciekawy kawałek kodu. Na szczególną uwagę zasługuje linijka 902 :)

sobota, 11 lutego 2012

Array shuffle

Implementacja funkcji mieszającej elementy tablicy w języku JavaScript.
Array.prototype.shuffle = function(){
  return this.sort(function(){
    return Math.random() - 0.5;
  });
};
Przykład użycia:
[1, 2, 3].shuffle();
Poniżej inna implementacja bez użycia prototypów.
var shuffle = function(arr){
  return arr.sort(function(){
    return Math.random() - 0.5;
  });
};

piątek, 10 lutego 2012

Pobranie treści strony przy pomocy XMLHttpRequest

Poniższa funkcja pozwala pobrać treść podstrony przy pomocy JavaScript.
var get = function(url, fn){
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.onabort = xhr.onerror = function(){
    fn(false);
  };
  xhr.onreadystatechange = function(resp){
    if( xhr.readyState === 4 ){
      fn(resp.target.responseText, resp);
    }
  };
  xhr.send();
};