This is both an update and a news about my little Phomet project.
I am sorry because I have not found time to write better examples or to explain possibilities as well, but I am sure you would like to know that now the project is called Phico (click there to download them)
See you as soon as possible to talk again about Phico :geek:
behind the design
My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.
Sunday, April 27, 2008
Monday, April 21, 2008
Phomet - PHP Comet tiny library
Comet is a particular technique to interact asyncronously with the client.
Instead of perform a lot of calls using Ajax (polling) the server is able to send to client, whenever it wants, a generic response.
Unfortunately in the PHP world there's no simple way to implement this kind of technique and I'll write more posts to explain better how to implement this library and what is generally possible to do, or not possible yet, with Comet idea inside a dedicated PHP environment.
At the moment, the only thing you can do is read documentation inside JavaScript and PHP files (truly few lines) and test the first basic example, a server side clock in less than 30 lines of mixed code.
As last information, Phomet comes with all necessary to be optimized on client, and its final result is about 1.57Kb on client, and ridiculously 4.52 Kb on server, comments included :)
Here is the download, unpack them into your localhost, and go into phomet folder to view the first demo.
Compatibility? I've tested them with IE6, 7, 8, Opera 9, FireFox 1.5, 2, 3, Safari 3 windows but I am sure there are other browsers compatible.
I am waiting for your suggestions, bugs, opinions, whatever :D
Cheers, and please stay tuned for next Comet appointments :geek:
Instead of perform a lot of calls using Ajax (polling) the server is able to send to client, whenever it wants, a generic response.
Unfortunately in the PHP world there's no simple way to implement this kind of technique and I'll write more posts to explain better how to implement this library and what is generally possible to do, or not possible yet, with Comet idea inside a dedicated PHP environment.
At the moment, the only thing you can do is read documentation inside JavaScript and PHP files (truly few lines) and test the first basic example, a server side clock in less than 30 lines of mixed code.
As last information, Phomet comes with all necessary to be optimized on client, and its final result is about 1.57Kb on client, and ridiculously 4.52 Kb on server, comments included :)
Here is the download, unpack them into your localhost, and go into phomet folder to view the first demo.
Compatibility? I've tested them with IE6, 7, 8, Opera 9, FireFox 1.5, 2, 3, Safari 3 windows but I am sure there are other browsers compatible.
I am waiting for your suggestions, bugs, opinions, whatever :D
Cheers, and please stay tuned for next Comet appointments :geek:
Monday, April 14, 2008
Script Type PHP :)
Update 2008/03/15
I have removed preg_replace and added DOM classes to parse and manage, in a better way, script nodes that contain php code.
Everything inside a simple PHP 5 compatible class.
Finally, please remember that this is a layer between <?php ?> and JavaScript, and only an experiment ;)
Here you can read another example, where difference between server, output, and client, should be more clear than precedent one.
-------------------------------
This is a little experiment to emulate script tag with php.
The final result will be something like this one:
How can it be possible?
Of course, we need to include this file before we write a single character in the layout (spaces included), so basically to obtain the expected result, just save above code in a file called, for example, php_script_handler.php, and put them before the layout
The evil eval? Yes, absolutely ... but first of all, this is only a simple experiment, secondly, the page will not be sent before evaluation, so there's no way from the client side to inject malicious code.
The main problem is true interoperability between these two languages, JavaScript, and PHP, but did I say that this is only an experiment? :P
I have removed preg_replace and added DOM classes to parse and manage, in a better way, script nodes that contain php code.
Everything inside a simple PHP 5 compatible class.
Finally, please remember that this is a layer between <?php ?> and JavaScript, and only an experiment ;)
Here you can read another example, where difference between server, output, and client, should be more clear than precedent one.
<?php require 'PHPScriptHandler.php'; ?>
<html>
<head>
<title>Hello PHP World</title>
<script type="text/php" author="andr3a">
// here we are between the server and output, known as client
$hello = ucwords('hello php world');
// imagine that we would like to use a variable
// defined somewhere in the server
global $something;
// we could even include or require php files
// perform database operations and everything else
</script>
<script type="text/javascript">
onload = function(){
// here we are in the client, on window load event
alert($hello);
alert($something);
};
</script>
</head>
<body>
<?php
// here we are in the server side
// we could do what we do every day without problems
$something = '<div>Hello Body</div>';
echo $something;
?>
</body>
</html>
-------------------------------
This is a little experiment to emulate script tag with php.
The final result will be something like this one:
<html>
<head>
<title>Hello PHP World</title>
<script type="text/php">
// string
$hello = ucwords('hello php world');
// object
$o = new stdClass;
$o->test = 'hello again';
</script>
<script type="text/javascript">
onload = function(){
alert($hello);
alert($o.test);
};
</script>
</head>
<body>
</body>
</html>
How can it be possible?
<?php // 5 - PHP Script Handler Experiment - by Andrea Giammarchi
function php_script_handler($output){return stripos($output, 'type="text/php"') ? preg_replace_callback('#(?i)<script[[:space:]]+type="text/php"(.*?)>([^\a]+?)</script>#', 'php_script_parser', $output) : $output;}
function php_script_parser(){eval(end(func_get_arg(0)));return '<script type="text/javascript"'.next(func_get_arg(0)).'>'.PHP_EOL.php_script_vars(get_defined_vars()).PHP_EOL.'</script>';}
function php_script_vars($vars){foreach($vars as $key => $value)$vars[$key] = '$'.$key.'='.json_encode($value).';';return implode(PHP_EOL, $vars);}
ob_start('php_script_handler');
?>
Of course, we need to include this file before we write a single character in the layout (spaces included), so basically to obtain the expected result, just save above code in a file called, for example, php_script_handler.php, and put them before the layout
<?php require 'php_script_handler.php'; ?>
<html>
<head>
<title>Hello PHP World</title>
.... other stuff ....
The evil eval? Yes, absolutely ... but first of all, this is only a simple experiment, secondly, the page will not be sent before evaluation, so there's no way from the client side to inject malicious code.
The main problem is true interoperability between these two languages, JavaScript, and PHP, but did I say that this is only an experiment? :P
Friday, April 11, 2008
Io programming language List for JavaScript
Io is a small, prototype-based programming language. The ideas in Io are mostly inspired by Smalltalk (all values are objects, all messages are dynamic), Self (prototype-based), NewtonScript (differential inheritance), Act1 (actors and futures for concurrency), LISP (code is a runtime inspectable/modifiable tree) and Lua (small, embeddable).
This programming language is really interesting, starting from syntax, throw the entire guide.
One of its primitive type is called List, and this is a summary of this type:
A List is an array of references and supports all the standard array manipulation and enumeration methods.
It seems that List is all we need when we think about an Array of elements ... so why couldn't we have something similar in JavaScript?
// Io programming language List example
// followed by my JavaScript List implementation
a := List clone
a = List.clone()
a := list(33, "a")
a = list(33, "a")
a append("b")
a.append("b")
==> list(33, "a", "b")
a size
a.size
==> 3
a at(1)
a.at(1)
==> "a"
a atPut(2, "foo")
a.atPut(2, "foo")
==> list(33, "a", "foo", "b")
a atPut(6, "Fred")
a.atPut(6, "Fred")
==> Exception: index out of bounds
a remove("foo")
a.remove("foo")
==> list(33, "a", "b")
a atPut(2, "foo")
a.atPut(2, "foo")
==> list(33, "a", "foo", "56")
a := list(65, 21, 122)
a = list(65, 21, 122);
a foreach(i, v, write(i, ":", v, ", "))
a.foreach(function(i, v){alert(i + ":" + v + ", ")})
==> 0:65, 1:21, 2:122,
a foreach(v, v println)
a.foreach(function(v){document.writeln(v)})
==> 65
21
122
numbers := list(1, 2, 3, 4, 5, 6)
numbers = list(1, 2, 3, 4, 5, 6)
numbers select(x, x isOdd)
numbers.select(function isOdd(x){return !!(x%2)})
==> list(1, 3, 5)
numbers select(i, x, x isOdd)
numbers.select(function isOdd(i, x){return !!(x%2)})
==> list(1, 3, 5)
numbers map(x, x*2)
numbers.map(function(x){return x*2})
==> list(2, 4, 6, 8, 10, 12)
numbers map(i, x, x+i)
numbers.map(function(i, x){return x+i})
==> list(1, 3, 5, 7, 9, 11)
The map and select methods return new lists. To do the same operations in-place, you can use selectInPlace() and mapInPlace() methods.
and my implementation has mapInPlace and selectInPlace as well :)
Am I forgetting something? ... of course, the source!
P.S. because of nature of List, you can do stuff like this one:
list(1,2,3).append(4).remove(2).size;
// 3
an so on ;)
Wednesday, April 09, 2008
S.O.S. JavaScript - How to recover your stuff !!!
In this Ajax Web era there are a lot of sites that use JavaScript to perform simple or complex stuff.
Sometime, one of these site could be "not so well" programmed, specially during client-server interactions.
For example, it happens few days ago that while I was trying to post a message to another "friend", an error occurred during this operation.
The result was a beautiful fake popup with returned server error information and only a button to close them ... and I wondered what about my content? Can I try again to send them?
The answer was NO, because the SEND button has been disabled, and the worst thing is that the textarea with my message was disabled as well.
I wasn't able to get my message content again because of some client/server error and some bad logic in the client side. What could we do in these cases?
Reading the source? ... uhm, content wasn't there ...
Using firebug? Maybe, but content could not be there as well ...
Press F5 and reload the page? ... ok, but why should we loose our content in this way? What I mean, I wasted my time to write that message and why on heart should I spend twice ... ok, ok, here I come with these "stupid" links:
If you bookmark these links, dragging them in your Browser Bookmarks area, you will be able in 90% of cases to enable again the blocked page.
Basically, I created the first one (runtime and in few seconds), Enable Area, to get my content that was inside the disabled textarea, to refresh the page and try the entire operation without loosing whatever I wrote before.
The simple used code is this one:
and the difference between those links is only in the sent parameter, the first is the string textarea, the second is the string input, and finally the third one is the string button.
These links, and this code, are compatible with every browser that supports javascript uris (so, basically, every recent browser where recent means since some year ago ...)
Finally, in this way we use JavaScript to help us with pages that have problems with JavaScript, sounds weird? :D
Sometime, one of these site could be "not so well" programmed, specially during client-server interactions.
For example, it happens few days ago that while I was trying to post a message to another "friend", an error occurred during this operation.
The result was a beautiful fake popup with returned server error information and only a button to close them ... and I wondered what about my content? Can I try again to send them?
The answer was NO, because the SEND button has been disabled, and the worst thing is that the textarea with my message was disabled as well.
I wasn't able to get my message content again because of some client/server error and some bad logic in the client side. What could we do in these cases?
Reading the source? ... uhm, content wasn't there ...
Using firebug? Maybe, but content could not be there as well ...
Press F5 and reload the page? ... ok, but why should we loose our content in this way? What I mean, I wasted my time to write that message and why on heart should I spend twice ... ok, ok, here I come with these "stupid" links:
- Update
CTAPbIu_MABP gave me a suggestion to write an all in one version, keep it ;)
Enable All - Enable Areas
- Enable Inputs
- Enable Buttons
- Enable Select
If you bookmark these links, dragging them in your Browser Bookmarks area, you will be able in 90% of cases to enable again the blocked page.
Basically, I created the first one (runtime and in few seconds), Enable Area, to get my content that was inside the disabled textarea, to refresh the page and try the entire operation without loosing whatever I wrote before.
The simple used code is this one:
(function(A,G){A=document.getElementsByTagName(A);G=A.length;while(G--)A[G].disabled=!A})("textarea")
and the difference between those links is only in the sent parameter, the first is the string textarea, the second is the string input, and finally the third one is the string button.
These links, and this code, are compatible with every browser that supports javascript uris (so, basically, every recent browser where recent means since some year ago ...)
Finally, in this way we use JavaScript to help us with pages that have problems with JavaScript, sounds weird? :D
Tuesday, April 08, 2008
Famous documentation and the dark side of "this" !
The good thing of internet is that you can find a lot of free documentation.
At the same time, the bad thing of internet, is that this documentation is rarely updated.
It could be a "guru documentation" or it could be a newbie documentation, but in both cases, it doesn't matter because it is probably wrong, not updated, or too generic.
This post has not enough space to describe every error you can find on, and off line ... so let me start with some true example about a common misunderstood referer, the this one.
This page is famous enough, and I suppose that every true JavaScript developer has read them at least once.
The main error in that page is described in this sentence
We know, or maybe we don't, that everything without a prefix will be executed in the global scope or in nested closure, if any. But even if a function is created inside a method, it fortunately does not make sense to call a function that has not been assigned as instance method and find a this reference inside.
The main reason we do not need to use window when we call a global method, or function, is that everything in JavaScript is virtually executed like in a global window with statement (that's why write window.open is redundant and nothing else ... and Stargate code is totally redundant too :D).
Let's focus on the onload example in the middle ... ok? Who will be the this referer if we do not use call or apply Function.prototype methods? window, of course.
And as window has a self property, that a link to window itself, if we use alert(this === self); it will be true every time we will use onload();
If we assign onload function as object method
... we will read two alerts with two false instead of two true value.
This simply means that to use a function that has not been assigned as method, or better, that is not called from a method, the this reference will be the global object.
I do not really know why Doug defined this an error in ECMA Specification, but if it really is, what could be the logic behaviour, an "unpredictable" default this referer even if the nested function is not inside an instance constructor?
I don't think so.
Thanks to this "error", we could use a constructor in two ways or recognize when it has been called with new or as function.
If it is an error, it couldn't be possible to know this kind of useful information.
Anyway, as I wrote in my recent and updated documentation, that passed totally unobserved, we do not need a that variable for nested private function.
Finally, I have to admit that Douglas Crockford is my favourite JavaScript professor, and it's basically thanks to him that I know what I know about JavaScript. He wrote a lot of interesting JS stuff, and some document is truly updated, explaining for example errors wrote in old one.
Every programmer should evolve because in this sector knowledge is never enough. So thanks a lot Doug, but please update your 2001 doc writing something more about this, that, scope, injected this, and closures :D (a link to this post should be appreciated as well)
Differently, here we are in late 2007 ... December 2007
For some reason, few days ago someone posted again this book in Digg ... and for the first time, I read about them.
It seems to be really a good book, but without reading them, I've just downloaded examples trying to imagine what are these used for.
Fortunately, and thanks to Apress or authors decision, these sources are free and well organized inside chapter folders, each file with dedicated paragraph.
Well done ... but at the third chapter, I've read a pseudo "horror" in file 3.07 ...
Forgetting the missed = function, that could be a common error during quick development, getUPPER_BOUND is a privileged method of the global scope, aka window, and it is not static, it is like a window.getUPER_BOUND call, where this is obviously the window itself.
As I wrote few lines before, if we use this inside a function it will refer to window object. That's why after we can see a wrong example like this one:
I am pretty sure that if this code is the one showed to explain privileged, that chapter could be full of errors ... please update them putting correct code and free corrected page inside the zip ... otherwise, sorry for this correction.
Finally, Dustin and Ross are two JavaScript ninjas, and reading the rest of the code it seems that I absolutely need to find that book because I do like design patterns and I am so curious to know how are their implementation (good stuff guys!).
I am the first one that writes horrible code, and probably I've even forgot what I wrote one year ago and where ... so the only suggestion I could write is that if you find something interesting, or something that you did not know, look for something else and look every time for the date that document has been published.
Have fun with self instruction, and never stop ;)
At the same time, the bad thing of internet, is that this documentation is rarely updated.
It could be a "guru documentation" or it could be a newbie documentation, but in both cases, it doesn't matter because it is probably wrong, not updated, or too generic.
This post has not enough space to describe every error you can find on, and off line ... so let me start with some true example about a common misunderstood referer, the this one.
Douglas Crockford and Private Members in JavaScript
This page is famous enough, and I suppose that every true JavaScript developer has read them at least once.
The main error in that page is described in this sentence
By convention, we make a private that parameter. This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.
We know, or maybe we don't, that everything without a prefix will be executed in the global scope or in nested closure, if any. But even if a function is created inside a method, it fortunately does not make sense to call a function that has not been assigned as instance method and find a this reference inside.
// guys, this function ...
window.testMe = function(){};
// is exactly the same of this one
function testMe(){};
// or this one in a global scope
var testMe = function(){};
The main reason we do not need to use window when we call a global method, or function, is that everything in JavaScript is virtually executed like in a global window with statement (that's why write window.open is redundant and nothing else ... and Stargate code is totally redundant too :D).
// this code ...
window.onload = function(){};
// is exactly the same of this one
onload = function(){};
onload();
// that is virtually similar to ...
with(window){
onload();
};
Let's focus on the onload example in the middle ... ok? Who will be the this referer if we do not use call or apply Function.prototype methods? window, of course.
And as window has a self property, that a link to window itself, if we use alert(this === self); it will be true every time we will use onload();
If we assign onload function as object method
onload = function(){
alert(this === self);
alert(this === window);
};
var o = {};
o.onload = onload;
... we will read two alerts with two false instead of two true value.
This simply means that to use a function that has not been assigned as method, or better, that is not called from a method, the this reference will be the global object.
onload = function(){
alert(this === window);
};
onload(); // true
var o = {onload:onload};
o.onload(); // false
function useCallback(callback){
callback();
};
useCallback(o.onload); // false again
I do not really know why Doug defined this an error in ECMA Specification, but if it really is, what could be the logic behaviour, an "unpredictable" default this referer even if the nested function is not inside an instance constructor?
I don't think so.
The intrinsic constructor Factory Design Pattern
Thanks to this "error", we could use a constructor in two ways or recognize when it has been called with new or as function.
If it is an error, it couldn't be possible to know this kind of useful information.
function Person(name, age){
// this is true only if we used
// new before Person constructor
if(this instanceof Person){
this.name = name;
this.age = age;
} else
// otherwise we used the constructor
// as factory design pattern (in this example)
return new Person(name, age);
};
// these two lines do the same thing: create a Person instance
var me = Person("Andrea", 29), // doyou like python style, don't you?
you = new Person("You", null);
alert(me instanceof Person); // true
alert(you instanceof Person); // true
Anyway, as I wrote in my recent and updated documentation, that passed totally unobserved, we do not need a that variable for nested private function.
function Person(name, age){
function setNameAndAge(){
this.name = name;
this.age = age;
};
// to call setNameAndAge as private
// method we do not need a that
// but only call or apply Function.prototype
// methods to inject instance as this referer
setNameAndAge.call(this);
};
alert(
(new Person("Andrea", 29)).name // Andrea
);
Finally, I have to admit that Douglas Crockford is my favourite JavaScript professor, and it's basically thanks to him that I know what I know about JavaScript. He wrote a lot of interesting JS stuff, and some document is truly updated, explaining for example errors wrote in old one.
My programming style has evolved since then, as any good programmer's should. I have learned to fully embrace prototypalism, and have liberated myself from the confines of the classical model.
Every programmer should evolve because in this sector knowledge is never enough. So thanks a lot Doug, but please update your 2001 doc writing something more about this, that, scope, injected this, and closures :D (a link to this post should be appreciated as well)
Ross and Dustin in Pro JavaScript Design Patterns
Differently, here we are in late 2007 ... December 2007
For some reason, few days ago someone posted again this book in Digg ... and for the first time, I read about them.
It seems to be really a good book, but without reading them, I've just downloaded examples trying to imagine what are these used for.
Fortunately, and thanks to Apress or authors decision, these sources are free and well organized inside chapter folders, each file with dedicated paragraph.
Well done ... but at the third chapter, I've read a pseudo "horror" in file 3.07 ...
var Class = (function() {
// Constants (created as private static attributes).
var UPPER_BOUND = 100;
// Privileged static method.
// ... that will never work, where is the function?
this.getUPPER_BOUND() {
return UPPER_BOUND;
}
// Return the constructor.
return function(constructorArgument) {
//
}
})();
Forgetting the missed = function, that could be a common error during quick development, getUPPER_BOUND is a privileged method of the global scope, aka window, and it is not static, it is like a window.getUPER_BOUND call, where this is obviously the window itself.
As I wrote few lines before, if we use this inside a function it will refer to window object. That's why after we can see a wrong example like this one:
var Class = (function() {
var constants = {
UPPER_BOUND: 100,
LOWER_BOUND: -100
}
// again ...
this.getConstant = function(name) {
return constants[name];
}
return function(constructorArgument) {
//...
}
})();
// anyway ... Error!!!
Class.getConstant('UPPER_BOUND');
alert(Class.getConstant); // undefined
alert(getConstant); // expected function
I am pretty sure that if this code is the one showed to explain privileged, that chapter could be full of errors ... please update them putting correct code and free corrected page inside the zip ... otherwise, sorry for this correction.
Finally, Dustin and Ross are two JavaScript ninjas, and reading the rest of the code it seems that I absolutely need to find that book because I do like design patterns and I am so curious to know how are their implementation (good stuff guys!).
Conclusion
I am the first one that writes horrible code, and probably I've even forgot what I wrote one year ago and where ... so the only suggestion I could write is that if you find something interesting, or something that you did not know, look for something else and look every time for the date that document has been published.
Have fun with self instruction, and never stop ;)
Monday, April 07, 2008
Natural JavaScript private methods
I've never seen this technique yet, but basically it allows us to create private methods, without privileged, and in an way that does not allow subclasses to inherit them ... does it sound interesting? ;)
As we can read in my JavaScript Prototypal Inheritance for Classical Emulation documentation, there is a way to easily create private methods without usage of privileged.
The advantage of this way is, as explained in my doc, is that JavaScript interpreter does not have to create many functions for each declared instance.
Here there is a basic example:
Function toString will be shared by prototype with every created instance for the simple reason that every instance will inherit prototype.toString method and, at the same time, it points to private scope where toString function has been defined.
Is everything ok? Perfect, because we have to comprehend quite perfectly above example to understand what we are going to do right now ( and if you do not understand, read my doc to know more :P )
What we have to do each time is to remember that when we need a private method, with our instance injected scope, we have to write in an unnatural way.
What I mean is that if we usually use the underscore prefix to define our virtually protected methods, why couldn't we use them to define a function for private stuff only?
The difference is basically in this line of code:
Please do not forget that these methods are private, so there is no way to use them in subclasses, if those are created in an external or different closure, and that is exactly an expected behaviour (these functions are private).
But at the same time, if a subclass call an inherited method that use inside the parent prototype the private underscore, it will work perfectly.
Finally, what we can do with this method, is to redefine them to allow us to overwrite private functions and/or use them without problems:
That's it :)
As we can read in my JavaScript Prototypal Inheritance for Classical Emulation documentation, there is a way to easily create private methods without usage of privileged.
The advantage of this way is, as explained in my doc, is that JavaScript interpreter does not have to create many functions for each declared instance.
Here there is a basic example:
// our constructor
function Person(name, age){
this.name = name;
this.age = age;
};
// prototype assignment
Person.prototype = (function(){
// we have a scope for private stuff
// created once and not for every instance
function toString(){
return this.name + " is " + this.age;
};
// create the prototype and return them
return {
// never forget the constructor ...
constructor:Person,
// "magic" toString method
toString:function(){
// call private toString method
return toString.call(this);
}
};
})();
// example
alert(
new Person("Andrea", 29)
); // Andrea is 29
Function toString will be shared by prototype with every created instance for the simple reason that every instance will inherit prototype.toString method and, at the same time, it points to private scope where toString function has been defined.
Is everything ok? Perfect, because we have to comprehend quite perfectly above example to understand what we are going to do right now ( and if you do not understand, read my doc to know more :P )
What we have to do each time is to remember that when we need a private method, with our instance injected scope, we have to write in an unnatural way.
What I mean is that if we usually use the underscore prefix to define our virtually protected methods, why couldn't we use them to define a function for private stuff only?
// our constructor
function Person(name, age){
this.name = name;
this.age = age;
};
// prototype assignment
Person.prototype = (function(){
// private stuff
function toString(){
return this.name + " is " + this.age;
};
// prototype
return {
constructor:Person,
toString:function(){
// call private toString method
// in a more natural way
return this._(toString)();
},
// define private methods dedicated one
_:function(callback){
// instance referer
var self = this;
// callback that will be used
return function(){
return callback.apply(self, arguments);
};
}
};
})();
// example
alert(
new Person("Andrea", 29)
); // Andrea is 29
The difference is basically in this line of code:
// instead of this way
return toString.call(this);
// we have this one
return this._(toString)();
Please do not forget that these methods are private, so there is no way to use them in subclasses, if those are created in an external or different closure, and that is exactly an expected behaviour (these functions are private).
But at the same time, if a subclass call an inherited method that use inside the parent prototype the private underscore, it will work perfectly.
// basic extend function
function extend(B, A){
function I(){};
I.prototype = A.prototype;
B.prototype = new I;
B.prototype.constructor = B;
B.prototype.parent = A;
};
// same stuff ...
function Person(name, age){
this.name = name;
this.age = age;
};
Person.prototype = (function(){
function toString(){
return this.name + " is " + this.age;
};
return {
constructor:Person,
toString:function(){
return this._(toString)();
},
_:function(callback){
var self = this;
return function(){
return callback.apply(self, arguments);
};
}
};
})();
// subclass
function Employee(company, name, age){
this.parent.call(this, name, age);
this.company = company;
};
extend(Employee, Person);
Employee.prototype.getFullDetails = function(){
// toString has been inherited from Person
// and it uses inside the private method
return this.toString() + " and works in " + this.company;
};
var other = new Employee("Mega Ltd", "Daniele", 26);
alert(
other.getFullDetails()
);
Finally, what we can do with this method, is to redefine them to allow us to overwrite private functions and/or use them without problems:
// above stuff + subclass
function Employee(company, name, age){
this.parent.call(this, name, age);
this.company = company;
};
extend(Employee, Person);
// extend prototype and return them
Employee.prototype = (function(proto){
function toString(){
return this.company;
};
proto.toString = function(){
return this.parent.prototype.toString.call(this) + " and works in " + this._(toString)();
};
proto._ = function(callback){
var self = this;
return function(){
return callback.apply(self, arguments);
};
};
return proto;
})(Employee.prototype);
alert(new Employee("Mega Ltd", "Daniele", 26));
// Daniele is 26 and works for Mega Ltd
That's it :)
Sunday, April 06, 2008
PHP - JavaScript like Object class
As I've wrote in last post, there's some JavaScript feature I would like to have in PHP too.
This time we will use a basic implementation of JavaScript Object constructor in PHP.
What we need to start is this class, based on SPL ArrayAccess interface.
The main goal of this class is to have a JS like literal object, and in this reduced version, with best possible performances for this kind of purpose.
Here is some example:
These instances are simple as useful and could be used instead of associative arrays.
The class contains 3 public static methods to perform common task during client/server interactions.
One of the common PHP error is to access to an associative array propery sending undefined constants instead of strings.
Of course, using associative wrong way to retrieve a property will cause a notice error again, but having the common instance "->" operator, why should we cause that notice?
Another interesting thing could be the usage of dynamic instances, and the ability to add methods (not possible with associative arrays) or use current one to share, save, or send these instances.
To have these functionalities in every day applications, we could think about this simple task:
Of course, you can find a lot of different common situation where this kind of class could be useful, don't you?
This time we will use a basic implementation of JavaScript Object constructor in PHP.
What we need to start is this class, based on SPL ArrayAccess interface.
class Object extends stdClass implements ArrayAccess {
// (C) Andrea Giammarchi - webreflection.blogspot.com - Mit Style License
// static public methods
static public function create(){
return new Object;
}
static public function parseJSON($json){
return self::create()->extend(json_decode($json));
}
static public function parseSource($source){
return self::create()->extend(unserialize($source));
}
// basic JavaScript like methods
public function extend(){
for($i = 0, $length = count($arguments = func_get_args()); $i < $length; $i++)
foreach($arguments[$i] as $key => $value)
$this->$key = $value;
return $this;
}
public function toJSONString(){
return json_encode($this);
}
public function toSource(){
return serialize($this);
}
// ArrayAccess interface methods
public function offsetExists($key){
return isset($this->$key);
}
public function offsetGet($key){
return $this->$key;
}
public function offsetSet($key, $value){
$this->$key = $value;
}
public function offsetUnset($key){
unset($this->$key);
}
}
The main goal of this class is to have a JS like literal object, and in this reduced version, with best possible performances for this kind of purpose.
Here is some example:
$o = new Object;
$o->test = "test";
echo $o->test === $o['test']; // 1
$o['other_test'] = 123;
echo $o->other_test; // 123
These instances are simple as useful and could be used instead of associative arrays.
The class contains 3 public static methods to perform common task during client/server interactions.
// factory pattern
$o = Object::create();
// factory with serialized string
$o = Object::parseSource(serialize(array('A'=>'A')));
echo $o->A; // A
// factory with JSON string
$o = Object::parseJSON('{"B":"B"}');
echo $o->B; // B
One of the common PHP error is to access to an associative array propery sending undefined constants instead of strings.
$a = array('A'=>'A');
echo $a[A]; // notice, defined constant possible ambiguity
// factory + extend
$o = Object::create()->extend($a);
// we have two ways to access to the same property
echo $o->A; // OK, output is A
echo $o['A']; // OK again ...
Of course, using associative wrong way to retrieve a property will cause a notice error again, but having the common instance "->" operator, why should we cause that notice?
Another interesting thing could be the usage of dynamic instances, and the ability to add methods (not possible with associative arrays) or use current one to share, save, or send these instances.
$me = new Object;
$me->name = 'Andrea';
$me->surname = 'Giammarchi';
$me->age = 29; // ... still ...
// simple interaction
echo '';';
foreach($me as $key => $value)
echo $key."\t".$value.PHP_EOL;
echo '
// or JSON / PHP serializzation
echo // {"name":"Andrea","surname":"Giammarchi","age":29}
$me->toJSONString().
PHP_EOL.
// O:6:"Object":3:{s:4:"name";s:6:"Andrea";s:7:"surname";s:10:"Giammarchi";s:3:"age";i:29;}
$me->toSource();
To have these functionalities in every day applications, we could think about this simple task:
$result = array();
$query = mysql_unbuffered_query(
'SELECT t.name AS "name", t.surname AS "surname", t.age AS "age" FROM table t',
$connection
);
while(@$row = mysql_fetch_assoc($query))
$result[] = Object::create()->extend($row);
echo 'First person name is '.$result[0]->name;
Of course, you can find a lot of different common situation where this kind of class could be useful, don't you?
Saturday, April 05, 2008
PHP - apply, call, and Callback class
The "news" is that while some developer is putting a lot of effort to emulate PHP functionalities with JavaScript, I would like to have JavaScript functionalities in PHP.
Nested functions, closures, and injected scope, are only some of JS cool stuff that's currently missing PHP (hoping that during this summer of code someone will implement at least one of them).
Today what I'm going to emulate is a partial implementation of apply and call Function.prototype methods, and this is the basic example:
As is for JavaScript, the main difference between these functions is that apply accept an array of arguments while call accepts an arbitrary number of arguments.
Simple, but not so useful yet.
Currently, these implementations are just shortcuts to call_user_func or call_user_func_array PHP native functions ... and these are not JavaScript style friendly ... so what could we do?
To have a JS style code we would like to be able to write something like this:
... and I suppose noone could say that this way couldn't be cool, isn't it?
To obtain above behavior all we need is a class, called for obvious reasons Callback, that will contain those 2 public static methods:
What we can do now, is to create every kind of function alias simply sending the name of the function or arguments and body for a runtime function creation.
The public name property will contain the string rappresenting the used function name (lambda too), while the magic __toString method will return the name using dedicated ReflectionFunction isntance method (note: lambda functions have everytime the same one: __lambda_func).
With a simple class like this one we are able to send or recieve callbacks between functions, methods, or whatever else ... have you never sent a function in this way?
The principal goal is to solve type checks and improve code portability ... but with another little piece of code, this stuff could be even funny!
With above function we are now able to do something like:
Or, to be extremely scriptish, something like:
Enjoy :)
Nested functions, closures, and injected scope, are only some of JS cool stuff that's currently missing PHP (hoping that during this summer of code someone will implement at least one of them).
Today what I'm going to emulate is a partial implementation of apply and call Function.prototype methods, and this is the basic example:
function apply($name, array $arguments = array()){
return call_user_func_array($name, $arguments);
}
function call(){
$arguments = func_get_args();
return call_user_func_array(array_shift($arguments), $arguments);
}
As is for JavaScript, the main difference between these functions is that apply accept an array of arguments while call accepts an arbitrary number of arguments.
echo call('md5', 'hello world');
// 5eb63bbbe01eeed093cb22bb8f5acdc3
echo apply('pow', array(2, 3));
// 8
Simple, but not so useful yet.
Currently, these implementations are just shortcuts to call_user_func or call_user_func_array PHP native functions ... and these are not JavaScript style friendly ... so what could we do?
To have a JS style code we would like to be able to write something like this:
$md5->call('hello world');
$pow->apply(array(2, 3));
... and I suppose noone could say that this way couldn't be cool, isn't it?
To obtain above behavior all we need is a class, called for obvious reasons Callback, that will contain those 2 public static methods:
class Callback{
// (C) webreflection.blogspot.com - Mit Style License
public $name; // name of the function
protected $_callback; // ReflectionFunction instance
public function __construct($arguments, $callback = ''){
$this->_callback = new ReflectionFunction(
0 < strlen($arguments) &&
strlen($callback) < 1 &&
is_callable($arguments) &&
function_exists($arguments) ?
$this->name = $arguments :
$this->name = ''.create_function($arguments, $callback)
);
}
public function __toString(){
return $this->_callback->getName();
}
public function apply(array $arguments){
return $this->_callback->invokeArgs($arguments);
}
public function call(){
// /* simple, unfornutatly with bad performances */ return $this->apply(func_get_args());
return $this->_callback->invokeArgs(func_get_args());
}
}
What we can do now, is to create every kind of function alias simply sending the name of the function or arguments and body for a runtime function creation.
$md5 = new Callback('md5');
$pow = new Callback('pow');
$sum = new Callback('$x, $y', 'return $x + $y;');
echo $md5->call('hello world').PHP_EOL; // 5eb63bbbe01eeed093cb22bb8f5acdc3
echo $pow->apply(array(2, 3)).PHP_EOL; // 8
echo $sum->call(2, 3).PHP_EOL; // 5
The public name property will contain the string rappresenting the used function name (lambda too), while the magic __toString method will return the name using dedicated ReflectionFunction isntance method (note: lambda functions have everytime the same one: __lambda_func).
With a simple class like this one we are able to send or recieve callbacks between functions, methods, or whatever else ... have you never sent a function in this way?
function hashMe($value, Callback $hash){
return $hash->call($value);
}
$md5 = new Callback('md5');
$sha1 = new Callback('sha1');
echo hashMe('hello world', $md5).
PHP_EOL.
hashMe('hello world', $sha1);
// 5eb63bbbe01eeed093cb22bb8f5acdc3
// 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
The principal goal is to solve type checks and improve code portability ... but with another little piece of code, this stuff could be even funny!
// Callback dedicated factory pattern function
function callback(){
static $Callback;
if(!isset($Callback))
$Callback = new ReflectionClass('Callback');
return $Callback->newInstanceArgs(func_get_args());
}
With above function we are now able to do something like:
echo callback('str_repeat')->call('hello world ', 2);
// hello world hello world
Or, to be extremely scriptish, something like:
// create a string with "callback" content
$F = 'callback';
// use them as a function
echo $F('str_repeat')->call('hello world ', 2);
echo $F('pow')->call(2, 3);
// but if we need better performances ...
$md5 = $F('md5');
while($i--)
echo $md5->call($container[$i]);
Enjoy :)
Monday, March 31, 2008
Bases, merits, and defects of packed code
How many times we have seen an included JavaScript apparently incomprehensible?
These examples could explain better what I mean:
packed.it via MyMin
Dean Edwards packer
These are only two parsers which aim is to reduce code size using an inline decompression technique that is able to evaluate source code after common keywords replacement.
The main goal of these services is to compress a source reducing occurrences of repeated words, using different technique to create both compressed string and inline function with decompression algo.
In this paragraph we will see a rudimentary example on how can be possible to create our own compressor. Let's go with the first function:
Reading comments, we can understand the logic behind a client side based compressor.
And since compression operation follows usually a "one to many" logic, where one is the operation to compress, and many are clients that will decompress code, more simple and fast will be the decompression operation, more powerful, portable, and compatible will be our algorithm.
The last ring of our chain, is a function that is able to create automatically final result code:
This is our first home made client side compression example, not really so efficient, but good enough to understand the logic behind.
It simply does not necessary require server side operations to optimize the result size of our scripts, that are every day more than ever "thanks" to the Web 2.0 era.
Required bandwidth will be less than before, while download speed will be increased, and more code we pack, more possibilities we have that ratio between source and packed code will be greater, thanks to common names for common tasks programming routines.
Nowadays, quite every browser supports gzip or deflate runtime decompression.
These compression algorithms are really efficient thanks to decompression speed, 10 to 100 faster than pure JavaScript operations plus evaluation, and thanks to their support provided by every server side program language.
Every time we download a client side packed code, even if file will be saved in browser cache, it has to be executed every time we will visit that page again.
So, if our goal is to increase page interaction speed during navigation, JavaScript decompression delay will be a problem.
If this problem will be hilarious or heavy, it depends only on client hardware and its browser performances.
At the same time, using a gzip or deflate compression over a packed code, will not truly increase performances and result will be bigger than clear code gzip compression.
The reason is that common compression algorithms create compressed code using a dictionary that will contain common, repeated, words or letters, found in original string.
Since JavaScript compressors usually replace numbers or words with a unique identfier to be able to recreate original string, resulted string will contain much more characters pairs than before and every baseN encoded key, that is not human friendly and for this reason rarely wrote in original code, could be one more byte inside final compressed string.
Finally, client side compressors are not, usually, 100% compatible with every kind of code, and this is another reason to prefer minifiers + gzip|deflate to obtain the best, fastest, and finally smallest, result.
Nowadays, pure JavaScript client side runtime decompression technique is not really a necessary, but in some case, it could do things that gzip or deflate will never be able to do, for example merging both JavaScript and CSS using a single and common keywords list to produce a unique file that could contain both JavaScript and CSS with the best size result requiring only 1 download instead of 2 (1 for JavaScript, 1 for CSS). That is what packed.it is able to do since 2007, but never forget speed issue and please remember that more great will be packed code, more delay there will be in every page that will use them.
These examples could explain better what I mean:
packed.it via MyMin
eval((function(M,i,n){return '0("1");'.replace(/\w+/g,function(m){return (n[m]!=i[m]&&i[m])||(i[m]=M[parseInt(m,36)])})})('alert.test'.split('.'),{},Object.prototype))
Dean Edwards packer
eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--)d[c]=k[c]||c;k=[(function(e){return d[e]})];e=(function(){return'\w+'});c=1};while(c--)if(k[c])p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c]);return p}('1('0');',2,2,'test|alert'.split('|'),0,{}))
These are only two parsers which aim is to reduce code size using an inline decompression technique that is able to evaluate source code after common keywords replacement.
Basis of portable and packed code
The main goal of these services is to compress a source reducing occurrences of repeated words, using different technique to create both compressed string and inline function with decompression algo.
In this paragraph we will see a rudimentary example on how can be possible to create our own compressor. Let's go with the first function:
function pack(code, keywords){
var re = /\w+/g,
filter = {},
key;
// foreach word or number in string
while(key = re.exec(code))
// make found one unique
// if does not exists it creates them
// otherwise it overwrite them
filter[key[0]] = 0;
// for example, if code is "a b a", filter
// will contain only two properties, a and b
// with value 0 for both of them
// with found list of unique words or numbers
for(key in filter)
// avoid inherited Object.prototype parameters or methods
if(filter.hasOwnProperty(key))
// add key to array
// save into filter key position in the array
// converting them into base 36 string
filter[key] = (keywords.push(key) - 1).toString(36);
// for example, if code is "a b a", filter.a value will be 0, and filter.b will be 1
// for each word or number
// return keyword index in base 36 format
return code.replace(re, function(key){
return filter[key];
// for example, if code is "a b a"
// returned code will be "0 1 0"
});
};
var myCode = 'alert("this alert will show this text");',
myKeywords = [],
packed = pack(myCode, myKeywords);
alert(packed); // 0("1 0 2 3 1 4");
Reading comments, we can understand the logic behind a client side based compressor.
And since compression operation follows usually a "one to many" logic, where one is the operation to compress, and many are clients that will decompress code, more simple and fast will be the decompression operation, more powerful, portable, and compatible will be our algorithm.
function unpack(code, keywords){
// foreach word or number
return code.replace(/\w+/g, function(key){
// return related keywords value
// converting base 36 string into
// base 10 index
return keywords[parseInt(key, 36)];
// for example, if code is "0 1 0"
// returned string will be like
// keywords[0] + " " + keywords[1] + " " + keywords[0]
});
};
(unpack(packed, myKeywords) === myCode); // true
The last ring of our chain, is a function that is able to create automatically final result code:
function portablePack(code){
var
// keywords container
keywords = [],
// packed version of the code
packed = pack(code, keywords),
// object to make returned string evaluable
safe = {"'":"\\'", "\\":"\\\\", "\n":"\\n", "\r":"\\r"};
// to solve problems with some special char inside the string
// make packed result more safe replacing chars using safe object keys values
packed = packed.replace(/'|\\|\n|\r/g, function(match){
return safe[match];
});
// return an evaluable string
return "eval((function(p,l){return p.replace(/\\w+/g,function(k){return l[parseInt(k,36)]})})('" + packed + "','" + keywords.join(".") + "'.split('.')))";
// created string has to contain an inline function
// that should be able to return original code
// to eval function. Created string will be
// something like
// eval((function(packedString,keywords){return unpack(packedString,keywords)})("packed string", "key.words.list".split(".")))
};
This is our first home made client side compression example, not really so efficient, but good enough to understand the logic behind.
Merits of client side compression technique
It simply does not necessary require server side operations to optimize the result size of our scripts, that are every day more than ever "thanks" to the Web 2.0 era.
Required bandwidth will be less than before, while download speed will be increased, and more code we pack, more possibilities we have that ratio between source and packed code will be greater, thanks to common names for common tasks programming routines.
Defects of packed code
Nowadays, quite every browser supports gzip or deflate runtime decompression.
These compression algorithms are really efficient thanks to decompression speed, 10 to 100 faster than pure JavaScript operations plus evaluation, and thanks to their support provided by every server side program language.
Every time we download a client side packed code, even if file will be saved in browser cache, it has to be executed every time we will visit that page again.
So, if our goal is to increase page interaction speed during navigation, JavaScript decompression delay will be a problem.
If this problem will be hilarious or heavy, it depends only on client hardware and its browser performances.
At the same time, using a gzip or deflate compression over a packed code, will not truly increase performances and result will be bigger than clear code gzip compression.
The reason is that common compression algorithms create compressed code using a dictionary that will contain common, repeated, words or letters, found in original string.
Since JavaScript compressors usually replace numbers or words with a unique identfier to be able to recreate original string, resulted string will contain much more characters pairs than before and every baseN encoded key, that is not human friendly and for this reason rarely wrote in original code, could be one more byte inside final compressed string.
Finally, client side compressors are not, usually, 100% compatible with every kind of code, and this is another reason to prefer minifiers + gzip|deflate to obtain the best, fastest, and finally smallest, result.
Conclusion
Nowadays, pure JavaScript client side runtime decompression technique is not really a necessary, but in some case, it could do things that gzip or deflate will never be able to do, for example merging both JavaScript and CSS using a single and common keywords list to produce a unique file that could contain both JavaScript and CSS with the best size result requiring only 1 download instead of 2 (1 for JavaScript, 1 for CSS). That is what packed.it is able to do since 2007, but never forget speed issue and please remember that more great will be packed code, more delay there will be in every page that will use them.
Monday, March 24, 2008
My 5 cents about JavaScript Prototypal Inheritance
Few days ago I read an interesting post about Simple JavaScript Inheritance.
The most hilarious thing is that prototypal inheritance is truly simple, as John wrote, but there are still a lot of developers that do not probably understand perfectly them.
In this link you can find an "all in one" page about JavaScript prototypal inheritcance and classical emulation.
As I wrote at the end of that page, please do not hesitate to correct me if there is something wrong, or please ask me more details if there is something that is not so clear.
Sorry for my not perfect yet English, and have fun with JavaScript.
(happy easter too!)
The most hilarious thing is that prototypal inheritance is truly simple, as John wrote, but there are still a lot of developers that do not probably understand perfectly them.
In this link you can find an "all in one" page about JavaScript prototypal inheritcance and classical emulation.
As I wrote at the end of that page, please do not hesitate to correct me if there is something wrong, or please ask me more details if there is something that is not so clear.
Sorry for my not perfect yet English, and have fun with JavaScript.
(happy easter too!)
Friday, March 21, 2008
How to inject protected methods in JavaScript - Part II
As a performances maniac, I've found another way to inject protected methods, or something similar, without unnecessary overload of each public method.
Of course, precedent way is definitively more clear, linear, but if you have a constructor.prototype with a lot of private methods, the overload process will be a wall in front of method execution speed.
Each time you will use a public method, you have to set, and unset, every protected method, and at the same time, as explained in my precedent post, you cannot send the object outside during public method execution, because it will expose every method, protected included.
This new proposal is based on a Function like strategy, applied to instances: apply, and call. Please have a look at this prototype function:
A usage example should be this one:
The first sent object will be the prototype of MyMath constructor, while the second one will contain protected methods.
As you can see in the simple prototype function, there's no override and no overhead for both public and protected methods. This means that you can use a public method directly and without problems:
These simply "does not exists" :)
Protected methods are not directly accessible even from instance itself. This means that these methods are safe and not mutable, if used object is created in a private scope, or runtime as showed before.
Apply and call, in this case, are used with instance to call a method that, if contain an underscore as first prefix char, will be one from protected prototype, otherwise will be one of the public prototype. Sounds weird?
If everyone can call a method, it does not make sense to call them protected.
But this time, the meaning is not the same of classical inheritance, but it is more close to the word itself: proteced.
The main goal is to have a not common or usual way to call methods, specially for libraries developers.
Every API could be based on public methods, while authors could choose to call a protected method when their need them.
This is basically a transparent layer between the developer and the final user: who will use num.call("doStuff") when you can do this: num.doStuff() ?
I know I am not so good to explain my ideas, so I hope someone will find this useful. Have a nice easter ;)
Of course, precedent way is definitively more clear, linear, but if you have a constructor.prototype with a lot of private methods, the overload process will be a wall in front of method execution speed.
Each time you will use a public method, you have to set, and unset, every protected method, and at the same time, as explained in my precedent post, you cannot send the object outside during public method execution, because it will expose every method, protected included.
This new proposal is based on a Function like strategy, applied to instances: apply, and call. Please have a look at this prototype function:
function prototype(constructor, public, protected){
// webreflection - mit style
if(protected){
public.apply = function(callback, arguments){
return (callback.charAt(0) === "_" ? protected : this)[callback].apply(this, arguments);
};
public.call = function(callback){
return this.apply.call(this, callback, Array.prototype.slice.call(arguments, 1));
};
};
public.constructor = constructor;
constructor.prototype = public;
return public;
};
A usage example should be this one:
function MyMath(value){
this.value = value;
};
prototype(
MyMath,
{doStuff:function(){
return this.value * this.value;
}},
{_doStuff:function(){
return this.value + this.value;
}}
);
The first sent object will be the prototype of MyMath constructor, while the second one will contain protected methods.
About performances
As you can see in the simple prototype function, there's no override and no overhead for both public and protected methods. This means that you can use a public method directly and without problems:
var num = new MyMath(3);
num.doStuff(); // direct, fast as regular prototype
About protected methods
These simply "does not exists" :)
var num = new MyMath(3);
num._doStuff(); // error
Protected methods are not directly accessible even from instance itself. This means that these methods are safe and not mutable, if used object is created in a private scope, or runtime as showed before.
How to use protected methods
var num = new MyMath(3);
alert(num.call("_doStuff")); // 6
Apply and call, in this case, are used with instance to call a method that, if contain an underscore as first prefix char, will be one from protected prototype, otherwise will be one of the public prototype. Sounds weird?
// full example
function MyMath(value){
this.value = value;
};
prototype(
MyMath,
{doStuff:function(){
return this.value * this.value;
}},
{_doStuff:function(){
return this.value + this.value;
}}
);
var num = new MyMath(3);
alert([
num.doStuff(), // 9
num.call("doStuff"), // 9
num.call("_doStuff") // 6
].join("\n"));
num._doStuff; // undefined
Why do I call them protected
If everyone can call a method, it does not make sense to call them protected.
But this time, the meaning is not the same of classical inheritance, but it is more close to the word itself: proteced.
The main goal is to have a not common or usual way to call methods, specially for libraries developers.
Every API could be based on public methods, while authors could choose to call a protected method when their need them.
This is basically a transparent layer between the developer and the final user: who will use num.call("doStuff") when you can do this: num.doStuff() ?
I know I am not so good to explain my ideas, so I hope someone will find this useful. Have a nice easter ;)
Thursday, March 13, 2008
ABC - Ajax Basic Call
I know everyone uses incredibly cool libraries that do everything in few lines, and 30 or more Kb ... but do you always need all this stuff for simple Ajax interactions?
The JavaScript ninja secret is to create everything ad hoc, where everything will be under control and will be extremely optimized and, why not, fast.
ABC goals is to let you use, simply, Ajax.
What is Ajax in few words? The possibility to send and recieve data, usually using GET, POST, or both method (POST with a query stirng).
That's exactly what you can do with ABC, and these are major features:
Here some example code:
These are only the beginning ... there's more, because we all love callbacks and asyncronous requests!
Both onLoad and onError are optional callbacks ... and that's basically how ABC works to choose GET or POST method:
The good thing is that you have exactly same parameters that a regular XMLHttpRequest instance wants in open methods. This basically means that migration between some code will be ridiculously simple.
On the other hand, ABC is simple and is perfect for simple things.
Of course if you need more features ... you are higher level than ABC ... but for every other client / server interaction, are you sure you need every time so many features?
This is the source, and this is the packed.it version ... about 0.66Kb (deflate) ... and that's it! Enjoy Ajax :geek:
The JavaScript ninja secret is to create everything ad hoc, where everything will be under control and will be extremely optimized and, why not, fast.
ABC goals is to let you use, simply, Ajax.
What is Ajax in few words? The possibility to send and recieve data, usually using GET, POST, or both method (POST with a query stirng).
That's exactly what you can do with ABC, and these are major features:
- simple, fast, lightweight ... probably the only function you need for 80% of Ajax tasks
- unobtrusive, does not change, create, modify ... absolutely nothing
- IE cache safe, forget IE cache problems without effort
- array compatible, send single dimensional arrays too
- easily integrable, using around your own cool code to send entire forms or whatever you need
- quick but not dirty, and without global scope paranoia ... one function, every number of interactions you want, syncronous or asyncronous
Here some example code:
// basic asyncronous GET request
ABC(null, "page.php?hello=ABC");
// basic asyncronous POST request
ABC({hello:"ABC"}, "page.php");
// basic syncronous GET request
alert(
ABC(null, "page.php?hello=ABC", false).responseText
);
// basic syncronous POST request
alert(
ABC({hello:"ABC"}, "page.php", false).responseText
);
// basic syncronous POST with GET request
alert(
ABC({hello:"ABC"}, "page.php?query=string", false).responseText
);
These are only the beginning ... there's more, because we all love callbacks and asyncronous requests!
ABC({
parameter1:"Hello",
parameter2:"World",
list:[1,2,3,4,5],
onLoad:function(xhr, elapsedTime){
alert([elapsedTime, xhr.responseText]);
}
});
ABC({
parameter1:"Hello",
parameter2:"World",
list:[1,2,3,4,5],
onLoad:function(xhr, elapsedTime){
alert([elapsedTime, xhr.responseText]);
},
onError:function(xhr, elapsedTime){
alert([elapsedTime, xhr.status]);
}
});
Both onLoad and onError are optional callbacks ... and that's basically how ABC works to choose GET or POST method:
- If first argument is null, or it does not contain object properties that are not functions, the request is GET
- If first argument contains an object with at least one parameter that is not an Object prototype and is not a function, the request is POST
- If third arguments is not present or is undefined, request is syncronous by default
- If third arguments is true or false like (1, 0, "ok", undefined or null), the request will be asyncronous if true, syncronous if false (basic XMLHttpRequest behaviour)
- If you pass fourth and/or fifth argument, these are user and pass
The good thing is that you have exactly same parameters that a regular XMLHttpRequest instance wants in open methods. This basically means that migration between some code will be ridiculously simple.
On the other hand, ABC is simple and is perfect for simple things.
Of course if you need more features ... you are higher level than ABC ... but for every other client / server interaction, are you sure you need every time so many features?
This is the source, and this is the packed.it version ... about 0.66Kb (deflate) ... and that's it! Enjoy Ajax :geek:
Wednesday, March 12, 2008
Do You Like Browser Benchmarks? Here I am!
Hi guys,
today we will not talk about my last JavaScript ArrayObject creation :D
Today is the benchmark day, and in this case the test is as simple as explicative ... both Math object and scope are two things we use every day for whatever purpose in this baby Web 2.0 era!
Let me start directly with results (ORDER BY speed ASC):
What kind of benchmark is it?
This is a double test that includes the usage of scoped shortcuts, and the usage of the object that you cannot absolutely get by without: the global Math one!
To understand better this kind of test, please look at these functions:
The first one, is the most common in every day libraries / scripts, while the second one and the third one, are used by "a little bit more skilled" developers.
The second one, uses the same concept of my good old friend, the smallest FX library from 2006: bytefx
The scoped schortcut is absolutely the fastest way to use a global objet, constructor, whatever you want.
Just think about nested scopes, this amazing ECMAScript 3rd Edition more close to future than many other new program languages ... ( IMO, and sorry for exaggeration :lol: )
When you write the name of something in your scope, the engine looks obviously in the same scope, than in the external one, going on until the super global object, the window
This behavior is basically what should happen using the with statement as well ... but unfortunately, even if this is basically what's up, performances are clearly against the usage of absolutely comfortable with statement.
At the same time, there is one browser that you are probably using right now, that create a bit of confusion about everything I've just said right now: Firefox 2
With quite twice of time, using scoped shortcuts, this browser (the best I've ever used for years, and the one I'll use for other many years) reverse totally my conviction about how does scope work ... anyway, we are lucky because Mozilla staff is creating good stuff with Firefox 3 ... who cares about Firebird and other old versions? :D
Don't you really trust me and my results?
So do this bench by yourself :geek:
today we will not talk about my last JavaScript ArrayObject creation :D
Today is the benchmark day, and in this case the test is as simple as explicative ... both Math object and scope are two things we use every day for whatever purpose in this baby Web 2.0 era!
Let me start directly with results (ORDER BY speed ASC):
Firefox 3.0b4
----------------------------------
regular avg time in ms: 9.98
scoped avg time in ms: 3.18
encapsulated avg time in ms: 12.98
Safari 3.0.4 (523.15)
----------------------------------
regular avg time in ms: 13.42
scoped avg time in ms: 6.42
encapsulated avg time in ms: 11.82
Opera 9.24
----------------------------------
regular avg time in ms: 13.82
scoped avg time in ms: 9.6
encapsulated avg time in ms: 17.64
Internet Explorer 8.0.6001.17184
----------------------------------
regular avg time in ms: 16.42
scoped avg time in ms: 6.82
encapsulated avg time in ms: 16.82
Firefox 2.0.0.12
----------------------------------
regular avg time in ms: 26.84
scoped avg time in ms: 42.06
encapsulated avg time in ms: 28.64
What kind of benchmark is it?
This is a double test that includes the usage of scoped shortcuts, and the usage of the object that you cannot absolutely get by without: the global Math one!
To understand better this kind of test, please look at these functions:
function regular(){
for(var i = 0, time = new Date; i < 10000; i++)
Math.round(i / Math.PI);
time = new Date - time;
return time;
};
function scoped(){
for(var round = Math.round, PI = Math.PI, i = 0, time = new Date; i < 10000; i++)
round(i / PI);
time = new Date - time;
return time;
};
function encapsulated(){
with(Math){
for(var i = 0, time = new Date; i < 10000; i++)
round(i / PI);
time = new Date - time;
};
return time;
};
The first one, is the most common in every day libraries / scripts, while the second one and the third one, are used by "a little bit more skilled" developers.
The second one, uses the same concept of my good old friend, the smallest FX library from 2006: bytefx
The scoped schortcut is absolutely the fastest way to use a global objet, constructor, whatever you want.
Just think about nested scopes, this amazing ECMAScript 3rd Edition more close to future than many other new program languages ... ( IMO, and sorry for exaggeration :lol: )
When you write the name of something in your scope, the engine looks obviously in the same scope, than in the external one, going on until the super global object, the window
This behavior is basically what should happen using the with statement as well ... but unfortunately, even if this is basically what's up, performances are clearly against the usage of absolutely comfortable with statement.
At the same time, there is one browser that you are probably using right now, that create a bit of confusion about everything I've just said right now: Firefox 2
With quite twice of time, using scoped shortcuts, this browser (the best I've ever used for years, and the one I'll use for other many years) reverse totally my conviction about how does scope work ... anyway, we are lucky because Mozilla staff is creating good stuff with Firefox 3 ... who cares about Firebird and other old versions? :D
Don't you really trust me and my results?
So do this bench by yourself :geek:
Tuesday, March 11, 2008
Sorry Dean, I subclassed Array again
Most library authors would love to extend the Array object (especially for those tasty iteration methods) but shy away from doing so for fear of breaking other scripts. So nearly all (with the noteable exception of Prototype) leave Array and other built-in objects alone.
This is how Dean Edwards started one of his (historic) post about subclassing Array, but I finally found the way to do it better, and You'll read why and how ... please be patience :D
The nightmare does not come only from IE
We all know how weird is Internet Explorer when you try to use an array as a constructor prototype.
What you probably do not know yet, is that IE is the only one that gives you problem "instantly instead of during". Let's start with the first, basic example:
// FireFox and Safari, plus IE, why not
function MyArray(){};
MyArray.prototype = [];
/** this should be a must ... however, who cares about that ...
MyArray.prototype.constructor = MyArray;
*/
var ma = new MyArray;
ma.push(1,2,3);
alert(ma); // 1,2,3 ... seems good, isn't it?
// now, lets use our Array thinking it's an array
var a = new Array(4,5,6);
// now, for some reson you should use your
// personal Array as is ... an Array, are you sure?
a.push.apply(a, ma);
/*
second arguments to Function.prototype.apply
must be an array
expected object or arguments
type error ...
*/
Well done ... we cannot use an instance that inherits from Array as an Array. The only one that seems to be clever enough to understand that ma is basically an Array, is Opera, well done Opera Team!.
The unespected instance
Another weird situation, using precedent constructor as example, is this one:
// Every browser you can try ...
function MyArray(){};
MyArray.prototype = [];
var ma = new MyArray;
alert(ma.concat(ma) instanceof MyArray); // false
false ??? ... What does it mean, false ?
False means that if we should be able to subclass an Array with IE too, there's no browser so clever to understand that internal methods should create an instance of the same constructor ... ok, ok, it's more close to ED209 in Delta City than reality ... anyway ...
I would like to obtain an instance of my constructor, and not an array.
This simply because we could extends whatever we want and after we use every native method, so fast and so powerful, we basically will lose our enhanced constructor coming back to a native Array.
In few words, if we should be able to extend Array, we should create wrappers for every method that returns, natively, an Array ... who talk about performances?
Just think that every this.slice() inside our prototypes should convert again the result if we would like to threat them as an instance of our super extended Array. ... does it sound still cool?
map, filter, sort, reverse ... and many others!
A clever solution, that noone seems to like so much
Basically, Dean found a solution that's clever and simple at the same time.
This one has not been used so much by libraries developers ... but why?
What I could suppose, is that there are a lot of limits:
- it depends on iframe creation, while JavaScript could be used everywhere, not only when an element is ready to recieve an iframe inside
- an iframe could means a lot of problems, specially in https sites, where some browser (of course IE) has a sort of paranoia if the iframe does not contain an src that points to a file in the same domain ... and sometime, even an empty html file to use as sentinel for empty iframes could be boring ...
- the iframe solution, has the same problem than Array extension ... if you want more power with native methods too, you have to wrap them!
Here is an example:
// directly from Dean Edward page
onload = function(){
var iframe = document.createElement("iframe");
iframe.style.display = "none";
document.body.appendChild(iframe);
frames[frames.length - 1].document.write(
"<script>parent.Array2 = Array;<\/script>"
);
// let's play
var a = new Array2(1,2,3);
alert(a); // 1,2,3 ... Yes!
alert(a.concat([4,5,6]) instanceof Array2); // FALSE AGAIN!!!
}
bloody hell, why the native concat method of my Array2 constructor returns an Array?
No way, if You use a native prototype, its behavior will be the expected one for current enviroment ... so as new Array ported inside the iframe will generate an instance of Array2 for every method that returns a partial or full copy of the Array.
More light in the black hole, please
Even if I agree with Dean when He says
shy away from doing so for fear of breaking other scripts. So nearly all (with the noteable exception of Prototype) leave Array and other built-in objects alone.
(removing the notable exception) ... I think that sometime prototypes could save our work, avoiding huge brainstormings to find alternative solution.
Array.prototype.to
Exactly, a stupid, short, simple, damned Array.prototype that has this goal:
Transform an Array like instance into a generic Array like instance (does it sound redundant?).
Array.prototype.to = function(constructor){
if(this instanceof constructor)
return this;
var self = new constructor;
Array.prototype.push.apply(self, Array.prototype.slice.call(this, 0));
return self;
};
This prototype could solve every kind of Array like transformation problems.
Do You need a jQuery from an Array ?
[document.body, document.getElementById("test")].to(jQuery).each(
function(element){
// do whatever stuff
});
You can use this stupid prototype to transform your results as well, but basically, you can use this prototype for every kind of Array like object.
jQuery.prototype.to = Array.prototype.to;
jQuery("input").to(Array).sort(function(el1, el2){
return el1.value < el2.value ? -1 : 1;
}).to(jQuery).doStuff();
Performances are really good, and compatibility is excellent. Starting from IE 5.5 and more, adding your own little simple push prototype plus a Function.prototype.call ... and you'll have support for IE4 too, even if this will not do make sense!
I know that a prototype to a global native variable is never a good thing to assing, but:
- Array or Array like objects (arguments) are often (always?) looped using their length and not using for in
- if you want to add aprototype, why do not add one that is strictly related with the same constructor and cosntructor like objects?
ArrayObject, and my last call for a truly subclassed Array
Thanks to precedent idea, the Array.prototype.to, I totally redraw my ArrayObject, now compatible with quite every JavaScript 1.6 method without other dependencies, and finally extendible in the most simple possible way, to create your own Array like library. Do you want an example?
// first of all, your constructor
function MyArrayLikeLib(){
// be sure that basic behavior is Array like
// using ArrayObject constructor
ArrayObject.apply(this, arguments);
};
// extend your constructor with an ArrayObject instance
MyArrayLikeLib.prototype = new ArrayObject;
// finally, add one or more prototypes to your personal
// constructor ... but DO NOT FORGET the constructor!
MyArrayLikeLib.prototype.constructor = MyArrayLikeLib;
var demo = new MyArrayLikeLib(1,2,3);
alert(demo); // 1,2,3
alert(demo.concat(new MyArrayLikeLib(4,5,6))); // 1,2,3,4,5,6
alert(demo.concat(new MyArrayLikeLib(4,5,6)) instanceof ArrayObject); // TRUE
alert(demo.concat(new MyArrayLikeLib(4,5,6)) instanceof MyArrayLikeLib); // TRUE
Thanks to the to prototype, natively created in the ArrayObject itself, you will recieve for every method that returns an array like object, an instance of your constructor.
How can it be possible?
// one ArrayObject prototype method, the slice one
slice: function(){
return Array.prototype.slice.apply(this, arguments).to(this.constructor);
}
It's diabolic simple if you remember to assign the real constructor to the prototype!
How to add prototype methods to ArrayObject inherited constructor
Uhm ... this is quite a newbie question, isn't it? :lol:
However, just forget the new Object assignment, or use the object in a different way:
function A(){ArrayObject.apply(this, arguments)};
A.prototype = new ArrayObject;
A.prototype.constructor = A;
(function(prototype){
for(var key in prototype)
A.prototype[key] = prototype[key];
})({
doMyStuff:function(stuff){
this.push(stuff);
return this.sort();
},
each:function(callback){
this.foreach(callback, this);
}
});
A simple benchmark
This page contains some simple speed challenge between native Array and ArrayObject.
Of course in some case ArrayObject is a bit slower, specially with Safari beta for widnows, but those are the worst case scenario, where for compatibility and unexpected behaviors reason I had to put more code, while every, forEach, indexOf, join, lastIndexOf, pop, push, reverse, shift, and finally some, are native when your browser is cool, are compatible and fast enough, when your browser is IE.
The bad news, what You cannot do with ArrayObject
You know, arguments is exactely an ArrayObject like variable ... and what's up if you do something like this?
function length(){
for(var i = 0; i < 3; i++)
arguments[arguments.length] = i;
alert(arguments[0]); // 2
alert(arguments[1]); // undefined
};
length();
You cannot use the length as a getted/setted property as is for native Arrays, but hey, you have native push method, why should you use the length in that way?
(speed? ... if you think that will boost up your applications, use native Arrays inside those loops, and finally convert them.to(ArrayObject)) ;)
Kind Regards
P.S. just another tricky usage of Array.prototype.to
function args2arr(){
arguments.to = [].to;
return arguments.to(Array);
};
alert(args2arr(1,2,3)); // 1,2,3
Thursday, March 06, 2008
Jaxer and packed.it ... not possible yet
Unfortunately, my experience with Jaxer has been really cool but this project is too young to be used as a server side project, and this is only my opinion.
First of all, the simple File API is great, but if you look for binary safe in the search form, you'll be redirect in an empty page ... quite hilarious, isn't it?!
Anyway, I did not test the file.open("wb") mode, probably it's working, probably not ... who care about that? Me, because to pre compile packed.it projects using MyMin and then Zlib I need to write in binary mode ... no way guys!
At the same time, there's not a true bridge for Java, at least that what I was looking for, since Jaxer could be integrated with TomCat, I wonder what are they waiting for to create an easy interface to call directly Java, or whatever mature server language you want.
It will be an extreme start up improvement for your project, what's not possible yet, will be with some Java, Mono, Python, Ruby, PHP, or whatever is it, wrapper.
Is this in your roadmap? None, I can read about DRW but come on guys, the server before the client!
You can have the best Ajax based solution on client, but if the server could do things that a basic PHP / JS interaction could do since 2000 or before, I wonder why you are putting so much effort on client side, where we have a lot of choice, while what we do not have, is simply Jaxer, but on server ;)
Finally, good stuff, and good project, I wish you all the best but please, think about Ajax after a good bridge ... and of course, I eat JavaScript in the morning and I compile them during the night :lol: ... are you still looking for a JS ninja ?
Enjoy Jaxer, at least for fun, this project will become awesome the day it will integrate JS2 engine!
P.S. I created a parseIni method as well ... this is not probably perfect but hey, about 20 minutes debug included :geek:
First of all, the simple File API is great, but if you look for binary safe in the search form, you'll be redirect in an empty page ... quite hilarious, isn't it?!
Anyway, I did not test the file.open("wb") mode, probably it's working, probably not ... who care about that? Me, because to pre compile packed.it projects using MyMin and then Zlib I need to write in binary mode ... no way guys!
At the same time, there's not a true bridge for Java, at least that what I was looking for, since Jaxer could be integrated with TomCat, I wonder what are they waiting for to create an easy interface to call directly Java, or whatever mature server language you want.
It will be an extreme start up improvement for your project, what's not possible yet, will be with some Java, Mono, Python, Ruby, PHP, or whatever is it, wrapper.
Is this in your roadmap? None, I can read about DRW but come on guys, the server before the client!
You can have the best Ajax based solution on client, but if the server could do things that a basic PHP / JS interaction could do since 2000 or before, I wonder why you are putting so much effort on client side, where we have a lot of choice, while what we do not have, is simply Jaxer, but on server ;)
Finally, good stuff, and good project, I wish you all the best but please, think about Ajax after a good bridge ... and of course, I eat JavaScript in the morning and I compile them during the night :lol: ... are you still looking for a JS ninja ?
Enjoy Jaxer, at least for fun, this project will become awesome the day it will integrate JS2 engine!
P.S. I created a parseIni method as well ... this is not probably perfect but hey, about 20 minutes debug included :geek:
MyMin = {Creator:function(){}};
MyMin.Creator.prototype.parseValue = function(value){
var result;
switch(true){
case value instanceof Array:
result = [];
for(var i = 0, length = value.length; i < length; i++)
result[i] = this.parseValue(value[i]);
break;
case /^true$/i.test(value):
result = true;
break;
case /^false$/i.test(value):
result = false;
break;
case /^[0-9]+$/i.test(value):
result = parseInt(value);
break;
case /^[0-9]*\.[0-9]+$/i.test(value):
result = parseFloat(value);
break;
default:
result = value;
break;
};
return result;
};
MyMin.Creator.prototype.parseIni = function(fileContent){
var self = this,
pos = 0,
result = {},
trim = /^\s+|\s+$/g,
section,
name,
value;
while(pos < fileContent.length){
pos = fileContent.indexOf("[");
if(pos < 0)
break;
fileContent = fileContent.substr(++pos);
pos = fileContent.indexOf("]");
if(pos < 0)
break;
section = fileContent.substr(0, pos++);
if(!section)
continue;
fileContent = fileContent.substr(pos);
pos = 0;
result[section] = {};
fileContent.replace(/(\[.+\]|.+=[^;\n\r]+)/gm, function(match, sub, p){
if(pos === 0 && /^\[.+\]/.test(match))
pos = p;
else if(pos === 0){
value = match.split("=");
name = value[0].replace(trim, "");
if(/\]$/.test(name)){
name = name.substr(0, name.indexOf("["));
if(!result[section][name])
result[section][name] = [];
result[section][name].push(self.parseValue(value[1].replace(trim, "")));
}
else
result[section][name] = self.parseValue(value[1].replace(trim, ""));
}
});
fileContent = fileContent.substr(pos);
pos = 0;
};
return result;
};
Wednesday, March 05, 2008
Turbo ArrayObject
Today I am more clever than two days ago :lol: ... that's why ArrayObject has now a turbo compressor, specially with those methods that do not require an intermediate wrapper:
These methods, if susported (if not use JSLRevision ;)), works directly in core.
The result is that every Array like instance now are more fast than ever, considering that join, pop, push, reverse, indexOf, shift, and forEach are widely used in a lot of projects.
This object could be the core for libraries like jQuery, or other that emulates array behaviour ... and I solved problems with sort plus some minor fix.
It has been successfully tested in FireFox, IE, Safari, and Opera.
Seems cool? I hope so :geek:
- every
- forEach
- indexOf
- join
- lastIndexOf
- pop
- push
- reverse
- shift
- some
These methods, if susported (if not use JSLRevision ;)), works directly in core.
The result is that every Array like instance now are more fast than ever, considering that join, pop, push, reverse, indexOf, shift, and forEach are widely used in a lot of projects.
This object could be the core for libraries like jQuery, or other that emulates array behaviour ... and I solved problems with sort plus some minor fix.
It has been successfully tested in FireFox, IE, Safari, and Opera.
Seems cool? I hope so :geek:
Sunday, March 02, 2008
JavaScript ArrayObject
I think this constructor could be a good start point for a lot of projects.
We know that IE has problems while it try to extend an array, disabling length modification.
That's why I have created this wrapper that does not require weird strategies (e.g. iframe with a different enviroment) and works with a wide range of browsers.
Honestly, I did not test performances against pure arrays, but I did everything to make code as fast as possible, using good practices and creating an in-scope shortcut for the Array.prototype.
Have a look here if you are interested in this constructor, ignore them if you do not think this is a good idea :)
P.S. Please note that this constructor does not care about missed prototypes, it only does its wrapping work and nothing else. To improve Array compatibility and methods, please remember my JSL Revision. Including them in your page, You'll not have problems with every ArrayObject method, eccept for reduce and reduceRight (I will create a good implementation of those function, I promise!)
We know that IE has problems while it try to extend an array, disabling length modification.
That's why I have created this wrapper that does not require weird strategies (e.g. iframe with a different enviroment) and works with a wide range of browsers.
Honestly, I did not test performances against pure arrays, but I did everything to make code as fast as possible, using good practices and creating an in-scope shortcut for the Array.prototype.
Have a look here if you are interested in this constructor, ignore them if you do not think this is a good idea :)
P.S. Please note that this constructor does not care about missed prototypes, it only does its wrapping work and nothing else. To improve Array compatibility and methods, please remember my JSL Revision. Including them in your page, You'll not have problems with every ArrayObject method, eccept for reduce and reduceRight (I will create a good implementation of those function, I promise!)
Saturday, March 01, 2008
[COW] The fastest JavaScript rand ... isn't it ?
Hi guys, the WebReflection COW is a function that's so simple as usual: the php like rand function, to create random number, or random boolean evaluation:
What's new? Nothing, but could be useful :lol: ... and it has really good performances
Above example is for boolean assignment for random things
The function works as PHP one, creation of something casual apart.
I mean, if you use rand(), why don't you use Math.random() ?
So, basically, this function is to have a random number from 0 to N, where N is the min argument, or from min to max, where MAX is the second one.
Have a nice WE
function rand(min, max){
return max ? min + rand(max - min) : Math.random() * ++min << .5;
};
// pseudo packed version, 62 bytes
function rand(m,M){return M?m+rand(M-m):Math.random()*++m<<.5}
What's new? Nothing, but could be useful :lol: ... and it has really good performances
// boolean evaluation
var testMe = rand(1) ? true : false;
Above example is for boolean assignment for random things
The function works as PHP one, creation of something casual apart.
I mean, if you use rand(), why don't you use Math.random() ?
So, basically, this function is to have a random number from 0 to N, where N is the min argument, or from min to max, where MAX is the second one.
rand(2); // 0, 1 or 2
rand(2, 5); // 2, 3, 4 or 5
Have a nice WE
Wednesday, February 27, 2008
[ES4] ... too horrible to be an editor ...
... but probably simple enough for these milestones.
Its name is ES4me, it's for windows and works in this way:
Basically, there is a place to write something, where for some reason TABS are usable only with CTRL + TAB instead of single TAB key, a panel where errors or output will be showed, and finally, 5 buttons:
Here some example:
Press Run, and You'll read 123 on output panel.
Now press clear, and area will be without text.
Write again ...
Without the print, now press Add Before, area will be clean again ... BUT, write this:
and press Run, you'll read 123 in the output panel.
This mean that precedent code is in ram, and is present on output but not in the area.
Of course, if you Add Before print(i); , this will be executed after var i:int = 123;
This is useful to add classes or other scripts, just tested.
Now, if you press Get Before, the entire content will be added to the area, after current one, if any.
Finally, with Clear Before, everything in the Ram will be cleaned.
Simple? Last thing: every time you press Run, code is compiled in a new enviroment.
That's it, and sorry for this horrible debugger ... but time is never enough :)
Its name is ES4me, it's for windows and works in this way:
- download the file in your es4 folder, where there is the run.exe and the es4.bat file
- double click
Basically, there is a place to write something, where for some reason TABS are usable only with CTRL + TAB instead of single TAB key, a panel where errors or output will be showed, and finally, 5 buttons:
- Run, to execute the code
- Clear, to clear the code in the area
- Add Before, to add area code before execution
- Get Before, to add in area the code added before
- Clear Before, to clear content added before
Here some example:
var i:int = 123;
print(i);
Press Run, and You'll read 123 on output panel.
Now press clear, and area will be without text.
Write again ...
var i:int = 123;
Without the print, now press Add Before, area will be clean again ... BUT, write this:
print(i);
and press Run, you'll read 123 in the output panel.
This mean that precedent code is in ram, and is present on output but not in the area.
Of course, if you Add Before print(i); , this will be executed after var i:int = 123;
This is useful to add classes or other scripts, just tested.
Now, if you press Get Before, the entire content will be added to the area, after current one, if any.
Finally, with Clear Before, everything in the Ram will be cleaned.
Simple? Last thing: every time you press Run, code is compiled in a new enviroment.
That's it, and sorry for this horrible debugger ... but time is never enough :)
Subscribe to:
Posts (Atom)