December 26, 2012

False promises by promises

So the critiques to my previous article is that is too short or that the article "miss the point" without explicitly saying what is such "point". The best written arguments for promises I could find are this ones:
Now, in an asynchronous world, you can no longer return values: they simply aren't ready in time. Similarly, you can't throw exceptions, because nobody's there to catch them. So we descend into the so-called "callback hell," where composition of return values involves nested callbacks, and composition of errors involves passing them up the chain manually, and oh by the way you'd better never throw an exception or else you'll need to introduce something crazy like domains. The point of promises is to give us back functional composition and error bubbling in the async world. They do this by saying that your functions should return a promise, which can do one of two things: Become fulfilled by a value Become rejected with an exception
Let's go slowly through every bit.
(..)we descend into the so-called "callback hell," where composition of return values involves nested callbacks, and composition of errors involves passing them up the chain manually
This is dishonest; there are thousands of effective ways to avoid "callback hell" without introducing a library that changes the way Javascript is written and without pretending that every library should use that library:
function start(){
 
 start.time = new Date();
 fs.readFile("example.txt", readHandler );

}

function readHandler(err, data){

 if(err)throw err;
 console.log(data, start.time);
 
}
Oh by the way you'd better never throw an exception or else you'll need to introduce something crazy like domains.
This is a problem but not one that this library solves; you can't throw an exception in promises neither; you have to encapsulate it in a promise and becomes effective when it bubbles up to a callback that cares about such error.
The point of promises is to give us back functional composition and error bubbling in the async world.
The way you get effective error bubbling is not by introducing a new layer of complexity to the way Javascript is written, but to promote a sane consistent way of writing callbacks among Javascript developers preferably by using a simple popular solution like the one used in Node.js of returning the error in the first argument and data in the second (and optionally higher)
callback( error, data );
They do this by saying that your functions should return a promise, which can do one of two things:
Become fulfilled by a value
Become rejected with an exception
Exactly the same 2 things any well written callback should do:
Return a value
Or return an error.

December 24, 2012

I don't want promises

The next lines are about this new thing going on in the Javascript community: Promises
Chainable promises
Useless, jQuery does it for efficiency gains; gains that don't exist here. Even the syntax is the same length and sometimes longer.
Promises throw errors if an error handler is not provided
Error handlers should be always provided; if it is your own custom library fix it; if it is not use an alternative it does or fix it yourself (and make a pull request if possible).
CommonJS promise proposal [1] compliant
Oh, standards. It would even more standard not to use this.
Promises can be used securely (as separate resolver/promise pairs in ocap situations)
Don't call that security, just, no. (... what the hell is ocap?)
when() - Normalization of sync (normal values) and async (promises)
You are a big boy now, you can handle the difference
all() - Create a promise that accumulate multiple concurrent promises (failed promises resolve to Error objects)
What is the problem with array.push?
allOrNone() - Ditto, but the first promise to fail causes the composition to fail as well
Or you could use, you know; the Javascript logical AND operator ( && )
first() - Find the first promise to be fulfilled in a group of promises
Let me help you there: Array.shift()
seq() - Sequentially execute a set of promise returning functions
Dev used nested callbacks, is super effective
delay() - Returns a promise that is fulfilled after a given amount of time
Dev used setTimeout, is super effective
Promises are a software abstraction that makes working with asynchronous operations much more pleasant. In the most basic definition, your code will move from continuation-passing style, to one where your functions return a value, called a promise, which represents the eventual results of that operation.
Yeah, with the little overhead that absolutely everything will be required to be a goddamn promise. More "pleasent" is merely your subjective view and continues-passing style is better than adding a new level of complexity in the way Javascript is executed. If you need to throw an error save it in the first parameter in the callback, just like almost any Node.JS function does, is not that hard.
function(error, data){
    if(error)
    throw error;
}
And if you really have so much problems trying to get a proper stacktrace for Javascript exceptions you should try learning a little more about the library you are using; or if that fails there is a new Javascript feature in the making called "domains"; which will be like Javascript exceptions for dummies.

November 22, 2012

Fast development of pretty HTML design with CSS3 "opening" effect.

