i've got this function as per below:
$(".selectedItems").on('click', '.deleteItem', function (event) {
$(this).parent().remove();
if ($(this).parent('.selectedItems').children().length === 0) {
alert('hello');
}
});
in conjunction with the following html:
<div class="selectedItems">
<div class="item">
</div>
<div class="item">
</div>
</div>
<div class="selectedItems">
<div class="item">
</div>
<div class="item">
</div>
</div>
The problem is that the size is always showing up as 0 regardless and my if statement keeps on triggering, i been looking at this code for a while.. im not sure about what can be the problem.
You can find a link to the jsfiddle here: http://jsfiddle.net/kmcbride/UpGgQ/6/
As mentioned in comments, you have already removed the element and therefore $(this).parent() no longer refers to anything.
Try storing the parent first:
var $parent = $(this).parent(), $selItem = $(this).parents(".selectedItems");
$parent.remove();
if( $selItem.children().length === 0) {
alert("Hello!");
}
Updated Fiddle
change the selector like this,
$(this).parents('.selectedItems').children().length
also you are removing the parent $(this).parent().remove();.
change that too
Demo
You need to first save a count of how many items there are before you remove the item from the DOM. Otherwise the reference to the DOM is lost.
http://jsfiddle.net/thinkingmedia/zXnDa/
$(".selectedItems").on('click', '.deleteItem', function (event) {
var count = $(this).closest(".selectedItems").find(".item").length;
$(this).closest(".item").remove();
if (count == 1) {
alert('hello');
}
});
Related
I have the following function that refreshes its data as follows
refresh: function($contentholder) {
$contentholder.each(function() {
$this = $(this);
if ($this.hasClass("Codes")) {
//then it does some stuff in here
}
}
}
the $contentholder comes in with data as follows
<div class="Codes" cod="t592">
<h3></h3>
<div class="Items">
<div class="ItemCodes" id="592" time="2016/04/30 12:15" places="1"></div>
</div>
</div>
The only way my if-statement gets detected, is if I check it as follows $this.hasClass("Codes"), but I only want the if-statement to get executed if the hasClass("codes") contains the class ItemCodes
This is what I tried but doesn't work
if ($this.hasClass("Codes").length > 0) //comes back undefined even though there is data
if ($this.hasClass("ItemCodes"))` //doesnt get detected
Basically, I want to do something like this
if ($this.hasClass("Codes").find("ItemCodes"))
How do I achieve this?
You can use find() to determine if there was any child .ItemCodes elements. You will need two separate conditions as these statements cannot be combined.
refresh: function ($contentholder) {
$contentholder.each(function () {
$this = $(this);
if ($this.hasClass("Codes") && $this.find('.ItemCodes').length) {
// do some stuff in here
}
}
}
You can use .is() method combined with :has() pseudo selector as follows:
if ( $this.is('.Codes:has(".ItemCodes")') ) {
//
}
let $that = $('div.Codes');
console.log( $that.is('.Codes:has(".ItemCodes")') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Codes test me" cod="t592">
<h3></h3>
<div class="Items">
<div class="ItemCodes" id="592" time="2016/04/30 12:15" places="1"></div>
</div>
</div>
So I have this HTML:
<div class="tip-box">
<div class="tip-title" onclick="toggleTip()">
<h2>Tip 1</h2>
</div>
<div class="tip-content hidden">
<p>Tip 1 content</p>
</div>
</div>
And this Javascript:
function toggleTip() {
$(this).siblings(".tip-content").toggleClass("hidden");
}
Hopefully it's obvious what this is supposed to do, but it doesn't work. Using .siblings() just doesn't seem to work in this way.
What's the correct solution for this? To get the next sibling of a certain type or with a certain class and then hide/show it?
You can use Jquery function.
<div class="tip-box">
<div class="tip-title">
<h2>Tip 1</h2>
</div>
<div class="tip-content hidden">
<p>Tip 1 content</p>
</div>
</div>
$(document).ready(function(){
$('.tip-title').click(function(){
$(this).siblings(".tip-content").toggleClass("hidden");
});
});
you can also use this
<div class="tip-box">
<div class="tip-title" onclick="toggloTip(this)">
<h2>Tip 1</h2>
</div>
<div class="tip-content hidden">
<p>Tip 1 content</p>
</div>
</div>
<script>
function toggloTip(elm) {
$(elm).siblings(".tip-content").toggleClass("hidden");
}
</script>
You can use pure javaScript with nextElementSibling property of node something like below,
I suppose you want do this operation with siblings.
function getChildrens(n, selector) {
var nodes = [];
while (n.nextElementSibling != null) {
if (n.nextElementSibling.hasOwnProperty('classList')) {
if (n.nextElementSibling.classList.contains(selector)) {
//return n.nextElementSibling;
nodes.push(n.nextElementSibling);
}
}
n = n.nextElementSibling;
}
return nodes;
};
function getSiblings(n, selector) {
return getChildrens(n, selector);
}
function toggleTip(elem) {
var siblings = getSiblings(elem, "tip-content");
if (siblings.length > 0) {
for (var i = 0; i < siblings.length; i++) {
siblings[i].classList.toggle("hidden");
}
}
}
.hidden {
display: none;
}
<div class="tip-box">
<div class="tip-title" onclick="toggleTip(this)">
<h2>Tip 1</h2>
</div>
<div class="tip-content hidden">
<p>Tip 1 content</p>
</div>
</div>
Here is another non JQuery answer.
To get the next element sibling use:
var nextElement = element.nextElementSibling;
To get the previous element sibling use:
var previousElement = element.previousElementSibling;
To get the element index use:
var index = Array.prototype.slice.call(element.parentElement.children).indexOf(element);
If you are at the first element the previousElementSibling value will be null.
If you are at the last element the nextElementSibling value will be null.
How about this JavaScript:
$(function(){
$('.tip-box').on('click', '.tip-title', function(){
$(this).next('.tip-content').toggleClass('hidden');
});
});
Remove the idea of working with onclick attributes when you use jQuery.
None of the previous answers, not even that serial-upvoted one ;), actually explains the problem and why their solutions work.
The problem is that an inline onclick handler does not pass on its current context. Inside the onclick="" JavaScript code this is the element clicked. Once you call a global function (like your toggleTip), that context is lost. The this the function receives is window and not the element.
The usual quick fix, for raw JavaScript code, is to pass this as a parameter to the global function.
e.g.
onclick="toggleTip(this)"
and receive a parameter in the function like this:
function toggleTip(element) {
$(element).siblings(".tip-content").toggleClass("hidden");
}
However, as you are using jQuery, inline event handlers are actually a bad idea. They separate the event registration from the event handler code for no reason and do not allow for multiple event handlers, of the same type, on the same element. They also bypass the rather cool event bubbling system jQuery uses.
The preferred alternative, with jQuery, is to use jQuery to select the element and jQuery to connect the event in one step:
jQuery(function($){
$('.tip-title').click(function(){
$(this).siblings(".tip-content").toggleClass("hidden");
});
});
As you only want the element that follows, and potentially will add more pairs, the better option would be using nextAll and first(), with the same jQuery filter, instead of siblings:
e.g.
jQuery(function($){
$('.tip-title').click(function(){
$(this).nextAll(".tip-content").first().toggleClass("hidden");
});
});
Or, of you can guarantee it is the next element, use next as #Tim Vermaelen did (with or without the selector makes no difference, so might as well leave it out):
jQuery(function($){
$('.tip-title').click(function(){
$(this).next().toggleClass("hidden");
});
});
Note: In this example jQuery(function($){ is a DOM ready event handler which is the rather handy shortcut version of $(document).ready(function(){YOUR CODE});, which also passes a locally scoped $ value. For those that mistake this code for an incorrect IIFE, here is a working example: http://jsfiddle.net/TrueBlueAussie/az4r27uz/
I want to add a specific DIV to other DIVs of a defined class. Because the page changes regularly I do this on every DOM-Change. This happens quite often and there are a lot of DIVs (up to a few 1000) that meet the criteria.
(This is an extension so I cannot modifiy the source)
I do it this way:
$('.Qg').each(function() {
if ($(this).parent().find('.quickShare').length === 0)
{
$(this).before('<div class="quickShare">(some more html)<br/></div>');
}
});
That works but does not seem to be very performant, mainly because of the "each" - Loop
Is there a more elegant (and especially performant) way to get only those DIVs which's parent do not contain my DIV (something like $('.Qg').parent().without('quickShare').each(function(){}); (pseudocode)?
Update: To make it clearer a DOM-Example:
<div class="anOuterDiv>
<div class="Qg">something here</div>
</div>
<div class="anotherOuterDiv">
<div class="quickShare">already added</div>
<div class="Qg">something here</div>
</div>
I want to Add the "quickShare" div before the "Qg", but only if it does not exist. (So I want to get the upper Qg, but not the lower Qg)
Give all the parents of .Qg the class QgContainer, then do:
$(".QgContainer:not(:has(.quickShare)) > .Qg").each(function() {
...
});
Since you can't change the site, try:
$(".Qg").filter(function() {
return $(this).siblings(".quickShare").length == 0);
}).each(function() {
...
});
As you wanted better(more perfomant) then you could consider using pure Javascript.
HTML
<div class="anOuterDiv1">
<div class="Qg">something here</div>
</div>
<div class="anOuterDiv2">
<div class="quickShare">already added</div>
<div class="Qg">something here</div>
</div>
<div class="anOuterDiv3">
<div class="Qg">something here</div>
</div>
<div class="anOuterDiv4">
<div class="quickShare">already added</div>
<div class="Qg">something here</div>
</div>
Javascript
Array.prototype.forEach.call(document.getElementsByClassName('Qg'), function (Qg) {
var parentNode = Qg.parentNode,
quickShares = parentNode.getElementsByClassName('quickShare'),
newQuickShare;
if(!quickShares.length) {
newQuickShare = document.createElement('div');
newQuickShare.className = 'quickShare';
newQuickShare.textContent = 'Newly added';
parentNode.insertBefore(newQuickShare, Qg);
}
});
On jsFiddle
Next we should actually compare it against some jQuery, so we will use the accepted answer.
$(".Qg").filter(function() {
return $(this).siblings(".quickShare").length == 0;
}).each(function() {
$(this).before('<div class="quickShare">Newly added</div>');
});
On jsFiddle
And now lets see how they perform on jsPerf
You can filter each .Qg that's not preceded by a .quickShare sibling and then apply .before() on that:
$('.Qg')
.filter(function() {
var node = this.previousSibling; // start with previous sibling
while (node) {
if (node.className == 'quickShare') {
return false; // we found one
}
node = node.previousSibling; // keep trying with previous sibling
}
return true;
})
.before('<div class="quickShare">(some more html)<br/></div>');
This time it will definitely work:
$('div:only-child.Qg').each(function(){
$(this).before('<div class="quickShare">(some more html)<br/></div>');
});
Try this. This is very easy and readable and small and performant.
jsFiddle Demo http://jsfiddle.net/VS6mG/
So I have a mini slide menu in my website there is a menu you can choose what you want to read. There are points to click, when u clicked it the point get a red background.
But there is a problem.
When i click one point and then an other point the first clicked point have to lose his background.
Here is my HTML:
<div id="slide_button" onClick="clicked(this);"><dir class="button_1"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_2"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_3"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_4"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_5"></dir></div>
Here is my JS:
function clicked(slide_button) {
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
HERE IS AN EXAMPLE ON FIDDLE.
My "QUESTION IS" what i have to do to solve that?
What should I pay attention?
First you need to fix your HTML becaue your id values aren't unique. In fact, you don't even need id values, so you should use "slide_button" as a class. You can then use it to select all the buttons:
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
The CSS needs to be changed now so "slide_button" is a class selector, instead of an id selector:
.slide_button {
display: inline-block;
}
As for clearing the background, clear all of them before coloring the selected one red:
function clicked(slide_button) {
var buttons = document.getElementsByClassName('slide_button');
for(var i = 0; i < buttons.length; i++) {
buttons[i].getElementsByTagName('dir')[0].style.backgroundColor = '';
}
slide_button.getElementsByTagName('dir')[0].style.backgroundColor = 'red';
}
jsfiddle
This uses just JavaScript with no JQuery, but if you are using JQuery, you might as well use it here. The code is a lot shorter and easier to follow.
Here's a JQuery version:
$(function() {
$('.slide_button').click(function() {
var $button = $(this);
$button.children(':first').css({ backgroundColor: 'red' });
$button.siblings().children(':first').css({ backgroundColor: '' });
});
});
Note: This registers a click-handler, so you can get rid of the "onclick" attirbutes.
jsfiddle
You have to select all other points and set their background to none.
Or remeber which point is selected and on select another just remove background on last and remeber current point, then set its background to red.
See fiddle: http://fiddle.jshell.net/399Dm/5/
At first id should be unique per element.
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
Second, you should store reference of clicked element if you want later remove background color, and instead of inline event handlers or binding all elements would be better if you use event delegation.
Demonstration
(function () {
"use strict";
// getting parent node of divs, due to bind click event. then
var ele = document.querySelector(".slide_button").parentNode,
prev = null; // store previous clicked element
ele.addEventListener("click", clickHandler); // event handler.
function clickHandler(e) {
var t = e.target; // get target of clicked element
// filter by target node name and class. edit: removed class checking
if (t.nodeName.toLowerCase() === "dir") {
// checking value of prev !== null and it's not same element.
if (prev && prev !== t) {
prev.style.backgroundColor = "";
}
prev = t; // store clicked element
t.style.backgroundColor = "red";
}
}
}());
I have fixed the fiddle so that it works hopefully as you plan.
http://jsfiddle.net/399Dm/8/ There you go!
var forEach = function(ctn, callback){
return Array.prototype.forEach.call(ctn, callback);
}
function clear(element, index, array) {
element.getElementsByTagName("dir")[0].style.backgroundColor="";
}
function clicked(slide_button) {
forEach(document.getElementsByClassName("slide_button"), clear);
//.style.backgroundColor="";
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
I had a slightly different method than #atlavis but a similar result.
http://fiddle.jshell.net/2AGJQ/
JSFIDDLE DEMO
jQuery
$('.slide_button').click(function(){
$('.slide_button dir').css("background-color", "inherit");
$(this).find('dir').css("background-color", "red");
});
HTML - Your markup is invalid because you have duplicate ids. Make them classes as below instead.
<div class="slide_button" >
<dir class="button_1"></dir>
</div>
<div class="slide_button">
<dir class="button_2"></dir>
</div>
<div class="slide_button">
<dir class="button_3"></dir>
</div>
<div class="slide_button">
<dir class="button_4"></dir>
</div>
<div class="slide_button">
<dir class="button_5"></dir>
</div>
CSS change
.slide_button {
display: inline-block;
}
If you can look at the following jsfiddle, I used jQuery to get what you want.
I've seen various examples come close to what I am looking for, but none of it seems to describe it how I exactly want it. I am a beginner to jQuery, so explanations welcome.
I'm looking for this to toggle the innerHTML from - to +. Anyone know of a way to do this, efficiently?
jQuery/JavaScript
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow");
$(".A1").html("+");
});
});
HTML
<div class="A1">-</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
Thank you, anything relating to switching the inside text of an HTML element shall help. =)
How about adding a class that will let you know the expanded/collapsed status?
$(document).ready(function() {
$(".A1").click(function() {
var $this = $(this);
$(".P1").toggle("slow")
$this.toggleClass("expanded");
if ($this.hasClass("expanded")) {
$this.html("-");
} else {
$this.html("+");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="A1 expanded">-</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
Example: http://jsfiddle.net/sGxx4/
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow");
$(".A1").html(($(".A1").html() === "+" ? $(".A1").html("-") : $(".A1").html("+")));
});
});
A bit of explanation: I'm setting $("#A1").html() with the product of the tertiary operator, using it to check for the current value of #A1's text. If it's a +, I set the element's text to -, otherwise, I set it to +.
However, you said "efficiently." To this end, it's important to note that if you're going to use a selector twice or more in the same function, you should store the jQuery object that results from the selector you give in a variable, so you don't have to re-run the selector each time. Here's the code with that modification:
$(document).ready(function() {
$(".A1").click(function() {
var $A1 = $(".A1");
$(".P1").toggle("slow");
$A1.html(($A1.html() === "+" ? $A1.html("-") : $A1.html("+")));
});
});
There's no way to toggle content.
You could check if the $('.P1') is visible, then changing the +/- div according to that.
Something like :
$(document).ready(function() {
$(".A1").click(function() {
$(".P1").toggle("slow", function(){
if($(this).is(':visible'))
$(".A1").html("-")
else
$(".A1").html("+")
});
});
});
Using a callback function (the second argument of the .toggle() method) to do the check will guarantee that you're checking after the animation is complete.
JsFiddle : http://jsfiddle.net/cy8uX/
more shorter version
$(document).ready(function() {
$(".A1").click(function() {
var $self = $(this);
$(".P1").toggle("slow", function ( ) {
$self.html( $self.html() == "-" ? "+" : "-");
});
})
});
Here's a way that uses class names on a parent and CSS rules and doesn't have to change the HTML content and works off a container and classes so you could have multiple ones of these in the same page with only this one piece of code:
HTML:
<div class="container expanded">
<div class="A1">
<span class="minus">-</span>
<span class="plus">+</span>
</div>
<h2 class="H1">Stuff</h2>
<div class="P1">
Stuffy, Stuffy, Stuffed, Stuffen', Stuffing, Good Luck Stuff
</div>
</div>
CSS:
.expanded .plus {display:none;}
.collapsed .minus {display: none;}
Javascript:
$(document).ready(function() {
$(".A1").click(function() {
$(this).closest(".container")
.toggleClass("expanded collapsed")
.find(".P1").slideToggle("slow");
});
});
Working demo: http://jsfiddle.net/jfriend00/MSV4U/