JavaScript | jQuery | Selecting In Layers: Select Closest Children But Their Children - javascript

The goal is to select any descendant(s) -- regardless of direct-descendant indication -- but not their children. In other words, if I'm searching from document I'd like to find all children which are not wrapped by the target selector:
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>
$(document).findAllInFirstLayer([data-behavior]);
This, ideally, would select #a1 & #b1 in the result-set. However, #a2, #a3, and #b2 should not be included, as this would proceed one scope to many.
The complimentary function for this will be recursive to drill down to the next scope for each layer-element in the set. So the next recursive call would return a set containing #a2, #b2, but not #a3 or any children ([data-behavior]) of #b2.
Also, this Question should not be marked as a duplicate of this question as the Accepted-Answer is not acceptable here -- the accepted answer here should use a jQuery selector or prove its impossibility with only using a jQuery selector.
Edit
With #guest271314's help, we reached the following answer:
'[data-behavior]:not([data-behavior] [data-behavior]), [data-behavior]:first'
Now, a recursive function can be used to take a parent-context and find the first-level scopes -- and recur in that fashion indefinitely. Here's an example:
arm: function autoRegisterModules(parent) {
var $firstScope = $(parent).find('[data-behavior]:not([data-behavior] [data-behavior]), [data-behavior]:first');
console.log('#context, #first-scope', parent, $firstScope);
if ($firstScope.length) {
$firstScope.each(function (i, p) {
autoRegisterModules(p);
});
}
},
Please be sure to give credit where it's due.
#prethanks

