Create a gist now

Instantly share code, notes, and snippets.

@abernier /index.md
Last active Feb 22, 2016

What would you like to do?
JavaScript tips

transitionend

var TRANSITIONEND = (function () {
  var prefixes = {
    'transition': 'transitionend',
    'OTransition': 'otransitionend',
    'MozTransition': 'transitionend',
    'WebkitTransition': 'webkitTransitionEnd'
  };

  for (var k in prefixes) {
    if (prefixes.hasOwnProperty(k) && document.documentElement.style[k] !== undefined) {
      return prefixes[k];
    }
  }

  return;
}).call(this);

transform property

var TRANSFORM = ["transform", "webkitTransform", "MozTransform", "msTransform"].filter(function (prop) {
  return prop in document.documentElement.style;
})[0];

Load with progress

function progress(url, tick, cb) {
  tick || (tick = function () {});
  cb || (cb = function () {});

  var xhr = new XMLHttpRequest();
  xhr.onprogress = function (e) {
    if (e.lengthComputable) {
      tick(e.loaded / e.total);
    }
  };
  xhr.onload = function () {
    cb(null);
  };
  xhr.onerror = function (er) {
    cb(er);
  };
  xhr.open("GET", url, true);
  xhr.send();
}

and smoke it with:

progress('http://abernier.name/images/iscool-pelican.png', function (x) {console.log(x);}, function (er) {
  if (er) console.error(er); return;
  
  console.log('done');
});

responsive images

<img width="{w}" height="{h}'>
<noscript>
  <img src="{file1}" data-srcset="{file1} 320w,{file2} 320w 2x, {file3} 768w,{file4} 768w 2x, {file5} 1024w,{file6} 1024w 2x, {file6} 3500w">
</noscript>
  • {w} et {h} devant être la largeur et hauteur de {file1}
  • file devant être des retailles de la même image inscrite dans un carré de :
  • 160px
  • 320px
  • 1088px
  • 1536px
  • 1792px
  • 2048px

$.fn.imgsloaded

;(function () {
  //
  // one <img>
  //
  function imgloaded(src) {
    var dfd = $.Deferred();
    
    var img = document.createElement('img');
    img.onload = dfd.resolve;
    img.src = src;
    
    return dfd.promise();
  }
  
  //
  // all inner <img>s
  //
  $.fn.imgsloaded = function (options) {
    var $el = this;
  
    var dfds = [];
    $el.each(function (i, el) {
      var $imgs = $(el).find('img');
      $imgs.each(function (i, el) {
        dfds.push(imgloaded($(el).attr('src')));
      });
    });
  
    return $.when.apply($, dfds);
  };

}).call(this);

// Usage:
$('.foo, .bar').then(function () {
  alert('all innert .foo and .bar images are now fully loaded!');
});

imgloaded

function imgloaded(src, cb) {
  var img = document.createElement('img');
  img.onload = function () {
    cb(null);
  }
  img.src = src;
}

// Usage:
imgloaded('http://placehold.it/1600x600', function () {
  alert('img is fully loaded');
})

promise things

function promiseSomething() {
  var dfd = $.Deferred();
  
  // dfd.resolve(arg1, arg2)
  // dfd.reject()
  
  return dfd.promise();
}

// Usage
promiseSomething()
  .done(function (arg1, arg2) {alert('hurray!');})
  .fail(function () {alert('too bad!');})
  ;

Environment independent require (browser or server)

var $ = (function () {return this; /* ie: global or window */}()).jQuery || require('jquery');

or more simply:

var $ = this.jQuery || require('jquery');

Get image "natural" ratio

function getImageRatio(src, cb) {
  var img = new Image();
  img.onload = function () {
      var w = img.width;
      var h = img.height;
      
      var ratio = w/h;
      
      cb(null, ratio);
  }
  img.src = src;
}

// Usage
getImageRatio('http://lorempixel.com/150/240/', function (ratio) {
  alert(ratio);
});

$.fn.redman

