Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Monday, October 8, 2012

Different font size for each font family


No matter how surprising it is, there was no solution to change the font size based on the font family. Until now. :)

What is the problem?

I used two different fonts on a webpage. One is a simple Arial, the other is a custom font. The custom font requires a much bigger font size, to get the same result as the Arial.

What needed to be done?

I needed a solution, to change font size CSS properties on some of the elements, if the custom font is loaded. For example IE could not load it, so there should be Arial everywhere, but with a correct font size.

How is it done?

With Javascript of course. The basic idea is, to create a hidden element with some characters in it. This text has a different with on each font family. So I measured it with Arial, then I have set the font family to the custom value, and measured it again. It the element's width is different than the previous one, then the font is loaded. If the width of the element doesn't changes in 10seconds, the checking interval is cleared, so it doesn't uses the resources anymore. In the callback funcion, I just removed the ".no-custom-font" class from the body, so everything should look good now. Note, that I had to create some other CSS rules (and with the additional class, these rules have a higher specificity than the default ones) to set the right font size values.

Okay, this worked fine in the project, so lets look at the code:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function onWebFontLoaded(font, callback) {
 
 // create a test element for each font
 jQuery("body").append("<div id=\'font_test\' style=\'position: absolute;left:-1000000px; top: -1000000px;font-size:300px;font-family:Arial;font-style:normal;font-weight:normal;letter-spacing:0px;\'>giItT1WQy@!-/#</div>");
 var width = jQuery("#font_test").width();
   
 jQuery("#font_test").css("font-family", font+", Arial");

 var timeWaited = 0;
 var intervalTime = 200; 
 var maxWaitingTime = 10000; // 10 sec
 var interval;
 function checkFont() {
  
  timeWaited += intervalTime;
  
  if(jQuery("#font_test").length > 0 && jQuery("#font_test").width() != width) {
   callback();
   jQuery("#font_test").remove();
   return true;
  }
  else if( timeWaited > maxWaitingTime) {
   clearInterval(interval);
   if( typeof console != "undefined") console.log("font ("+font+") not loaded.");
  }
  return false;
 }

 if(!checkFont()) {
  interval = setInterval(checkFont, intervalTime);
 }
   
};

jQuery(document).ready(function() {
 
 onWebFontLoaded('AGENCYR', function() {
  
  // remove the no-font-... class from the body tag
  jQuery(".no-font-AGENCYR").removeClass("no-font-AGENCYR");
 });
 
});



Tuesday, April 17, 2012

Javascript: Count a string occurence in text


While working on my favorite project I had to count the colons in a string. I was wondering which could be the best solution. I had two methods in my mind to solve that.

The first is the "split" method:
var text = 'text text text: text2: text3::';
var colon_length = text.split(":").length - 1;


The other one is the "RegExp" method:
var text = 'text text text: text2: text3::';
var colon_length = text.match(/:/g).length;


After googling for a while I found a test which one is better:
http://jsperf.com/count-the-number-of-occurances-in-string


Well, that graph is self explanatory I guess :) (Thanks jsPerf.com)



In the mean time I stumbled into this solution which I think is quite interesting:
http://www.codecodex.com/wiki/index.php?title=Count_the_number_of_occurrences_of_a_specific_character_in_a_string#JavaScript

This is the code:
String.prototype.count=function(s1) { 
 return (this.length - this.replace(new RegExp(s1,"g"), '').length) / s1.length;
}


And this is the usage:
// use like this 
test = "this, as you see, is a sentence, containing many ','s";
numberOfCommas = test.count(','); //4
// or 
numberOfSblank = test.count('s '); //2


But because in my project I have to use a minimal amount of global footstep I sticked to the "RegExp" method.

Wednesday, December 14, 2011

Javascript: Is date in range?

Today I encountered a little problem wich I had to solve with dates. I had to check, if today has a special event. The range is stored in a simple date format: YYYY.MM.DD-YYYY.MM.DD

Here is the solution:

var nowDate = new Date(2011, 12, 14).getTime();

var startDate = new Date(2011, 12, 13).getTime();
var endDate = new Date(2012, 1, 5).getTime();

if (startDate <= nowDate && nowDate <= endDate) {
 alert('It\'s in range!');
}


The "getTime()" method will create a timestamp from the created date. It's like a date in a number format wich can be easily compared to eachother.

Wednesday, October 26, 2011

Complete website on client side?

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 :)

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:

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.

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.