This, ideally, would select #a1 & #b1 in the result-set.
Try using :not() for first result set , :first for next results
var first = $("[data-behavior]:not([data-behavior] [data-behavior])"),
second = first.find("[data-behavior]:first"),
third = second.find("[data-behavior]:first");
console.log(first, second, third);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>
So the next recursive call would return a set containing #a2, #b2, but not #a3 or any children ([data-behavior]) of #b2.
using $.fn.extend()
(function($) {
$.fn.extend({
layers: function(sel) {
var root, next, res = [],
sel = sel || this.selector;
if ($(sel + ":not(" + sel + " " + sel + ")").length) {
root = $(sel + ":not(" + sel + " " + sel + ")");
res.push([root]);
if (root.find(sel + ":first").length) {
next = root.find(sel + ":first");
res.push([next]);
while (next.find(sel + ":first").length) {
next = next.find(sel + ":first");
res.push([next])
}
}
}
return this.data("layers", res)
}
})
}(jQuery))
var layers = $("[data-behavior]").layers().data("layers");
$.each(layers, function(key, value) {
console.log(key, value[0])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>

Related

Wrap two elements in HTML with javascript

I have this code that is generated by php:
<div class="fusion-post-content post-content">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
<div class="fusion-post-content-container"></div>
</div>
I need to wrap two elements by using javascript so the code would look like this:
<div class="fusion-post-content post-content">
<div class="class">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
</div>
<div class="fusion-post-content-container"></div>
</div>
This will do what you want. Isn't it better to change the code on server-side??
// Select the first element found
var parent = document.querySelector('.fusion-post-content');
console.log('Old child-length', parent.children.length);
console.log('Old:', parent.innerHTML);
// *You don't need the timeout
setTimeout(function () {
var h2 = parent.firstElementChild;
var p = parent.firstElementChild.nextElementSibling;
// Remove cildren
parent.removeChild(h2);
parent.removeChild(p);
// Insert the new child
parent.insertAdjacentHTML('afterbegin', '<div class="class"></div>');
// Insert the other children (old) in the new child
parent.firstElementChild.insertAdjacentElement('beforeend', h2);
parent.firstElementChild.insertAdjacentElement('beforeend', p);
// Gets one less, since we put to children in one (3 - 1 = 2)
console.log('New child-length', parent.children.length);
console.log('New:', parent.innerHTML);
}, 500);
<div class="fusion-post-content post-content">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
<div class="fusion-post-content-container"></div>
</div>

Finding value of checkbox in dynamically created element

So, I'm writing some JS which dynamically creates some DOM elements. Below is a structure of the elements created:
<div class='list_item' key='1'>
<p>Hello, World!</p>
</div>
<div class='cont' key='1'>
<input type='checkbox' name='test'/>
</div>
When an event is triggered, I want to loop through all .list_item, and find their corresponding .cont, using the key attribute as an identifier. I want to find the value of the .cont > input[type="checkbox"].
Here's my code so far:
$('.list_item').each(function() {
var x = $('.cont[key="' + $(this).attr('key') + '"]').find('input[type="checkbox"]').prop('checked');
console.log(x);
});
Instead of getting a true or false response, my code throws undefined as its result. What can I do to my code to get the response I want (the value of the checkbox)?
Thanks
Two problems:
You forgot to close the attribute selector
You forgot the . before cont in the class selector
So:
$('.list_item').each(function() {
var x = $('.cont[key="' + $(this).attr('key') + '"]').find('input[type="checkbox"]').prop('checked');
// ------------^--------------------------------------^
console.log(x);
});
Note that you can do that with a single selector rather than find:
$('.list_item').each(function() {
var x = $('.cont[key="' + $(this).attr('key') + '"] input[type="checkbox"]').prop('checked');
console.log(x);
});
Example:
$('.list_item').each(function() {
var x = $('.cont[key="' + $(this).attr('key') + '"] input[type="checkbox"]').prop('checked');
console.log(x);
});
<div class='list_item' key='1'>
<p>Hello, World!</p>
</div>
<div class='cont' key='1'>
<input type='checkbox' name='test' />
</div>
<div class='list_item' key='2'>
<p>Hello, World!</p>
</div>
<div class='cont' key='2'>
<input type='checkbox' name='test' />
</div>
<div class='list_item' key='3'>
<p>Hello, World!</p>
</div>
<div class='cont' key='3'>
<input type='checkbox' name='test' checked/>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I see that your selector is wrong. The class dot is missing. Try with this:
$('.cont[key="' + $(this).attr('key') + '"')
you just missed '.' before class selector
$('.list_item').each(function() {
var x = $('.cont[key="' + $(this).attr('key') + '"]').find('input[type="checkbox"]').prop('checked');
console.log(x);
});

alert box sequence after an image has been loaded

So I am trying to create pop up logic for a simple find an object game. So I created a an array of strings that I want to display 2 alert messages. The first alert stating hey you found [insertName].Then if you click on the same object again it display a generic message "you already found this". Then after all images have been clicked, I have a new page loaded based of the int count of items clicked. What I'm having trouble with is how to execute that first initial alert. I was thinking I would create another array for the initial alerts,but that when i got stuck.
<div id="b1" class="mybox">One</div>
<div id="b2" class="mybox">Two </div>
<div id="b3" class="mybox">Three </div>
<div id="b4" class="mybox">Four </div>
<div id="b5" class="mybox">Effortless Calls </div>
<div id="b6" class="mybox">Voicebot </div>
<script type="text/javascript">
//$('body').css('background','blue');
var Boxes = [];
var ttle = $('.mybox').length;
$('.mybox').click(function () {
alert('Blah ');
var bx = this.id;
if (Boxes.indexOf(bx) >= 0){
alert('You Already Found Object ');
}else{
Boxes.push(bx);
}
if (Boxes.length ==ttle)
window.location = "#/finishedgame";
});
</script>
Add a custom attribute to the your elements data-clicked="false"
When the user clicks the element set elem.setAttribute('data-clicked','true');
<div id="b1" class="mybox" data-clicked="false">One</div>
<div id="b2" class="mybox" data-clicked="false">Two </div>
<div id="b3" class="mybox" data-clicked="false">Three </div>
<div id="b4" class="mybox" data-clicked="false">Four </div>
<div id="b5" class="mybox" data-clicked="false">Effortless Calls </div>
<div id="b6" class="mybox" data-clicked="false">Voicebot </div>
$('.mybox').click(function (elem) {
var clicked = $(elem).data('clicked');
if(clicked){
alert(msg1);
} else {
alert(msg1);
elem.setAttribute('data-clicked','true');
};
});
You don't need another array, before you do Boxes.push(bx); why don't you just do alert(hey you found [insertName]);? this should be the first time a user is touching a box aka when you want the first alert at least from what I gathered from your post. So
var Boxes = [];
var ttle = $('.mybox').length;
$('.mybox').click(function () {
var bx = this.id;
if (Boxes.indexOf(bx) >= 0){
alert('You Already Found Object ');
}else{
var text = [get name of box here]
alert("hey you found" + text);
Boxes.push(bx);
}
if (Boxes.length ==ttle)
window.location = "#/finishedgame";
});

Javascript increment through elements within div?

Ok, so I have the following HTML:
<div class="calculator-section">
<p class="x"></p>
<p class="y"></p>
</div>
<div class="calculator-section">
<p class="z"></p>
<p class="a"></p>
</div>
<div class="calculator-section">
<p class="b"></p>
<p class="c"></p>
</div>
I need to increment through each of these divs and compare classes that each <p> has.
How would I go about doing this?
Currently I have this:
$('.calculator-section').each(function(i, obj) {
$(this).$('p').each(function(i, obj) { //This bit doesn't work
//Check classes for $(this) here?
});
});
But I'm not sure what to do for that inner loop. Any ideas?
Add p to your initial each loop and use the className property within the loop
$('.calculator-section p').each(function(i, obj) {
if(this.className == "x") {
$(this).css('background', 'green')
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="calculator-section">
<p class="x">x</p>
<p class="y">y</p>
</div>
Alternatively, if you are using the multiple loops for a reason:
Select p within the iteration of specific section with $('p', this) or $(this).children('p') etc
$('.calculator-section').each(function(i, obj) {
// $(this) = section
$('p', this).each(function(i, obj) {
// $(this) = p within above section
});
});
Use single each() instead of double each(). Example here..
$('.calculator-section p').each(function(i, obj) {
var className = $(this).attr('class');
if(className == 'expected value'){
//do something
//return false;
}
});
You're going to get too many results. <p class="x"><p> should be <p class="x"></p> (with a forward slash to indicate closing the paragraph.
<div class="calculator-section">
<p class="x"></p>
<p class="y"></p>
</div>
<div class="calculator-section">
<p class="z"></p>
<p class="a"></p>
</div>
<div class="calculator-section">
<p class="b"></p>
<p class="c"></p>
</div>
Once that's fixed,
//you can grab the class couples this way
var results = $('.calculator-section').map(function(i, obj) {
return $(obj).find('p').map(function(i, obj) {
return obj.className;
});
});
//and then do what you want with them later
results.each(function(i, obj) {
console.log(obj[0] + ',' + obj[1]);
});
>> x,y
>> z,a
>> b,c

how to pass accurate multiple selections data using ui-selectable

I am useing jquery-ui selectable, I choose multiple divs, For example: divs 1-3 and divs 5-6 after the selection I pass the divs's info to an array and later to a string (strToSend). the problem is : when I choose divs 1-3 and divs 5-6 I get this Information :
for divs 1-3 : 100,200,300.
for divs 5-6 :100,200,300,400,500,600. -> what I really need is to get: 500,600.At first I thought that I need to clear my array in each loop so I tried : _info1.length = 0; _info1 = []; - no change.
I hope my problem is clear, please ideas what to do ?..
//HTML
<div class="ui-selectable" id="day" style="width: 100px; float: left;">
Sunday
<div class="ui-selectee" id="1" >100 </div>
<div class="ui-selectee" id="2" > 200 </div>
<div class="ui-selectee" id="3" > 300 </div>
<div class="ui-selectee" id="4" > 400 </div>
<div class="ui-selectee" id="5"> 500 </div>
<div class="ui-selectee" id="6"> 600 </div>
<div class="ui-selectee" id="7"> 700 </div>
</div>
//Jquery
$(function () {
$("#day").bind("mousedown", function (event) {
return event.metaKey = true;
}).selectable({
stop: function () {
_info1.push(0);
$(".ui-selected", this).each(function () {
var id = this.id;
_info1.push(id);
});
strToSend += _info1[0] + "_" + _info1[1] + "-" + _info1[_info1.length - 1] + "*";
}
});});
Here's a fiddle: http://jsfiddle.net/tS2cV/
Not sure where you're declaring your _info1 but it looks like you just want it to hold the divs you've selected. Your each function (below) goes through and grabs all divs that have been selected, so you don't have to manually push anything into it beforehand.
All I did was declare _info inside of the stop function - I'm sure what you were doing with the string to send so I removed it for simplicity:
$(function () {
$("#day").bind("mousedown", function (event) {
return event.metaKey = true;
}).selectable({
stop: function () {
var _info1 = [];
$(".ui-selected", this).each(function () {
var id = this.id;
_info1.push(id);
});
alert(_info1);
}
});});

Categories

Resources