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, 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

Wednesday, March 14, 2012

How to build an HTML email

This is just a quick summary on how to create an HTML email:

DON'T use:
- "div"
- "padding"
- "background-image"

DO use:
- images
- "background-color" -s
- "width" with exact px values
- "table" -s (even if normally you would use a "div")
- inline styles everywhere

This list will be expanded over time and experience or if you have some own rule-of-thumb please share it with us.

Thursday, February 23, 2012

MySQL - Order users by address

Today I encountered a little SQL problem I had to solve...so here is the task:

Order the users by their address. Basically this isn't a big thing, but I had all the address parts separatedly in the database. There is a coloumn for the city, street...parts.

Here is the solution:

SELECT *, CONCAT_WS(' ', `users`.`zipcode`, `users`.`city`, `users`.`street`, `users`.`housenumber)` AS address FROM (`users`) ORDER BY `address` asc, `name` ASC


This is not such a great achievement, but it's good for reminding myself about this cool trick.

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