Sort sibling <div>s with jQuery - javascript

I'm banging my head with the problem that has more to do with 2nd grade mathematics than programming. Here goes: four <div> elements are placed one after another, horizontally. When you click one, script places it in front. You click another one, and it's also placed in front, etc. You get the picture. Now, what I'd like to do is to sort remaining <div> elements (all but the first one) using original order.
Maybe this pic will make things clear:
After step #3, C should be placed after B, so it should go like this: D A B C.
Here's a sample code:
<html>
<head>
<title>mixit</title>
<style type="text/css">
.insidebox{
width: 50px;
height: 50px;
line-height: 50px;
margin: 0 0 0 20px;
text-align: center;
float: left;
border: black solid 3px;
font-family: sans-serif;
cursor: pointer;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div id="container">
<div id="a" class="insidebox">A</div>
<div id="b" class="insidebox">B</div>
<div id="c" class="insidebox">C</div>
<div id="d" class="insidebox">D</div>
</div>
</body>
</html>
Now, I understand that I can use .insertAfter() to place element in front, but how should I tackle the sorting part? The keyword is initial order, not alphabetical order. Letters and boxes are given just for illustrative purposes.

This should do what you want.
var $initial = $('.insidebox');
$('.insidebox').click(function(){
var $this = $(this);
$this.parent()
.prepend($this)
.append( $initial.not(this) );
});
You store the initial list and on each click re append it (excluding the current one)
demo http://jsfiddle.net/gaby/Dyafx/
update
Hell.. you do not even need to prepend the current element.. when you append the rest they will go after the clicked one anyway ..
var $initial = $('.insidebox');
$('.insidebox').click(function(){
$(this).parent()
.append( $initial.not(this) );
});
demo http://jsfiddle.net/gaby/Dyafx/1/

Store the initial order as an array. Then sort by array index- the first one (A) will have array index 1, etc.

Do this:
$(document).ready(function(){
$("#container div").click(function(){
$(this).prependTo($(this).parent());
});
});
cheers.

Related

Access dynamically added CSS Grid items from parent grid container in grid order using JavaScript?

I have a CSS Grid Layout with no preset columns or rows because the number of items to be added is unknown beforehand. I use JS to create DOM elements and set their column and row numbers. Later, I want to update specific spots in the grid with a new element; before doing so I want to check if there is an element already at that position in the grid and, if so, retrieve and remove it.
To do that I'm looking for something along the lines of a 'containerElement.getElements().gridOrder()' type of deal which would return children elements in an array (or 2D array).
Perhaps I'm looking in the wrong place but I haven't seen anything like this on MDN. Do I need to loop through child elements and use their 'style.gridColumn' and 'style.gridRow' properties to manually sort things?
Here is sample code showing how I'm dynamically adding items to a grid:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>test page</title>
<style>
.box {
width: 30px;
height: 30px;
border-radius: 5px;
background-color: rgb(207,232,220);
margin: 5px;
}
.wrapper {
display: grid;
grid-gap: 20px;
background-color: rgb(79,185,227);
color: #fff;
overflow: auto;
}
</style>
<script>
function run(){
let con = document.getElementsByClassName('wrapper')[0];
for(let i=1; i<10; i++){
let e = document.createElement('div');
e.className = 'box';
e.id = i+"";
e.style.gridColumn = i;
e.style.gridRow = i;
con.appendChild(e);
}
}
</script>
</head>
<body onLoad='run()'>
<h1>Grid</h1>
<div class="wrapper">
</div>
</body>
</html>
I did not find any further information relating to my question so I went ahead with my own suggestion in the post; I just used a standard 2D array to track which spaces were filled or not.
Since arrays in JavaScript are dynamic this only requires checking if a slot contains an existing array for a row-- adding one if it doesn't --and then adding the item at the specified location.

Apply JQuery to div's clicked

I am working on making a number list with each number on its individual div. So far I am able to remove the div with Javascript (on click), but I would like to enable JQuery so that I am able to add a class to a div and then remove all divs of that class with a button or something like that.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=203">
<title>Lista Mundial</title>
<style>
.divContainer {
width: 35px;
height: 25px;
border: solid 1px #c0c0c0;
background-color: #e1e1e1;
font-family: verdana;
float: left;
}
.text {
font-size: 15px;
font-family: verdana;
color: black;
margin-top: 4px;
}
h4 {
font-family: Verdana;
color: black;
text-decoration: none;
}
</style>
</head>
<body>
<h4>Double click para borrar un numero</h4>
<script type="text/javascript">
for(var i = 1; i <= 639; i++){
var divTag = document.createElement("div");
divTag.id = i;
divTag.className = "divContainer";
document.body.appendChild(divTag);
divTag.ondblclick = function(){this.parentNode.removeChild(this)};
var pTg = document.createElement("p");
pTg.setAttribute("align", "center");
pTg.className = "text";
pTg.innerHTML = (i);
document.getElementById(i).appendChild(pTg);
}
</script>
</body>
</html>
http://jsfiddle.net/ramonfabrega/AZSy8/
For simplicity, I just tried hiding the div's clicked, but JQuery does not seem to work. So something must be off.
Two issues:
1) jQuery wasn't loaded.
2) You were trying to bind the click event on an invalid selector (divTag instead of div)
Here's an updated fiddle: http://jsfiddle.net/LFC3A/2/
Regarding #2 - jQuery allows you to select an element multiple ways. The most common is to use a selector. The majority of selectors jQuery supports are from CSS 1 - 3, though jQuery supports some of its own custom selectors (such as div:eq, div:gt, and so on...) Check out the selectors page here: http://api.jquery.com/category/selectors/
Now, if your markup was:
<body>
<divTag>My Custom Div Tag</divTag>
<div>My regular DIV</div>
</body>
Then your original fiddle would have worked. In fact, here's an updated fiddle demonstrating that: http://jsfiddle.net/FpMAw/ (I updated your createElement to return a custom element, divTag)
The other way of accessing jQuery is by passing it a DOM element. Something like:
var $body = $(document.body) is equivalent to var $body = $('body')
If you reference that, you now have a jQuery object with a bunch of useful helper methods. So, in our previous example, we can now do:
$body.css('color', 'red')
Hopefully this helps explain a bit more why it didn't work. If you have any other questions, feel free to ask :)
Fiddle Demo
you are not including jQuery library in the fiddle
change $('divTag') to $('div')
Read $( "element" )
$(document).ready(function () {
$('div').click(function () {
$(this).hide();
});
});
Start Learning
jQuery API Documentation
This will create and add a click handler at the same time.
$('<div>').click(function(e){ this.addClass('active');})

