jQuery wont append a clone on page load - javascript

If you click option 2, it appends the original clone from page load but it wont repeat every time the button is clicked.
1. Turn the element red...<br />
2. Append the original black element...<br /><br />
<div id="container">
<div class="element">This is an element!</div>
</div>
$(document).ready(function () {
var obj = $(".element").clone(true);
$(".copy").click(function (e) {
e.preventDefault();
//alert(obj); //Just to see if it still exists.
$("#container").append(obj);
});
$(".modify").click(function (e) {
e.preventDefault();
$(".element").css("color", "#F00");
});
});
Here is my CodePen link http://codepen.io/anon/pen/dsvLm
Any ideas?

One feature of an individual DOM element, that you may not have been aware of, is that it can only have one parent. This makes sense as the DOM tree connects elements up, down, and sideways to each other and only have a single parent-element link (and a single next and single prev sibling element link) but a list of multiple children.
When you clone an element, you create a new DOM element that is effectively a new branch in a DOM tree (if only a small one). Calling append adds the element to its new parent, but it also points a parent link of your clone to its new parent. By appending the same element over and over you are simply changing the parent of a single element (i.e. moving it in the DOM tree).
Instead just make a new clone of your disconnected cloned object (in its original state) each time you need one:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/7h8MK/2/
$("#container").append(obj.clone(true));

You need to create the clone while appending.Use:
var obj = $(".element");
$(".copy").click(function (e) {
e.preventDefault();
//alert(obj); //Just to see if it still exists.
$("#container").append(obj.clone(true));
});
Demo

Related

.appendChild() an HTML element on click

I wanted to copy an entire row including its' siblings and contents on button click. When I click the button the element, it appears in the console but doesn't append to the page. This is my code:
It doesn't show any error messages. I've tried innerHTML/outerHTML or append() it doesn't work.
$(document).ready(function() {
$('#addSubFBtn').on('click', function() {
var itm = document.getElementById("trFb");
var wrapper = document.createElement('div');
var el = wrapper.appendChild(itm);
document.getElementById("tbFb").append(el);
console.log(el);
});
});
Seems like what you're trying to do is clone the item after you get it from your document. W3schools website explains how to accomplish this. Check out the link: https://www.w3schools.com/jsref/met_node_clonenode.asp
Once you clone the node, [appendchild] should work as intended
Not sure (as said without seeing related HTML) but i see flaw in your logic:
var itm = document.getElementById("trFb");
still exist on the document(so in the page) so you've to retrieve it before you want to add/move it to another place.
using .removeElement will return you removed element(or null if no element matche the selector) so correct script should be:
var itm=document.getElementById("trFb").parentNode.removeChild(document.getElementById("trFb"));
as shown here to remove element you've to use method on to parent element.
So you can add it to any other element existing.
For more specific use or element created in global JS variable (such an createElement not yet appended) you can see :document.createDocumentFragment(); as explained here https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

jquery not reacting to class changes?

So I've got this assignment I've got to do, it has to do with a christmas tree where you can click the branches and turn them into ornaments and whatnot.
When the tree is on, you should not be able to change the ornaments.
So far i've got this jquery:
$('.branch1, .ornament1, .light1').click(function()
{
alert("WARNING - Power off the tree first!");
die();
});
$('.branch, .ornament, .light').click(function()
{
this.className =
{
light : 'branch', branch: 'ornament', ornament: 'light'
}[this.className];
});
$('#treePowerButton').click(function()
{
$(".branch, .branch1").toggleClass("branch branch1");
$(".ornament, .ornament1").toggleClass("ornament ornament1");
$(".light, .light1").toggleClass("light light1");
$(".powerStatus, .powerStatus1").toggleClass("powerStatus powerStatus1");
});
$('#treeClearButton').click(function()
{
$(".ornament").toggleClass("ornament branch");
$(".light").toggleClass("light branch");
});
But when I turn the tree on and click a branch or ornament it doesn't throw the alert, it just makes the clicked item completely disappear. What am I doing wrong?
here's a jsfiddle: http://jsfiddle.net/a1smjgrv/
Refined Answer:
Try this jsfiddle: http://jsfiddle.net/a1smjgrv/5/. It will accomplish what you're looking for and is much simpler than trying to bind multiple click events on the same element.
Original Answer:
The problem is that when the page is loaded, there are not any 'branch1', 'ornament1', or 'light1' elements on the page, so the click event containing the alert() is not being bound to anything. There are only 'branch' elements on the page, so the click events for the branches are all that's bound.
When the tree is powered ON and the 'branch' elements are changed to be a 'branch1' class, the click event containing the className update are still attached to that element. So, when it tries to update the class name based on your object literal ({light: 'branch', branch: 'ornament', etc...}), it can't find a match for any of those because the class name of the given element is now 'branch1' instead of 'branch', so it's setting the class name on the element to 'undefined' (hence, the disappearance).
If you want a function to be bound to an element at any point in time that the element is rendered to the page, you'll need to bind it at the document level instead. Something like the following:
$(document).on('click', 'branch1', function() {
alert('SHAZAM!');
});

