jQuery - Trouble with children - javascript

I have a container with several divs inside of it. Only one of the divs should should at a time. The container is essentially just a jQuery slider of divs. It should show and hide the next/prev div depending on which button you click, but it returns an error on the following line:
children[current--].show();
I'm not sure as to why this is happening. I am calling children (an array) then trying to access the index with an int--, then showing it, but it never shows.
Here is a jsFiddle: http://jsfiddle.net/n6fW7/1/
HTML:
<div id="container">
<div id="content">
<div id="prev" class="arrow">></div>
<div id="next" class="arrow"><</div>
</div>
</div>
jQuery:
$(function(){
$('#content').append('<div class="box"><p class="title">1</p><p class="text">abc</p></div><div class="box"><p class="title">2</p><p class="text">efg</p></div>');
var children = $('#content').find('.box');
var count = children.length;
var current = 1;
$('.box').not(children[0]).hide();
$('.arrow').click(function(){
var where = $(this).attr('id');
if(where == 'next'){
if(current != count){
current++;
}
}
else{
// previous
if(current > 2){
current--;
}
}
$('.box').hide();
children[current--].show();
});
});

Using the indexer in a jQuery object returns the raw DOM element, which does not contain the show() function. You can use the eq() function instead of the indexer, which returns a jQuery object wrapping the DOM element:
children.eq(current--).show();

Related

jQuery on click to check if it has a div with a certain class and then change the value of a different class

