Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

Monday, October 15, 2012

Handling cross-browser key events with jQuery

Another little copy-paste code fragment from the house of jQuery :) If you need to od different things on keydown event, use this basic structure, so it will be cross-browser friendly:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
jQuery(document).keydown(function (e) {

 var evt=(e)?e:(window.event)?window.event:null;
 if(evt){
  var key=(evt.charCode)?evt.charCode:((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
  
  // the key specific code comes here:
  console.log(key);

 }

}); 


I've tested it on Chrome, FF and IE9-10, and it works well.

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");
 });
 
});



Wednesday, April 11, 2012

Copy jQuery click event from one element to another



Today I had to solve a task wich seemed to be quite easy... I had to copy a "click" event from an element. To copy an "onclick" attribute...it's a piece of cake. BUT, how do you copy a jQuery "click" event?

I found an interesting conversation about this problem here, but I couldn't find a solution for my problem:
http://forum.jquery.com/topic/how-do-i-copy-the-click-event-from-one-element-to-another.

I'm not 100% sure you understand my problem, so here are some example codes:


This is a common "a" tag with an onclick attribute:

<a href="javascript:void(null)" onclick="alert('onclick event triggered')" id="test_element">Trigger OnClick</a>

This click event can be copied with this code:

jQuery("#test_element").attr("onclick")




BUT, what's the case with this method?

<a href="javascript:void(null)" id="test_element">Trigger OnClick</a>

And with this Javascript:

jQuery("#test_element").click(function() {
    alert("jQuery click event triggered");
})




How do I copy this click event?

Well, I dove in jQuery-s source code because I knew it can be done. jQuery has a .clone() function which has an attribute to decide, whether to copy the events too or not. This is what I found:

function cloneCopyEvent( src, dest ) {

 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
  return;
 }

 var type, i, l,
  oldData = jQuery._data( src ),
  curData = jQuery._data( dest, oldData ),
  events = oldData.events;

 if ( events ) {
  delete curData.handle;
  curData.events = {};

  for ( type in events ) {
   for ( i = 0, l = events[ type ].length; i < l; i++ ) {
    jQuery.event.add( dest, type, events[ type ][ i ] );
   }
  }
 }

 // make the cloned public data object a copy from the original
 if ( curData.data ) {
  curData.data = jQuery.extend( {}, curData.data );
 }
}


The most interesting part is this:

oldData = jQuery._data( src ),
curData = jQuery._data( dest, oldData ),
events = oldData.events;


The events are saved inside (jQuery._data( src )).events. To stay by my example, the solution will look like this:

(jQuery._data( jQuery("#test_element")[0] )).events.click[0].handler


This way I can make a copy of the function bound to the element. And of course, if there are more bindings to one element, they can be reached with "...click[1].handler", "...click[2].handler", etc.


I hope this little trick helped you too.





Friday, March 23, 2012

jQuery simple banner rotator plugin

Today I had a task, to create a simple image (banner) rotator in Javascript...so I thought: If I have to do it, then do it right and created a simple jQuery plugin. The code is really easy to understand... here is the essence of it:


setInterval(function () {
 var items = jQuery( jQuery(options.items, this).get().reverse());

 items.each(function () {
  // if visible, than hide
  if (jQuery(this).is(":visible")) {
   jQuery(this).fadeOut();

   return false;
  } 
 });

 // if nothing more to hide, show all
 if( jQuery(":visible", items).length <= 1 ) items.fadeIn();

}, options.timeout);


Basically there is an interval and it's hiding all the items backwards. When they are all hidden, then show them. Because the items are positionated "absolute" they are overlapping eachother. So when I hide one, another appears.


That's it. Simple and small! :)



Here is the full code:
jQuery.bannerRotate.js

Cheers,
Phil

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

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.