I've been working on this JSFiddle to practice my understanding of jquery, but now I'm stuck.
How do you wrap a child element in a div to follow this pattern: child elements 1-5, then child elements 6-10, then child elements 11-15, and so on?
I'm working on a tally counter, so I want every 5 tallies to cluster together. That way, I can more easily select the last child and apply a class to make it rotate, in order to "cross out" the previous 4 tallies.
edit: (To clarify: I've been looking into selecting by index and by nth-child/nth-of-type, but those methods can only really grab the fifth element, or maybe even multiples of five? It doesn't grab the previous divs, too.)
edit 2: (So, you can actually use those selectors! I figured I was getting something wrong. It's always something simple.)
$(".button").click(function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$("#counternumber").val(newVal);
});
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally)
});
$(function(){
$('#scratchpad.tally:nth-of-type(5)').wrap('tallyfamily');
});
JSFiddle.
Here is a general solution to wrap elements in groups of 5:
$(".holder > div:nth-child(5n-4)")
.addClass("first-of-group")
.each(function(){
$(this).nextUntil(".first-of-group")
.addBack()
.wrapAll("<div class='wrapper'>");
})
.removeClass("first-of-group");
http://jsfiddle.net/nJJM8/1/
Basically, :nth-child(5n-4) gets the first element in each group of 5. Then a class is temporarily added to keep track of these. nextUntil is used to find all elements up until the next element with that class. And finally wrapAll is used to wrap the matched elements in a div.
EDIT: Even easier:
var $divs = $(".holder > div");
for (var i = 0; i < $divs.length; i += 5) {
$divs.slice(i, i + 5).wrapAll("<div class='wrapper'>");
}
http://jsfiddle.net/kMzeN/1/
You're almost there, but a couple of things to note. You will only call your "wrap" function once, as it's outside of the click event. If you are dynamically adding, then you'll want to call it each time.
Secondly, with the HTML in your fiddle, you will never get the 5th record because you are appending your selector is looking for the 5th element with ID "scratchpad" with the class of tally. You'd need to change your selector to something that looks for all tallies, like so:
$(".tally:nth-of-type(5)").css('color', 'red');
I've updated the fiddle you were working on, and my code highlights each 5th record, so you can see what's going on. You were close, but you'll also want to add to your "nth-of-type" selector the use of "n", this way it gets every 5th record, not just the 5th one. So the full function becomes this
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally);
$(".tally:nth-of-type(5n)").css('color', 'red');
});
Fiddle: http://jsfiddle.net/Hfz9L/16/
To rotate (or apply any other property) to each 5th element, you don't even need to wrap them. Just specify a css class using the nth-of-type(5n) and it will affect every 5th element.
#scratchpad .tally:nth-of-type(5n) {
display: inline-block;
transform:rotate(20deg);
-ms-transform:rotate(20deg); /* IE 9 */
-webkit-transform:rotate(20deg); /* Opera, Chrome, and Safari */
}
Here is your fiddle updated: http://jsfiddle.net/Hfz9L/20/
Check this Working Demo Fiddle
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally);
$('#scratchpad .tally:nth-of-type(5n+1)').prevUntil('span').wrapAll('<span style="margin-right:5px;color:red;text-decoration:line-through;"></span>');
});
$('#scratchpad .tally:nth-of-type(5n+1)').prevUntil('span').wrapAll('<span style="margin-right:5px;color:red;text-decoration:line-through;"></span>');
Some changes:
$('#scratchpad .tally:nth-of-type(5n+1)') and not $('#scratchpad.tally:nth-of-type(5)'). - .tally is the child of #scratchpad ; selector to be used :nth-of-type(5n+1)
Use .wrapAll() - to wrap the selected elements in a <span> or any other element.
.prevUntil() - get all the previous elements.
You can make a for loop and do this:
for(i=1;i<=noOfChildElements/5;i++)
{
$('.child:nth-child('+i+'), .child:nth-child('+(i+1)+'), .child:nth-child('+(i+2)+'), .child:nth-child('+(i+3)+'), .child:nth-child('+(i+4)+')').wrapAll("<div />");
}
Basically I'm going through the child elements in the for loop and at every turn of the loop I'm selecting the 5 next child elements and wrapping them in a div using the .wrapAll() function. Hope this helps.
Related
I have several div elements with incremental IDs (e.g. div0, div1, div2 (I know this is bad practice - I'm developing a dynamic CSV-to-HTML converter for Outlook calendar exports)) and I'd like to switch between them using jQuery linked to forward/back buttons . What I'm trying to do is as follows (in meaningless pseudo-code):
int pos = 0
forward.onclick
hide ("#div"+pos)
pos++
show ("#div"+pos)
back.onclick
if pos != 0
hide ("#div"+pos)
pos--
show ("#div"+pos)
Since I know next to nothing about jQuery, my questions are 1. What would the syntax be for implementing the above example (assuming I'm on the right track), and 2. Is there a way in jQuery to somehow check for an upper boundary so the counter doesn't increase above the number of divs?
If you want to know how many divs you have in jQuery, select them and take the length of your selection:
$('.div').length
You could even just use that selection to cycle through which divs to show:
var $divs = $('.div');
var upperLimit = $divs.length - 1;
var index = 0;
// on arrow click
$($divs[index]).hide();
index++ (or index--, depending on the arrow)
$($divs[index]).show();
int is not a data type in JavaScript. Use var. Declaration would be var pos = Number(0). To prevent exceeding the boundaries of number of divs, declare a variable with the number of divs you have, and inside your hide and show calls, use pos℅divLength instead of pos. Suppose you have total divs as 4, you will never exceed div3 this way. It will iterate from div0 to div3. Refer this to learn how to use show and hide methods.
Here's a demo.
var index = 0;
$('#div' + index).show();
$('#next').click(function () {
index++;
$('#back').prop('disabled', false);
if (index === fakeData.length - 1) {
$('#next').prop('disabled', true);
}
$('.items').hide();
$('#div' + index).show();
});
$('#back').click(function () {
index--;
$('#next').prop('disabled', false);
if (index === 0) {
$('#back').prop('disabled', true);
}
$('.items').hide();
$('#div' + index).show();
});
The above code will disable and enable the next and back buttons based on whether you are at the beginning or the end of your list of data. It hides all elements and then shows the specific one that should be shown.
Working on the div's. I am doing changes that if one div is selected, it should deselect the another div.
The div's defined are in ul li
Like in every li, there is a div with same classname called as inonset. Now the div which is already selected is having a class of inonset isactive.
I am adding a onclick function on every <div class="inonset" onclick="selectme(divid)"> to select it and unselect other, but how the other will be unelected, I am lost
Here is the fiddle
Not have not added the javascript code yet, but from the code, it will clear what I am trying to do.
You will see initially one selected and others are there, i just trying to selected any other one and deselect the previous one, Hope my questions makes sense
Worst thing: I cannot use Jquery, Only Dojo or Plain Javascript
Update #1
<div class="optionsBox" align="left" id="Invoicing" onclick="chooseDiv(this);">
function chooseDiv(oObj){
var d = document.getElementsByClassName("ul li div");
alert(d.className);
It is giving me undefined and not looping over the classes
the div is having classes like
iv class="headerSelected isactive">
where isactive needs to be removed from the previous selected div and add to the newly selected Div
First u need to change on click event for this:
onclick="selectme(this)"
And then in function:
function selectme(oObj){
var d = document.getElementById("ul li div");
d.removeAttribute("class");
oObj.className = oObj.className + " otherclass";
}
It should work fine
I am not sure whether the answer is still required or not. However, posting my approach of doing it.
function removeClass(className) {
// convert the result to an Array object
var els = Array.prototype.slice.call(
document.getElementsByClassName(className)
);
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
el.className = el.className.replace(
new RegExp('(^|\\s+)' + className + '(\\s+|$)', 'g'),
'$1'
);
}
}
var elements = document.getElementsByClassName("inoneset");
for (var i = 0; i < elements.length; i++) {
(function(i) {
elements[i].onclick = function() {
removeClass("isactive");
//this.setAttribute("class", this.getAttribute("class") + " isactive");
var headerElem = this.getElementsByClassName("headerSelected")[0];
headerElem.setAttribute("class", headerElem.getAttribute("class") + " isactive");
var addressElem = this.getElementsByClassName("selDelAddress")[0];
addressElem.setAttribute("class", addressElem.getAttribute("class") + " isactive");
var footerElem = this.getElementsByClassName("footerSelected")[0];
footerElem.setAttribute("class", footerElem.getAttribute("class") + " isactive");
};
})(i);
}
Fiddle - http://jsfiddle.net/38nv5rft/18/
Reasoning
As you can see, there is a remove class function, that removes the class from the elements in the document. One can update it as per the requirement.
Then the main logic, which gets all the elements, iterate on them and bind the click function.
In click function, we are removing the inActive class from every element and then for current block, adding inActive class. Please note, as per the fiddle, I did not find the class on inoneset elements being updated, hence, commented out the code.
Important Point
Click event bubbles, hence, click on elements with showDelete and showDialog click functions will bubble the event to click event of inoneset i.e. click handler of inoneset will also be triggered. In order to stop the propagation of event to it, use event.stopPropogation() in showDelete and showDialog functions.
i'm building a webpage where many span needs to be transitioned from one class to another to create a bg-color fadein effect. Distribution of elements of same classes is mixed through the page, but they are all grouped under common classes.
I want to create a behavior that does the following: when you click any elements of class-n, the other elements of that class transitions, with the clicked element acting as the starting point.
This is mostly figured out, thanks to some help on SO; see the jsfiddle.
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
console.log(itemThread);
});
function colorThread($div, tId) {
tId = '.'+tId;
$div.toggleClass('div-clicked');
setTimeout(function () {
(function togglePrev($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
togglePrev($div.prev(tId));
}, 100);
})($div.prev(tId));
(function toggleNext($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
toggleNext($div.next(tId));
}, 100);
})($div.next(tId));
}, 100);
}
However, I am still struggling around a particular issue: I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating. If the jsfiddle, that would translate in all of the same color div to transition, regardless of their placement in the DOM tree.
In my togglePrev/toggleNext function, I have tried something along
if($div.hasClass(".classToTransition"))
{
$div.toggleClass(".div-clicked");
}
but couldn't get it to work properly (it doesn't ieterate to the next elements). There is something that I can't seem to grasp in the structure of that conditional. Anyone has a lead?
You really did manage to complicate something that should be pretty simple ?
$(".div").click(function () {
var coll = $('.'+this.className.replace(/(div-clicked|div)/g, '').trim()),
idx = coll.index($(this).toggleClass('div-clicked'));
$.each(coll, function(i) {
setTimeout(function() {
if (idx + i <= coll.length) coll.eq(idx + i).toggleClass('div-clicked');
if (idx - i >= 0) coll.eq(idx - i).toggleClass('div-clicked');
},i*200);
});
});
FIDDLE
It gets all the elements with the same class as the one currently clicked, and the index of the currently clicked, and then just adds and subtract 1 to the current index to get the next and previous elements. The checks are to make sure it stops when it reaches the end.
I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating
You might want to use nextAll(tId).first()/prevAll(tId).first() to select the next to-be-toggled element: http://jsfiddle.net/35uNW/4/. .next() does only look at the next sibling, and if that doesn't match your tId selector, no element will be selected.
If you want to iterate the different-classed elements so that you wait for each one, but don't want to toggle it, you can use your if-condition but you must remove the tId selector from the next()/prev() calls: http://jsfiddle.net/35uNW/3/.
This was a fun one. I did it a slightly different way, getting all of the matched elements and splitting them into before and after arrays.
var $allItems = $(".div");
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
});
function colorThread($div, classname) {
var tId = '.'+classname,
$divs = $allItems.filter(tId),
index = $divs.index($div),
$before = $divs.slice(0, index),
before = $before.get().reverse(),
$after = $divs.slice(index+1);
$div.toggleClass('div-clicked');
$(before).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
$($after).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
}
Here's a working fiddle: http://jsfiddle.net/5sUr4/
I have a function that is successful in removing an element and appending it elsewhere on the page as successful. The problem is that as soon as the document is ready jQuery adds classes and attributes to the children that upon moving are lost. I need these classes and attributes to remain after removing and appending. I have thought about calling the original function that adds the classes, but the problem is they are key based and rely on their position prior to the move, calling it after changes the key and thus will add brand new and different classes.
The classes adding jQuery is pretty standard:
$(function(){
$("div").each(function(key){
if ($(this).hasClass("container")){
$(this).find("ul").addClass("parent" + key);
$(this).find(".container-item").attr("parentClass", ".parent" + key);
};
});
});
The remove/append function:
function copy_item(draggable, target){
var account = clone_items(draggable);
//$('#'+name.uid).remove();
$('#'+name.uid).hide();
target.append(make_div(name, true, true));
//$(draggable).children().attr("class", ($(draggable).children().attr("class")));
}
function make_div(name, drag, drop){
var newdiv = document.createElement('div');
newdiv.setAttribute('id', name.uid);
newdiv.appendChild(make_h3(name.username));
ul = document.createElement('ul');
ul.setAttribute("class", "domain_list");
newdiv.appendChild(ul);
for (j = 0; j < name.domains.length; ++j) {
ul.appendChild(make_li(name.domains[j], drag));
}
return newdiv;
}
The end result in the HTMl is basically:
<div class="container">
<ul class="parent0">
<li parentClass="parent0">
<li parentClass="parent0">
When recreating this structure, I need to have the class "parent0" and the parentClass attribute intact. Above you can see I've tried hiding the element, ensuring that it still stays a valid element with the correct classes/attributes, but in the end that still didn't work out. Ideally, I could remove the element entirely and recreate it with the correct classes.
If I am correct in my understanding of what you are trying to do, you do not need to .remove() and recreate the element in order to move it. You can just do this:
function copy_item(draggable, target) {
// not sure what this variable is for
// as you don't seem to be using it?
var account = clone_items(draggable);
// ...however, appending an existing
// element to another will 'move' it
// and preserve all of it's properties
target.append($('#' + name.uid));
}
I'm developing an application with javascript. What I need is to have divs with id's (1,2,3...) and be able to insert a div between, for example, 2 and 3, with jquery, and then have that be the new three, and three becomes four, four becomes five, etc. I've got the div insertion working, I just need to know how to reorder the divs. Any ideas?
After you inserted the new div, you can do this:
var i = 1;
$('div').each(function() {
$(this).attr('id', i++);
});
Replace $('div') by your own selector.
Remember also that, depending on which version of HTML you use, id's can't start with a number.
You can't start IDs with a numeric value, but regardless of that you'd do something like
// set a data value in the div you have just inserted into the dom and set a variable theID to the current ID you have just inserted.
$(this).data('inserted', true);
var theID = $(this).attr('id'); // this will be 3.
// now to update the other divs.
$('div').each(function() {
if($(this).attr('id') >= theID && !$(this).data('inserted')){
$(this).attr('id', $(this).attr('id') + 1);
}
});
// now set the data inserted to false for future updates
$('div#3').data('inserted', false);
$(function() {
reorder();
$('#click').click(function() {
$('<h2>hello world blah!</h2>').insertAfter('.content h2:eq(1)');
reorder();
});
});
function reorder() {
$('.content h2').each(function(i) {
$(this).attr('id', 'order_'+(i+1));
// alert( parseInt(this.id.split('_')[1]) ); // this is the id #
});
};
I'm pretty sure that you get things back in DOM order from jQuery selectors, so couldn't you just find the parent element, select the child <div> elements, and then .each() through the list?