Crossbrowser Javascript Listener - javascript

I have the next code working correctly:
var links = document.getElementsByClassName('register');
for(var index = 0; index < links.length; ++index)
{
links[index].addEventListener('click', function(){
var newMixpanelEvent = 'mixpanel.track("Click On Searched List", {"user is logged": "no"})';
trackEvent(newMixpanelEvent);
});
}
This is just listening for a click event, and then executing a function to create an event to Mixpanel.
Now I need to check the addEventListener function and attachEvent to make it work almost all browsers, so I do:
var links = document.getElementsByClassName('register');
for(var index = 0; index < links.length; ++index)
{
if( links[index].addEventListener ) {
links[index].addEventListener('click', function(){
var newMixpanelEvent = 'mixpanel.track("Click On Searched List", {"user is logged": "no"})';
trackEvent(newMixpanelEvent);
});
} else if( links[index].attachEvent ) {
links[index].attachEvent('onclick', function(){
var newMixpanelEvent = 'mixpanel.track("Click On Searched List", {"user is logged": "no"})';
trackEvent(newMixpanelEvent);
});
}
}
But this is not firing the events. Seems like if( links[index].addEventListener ) is not passing. Any idea of why?

Well, the above code works right. The problem was that I had not cleared cache. This is what I previously had and didn't work:
if( window.addEventListener ) {
...
But
if( links[index].addEventListener ) {
...
is working right.

As a final fallback you can add the event through onclick attribute. You should define sperate function with the logic for checking available ways for attaching event handlers.
function addCrossBrowserEvent(element, eventName, callback){
if(element.addEventListener){
element.addEventListener(eventName, callback);
}
else if(element.attachEvent){
element.attachEvent('on' + eventName, callback);
}
else{
element['on' + eventName] = callback;
}
}
Usage:
addCrossBrowserEvent(myElement, 'click', function() {
alert('clicked');
});
Note: Also you can try to design it as extension of HTMLElement prototype.
HTMLElement.prototype.addCrossBrowserEvent = function(eventName, callback) {
if(this.addEventListener){
this.addEventListener(eventName, callback);
}
else if(this.attachEvent){
this.attachEvent('on' + eventName, callback);
}
else{
this['on' + eventName] = callback;
}
}
// Usage
document.getElementById('elementId').addCrossBrowserEvent('click', function() {
// ...
});

Related

Function when multiple elements have been clicked

I want a to have an animation only when seven elements have been click. Here is the code but it doesn't work:
var animp5 = function () {
var i = 0;
$("#ans1_p5").on('click', function () {
i = i + 1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
});
$("#ans2_p5").on('click', function () {
i = i + 1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
});
$("#ans3_p5").on('click', function () {
i = i + 1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
});
$("#ans5_p5").on('click', function () {
i = i + 1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
});
$("#ans7_p5").on('click', function () {
i = i + 1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
});
$("#ans9_p5").on('click', function () {
i = i + 1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
});
$("#ans10_p5").on('click', function () {
i = i + 1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
});
if (i === 7) {
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
};
I have tried other solutions (like .data('clicked') or .attr('clicked') but they didn't work either.
You can use observer design pattern in javascript to achieve this the right way.
First create handlers, subscribe and execute functions and then you can subscribe waht ever you like in your case its comparison i===7. execute fade.execute after every click to validate.
Also it's advisable to use class selectors than id selectors in your case. As id selectors will be unmanageable and you will end up with a lot of duplicate code.
But for the sake of your question observer is your way to go.
jsFiddle
function Fade() { // Create Fade handlers
this.handlers = []; // observers
}
Fade.prototype = { // define subscribe and execute
subscribe: function(fn) {
this.handlers.push(fn);
},
execute: function(o, thisObj) {
var scope = thisObj || window;
this.handlers.forEach(function(item) {
item.call(scope, o);
});
}
};
var fade = new Fade();
fade.subscribe(function(){ // pass function you want to subscribe
console.log(i);
if(i===7){
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
});
var animp5 = (function(){
var i = 0;
$("#ans1_p5").on('click',function(){
i=i+1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
fade.execute(); // execute to check if condition met
});
$("#ans2_p5").on('click',function(){
i=i+1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
fade.execute();
});
$("#ans3_p5").on('click', function(){
i=i+1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
fade.execute();
});
$("#ans5_p5").on('click', function(){
i=i+1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
fade.execute();
});
$("#ans7_p5").on('click', function(){
i=i+1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
fade.execute();
});
$("#ans9_p5").on('click', function(){
i=i+1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
fade.execute();
});
$("#ans10_p5").on('click', function(){
i=i+1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
fade.execute();
});
})();
Thanks for your answers.
As I have not much experience working with jquery I was unable to code your solution but I found a new one that works perfect. I put the "if" inside every click function so each time I click, code checks if the condition has been fulfilled and once this happens run the appropriate code.
Thanks again

jQuery can't find element when it's parsed from JSON [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 7 years ago.
At first I made a simple array just inside the .js file and wrote the function to make list items from it.
Then clicking on freshly created li elements should do something.
//This code works
dic[0] = "decir";
dic[1] = "querer";
dic[2] = "poder";
$(document).ready(
function verbsarray() {
for (var i = 0; i < dic.length; i++) {
var verbo = dic[i];
verbos += "<li class='h_li'>" + verbo + "</li>\n";
};
$('ul.h_list').html(verbos);
});
$(".h_li").click(function() {
alert("it works!");
//Dollar finds .h_li here
}
Since that was a prototype, then I developed that function to take items not from the static array, but from loaded JSON.
Function parses the needed items and again makes list items from them.
But the other function (that looks for clicked <li class="h_li">) now doesn't work...
//this doesnt work :-(
function verbos_from_json () {
$.getJSON('verbos.json', function verbsarray(vjson) {
for (var i = 0; i < vjson.data.length; i++) {
verbo = vjson.data[i].verb;
verbos += "<li class='h_li'>" + verbo + "</li>\n";
};
$('ul.h_list').html(verbos);
});
};
$(".h_li").click(function() {
alert("it works?.. no");
}
For dynamically rendered elements, you need to use delegate binding with jquery. Instead of click():
$(".h_li").click(function() {
alert("it works?.. no");
};
use on():
$(".h_list").on('click', '.h_li', function() {
alert("it works?.. no");
};
You have to integrate your listening function in your verbos_from_json
function verbos_from_json () {
$.getJSON('verbos.json', function verbsarray(vjson) {
for (var i = 0; i < vjson.data.length; i++) {
verbo = vjson.data[i].verb;
verbos += "<li class='h_li'>" + verbo + "</li>\n";
};
$('ul.h_list').html(verbos);
//****************************************************************
//}); // bad place : it was a typo ( edited after discussion )
//****************************************************************
// THIS PART HAS MOVED IN
$(".h_li").click(function() {
// better to off before (if is safe for you) to prevent multiple event
// $(".h_li").off('click').click(function() {
alert("it works?.. no");
}
}); // it was a typo ( edited after discussion )
};
Since the elements are added after ajax call. The click event is not attached to new elements that are added asynchronously . I will do this:
function verbos_from_json () {
$.getJSON('verbos.json', function verbsarray(vjson) {
for (var i = 0; i < vjson.data.length; i++) {
verbo = vjson.data[i].verb;
verbos += "<li class='h_li'>" + verbo + "</li>\n";
};
$('ul.h_list').html(verbos);
// bind here
$( ".h_li" ).bind( "click", function() {
alert( "It works" );
});
});
};
{OR}
As mentioned by War10ck delegation can be done instead of binding in the json.
Change:
$(".h_li").click(function() {
alert("it works?.. no");
};
To:
$( ".h_list" ).delegate( ".h_li", "click", function() {
alert("It works?.....no")
})

mouseover set by jquery not working in ie7

i need to set the call the function active() on onmouseover area on image, i tried to set onmouseover using jquery , this work in all browser but not in IE7 so please anybody suggest me hint to work this code on IE7
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).attr('onmouseover', "active('area"+i+"','"+Id+"',"+i+")");
i++
});
});
the active function code as follow:-
function active(value,value2,value3)
{
$("#"+value).css({'display':'block'});
$("#area"+value3+"_link").css({'text-decoration':'underline'});
$('#'+value2).mouseout(function(){$('#'+value).css({'display':'none'});$("#area"+value3+"_link").css({'color':'#707070','text-decoration':'none'});});
}
and no js error shown.
Why are you using $(this).attr('onmouseover'. Only reason I am seeing is i
You can simply use .index()
$("#map area").on('mouseover', function(){
var i = $("#map area").index(this) + 1;
active('area'+ i, $(this).attr('id'), i);
})
Note: .index() starts with 0
Try changing to anonymous function definition like this
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).attr('onmouseover', function() {...your code here...});
i++;
// and you missed the ; after i++
});
});
Try:)
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).mouseover(function(){
active('area"+i+"','"+Id+"',"+i+")");
i++;
});
});
Attach event using following func e.g. addEvent('mouseover', $(this).get(0), <callback>)
function addEvent(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
elem.attachEvent("on"+evnt, func);
}
else { // No much to do
elem[evnt] = func;
}
}