So I created a little service (v.1.0) in Node.JS where you can get categorized but random images for your HTML designs called PlaceAnything; lets create something cool with it and a little bit of CSS3. Check out the final result if you want.
for( var i = 0; i < 30 ; i++){
    $('<a href="#"></a>')
        .append('<div class="data">'+i+'</div>')
        .append('<div class="top"><img></div>')
        .append('<div class="bottom"><img></div>')            
        .appendTo("#container")
        .find('img')
            .attr('src','http://placeanything.com/AlbumArtPorn/200/200/?r='+i);
}
Don't get exited, AlbumArtPorn is just a collection by Reddit users of album art.
Now the CSS that includes the prefixes for Firefox and Webkit browsers.
body{
    background:black;
}

#container img, #container a {
    padding:0;
    margin:0;
    border:0;
    width:200px;
    height:200px;  
}

#container a {
    -webkit-perspective:200px;
    -moz-perspective:200px;
    perspective:200px;
    float:left;    
    border:1px solid black;
}

.bottom, .top {
    -webkit-transition: -webkit-transform 0.5s;    
    -moz-transition: -moz-transform 0.5s;    
    transition: transform 0.5s;    
}

.bottom {
    -webkit-transform-origin: right bottom;   
    -moz-transform-origin: right bottom;   
    transform-origin: right bottom;   
}

.top{
    -webkit-transform-origin: left top;   
    -moz-transform-origin: left top;   
    transform-origin: left top;   
}

#container .top, #container .bottom {
    height: 100px;
    overflow: hidden;
}

#container .bottom img{
    margin-top: -100px;
}

#container a:hover .bottom {
   -webkit-transform: rotateX( 117deg );    
   -moz-transform: rotateX( 117deg );    
   transform: rotateX( 117deg );    
}

#container a:hover .top {
   -webkit-transform: rotateX( -117deg );    
   -moz-transform: rotateX( -117deg );    
   transform: rotateX( -117deg );    
}

.data {
    position:absolute;
    width:100%;
    height:100%;
    max-width:200px;
    max-height:200px;
    line-height: 197px;
    color:#CCC;
    font-family: Verdana, Tahoma, serif;
    font-size:10px;
    text-align:center;
    background-image: url(http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/blackorchid.png);
    opacity:0;
    -webkit-transition:opacity 0.5s linear;
    -moz-transition:opacity 0.5s linear;
    transition:opacity 0.5s linear;
    z-index:-1;
}

#container a:hover .data {
    opacity:1;
}
This is just an example but for the sake of good practices lets add a fallback for browsers who don't support 3D CSS transformations (remember that IE9 does not support 3D transformations). ​
if( typeof document.body.style["-webkit-transform"] === "undefined" &&
    typeof document.body.style["MozTransform"] === "undefined" && 
    typeof document.body.style["transform"] === "undefined"){       
        
        $("#container a").on("mouseenter mouseleave",function(event){
            var action = ( event.type === "mouseenter" ? "hide" : "show" );
            $(this).find("img")[action]();
        });
}​
Don't forget to check out PlaceAnything; very useful for random but on-topic HTML placeholders.
Take care.

May 4, 2012

Sharing prototypes in JS

jQuery is certainly awesome, but thanks to modern browsers and the prototypical nature of Javascript we can have many of its features just by interchanging methods from different prototypes.
NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;
And now we can chain the forEach method after anything that returns a NodeList (or HTMLCollection in IE9) object.
document.getElementsByClassName("links").forEach(function(node){
 console.dir(node)
})
document.querySelectorAll(".menu").forEach(function(node){
 console.dir(node)
})
And many others work as well:
NodeList.prototype.map = HTMLCollection.prototype.map =  Array.prototype.map
NodeList.prototype.filter = HTMLCollection.prototype.filter = Array.prototype.filter
But there are some methods that do not work the way you may expect:
NodeList.prototype.pop = Array.prototype.pop
var collection = document.querySelectorAll(".example")
console.log( collection.length ) // 13
collection.pop()
console.log( collection.length ) // 13
But there is a way to avoid this problem and similar ones: instead of directly using the Array prototype we explicitly convert it to an array with a simple method.
NodeList.prototype.toArray = function(){
 return Array.prototype.slice.call(this) 
}

document.getElementsByTagName("a").toArray()
Yeah, is not as sexy but it works a lot better and nobody will have to guess if it returns a NodeList or an Array.

Just to cheer you up after that disappointment lets implement the find method on arrays, similar to the one jQuery uses.
Array.prototype.find = function(selector){
 var matches = [];
 var each = Array.prototype.forEach;
 each.call(this,function(ele){  
  if(ele.querySelectorAll){
   each.call(ele.querySelectorAll(selector),function(ele){
    if(matches.indexOf(ele) === -1){
     matches.push(ele)
    }
   })
  }
 }) 
 return matches;
}
Now we can do cool stuff, like:
[document].find(".related a").map(function(ele){
 // your awesome code
})