The code that i am writing is for an application where you select an icon and you get the css line displayed so you easily copy paste it and use it for another project. I'm having trouble with the $(this) selector. I have several divs with the "glyph-holder" class and it doesn't matter wich one I press, it always changes the "copy_text" div's value to the same class, the first one. I want it to change it to the div that i pressed.
The html that i have is:
<div id="copy_text">Select icon</div>
<div class="glyph-holder">
<div class="glyph">
<div class="icon-flip-horizontal"></div>
</div>
<div class="beschrijving-bij-glyph">
icon-flip-horizontal
</div>
</div>
The javascript that i currently have is this:
$(document).ready(function(){
var displayText = "Empty";
$(".glyph-holder").click(function(){
if($(this).has("icon-flip-horizontal")){
displayText = "icon-flip-horizontal";
}else if($(this).has("icon-flip-vertical")){
displayText = "icon-flip-vertical";
}
$("#copy_text").text(displayText);
});
});
Your selector in has() is missing the . prefix for the class. You also need to check the length property of the resulting jQuery object. Try this:
var displayText = "Empty";
$(".glyph-holder").click(function() {
if ($(this).has(".icon-flip-horizontal").length) {
displayText = "icon-flip-horizontal";
} else if ($(this).has(".icon-flip-vertical").length) {
displayText = "icon-flip-vertical";
}
$("#copy_text").text(displayText);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="copy_text">Select icon</div>
<div class="glyph-holder">
<div class="glyph">
<div class="icon-flip-horizontal"></div>
</div>
<div class="beschrijving-bij-glyph">
icon-flip-horizontal
</div>
</div>
You are targeting div by id so it will target only one div. You can get the copy_text div by the div using prev function.
$(document).ready(function(){
var displayText = "Empty";
$(".glyph-holder").click(function(){
if($(this).has(".icon-flip-horizontal")){
displayText = "icon-flip-horizontal";
}else if($(this).has(".icon-flip-vertical")){
displayText = "icon-flip-vertical";
}
$(this).prev().text(displayText);
});
});
You're not currently specifying that the has is looking for a class, also .has() returns a jQuery object and therefore .length should be used to test for the number of elements. Try this instead.
$(document).ready(function(){
var displayText = "Empty";
$(".glyph-holder").click(function(){
if($(this).has(".icon-flip-horizontal").length){
displayText = "icon-flip-horizontal";
}else if($(this).has(".icon-flip-vertical").length){
displayText = "icon-flip-vertical";
}
$("#copy_text").text(displayText);
});
});
Note, the . in .has(".icon-flip-horizontal") is important since it's referencing a class.

How to to make element move to another element then when click, return to previous position in JQuery?

Objective
What method to use to make item 3 move to another container.
Then if click again return the item to previous position
this function should be apply to all items.
Jquery
$('#item3').click(function(){
// What method to use to make item_1 move to another container.
// Then if click again return the item to previous position
});
Check DEMO
HTML
<div id="start">
<div class="element">one</div>
<div class="element">two</div>
<div class="element">three</div>
</div>
<div id="target"></div>
jQuery
$('.element').click(function() {
var cont = $(this).parent().attr('id');
if (cont == 'start') {
var place = '#target';
} else {
var place = '#start';
}
$(place).append($(this));
});
you can use drag and drop plugin of jquery UI.
if you cont want use this then you can try this code by onClick finction....
.JS
function onclickIteam(iteamId){
var x = if('#iteamId').html();
if(if('#iteamId').parent().prop("id") == "my_inventory"){
//$('#iteamId').detach();
$('#server_inventory').append(x);
}else{
//$('#iteamId').detach();
$('#my_inventory').append(x);
}
`}`

Deleting all div children from a parent without a for loop in javascript

I have the following code in my javascript:
for (var a = 0; a < cnt; a++) {
var element = document.getElementById("button" + a).getElementsByTagName("div");
for (index = element.length - 1; index >= 0; index--) {
element[index].parentNode.removeChild(element[index]);
}
$("#button" + a).append("Some large html data");
}
I am deleting all the children from parent id "button0","button1"... and so on, which are divs.
and then appending new data to those parents.
However, this particular piece of code takes a long time to execute when the cnt is more than 200, which it usually is. How will I be able to speed it up? Is there an alternative way to delete all children divs without going through each of it?
<div class="main">
<p>hello p1</p>
<p>hello p2</p>
<span> hello world this is span </span>
</div>
$('.main p').remove(); // any number of depths
$('.main > p').remove(); // immediate children
Try this : You can use children selector to remove them, no need to iterate through children.
for (var a = 0; a < cnt; a++) {
//remove div elements inside button
$("#button"+a+" > div").remove();
$("#button" + a).append("Some large html data");
}
DEMO
IF you can have particular class to button div then you can get rid of for loop.
Lets say class="buttonDiv" is assigned to all button div, for example
<div id="button0" class="buttonDiv">
Now your jQuery script to remove child div will be like
$('div.buttonDiv').each(function(){
$(this).children("div").remove();
$(this).append("Some large html data");
});
DEMO with Class
You can use jQuery to delete them, but I don't know how much faster it will be. Under the covers it has to do pretty much the same work:
for (var a = 0; a < cnt; a++) {
$("#button" + a + " div").remove().end().append("Some large html data");
}
It would be much easier if you just add one class to all the buttons you want to remove the children of. Lets say you add the class button to all of them. Then you could just do this:
$('.button > div').remove(); // Removes all direct children divs of the .button element.
Or
$('.button div').remove(); // Removes all divs inside the `.button` element.

How to find element of div from another div

I have the elements in the div as mentioned below:
<div id="container">
<div id="first_div">
<div id="comment-1" class="comment">Child 1 of first div</div>
<div id="comment-2" class="comment">Child 2 of first div</div>
<div id="comment-3" class="comment">Child 3 of first div</div>
<div id="comment-4" class="comment">Child 4 of first div</div>
</div>
<div id="second_div">
<div id="comment-5" class="comment">Child 1 of second div</div>
<div id="comment-6" class="comment">Child 2 of second div</div>
<div id="comment-7" class="comment">Child 3 of second div</div>
<div id="comment-8" class="comment">Child 4 of second div</div>
</div>
<div id="third_div">
<div id="comment-9" class="comment">Child 1 of third div</div>
<div id="comment-10" class="comment">Child 2 of third div</div>
<div id="comment-11" class="comment">Child 3 of third div</div>
<div id="comment-12" class="comment">Child 4 of third div</div>
</div>
I need to retrieve the next element from comment id comment-4.
$('#comment-4').next().attr('id') gives me result as undefined.I need the target div to be comment id - comment-5.How to retrieve the next element of div from another div using jquery?
Try this :
$(function(){
$('.comment').click(function(index){
var id;
if ( $(this).is(':last-child') )
id = $(this).parent().next().children(':first').attr('id');
else
id = $(this).next().attr('id');
alert(id);
});
});
Demo
Demo : http://jsfiddle.net/abdennour/PU54r/
function nextOf(id,cyclic){
var ids= $('div[id^=comment-]').toArray().map(function(e){return $(e).attr('id')}).sort();
var idx=ids.indexOf("comment-"+id);
if(idx!==-1){
if(ids.length> idx+1){
return $('div#'+ids[idx]);
}
else{
// it is the last div: if it is cyclic ,you may return the first
if(cyclic){
return $('div#'+ids[0]);
}
}
}else{
// no div with this id
}
}
Then :
var target=nextOf(4)
if(target){
target.html()
//--> Child 1 of second div
}
I think you can use $('.comment') to pick up all of your wanted, and save them in some variable such as var arrResult = $('.comment');.
So far, you can choose what you wanted use the arrResult variable.
Because your inner-most divs have different parents, I would first get all the divs you care about:
var comments = $('.comment');
Next, if we can assume your id's are all numbered sequentially, get the number in the id (assuming this references the element):
var index = parseInt($(this).attr('id').substr(8));
Now, the next div in the comment list is at that position in the comments:
var nextDiv = comments[index];
Just for good measure, I'd first make sure index is set:
var nextDiv;
if (index < comments.length) {
nextDiv = comments[index];
}
You could use an index in your case :
JS:
for (var index = 0; index <= 12; ++index) {
$("#comment-" + index).attr("id");
}
You can define a statement which checks the target id is the last child, than you can return a function according to value.
jsFiddle Demo
var target = 'comment-4';
$('.comment').each(function(i) {
if ( $(this).attr('id') == target ) {
if ( $(this).is(':last-child') ) {
$(this).parent().next().children().first().addClass('red');
}else{
$(this).next().addClass('red');
}
}
});
Here is one way - http://jsfiddle.net/jayblanchard/WLeSr/
$('a').click(function() {
var highlight = $('.highlight');
var currentIndex = $('.comment').index(highlight); // get the index of the currently highlighted item
$('.comment').removeClass('highlight');
var nextIndex = currentIndex + 1;
$('.comment').eq(nextIndex).addClass('highlight');
});
It is showing undefined because comment-4 and comment-5 are childrens of different parent elements. Means comment-4 is children of first_div and second_div parent of comment-5.
You can get the comment-5 using below code.
$('#comment-4').parent().next().children().attr('id');
Assuming jQuery-wrapped element is collected in $comment, there's one way to solve it:
function getNextComment($comment) {
var $nextComment = $comment.next();
if ($nextComment.length) {
return $nextComment;
}
var $nextParent = $comment.parent().next();
if ($nextParent.length) {
return $nextParent.children().first();
}
return null;
}
Demo. Click on one comment - and see the next one's highlighted. )
The base algorithm's very simple here. First, we attempt to retrieve the next sibling of the given element. If there's one, it's returned immediately. If not (and it's the case with #comment-4 in your question - it's the last element in its hierarchy), we go up the DOM chain for its parent (#first-div, in this case), and look for its next sibling (#second-div). If it exists, then its very first child element is returned. If it doesn't, null is returned (we can actually return an empty jQuery object - $(), but that depends on use cases.
Just one instruction : )
$('<div id="mock" />').append($('.comment').clone()).find('#comment-4').next().attr('id')//---> comment-5
Based on divs have the same Css class .comment
DEMO
Why not this will be undefined: $('#comment-4').next().attr('id') because there is no next element. as you mentioned that you want to target the #comment-5 in the next div's child then you can do this:
function giveId(el) {
var sel = el.id ? '#'+el.id : '.'+el.className;
var id = $(sel).next('div').length ? $(sel).next('div').attr('id') : $(sel).parent('div').next('div').find('> div:first').attr('id');
return id || "Either no next elem exist or next elem doesnot have any id/class.";
}
$(function () {
$('div').click(function (e) {
e.stopPropagation();
alert(giveId(this));
});
});
Updated Demo in action
Try this: JSFiddle (The easiest solution!)
$(document).ready(function(){
var currDiv = $("#comment-4"); // Try with different valies: "#comment-x"
currDivId = currDiv.prop('id');
lastDivId = currDiv.parent('div').find('.comment').last().prop('id');
if(currDivId == lastDivId){
var nextComment = currDiv.parent('div').next('div').find('.comment').prop('id');
}else{
var nextComment = currDiv.parent('div').find('.comment').next().prop('id');
}
alert(nextComment);
});

Using :last-child and :first-child with jQuery

I'm trying to write my first self-built jQuery script, as a super simple gallery.
CSS:
#gallery li{
display:none;
}
#gallery li.current {
display: block;
}
HTML:
<div id="gallery">
<li class="current"><img src="img/1.jpg" /></li>
<li><img src="img/2.jpg" /></li>
<li><img src="img/3.jpg" /></li>
<li><img src="img/4.jpg" /></li>
</div>
<div id="controls">
<span id="left"><</span>
<span id="right">></span>
</div>
JQUERY:
$(function(){
$('#controls #left').click(function(){
var old = $('li.current');
$('li.current').removeClass('current');
if (old = $('#gallery:first-child')){
$('#gallery:last-child').addClass('current');
}else{
$(old).prev('li').addClass('current');
}
});
$('#controls #right').click(function(){
var old = $('li.current');
if (old = $('#gallery:last-child')){
$('#gallery:first-child').addClass('current');
}else{
$('li.current').removeClass('current');
$(old).next('li').addClass('current');
}
});
});
It worked fine until I added the if/else statements to check whether we're looking at the first/last gallery image. I want this statement so that the gallery loops. Can't figure out why it's not working, and debug is giving me nothing.
Can I get a little push in the right direction?
EDIT: using some suggestions below, here's where I'm at:
$(function(){
$('#left').click(function(){
var old = $('li.current');
old.removeClass('current');
if (old == $('#gallery li:first-child')){
$('#gallery li:last-child').addClass('current');
}else{
old.prev('li').addClass('current');
}
});
$('#right').click(function(){
var old = $('li.current');
old.removeClass('current');
if (old == $('#gallery li:last-child')){
$('#gallery li:first-child').addClass('current');
}else{
old.next('li').addClass('current');
}
});
});
Still isn't looping around though (pressing "left" on the first image makes the gallery blank, as does pressing "right" on the last image)
You might want to be using ==:
if (old == $('#gallery:first-child')){
and
if (old == $('#gallery:last-child')){
Although that won't work anyways, as pointed out by Jack, because they are separate jQuery calls that may select the same elements and return similar jQuery objects, but won't work with comparison because they are separate collections of DOM element(s). The correct way is to use .is like I provide below...or to compare with:
if (old[0] == $('#gallery:first-child')[0]){
Indexing them like that retrieves the first item each in the selected sets, which are the actual DOM elements, and can be compared. Probably not preferred, but its not wrong.
Here's an example of proving this is true: http://jsfiddle.net/4adSj/
You're also doing a few weird things. You don't need to use this selector: $('#controls #right') - $('#right') is unique enough thanks to how id should be used.
Also, you store var old = $('li.current'); and then the next line you don't bother using old - you re-get it like $('li.current').
Also, you are nesting <li> elements in a <div>, when they should only be nested in <ul>, <ol>, or <menu>.
One more - the variable old is a jQuery object, so you don't need to be doing $(old) every other time you want to access it after you declared it. Just use old.jQueryMethod().
Finally, the other problem is that your selector for the if statements:
$('#gallery:last-child')
Means find the element that has the id "gallery" and is a last-child. You probably want:
$('#gallery > li:last-child')
Which means find the child element that is the last li child element of the parent element with an id of "gallery".
So here's my suggestion of your final code to use:
$(function(){
$('#left').on("click", function () {
var old = $('li.current');
old.removeClass('current');
if (old.is(':first-child')){
$('#gallery > li:last-child').addClass('current');
} else {
old.prev('li').addClass('current');
}
});
$('#right').on("click", function () {
var old = $('li.current');
old.removeClass('current');
if (old.is(':last-child')){
$('#gallery > li:first-child').addClass('current');
} else {
old.next('li').addClass('current');
}
});
});
You can use .is(':first-child) and .is(':last-child') to find out if something is the first or last child respectively:
$('#controls #left').click(function() {
var old = $('li.current')
.removeClass('current');
if (old.is(':first-child')) {
// search the siblings for the last child
old.siblings(':last-child').addClass('current');
} else {
$(old).prev('li').addClass('current');
}
});
$('#controls #right').click(function() {
var old = $('li.current')
.removeClass('current');
if (old.is(':last-child')) {
old.siblings(':first-child').addClass('current');
} else {
$(old).next('li').addClass('current');
}
});
​
Btw, I would change your HTML to this:
<div id="controls">
<span class="left"><</span>
<span class="right">></span>
</div>
And then use $('#controls .left') and $('#controls .right') to target your clickable elements.
Edit
A fancier approach could be this, food for thought:
// wrap the functionality inside an anonymous function
// localizing the gallery and controls blocks
(function($gallery, $controls) {
var pos = 0;
// this function performs the actual move left and right, based on event data being passed in via evt.data.delta
function move(evt) {
var $items = $gallery.children(), // if the gallery never changes size you should cache this value
max = $items.length;
$items.eq(pos).removeClass('current');
pos = (pos + evt.data.delta) % max; // update the position
$items.eq(pos).addClass('current');
}
// attach the controls
$controls
.on('click', '.left', {
delta: -1 // left decreases the position
}, move)
.on('click', '.right', {
delta: 1 // right increases the position
}, move);
// make sure the first is always selected
$gallery.children().removeClass('current').eq(pos).addClass('current');
}($('#gallery'), $('#controls')));​​​​​​​​​ // immediate invocation
jsBin demo
var c = 0;
var imgN = $('#gallery li').length; // 4
$('#left, #right').click(function(){
c = this.id=='right' ? ++c : --c ;
$('#gallery li').hide().eq( c%imgN ).show();
});
Or even:
var c = 0;
$('#left, #right').click(function(){
$('#gallery li').hide().eq( (this.id=='right'?++c:--c) % 4 ).show();
});
gallery Demo
P.S: instead of .hide() you can use .removeClass('current')
and instead of .show() you can use .addClass('current')

Categories

Resources