new here and deeply hoping I'm not missing a stupid syntax flaw. I was thinking that my problem is a fairly common one, but somehow nothing has helped so far in my specific case.
There is a simple inline-block list of Image Galleries which are zoomable to fill the parent width. As soon as one is zoomed through click on a child, the others should unzoom by stripping of the class which maximizes them. Nothing more to it.
I achieved the first part via the following jQuery (where the problem is hidden in the for-loop, I think):
$(".zoom").click(function() {
var target = $(this);
target.closest('div.product-item').toggleClass('maximized');
var ot = document.getElementsByClassName('product-item');
for (var i = 0; i < ot.length; i++) {
if (ot[i] !== target) {
ot[i].removeClass('maximized');
}
}
});
So: Some .zoom classed element is clicked, its parent is toggled to maximize and a for loop checks all other elements of the same class as the parent and removes the .maximized class.
The reason the script is constructed with a for-loop and a removeClass is so that the same .zoom elements are able to minimize their parent elements, not only to maximize them.
Im not a javascript professional, but to my knowledge this should work in principle. Am I missing anything here?
This post from a year ago addressed a similar problem but didn't help in my case: jQuery onClick: How to add class to element and remove from all others
You can find a pen to see the script in action here.
$(".zoom").on('click',function() {
var target = $(this);
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').toggleClass('maximized');
});
you can use
if(target.closest('div.product-item').hasClass('maximized')){
$('div.product-item').removeClass('maximized');
}else{
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').addClass('maximized');
}
JSFIDDLE
Related
I need a little bit of help with my shopify store. I'm trying to change the class of a button in order to style it from the default class "btn" to "askAQButton". However, the code for the buttons are not in the markup at all and so I can only assume they're generated by JS by the shopify plugin itself.
I figured it should be simple and I should be able to just target the element by "id" with jquery and change class. However, the button doesn't have an ID and neither does the href...
My next thought was okay, target the parent div by id, then target the class of the button and href and change it that way (to avoid targeting duplicate classes).
I just can't seem to get it working.
Here is all the markup I'm given to implement this onto my store page:
Obviously a lot of it is irrelevant (probably all of it besides the parent div) however, when I load my page up after implementing this code it auto-generates this right under the second input:
<div class="wk-ask-order">
<button class="wk-ask-a-question-order btn" style="display: inline-block;">Raise a Query
</button>
View Your Queries
</div>
Can anyone help me with targeting it and changing the class names please.
I'm not sure if I get the question right, but there might be a problem with the button having not yet been injected into the DOM at the time when your script is targeting it.
Try waiting for the DOMContentLoaded event before executing your code:
document.addEventListener('DOMContentLoaded', () => {
const askAQBtn = document.querySelectorAll('.wk-ask-a-question-order')[0]; //there's probably a better selector
askAQBtn.classList.replace('btn', 'askAQButton');
});
If that doesn't work, have a look at MutationObserver to wait for the specific element to exist. I found a snippet for this on Github:
https://gist.github.com/jwilson8767/db379026efcbd932f64382db4b02853e
This was my answer it's a bit lo-fi but I hope it gives you something to work from. I followed your idea regarding the parent div id.
let parent = document.getElementById('wk-askme');
let child_nodes = parent.childNodes;
for (let i = 0; i < child_nodes.length; i++) {
let item = child_nodes[i];
if ($(item).attr('class') == "wk-ask-a-question-order btn") {
$(item).attr('class', 'wk-ask-a-question-order askAQButton');
}
}
So currently in class we are trying to make a 15-puzzle using ONLY Javascript, CSS, and basic HTML. I am also not allowed to modify the html at all, fun stuff. Anyway, I was able to add dynamic class names to my html and reference them in the css as follows:
var children = document.getElementById("puzzlearea").childNodes;
//iterates through all children
for (child in children) {
//if children is a div then we do something to it
if (children[child].nodeName == "DIV") {
//add a class that corresponds to a css to the current div child that we are on
children[child].classList.add('a' + i);
i = i + 1;
}
}
In our CSS then we are able to reference it by simply stating .a15 and assigning it the required margin, size, image positioning, and all. However, when I try to move it by referencing its id using document.getElementById(".a15").style.top = "200px" -- or just "a15" -- it does not work. The above mentioned way is the suggestions I have seen on stack in order to move divs.
Currently I am trying something as follows:
document.getElementsByTagName('div')[15].onclick = function () {
alert("work"); //does actually only happen on correct div
this.style.top = "500px" //still doesn't move it
}
However, with this it still does not move it, and of course fetches all divs. As such, the question still stands: "How to move divs with dynamically added class names?
Edit: Got it to move by also mentioning that the position should be relative in the CSS, however I can still only reference it in the above mentioned way and not via direct iD.
You are adding class to those div(s), so when you are referencing them instead of:
document.getElementById(".a15").style.top ...
it should be:
document.getElementsByClassName("a15").style.top ... // without .
Note that getElementsByClassName returns array of elements which has that certain class. So you may have to do something like
var currentDiv = document.getElementsByClassName("a15")[0] // assuming you have only one div with class a15
// then
currentDiv.style.top ...
working example just in case: https://jsfiddle.net/Laf54y1a/3/
I am trying to select all the elements of a page except one, inside a function:
$('#sidebutton').click(function () {
if (!$('.sidemenu').hasClass("current")) {
prevScrolPos = $(window).scrollTop();
scrollTo = 0;
} else {
scrollTo = prevScrolPos;
}
$('.hidelem').toggleClass("hidden");
$('.sidemenu').toggleClass("current");
$('html,body').scrollTop(scrollTo);
});
It works when I use a simple class selector (.hidelem), but doesn't when I use something a bit more complicated (for example, $("*:not(.sidemenu)").toggleClass("hidden"); or $("*").not(".sidemenu").toggleClass("hidden");); these just lead to a blank window.
Could you tell me what I'm missing here?
JSFiddle: https://jsfiddle.net/et978wjw/5/ (full functionality is missing but I hope you get the idea)
The problem is that you may be skipping .sideMenu with $("body *:not(.sidemenu)"), but you are not skipping its parent DIV. If you hide an ancestor, you hide all its descendants too. You also do not skip any descendants, so the children of .sidemenu are also hidden
So you need to exclude anything that is an ancestor of .sidemenu with :not:(has()), then exclude the sidemenu itself, then exclude any children of sidemenu:
$("#container :not(:has(.sidemenu)):not(.sidemenu):not('.sidemenu *')").toggleClass("hidden");
JSFiddle: https://jsfiddle.net/TrueBlueAussie/et978wjw/8/
You really should direct the hide/show at something more specific though. Perhaps a wrapper div around everything you want hidden? I added one for the demo.
Now having said all that, your selection process is quite complicated. You would be better off simply adding a class to all the things you want to toggle instead and just toggle those (you already have nodisplay on the divs, so I used that for now).
e.g. just this:
$(".nodisplay").toggleClass("hidden");
JSFiddle: https://jsfiddle.net/TrueBlueAussie/et978wjw/9/
I was wanting to have a javascript (jQuery) function that removed everything that didn't have the safe class.
The problem is, if the parent element is hidden, it cannot show the 'safe' part of it.
Is there a simple way to get around this? I'd rather not go in and span all of the elements that need removed.
trimmer = function(element){
x = $(element+' *:not(.safe)');
x.hide();
}
trimmer('section');
Fiddle
var element = 'section';
//finds all non `.safe` elements in `section`s and hides them
$(':not(.safe)', element).hide();
//finds all `.safe` elements in `section`s and shows the `section`s
$('.safe', element).parents(element).show();
Horen was right, it is indeed impossible to show parts of a hidden element.
To make only parts of the text disappear, the non-safe content must be labeled for removal.
$(element).contents().each(function() {
if (this.nodeType == 3)
$(this).wrap('<span class="disappear" />');
});
You can read more about this answer here:
How to add spans to all areas of a node that isn't restricted
I have a page generated by Yii CListView which contains a div andmultiple child divs.I need to access a specific the child div and add one more div into that.
Although I managed to solve it using one approach but dont think its the right one. Following is the overview of my solution (the code below does not contain all necessary variables declarations and other stuff, I have pasted the core code not the complete.):
Accessed the parent div by Id (Since the Id was available as I can
code this into Yii)
Obtained all the elements in this div using :
var div_childern = document.getElementById('StudentGridViewId').getElementsByTagName('*');
Iterated through and when reached to the desired div, added my new div. Please note that the div in which I want to add new div has the class name as "items". Code as below:
for (var i = 0; i < div_childern.length; i++) {
if (div_childern[i].getAttribute('class')=='items'){
document.getElementById('StudentGridViewId').getElementsByTagName('*')[i].appendChild(newdiv);
i=div_childern.length+1;
}
}
The only problem in this solution is, I am accessing the whole document twice, the call to getElementsByTagName. First to obtain the list of all items and then again to add my new div. Is there a better way to this ?
and also, could anyone point me to set the Id of the "items" div that Yii generates?
Thanks
Faisal
You might be able to get a much more elegant solution if you use JQuery.
But, if you want to use the traditional javascript, here is what you could do
for (var i = 0; i < div_childern.length; i++) {
if (div_childern[i].getAttribute('class')=='items'){
div_childern[i].appendChild(newdiv);
i=div_childern.length+1;
}
}