javascript attachEvent within loop - javascript

I'm using the code below within a loop. It works so long as I'm not using IE.
var remove = document.createElement("input");
remove.type = "button";
remove.value = "x";
if (remove.addEventListener) {
remove.addEventListener("click", (function(item_id) { return function() { remove_from_cart(item_id); } })(item_id), false);
} else {
remove.attachEvent("click", (function(item_id) { return function() { remove_from_cart(item_id); } })(item_id));
}

IE needs to have the on when describing the event so this is what you need.
remove.attachEvent("onclick", (function(item_id) { return function() { remove_from_cart(item_id); } })(item_id));
}

Related

Preventing Jquery .click toggle function from running over and over with excess clicking

Im building a .clicktoggle function in jQuery and for the life of me i can't get a .stop like effect on it, basically i don't want it to play over and over if mash clicked.
I want it to be applied the the function so its self contained, that's where im stuck.
JS fiddle link
(function($) {
$.fn.clickToggle = function(func1, func2) {
var funcs = [func1, func2];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 2;
});
return this;
};
}(jQuery));
$('div').clickToggle(function() {
$('.testsubject').fadeOut(500);
}, function() {
$('.testsubject').fadeIn(500);
});
<div class="clickme">click me fast</div>
<div class="testsubject">how do i stop it playing over and over if you click alot</div>
Toggle .click seems like something alot of people would use so i thought it might be useful to ask it here
By adding a check to a boolean variable fadeInProgress, you can choose to only queue the animation if fadeInProgress is false. It then sets the value to true and executes the animation. When the animation is completed, set the value to false.
var fadeInProgress = false;
$('div').clickToggle(function() {
if (!fadeInProgress) {
fadeInProgress = true;
$('.testsubject').fadeOut(700, function(){fadeInProgress = false;});
}
}, function() {
if (!fadeInProgress) {
fadeInProgress = true;
$('.testsubject').fadeIn(700, function(){fadeInProgress = false;});
}
});
var clicked = false;
var doing = false;
$(".clickme").click(function(e) {
if (doing) {
return;
} else {
doing = true;
}
doing = true;
clicked = !clicked;
if (clicked) {
$('.testsubject').fadeOut(700, function() {
doing = false
});
} else {
$('.testsubject').fadeIn(700, function() {
doing = false;
});
}
});
This example is a simple toggle which only allows you to click when it is not doing anything. I explained on IRC, but as an example here, the function only runs when doing is set to false, which only happens when it's set after fadeIn() or fadeOut's callback function thingymajigger.

JS Event Disabler: Can't stop native eventlisteners from executing