March 21, 2012

Zero nested callbacks

function init(){;
  //init code
  some.event(function callback1(){;
    // callback 1 code
    other.event(function callback2(){;
      // callback 2 code
      another.event(function callback3(){;
        // callback 3 code
      }) 
    })  
  })  
}
Instead of a lots of nested callbacks or creating a lot of named functions in your javascript (for node.js or browsers) you can use something like this:
function fullProcess(){
 this._step = ++this._step || 0;
 switch(this._step){
  case 0:
   // init code 
   some.event(fullProcess) 
  break;
  case 1:
   // callback 1 code
   other.event(fullProcess)
  break;
  case 2:
   // callback 2 code
   another.event(fullProcess)
  break;
  case 3:
   // callback 3 code
  break;
 } 
}
Be aware that the "this" keyword is referring to the global object and not the function.

January 13, 2012

Add class for each Internet Explorer Version

Edit: Now supports IE10! There is a little code snippet to detect the current version of IE (or if its not IE at all):
var ie = (function(){
 
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');
 
    do {
        div.innerHTML = ''; 
    } while(all[0]);
    /*@cc_on;if(v<5)v=10;@*/
    return v > 4 ? v : undef ;
 
}());
Its pretty useful; and if you want to have dynamic class names for each IE version, just do this after the initial <body> tag (with jQuery):
if(ie){$('body').addClass("ie"+ie)}
Or in plain Javascript:
if(ie){document.body.className += " ie"+ie}
Now you can easily apply CSS rules for those ugly browsers:
.ie8 #menu, ie7 #menu{
 position:absolute;  
}
.ie6 #top{
 display:none;
}
You get the idea.

November 11, 2011

SetInterval With Context

When i started experimenting with the "OOP" structures that one could use in Javascript, there was something that always annoyed me; the timeOuts and setIntervals think that the context is the global object (window) instead of the current object; so the 'this' keyword points to the global object.

function hero(){
 this.speed = 0
 this.getFaster = function(){
  this.control = setTimeout(function(){
   console.log(++this.speed) // returns NaN
  },1000) 
 }
}

var superman = new hero();
superman.getFaster()

Yeah, yeah... i have read all about why it does that... the thing is... i don't care why it does that! I just want it to work!

The good news is that it haves multiple work-arounds but the one i find the best is this simple function:

setIntervalWithContext = function(code,delay,context){
 return setInterval(function(){
  code.call(context)
 },delay) 
}

setTimeoutWithContext = function(code,delay,context){
 return setTimeout(function(){
  code.call(context)
 },delay) 
}

Now i can call this new function and have an in-context setInterval, awesomeness!

function hero(){
 this.speed = 0
 this.getFaster = function(){
  this.interval = setIntervalWithContext(function(){
   console.log(this.speed++)
   // Run Forest! RUN!!!
  },100,this)
 }
}

var flash = new hero();
flash.getFaster()

And because the function returns the ID of the interval, you can save it in a variable and clear the interval anywhere you want (including inside the callback itself)

this.interval = setIntervalWithContext(function(){
 if(this.speed++ > 100){
  clearInterval(this.interval)
 }
},100,this) 


In other news:
The graphic tool for my little project "CreativeTextBoxes" is now available:
More info at: http://creativetextboxes.com/
Graphic tool at: http://creativetextboxes.com/graphic_tool.php

September 10, 2011

jQuery CSS3 Rotate (and animate Rotation)

This is for browsers with CSS3 support only! That means Chrome 1+, Firefox 3.5+ and IE9+.

Just put this somewhere after jQuery:
(function($){
 var _e = document.createElement("canvas").width
 $.fn.cssrotate = function(d) {  
    return this.css({
  '-moz-transform':'rotate('+d+'deg)',
  '-webkit-transform':'rotate('+d+'deg)',
  '-o-transform':'rotate('+d+'deg)',
  '-ms-transform':'rotate('+d+'deg)'
 }).prop("rotate", _e ? d : null)
 }; 
 var $_fx_step_default = $.fx.step._default;
 $.fx.step._default = function (fx) {
 if(fx.prop != "rotate")return $_fx_step_default(fx);
 if(typeof fx.elem.rotate == "undefined")fx.start = fx.elem.rotate = 0;
 $(fx.elem).cssrotate(fx.now)
 }; 
})(jQuery);