Trouble with javascript click() method / html

Thank you in advance for looking at this.
My webapp allows a user to select choices from four different drop-down menus. When the user makes a selection, the program successfully performs the following click() function which creates a new span element within a div element:
var activeFilterNames = [];
$('.filter').click(function()
{
if (!this.classList.contains('disabled'))
{
//above checks to see if link has already been clicked
//and is therefore disabled. If not, go ahead.
activeFilterNames.push(this.textContent);
//above adds name of selected link to array
i = activeFilterNames.length;
var newFilter = document.createElement('span');
newFilter.id = activeFilterNames[i-1];
newFilter.className = this.className+" activated";
//above adds a new class to identify the filter as 'activated'
//above retains existing classname to identify
//which of the four filters it came from
newFilter.innerHTML = activeFilterNames[i-1];
//above creates display text to be rendered in browser
document.getElementById('active_filters').appendChild(newFilter);
//above is the div in which span will be appended to other spans.
$("#active_filters > span").removeClass('filter');
//above removes .filter class so that this newly created span does
//not respond to the .filter click() function.
$(this).addClass('disabled');
//above adds 'disabled' class to the originally
//clicked link, causing it to skip this block of code
}
}
);
Everything appears to work fine up to this point (though I may be missing something). Essentially I am creating span elements that come out looking like this in html:
<span id="id_name" class="menu_name activated">Rendered Name</span>
And since the above span does not have the filter class, I then try to create a new function in javascript (just as a test) to make the element responsive:
$('.activated').click(function()
{
alert('hi');
}
);
But no luck. I've tried to re-render the dynamically created elements by nesting div or a inside the span, modifying the code as needed, but still nothing. I would like to keep the span because it's the only way I've found to wrap these dynamically generated elements to a second line within the div (#active_filters) where they are being created.
Can anyone see what I'm doing wrong given that I want to make the activated click() function responsive within each newly created span element?
Your binding will not work if you attempt to bind to DOM elements contained in $('.activated') before creating them. What this usually means is that you need that event listener to bind after creating. If you're dynamically creating DOM elements, you need to do something like this:
var activeFilterNames = [];
$('.filter').click(function()
{
if (!this.classList.contains('disabled'))
{
activeFilterNames.push(this.textContent);
i = activeFilterNames.length;
var newFilter = document.createElement('span');
newFilter.id = activeFilterNames[i-1];
newFilter.className = this.className+" activated";
newFilter.innerHTML = activeFilterNames[i-1];
document.getElementById('active_filters').appendChild(newFilter);
$('.activated').unbind('click');
$('.activated').click(function()
{
alert('hi');
}
);
$("#active_filters > span").removeClass('filter');
$(this).addClass('disabled');
}
}
);
Notice, before binding we unbind. This makes sure that if you do this multiple times, you aren't binding 2, 3, 4 times to the same DOM element.
You need to attach click event on dynamically created elements. In jQuery this can be done using on method if you will pass your selector as second argument and attach click to some parent element, body for example:
$( 'body' ).on( 'click', '.activated', function()
{
alert('hi');
}
);

JavaScript lastChild issue

When I add text in my text field before and after the existing paragraphs the remove button functions perfectly. However, if I click the remove button before adding elements you have to click TWICE to remove the paragraphs that were not created by a function.
What could be wrong here? I watch the DOM in Firebug as I'm adding and removing, and before the new elements are added, my remove button does not target "firstDiv" on the first click, but does so on the second click.
Here is the problem function:
function removeIt() {
firstDiv.removeChild(firstDiv.lastChild);
}
Here is the fiddle: http://jsfiddle.net/nxpeD/2/
Thanks for the help!
That's because you have text nodes (spaces) at the end, so the last paragraph isn't the last child (it is the last element child).
Then, use
function removeIt() {
firstDiv.removeChild(firstDiv.lastElementChild);
}
Demo: http://jsfiddle.net/nxpeD/6/
Compatibility: To make it work on old browsers, you could also use
function removeIt() {
if (firstDiv.lastElementChild) {
firstDiv.removeChild(firstDiv.lastElementChild);
} else {
var last;
while((last = firstDiv.lastChild).nodeType !== 1) {
firstDiv.removeChild(last);
}
firstDiv.removeChild(last);
}
}
References
lastChild
lastElementChild
Use:
firstDiv.removeChild(firstDiv.lastElementChild);
Since there are formatting new line chars in your html, that will be considered as a child as well of the div. So you need to use lastElementChild to get the element and ignore the formatting and and other text nodes outside.
Demo
The last_child returned is a node. If its parent is an element, then the child is generally an Element node, a Text node, or a Comment node. Returns null if there are no child elements.
lastElementChild

Including variable assignments inside a function?

<button onclick="insert()">Click to insert</button>
<hr id="start">
<hr id="end">
I wrote a javascript function that inserts a div between two horizontal rules:
<script type="text/javascript">
var element = document.createElement("div");
var element_content = document.createTextNode("This is a newly added row!");
element.appendChild(element_content);
var sibling = document.getElementById("end")
var parent = document.getElementById("start").parentNode;
function insert(){
parent.insertBefore(element,sibling);
}
</script>
However when I click the button for the second time, no divs are inserted. I had to include all the variable assignments inside the function in order to click on the button for the 2nd time have the div inserted:
<script type="text/javascript">
function insert(){
var element = document.createElement("div");
var element_content = document.createTextNode("This is a newly added row!");
element.appendChild(element_content);
var sibling = document.getElementById("end")
var parent = document.getElementById("start").parentNode;
parent.insertBefore(element,sibling);
}
</script>
Can someone explain why my first approach didn't allow a 2nd div to be inserted after clicking the button?
In the first example you create one element, since you define it outside of the function. The first time the function is called, that element is appended to the DOM and it won't be appended again (it actually gets removed and appended again, but in the same place):
If the node already exists it is removed from current parent node,
then added to new parent node.
See appendChild on MDN.
The second example creates a new element every time you call the function, and appends that new element to the DOM.
Of course! If you keep the element outside of the function, only 1 new div is created and you are inserting the same div over and over. When a div is inserted in a new location, it is removed from it's old location (if any).
Your second method creates new divs every time the button is clicked.
Because you're only creating a div once and then inserting it when you click the button. You never create a second div, so how can you expect one to magically appear out of nowhere?
The second function works because it creates the div when you click the button, then inserts it. Here you create one div for every click, so it works.
in your first approach, the variables you declare outside the function are created before the click is triggered, therefore they will exist always in the same state independently of what you click.
The first approach only creates the div once and inserts it in the DOM. Calling the function twice doesn't create the div again like the second method does. You could probably take the:
var sibling = document.getElementById("end")
var parent = document.getElementById("start").parentNode;
out of the function though.
The Script is syntactically correct and does what you tell it to do. You're inserting the same node to the same position, which results in... nothing.
Try cloning the node:
function insert(){
parent.insertBefore(element.cloneNode(true), sibling);
}

Categories