(function($) {
  
  var defaults = {
    klass: 'red',
    autopaint: true
  }

  //
  // Constructor
  //

  function Redman(el, options) {
    options = $.extend({}, defaults, options); // Merge with defaults
    this.options = options;
    
    var $el = $(el);
    var el = $el[0];

    this.$el = $el;
    this.el = el;

    // auto paint
    if (options.autopaint !== false) {
      this.paint();
    }
  }
  Redman.prototype.paint = function () {
    this.$el.addClass(this.options.klass);
  };
  Redman.prototype.unpaint = function () {
    this.$el.removeClass(this.options.klass);
  };

  //
  // Plugin
  //

  $.fn.redman = function (options) {
    var $el = this;

    return $el.each(function () {
      var redman = new Redman($el, options);

      $el.data('redman', redman); // save as expando
    });
  };

  $.fn.redman.defaults = defaults;

}(this.jQuery));           

//
// Usage
//

var $foo = $('#foo');
$foo.redman({
  klass: 'rouge'
});
$foo.data('redman').unpaint();

backup/restore CSS styles

// backup
$(el).data('original-cssText', el.style.cssText);

// restore
el.style.cssText = $(el).data('original-cssText');

Method/function invocation pattern

var o = {
    value: 3
};

* Method invocation

When invoking a function that is a property of an object

o.incr = function () {
    this.value += 1;  // 'this' will be bound to 'o'
};
o.incr();  // Method invocation pattern

* Function invocation

When invoking a function that is not a property of an object

o.double = function () {
    var that = this;  // save the context! (Workaround)

    function helper() {
        //this.value *= 2;
        that.value *= 2;
    };

    helper();  // Function invocation pattern: 'this' will be bound to the global object
};
o.double();

Callback pattern

function asyncMult(x, y, cb) {
  var ret = x * y;

  if (_.isNumber(ret)) {
    cb(null, ret); // Ok
  } else {
    cb(new Error('fail !')); // Problem
  }
}

asyncMult(2,3, function (er, result) {
  if (er) return er;

  // otherwise, we've got the result: 6
})

Also see: http://callbackhell.com

check a variable exists

Short version:

(typeof x !== 'undefined' && x !== null)

Long version, why all this?

A variable exists as soon as it is declared:

var toto; // ok, toto exists!
;         // but here, tata does not (not declared)

now, let's try to define our exists function...

function exists(x) {
  //
}

we can't do this:

if (x) {
  return true;
} else {
  return false;
}

since it will throw an Error: ReferenceError: x is not defined

so we need typeof:

if (typeof x !== 'undefined') {
  return true;
} else {
  return false;
}

but since typeof null equals "object" we need to make sure x does not exist while being set to null, thus:

if (typeof x !== 'undefined' && x !== null) {
  return true;
} else {
  return false;
}

so

function exists(x) {
  if (typeof x !== 'undefined' && x !== null) {
    return true;
  } else {
    return false;
  }
}

commonJS module

function foo(x) {
  return 'foo' + x;
}

this.foo = foo; // this equals the global object: window or exports
if (typeof module !== "undefined" && module !== null) { // check module variable exists
  module.exports = this.foo;
}

then simply:

var foo = require('./foo');
console.log(foo(2)); // foo2

or

<script src="path/to/foo.js"></script>
<script>
alert(foo(2));
</script>

environment independent require

var $ = this.jQuery || require('jquery');

clone an array

var arr1 = [1, 2, 3];

var arr2 = arr.slice();

assert.deepEqual(arr1, arr2, "same values");
assert.notStrictEqual(arr1, arr2, "but not same object in memory")

clone an object

see: http://stackoverflow.com/a/12826757/133327

var o1 = {a: 'a', b: {c: 'c'}};

var o2 = JSON.parse(JSON.stringify(o1));

assert.deepEqual(o1, o2, "same values");
assert.notStrictEqual(o1, o2, "but not same object in memory")

Caveats: functions will be stringified, as well as Dates — use _.clone here

"class"ical inheritance

Principle: in javascript, every function - which is also an Object - has a prototype property. Why? just because functions can also be used as constructors with the new operator. If you do, then the new created object will be linked to that prototype object and will inherit from it.

function toto() {/*hey*/}

toto.prototype exists is now:

{
  constructor: function toto() {/*hey*/} // allow us to keep a reference to constructor
}

Simple:

function MyError(message) {
  this.name = "MyError";
  this.message = message;
}
MyError.prototype = new Error();
MyError.prototype.constructor = MyError;

More complete:

