Javascript became very popular these days. There are countless frameworks and plugins developed to make our web developer life easier. But... I have a question.
What are the limits of Javascript? Can we make a complete website to work only on client side?
I'm developing a very interesting project recently. I have to solve everything (even content search) in the browser. The website has no contact to the internet at all...Yes. A website without internet connection or server contact. It will be an information box with touch screen on my former college. It will work as a digital doorman and it's quite nifty (and heavy like a mountain). Our designer did his job very well. It has now a very nice touch compatible interface. (Print screens and actual "in-use" images soon)
The computer runs on Ubuntu and unfortunately nobody knows the root password :) That's why I'm sticked with Firefox. The base hardware is... very environment (therefore not too user-experience) friendly, but I will do my best. Later, when I will have more time I will reinstall the system and use Chrome instead. The Javascript animations are much faster there. And I did a little test with flash. Surprisingly (at least for me) Opera handles Flash animation much more smoothly than any other browser. I designed a little active backgound for the whole system, and it looked awesome in Opera (I tested it with an Ubuntu live CD).
I have came up with a solution, I just want to test it. If it works, I will write a full post about it. If it won't than I will write it down, why it didn't worked.
But now I have a very tight deadline so I stop writing posts and go back to work :)
Wednesday, October 26, 2011
Complete website on client side?
Labels:
client side,
javascript,
touch screen
Sunday, October 23, 2011
JavaScript: Objects and the this keyword
Right now, I'm developing a complex jQuery plugin with a bunch of objects. Most of the these are connected together somehow in each others' definition. In one of these objects, the this keyword referenced to another object and I was not able to find a variable related to my object. The reason was I had to call one of its function in another context and with another this object. Here is the example:
So, when when I called the update function in another context with another this object, the this keyword referenced to the caller object, not to the object where it was. The result of this is that the state variable is undefined, because the caller object didn't have a state variable. I knew that the this keyword is the problem and I also knew that I need to reference to the object in its own functions. So the solution is to create a private variable and store a reference to the object in it.
With this solution, if you create an object with the new keyword, the constructor is called and the _self variable will store a reference to itself. This won't mess up the this reference in other contexts.
var obj = function() { /* Private variables */ var v1 = 0; var v2 = 0; /* Public variables */ this.state = false; /* Public functions */ this.update = function() { if(this.state) do_stuff(); console.log(this.state); // undefined!!! } };
So, when when I called the update function in another context with another this object, the this keyword referenced to the caller object, not to the object where it was. The result of this is that the state variable is undefined, because the caller object didn't have a state variable. I knew that the this keyword is the problem and I also knew that I need to reference to the object in its own functions. So the solution is to create a private variable and store a reference to the object in it.
var obj = function() { /* Reference to self */ var _self = this; /* Private variables */ var v1 = 0; var v2 = 0; /* Public variables */ _self.state = false; /* Public functions */ _self.update = function() { if(_self.state) do_stuff(); console.log(_self.state); // false this.somethingElse = true; } };
With this solution, if you create an object with the new keyword, the constructor is called and the _self variable will store a reference to itself. This won't mess up the this reference in other contexts.
Thursday, October 20, 2011
JavaScript: Drawing and appending an Image object
Let's have some fun with images tonight!
The <img/> tag is part of HTML, as you've already known from your previous studies in web technologies. :) You can create one programmatically with the Image object in JavaScript. See below:
Try to log it to the console. Right know, it's empty. To load an image, use the src tag:
The image is loaded, but you can't see it yet, because it isn't appended to the DOM. Let's use jQuery to do what is needed to do!
The image is visible right know. This JavaScript object has another property called onload. It fires when the image is loaded. Append these few lines after your code and refresh your page:
In Internet Explorer, the onload function won't run, unless you place it before the definition of src attribute:
Go and have some fun with the onerror attribute! It runs when an error occurs while loading an image.
Then, get the canvas and a context and use drawImage function.
The first parameter of the drawing function is the image object itself. The second and third parameters are for placing the image along the x and y coordinates. Note that the (0, 0) coordinate is the top left corner. Also note that canvas element is not supported yet in Internet Explorer.
That's all for today of the JavaScript Image object and its usage. I will tell more about the drawImage function in another post where I will talk about sprites, animation and a bit more JavaScript tricks. I hope you learned a little new today.
The <img/> tag is part of HTML, as you've already known from your previous studies in web technologies. :) You can create one programmatically with the Image object in JavaScript. See below:
var img = new Image();
Try to log it to the console. Right know, it's empty. To load an image, use the src tag:
var img = new Image(); // of course, don't forget to replace this url ;) img.src = 'http://www.testsite.com/images/myimage.jpg';
The image is loaded, but you can't see it yet, because it isn't appended to the DOM. Let's use jQuery to do what is needed to do!
jQuery('#myDiv').html(img);
The image is visible right know. This JavaScript object has another property called onload. It fires when the image is loaded. Append these few lines after your code and refresh your page:
img.onload = function() { alert('image loaded'); }
In Internet Explorer, the onload function won't run, unless you place it before the definition of src attribute:
var img = new Image(); img.onload = function() { alert('image loaded'); } img.src = 'http://www.mysite.com/images/an_image.jpg';
Go and have some fun with the onerror attribute! It runs when an error occurs while loading an image.
var img = new Image(); img.onerror = function() { alert('failed to load image :( '); } img.src = 'http://www.fakelink.com/images/non_existing_image.png';
Canvas element and Javascript drawImage function
Another way to use the image object is to draw it with the help of the canvas element. First, have one in your example html page:<canvas id="myCanvas" width="400" height="300"></canvas>
Then, get the canvas and a context and use drawImage function.
var canvas = $("#myCanvas"); /* For browser compatibility issues, put error handling code here. I won't.. */ var ctx = canvas[0].getContext('2d'); var img = new Image(); img.src = 'http://static.yoursite.com/images/something.png'; ctx.drawImage(img, 0, 0);
The first parameter of the drawing function is the image object itself. The second and third parameters are for placing the image along the x and y coordinates. Note that the (0, 0) coordinate is the top left corner. Also note that canvas element is not supported yet in Internet Explorer.
That's all for today of the JavaScript Image object and its usage. I will tell more about the drawImage function in another post where I will talk about sprites, animation and a bit more JavaScript tricks. I hope you learned a little new today.
Tuesday, October 18, 2011
JavaScript: Types and values
Working on other's codes is like walking in a huge cellar with a bunch of old boxes: you always find some interesting things. I write about types today.
Let's work with the following variables:
How can you determine the type of each variable? Use the typeof operand. It returns a string representation of the operand's type. Let's see the types of the variables above:
Look at the result of v0 and v1. Why do they have the same undefined type? v0 is not declared, it's obvious why it is undefined. But v1? Because it is not defined (just like the type tells to us)! We stated that there is a variable called v1 but we didn't give it a value.
Did you notice that v2 with null assigned to it is an object type? Yes, you see it well. As I know, the reason for this is that the null type is a special object in JavaScript.
The alert function call won't run because the comparison in the if statement is wrong. As said before, typeof returns a string, but right now it is matched against an undefined value. It won't even work with the 'equal to' operator. Let's correct it:
So now, the return value of typeof is compared to a string.
With the 'equals to' operator, JavaScript does type casting and evaluates the v1 variable with null value. But in the second case, with the 'exactly equals to' operator, the undefined value is kept because the operator checks the value and the type too.
I hope you also found it interesting. :)
Let's work with the following variables:
var point = function() { this.x = 4; this.y = 6; } // var v0; Note: I commented it out with purpose to make it undefined. var v1; var v2 = null; var v3 = false; var v4 = 'some text'; var v5 = 68; var v6 = {}; var v7 = new point(); var v8 = new Array(); var v9 = function() {};
How can you determine the type of each variable? Use the typeof operand. It returns a string representation of the operand's type. Let's see the types of the variables above:
typeof v0; // undefined typeof v1; // undefined typeof v2; // object typeof v3; // boolean typeof v4; // string typeof v5; // number typeof v6; // object typeof v7; // object typeof v8; // object typeof v9; // function
Look at the result of v0 and v1. Why do they have the same undefined type? v0 is not declared, it's obvious why it is undefined. But v1? Because it is not defined (just like the type tells to us)! We stated that there is a variable called v1 but we didn't give it a value.
Did you notice that v2 with null assigned to it is an object type? Yes, you see it well. As I know, the reason for this is that the null type is a special object in JavaScript.
Common mistake with types
Typeof
I see the following comparison many times in codes I meet:if(typeof v0 === undefined) { alert('not executed! hah!'); }
The alert function call won't run because the comparison in the if statement is wrong. As said before, typeof returns a string, but right now it is matched against an undefined value. It won't even work with the 'equal to' operator. Let's correct it:
if(typeof v0 === 'undefined') { alert('executed! hah!'); }
So now, the return value of typeof is compared to a string.
Null values
Another confusion rises when comparing undefined but declared variables against null value.var v1; if(v1 == null) { // it will run alert('yep'); } if(v1 === null) { // it won't run alert('nope'); }
With the 'equals to' operator, JavaScript does type casting and evaluates the v1 variable with null value. But in the second case, with the 'exactly equals to' operator, the undefined value is kept because the operator checks the value and the type too.
Infinity and NaN
Take into account that type of a variable with Infinity or NaN value is number:var v10 = 1000 / 0; // Infinity var v11 = 1000 / 'book'; // NaN typeof v10; // number typeof v11; // number
I hope you also found it interesting. :)
Sunday, October 16, 2011
Playing with Numbers in Javascript
Handling numbers is a very basic task for (web)developers, but how exactly is this working in Javascript?
Numbers are "double-precision 64-bit format IEEE 754 values". Let's see some examples how it can handle things:
My conclusion are:
I have read the basic number handling tests on: developer.mozilla.org and I have made up some others on my own.
Numbers are "double-precision 64-bit format IEEE 754 values". Let's see some examples how it can handle things:
console.log( 0.1 + 0.2 ); // 0.30000000000000004 // but: console.log( (0.1*10 + 0.2*10) / 10 ); // 0.3 console.log( parseInt("123", 10) ); // 123 console.log( parseInt("010", 10) ); // 10 // The parseInt() and parseFloat() functions parse a string until // they reach a character that isn't valid for the specified number // format, then return the number parsed up to that point. console.log( parseInt("test: 123", 10) ); // NaN console.log( parseInt("test: 010", 10) ); // NaN console.log( parseInt(1.23, 10) ); // 1 console.log( parseInt(1.99, 10) ); // 1 console.log( parseInt(-5.1) ); // -5 console.log( Math.floor(-5.1) ); // -6 (!!) console.log( parseFloat("1.67") ); // 1.67 (Number) console.log( parseInt("456test: 010", 10) ); // 456 // converting without parseInt() or parseFloat() console.log( "456 test: 010" * 1 ); // NaN console.log( 1 * "456 test: 010" ); // NaN console.log( 1 * " 456 " ); // 456 (space characters are allowed) console.log( 1 * " .456 " ); // 0.456 console.log( 1 * " . 456 " ); // NaN console.log( 1 + "2" + 3 + 4 ); // 1234 console.log( 1 - "2" + 3 + 4 ); // 6 (-1 + 3 + 4) console.log( 1 * "2" + 3 + 4 ); // 9 (2 + 3 + 4) console.log( 1 / "2" + 3 + 4 ); // 7.5 (0.5 + 3 + 4) console.log( 5 % "3" ); // 2 console.log( 5 % " 3 " ); // 2 console.log( 5 % " 3a " ); // NaN console.log( parseInt("010") ); // 8 (!!) console.log( parseFloat("010") ); // 10 (!!) console.log( parseFloat("010.123") ); // 10.123 console.log( parseInt("11",2) ); // 3 (binary to integer) console.log( parseFloat("11") ); // 11 // converting with unary operator console.log( +"11" ); // 11 console.log( typeof +"11" ); // number console.log( +"11a" ); // NaN console.log( -"11" ); // -11 console.log( typeof -"11" ); // number // other number types console.log( parseInt("hello", 10) ); // NaN console.log( typeof parseInt("hello", 10) ); // Number (!!) console.log( parseInt("hello", 10) * 1 + 5 ); // NaN (NaN is toxic..) console.log( isNaN(parseInt("hello", 10)) ); // true console.log( isNaN(10) ); // false console.log(1/0); // Infinity console.log(-1/0); // -Infinity
My conclusion are:
- If I'm working with floats I should round them to a limited precision.
- The safest way to convert strings to numbers is to use parseInt() or parseFloat().
- The parseInt() function has a second argument wich defines the base of the number system that the string has. I should always set this value, just to be clear and avoid some untrackable bugs..
- Before I use parseInt() it's a good idea to clean the string from any letters (this is quite task dependent). I should care about this, because if a string made up of numbers it's fine. But it could have some toxic character value in it and that could kill the whole process. So be careful.
- If I call parseInt on a float number, it will return always the integer part of the number. So it's not the same as Math.floor()
- parseInt() on a string like (123a456) will only return the first few characters parsed as numbers.
- Converting numbers with only " * 1" is not safe. Only if I can be absolutely sure that the string will only contain number characters or space.
- parseFloat() uses always 10 as the base number system
- I can convert strings into numbers with an unary operator (Wow..)
- NaN is toxic. Very toxic.. avoid it at all cost (unless this is what I want)
- There is an Infinity type number in Javascript but I don't quite know what is it good for. (Maybe just to indicate that the number is too big..do something with it because javascript can't handle it)
I have read the basic number handling tests on: developer.mozilla.org and I have made up some others on my own.
Labels:
converting,
javascript,
number,
types
Friday, October 14, 2011
jQuery :contains with the exact same value
The task to do:
During my work I had to create a page scrolling effect with a dropdown menu and a (verticaly) very long content. So when someone clicks on a menu item the page has to scroll to the exact position where the content begins.
The idea of the solution:
As the menu-items' text and the title of the content parts are exactly the same, the idea is to find the title tag according to it's content. Then get the Y coordinate of it and scroll the body to this position.
The solution in jQuery:
My first (key) idea was to use jQuery's built-in ":contains" method:
But in this case this won't work perfectly, because there were menu items like "Product" and "Product 2.0". So I needed a ":contains" solution but with the exact values. This is what I came up with:
Note: I used Ariel Flesler's ScrollTo jQuery plugin. (Thanks Ariel by the way..)
During my work I had to create a page scrolling effect with a dropdown menu and a (verticaly) very long content. So when someone clicks on a menu item the page has to scroll to the exact position where the content begins.
The idea of the solution:
As the menu-items' text and the title of the content parts are exactly the same, the idea is to find the title tag according to it's content. Then get the Y coordinate of it and scroll the body to this position.
The solution in jQuery:
My first (key) idea was to use jQuery's built-in ":contains" method:
jQuery("h2:contains('Some Value')")
But in this case this won't work perfectly, because there were menu items like "Product" and "Product 2.0". So I needed a ":contains" solution but with the exact values. This is what I came up with:
jQuery("#menu a") // disable links. We need only Javascript behavior .attr("href", "javascript:void(null)") // what shall happen if the link is clicked .click(function () { // get the text of the menu item var text = jQuery(this).text(); // get the DOM object of the target title (The h2 element wich contains the exact same text of the menu item) var target = jQuery('h2').filter(function() { return jQuery(this).text() === text; }); // get the position of the target element var pos = target.offset(); // if the position is found... if (typeof pos.top != 'undefined') { // scroll the page there jQuery.scrollTo((pos.top-10) + "px", 700); } });
Note: I used Ariel Flesler's ScrollTo jQuery plugin. (Thanks Ariel by the way..)
Labels:
contains,
exact value,
jQuery
Thursday, October 13, 2011
XHTML Strict and target _blank
This topic is quite a challange because on one side I want my websites "strict" valid. On the other hand, sometimes it's important (at least clients say so) to open links in a new window, so I did a little research (and there are a lot of informations out there to this problem)
What are the solutions for being valid and in the same time opening links in a new window?
1. I tried it with CSS: (I know, I know... CSS is for styling only, not for behavior.. I'm searching solutions right now)
Theoretically it can be done with CSS3. According to this page the code should look like this:
a {
target-name: new;
target-new: tab;
}
But none of the browsers responded to it so this solution is precluded.
2. Javascript:
Here we have quite interesting solutions.
Manually open a new window with "window.open(URL)":
Inline mode:
<a href="http://thinkrement.blogger.com" onclick="window.open(this.href); return false;">Read Thinkrement!</a>
This works, however it's not so elegant and it's better to keep the HTML and Javascript seperate.
So, let's improve it a bit:
HTML:
<a href="http://thinkrement.blogger.com" rel="popup">Read Thinkrement!</a>
Javascript:
window.onload = function() { var links = document.getElementsByTagName('a'); for (var i=0;i < links.length;i++) { if (links[i].rel == 'popup') { links[i].onclick = function() { window.open(this.href); return false; }; } } };
or with jQuery:
$('a[rel="popup"]').click(function() { window.open(jQuery(this).attr("href")); return false; });
The constrained method:
With Javascript it's similar to the previous "window.open" method with the difference, that instead of "window.open" we use:
window.onload = function() { var links = document.getElementsByTagName('a'); for (var i=0;i < links.length;i++) { if (links[i].rel == 'popup') { links[i].target="_blank"; } } };
This is quite simple, however this solution is not supported by IE and Chrome.
With jQuery it a bit easier (only 1 line):
$('a[rel="popup"]').attr("target", "_blank");
3. HTML:
- Use a Transitional Doctype
- Have some "target" errors on your site
- or put it out of your mind that you want to use the target attribute. It is said that for usability reasons it's better to let users decide whether they want a new window (tab) or not.
Labels:
_blank,
javascript,
jQuery,
target,
XHTML
Subscribe to:
Posts (Atom)