Can each new click produce a new image?

I know how to make an image appear using onclick or onMouseOver but how can I make each click produce the appropriate image not just in the same place but, for example, in a row, next to it's previous apperance? My idea is this: I click on reference1 and a picture1 shows up. Then I click on reference2 and a picture2 shows up next to the picture1 already displayed. Now I click on reference1 again, and I want to see pictures 1,2,1 in a row. How can I do that? My ideal would be to see the row rolling when filled, and a delete button deleting the last image in that row, even making the pictures jump out being called from the text field, but I can search for these myself. My greatest concern for now is new click=new image. Thank you.
Assuming this is relatively simplistic- you could keep track of the current position in a list of images, afterwards create a function that deals with the current image then increments this position. Have the onClick event call this function, and there you are.
An example of this in action, using JQuery, can be viewed here:
http://jsfiddle.net/8Q4LQ/
Here's an example.
<html>
<head>
<style>
.refimg { width: 100px; height: 100px; }
.choices a { margin-right: 2ex; }
.choices img { display: none; }
#target { display:block; width: 500px; overflow-x: scroll; border: 1px solid black; }
</style>
</head>
<body>
Choices:
<div class="choices">
ref1
ref2
<image id="image1" src="image1.gif" class="refimg" />
<image id="image2" src="image2.gif" class="refimg" />
</div>
<br />
Selections: <input type="button" value="Delete" onclick="delImage()" />
<nobr id="target">
</nobr>
<script>
function putImage(src) {
var a = src.cloneNode(true);
a.id = ''; //clear id to prevent duplicate id
target.appendChild(a);
a.scrollIntoView(true);
return false;
}
function delImage() {
var a=target.children;
if (a.length>0) target.removeChild(a[a.length-1]);
}
target.style.height=((target.offsetHeight-target.clientHeight)+100)+'px'; //extend height for scroll bar
</script>
</body>
</html>

Is redrawing the contents of a DIV by means of a function call possible?