I am implementing a JS Event-Disabler class, to disable all Native and Programmable eventlisteners of a certain dom element and all its children.
So far I've been able to disable all JQuery events and the default browser events, but not the eventlisteners set like
document.getElementById('cin').addEventListener("click", function(){
alert('I should not alert when disabled');
});
So clicking on the element ('native element') shouldn't alert, but it does.
How do I stop that from happening, within my nothing function.
If there is away to not even need to call another function but just disable all events then that would also be fine, but need to be able to re-enable all again.
Also, I can assure you that the nothing() function executes first.
var tellme = function(who) {
//console.info('Event by: '+who+' #'+Date.now());
alert('Event by: ' + who + ' #' + Date.now());
}
$(window).load(function() {
/* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
$.fn.bindFirst = function(name, fn) {
this.on(name, fn);
this.each(function() {
var handlers = $._data(this, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
var listeners = handlers[key];
if (listeners.length > 1) {
var lastEvent = listeners.pop();
listeners.splice(0, 0, lastEvent);
if (listeners[1].handler.name === lastEvent.handler.name)
listeners.splice(1, 1);
}
}
}
});
};
function shouldbenothing() {
tellme('native catcher');
nothing();
}
/* THE DO NOTHING FUNCTION, NEEDS SOMETHING MORE, DOESN'T CANCEL ALL*/
function nothing() {
event.cancel = true;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
//Needed for Jquery
throw new Error("NOT AN ERROR: Just forcefully stopping further events #" /*+Date.now()*/ ); //Add the Date.now to see that this code does run before the native function.
return false;
}
/* THIS WILL ONLY RETURN NON-NATIVE EVENTS, ONLY PROGRAMMED EVENTS*/
function getAllActiveEvents(element) {
var result = [];
var handlers = $._data(element, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
result.push(key);
}
}
return result.join(' ');
}
function getAllEvents(element) {
var result = [];
for (var key in element) {
if (key.indexOf('on') === 0) {
result.push(key.slice(2));
}
}
return result.join(' ');
}
/*SOME PROGRAMMED EVENTS, BESIDES THE NATIVE ONES*/
$('input').on('keyup', function() {
$('#text').html(this.value);
});
$('p').on('click', function() {
$('#text').html(this.innerHTML);
tellme('jquery');
});
document.getElementById('jsE').addEventListener("click", function() {
tellme('p:js');
});
document.getElementById('cin').addEventListener("click", function() {
tellme('input:js');
});
/* THE ACTUAL DISABLER CODE */
/*TOGGLE TO ACTIVE OR DISABLE EVENTS FROM TAKING PLACE NATIVE AND EXTRA*/
var isOn = false;
$('button').on('click', function() {
if (isOn)
$("#obj *").each(function() {
$(this).off(getAllEvents($(this)[0]), "", nothing);
$("#obj").css('pointerEvents','');
});
else {
$("#obj *").each(function() {
var elem = $(this)[0];
var events1 = getAllActiveEvents(elem); //Only programmed listeners
var events2 = getAllEvents(elem); //Native + other listeners
$(this).bindFirst(events2, nothing);
});
$("#obj").css('pointerEvents','none');
}
isOn = !isOn;
this.innerHTML = isOn;
});
});
p {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style>p {pointer:hand;}</style>
<div id="obj">
<p>jquery event</p>
<p id="jsE">js event</p>
<p onclick="tellme('native');">native event</p>
<input id='cin' type="text" />
<p id="text">3</p>
</div>
<p>not catched</p>
<input type="text">
<button>toggle</button>
There might be a very simple, non-js, pure css-solution ... like this:
.whatever {
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
pointer-events:none;
}
... just add the whatever-class to any elements you want to disable completely from user-interaction.
So I found a solution shortly after.
By playing with the css code, I could disable all the relevant mouse events. This however doesn't stop the native events, say if you were to trigger the event via JS, but at least it stops it from user's point.
I actually also like the css method better, as it does allow me to still interact and trigger events, for instance when I want to show the user something without having the user interfere.
The css code:
//To Disable
$("#obj").css('pointerEvents','none');
//To Enable
$("#obj").css('pointerEvents','');
For anyone looking for the full Working Code: Here it is.
Make sure you add the css.
/* Event Disabler, disables all events */
/* How to use:
* Toggle Events: toggleEvents(selector);
* Disable all Events: toggleEvents('body',true);
* Enable all Events: toggleEvents('body',false);
*/
var toggleEvents = null;
$(window).load(function(){
/* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
$.fn.bindFirst = function(name, fn) {
this.on(name, fn);
this.each(function() {
var handlers = $._data(this, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
var listners = handlers[key];
if (listners.length > 1) {
var lastEvent = listners.pop();
listners.splice(0, 0, lastEvent);
//Removes duplicate eventListners
if (listners[1].handler.name === lastEvent.handler.name)
listners.splice(1, 1);
}
}
}
});
};
/* THE DO NOTHING FUNTION CANCELS ALL EVENTS, EVEN BY TRIGGERED*/
function nothing() {
event.cancel = true;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
event.bubbles = false;
if(window.event){
window.event.cancelBubble=true;
}
//throw new Error("NOT AN ERROR: Forcefully stopping further events");
return false;
}
function getAllActiveEvents(element) {
var result = [];
var handlers = $._data(element, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
result.push(key);
}
}
return result.join(' ');
}
function getAllEvents(element) {
var result = [];
for (var key in element) {
if (key.indexOf('on') === 0) {
result.push(key.slice(2));
}
}
return result.join(' ');
}
var enabled = false;
toggleEvents = function(selector,flag) {
enabled = flag === undefined ? !enabled : flag;
if (enabled) {
$(selector+" *").each(function(){
//Only programmed and attached listners
var events1 = getAllActiveEvents($(this)[0]);
//All Native events attached or not
var events2 = getAllEvents($(this)[0]);
$(this).bindFirst(events2, nothing );
});
//Disabled most user pointer events
$(selector).addClass('eventsDisabled');
} else {
$(selector+" *").each(function() {
$(this).off(getAllEvents($(this)[0]), "", nothing );
});
$(selector).removeClass('eventsDisabled');
}
};
});
.eventsDisabled {
-webkit-user-select:none !important;
-moz-user-select:none !important;
-ms-user-select:none !important;
user-select:none !important;
pointer-events:none !important;
}

