I'm trying to get some divs with an id to randomize the order they appear in. I've found a script that supposedly will do this, but for the life of me, I can't figure out why mine isn't working.
Basically, when the page loads the HTML will read like this:
<div class="main">
<div id="box">1</div>
<div id="box">2</div>
<div id="box">3</div>
<div id="box">4</div>
</div>
But the code when applied will randomize the order in which they appear (in the browser), like so:
<div class="main">
<div id="box">3</div>
<div id="box">1</div>
<div id="box">4</div>
<div id="box">2</div>
</div>
And here is the javascript that supposedly is making it all work:
function reorder() {
var grp = $(".main").children();
var cnt = grp.length;
var temp,x;
for (var i = 0; i < cnt; i++) {
temp = grp[i];
x = Math.floor(Math.random() * cnt);
grp[i] = grp[x];
grp[x] = temp;
}
$(grp).remove();
$(".main").append($(grp));
}
I thought it was because I had an id property, but even if I strip that out and just make it a plain old div tag, it doesn't work :/
Here is the the like to a js fiddle of the code in question...
js fiddle
There are a few questions here similar to this, but they're all older topics, so I hope no one minds my making a new one. I'm still pretty new to javascript, if that isn't already obvious :D
Just change
<div class=".main">
<div id="#box">1</div>
<div id="#box">2</div>
<div id="#box">3</div>
<div id="#box">4</div>
</div>
to
<div class="main">
<div >1</div>
<div >2</div>
<div >3</div>
<div >4</div>
</div>
Two errors :
the ".main" which should be "main" as you look for $(".main").children().
the id "#box" that you were using for more than one element
In your fiddle, you also forgot to import jQuery.
Demonstration (click "Run with JS")
First, as was said before, ID should be unique, and they don't start with a #. The selector for ids uses a #.
Same for classes, they should start with a letter, only the selector uses a dot.
Now for your fiddle. You visibly use jQuery, here, so include jQuery on your fiddle, in the menu on the left.
Then, what you are doing in your fiddle is defining a function, but you never call it.
Just add a call to your function at the end of your code (that will be called by jsFiddle on load of the document, like this:
reorder();
Worked for me on your fiddle.
Related
I'm kind of a newbie to js, could someone have a look at this code and tell me if it is correct and if it could be improved and how? it is working as intended, but honestly I don`t know if it is well written. Thanks in advance (:
<script>
$(document).ready(function() {
$("button").click(function(event) {
var a = (event.target).classList.item(0);
var b = ".carousel" + "." + a ;
$(b).myfunction;
});
});
</script>
The reason for that script is that I have a Carousel (Bootsrap) inside a Slider ("JQuery lightSlider") inside a custom popup modal and I don`t want the imgs carousel to load at page start only when the carousel would be visible.
What the script does is to "store" the class name of the button element ("custom-n") clicked, then write .carousel.custom-x to be stored in the variable b, and then use the var b as a selector to call the function for that custom-n carousel that replaces data-src with src.
I hope this isn't confusing haha
This is a simplification of the html, the modal opens whenever a <button> is clicked.
The are kind of a "thumbnail" for the main slider (light-slider), so:
<button class="custom-1"> opens the modal and set the "light-slider" to slide n1
<button class="custom-2"> opens the modal and set the "light-slider" to slide n2
and so on.
The carousels inside the lightslider's slides they all have img with data-src and the Idea is to replace the data-src with src of the carousel that should be "related" to the custom
<div class="light-slider-buttons">
<button class="custom-1 myclass"></button>
<button class="custom-2 myclass"></button>
<button class="custom-3 myclass"></button>
</div>
<div class="modal-wrp">
<div class="modal-inner">
<ul id="light-slider">
<li>
<div class="slide-wrapper">
<div class="carousel custom-1">
<div class="carousel-inner">
<div class="carousel-item active">
<img data-src="...">
</div>
<div class="carousel-item">
<img data-src="...">
</div>
<div class="carousel-item">
<img data-src="...">
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
The code looks good.
I have two suggestions.
Firstly, you seem to be using class attribute to store data (custom-1, etc)
Why not set it to data-item-class attribute instead (any name starting with data- will do)?
<div class="light-slider-buttons">
<button class="myclass" data-item-class="custom-1"></button>
<button class="myclass" data-item-class="custom-2"></button>
<button class="myclass" data-item-class="custom-3"></button>
</div>
The value can be read as event.target.dataset.itemClass (item-class becomes itemClass, see docs for more info).
The code for variable a will be replaced with:
var a = event.target.dataset.itemClass;
Secondly, setting click event handler for 'button' selector is too wide.
It will cause errors when new button element with another purpose gets added to your page in the future.
It is much safer to think of <div class="light-slider-buttons"> as a component wrapping your button elements and apply the click handler only to those.
$(".light-slider-buttons button").click(function(event) {
...
}
It does not change much but is important because if you add other buttons outside <div class="light-slider-buttons"> they will not get click event handler.
jQuery uses CSS selectors syntax, you can find more in docs.
Here's the recommended code for script tag
<script>
$(document).ready(function() {
$(".light-slider-buttons button").click(function(event) {
var a = event.target.dataset.itemClass;
var b = ".carousel" + "." + a ;
$(b).myfunction;
});
});
</script>
P.S. jQuery programming style is quite imperative (specifying how page should update on every event).
There are other ways to build UI, for example in React programming is declarative (specifying how UI should look like based on given input/state)
I don't want to change HTML because I want to leave the display the way it is for default view and want to move them in second view. I want to know how I can dynamically order the class of a div.
I want to do this via button click. I have adEventListener() for 'click' where I am doing something and the move logic would go inside this event listener.
I understand that I can get these divs, remove from their parents and place it where I want. But I do not know how to do these for each of them since I have multiple lis. I am struggling with the loop so that I can do these for each li. I need to do this using pure JS and not jQuery.
<ul>
<li>
<div>
<div class="a">
<div class="b">
<a class="c">
<div class="d"></div>
<div class="e">
<div class="f"></div> // this is the first item that I want to move
</div>
<div class="g"></div> // this is the second item that I want to move
</a>
</div>
<div class= "h"></div> // I want above mentioned divs to be before this div
</div>
</div>
</li>
//There are multiples lis
<li></li>
Assuming you would like to do this on load of the page, you could solve your problem with the following JQuery DOM manipulations:
$(document).ready(function(){
$("ul .a").each(function(index, element){
$current_div_a = $(element);
$div_h = $current_div_a.find(".h");
$div_f = $current_div_a.find(".f");
$div_f.clone().insertBefore($div_h);
$div_f.remove();
$div_g = $current_div_a.find(".g");
$div_g.clone().insertBefore($div_h);
$div_g.remove();
})
});
You can test it out on this demo.
I strongly advise against this way of doing it though. I guess it's also the reason why your question got some downvotes too. Just modifying your HTML keeps your code clean, maintainable and clearer for anyone else starting to work on your project. Keeping backwards compatibility for your code as much as possible will cause maintainability problems later.
I ended up using
var list = document.querySelectorAll("ul li");
for (var item of list) {
let fClass = item.querySelector(".f");
fClass.parentNode.removeChild(fClass);
let parentOfFirstChildAfterWhichIwantMyF = item.querySelector(//selector for parentOfFirstChildAfterWhichIwantMyF);
parentOfFirstChildAfterWhichIwantMyF.insertAdjacentElement("beforeend", fClass);
}
just having some issues with this jQuery thing.
What i'm trying to do is:
i have some audio control buttons that look like this:
<p>Play audio</p>
but there are too many on the page so i'm trying to optimise the code and make a little function that checks for the div id on the button and adds tells the player what track to play.
so i've done this:
<div id="audioControlButtons-1">
<div class="speaker"> </div>
<div class="play"> </div>
<div class="pause"> </div>
</div>
<script>
$(document).ready(function() {
$("[id^=audioControlButtons-] div.play").click(function() {
var id = new Number;
id = $(this).parent().attr('id').replace(/audioControlButtons-/, '');
//alert(id);
player1.loadAudio(id);
return false;
});
});
</script>
my problem is:
the id is not passing to the the player1.loadAudio(id)
if i hardcode player1.loadAudio(1)
it works! but the moment i try to pass the variable to the function it doesn't work...
however if you uncomment the alert(id) thing you will see the id is getting generated...
can someone help?
cheers,
dan
I think I see your problem. The variable id is a string. Try;
player1.loadAudio(parseInt(id));
Yah and the initialise line isn't necessary. Just use;
var id = $(this).parent().attr('id').replace(/audioControlButtons-/, '');
I'm actually kind of confused with your example because you originally have this:
<p>Play audio</p>
but then you don't reference it again. Do you mean that this html:
<div id="audioControlButtons-1">
<div class="speaker"> </div>
<div class="play"> </div>
<div class="pause"> </div>
</div>
Is what you are actually creating? If so, then you can rewrite it like this:
<div class="audio-player">
<div class="speaker"> </div>
<div class="play" data-track="1"> </div>
<div class="pause"> </div>
</div>
Then in your script block:
<script>
$(document).ready(function() {
$(".audio-player > .play").click(function() {
var track = $(this).data('track');
player1.loadAudio(+track);
return false;
});
});
</script>
So a few things are going on here.
I just gave your containing div a class (.audio-player) so that it's much more generic and faster to parse. You don't want to do stuff like [id^=audioControlButtons-] because it is much slower for the javascript to traverse and parse the DOM like that. And if you are going to have multiples of the same element on the page, a class is much more suited for that over IDs.
I added the track number you want to the play button as a data attribute (data-track). Using a data attribute allows you to store arbitrary data on DOM elements you're interested on (ie. .play button here). Then this way, you don't need to this weird DOM traversal with a replace method just to get the track number. This saves on reducing unnecessary JS processing and DOM traversing.
With this in mind now, I use jQuery's .data() method on the current DOM element with "track" as the argument. This will then get the data-track attribute value.
With the new track number, I pass that along into your player1.loadAudio method with a + sign in front. This is a little javascript trick that allows you to convert your value into an actual number if that is what the method requires.
There are at least a couple of other optimizations you can do here - event delegation, not doing everything inside the ready event - but that is beyond the scope of this question. Hell, even my implementation could be a little bit optimized, but again, that would require a little bit more in depth explanation.
I would like to know how to remove all the HTML between two strings in a webpage. The webpage will not always have the same content, so this must work no matter what the two strings are and what their positions are. For example,
<div class='foo'>
<div class='userid'>123</div>
<div class='content'>
asdfasdf
</div>
</div>
<div class=bar>
<div class='userid'>456</div>
<div class='content'>
qwerqwer
</div>
</div>
How could I remove all the HTML between 'asdfasdf' and '123'?
Thanks
This is ugly but it works:
​var container = $("#cont");
var text = container.html();
var arr = text.split("asdfasdf");
arr[1] = "";
arr = arr.join("");
$("#cont").html(arr);
I added a container div. You could use the body tag or something else. Its possible with a regex as well.
Here is a working demo http://jsfiddle.net/QJSJH/.
Edit
I see the post changed quite a bit, but you could use the same concept as above.
I'm trying to remove all the sibling elements after a particular div, lets say the div tag with id = id8.
<form>
<div id="id5">something ...<div>
<div id="id8">something ...<div>
<div id="id3">something ...<div>
<div id="id97">something ...<div>
<div id="id7">something ...<div>
...
<div id="idn">some text ...<div>
</form>
To do that I use the following code in jquery.
$("#id8 ~ div").remove();
It works fine in Firefox, but It doesn't work in IE7.
Is there an alternative way to archieve this, using jquery and just giving the tag id from the element I want to start removing the elements?
Thanks
Thanks everybody for your help
I end up with this solution based on the accepted answer
function removeAfter(el,tag){
element = $('#'+el);
var aElements = $(tag,element.parent());
var index = (aElements.index(element));
for(i=(index+1);i<aElements.length;i++) {
$('#'+$(aElements.get(i)).attr('id')).remove();
}
}
just call
removeAfter('id8', 'div')
Two things!
1) Close your <div> tags! It should look like this:
<form>
<div id="id5">something ...</div>
<div id="id8">something ...</div>
<div id="id3">something ...</div>
<div id="id97">something ...</div>
<div id="id7">something ...</div>
<div id="idn">some text ...</div>
</form>
2) The ~ operator only matches siblings that follow the matched element (ie it will match id3, id97, id7 and idn, but not id5). To match every sibling, including id5, you do this:
$("#id8").siblings("div").remove();
That should leave you with just id8. I tested this in Firefox 3.5.5 and IE7.0something. Hope that helps!
Three steps here:
Find the index number of the element we've clicked, with respect to its parent.
Loop through all the div elements contained within this parent, starting after the one we just found
Delete each div found
$(document).ready(function(){
$('#parent').children().click(function(){
var index = ($('div',$(this).parent()).index(this));
for(i=(index+1);i<$('div',$(this).parent()).length;i++){
$($('div',$(this).parent()).get(i)).hide();
}
});
});
This will work on this HTML
<div id="parent">
<div id="c1">c1</div>
<div id="c2">c2</div>
<div id="c3">c3</div>
<div id="c4">c4</div>
<div id="c5">c5</div>
</div>
Comment here if you've got any more problems on the matter!
P.S. An application of this solution exact to your request is the following
function removeAfter(el){
element = $('#'+el);
var index = ($('*',element.parent()).index(element));
for(i=(index+1);i<$('*', element .parent()).length;i++){
$($('*', element.parent()).get(i)).hide();
}
};
EDIT:
Editing the answer below to add what should be a fix for the problem:
$("#id8").nextAll().remove();
END EDIT.
Ok. This appears to be an interesting bug - initial testing seems to indicate it's a jquery bug although I haven't found any specific mention of it anywhere.
The bug seems to be that if your initial selector tag is the same type as its siblings then it will fail to return any siblings in IE7.
I tested it using the jQuery example code for the selector itself and was able to duplicate your problem in IE8 emulating IE7.
If you check the jquery example code I'll stick below you can see that the actual element they're using as the initial selector is a span and the sibling elements are all divs whcih seems to me to indicate they know about this bug and haven't documented it, which is both cunning and shitty.
<script>
$(document).ready(function(){
$("#prev ~ div").css("border", "3px groove blue");
});
</script>
<div>div (doesn't match since before #prev)</div>
<span id="prev">span#prev</span>
<div>div sibling</div>
<div>div sibling <div id="small">div niece</div></div>
<span>span sibling (not div)</span>
<div>div sibling</div>
Change the #prev span to a div and you'll get the same failure as you're getting currently. I'd submit a bug with the jquery team.