Just an amateur/hobbyist here - what this is supposed to do is be a tool for a board game I play with friends. The plastic sliders the game uses are too loose to be reliable so I wanted to reproduce that functionality as a webpage to use on a smartphone while playing.
It gets a character's name from a form (on another page) and supplies it to
the one below. Based on the name, it chooses the right set of attributes from the switch statement (I removed all but two cases for the sake of simplicity), runs through a for loop to display the attributes in a list and highlight the "current" value as green. Two buttons are supposed to increase or decrease the array counter ("speed"), and rerun the function that draws the array with the new highlighted value. innerHTML is meant to redraw the div ("speeddiv") with the new results.
Now the javascript console in chrome is telling me that speedcounter() and character are undefined. I suspect this has something to do with the scope of the function and variables I'm using being lost through innerhtml. All I want to do is find a way to easily redraw/replace the stat counter so it appears that the highlighted number is moving up and down as you press the + or - buttons, within the div.
I'm only working on the "speed" attribute below, so I can get that working first.
<!DOCTYPE html>
<html>
<body>
<style type="text/css">
html, body { height: 100%; width: 100%; margin: 0; }
#dossier {height: 10%; text-align: center; background: #808080}
#container {height: 90%; width: 100%; background: #000000; overflow: hidden; float: left}
#stats {height: 100%; width: 100%; float: left; position: relative}
#speeddiv, #mightdiv, #sanitydiv, #knowledgediv {width: 25%; height: 100%; text-align: center; float: left; position: relative; overflow: hidden}
#speeddiv {background: #0000FF}
#mightdiv {background: #FF0000}
#sanitydiv {background: #FFFF00}
#knowledgediv {background: #00FF00}
</style>
<?php $character = $_GET["character"]; ?>
<script type="text/javascript">
var character = "<?php echo $character ?>";
var sp;
var speed;
function speedcounter() {
var spx;
document.write(' <h2>Speed</h2></br>');
document.write('<input type="button" onclick="addspeed();" value="+"><br />');
for (spx=8; spx>=0; spx--) {
if (spx == speed) {
document.write('<font color=#00FF00>');
}
document.write(sp[spx]);
document.write('<font color=#000000><br />');
}
document.write ('<input type="button" onclick="remspeed();" value="-">');
}
function addspeed() {
if (speed < 8) {
speed++;
document.getElementById("speeddiv").innerHTML = "<script type="text/javascript">speedcounter();<\/script>";
}
}
function remspeed() {
if (speed > 0) {
speed--;
document.getElementById("speeddiv").innerHTML = "<script type="text/javascript">speedcounter();<\/script>";
}
}
switch (character) {
case "brandon":
sp=["0","3","4","4","4","5","6","7","8"];
mt=["0","2","3","3","4","5","6","6","7"];
sn=["0","3","3","3","4","5","6","7","8"];
kn=["0","1","3","3","5","5","6","6","7"];
speed=3;
might=4;
sanity=4;
knowledge=3;
break;
case "flash":
sp=["0","4","4","4","5","6","7","7","8"];
mt=["0","2","3","3","4","5","6","6","7"];
sn=["0","1","2","3","4","5","5","5","7"];
kn=["0","2","3","3","4","5","5","5","7"];
speed=5;
might=3;
sanity=3;
knowledge=3;
break;
}
</script>
<div id="dossier">
<script type="text/javascript">
document.write(character);
</script>
</div>
<div id="container">
<div id="stats">
<div id="speeddiv">
<script type="text/javascript">
speedcounter();
</script>
</div>
<div id="mightdiv">
<h2>Might</h2></br></br>
</div>
<div id="sanitydiv">
<h2>Sanity</h2></br></br>
</div>
<div id="knowledgediv">
<h2>Knowledge</h2></br></br>
</div>
</div>
</div>
</script>
</body>
</html>
I've created a jsfiddle from the code you've posted http://jsfiddle.net/amelvin/bwwce/ - working on it interactively in there may help.
I think your problem is what is happening with the document.write; the section on document.write explains that what document.write does is not very predictable.
Use a javascript library like jquery to insert elements into the webpage rather than document.write - the html() method in jquery (amongst others) allows you dynamically and predictably manipulate any aspect of the page based on events like button pushes, adding or removing buttons or divs.

How to move an element into another element