And then if you want to rotate an object:
$("div").cssrotate(95) // value in degrees

And if you want animation:
$("div").animate({rotate:95},{duration:1000})

BTW if you want to check if an old browser didn't rotate the object; you can do something like this:
if($("div").prop("rotate")==null){
 // Fallback
}

August 17, 2011

Revolution in Web Design - Creative Text Boxes

Jaja ok it many not be a revolution, but its a pretty neat; check out some examples like a guitar or a triangle.

The illusion of irregular shape text boxes: Now you can give any shape you want to your HTML text container. The effect is accomplished only with empty floating <span> tags so it doesn't hurt SEO or anything like that.

This script works on IE8,IE9, Firefox and Chrome; it also works on IE7 but not as well as in the others browsers... and i couldn't care less for IE6 so don't ask for support on that browser!

Some example of how to use it:

CreativeTextBox({
text: document.getElementById("text"),
leftSizes: [410, 456, 487, 507, 520,
   524, 525, 518, 506, 485,
   454, 407, 328],
pixelDistance:40
}); 

And actually i created a website just for this script: CreativeTextBoxes.com; there you can find the documentation, a little video tutorial and a couple of tools that helps you get the shapes you want.

If after reading the documentation you have questions about how to use it post them here in this post entry; if you have questions/comments about how the script works internally please do so on Github. The code is minified on the website but it is uncompressed and commented in github.

Hope you like it.

July 26, 2011

Dont Reload jQuery on your Iframes

So, you may have some pages (in the same domain) that always are going to be loaded as iframes. But if you have jQuery loaded in the parent document and you want to use it INSIDE the iframe (a script tag inside) you just have to do this:

var $ = function(a,b){
 b = b || document;
 return parent.jQuery.apply(this,[a,b])
};

But that is only if you are not going to use document.ready or any of its shortcuts. If you want to use any of those there is a workaround (Note: The iframe needs to have an id)

var $ = function(a,b){
 var that = this;
 b = b || document;
 function ready(a){
   parent.jQuery("#"+window.frameElement.id).load(function(){a.call(that)})
 } 
 if(typeof a == "function"){
  ready(a)  
 } else {
  var r = parent.jQuery.apply(this,[a,b]);
  r.ready = ready;
  return r 
 }
};

So now you can write jQuery like it was loaded naturally inside the iframe (using the dollar sign)

July 24, 2011

Faster than jQuery(document).ready() - Wait Until Exists

Well, lets be honest; 99% of the time you are waiting for ONE <div> (or other HTML element) to exists to do some javascript; not the entire document.

So i created a javascript function called waitUntilExists and it basically does what its name says it does, it waits until one HTML element exists.

So how does it work?

waitUntilExists("id_of_the_div",function(){
 // Div exists, do whatever you want with it now
})

And that is it; you can put any code inside of it...

But guess what? Is also faster if you are waiting for all the <body> to load

This is faster:
waitUntilExists(document,function(){
 // Page finished loading
})

Than this:
jQuery(document).ready(function(){
 // Page finished loading
})

Well, but i got to be honest to you, is not faster on old versions of Internet Explorer (IE8 and all the crap before), but in any other browser it is faster.

But this thing can do stuff that $(document).ready() cannot do; it is called waitUntilExists for a reason... it will wait until the div exists no matter if it takes one milisecond or ten hours to come into existence. This can be handy for ajax and stuff like that, because you don't need callbacks, the function is executed once if the div comes into existence.

Lets check some other nice little features, there is a third paramater that is optional for the context; for example:

var obj = {}
obj.value = 123
obj.a = function(){
 waitUntilExists(document, function(){alert(this.value)},this)
}
obj.a() // outputs 123

So, in that third parameter you may want to write the keyword this.

Another nice little feature is the ability to use the HTML element as the context, you just have to write "itself" in the third parameter.

waitUntilExists("content",function(){
 this.style.background = "red"
},"itself")

Another nice little feature is to be able to remove one "listener"; so if you want to stop waiting for an HTML element to exist:

waitUntilExists.stop("id_of_div")

You can also put the function as the second parameter if you need to be specific.

The dark secret!

The code is in few words... just a wrapper of functions for a DOMNodeInserted event listener... yep, that is pretty much all about it. In old IE versions it becomes a wrapper for one setInterval.