multiple window.onload function

I have Javascript functions called start() that have multiple functions to load using window.onload function. However, I have below function that works independently fine. However, if I write it inside the window.onload, then it doesn't work.
//START()
window.onload = start;
function start()
{
loadValues();
showState4();
}
Code that does work independently fine.
window.onload=function(){
document.getElementById("src2TargetAll").onclick = function() {
sureTransfer(document.getElementById("net"), document.getElementById("target"), true);
};
};
I tried re-writing the code as follows in window.onload but it doesn't work. How to re-write the below code in single window.onload function.
window.onload = start;
function start()
{
loadValues(); //loadValues() and showState4() works fine without sendValues().
showState4();
sendValuess(); // tested this sendValues without above two functions and that also works fine. but three functions in window.onload creates a problem
}
function sendValuess(){
document.getElementById("src2TargetAll").onclick = function() {
sureTransfer(document.getElementById("net"), document.getElementById("target"), true);
};
};
Error that I get after adding sendValues() to window.onload is as follows:
STOP RUNNING THIS SCRIPT?
A SCRIPT ON THIS PAGE IS CAUSING YOUR WEB BROWSER TO RUN SLOWLY. IF IT CONTINUES TO RUN, YOUR COMPUTER MIGHT BECOME UNRESPONSIVE.
below is the code for loadValues and other functions as requested by a person who trying to help me:
function showState4(){
var me = document.getElementById('stk1');
var values = ''; //populate selected options
for (var i=0; i<me.length; i++)
if (me.options[i].selected)
values += me.options[i].value + ',';
values = values.substring(0, values.length-1);
var selected=[values];
var temp= new Array();
temp = values.split(",");
var del = document.getElementById('StakeHolder');
for(var i=0; i<del.length; i++)
{
for(var j=0;j<temp.length;j++)
{
if(temp[j] == del.options[i].value)
{
del.options[i].selected = true;
}
}
}
}
function loadValues()
{
var RD_REQ_RT_ID = "<%=RD_REQ_RT_ID %>";
if(RD_REQ_RT_ID=="null")
{
document.getElementById('requestType').value="";
}
else{
document.getElementById('requestType').value=RD_REQ_RT_ID;
}
)
_
function sureTransfer(from, to, all) {
if ( from.getElementsByTagName && to.appendChild ) {
while ( getCount(from, !all) > 0 ) {
transfer(from, to, all);
}
}
}
function getCount(target, isSelected) {
var options = target.getElementsByTagName("option");
if ( !isSelected ) {
return options.length;
}
var count = 0;
for ( i = 0; i < options.length; i++ ) {
if ( isSelected && options[i].selected ) {
count++;
}
}
return count;
}
function transfer(from, to, all) {
if ( from.getElementsByTagName && to.appendChild ) {
var options = from.getElementsByTagName("option");
for ( i = 0; i < options.length; i++ ) {
if ( all ) {
to.appendChild(options[i]);
} else {
if ( options[i].selected ) {
to.appendChild(options[i]);
}
}
}
}
}
How to add sendValuess() to window.onload without any issue?
window.addEventListener will not work in IE so use window.attachEvent
You can do something like this
function fun1(){
// do something
}
function fun2(){
// do something
}
var addFunctionOnWindowLoad = function(callback){
if(window.addEventListener){
window.addEventListener('load',callback,false);
}else{
window.attachEvent('onload',callback);
}
}
addFunctionOnWindowLoad(fun1);
addFunctionOnWindowLoad(fun2);
The error:
STOP RUNNING THIS SCRIPT?
A SCRIPT ON THIS PAGE IS CAUSING YOUR WEB BROWSER TO RUN SLOWLY.
IF IT CONTINUES TO RUN, YOUR COMPUTER MIGHT BECOME UNRESPONSIVE.
It occures when IE is running in compatibility mode. (happens while using FB and Google+)
goto "Tools" menu and select the "Compatibility View Settings" option. This will open a window where you can turn off the feature "Display all websites using Compatibility View".

