Retaining order of moving elements in a list - javascript

I've created a section of spans that when clicked on move into another html element and when clicked on while within the target element returns back to the section of spans.
My question is, how can I return the clicked span back to it's ORIGINAL position in the list of spans?
I can think of one way that might work and would involve using CSS child selectors, but that can become very complicated and I'm looking for a more intuitive way.
As it happens now, the span in question returns to the end of the list.
<div id="genres">
<?php
$query = 'SELECT * FROM genres ORDER BY genre DESC';
$genres = mysqli_query($db, $query);
while($row = mysqli_fetch_assoc($genres)){
echo "<span class='genre'>";
echo ucfirst($row['genre']);
echo "</span>";
The above simply outputs the data into seperate spans styled to be clickable elements that look similar to buttons.
When a span is clicked on it is moved into an empty div.
My Jquery:
$("span.genre").click(function(){
// remove the span and move it to the empty div
$(this).remove().appendTo('div#genres_select');
// remove span from the empty div and puts it back in the list
$('div#genres_select span.genre').click(function(){
$(this).remove().appendTo('div#genres');
});
What is interesting and that I like is that when a clicked span is moved out of the list, all the other elements conform to fill it's space.
Ideally, I'm looking for the exact reverse action of clicking on a span, as if you pushed the rewind button.
Thanks in advance

Add the position to the dom.
$pos = 0
while($row = mysqli_fetch_assoc($genres)){
echo "<span orgPos='".$pos."' class='genre'>";
echo ucfirst($row['genre']);
echo "</span>";
$pos++
}
The javascript looks for the lower neighbor
$('div#genres_select span.genre').click(function(){
var pos = $(this).attr("orgPos");
var neighbor = false;
$('#genres span.genre').each(function(){
if (!neighbor && ($( this ).attr("orgPos") < pos ))
neighbor = $( this );
})
$(this).remove();
sibling.after(this)
}
You will need to figure out what to do if it is the first element or only one element in the list.

Related

Check multiple buttons with same id with JavaScript

I'm trying to build a website where people can make a reservation, I'm using a database to collect the times and php to display it. It displays all times within 5 days, including the ones that aren't available. They are displayed as buttons, all sharing the same id. I got stuck at the last step, disabling the buttons with unavailable times.
Since the only difference between these buttons is their background color (grey for unavailable and green for available) I figured I'd use a javascript function in which it checks the background colors of the boxes in a condition and then the grey ones get disabled and the green ones give a form. However: it'll only check the color of the first button and all buttons give the same result as that one.
My page will always display 50 buttons, so I thought I could just use a while loop with an auto-decrement at the end, however I can't seem to find out how to check the next button, it will now only check the same button again and again. Here's a part of the php-code to show the buttons with the right color (I've take some irrelevant parts out):
while($row = $results->fetch_assoc()){
$color = "##8fd6a5";
if (!empty($row['unavailable'])){
$color = "##9b9393";
}
$time= new DateTime($row['time']);
if ($time->format('H') == '08'){
echo '<button id="myBtn" onload="disablebuttons()" class="buttonstyle"
style="background-color: '.$color.'">'.$time>format('m/d H:i').'</button>';
}
}
This works entirely, but since all buttons have id="myBtn" when disablebuttons() executes, it only looks at the first button, following this code:
function disablebuttons() {
var amountButton = 50;
while (amountButton > 0){
var buttondisable = document.getElementById("myBtn");
if (buttondisable.style.backgroundColor == "rgb(155, 147, 147)"){
document.getElementById("myBtn").disabled = true;
amountButton--;
}
}
}
I've tried to delete the variable at the end of the while loop and place the "var buttondisable = document.getElementById("myBtn");" inside the loop, however this did not work.
IDs need to be unique so you need to use different ids for each button. To group them, give then same class say available if they are available unavailable if its not available. Something like this:
while($row = $results->fetch_assoc())
{
$color = "##8fd6a5";
$class= 'available'
if (!empty($row['unavailable']))
{
$color = "##9b9393";
$class= 'unavailable'
}
$time= new DateTime($row['time']);
if ($time->format('H') == '08')
{
echo '<button id="myBtn" onload="disablebuttons()" class="buttonstyle '.$class.'" style="background-color: '.$color.'">'.$time>format('m/d H:i').'</button>';
}
}
Now on javascript you can target specific buttons only like this:
var buttondAvailable = document.getElementByClassName("available");
OR
var buttondUnavailable = document.getElementByClassName("unavailable");
The id attribute should be unique in the same document, so use common classes instead of id's for your buttons like :
if ($time->format('H') == '08'){
echo '<button onload="disablebuttons()" class="buttonstyle myBtn"
style="background-color: '.$color.'">'.$time>format('m/d H:i').'</button>';
}
Then in your JS code loop through all the buttons using getElementsByClassName() :
var buttons = document.getElementsByClassName('myBtn');
for(var i = 0; i < buttons.length; i++)
{
//Your logic here
var button = buttons[i];
if (button.style.backgroundColor == "rgb(155, 147, 147)")
{
button.disabled = true;
}
}
Hope this helps.
if you get the parent element and loop their childrens, you can check each element and his background and disable it.
$('#mydiv').children('button').each(function () {
// "this" is the current element in the loop
if($(this).css("background-color") == "rgb(155, 147, 147)"){
$(this).disabled = true;
}
});

jQuery hover multiple ID's from php generated DIV

I'm having some troubles with a jQuery script.
I get my div's generated with PHP based on data from SQL.
echo "<div class='order' id='a$i' runat='server' draggable='true' >";
On mouseover it shows a different div also generated from PHP and SQL.
echo "<div class='position' id='b$i2' runat='server' draggable='true'>";
Then i have a jQuery script that has the hover function for the second div.
Every div get's it's ID from php. Menu div's get a1, a2, a3.... and hover div's get b1, b2, b3....
$(function() {
var moveLeft = 20;
var moveDown = 10;
var r = 1;
$('div#a'+r).hover(function(e) {
$('div#b'+r).show();
}, function() {
$('div#b'+r).hide();
});
$('div#a'+r).mousemove(function(e) {
$("div#b"+r).css('top', e.pageY + moveDown).css('left', e.pageX + moveLeft);
});
});
The code works for the first div, or the div i specify with the r variable.
I'm having troubles with code working for all the ID's on the page. They get generated based on SQL data.
https://postimg.org/image/ooqnfkx3n/
Is there a way to do this using LOOP function? Or getting the ID from generated div's?
Thanks for all the help in advance.
Use starts with selector
$("div[id^='a']").hover(function(event) {
//Do your thing
}
Documentation: Attribute Starts With Selector [name^=”value”]
How about you add the hover event on class instead of div but add logic based on div.
$(".theclassofA").hover(function(event) {
var id = $(this).attr('id');
var temp_rel = //then get the integer 'r' from this id
var temp_id = "b"+temp_rel;
//use this temp_id to show/hide your elements
}

Highlight slices of text with Javascript

Problem
Suppose that in the backend of my Web application I have a generic string of letters:
seq = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
and an array of positions in such a string:
pos = [(0, 2), (4, 8)]
I need to render this sequence in the frontend by splitting it every n characters. Then when a user clicks a button I need to highlight the sequence between two parameters (taken from pos) for which the button refers to.
My solution
I solve this by implementing a Javascript function formatSequence which splits seq every n characters and iterates through the pos array in order to wrap each substring inside a span tag. The result is something like this:
<pre>
<span class="A">AA</span>AA<span class="B">A</span>
<span class="B">AAA</span>AA
AAAAA
</pre>
When the user clicks the button referring to the class A I simply change the CSS background rule for class A.
It works :) But the function formatSequence is way too complicated imho. It was a pain dealing with multiple lines. I prefer not posting the code since I am looking for other approaches not changing the code of such function.
A better solution?
I think that a (better?) solution would be to implement a function that given two parameters start and end it dynamically highlights the text between them. But it appears to be even more complicated than the previous one (remember that the sequence must be split every n characters and thus the highlight must be multilines).
Any suggestions? Better approach to solve this?
One simple solution would be just to print the full seq multiple times into the HTML and hide every row you don't need at the time. When a user clicks on a button, another row would be displayed (and the first one would be hidden).
HTML:
<div class="rows"></div>
<div class="buttons"></div>
JavaScript (depending on jQuery):
(function generateRowsAndButtons() {
var sequence = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
var position = [ [0,2], [4,8] ];
var $rows = $('.rows');
var $buttons = $('.buttons');
for(var i = 0; i < position.length; i++) {
if(position[i].length !== 2 || position[i][0] > position[i][1]) {
console.log("every position array needs exactly two values with the second larger than the first one");
continue;
}
// the index is used for mapping the button the highlight position
var row = '<div class="row" data-index="' + i + '" style="display: none;">';
// you should add some checks here, if position larger then the length of the string to avoid some misbehaviors. this is of course only necessary if you aren't validating the values on another place.
row += sequence.substring(0, position[i][0]);
row += '<span class="highlighted">';
row += sequence.substring(position[i][0], position[i][1]);
row += '</span>';
row += sequence.substring(position[i][1]);
row += '</div>';
var $row = $(row);
$rows.append($row);
// a button needs the index to find the link the highlighted value
var $button = $('<button data-index="' + i + '">' + position[i] + '</button>');
$buttons.append($button);
}
$buttons.find('button').click(function() {
var index = $(this).data('index');
// hide every row, except the one with the correct index
$rows.find('.row').hide().filter('[data-index="' + index + '"]').show();
});
})();
CSS:
.row .highlighted {
background: yellow;
}
Here is a jsFiddle: https://jsfiddle.net/y8uoou1L/2

move blocks between two divs

So I have two divs and inside there gona be some blocks:
<div class="list-block 01">
<span>21#epos.com</span>
<span class="moveSym" id="01">+</span>
</div>
if one clicks on
+
whole block moves to other div.
Everything works but only to move ech block to another div once,
but I need them to go both ways as much as .moveSym clicked.
my JS
//remove block on click
$('.del-block').on('click', function() {
var block = $(this).attr('id');
$('.' + block).remove();
})
//move form list blocks to different fields
$('.leftSide01 .moveSym').click(function() {
console.log($(this).attr('id'));
var id = $(this).attr('id');
$(this).text("-");
$('.leftSide01 .list-block.' + id).appendTo('.rightSide01');
})
$('.rightSide01 .moveSym').click(function() {
console.log($(this).attr('id'));
var id = $(this).attr('id');
$(this).text("+");
$('.rightSide01 .list-block.' + id).appendTo('.leftSide01');
})
I know there are plugins for this, but I really want to write it by myself and learn :)
Fiddle http://jsfiddle.net/A1ex5andr/CRvVK/
Need to use event delegation, because the handler to be executed depends on the parent element.
//move form list blocks to different fields
$('.leftSide01').on('click', '.moveSym', function () {
console.log($(this).attr('id'));
var id = $(this).attr('id');
$(this).text("-");
$('.leftSide01 .list-block.' + id).appendTo('.rightSide01');
})
$('.rightSide01').on('click', '.moveSym', function () {
console.log($(this).attr('id'));
var id = $(this).attr('id');
$(this).text("+");
$('.rightSide01 .list-block.' + id).appendTo('.leftSide01');
})
Demo: Fiddle
You can really simplify this logic into one function that works for both (if there are only ever going to be two divs) . . .
$('.moveSym').click(function() {
console.log($(this).attr('id')); // I just left in, because you had it in the original code :)
var targetParent = $(".rightSide01");
var linkText = "-";
if ($(this).parent(".rigthSide01") > 0) {
linkText = "+";
targetParent = $(".leftSide01");
}
$(this).text(linkText);
$(this).parent().appendTo(targetParent);
});
This code starts out assuming that the block is on the left-hand side . . . it sets up the targetParent value (i.e., where the block will move to) to the right-hand side and the new link text to be "-".
After that, it checks to see if the block is actually on the right-hand side, instead, and, if it is, then it updates the variables with the values needed to move it to the left.
At that point, it updates the text in the "move-sym" span element to the final linkText value, and moves its parent block to the new target div (the targetParent value).
No need to worry about the delegation or event handlers in this one, because the function is the same, regardless of the location, and will travel with the "move-sym" span element, wherever it goes.

popup problem : not showing proper corresponding content

iterating over an array, am printing some div content for each iteration.
Whenever the user clicks on any div content, a popup should appear and should show the corresponding content in the popup from the array.
below is my code,
foreach ($email as $client)
{
echo "<div class = 't'> Show more....... </div>";
echo "<div class='popup_msg'>";
echo $client['Email']['body'];
echo "</div>";
}
javascript code below
jQuery(document).ready(function(){
jQuery('.t').click(function(e)
{
var height = jQuery('.popup_msg').height();
var width = jQuery('.popup_msg').width();
leftVal=e.pageX-(width/1.5)+"px";
topVal=e.pageY-(height/13)+"px";
jQuery('.popup_msg').css({left:leftVal,top:topVal}).show();
});
jQuery('.popup_msg').click(function(e)
{
jQuery('.popup_msg').fadeOut('fast');
});
});
in the above codes, what i want to achieve is, whenever the user clicks on the div with class t, the corresponding $client['Email']['body'] should appear in the popup
The problem is that your selector matches all .popup_msg, not only the one you need. Use the find() method to get the correct popup in the $('.t').click function:
jQuery('.t').click(function(e)
{
var popup_msg = jQuery(this).find('.popup_msg');
var height = popup_msg.height();
var width = popup_msg.width();
leftVal=e.pageX-(width/1.5)+"px";
topVal=e.pageY-(height/13)+"px";
popup_msg.css({left:leftVal,top:topVal}).show();
});
Note: I haven't tested this code, it might not be 100% correct but hopefully you get what I mean.

Categories

Resources