How to find an element inside another element in mootools - javascript

Let's say i need to find all .bar elements inside an element that's assigned to a variable foo.
In jQuery, foo.find('.bar') solves the problem.
What's the equivalent function in mooTools?

<div id="container">
<span class="elems">...</span>
<span class="elems">...</span>
...
</div>
----
var elems = $('container').getElements('.elems');
// elems is now an array containing all spans with the class 'elem'
Or:
var elems = $$('#container.elems');

Related

Object returned by Jquery.find behaving unexpectedly with .data()

Take a look at this example :
let ele = $(`
<div></div>
<div class="test" id="test" data-test="test"></div>`
);
const ele1 = ele.find('.test'); //undefined
const ele2 = ele.find('#test'); //undefined
console.log(ele1.data());
console.log(ele2.data());
ele = $('<div class="test" id="test" data-test="test"></div>');
console.log(ele.data()); //works
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
There seems to be a difference between the object returned by .find() and the one returned by $()
I'm assuming it has something to do with the first ele being two siblings with no parent, but considering this can't be changed, how can I get #test's data?
I couldn't find anywhere what's the expected behaviour when you create an element with no parent like I did, and why does this happens.
Fiddle : https://jsfiddle.net/xpvt214o/26285/
You can just wrap that HTML inside a single div to be able to use find() on it. But, if you can't change the HTML, you can do it using filter(), since it's a collection of jQuery elements:
// Your element, as you defined it in your question
let ele = $(`
<div></div>
<div class="test" id="test" data-test="test"></div>`
);
console.log(ele.filter('.test').data());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Difference between cloned object and hardcoded HTML

Scenario is to copy #first inside #test, below are the 2 scenarios of implementing it and which is the best way of implementation and why?
<div class="first">
<div class="second">1</div>
</div>
<div class="test">
<div>--------------</div>
</div>
JQUERY1:
var cloner = $('.first').clone().prop({
'class': 'changed_first'
});
$('.test').append(cloner)
$('.changed_first > .second').attr('class', 'changed_second');
$('.changed_first > .second').html('2');
Detour question on JQUERY1: Is there a possibility in the clone method to change the properties of inner elements?
JQUERY2:
$('.test').append('<div class="changed_first"><div class="changed_second">2</div></div>');
your 1st method of using clone will be a good one.
And yes you can manipulate the cloned elements before you bind it to dom.
If you want to access any id or class to cloned element before you bind if to anywhere, you can do like
var cloner = $('.first').clone().prop({
'class': 'changed_first'
});
cloner.find('#id').css('something','css-value');
var data_id = cloner.find('.class').attr('data-bind');

How to get reference to the new DOM object after changing content with outerHTML?