jQuery unbind event from whole array

Hi does anybody know how is jquery unbind function woking?I have a jquery powered photogallery where I am binding some stuff on load event(change image and so on)..But when the user is quickly walking through the gallery I want to unbind "older" events and than bind load event only on the last image. Otherwise the user will see every image he walked through for a tiny moment and I only want to show the last one..(performance, UX,..)I store every loaded(not exactly loaded, too every requested) image in an array, so everytime I call my loadImage function I call jQuery(myArrayWithImages).unbind("load.backgroundImagesLoader")
but it seems it does not work, the load events are still there (its a bit weird, I cant find it in debugger, but I see it:))
Is there any way to unbind the events from whole array, or from whole js instance, except do it through foreach?
Here is some code snippet..It is whole loadImage function..
function loadImage(index , showLoading, callback){
if(backgroundImages==undefined) backgroundImages=Array();
//if(backgroundImages[window.location.hash][index]==undefined)backgroundImages[window.location.hash][index] = Array();
jQuery("#galleryEl .sig_thumb a").each( function( pos , el ) {
var wh_bg_b = getVierwportSize();
if(index == pos){
var bg_img_path_b = jQuery(el).attr('href');
var size = 'max';
if ( bg_img_path_b != undefined ) {
if ( (wh_bg_b[0] < 1281) && (wh_bg_b[1] < 801) ) {
size = 'min';
bg_img_path_b = bg_img_path_b.substring( 0, bg_img_path_b.lastIndexOf("/") ) + "/1280/" + bg_img_path_b.substring( bg_img_path_b.lastIndexOf("/")+1 );
} else if ( (wh_bg_b[0] < 1441) && (wh_bg_b[1] < 901) ) {
size = 'med';
bg_img_path_b = bg_img_path_b.substring( 0, bg_img_path_b.lastIndexOf("/") ) + "/1440/" + bg_img_path_b.substring( bg_img_path_b.lastIndexOf("/")+1 );
}
}
console.log("test");
if(backgroundImages[bg_img_path_b]!=undefined){
if(backgroundImages[bg_img_path_b].loaded=="true"){
//console.log(index+" "+backgroundImages[window.location.hash][index][size]['loaded']);
if(typeof callback=='function'){
callback.call(this, bg_img_path_b);
} }
else if(backgroundImages[bg_img_path_b].loaded=="loading"){
jQuery(backgroundImages).unbind('load.backgroundImages');
jQuery(backgroundImages[bg_img_path_b]).bind('load.backgroundImages',function(){
backgroundImages[bg_img_path_b].loaded="true";
if(typeof callback=='function'){
callback.call(this, bg_img_path_b);
//console.log("loaded "+index);
}
});
}
}
else{
backgroundImages[bg_img_path_b]=new Image();
backgroundImages[bg_img_path_b].src = bg_img_path_b;
backgroundImages[bg_img_path_b].loaded="loading";
jQuery(backgroundImages).unbind('load.backgroundImages');
jQuery(backgroundImages[bg_img_path_b]).bind('load.backgroundImages',function(){
backgroundImages[bg_img_path_b].loaded="true";
if(typeof callback=='function'){
callback.call(this, bg_img_path_b);
//console.log("loaded "+index);
}
});
}
console.log(backgroundImages[bg_img_path_b]);
//console.log(size);
//console.log(backgroundImages);
}
} );
}
You need to unbind not like
jQuery(myArrayWithImages).unbind("load.backgroundImagesLoader")
but
jQuery(myArrayWithImages).unbind(load.backgroundImagesLoader).
Just read manual, you can use namespaces:
$('#foo').bind('click.myEvents', handler);
and
$('#foo').unbind('click.myEvents');

Categories