Tomorrow I am going to #meetbing to talk about Bing ( :P ) and its present/future.
The event has been better described by Phil Leggetter and as He did, I would like to know if there is any tech question you would like me to bring there.
So far, I kinda like what Bing API offers, and I am planning to use it soon, but my only concern is about requests limits over a single IP.
Thinking about firewalled/natted/DHCPped infrastructure, 7 different people could not use a generic Bing gadget in the same moment ... anything else?
Sunday, June 28, 2009
Wednesday, June 24, 2009
ES5 arguments and callee, I was wrong!
JavaScript is not JavaScript, I am not crazy, it is just a consideration between the language itself and what is behind it: another programming language with lower level rules and logic ... sounds silly and obvious, but please keep reading to understand what I mean.
Apparently, except for Internet Explorer, I was so wrong.
arguments.callee is not a pointer or a static variable retrieved instantly as
Impressive is the responsiveness of Internet Explorer, the browser which is "die hard" and the only one I was trying to defend about this decision, due to named functions misbehavior. IE is about 100 times slower when arguments variable is used, while Firefox 3 for example is about 50 time slower when arguments.callee is discovered. Chrome is about 4 times slower with both arguments, and callee, and the same is for Safari and Opera, impressive results. A little note about Chrome, apparently the main problem is the scope resolution, rather than arguments or callee.
Avoiding conflicts via global navigator object, ES5 will tell us if the browser is compatible with ECMAScript 5 "use strict"; rule or not, allowing our code to behave differently when necessary.
It does not really matter in any case, to use my callee proposal we need to inject a callee property, as I suggested in the latest post, and for the sake of good gode, via eval:
Above function is able to take a user defined function and to inject a callee property creating another defined function, a sort of operation usually performed once and never again. In few words, inside our function body we will find another variable with local scope: callee
This strategy is particularly useful for these cases:
Last point is the one that should let us think about what we have done so far.
If we try to execute latest benchmark, we will realize that specially with Internet Explorer, the evaluation trap works faster than arguments.callee so every time we need callee, but we do not need arguments, we should go for it.
I hope I gave you more knowledge about this problem and why ECMAScript group decided to get rid of callee, and in a possible future get rid of arguments as well. One side is pro scriptish stuff, and we all love it, bot the other side is about how much this stuff could slow down Web possibilities. Stay tuned!
P.S. amazing, in FF and Chrome you can set whatever property into the navigator object and rather than transform it into a string a la window.name, you can safe whatever amount of data without loosing it until you do not close that tab!!! Stay tuned for this as well, it is a new security or hack problem we could use for better purposes ;)
No Results Yet, But I've Already Lost My Battle
I spread comments, I wrote post after posts to defend ECMAScript 5 arguments.callee decision with "use strict", but I have to admit I have never investigate the internal behavior of callee, an arguments property which is not what we think is ...Discovering In Core The Callee Property
What I was thinking was something hilarious for a C or C++ programmer: an inherited property for a mutable instance.
// JavaScript should have a "secret" Arguments class
// and for each function, something like this
function Test(){};
// we have declared the function Test
// internally there should be a secret operation like this:
Test._createArguments = function(args){
for(var i = 0; i < args.length; i++)
this[i] = args[i];
};
Test._createArguments.prototype.callee = Test;
// and for each Test call, there should be
// a secret operation like this one:
Test._injectArguments(
new Test._createArguments(args);
);
// in order to retrieve Test arguments
// variable for each call ... inheriting
// automatically the callee property
Apparently, except for Internet Explorer, I was so wrong.
arguments.callee is not a pointer or a static variable retrieved instantly as
{callee:"it's a me!"}.callee
could be, arguments, plus callee is a property with a "discover latency" able to make each call execution up to 100 times slower than a regular function!We Want Perfomance? Get Rid Of Arguments And Callee Then!
Even with most advanced JavaScript Engines, like the V8 one used by Google Chrome Browser, arguments and arguments.callee are a big bottleneck. Test by yourself!
(function(){
// Array to store execution time
var execution = [];
// named function
function factorial(i){
return i < 2 ? i : i * factorial(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
factorial(100);
t = new Date - t;
execution.push(
"Native named function: " + t
);
// named function with arguments
function fact(i){
var i = arguments[0];
return i < 2 ? i : i * fact(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
fact(100);
t = new Date - t;
execution.push(
"Native named with arguments: " + t
);
// arguments.callee
fact1 = function(i){
return i < 2 ? i : i * arguments.callee(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
fact1(100);
t = new Date - t;
execution.push(
"arguments.callee: " + t
);
alert(execution.join("\n"));
})();
Impressive is the responsiveness of Internet Explorer, the browser which is "die hard" and the only one I was trying to defend about this decision, due to named functions misbehavior. IE is about 100 times slower when arguments variable is used, while Firefox 3 for example is about 50 time slower when arguments.callee is discovered. Chrome is about 4 times slower with both arguments, and callee, and the same is for Safari and Opera, impressive results. A little note about Chrome, apparently the main problem is the scope resolution, rather than arguments or callee.
We Still Love Scripting: A Callee Proposal
During these tests, I can proudly say I found a way to understand in which era we are, thanks to this simple snippet:
// WebReflection knows if we are in ES5 era!
navigator.ES5 = (function(){"use strict";try{return !arguments.callee}catch(e){return true}})();
Avoiding conflicts via global navigator object, ES5 will tell us if the browser is compatible with ECMAScript 5 "use strict"; rule or not, allowing our code to behave differently when necessary.
It does not really matter in any case, to use my callee proposal we need to inject a callee property, as I suggested in the latest post, and for the sake of good gode, via eval:
// Another WebReflection Silly Idea
function F/*or whatever name you prefer*/(callee){
return eval("(callee="+callee+")");
};
Above function is able to take a user defined function and to inject a callee property creating another defined function, a sort of operation usually performed once and never again. In few words, inside our function body we will find another variable with local scope: callee
(function(){
"use strict"; // or not
var execution = [];
// create the function via F
factorial = F(function(i){
// we got arguments, and callee
return i < 2 ? i : i * callee(i - 1);
});
for(var i = 0, t = new Date; i < 1000; ++i)
factorial(100);
t = new Date - t;
execution.push(
"WebReflection F: " + t
);
alert(execution.join("\n"));
})();
This strategy is particularly useful for these cases:
- classic configuration object, new Ext.Panel({listeners:render:F(function(Panel){
Panel.removeListener("render", callee);
})}) - classic pre-compiled function, var circle = F(Function("r,i","return !i ? r*callee(r," + Math.PI + ") : r*i"));
- every time we would like to retrieve arguments.callee
Last point is the one that should let us think about what we have done so far.
If we try to execute latest benchmark, we will realize that specially with Internet Explorer, the evaluation trap works faster than arguments.callee so every time we need callee, but we do not need arguments, we should go for it.
Deeper Investigation
I'll keep digging inside this stuff but right now the only thing I can say is that I will try to avoid the usage of arguments.callee every single time I can because specially for the already JS speaking slow browser Internet Explorer, it is a performances killer I could not even imagine.I hope I gave you more knowledge about this problem and why ECMAScript group decided to get rid of callee, and in a possible future get rid of arguments as well. One side is pro scriptish stuff, and we all love it, bot the other side is about how much this stuff could slow down Web possibilities. Stay tuned!
P.S. amazing, in FF and Chrome you can set whatever property into the navigator object and rather than transform it into a string a la window.name, you can safe whatever amount of data without loosing it until you do not close that tab!!! Stay tuned for this as well, it is a new security or hack problem we could use for better purposes ;)
Monday, June 22, 2009
Do Not Remove arguments.callee - Part II
Few days ago kangax demystified named function expressions, underling the importance of the read only function name property and how messy is Internet Explorer JScript engine with named function and their scope.
Before that post, I wrote one about ECMAScript 5 decision to remove arguments.callee when "use strict"; is present (note in the link: it is not deprecated right now, it is an arguments property)
jQuery Ajax ?
NO? Simple enough, but of course I could use the "long kangax procedure" to wrap that function to avoid IE problems ... and in any case, what about two Ajax calls in the same page?
More comes with User Interface libraries, take ExtJS as example ...
Above snippets is so simple that ECMAScript 5 better decided to transform it into something like this:
In few words, we have to forget shortcuts to add and remove listeners for any kind of configuration object. Nice, isn't it?
The main difference between above functions is that the first one needs to discover in the scope the Math "variable" plus its PI parameters for each call, while the second one will be exactly the function:
which is about 1.6 to 2 times faster than the other one .... cool? Perfect, now try to imagine that our pre-compiled function is more complicated and inside a closure ... how the hell do you think to retrieve the function itself?
Cool enough? That function will be extremely slower than a pre-compiled one due to the global window object which is a variable not that fast to retrieve.
Moreover, since they decided that null or undefined should not be considered as window object, the usage of this of run-time called function is not a shortcut anymore, is it?
What I do not understand, is why they do not make callee a reserved keyword and put this variable inside the function body as is for arguments and the function name.
We'll see how much we will have to change our code and how bigger will be for this non-sense decision ... JavaScript beauties should not be changed, even PHP has at least a function to retrieve the arguments array ... put a function then, whatever other solution, but please do not constrict developers to name in a completely meaningless and redundant way every single lambda. Not a single lambda based language is that fossy about it, IMHO.
Before that post, I wrote one about ECMAScript 5 decision to remove arguments.callee when "use strict"; is present (note in the link: it is not deprecated right now, it is an arguments property)
How These Two Things Are Related
While kangax post was more focused about possible leaks and unexpected functions definitions, I would like to grab more attention about what this problem will cause in tomorrow libraries and JavaScript usage. Removing arguments.callee, our code size, apparently faster in core thanks to this missed variable, will increase drastically and a big part of the beauty of JavaScript language will disappear with this callee decision.The Classic Configuration Object Problem
How many libraries base constructors via configuration objects?jQuery Ajax ?
$.ajax({
url:"page.server",
success:function(data){
if(data){
$.ajax({
url:"fallback.server",
success:arguments.callee
});
} else
alert("everything is OK");
}
});
NO? Simple enough, but of course I could use the "long kangax procedure" to wrap that function to avoid IE problems ... and in any case, what about two Ajax calls in the same page?
$.ajax({
url:"page.server",
success:function success(data){
// whatever will be
// .... but don't ya think it is a bit
// redundant? How will be our code style,
// worse than an open close XML tag?
}
});
// second call ...
$.ajax({
url:"page.server",
success:function success(data){
// which one will be the
// function success in
// Internet Explorer ???
}
});
More comes with User Interface libraries, take ExtJS as example ...
new Ext.Panel({
renderTo:document.body,
listeners:{
render:function(Panel){
// do some stuff ... and ...
Panel.removeListener("render", arguments.callee);
}
}
});
Above snippets is so simple that ECMAScript 5 better decided to transform it into something like this:
new Ext.Panel({
renderTo:document.body,
listeners:{
// not suitable for IE and multiple
// Panel creations ...
render:function render(Panel){
Panel.removeListener("render", render);
}
}
});
// suitable for IE as well
new Ext.Panel({
renderTo:document.body,
listeners:{
render:function(Panel){
var callee = Panel.initialConfig.listeners.render;
// note how long and boring is precedent string/operation
Panel.removeListener("render", callee);
}
}
});
In few words, we have to forget shortcuts to add and remove listeners for any kind of configuration object. Nice, isn't it?
The Classic Pre Compiled Function Problem
Another problem comes with Function constructor, able to create an anonymous function (lambda) via string and a preferred solution over eval calls. A pre compiled function is something created once and executed at "native speed" for each call. Example:
// classic function
function circle(r){
return r * r * Math.PI;
};
// pre compiled one
var circle = Function("r", "return r * r * " + Math.PI);
The main difference between above functions is that the first one needs to discover in the scope the Math "variable" plus its PI parameters for each call, while the second one will be exactly the function:
function anonymous(r) {
return r * r * 3.141592653589793;
}
which is about 1.6 to 2 times faster than the other one .... cool? Perfect, now try to imagine that our pre-compiled function is more complicated and inside a closure ... how the hell do you think to retrieve the function itself?
(function(){
// my library scope
// this one will generate an errror
// Function evaluates in a global scope
var f = Function("i", "return i < 2 ? i : i + f(i - 1)");
// we have only two options here ...
// the elegant one:
var f = Function("i", "return i < 2 ? i : i + arguments.callee(i - 1)");
// or the horrible namespace conflicts prone one ...
var hopefullyNoProblems = "myLib" + (""+Math.random()).slice(2);
window[hopefullyNoProblems] =
Function("i", "return i < 2 ? i : i + window." + hopefullyNoProblems + "(i - 1)");
})();
Cool enough? That function will be extremely slower than a pre-compiled one due to the global window object which is a variable not that fast to retrieve.
Moreover, since they decided that null or undefined should not be considered as window object, the usage of this of run-time called function is not a shortcut anymore, is it?
As Summary
This is my last chance to explain the importance of arguments.callee which is NOT the reason JavaScript is less secure, it is only a pain in the ass for JS engines developers as is arguments variable itself, the magic one which apparently is going to disappear as well.What I do not understand, is why they do not make callee a reserved keyword and put this variable inside the function body as is for arguments and the function name.
function itsEasy(i){
// itsEasy lives only here in every browser except IE
// arguments lives only here in every browser
// so it is simple to put itsEasy, arguments,
// but so many problems with a callee variables ?
return i < 2 ? i : i + callee(i - 1);
};
We'll see how much we will have to change our code and how bigger will be for this non-sense decision ... JavaScript beauties should not be changed, even PHP has at least a function to retrieve the arguments array ... put a function then, whatever other solution, but please do not constrict developers to name in a completely meaningless and redundant way every single lambda. Not a single lambda based language is that fossy about it, IMHO.
Sunday, June 21, 2009
JavaScript arguments Weirdness!
As you know, arguments is a "magic undeclared variable" with a local scope present in each function body. This variable is an Object, with an Array like structure.
Nothing new so far, but I bet not everybody knew some arguments "feature" which is browser dependent or somehow re-usable.
Funny enough, even if we reassign indexed properties, these will not be exposes in the loop, but if we set an extra index or property, this one will probably be exposed.
And as soon as we change the length property, this one could be exposed (FF, IE) or not (Chrome). So what we have so far?
Since as I said arguments is always part of a function body, we could use this variable to know if some piece of code changed the Object prototype, rather than create a new object for each check.
Unfortunately, this is not worthy, because the empty inline Object instance creation performs better than a scope resolution for an undeclared variable as arguments is.
We could think to use arguments as a Function prototype in order to create objects ... wait a minute, NO! We could think to create a function that will directly make the magic argument public, rather than internal.
Unfortunately, the super innovative, secure, and efficient with advanced tab isolation and recovery browser Internet Explorer 8 crashes like a charm, so we need to rename the function into something less ambiguous for the magic JScript engine.
Nada, nien, nothing ... arguments is destined to be arguments, damn it!
Everything seems to be OK except Internet Explorer does not expose properties until you manually discover them:
Cool enough, we just discover a property and magic happens again:
Sometimes I forget we have to deal with a browser which logic is to bring internally even user comments:
As summary, to use arguments as prototype the function should be modified for IE:
In a valueOf operation, arguments[0] contains a sort of information, undefined, or "number", which could tell us if the object is going to be casted as a number:
I am sure every browser has some weird behavior with arguments variable so more than an inspiration for ArrayLike Objects, we cannot truly rely that much in this magic variable. What did you discover guys?
checkArgs(1, 2, 3);
function checkArgs(){
// even if we do not declare
// arguments, this one will
// be present with a length property
// equal to 3 and respective
// 1, 2, and 3 values at index
// 0, 1, and 2
arguments.length; // 3
arguments[0]; // 1
Array.prototype.join.call(arguments,"-");
// will produce 1-2-3
};
Nothing new so far, but I bet not everybody knew some arguments "feature" which is browser dependent or somehow re-usable.
The Common "For In" Behavior
There is a particular behavior about arguments variable, it does not expose properties in a "for in" loop.How can be possible? Simple enough, 0, 1, and 2 index properties are not user defined but JavaScript core assignments. Since JavaScript nature is extremely dynamic, it is simple to define what you want to expose in a loop, so far user defined properties or methods, and what should not be iterated in a "for in", something we will be able to manually introduce in next JavaScript release.
checkArgs(1, 2, 3);
function checkArgs(){
for(var key in arguments)
alert(key);
// nothing happened ...
};
Initial Weirdness
Funny enough, even if we reassign indexed properties, these will not be exposes in the loop, but if we set an extra index or property, this one will probably be exposed.
checkArgs(1, 2, 3);
function checkArgs(){
for(var i = 0; i < arguments.length; ++i)
arguments[i] = arguments[i];
// the extra index, manually assigned
arguments[3] = 4;
for(var key in arguments)
alert(key);
// will be 3 in FF and IE
// still nothing in Chrome
};
And as soon as we change the length property, this one could be exposed (FF, IE) or not (Chrome). So what we have so far?
Zero Stress for Extended Object.prototype Checks?
Since as I said arguments is always part of a function body, we could use this variable to know if some piece of code changed the Object prototype, rather than create a new object for each check.
function someGeniusExtendedObjectPrototype(){
for(var k in arguments)
return true;
return false;
};
Unfortunately, this is not worthy, because the empty inline Object instance creation performs better than a scope resolution for an undeclared variable as arguments is.
function someGeniusExtendedObjectPrototype(){
for(var k in {})return true;return false;
};
// that's it
An Instance With Not Exposed Indexes?
We could think to use arguments as a Function prototype in order to create objects ... wait a minute, NO! We could think to create a function that will directly make the magic argument public, rather than internal.
// global window scope
// where arguments has no
// meaning
// NOTE: do not use with Internet Explorer
function arguments(){
return arguments;
};
// let's test it
var a = arguments(1, 2, 3);
// loop ?
for(var k in a)
alert(k); // nothing!
// it "works"!
Unfortunately, the super innovative, secure, and efficient with advanced tab isolation and recovery browser Internet Explorer 8 crashes like a charm, so we need to rename the function into something less ambiguous for the magic JScript engine.
// use with Internet Explorer too
function args(){
return arguments;
};
A Magic Object Creation?
Using latest snippet, we could abuse about "for in" feature to create our favourite library ... maybe ...
function MyCoolCollection(){
// will be exposed in IE and FireFox
arguments.push = Array.prototype.push;
// will be exposed in FireFox
arguments.toString = Array.prototype.join;
return arguments;
};
var a = MyCoolCollection(1, 2, 3);
// nothing only in Chrome
for(var k in a)
alert(k);
// with this, IE will expose added index "3" and length
a.push(4);
alert(a); // 1,2,3,4
Nada, nien, nothing ... arguments is destined to be arguments, damn it!
arguments as prototype
Trying to discover more arguments freaking stuff, I used this magic variable as prototype:
(function(){"use strict";
// reusable in-scope constructor
function $(){};
// the magic ArgList function
window.ArgList = function ArgList(){
// assign arguments as prototype
$.prototype = arguments;
// return a new magic instance
return new $;
};
})();
var a = ArgList(1,2,3);
Everything seems to be OK except Internet Explorer does not expose properties until you manually discover them:
// after above snippet ...
Array.prototype.slice.call(a);
// ",," in Internet Explorer
// 1,2,3 in every other browser
Cool enough, we just discover a property and magic happens again:
a[1];
Array.prototype.slice.call(a);
// ",2," in Internet Explorer
Sometimes I forget we have to deal with a browser which logic is to bring internally even user comments:
var f = ( /* hi scope! */ function(){ /* hi bracket! */ } );
alert(f);
// will be exactly:
// ( /* hi scope! */ function(){ /* hi bracket! */ } )
// the magic of an efficient code parser
As summary, to use arguments as prototype the function should be modified for IE:
(function(){"use strict";
function $(){};
window.ArgList = function ArgList(){
$.prototype = arguments;
var o = new $, i = o.length;
while(i--)o[i]; // just access ...
return o;
};
})();
Firefox Specific Weirdness
arguments has some secret negative index in every Firefox (Spidermonkey) engine. For example, the index [-2] contains the length of the arguments object, but it does not perform faster than arguments.length, useless. The index [-3] contains the function itself:
function args(){
alert(arguments[-3] === arguments.callee);
alert(arguments[-2] === arguments.length);
};
In a valueOf operation, arguments[0] contains a sort of information, undefined, or "number", which could tell us if the object is going to be casted as a number:
var o = {
push:[].push,
length:0,
toString:[].join,
valueOf:function(){
return arguments[0] == "number" ? this.length : this.toString();
}
};
o.push(1, 2, 3);
alert(o); // 1,2,3
alert(o*1); // 3
Is That It?
I am sure every browser has some weird behavior with arguments variable so more than an inspiration for ArrayLike Objects, we cannot truly rely that much in this magic variable. What did you discover guys?
Wednesday, June 17, 2009
The One With Microsoft Paying Users
You probably do not know what's happened today at about UTC lunch time. It has been just a quick twit from John Resig, that at least every follower instantly noticed the next Microsoft campaign pro Internet Explorer 8.
Internet Explorer 7 by the time was still suffering standards events, CSS 2 problems, and slow general responsiveness, over missed possibility for developers to debug properly. From Firefox, Internet Explorer 8 tried to copy a wonderful tool, Firebug, without having sames possibilities. Internet Explorer 8, compared with Firefox, has still W3 standards compatibility problems, a 5 times slower JavaScript engine, and lack of plug-ins to develop or simply surf more free.
I am sure this is the adjective about Google in Microsoft corridors, but still, only assumption. A browser that in few months is already between the third and the fourth position, rich of plugins, innovative ideas, is open source and again, it has a proper JavaScript engine, the V8 one, able to destroy in performance all Internet Explorers togheter!
Which part is tarnished? Google is a "neverendingmoving" company, which rather than block Web Development for at least 5 years is putting effort every day to make the Web a better, evoluted place (Silverlight possibly excluded, personal opinion).
The Fact
Microsoft Australia launched a sort of "competition", called Ten Grand. Apparently, starting from Friday 19th, a twit will be released each N hours, creating a sort of one day investigation to discover where the price is (in my opinion somewhere in the same page where the contest begins, assumption created by my idea about M$ "fantasy").The Problem
That Web Page literally insults other web browsers, even discarding, probably on purpose, Opera one. In few words, that game is only for Internet Explorer 8 Users. OK, OK, they are apparently desperate enough to pay users in order to have more market share, fair enough, but what is all this "fun" about others?- You'll never find it using old Firefox
- You'll never find it using boring Safari
- You'll never find it using tarnished Chrome
The Old Firefox
Growing up, day after day and biting points to IE market share, Firefox has always been an advanced browser, specially compared with Internet Explorer. Easy for everyone, powerful for developers, Firefox supports, for example, still in draft HTML 5 elements and W3 standards ... since ages!Internet Explorer 7 by the time was still suffering standards events, CSS 2 problems, and slow general responsiveness, over missed possibility for developers to debug properly. From Firefox, Internet Explorer 8 tried to copy a wonderful tool, Firebug, without having sames possibilities. Internet Explorer 8, compared with Firefox, has still W3 standards compatibility problems, a 5 times slower JavaScript engine, and lack of plug-ins to develop or simply surf more free.
The Boring Safari
When you catalog a browser with such adjective, boring, it means you do not have arguments at all and you have been swallowed in the kiddish gne, gne, gne twister unable to admit that "the boring one", is 2 laps around the world in front of you. The pioneer of CSS 3 transitions, effects, text properties, animations, one of the first to implement via WebKit guys (Gosh, I forgot to test WebKit there!!!) the new Squirrel Fish Engine, now Extreme in Safari 4, which is about 20 times faster than Internet Explorer ... but I forgot, boring is Safari because I guess boring is Mac OSX right? The Operating System famous for its native fluid user friendly special effects? Tha company that made iPhone, iPod, iWhatever, a must for everyone? Ooooohhhh Yes, that's boring!The Tarnished Chrome
... wait a second, it's probably me .... let me think ... "tarnished Chrome ... rome ... ome ... om". To be honest, when I read that, I though the creator of this Chrome dedicated version smoked a truly powerful drug, one of those drugs they write: use carefully in open spaces to avoid poisoning, but he rolled up the chemical stuff and that's the slogan: Avoid The Tarnished Chrome (The One With All Colorful Logo, Right?)I am sure this is the adjective about Google in Microsoft corridors, but still, only assumption. A browser that in few months is already between the third and the fourth position, rich of plugins, innovative ideas, is open source and again, it has a proper JavaScript engine, the V8 one, able to destroy in performance all Internet Explorers togheter!
Which part is tarnished? Google is a "neverendingmoving" company, which rather than block Web Development for at least 5 years is putting effort every day to make the Web a better, evoluted place (Silverlight possibly excluded, personal opinion).
The Smell Of 90s Competition Page
Seriously, a competition which aim is to ask people to use Internet Explorer, rather than a website created only for Internet Explorer with, for example, @font-face instead of those old style images over hidden text ... I mean, what the hell is that, a web page? I think all bad practices found a single page to be presented. Bad quality png, maybe this is for IE6, disproportionate use of images to make the page size about 140Kb, insults that only old IE8 users will appreciate for Who knows which reason (wake up guys), and a logic, a server side control, SO EFFICIENT, that simply using a userAgent switcher Firefox plugin I was able to emulate IE8 without receiving insults. Is this what you are looking for, a winner with Firebug, a plug-in to emulate Internet Explorer 8? What will happen if for some reason the winner will not use IE8? I am the author of vice-versa, for example, even emulate IE8 JScript is not a problem, with a more powerful browser, isn't it?Tuesday, June 16, 2009
Opera Unite ... or better, Server Widgets!
My plan to conquer the World was so close that I could not believe it: the power of my old Centrino 1.6 based Laptop, nowadays less powerful than latest Netbook, plus my fantastic USB pen to surf constantly switching between GPRS, HSDPA, and 56Kb with constant lags of service, and finally a magic Web Server directly inside a good browser! WOW, It's Done!
Moreover, everything is sandboxed via the xml configuration file ... but why on earth? OK, security, so we as hosts are considered not safe ... no-ip again? Folders limited somehow because of the event managment, we need a naming convetion. No Rewrite Rules possibility, and if I can add "myPage" event, will it be fired when I try "myPage/myName"? I do not know, Opera Unite crashed few seconds ago, I cannot try.
What Blocked My Plans
... not the hardware, neither the connection, just the idea! First of all, I cannot understand (or maybe I can ...) that much why everybody should be excited by something like Opera Unite:- the idea is not new
- the implementation is not that friendly
- there are hundreds of limitations
Nothing New
Somebody already complained about the un-innovative service or the browser integrated web-server, I would like to add the good old no-ip service to the list: install a Web Server, whatever it is, and as long as you are connected, no-ip will redirect a static url into your dynamic IP address. Easy? Moreover, you'll have full control over chosen programming languages, databases, etc etc. So which part of a unified sub domain into Opera servers redirected into your browser is that exciting?Not That Friendly ... At All!
First of all, I think it is extremely ambiguous to put JavaScript files without understanding if these are for the server or for the client ... could be both? Who knows, I though the load event was for the global object ... what a surprise to find a load event specific for this internal web server. Something like addEventListener("webserver", function(){}); was too difficult to think about, wasn't it? If we would like to mess up our code, adding checks everywhere because we "do not know" how the file is going to be executed, that "load" event is the best option ever. Again, to test the application "as is", apparently we need to put files into a file zip renamed .us - how comfortable for a language which main tradition is the one to be run-time interpreted ... No way, write code, zip, rename the archive, test ... and if a coma was wrong, redo from the scratch. I am sure I am missing something, that was my first opinion as soon as I got how to create my first web app.Too Many Limits
A local web-server, the key to save some money in this credit crunch era? And how can we do it if the second we "close the browser" all our data will be lost? Alternatives:- storage mountPoint polled every N seconds in order to de-serialize data, add new one, if any, re-serialize, and save back again ... boring, not that safe, slow!
- pray that the service, so far beta (alpha?) will never shut down, and use the finally never that usefull JSON Query library
- ask Opera Engineers what's wrong with W3 Database API, considering we could implement an SQLite file directly in the package, and copy in the storage folder if necessary. Just easy like that!
- others, probably released with final version?
Moreover, everything is sandboxed via the xml configuration file ... but why on earth? OK, security, so we as hosts are considered not safe ... no-ip again? Folders limited somehow because of the event managment, we need a naming convetion. No Rewrite Rules possibility, and if I can add "myPage" event, will it be fired when I try "myPage/myName"? I do not know, Opera Unite crashed few seconds ago, I cannot try.
Maybe It Is Just Me
Yesterday I commented an arrogant post about JavaScript from PC Pro, today I am the arrogant one here and I am sorry if everything is because of my patience, vanished few seconds after I read the API and I did some test, but the impression is that since Opera Widgets are a good reality, this Opera Unite would like to make Widgets even closer to Developers, but in the server, it does not deal that well, IMHO. Anyway, there is still hope, this is a beta (alpha?), and hopefully good old Opera Pioneer will listen our opinion, improving our experience, and going forward thanks to our comments. Will it be the case?Monday, June 15, 2009
On David Fearon PC Pro GWT Article
I do not even know why somebody like me should buy PC Pro, maybe it was simply reminding me 12 years ago when I started fixing Hardware and Software problems as Computer Shop Technician? Maybe I was flying to Italy alone? It does not matter, nice enough I found, after years without reading it, an updated magazine which decided a while ago to talk about IT and Web as well, rather than only Hardware and few desktop applications.
First of all, unlike David, I deeply know JavaScript, and I worked with both Java language and Java Developers, so I know what I am talking about, secondly, comparing a strongly typed programming language, Java, with one of the most successful, famous, omnipresent, and advanced scripting one, JavaScript, is an error that even a kid would not commit ... what are we talking about?
Accordingly, if GWT and Java are "that cool", I wonder why big G developers use raw JavaScript, which in mentioned article is described also as the drudge that drains the fun out of web development ...
Moreover, JavaScript is apparently an assembly language, in this era the language that the web can understand ... nothing about its simplicity, new amazing performances thanks to new engines, prototypal inheritance, nested closure, injectable scope, and all stuff that if you are not familiar with, you cannot even understand (neither comment badly, IMHO).
Best Regards.
P.S. "Google has some of the best Ajax hackers out there", it cannot be true guys, I am not a Google developer so far :P
Don't be afraid about Google latest web revolution
this is the title of the article, and the subject is not wave but GWT.JavaScript, the hideous language saved by browsers?
If you do not know a language, or you cannot spot its beauty, 'cause you only know a different one, in David case Java, you should not categorize JavaScript that bad.First of all, unlike David, I deeply know JavaScript, and I worked with both Java language and Java Developers, so I know what I am talking about, secondly, comparing a strongly typed programming language, Java, with one of the most successful, famous, omnipresent, and advanced scripting one, JavaScript, is an error that even a kid would not commit ... what are we talking about?
Even Google Prefers JavaScript And Does NOT Use GWT
at least this is what Ajaxian reported few days ago.Accordingly, if GWT and Java are "that cool", I wonder why big G developers use raw JavaScript, which in mentioned article is described also as the drudge that drains the fun out of web development ...
Moreover, JavaScript is apparently an assembly language, in this era the language that the web can understand ... nothing about its simplicity, new amazing performances thanks to new engines, prototypal inheritance, nested closure, injectable scope, and all stuff that if you are not familiar with, you cannot even understand (neither comment badly, IMHO).
Tomato, Potato, and Pomato
I found that article for some reason interesting, not because it convinced me that JavaScript is a bad programming language, from scripting branch, just because I discovered how people could expose their opinion in such arrogant and not that competent way. PC Pro is still probably the best magazine out there, if we would like to be updated 360°, but please keep being neutral about subjects, whatever these are, you do not need to insult something you probably do not understand ... some reasonable comment could be enough, and that's it, don't you agree?Best Regards.
P.S. "Google has some of the best Ajax hackers out there", it cannot be true guys, I am not a Google developer so far :P
Wednesday, June 10, 2009
Wait A Moment, JavaScript Does Support Multiple Inheritance!
... we are just doing it wrong!
Above snippet demonstrates how inheritance and instanceof are related to the current prototype, rather than the function/constructor itself.
In few words, the function is the implicit init method for the current prototype object. The relation, as we could spot with FireFox, is with the prototype and not the used constructor.
Since the prototype is the relation, and not the constructor, and since a prototype is nothing but a common Object, we can add whatever method or property we want to this prototype object in order to obtain the hybrid one we are looking for.
In few words, we can add whatever we want to a prototype object creating exactly what multiple inheritance would create. We still have a problem with instanceof operator, don't we? Well, considering that "instance" concept is something more meaningful in classical inheritance, we could say that it is not possible to emulate multiple inheritance Python like with JavaScript, but we can inject whatever method/property from whatever constructor.prototype, something not possible with Java, PHP, C#, and others ... so are we missing something?
Purist Classical OOP Developers are probably already rolling around the floor in pain and screaming he's f#@*in idiot, but what is the meaning of implement in classical inheritance patterns?
Wikipedia - Interface
In few words my latest snippet checks if an object contains every method/property defined in another object so, using first example, we could do:
Nothing new? Nothing true? Is it clear for everybody? 8-)
Classical Inheritance? We Have Something Better!
The main limit about multiple inheritance in JavaScript is the presence of "instanceof" operator. In a prototypal based inheritance objects simply inherits from objects, and class keyword is almost meaningless.
// generic constructor
function B(){};
// remember the prototype
var B1proto = B.prototype;
// B instance
var b1 = new B;
// prototype reassignment
B.prototype = {
constructor:B
};
// remember new prototype
var B2proto = B.prototype;
// B instance
var b2 = new B;
alert(b2 instanceof B); // true
alert(b1 instanceof B); // false
Above snippet demonstrates how inheritance and instanceof are related to the current prototype, rather than the function/constructor itself.
In few words, the function is the implicit init method for the current prototype object. The relation, as we could spot with FireFox, is with the prototype and not the used constructor.
// FireFox exposes __proto__
// will be Object.getPrototypeOf
// in ECMAScript 3.1
b1.__proto__ == B1proto; // true
b2.__proto__ == B2proto; // true
Sure, And What About Multiple Inheritance?
... I am going there, wait another few seconds :DSince the prototype is the relation, and not the constructor, and since a prototype is nothing but a common Object, we can add whatever method or property we want to this prototype object in order to obtain the hybrid one we are looking for.
function A(){};
A.prototype.name = "A instance";
A.prototype.getName = function(){
return this.name;
};
function B(){};
B.prototype.name = "B instance";
function C(){};
// default name from B
C.prototype.name = B.prototype.name;
// getName from A
C.prototype.getName = A.prototype.getName;
// new method for C
C.prototype.setName = function(name){
this.name = name;
};
var c = new C();
c.getName(); // B instance
c.setName("Andrea");
c.getName(); // Andrea
In few words, we can add whatever we want to a prototype object creating exactly what multiple inheritance would create. We still have a problem with instanceof operator, don't we? Well, considering that "instance" concept is something more meaningful in classical inheritance, we could say that it is not possible to emulate multiple inheritance Python like with JavaScript, but we can inject whatever method/property from whatever constructor.prototype, something not possible with Java, PHP, C#, and others ... so are we missing something?
A Basic Object.implement Function Check
Due to the fact we could need to know if an hybrid instance is using this or that method, we could think about an abstract implement method able to tell us if a generic instance constructor prototype, is at least implementing another constructor prototype, considering latter one as an interface. If this is true, we are sure that we can use that instance/object in that way and without problems ... isn't it?
Object.implement = function(o, constructor){
// Another WebReflection Insane Snippet
if(o instanceof constructor)
// nothing to check
// classical boring stuff
return true;
// let's check if things are OK
var k, b = true,
// take the instance constructor prototype
po = o.constructor.prototype,
// take the implemented prototype
pc = constructor.prototype
;
// for each property or method
// in the implemented constructor
for(k in pc)
// check if the instance inherited prototype
// has this method/property as well
b = b && k in po; //* TOTHINK: */ && (typeof po[k] === typeof pc[k]); //*/
// if there was nothing to check
// we cannot say a word ... but ...
// if instance has every method/property
// present in the compared constructor
// prototype, we could say this instance
// implements this constructor
return !!k && b;
};
Purist Classical OOP Developers are probably already rolling around the floor in pain and screaming he's f#@*in idiot, but what is the meaning of implement in classical inheritance patterns?
Wikipedia - Interface
Interfaces are used to encode similarities which classes of various types share, but do not necessarily constitute a class relationship
In few words my latest snippet checks if an object contains every method/property defined in another object so, using first example, we could do:
// add noise and chaos with another constructor ...
function D(){};
D.prototype.notInObject = true;
// check Object.implement ...
Object.implement(c, A); // true
Object.implement(c, B); // true
Object.implement(c, C); // true
Object.implement(c, D); // false
Nothing new? Nothing true? Is it clear for everybody? 8-)
Tuesday, June 9, 2009
ExtJS And The Bloody TreePanel Arrow
First of all I am sorry for choose title, but I kinda lost dunno how many minutes to figure out what was wrong, and it was not me!
Please let me try to explain what was the requirement, and how I had to force ExtJS to act as I want, version 2.2.1 or 3.0RC2, it does not matter.
As example, try to click Start and Run a prompt command, explorer.
This is the typical Window$ file browser, something we deal with since ages, something still a user habit.
As summary, one click on the [+] to open the folder, one to [-] to close it, if we click the folder and it is closed, it will be opened as if we pressed the [+] and the right side will change showing details about that folder. Morevore, if we do a double click, nothing happen, the explorer works with click, and eventually right click. Seems to be truly simple, isn't it? It's NOT, unless I am missing an hidden part of ExtJS documentation because I swear I tried everything.
That's it, waiting for comments, better examples, or even solution I could not think about!
Please let me try to explain what was the requirement, and how I had to force ExtJS to act as I want, version 2.2.1 or 3.0RC2, it does not matter.
The Problem ...
The reason you or your company choose ExtJS is most likely because of its Office $uite / Window$ look and feel, closer than many others to a proper Desktop Application, perfect under Adobe Air, and one step forward about stability, performances, and documentation, even with the old enemy: Internet Explorer 6. Fair enough, it's a good library but, there is always a but, at the same time it does not replicate 100% same Window$ behaviors.As example, try to click Start and Run a prompt command, explorer.
This is the typical Window$ file browser, something we deal with since ages, something still a user habit.
... In Details
How does it work? It is really simple, we have a representation of our files in the left, let's call it Tree, and many details on the right but only if we click a folder. That is the problem, the Jurassic explorer acts differently if we click the [+] rather than the folder/file. The difference is that while we are simply surfing a Tree structure, we do not need to show every single detail, preview, whatever, on the right side until we click, still on the left side, into the folder we need.As summary, one click on the [+] to open the folder, one to [-] to close it, if we click the folder and it is closed, it will be opened as if we pressed the [+] and the right side will change showing details about that folder. Morevore, if we do a double click, nothing happen, the explorer works with click, and eventually right click. Seems to be truly simple, isn't it? It's NOT, unless I am missing an hidden part of ExtJS documentation because I swear I tried everything.
Ext.tree.TreePanel Hacked To Have More Control Over The Arrow
... where the rrow is the one in ExtJS 2, in version 3 they put a lovely [+]/[-] which reminds even more explorer surfing!!! I am not here to judge ExtJS choices, I am just writing my solution to this problem, specially because tdginnovations asked me, via twitter, to make this problem public, with solution as well.
// good old onload ...
onload = function(){
// simple function to add nodes
// just for this example
function addNodes(root, dummyData){
for(var
i = 0, length = dummyData.length,
cls = {true:"file",false:"folder"},
data, leaf;
i < length; ++i
){
data = dummyData[i];
leaf = root.appendChild(new Ext.tree.TreeNode({
text:data.text,
leaf:!data.items,
cls:cls[!data.items]
}));
if(data.items)
addNodes(leaf, data.items);
};
};
var
// just a sync example
// with a couple of folders
dummyData = [
{text:"Test 1", items:[
{text:"Sub Test 1 1"},
{text:"Sub Test 1 2"}
]},
{text:"Test 2"},
{text:"Test 3", items:[
{text:"Sub Test 3 1"},
{text:"Sub Test 3 2", items:[
{text:"Sub Test 3 2 1"},
{text:"Sub Test 3 2 2"}
]},
{text:"Sub Test 3 3"}
]}
],
// the lovely TreePanel
TreePanel = new Ext.tree.TreePanel({
renderTo:document.body,
border:false,
rootVisible: false,
root:{
expanded: true,
text: "",
draggable: false
},
// global TreePanel events
listeners:{
// Hack #1: The Lovely Arrow ..
// here starts the open hack ...
// when the arrow is clicked,
// no click event is propagated
// but when the node is clicked
// beforeexpandnode is called ...
// to avoid troubles I used a flag
// in order to discard next
// beforeexpandnode event
// without returning false
// but if this is the arrow
// without the click ... so
// the lonely beforeexpandnode ...
beforeexpandnode:function(Node){
// check if the flag is not setted
if(!Node.beforeexpandnode){
// set the flag, prevent
// return false onclick event
Node.beforeexpandnode = true;
// fire the click event
// the one in charge
// to load or show stuff
Node.fireEvent("click", Node);
// block this call
// or we gonna open twice ...
// with possible loops
// (at least in Ext 2.2.1)
return false;
}
},
// here we are ...
// if it was a click in the name/folder/leaf
// this event is fired before beforeexpandnode
// we need to check a couple of things ...
click:function(Node, e){
// if node is expanded
// we do not need to do anything
if(Node.isExpanded()){
console.log("already expanded");
}
// but if node is not expanded
// and the beforeexpandnode flag
// has been setted as true ...
else if(Node.beforeexpandnode) {
// we know that this click
// is from the arrow, and not
// from the folder or name
console.log("expand via arrow/plus or minus");
// we can load stuff async, putting
// a mask to the panel before, removing it
// on load success, add nodes
// and finally expand this Node
// this if should not exists if
// the node is a leaf, cause there
// is no arrow beside
Node.expand();
}
// if node is not expanded but it is
// a folder and beforeexpandnode flag
// has not been setted as true
// we know that the user performed
// a click ...
else if(!Node.isLeaf()) {
// to avoid another click event
// triggered via beforeexpandnode event
// we need to set the flag as true
// so beforeexpandnode will not
// return false calling this event
// again (precedent if)
Node.beforeexpandnode = true;
// at this point we could perform
// a different request
// which could return the entire node
// list plus some other information
// or simply do something else
// rather than just populate the
// Node with sub-nodes
console.log("expand via click");
// in this case, let's expand the node
Node.expand();
}
// none of precedent condition
// was true, interesting ...
// ... it must be just a leaf ;)
else {
// let's do something
// with this leaf
console.log(Node.text);
};
// the main problem with click
// is that it is not possible
// to avoid a double click
// e.stopEvent() ? no way
// it does not do anything with
// dblclick, useless
},
// last part of this little hack ...
// once the node is expanded
// it makes sense to
// set the flag as false
// so next beforeexpandnode event
// will work as expected
expandnode:function(Node){
Node.beforeexpandnode = false;
},
// Hack #2: ... I said:
// DO NOT CLOSE ON DOUBLE CLICK!!!
// at least this hack is even shorter
// but it still requires 2 events
// dblclick, as I said, cannot be
// stopped ... but it does not
// really matter, cause
// beforecollapsenode will be fired
// always before ... so, even
// implementing a proper stopEvent
// how could we avoid closing action
// from beforecollapsenode event
// since this is fired before
// dblclick?
// dblclick has to be a sort
// of filter able to change
// another flag
// beforecollapsenode
// if node is expanded
// we set the flag as false
// why ? ... read next ...
dblclick:function(Node, e){
if(Node.isExpanded())
Node.beforecollapsenode = false;
},
// beforecollapsenode event
// is fired before dblclick
// so this hack is about milliseconds.
// if the flag is not set
// we set it as true and we call a timetout
// Hopefully, the double click will be performed
// before choose timeout.
// If this happens, it means
// that the user double clicked the
// opened node, otherwise
// it means that the user did not
// mean a double click (the arrow
// does NOT fire a dblclick in any case)
// while He/She simpl clicked once in
// the arrow (or more than once to close it)
beforecollapsenode:function(Node){
if(!Node.beforecollapsenode){
Node.beforecollapsenode = true;
setTimeout(function(){
// so here this hack should
// perform its action ...
if(Node.beforecollapsenode)
// closing the node
// if it was not a dblclick
Node.collapse();
}, 20);
return false;
}
},
// to complete the task
// let's reset status
// on node collapsed
collapsenode:function(Node){
Node.beforecollapsenode = false;
}
}
})
;
// it's time to test
addNodes(TreePanel.getRootNode(), dummyData);
// and play with this version
TreePanel.render();
};
That's it, waiting for comments, better examples, or even solution I could not think about!
Sunday, June 7, 2009
MySQL UPDATE DELAYED - Just My Solution
The Problem
MySQL supports DELAYED option as INSERT statement but, for some obscure reason nobody got so far, it does not support UPDATE DELAYED or DELETE DELAYED.Why DELAYED Is Necessary
As quick summary, INSERT DELAYED is something truly useful when we would like to let MySQL decide when it is time to perform that insert without blocking tables and users. This is a problem almost specific for engines like MyISAM, MEMORY, ARCHIVE, and BLACKHOLE. This post is not about "why not InnoDB", this is about DELAYED with these engines, specially with MyISAM one.To better understand a common case where an UPDATE DELAYED could be extremely useful, just think about a counter, how many users visited that id. Is such information that useful to be not approximated and to possibly block every other select because of an update that nobody will verify with a microscope? In my opinion, such information is "just a plus" and if the page execution could be faster without blocking anybody and putting those UPDATES in a queue as is for INSERT DELAYED in order to perform it in a shot and in "the best moment ever" ... why on earth we should have not such option?
UPDATE LOW_PRIORITY Is NOT The Same
Unfortunately, we could choose to let the user wait a bit more thanks to LOW_PRIORITY option with an UPDATE statement but still: why that user should wait more for such irrelevant information?Split The Problem! That's My Idea
Apparently there are no good options to emulate an UPDATE DELAYED with MySQL so I tried to use INSERT DELAYED plus some trick able to delegate the LOW_PRIORITY update to somebody else (crontab or database via event), without blocking any user and making page response faster with hundreds of thousands of rows for a single static table.Example Tables
Try to imagine we have a generic service based on an id, which is unique and used in every other part of the database as main relation. Now for this id we could have other N fields, it does not matter, as long as we use a total field to know how many users visited that id.
CREATE TABLE IF NOT EXISTS counter (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
/* one or more fields (possibly static) */
total INT(3) UNSIGNED NOT NULL
) ENGINE=MyISAM;
/* let's populate the counter table with 3 ids */
INSERT INTO counter (total) VALUES (0), (0), (0);
The REPLACE DELAYED query will be a suicide for a big table with thousands of records, while INSERT DELAYED cannot be performed in the main table or every key will be duplicated for N times. To perform an INSERT DELAYED we need then another table, with just a single field, possibly the same type used for the main key, in this example the id.
/* specific table for delayed inserts */
CREATE TABLE IF NOT EXISTS counter_total (
id INT(10) UNSIGNED NOT NULL,
KEY id (id)
) ENGINE=MyISAM;
/* visits for ids, 3 users in id 1, 2 in id 2, 1 in id 3 */
INSERT DELAYED INTO counter_total VALUES (1);
INSERT DELAYED INTO counter_total VALUES (2);
INSERT DELAYED INTO counter_total VALUES (1);
INSERT DELAYED INTO counter_total VALUES (3);
INSERT DELAYED INTO counter_total VALUES (2);
INSERT DELAYED INTO counter_total VALUES (1);
Last INSERTs are to emulate 6 users visiting id 1 3 times, id 2 twice, and id 3 only once. Since we are using INSERT DELAYED it does not matter how many users are surfing the page and how many are in the same id, we simply do not care and we let MySQL decide when it is about the time to shot every insert in one go for the WRITE ONLY table, counter_total. Moreover, since the main id is the key for this solution, the query is so simple that its execution time will be extremely fast, even in my laptop.
Every N Seconds, Minutes, Hours ...
At this point the counter_total table will contain N main ids, what we have to do know is:- block possible insert delayed locking the counter_total table
- have a snapshot of visited ids and total visit, via function COUNT
- reset counter_total to keep it small and fast
- release counter_total to allow queued INSERT DELAYED to be executed
- find a way to quickly update with low_priority the main counter table
To solve above points we could use a TEMPORARY TABLE created directly with ENGINE=MEMORY. This will ensure us CPU+RAM speed performances without using that big amount of RAM in any case (if we do, we need to reduce the delay between one call and another one).
Here is the sequence to perform the entire operation in a flash!
/* WebReflection UPDATE DELAYED Workaround */
CREATE TEMPORARY TABLE tmp_counter (
id INT(10) UNSIGNED NOT NULL,
total INT(3) UNSIGNED NOT NULL
) ENGINE=MEMORY;
LOCK TABLE counter_total WRITE;
INSERT INTO
tmp_counter (
SELECT
counter_total.id,
COUNT(counter_total.id)
FROM
counter_total
GROUP BY
counter_total.id
)
;
DELETE FROM counter_total;
UNLOCK TABLE;
UPDATE LOW_PRIORITY
counter AS c
LEFT JOIN
tmp_counter AS tc
ON(
c.id = tc.id
)
SET
c.total = (
c.total + tc.total
)
;
That's it, tested over hundred of thousands of records in a reasonable 0.2 time and with an old laptop that apparently, if "used" properly, can still give me a lot :P
As Summary
A counter is a classic example where an UPDATE DELAYED could be useful. Unfortunately MySQL does not support it (probably version 6) so we can use the supported INSERT DELAYED (please note with replication will be a normal INSERT due to synchronization problems but it will be for a write only table). To do this, we need to create another table and lock it when we decide that it is about the time to update the main one. With a truly simple sequence of queries, this could be a super fast operation, rather than a bottleneck if for some reason 100 users are visiting our website with "inline update".Now, do you have a better solution? If Yes, please share it, thanks ;)
P.S. I need to say thanks to Olga for the temporary suggestion, I was almost struggling with missed MyISAM transactions :D
Friday, June 5, 2009
input.focus() ... something really annoying!
new libraries, new add-ons, new engines, new browsers, but still the bloody focus event directly in the onload one ... any chance we will go a step forward?
It could be a search input, a la Google, or it could be a generic log-in. It could be a blog post title, or it could be a comment ... whatever it is, it should NOT act like this!
Try to imagine you have a slow connection (I am still with mobile usb pen) or try to imagine you are using your A Grade browser mobile phone with still, a not that fast connection (I am still using my Android, iPhone is the same).
Since these magic-focused fields are usually at the beginning of the page and since the page will take more time to be downloaded, 90% of the time this automatic feature messes up my user and password or my searched keyword. Too often I have to correct or change back the field, specially when I need to log-in into my on-line banking service, where my actions are faster than page download. Am I that fast? OK, Android first model with its pretty keyboard let me type faster than how I could do with iPhone or second Android generation, but the main problem is that if there is an image, for example, or generally speaking just content after main focused input, the onload event will be fired too late and it will be completely useless and inefficient, rather than being an help for the user.
fff will be a global variable which name is absolutely irrelevant and which aim will be to stop the generic onload event to force focus in that input.
With a zero effort + stress strategy that will not increase more than a couple of bytes our page, users will have more control over their fields. This simple trick could be used for every textarea, input, select, or button in the page making the auto focus really helpful in those case user has a fast connection or is lazy and does not want to point the focus automatically, rather than quick posts via mobile or slow connections.
I agree that probably nobody will ever change every page layout adding an inline onfocus event for each field, so here I am with a better solution that should be widely copatible with every kind of device.
Above snippet does not require both onReady or onload events so it should work just adding it inside the head tag. It is so simple, now let's see how people will react 8)
What is wrong with focus
The main usage of this strategy is to force via JavaScript the focus of the main input field and it is usually on the top of the page.It could be a search input, a la Google, or it could be a generic log-in. It could be a blog post title, or it could be a comment ... whatever it is, it should NOT act like this!
Try to imagine you have a slow connection (I am still with mobile usb pen) or try to imagine you are using your A Grade browser mobile phone with still, a not that fast connection (I am still using my Android, iPhone is the same).
Since these magic-focused fields are usually at the beginning of the page and since the page will take more time to be downloaded, 90% of the time this automatic feature messes up my user and password or my searched keyword. Too often I have to correct or change back the field, specially when I need to log-in into my on-line banking service, where my actions are faster than page download. Am I that fast? OK, Android first model with its pretty keyboard let me type faster than how I could do with iPhone or second Android generation, but the main problem is that if there is an image, for example, or generally speaking just content after main focused input, the onload event will be fired too late and it will be completely useless and inefficient, rather than being an help for the user.
How could we solve the problem
In my opinion, it is the most simple thing ever. Assuming that the theoretically helping focus will be only one per page, if the site would like to make sense, all we need is a little manager able to understand if the input received focus before the onload event:
<form name="f" action="/search">
<input name="q" onfocus="fff=1" />
</form>
fff will be a global variable which name is absolutely irrelevant and which aim will be to stop the generic onload event to force focus in that input.
<body onload="if(!this.fff)document.f.q.focus();">
<!-- ... the rest of the page ... -->
</body>
With a zero effort + stress strategy that will not increase more than a couple of bytes our page, users will have more control over their fields. This simple trick could be used for every textarea, input, select, or button in the page making the auto focus really helpful in those case user has a fast connection or is lazy and does not want to point the focus automatically, rather than quick posts via mobile or slow connections.
Another Way Without Changing Every Layout
I agree that probably nobody will ever change every page layout adding an inline onfocus event for each field, so here I am with a better solution that should be widely copatible with every kind of device.
(function(){
// A WebReflection Anti Stress Idea
function onclick(e){
var target = (e && e.target) || event.srcElement;
if(/^(input|select|textarea|button)$/i.test(target.nodeName)){
window.fff = true;
if(document.detachEvent)
document.detachEvent("onclick", onclick);
else
document.removeEventListener("click", onclick, false);
}
};
if(document.attachEvent)
document.attachEvent("onclick", onclick);
else
document.addEventListener("click", onclick, false);
})();
// as body or window event
onload = function(){
if(!this.fff)
document.getElementById("main-input").focus();
};
Above snippet does not require both onReady or onload events so it should work just adding it inside the head tag. It is so simple, now let's see how people will react 8)
Subscribe to:
Posts (Atom)