Oh yeah... you can find the code here: http://pastebin.com/raw.php?i=XTDKbQvK

July 22, 2011

Be a god among internet users

EDIT: Bug fixed, now also works in firefox.

So many times i inject jQuery on a site to do something inside it. Here is a bookmarklet i use a lot: View it on pastebin; so basically why it does is inject jQuery (if is not already on the page) and take care about $.noConflict and all that jazz.

Drag this to your bookmarks: jQuery with prompt (or just click it to test it)

But it also brings a nice prompt in which to write the javascript code (eval is NOT evil!); and it also have some little nice features, you can open the prompt with Shift+J or by clicking the bookmarklet again. It remembers the last code you wrote on it. It also haves a handy function called print, it basically works as a wrapper for document.write javascript function. It also handle any errors in your syntax and you can use the function "$" instead of "jQuery" without breaking anything in the current web site.

So, lets see what this baby can do:

If you need to get the list of you are listening in Grooveshark, you could write this:
$(".songName").each(function(){print($(this).html())})

If you need to select all your friends in Facebook when you create an event...
$(".checkbox").click()

If you need to get all URL addresses from a Google search
$("cite").each(function(){print(this.innerHTML)})

To archive all your facebook messages (well, just current page)
$("#MessagingDashboard .archiveLink input").click();


Scrapping FUN!


Everyone loves to scrapp; so lets do that (ab)using Ajax! This code gets all links of the first 9 pages of a Google search result.

window.arrxx=[];$("#navcnt .fl").each(function(i){var opq = i;var that=this;setTimeout(function(){ $.get(that.href,function(data){ $("<div"+">").html(data).find("cite").each(function(){arrxx.push("http://"+$(this).text()) });if(opq == $("#navcnt .fl").length - 1){document.write("<pre"+">"+arrxx.join("\n")+"</p"+"re>")}})},1000*(i+1))});

July 19, 2011

jQuery weird mouseenter and mouseleave events

So jQuery is all-mighty but like any god is full of flaws... one of them is with the event.type when you are using "mouseenter" or "mouseleave",

This works fines:

$("body").bind("mouseenter",function(event){
 if(event.type == "mouseenter"){
  alert("OK")
 }
})

But in this other case the alert never gets executed

$("body").bind("mouseenter",function(event){
 setTimeout(function(){
  if(event.type == "mouseenter"){
   alert("OK")
  }
 })
})


That is because when the variable event is called inside a setTimeout (or setInterval) it returns "mouseover" instead of "mouseenter" as it should.

So just save the actual event type and you will be just fine.

$("body").bind("mouseenter",function(event){
 var eventType = event.type
 setTimeout(function(){
  if(eventType == "mouseenter"){
   alert("Mouse inside... i can feel it inside of me!")
  }
 })
})

July 18, 2011

HTML Comments are diamonds

So everyone thinks that html comments are lame... well... they are NOT! They can be extremely useful! In fact...

$("*").contents().filter(function()
 { return this.nodeType == 8;})
 .after(function(){return this.data})

- Ta-da
- What?
- What did you do that was so "ta-da"?
- Well, using jQuery i just converted all the comments content into actual HTML, so if someone had <!-- <h1>Haters gonna hate</h1> --> it will transform into actual HTML!
- And why would i want to do that?
- You know that comments don't get read by the Google Search bot, right?
- Yeah....
- Well, ajax is cool and all that... but is always faster if the content is already on the current page
- Yeah...
- Mmmm... do i need to make you a drawing or something dude?
- F*ck you.

I know some of you are lame as sh*t and don't love the all-mighty jQuery javascript library so here it is the same code in 100% pure cross-browser javascript (IE7+, Chrome, Firefox):


function find_comments(selection)
{
 selection = selection || document
 comments_found=[];
 loop(selection.childNodes)
 function loop(arr)
 {
  for(var i = 0; i<arr.length;i++)
  {
   if(arr[i].nodeType == 8)
   {
    comments_found.push(arr[i])
   }else{
    loop(arr[i].childNodes) 
   }
  }
 }
 return comments_found;
}


var comments = find_comments(document)

for(var i=0;i<comments.length;i++){
 var one_comment = comments[i]
 var div = document.createElement("div");
 div.innerHTML = one_comment.data
 for(var j=0;j<div.childNodes.length;j++){
  one_comment.parentNode.insertBefore(div.childNodes[0],one_comment)
 }
}