I have a division that I need to change its outer HTML upon an event. The problem is that upon setting the outerHTML I am not able to reference the new selected DOM object unless I explicitly catch it again.
Is there a way to directly update the variable reference upon calling outerHTML (in my case the reference of the div variable below) ?
$("#changeDiv").click(function(){
var div = $(this).prev();
div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
console.log(div); // logs [div#imFirstDiv, prevObject: n.fn.init[1], context: button#changeDiv]
// the following line does not affect the newly added division
// since the var `div` references the old DOM object
// unless I add div = $(this).prev(); before setting the html of
// the paragraph it will not set it
div.find('p').html('Override');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>
I have solved this by getting a reference element (sibling or parent) of tag that's going to be replaced.
Here is a function which is not dependent on which element are you going to change:
function replaceElement(ele, outerHTML)
{
var parent = false, refEle;
//if element that's going to be changed has previousElementSibling, take it as reference. If not, the parentElement will be the reference.
if (ele.previousElementSibling !== null)
refEle = ele.previousElementSibling;
else
{
refEle = ele.parentElement;
//indicate that parentElement has been taken as reference
parent = true;
}
//change the outerHTML
ele.outerHTML = outerHTML;
//return the correct reference
if (parent)
return refEle.firstElementChild;
else return refEle.nextElementSibling;
}
So in your case, you would invoke it this way:
div[0] = replaceElement(div[0], '<div id="imSecondtDiv"> <p> World </p> </div>');
I hope it will work with jQuery as well, as I am writing all my scripts only in native javascript.
As you are seeing changing the outerHTML makes things behave a bit strangely, as you are completely replacing the original element but still referencing the old one.
It would be better to create a new div, add it after() the old one then remove() the old one. This maintains the position of the div in the correct place.
$("#changeDiv").click(function(){
// get the oldDiv
var oldDiv = $(this).prev();
// Create a newDiv
var newDiv = $('<div id="imSecondtDiv"> <p> World </p> </div>');
// add newDiv after oldDiv one, then remove oldDiv from the DOM.
oldDiv.after(newDiv).remove();
// now you still have the reference to newDiv, so do what you want with it
newDiv.find('p').html('Override');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>
Using outerHTML
If you really really do need to use outerHTML, you can simply grab $(this).prev() again:
$("#changeDiv").click(function(){
var div = $(this).prev();
div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
// the "new" div is now before the button, so grab the reference of THAt one
div = $(this).prev();
// the following line does not affect the newly added division
// since the var `div` references the old DOM object
// unless I add div = $(this).prev(); before setting the html of
// the paragraph it will not set it
div.find('p').html('Override');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

Selecting second children of first div children in javascript [duplicate]

This question already has answers here:
querySelector with nested nth-child in Chrome doesn't appear to work
(2 answers)
Closed 3 years ago.
I have an html that look something like this:
<div id="mainDiv"> <-- I have this
<div>
<div></div>
<div></div> <-- I need to get this
</div>
<span></span>
<more stuff />
</div>
i am using:
var mainDiv = document.getElementById('mainDiv');
because I need that div in a var, but i also need to get that second div on the first div inside mainDiv into a variable.
How could I do it in a simple cross-browser way?
Assuming that structure is static you can do this:
var mainDiv = document.getElementById('mainDiv'),
childDiv = mainDiv.getElementsByTagName('div')[0],
requiredDiv = childDiv.getElementsByTagName('div')[1];
Further reading: .getElementsByTagName() (from MDN).
var mainDiv = document.getElementById('mainDiv');
var x = mainDiv.children[0].children[1];
or
var mainDiv = document.getElementById('mainDiv');
var x = mainDiv.getElementsByTagName('div')[0].getElementsByTagName('div')[1];
I would go simply with just one line of vanilla code.
Works for any elements, is not limited to the tag names you have in the structure. But the number of elements and the hierarchy must be preserved.
var requiredDiv = document.getElementById('mainDiv').firstChild.firstChild.nextSibling;
I would pick jQuery and end up with something like this:
var getThis = $('#mainDiv > div:eq(0) > div:eq(1)');
Fiddle
var mainDiv = document.getElementById('mainDiv');
var div = maindiv.getElementsByTagName('div')[2];//third div
http://jsfiddle.net/MGVw8/
You know there is querySelector now ?
console.log(
mainDiv.querySelector(':nth-child(1) > :nth-child(2)'))
<div id="mainDiv">
<div>
<div></div>
<div>come get me</div>
</div>
<!-- more stuff -->
</div>

Why does jQuery, outputs same rel each time?

so basically here is my script:
http://jsfiddle.net/JJFap/42/
Code -
jQuery(document).ready(function() {
var rel = new Array();
var count = 0;
jQuery(".setting").each(function() {
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
});
jQuery("body").text(rel);
console.log(rel);
});​
and
<div class="setting">
<span rel="Variable">Variable</span>
<span rel="Item">Item</span>
<span rel="Something">Something</span>
</div>
<div>
<span rel="Smth">Smth</span>
<span>Sec</span>
</div>
<div class="setting">
<span>Second</span>
<span rel="first">First</span>
<span rel="Third">Third</span>
</div>
​my question, is why does it display Variable, variable?
I would like it to display Variable, First, but I'm not able to do.
Basically what I would like to achieve is create new array, in which insert each div.setting span elements with rel attribute array.
So basically in this example it should output -
Array (
Array[0] => "Variable","Item","Something";
Array[1] => "first","Third";
)
Hope you understood what I meant :)
EDIT:
In my other example I tried to add jQuery("span").each(function() ... inside first each function, but it outputted two full arrays of all span elements with rel. I can't have different classes / ids for each div element, since all will have same class.
jQuery('span') is going to find ALL spans in your page, and then pull out the rel attribute of the first one. Since you don't provide a context for that span search, you'll always get the same #1 span in the document.
You should be using this:
jQuery('span',this).each(function() {
rel[count] = [];
if (jQuery(this).attr("rel")) {
rel[count].push(jQuery(this).attr("rel"));
}
console.log(count);
count++;
})
instead of this:
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
http://jsfiddle.net/mblase75/JJFap/52/
The trick is to use a second .each to loop over all the span tags inside each <div class="setting"> -- your original code was using jQuery("span"), which would just grab the first span tag in the document every time.
In addition to what has been said, you can also get rid of the count and one push() when using jQuery.fn.map() as well as getting rid of the if when adding [rel] to the selector:
jQuery(document).ready(function() {
var rel = [];
jQuery(".setting").each(function() {
rel.push(jQuery(this).find('span[rel]').map(function() {
return this.getAttribute('rel');
}).get());
});
jQuery("body").text(rel);
console.log(rel);
});
Within the .each() method, you have this code a couple times: jQuery("span").attr("rel"). That code simply looks for ALL span tags on the page. When you stick it inside the .push() method, it's just going to push the value for the rel attribute of the first jQuery object in the collection. Instead, you want to do something like $(this).find('span'). This will cause it to look for any span tags that are descendants of the current .setting element that the .each() method is iterating over.

Categories