// Inheritance utility (see: http://coffeescript.org/#try:class%20A%0Aclass%20B%20extends%20A)
function inherit(child, parent) {
  // shallow copy own properties
  for (var key in parent) {
    if (parent.hasOwnProperty(key)) {
      child[key] = parent[key];
    }
  }

  function ctor() {this.constructor = child;}
  ctor.prototype = parent.prototype;
  child.prototype = new ctor();

  child.uber = parent.prototype; // keep a reference to parent's prototype into child.uber

  return child;
};

which can be used like:

function Animal(name) {
  this.name = name;
}
Animal.prototype.move = function (meters) {
  alert(this.name + ' moved ' + meters);
}

function Snake() {
  Animal.prototype.constructor.apply(this, arguments); // borrow parent's constructor
}
inherit(Snake, Animal); // Snake.uber = Animal.prototype
Snake.prototype.move = function () {
  alert('Slithering...');
  Animal.prototype.move.call(this, 5); // borrow parent's move method
}

See: inherit.js

walk

// Define a walk_the_DOM function that visits every
// node of the tree in HTML source order, starting
// from some given node. It invokes a function,
// passing it each node in turn. walk_the_DOM calls
// itself to process each of the child nodes.
var walk_the_DOM = function walk(node, func) {
  func(node);
  node = node.firstChild;
  while (node) {
    walk(node, func);
    node = node.nextSibling;
  }
};

relative CSS path

//
// relative CSS path
//
// Example:
// 
// <html>
//   <head>
//     <meta charset="utf-8">
//     <title></title>
//   </head>
//   ...
//
// var el = document.querySelector('title');
// var ref = document.querySelector('html')
// getPath(el, ref)
//
// Outputs: ":nth-child(1) > :nth-child(2)"
//
// If then you want to retreive an element from a path: $(<path>, ref);
//
var getPath = (function () {
  function nth(el) {
    return $(el).parent().children().index(el) + 1;
  }
  
  return function (el, ref, path) {
    path || (path = []);

    // for the 1st iteration, check el is contained within ref, otherwise return undefined
    if (path.length < 1 && !$.contains(ref, el)) {
      return;
    }

    var $el = $(el);
    var $parent = $el.parent();
    var parent = $parent[0];

    var i = nth(el);
    path.unshift(':nth-child(' + i + ')');

    if (parent === ref) {
      return path.join(' > '); // stop condition
    }

    return getPath(parent, ref, path);
  };
}());

waitUntil

//
// Wait until the test is true or a timeout occurs.
//
//   - If test succeeds before timeout, cb is executed with [null, <elapsed time>]
//   - If test does not succeed before timeout, cb is executed with [<error>]
//

function waitUntil(test, duration, cb, options) {
  options || (options = {delay: 1}); // every 1ms by default
  duration || (duration = 3000);

  var start = new Date().getTime();
  var finish = start + duration;
  var int;

  function looop() {
    var time = new Date().getTime();
    var timeout = (time >= finish);
    var condition = test();

    // No more time or condition fulfilled
    if (condition) {
      cb(null, time - start); // passed elapsed time
      clearInterval(int);
    }

    // THEN, no moretime but condition unfulfilled
    if (timeout && !condition) {
      var er = new Error('waitUntil has timeouted and the test has not passed.');
      cb(er);
      clearInterval(int);
    }
  }

  int = setInterval(looop, options.delay);
}

Assignement if not defined

options = options || {};

or

options || (options = {});

Existential

if (typeof god !== "undefined" && god !== null) {
  pray();
}

JSONP

A script tag in the document (no cross domain limitation for it) pointing to a remote resource, which returns a function executed back in the document

<script src="http://example.com/data.json" type="text/javascript" charset="utf-8"></script>
  > jsonCallback({"data": "foo"})
window.jsonCallback = function (result) { // Do stuff with the result }

or

jQuery.getJSON("http://example.com/data.json?callback=?", function (result) {
  // Do stuff with the result
});

Object.create

if (typeof Object.create !== "function") {
  Object.create = function(o) {
    function F() {};
    F.prototype = o;
    return new F();
  };
}

Proxy

var proxy = function(func, thisObject){
  return(function(){
    return func.apply(thisObject, arguments);
  });
};

Reserved words

abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment