Clone does not count toward length - javascript

I have a problem with clone().
<div id="container">
<p id="template">a</p>
</div>
<script>
$(document).ready(function() {
$('#template').clone(true, true).appendTo('#container');
console.log($('#container').length); // it return 1, it supposed to return 2 right?, original and the cloned one.
});
</script>
The length of the container after the clone is 1, why not 2?
I checked via:
console.log($('#container').eq(1));
It returns undefined.
Shouldn't the cloned element become index number 1?

Because you are counting the number of element #container what you should count is the number of element inside of the container.
Appending in jquery means putting an element inside the #container.
calculate children's of container
console.log($('#container').children(".watever-class").length);

$('#container') is looking at the div called container. Since you're only looking at one div, the length of $('#container') is 1.
If you only want to count the number of paragraph elements inside the container, you can use this:
console.log($('#container p').length);
If you want to count the number of elements (not just paragraphs), you can use the children() function:
console.log($('#container').children().length);
Here's a JSFiddle that shows the different options and has comments explaining the three lines of code: https://jsfiddle.net/0uzusuwz/

Related

How to get the index of an element containing specific child

I have a series of div elements, some of which contains h2 element as children (direct or indirect (descendant)). I look for a javascript or jquery to give me the index of such a div element. Moreover I want to start the search from a specific div element. I mean a div element with an index greater than x containing h2. The following code find the ones in the series of all divs containing h2. However, some of divs may not contain h2 and should be counted.
$(".myDivs h2:gt(2)").eq(0)
Html example:
<div class='myDivs'></div>
<div class='myDivs'><h2>Hi</h2></div>
<div class='myDivs'></div>
<div class='myDivs'><div><h2>How are you</h2></div></div>
<div class='myDivs'></div>
if x=2 I want the index of 3 for the fourth div with class myDivs containing an h2.
This is what I found so far, which works:
$(".myDivs:gt("+x+"):has(h2)").eq(0).index()
Since gt is deprecated, the better solution is:
$(".myDivs").slice(x).has("h2").first().index()
Basically, I think you want a jquery something like this:
$(start).find("div").find("h2").parent("div").index();
From the start element, find your divs, then find the h2 tags in the divs, then get the parent divs of the h2s, and then get the index.
You may need a .each (...) after .find("h2");

How to swap placement of two elements, including their classes/ids with onclick?

I'm trying to switch the positions of two divs with an onclick event.
The divs have the same basic format (width, height), but an additional class and id change the way they look.
So, I have two functions that successfully change the id and class names, but there is no visual change.
Here they are:
function whenClickedFilled(){
console.log("filled");
this.firstElementChild.id = "empty";
this.firstElementChild.className = "puzzlepiece emptyDivClass";
}
function whenClickedEmpty(){
console.log("empty");
this.firstElementChild.id = "filled";
this.firstElementChild.className = "puzzlepiece";
}
I'd like to know what the best way is to alternate between classes/ids onclick.
Here is my js fiddle.
I think what you're really looking to do is not swaping the class and id, but swap the elements themselves. This will make sure the numbers contained within the div's is also transfer with the swap.
You still need to implement the logic checks to see if the element should be able to swap with the empty block and there looks like theres a bug when you click empty space itself. But, this should get you on the right track. I recommend placing a debugger statement to step through the code with dev tools open. It will help understand whats taking place. Good luck.
function whenClickedFilled(){
console.log("filled");
//Get the div element and parent
//Then determine the parent of the empty div
var clickedDiv = this.firstChild; //this refers to the TD clicked, get the child div element
var clickedDivParent = this; //this is TD
var emptyDivParent = emptyDiv.parentElement; //stored the empty div reference into a global, retrieve the parent as this could change
//Remove the empty and clicked div's from their container
emptyDivParent.removeChild(emptyDiv)
clickedDivParent.removeChild(clickedDiv);
//Add the elements back to the containers but swapped
clickedDivParent.appendChild(emptyDiv);
emptyDivParent.appendChild(clickedDiv);
}
http://jsfiddle.net/tWrD2/
I'm trying to switch the positions of two divs with an onclick event
If you want to swap two adjacent nodes, you can do something as simple as:
function swapAdjacent(el0, el1) {
el0.parentNode.insertBefore(el1, el0);
}
If you want to swap any two elements in the DOM, you can do something like:
// Swap the postion in the DOM of el0 and el1
function swapElements(el0, el1) {
// Create a temp node that can replace el0
var tmp = el0.cloneNode(false);
// Replace el0 with tmp
el0.parentNode.replaceChild(tmp, el0);
// Replace el1 with el0
el1.parentNode.replaceChild(el0, el1);
// Replace temp node with el1
tmp.parentNode.replaceChild(el1, tmp);
}
and some test markup:
<div id="d0">div 0</div>
<div id="d1">div 1</div>
<button onclick="
swapElements(document.getElementById('d0'), document.getElementById('d1'));
">Swap d0, d1</button>
<button onclick="
swapAdjacent(document.getElementById('d0'), document.getElementById('d1'));
">Swap adjacent</button>
Of course the two elements to swap must be consistent with the surrounding elements, e.g. you can't swap an option element with a div and expect everything to work, but you can probably swap a span with a div.
If you want to swap elements by clicking on one or the other:
<div id="d0" onclick="swapElements(this, document.getElementById('d1'))">div 0</div>
<div id="d1" onclick="swapElements(this, document.getElementById('d0'))">div 1</div>
I found a nice solution provided by fuell when I was searching fo an actual html swap:
<div id="div_1">THIS IS DIV 1</div>
<div id="div_2">THIS IS DIV 2</div>
Go Swap!
$(document).ready(function() {
$(".go-swap").click(function() {
$("#div_1").removeAttr("style");
$("#div_2").removeAttr("style");
var tmp = $("#div_1").html();
$("#div_1").empty().append($("#div_2").html());
$("#div_2").empty().append(tmp);
});
});

How can I identify every element in the DOM and the order of elements?

I want to be able to refer to any element within an HTML DOM and also know what order the elements appear in. I'm hoping elements in the DOM get indexed somewhere from 0 to <number-of-elements-minus-1> so that I can identify specific elements and, separately, list those elements in the order they appear within the HTML.
For example, in this HTML, the elements would be numbered from 0 for the html element, to 9 for the second p element:
<html lang="en-US">
<head>
<title>Element 2. Page title</title>
</head>
<body>
<h1 id="mainHead">Element 4. How to uniquely identify/order DOM elements</h1>
<div id="boxedContent">
<p class="smallText">Element 6. I want to be able to <span class="stress">7. uniquely</span> identify each element and <i>8. also</i> determine the order in which elements appear, reading from top to bottom through the HTML.</p>
</div>
<p>Element 9</p>
</body>
</html>
I want a JavaScript/jQuery way of specifying, for example, the title element, first p element and the span. The HTML pages I'll be working with aren't mine, but if there's a whole-DOM element index that I can access I could get to these 3 elements using those index refs - i.e.
title: 2
first p: 6
span: 7
The index numbers would allow me to list the elements in order.
Is this possible? How do I do it?
A better option would be to use node.compareDocumentPosition(node) (no jQuery needed)
see: https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
Given a list of nodes you can sort them this way:
nodes.sort((a, b) =>
a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
);
You could do something like this:
var elems = document.getElementsByTagName('*');
This will create an array-like object of all DOM element.
Then, there are many ways you can get the index of a specific element in that array-like object.
You could do this:
var indexOfTitle = elems.indexOf(document.getElementsByTagName('TITLE'));
Or, you can create a for loop which loops through all the elements in the elems variable, and uses a property like tagName to find it, etc.

jquery .each() loop

i want to read all links in ".vm-video-title"-divs and post them each in the same div. So i made this script:
$('.vm-video-title').each(function(i) {//all divs
$(this).html($(this).html()+$("div.vm-video-title>a").text());//add to div the link
});
but i have the problem that it reads ALL the links of all divs and put them in one div.
example:
<div class="vm-video-title">Text1</div>
<div class="vm-video-title">Text2</div>
<div class="vm-video-title">Text3</div>
output:
Text1Text1Text2Text3
Text2Text1Text2Text3
Text3Text1Text2Text3
wanted output:
Text1Text1
Text2Text2
Text3Text3
You can select the <a> elements directly, and use the after()[docs] method to append the content of each after each one respectively.
$("div.vm-video-title > a").after(function() { return $(this).text(); });
This doesn't do a "destroy then recreate" of the existing elements like the html()[docs] method will.
Working example: http://jsfiddle.net/CCr9C/
This should do the job for you,
you need to find the div inside current element in the loop (el).
$('.vm-video-title').each(function(i, el) {
el = $(el);
el.html(el.html()+el.find("a").text());
});
in your code you are adding text() of all matching "a" tags in your divs (i.e. Text1Text2Text3)
You were almost there. Instead of : $("div.vm-video-title").text(), which gives you text inside any div with class vm-video-title, you need to find a tag inside current div and get text from it. We pass this as context for selecting a inside current div jQuery( selector, [context] )
$('.vm-video-title').each(function(i) {//all divs
$(this).html($(this).html()+$("a", this).text());
});

How to make a function repeat/loop in jQuery?

I have a function here for centering an element within it's parent.
Check out the demo: http://jsfiddle.net/kE9xW/1/
right now it's only applying the centering to the first element, how do i make the function loop itself so it centers every #element on the page. the demo is self explanatory, thanks!
There are a few things you need to do.
As already suggested, id's must be unique, so change the id="..." to class="...". You will also need to change your css to be based on the class not the id (change #element' to '.element')
<div class="container">
<p> ... </p>
<div class="element">
</div>
</div>
Use each in your method to loop over all elements selected by the selector $('.element').
element.each(function(){
// work here in $(this) for the current element
});
You forgot to take the top of the parent div into account, which made all elements overlap each other. So your yPas becomes:
var yPos = $(this).parent().position().top +
parseInt($(this).parent().css('height'))/2 -
parseInt($(this).css('height'))/2 - yPosFromCenter;
Check the working fiddle: http://jsfiddle.net/H99DT/
First, the easiest but most important part: change your IDs to classes. IDs must be unique per page so jQuery's ID selector and JavaScript's document.getElementById() function are only going to give you the first matching element:
Each id value must be used only once within a document. If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM.
Change
<div id="container">
...
<div id="element">
to
<div class="container">
...
<div class="element">
and change
$('#element')
to
$('.element')
Next, the more difficult part: you are currently issuing one centerDiv() call to your elements with coordinates from center of 0, 0. That's going to take all your .elements and position them at the exact same spot.
If that's not what you intend, you're going to have to loop through them using .each() and decide the xPosFromCenter and yPosFromCenter in each iteration. It's not clear to me yet how your function works so you may have to explore on your own and see what you can come up with.
Scratch that, see Jamiec's working example for the solution.
Change Id to class in you divs, then make container's position relative with css, and I'll suggest make jQuery plugin from your function. See results http://jsfiddle.net/kE9xW/1/

Categories

Resources