DOM Traversal API

I am tryingto get the parent of nodes. I tried these.
Ist Approach:
function update(currentElement) {
document.getElementById("nodeNameField").value = currentElement.nodeName;
document.getElementById("nodeTypeField").value = currentElement.nodeType;
document.getElementById("nodeValueField").value = currentElement.nodeValue;
}
function nodeMove(direction) {
switch (direction)
{
case "parentNode": if (nodeMove.currentElement.parentNode)
nodeMove.currentElement = nodeMove.currentElement.parentNode;
else
alert("No parent");
}
update(nodeMove.currentElement);
}
window.onload = function () {
document.getElementById("parentBtn").onclick = function () {nodeMove("parentNode")};
nodeMove.currentElement = document.documentElement; // HTML
update(nodeMove.currentElement);
}
Since the current element is HTML, when i click on the parent button, I do get #document as it's parent.
2nd approach:
if (document.createTreeWalker) {
function myFilter(n) {
return NodeFilter.FILTER_ACCEPT;
}
var myWalker = document.createTreeWalker(document.documentElement,NodeFilter.SHOW_ALL,myFilter, false);
} else
alert("Error: Browser does not support DOM Traversal");
function update(currentElement) {
window.document.testform.nodeName.value = currentElement.nodeName;
window.document.testform.nodeType.value = currentElement.nodeType;
window.document.testform.nodeValue.value = currentElement.nodeValue;
}
var currentElement = myWalker.currentNode;
//var currentElement = document.documentElement;
update(currentElement);
</script>
<form>
<input type="button" value="Parent" onclick="myWalker.parentNode();update(myWalker.currentNode);">
In the 2nd case, i am unable to get the parent of HTML. How will I resolve it? Any suggestions?
If you declare myWalker inside if scope, it won't be visible for outer/global scope. Move declaration over this scope like here:
var myWalker;
if (document.createTreeWalker) {
function myFilter(n) {
return NodeFilter.FILTER_ACCEPT;
}
myWalker = document.createTreeWalker(document.documentElement,NodeFilter.SHOW_ALL,myFilter, false);
} else
alert("Error: Browser does not support DOM Traversal");
function update(currentElement) {
window.document.testform.nodeName.value = currentElement.nodeName;
window.document.testform.nodeType.value = currentElement.nodeType;
window.document.testform.nodeValue.value = currentElement.nodeValue;
}

Listen for keyup on all input fields