I would like to move one DIV element inside another. For example, I want to move this (including all children):
<div id="source">
...
</div>
into this:
<div id="destination">
...
</div>
so that I have this:
<div id="destination">
<div id="source">
...
</div>
</div>
You may want to use the appendTo function (which adds to the end of the element):
$("#source").appendTo("#destination");
Alternatively you could use the prependTo function (which adds to the beginning of the element):
$("#source").prependTo("#destination");
Example:
$("#appendTo").click(function() {
$("#moveMeIntoMain").appendTo($("#main"));
});
$("#prependTo").click(function() {
$("#moveMeIntoMain").prependTo($("#main"));
});
#main {
border: 2px solid blue;
min-height: 100px;
}
.moveMeIntoMain {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">main</div>
<div id="moveMeIntoMain" class="moveMeIntoMain">move me to main</div>
<button id="appendTo">appendTo main</button>
<button id="prependTo">prependTo main</button>
My solution:
Move:
jQuery("#NodesToMove").detach().appendTo('#DestinationContainerNode')
copy:
jQuery("#NodesToMove").appendTo('#DestinationContainerNode')
Note the usage of .detach(). When copying, be careful that you are not duplicating IDs.
Use a vanilla JavaScript solution:
// Declare a fragment:
var fragment = document.createDocumentFragment();
// Append desired element to the fragment:
fragment.appendChild(document.getElementById('source'));
// Append fragment to desired element:
document.getElementById('destination').appendChild(fragment);
Check it out.
Try plain JavaScript: destination.appendChild(source);.
onclick = function(){ destination.appendChild(source) };
div {
margin: .1em;
}
#destination {
border: solid 1px red;
}
#source {
border: solid 1px gray;
}
<div id=destination>
###
</div>
<div id=source>
***
</div>
I just used:
$('#source').prependTo('#destination');
Which I grabbed from here.
If the div where you want to put your element has content inside, and you want the element to show after the main content:
$("#destination").append($("#source"));
If the div where you want to put your element has content inside, and you want to show the element before the main content:
$("#destination").prepend($("#source"));
If the div where you want to put your element is empty, or you want to replace it entirely:
$("#element").html('<div id="source">...</div>');
If you want to duplicate an element before any of the above:
$("#destination").append($("#source").clone());
// etc.
You can use:
To insert after,
jQuery("#source").insertAfter("#destination");
To insert inside another element,
jQuery("#source").appendTo("#destination");
You can use the following code to move the source to the destination:
jQuery("#source")
.detach()
.appendTo('#destination');
Try the working CodePen.
function move() {
jQuery("#source")
.detach()
.appendTo('#destination');
}
#source{
background-color: red;
color: #ffffff;
display: inline-block;
padding: 35px;
}
#destination{
background-color:blue;
color: #ffffff;
display: inline-block;
padding: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="source">
I am source
</div>
<div id="destination">
I am destination
</div>
<button onclick="move();">Move</button>
If you want a quick demo and more details about how you move elements, try this link:
http://html-tuts.com/move-div-in-another-div-with-jquery
Here is a short example:
To move ABOVE an element:
$('.whatToMove').insertBefore('.whereToMove');
To move AFTER an element:
$('.whatToMove').insertAfter('.whereToMove');
To move inside an element, ABOVE ALL elements inside that container:
$('.whatToMove').prependTo('.whereToMove');
To move inside an element, AFTER ALL elements inside that container:
$('.whatToMove').appendTo('.whereToMove');
I need to move content from one container to another including all the event listeners. jQuery doesn't have a way to do it, but the standard DOM function appendChild does.
// Assuming only one .source and one .target
$('.source').on('click',function(){console.log('I am clicked');});
$('.target')[0].appendChild($('.source')[0]);
Using appendChild removes the .source* and places it into target including its event listeners: Node.appendChild() (MDN)
You may also try:
$("#destination").html($("#source"))
But this will completely overwrite anything you have in #destination.
You can use pure JavaScript, using appendChild() method...
The appendChild() method appends a node as the last child of a node.
Tip: If you want to create a new paragraph, with text, remember to
create the text as a Text node which you append to the paragraph, then
append the paragraph to the document.
You can also use this method to move an element from one element to
another.
Tip: Use the insertBefore() method to insert a new child node before a
specified, existing, child node.
So you can do that to do the job, this is what I created for you, using appendChild(), run and see how it works for your case:
function appendIt() {
var source = document.getElementById("source");
document.getElementById("destination").appendChild(source);
}
#source {
color: white;
background: green;
padding: 4px 8px;
}
#destination {
color: white;
background: red;
padding: 4px 8px;
}
button {
margin-top: 20px;
}
<div id="source">
<p>Source</p>
</div>
<div id="destination">
<p>Destination</p>
</div>
<button onclick="appendIt()">Move Element</button>
I noticed huge memory leak & performance difference between insertAfter & after or insertBefore & before .. If you have tons of DOM elements, or you need to use after() or before() inside a MouseMove event, the browser memory will probably increase and next operations will run really slow.
The solution I've just experienced is to use inserBefore instead before() and insertAfter instead after().
Dirty size improvement of Bekim Bacaj's answer:
div { border: 1px solid ; margin: 5px }
<div id="source" onclick="destination.appendChild(this)">click me</div>
<div id="destination" >...</div>
For the sake of completeness, there is another approach wrap() or wrapAll() mentioned in this article. So the OP's question could possibly be solved by this (that is, assuming the <div id="destination" /> does not yet exist, the following approach will create such a wrapper from scratch - the OP was not clear about whether the wrapper already exists or not):
$("#source").wrap('<div id="destination" />')
// or
$(".source").wrapAll('<div id="destination" />')
It sounds promising. However, when I was trying to do $("[id^=row]").wrapAll("<fieldset></fieldset>") on multiple nested structure like this:
<div id="row1">
<label>Name</label>
<input ...>
</div>
It correctly wraps those <div>...</div> and <input>...</input> BUT SOMEHOW LEAVES OUT the <label>...</label>. So I ended up use the explicit $("row1").append("#a_predefined_fieldset") instead. So, YMMV.
The .appendChild does precisely that - basically a cut& paste.
It moves the selected element and all of its child nodes.

Categories

Resources