Why is this "copy"(click) wrong, it binds all the previous handlers as well:
var add = function(element) {
var ele = element.clone(true);
$('.container').append(ele);
$('.copy', new).click(function(){ add(ele); });
}
Idea: I want to have an element text next to a "copy" button.
When I click "copy", it clones the current row and append it to the container.
But this seems to be recursive...
The true parameter says:
Normally, any event handlers bound to the original element are not copied to the clone. The optional withDataAndEvents parameter allows us to change this behavior, and to instead make copies of all of the event handlers as well, bound to the new copy of the element.
So you keep adding click event handlers to the .clone element. Depending on your actual case, just don't bind the event handler again:
var add = function(element) {
var cloned = element.clone(true);
$('.container').append(cloned);
}
$('.container .copy').click(function(){
add($(this).closest('tr'));
});
(I used $(this).closest('tr') to get the parent row. Obviously you have to adjust it to your needs.)
Update:
Or don't pass true:
var add = function(element) {
var cloned = element.clone();
$('.container').append(cloned);
$('.copy', cloned).click(function(){ add(cloned); });
}
new is JS keyword. Change it to something else and it should work.
( Your code does not have call of add() except of from itself. So it is not clear how code gets there initially. And recursive declaration of functions as in your code is a path to programmers hell )
Related
I have detached a div and want to re-attach it when clicking on a button.
Here's the code:
$('#wrapper').detach();
$("#open_menu").click(function(){
ATTACH HERE !!!
});
Any help will be appreciated.
var el = $('#wrapper').detach();
$("#open_menu").click(function(){
$(this).append(el);
});
I needed a solution that would work even if there are other elements after the target element to detach and then reattach. This means that append may not be reliable because it would move that element back to the end of its parent. I had to use a placeholder which may not be the most elegant solution, but I haven't found another way..
var $wrapper = $('#wrapper')
, $placeholder = $('<span style="display: none;" />')
.insertAfter( $wrapper )
;
$wrapper.detach();
$("#open_menu").on('click',function(){
$wrapper.insertBefore( $placeholder );
$placeholder.remove();
});
To make this more reusable, it might be better to wrap it in a jQuery plugin:
(function($){
$.fn.detachTemp = function() {
this.data('dt_placeholder',$('<span style="display: none;" />')
.insertAfter( this ));
return this.detach();
}
$.fn.reattach = function() {
if(this.data('dt_placeholder')){
this.insertBefore( this.data('dt_placeholder') );
this.data('dt_placeholder').remove();
this.removeData('dt_placeholder');
}
else if(window.console && console.error)
console.error("Unable to reattach this element because its placeholder is not available.");
return this;
}
})(jQuery);
Usage:
var $wrapper = $('#wrapper').detachTemp();
$("#open_menu").on('click',function(){
$wrapper.reattach();
});
if you want your item to attach at the beginning of the element you could use .prepend()
otherwise you could attach it using append().
in your case it would be:
var $wrapper = $('#wrapper').detach();
$("#open_menu").click(function(){
//ATTACH HERE !!!
$(this).prepend($wrapper); // or $(this).append($wrapper);
});
I hope it helps :)
I think this is largely a matter of recording the index of the element that will be detached, before detaching it, then using that index for determining where to re-attach the element. Consider the following "repl" https://repl.it/#dexygen/re-attach and the code below. The setTimeout is merely so you can see the element in the page before it gets detached, and a couple of elements have been renamed. I wonder if siblings can be used instead of parent().children() but am concerned what happens in the event the detached sibling is the only element among siblings, and we need a reference to parent anyway, for prepending if index === 0.
setTimeout(function() {
var bar = $('#bar');
var parent = bar.parent();
var index = parent.children().index(bar);
bar.detach();
$("#re-attach").one('click', function() {
if (index === 0) {
parent.prepend(bar);
}
else {
parent.children().eq(index-1).after(bar);
}
});
}, 5000);
$(function(){
var detached = $('#element_to_detach').detach();
// Here We store the detach element to the new variable named detached
$('.element_after_which_you_need_to_attach').after(detached);
});
var $wrapper = $('#wrapper').detach();
$("#open_menu").click(function(){
$(this).append($wrapper[0])
});
How about prepend() the detached element after assigning it to a variable, ie.
var det_elem = $('#wrapper').detach();
$("#open_menu").click(function(){
$(this).prepend(det_elem);
});
prepend() will attach at the beginning of the element.
jQuery does not offer an attach method. Consider that detach is the equivalent of permanently deleting an item from the Dom. If you believe that you might want to remove and later bring back an element, consider the following options:
Use the toggle method. To hide and unhide elements from the page.
If you must absolutely remove the item from the Dom, consider using the jQuery clone method, to first make a copy of the specified element, which you can then later reintroduce the element copy back to the Dom.
The above are not the only two ways to accomplish this, however, they are simply and would likely not require much code changes on your end.
im trying to replace various elements with another inside a jquery .each loop and give them on click events to their child nodes, but it does not work, here is my code.
var replacer = function () {
var elementbody = "<div class='Container'><div class='Button'></div></div>";
$('.myclass').each(function (index, element) {
$(element).replaceWith(elementBody);
$(element).find('.Button').click(function () {
//------------------To do on click event------------------//
});
};
After you use
$(element).replaceWith(...);
element still refers to the old element, not the elements that have replaced it. So $(element).find('.Button') doesn't find the button you just added.
Instead of adding the handler to each element that you add, use delegation to bind a handler just once, as explained in Event binding on dynamically created elements?
$("someSelector").on("click", ".Button", function() {
...
});
You can use a delegate as Barmar suggests or you could provide yourself with a new jquery object that references your new content before running the replaceWith
Something like this, maybe:
new_element = $('<div><button>Hello World</button></div');
$(element).replaceWith(new_element);
new_element.find('button').on('click', function(e) {
console.log(e);
});
I want to build a JS library, so I am not using any jQuery. This is Pure JavaScript.
I created a div after mouse entered the specific element then display some info inside the div just created and after mouse leave, the info will disappear.
The mouse enter part worked fine, it showed with correct text and css style, but when moving mouse out, it only run the function first time. the created div will stay there ignoring the mouseleave function after first try.
Here is the JS code
document.getElementById(id).addEventListener("mouseenter", function(){
var elemDiv = document.createElement('div');
elemDiv.id ="demo";
document.body.appendChild(elemDiv);
elemDiv.innerHTML = "something";
}, false);
document.getElementById(id).addEventListener("mouseleave", function(){
document.getElementById("demo").innerHTML="";
}, false);
I have tried the other method before, it gives same result
document.getElementById(id).onmouseenter = function(){...}
document.getElementById(id).onmouseleave = function(){...}
On every "mouseenter" you create a new element but you never delete it. On "mouseleave" you only delete the content of the first one, the second (third, ...) is still there and keeps its content.
You should probably create the element outside the event handlers and only change "innerHTML". Or you remove it on "mouseLeave" from the DOM.
You are creating multiple elements with the same ID and then querying with document.getElementById. This has unpredictable browser results (typically the first is returned) - you need to ensure that for each ID in your DOM, only one ID is present.
With that in mind, your mouseenter function is actually broken as it is creating extra copies of the same div when it needs to determine if one already exists.
document.getElementById(id).addEventListener("mouseenter", function(){
// Find the 'demo' div
var elemDiv = document.getElementById('demo');
// If it doesn't exist, create a div, give it the unique ID 'demo' and add it to the DOM'
if (!elemDiv) {
elemDiv = document.createElement('div');
elemDiv.id = 'demo';
document.body.appendChild(elemDiv);
}
// Whether it was already on the DOM or had to be created, the text is reset.
elemDiv.innerHTML = "something";
}, false);
See my JSFiddle for a complete example: http://jsfiddle.net/ckned3mx/6/
On every mouseenter event you are making a new element with the same id="demo" which is invalid HTML (ID should be unique).
Then on mouseleave the .getElementById() function will return the first element found with that ID, which is the one created by the first mouseenter.
This means you end up with multiple demo elements that don't get cleaned up.
You should either re-use the same element (don't create it if it already exists) or remove the element on mouseleave.
here is a Demo:
http://jsfiddle.net/hxzgpdoz/
i made some changes in your mouseenter event function:
var elemDiv = document.getElementById("demo");
if( elemDiv ){
elemDiv.innerHTML = "something";
}else{
elemDiv = document.createElement('div');
elemDiv.id ="demo";
document.body.appendChild(elemDiv);
elemDiv.innerHTML = "something";
}
I have a click function which is given below
$('.page-nav li').click(function(event){
console.log("clickedTab-page-nav-first-before set ="+Session.get('clickedTab'));
Session.set('clickedTab',event.target.id);
//var sel = event.prevUntil("[class*=active]").andSelf();
var sel = $(this).prevUntil("[class*=active]").andSelf(); //find all previous li
//of li which have
//class=active
sel = sel.add(sel.eq(0).prev()); // include the that li also(Now all li elements).
sel.removeClass('active'); //Remove the active.
//sel = event.nextUntil("[class*=active]").andSelf(); //Also for top to bottom
//(Viceversa)
sel = $(this).nextUntil("[class*=active]").andSelf();
sel = sel.add(sel.eq(-1).next());
sel.removeClass('active');
//event.addClass('active');
$(this).addClass('active'); //Now add class active for the clicked li
var rightcontent="";
console.log("clickedTab-page-nav-second-after set = "+Session.get('clickedTab'));
switch($(this).attr('id')){
case 'rfq':
.......
.....
}
});
Then next is I want to call this click function from another place
$(document).ready(function() {
console.log("clickedTab-page load = "+Session.get('clickedTab'));
if(Session.get('clickedTab')!=null||Session.get('clickedTab')!= undefined){
alert("Got It");
//$('.page-nav li').click(event);
$('.page-nav li').click(); //this is not working
}
});
Now the problem is page click function in if condition is not working. However I got the alert. Any help is highly appreciated. Thanks in advance...
you are not really using the event parameter in your function and you state you wish to call it outside of an event chain so you could change it to be a regular function
var setupClicktab = function(id){
console.log("clickedTab-page-nav-first-before set ="+Session.get('clickedTab'));
Session.set('clickedTab',id);
...
}
the you'd use it like:
$('.page-nav li').click(function(event){return setupClicktab(event.target.id);});
and in document ready
setupClicktab.Call($('.page-nav li'),Session.get('clickedTab'));
The latter call class it in the context of the selection (that is this inside the function will refer to the selection(1). It also passes the value stored in the session variable in as the id.
a side note. Your test
if(Session.get('clickedTab')!=null||Session.get('clickedTab')!= undefined)
could simply be
if(Session.get('clickedTab'))
Unless you might store either an empty string, zero or the boolean value false in that variable. But seeing how it's used that's unlikely since they are all invalid values for the id attribute
(1)This is slightly different than in the click event where it refers to the DOM element)
You need to put $('.page-nav li').click(function(event){ inside document.ready and before your $('.page-nav li').click();. Because if you call .click when the DOM is not ready, there are chances that there is no event handler attached
If you don't put $('.page-nav li').click(function(event){ inside document.ready OR you're dealing with dynamically created elements. You need delegated event $(document).on("click",".page-nav li",function(event){
From $.on
I've been struggling with what seems to be a simple problem for a few hours now. I've written a REGEX expression that works however I was hoping for a more elegant approach for dealing with the HTML. The string would be passed in to the function, rather than dealing with the content directly in the page. After looking at many examples I feel like I must be doing something wrong. I'm attempting to take a string and clean it of client Events before saving it to our Database, I thought jQuery would be perfect for this.
I Want:
Some random text click here and a link with any event type
//to become:
Some random text click here and a link with any event type
Here's my code
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv).find('a').unbind();
return $(myDiv).html();
}
My results are, the onClick remains in the anchor tag.
Here's a pure Javascript solution that removes any attribute from any DOM element (and its children) that starts with "on":
function cleanHandlers(el) {
// only do DOM elements
if (!('tagName' in el)) return;
// attributes is a live node map, so don't increment
// the counter when removing the current node
var a = el.attributes;
for (var i = 0; i < a.length; ) {
if (a[i].name.match(/^on/i)) {
el.removeAttribute(a[i].name);
} else {
++i;
}
}
// recursively test the children
var child = el.firstChild;
while (child) {
cleanHandlers(child);
child = child.nextSibling;
}
}
cleanHandlers(document.body);
working demo at http://jsfiddle.net/alnitak/dqV5k/
unbind() doesn't work because you are using inline onclick event handler. If you were binding your click event using jquery/javascript the you can unbind the event using unbind(). To remove any inline events you can just use removeAttr('onclick')
$('a').click(function(){ //<-- bound using script
alert('clicked');
$('a').unbind(); //<-- will unbind all events that aren't inline on all anchors once one link is clicked
});
http://jsfiddle.net/LZgjF/1/
I ended up with this solution, which removes all events on any item.
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv)
.find('*')
.removeAttr('onload')
.removeAttr('onunload')
.removeAttr('onblur')
.removeAttr('onchange')
.removeAttr('onfocus')
.removeAttr('onreset')
.removeAttr('onselect')
.removeAttr('onsubmit')
.removeAttr('onabort')
.removeAttr('onkeydown')
.removeAttr('onkeypress')
.removeAttr('onkeyup')
.removeAttr('onclick')
.removeAttr('ondblclick')
.removeAttr('onmousedown')
.removeAttr('onmousemove')
.removeAttr('onmouseout')
.removeAttr('onmouseover')
.removeAttr('onmouseup');
return $(myDiv).html();
}