Im trying to capture the keyup on all input fields on a page.
My current code is:
var els = document.querySelectorAll('input');
for (var i = 0; i < els.length; i += 1) {
addEvent('keyup', els[i], makeHandler(els[i]));
}
function makeHandler(field) {
console.log(field.value);
}
function addEvent(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt,func,false);
} else if (elem.attachEvent) {
elem.attachEvent("on"+evnt, function(e) {
e = e || window.event;
if (!e.preventDefault) {
e.preventDefault = preventDefaultOnIE;
}
func.call(this, e);
});
} else { // No much to do
elem[evnt] = func;
}
}
But for some reason its only capturing the value on page load, not once i begin to type in any of the fields.
Any ideas what I'm doing wrong?
The problem is with your makeHandler function. makeHandler(els[i]) is being evaluated and the return value (undefined, in this case) is being passed to addEvent as a handler. Try:
function makeHandler(field) {
return function() {
console.log(field.value);
};
}
This way, makeHandler(els[i]) will return a function that addEvent can then attach to keyup.
Alternatively, you could also just use:
function makeHandler() {
console.log(this.value); // 'this' will be the field that the event occurred on
}
and then use:
addEvent('keyup', els[i], makeHandler);
Side-note
I noticed a slight error in your code:
else { // No much to do
elem[evnt] = func;
}
I think you really want to set elem["on" + evnt] instead.
I like to embed the script in a function so I can minimize it in my IDE and turn it on and off globally. In other words, give it a name.
attachKeyupListenerToInputElements();
function attachKeyupListenerToInputElements(){
var inputs = doc.querySelectorAll('input');
for (var i = 0; i < inputs.length; i += 1) {
inputs[i].addEventListener("keyup", keyupHandler);
}
function keyupHandler() {
console.log(this.value);
}
}
Is this what you are looking for:
<script>
$(document).ready(function () {
$("input").keyup(function () {
alert("keyup");
});
});
</script>

.click() not working with specific selector

Setting the Selector's:
btNext = $('<a>' + options.labelNext + '</a>').attr("href", "#").addClass("buttonNext");
btPrevious = $('<a>' + options.labelPrevious + '</a>').attr("href", "#").addClass("buttonPrevious");
btFinish = $('<a>' + options.labelFinish + '</a>').attr("href", "#").addClass("buttonFinish");
test = $('<a class="LinkMe" href="#">MotherBoard</a>')
Click():
$(test).click(function () {
showStep(0);
});
$(btNext).click(function () {
if ($(this).hasClass('buttonDisabled')) {
return false;
}
doForwardProgress();
if ($.isFunction(options.onNext)) {
if (!options.onNext.call(this, $(steps))) {
}
}
return false;
});
$(btPrevious).click(function () {
if ($(this).hasClass('buttonDisabled')) {
return false;
}
doBackwardProgress();
if ($.isFunction(options.onPrevious)) {
if (!options.onPrevious.call(this, $(steps))) {
}
}
return false;
});
$(btFinish).click(function () {
if (!$(this).hasClass('buttonDisabled')) {
if ($.isFunction(options.onFinish)) {
if (!options.onFinish.call(this, $(steps))) {
return false;
}
} else {
var frm = obj.parents('form');
if (frm && frm.length) {
frm.submit();
}
}
}
return false;
});
ALL of the click functions work EXCEPT the selector (test), ive tried taking the click function out of the plugin and in a
$(document).ready(function () {});
and it still doesnt work thier, Please help.
Try doing:
test.click(function() {});
or
$("a.LinkMe").click(function() {});
// since test is a link having a class 'LinkMe'
But if those elements are dynamically added into your HTML, you can use .on() or .delegate()
$("a.LinkMe").on("click", function() {});
// OR
$(document).on("click", "a.LinkMe", function() {});
// OR
$("body").delegate("a.LinkMe", "click", function() {});
Take a look at this.
Instead of doing
test = $('<a class="LinkMe" href="#">MotherBoard</a>')
You'll want to do instead
$test = $('a.LinkMe');
// or just
$test = $('.LinkMe');
Same for the btNext, btPrevious, btFinish. I'm not sure why they work, maybe someone else can explain it to me.

Categories

Resources