JavaScript drag drop swap div on mobile devices - javascript

I'm currently working on a mobile app/game. I am having a difficult time getting an inventory system working properly on a phone. the drag and drop work perfectly fine with a mouse on the pc, but will not work on phone.
JavaScript code:
document.addEventListener("DOMContentLoaded", function(event) {
$(document).ready(function(){
var videoPath = "videos/lg/";
var draggedItem = null;
$('.segmentListItem').each(function(index){
$(this).on("dragstart", handleDragStart);
$(this).on("drop", handleDrop);
$(this).on("dragover", handleDragOver);
});
function handleDragStart(e){
//console.log('start');
draggedItem=this;
e.originalEvent.dataTransfer.effectAllowed = 'move';
//e.dataTransfer.dropEffect = 'move'; //MH - do we need both of these?
e.originalEvent.dataTransfer.setData('text/html', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
e.originalEvent.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
return false;
}
function handleDrop(e){
if (e.stopPropagation) {
e.stopPropagation(); // Stops some browsers from redirecting.
}
if (draggedItem != this) { //MH - swap if we're not dragging the item onto itself
var copy=$(this).clone(true,true);
var slot1 = $(this).attr("id");
var slot1Temp = slot1 + "temp";
var slot2 = $(draggedItem).attr("id");
$(this).replaceWith($(draggedItem).clone(true,true));
$(draggedItem).replaceWith($(copy).clone(true,true));
slotID = "slotID-" + slot1;
document.getElementById(slot1).id = slot1Temp;
document.getElementById(slot2).id = slot1;
document.getElementById(slot1Temp).id = slot2;
$.ajax({
type: "GET",
url: '/inventorySwap.php',
data: {'slot1': slot1,'slot2': slot2},
success: function(data) {
alert(data);
}
});
}
return false;
}
});
});
HTML/PHP code:
<div class='inventorySlot". $obj->slot_id ."'>
<img class='segmentListItem' draggable='true' id=slotID-". $obj->slot_id ." src='{$itemImage}' />
</div>
Sorry if this question is set up a bit weird, I generally research and learn on my own. I don't like asking questions, I'm just completely stumped on this one.
What I need (and works perfect with mouse/on pc)
Drag element from 1 div to another. In code posted, it also changed the id of swapped elements to match their div inventory slot number. this is to prevent errors when updating database to swap within slot record.
thank you for any and all help given.

After a few hours of playing around with everything I managed to get what I needed.
outer div is for drop events,
middle div is for drag events, has to have width/height to fill outer div
inner div HAS to have position as absolute and z index less than the middle div.
this way no matter what, you click on middle div, and not it's inner contents.
the JS code saves both slot ids as a variable
then stores the id's innerhtml as another variable.
then it changes innerhtml of stored variable id1 with html of id2
contents as a var, then replaces each one to
function dragStart(event) {
event.dataTransfer.setData("Text", event.target.id);
id1 = event.target.id;
id1Html = document.getElementById(id1).innerHTML;
}
function dragging(event) {
}
function allowDrop(event) {
event.preventDefault();
}
function drop(event) {
event.preventDefault();
var data = event.dataTransfer.getData("Text");
id2 = event.target.id;
id2Html = document.getElementById(id2).innerHTML;
document.getElementById(id1).innerHTML = id2Html;
document.getElementById(id2).innerHTML = id1Html;
alert(id1);
alert(id2);
}
.inventorySlot1{position: absolute;top: 22%;left: 45%;width: 9%;height: 1px;height: 7%;overflow:hidden;background-color:green;opacity:0.5;}
.inventorySlot2{position: absolute;top: 22%;left: 54.5%;width: 9%;min-height: 1px;height: 7%;overflow:hidden;background-color:red;opacity:0.5;}
.inventorySlot6{position: absolute;top: 29.5%;left: 45%;width: 9%;height: 1px;height: 7%;overflow:hidden;background-color:green;opacity:0.5;}
.inventorySlot7{position: absolute;top: 29.5%;left: 54.5%;width: 9%;min-height: 1px;height: 7%;overflow:hidden;background-color:red;opacity:0.5;}
<div class='inventorySlot1' ondrop='drop(event)' ondragover='allowDrop(event)'>
<div ondragstart='dragStart(event)' ondrag='dragging(event)' draggable='true' id='slotID-1' style='width:100%;height:100%;'>
<div style='position:absolute;z-index:-1;'>
<img src='http://siteprice.co/images/failed.png'>
</div>
</div>
</div>
<div class='inventorySlot2' ondrop='drop(event)' ondragover='allowDrop(event)'>
<div ondragstart='dragStart(event)' ondrag='dragging(event)' draggable='true' id='slotID-2' style='width:100%;height:100%;'>
<div style='position:absolute;z-index:-1;'>
<img src='http://siteprice.co/images/safe.png'>
</div>
</div>
</div>
<div class='inventorySlot6' ondrop='drop(event)' ondragover='allowDrop(event)'>
<div ondragstart='dragStart(event)' ondrag='dragging(event)' draggable='true' id='slotID-6' style='width:100%;height:100%;'>
<div style='position:absolute;z-index:-1;'>
<img src='http://siteprice.co/images/alexa.png'>
</div>
</div>
</div>
<div class='inventorySlot7' ondrop='drop(event)' ondragover='allowDrop(event)'>
<div ondragstart='dragStart(event)' ondrag='dragging(event)' draggable='true' id='slotID-7' style='width:100%;height:100%;'>
<div style='position:absolute;z-index:-1;'>
<img src='http://siteprice.co/images/whois.png'>
</div>
</div>
</div>

Related

use querySelectorAll on dynamically added element

I want to query newly added div having memberCard class call but queryselectorall being static , i am not able to do so .How to resolve this problem?
var elementsToShow = document.querySelectorAll('.memberCard')
function list(){
$.ajax({
url:`http://localhost:8000/members`,
type:"GET",
success:function(members){
members.forEach(member => {
// Construct card content
content = `
<div class='memberCard'>
<div style='background-image:url("${member.image}")' class='memberImage'>
</div>
<div class='memberDetails josephine-sans'>
<h5>${member.name}</h5>
<h6>${member.batch}</h6>
</div>
</div>
`;
container.innerHTML += content;
});
}
You can use some hack i guess, update elementsToShow after success;
var elementsToShow = document.querySelectorAll('.memberCard')
function list(){
$.ajax({
url:`http://localhost:8000/members`,
type:"GET",
success:function(members){
members.forEach(member => {
// Construct card content
content = `
<div class='memberCard'>
<div style='background-image:url("${member.image}")' class='memberImage'>
</div>
<div class='memberDetails josephine-sans'>
<h5>${member.name}</h5>
<h6>${member.batch}</h6>
</div>
</div>
`;
container.innerHTML += content;
elementsToShow = document.querySelectorAll('.memberCard')
});
}
Use Event delegation and set the querySelector on the parent element.
This is an example :
<div id="button-container"></div>
// event is added for the parent of #submit-button
document.querySelector("#button-container").addEventListener('click',
function(e) {
if(e.target.id == 'submit-button') {
alert('CLICKED');
}
});
// #submit-button is dynamically created
document.querySelector("#button-container").innerHTML = '<button id="submit-
button">Submit</button>';
// click on #submit-button will now work
document.querySelector("#submit-button").click();
I suggesst you try to change your code , so you can use it this way.

Replace div contents javascript (no jquery)

Every time a selection is made from a dropdown menu, specific data is pulled from facebook and added to different divs. I am trying to update the contents of the div every time a different selection is made, however at the minute, the contents are just appended on after the initial contents.
This is the code that gets data based on a selection and creates the list from the returned data
<script>
city = document.getElementById("citySelection")
city.addEventListener("change", function() {
var selected = this.value;
var eventsList = document.getElementById("events");
if (selected == "None") {
eventsList.style.display = "none";
} else {
eventsList.style.display = "block";
};
if (selected == 'Bristol') {
getBristolEvents();
};
if (selected == 'Leeds') {
getLeedsEvents();
};
if (selected == 'Manchester') {
getManchesterEvents();
};
if (selected == 'Newcastle') {
getNewcastleEvents();
};
});
function createList(response, listId) {
var list = document.createElement('UL')
for (var i = 0; i < 10; i++) {
var events = response.data[i].name
var node = document.createElement('LI');
var textNode = document.createTextNode(events);
node.appendChild(textNode);
list.appendChild(node)
listId.appendChild(list);
}};
</script
This is the div being targeted:
<html>
<div id="events" style="display: none">
<div id="eventsDiv" style="display: block">
<div id="eventsListOne">
<h3 id='headerOne'></h3>
</div>
<div id="eventsListTwo">
<h3 id='headerTwo'></h3>
</div>
<div id="eventsListThree">
<h3 id='headerThree'></h3>
</div>
</div>
</div>
</div>
</html>
I have tried resetting the innerHtml of the div every time the function to get the data from facebook is called:
<script>
function getEventsThree(fbUrl, title) {
var listId = document.getElementById('eventsListThree');
var headerThree = document.getElementById('headerThree');
listId.innerHtml = "";
headerThree.append(title)
FB.api(
fbUrl,
'GET', {
access_token
},
function(response) {
listId.innerHtml = createList(response, listId)
}
)};
</script>
However, that still doesn't reset the contents of the div.
I've looked at other response but they all use jquery which I am not using.
Can anyone advise on the best way to fix this? Thanks.
I think your Hennessy approach is fine. Generate the inner content, then set .innerHTML.
At least one of your problems, maybe the only one, appears to be that you set .innerHTML to the return value of createList, but that function does not return anything.

JQuery function call firing multiple times

I'm trying to call a function for an html element using jquery. I'm struggling with this has been hours and I can't figure out what is wrong.
I have an answer which I want to mark as solved. A question have multiple answers.
As far as I know the function is being fired the number of answers I have in the question. If I have two answers, the function will run twice and so on.
$(document).ready(function () {
$(".accepted.ans").on('click', function (e) {
e.preventDefault();
var parent = $(this).closest('.accept');
console.log(parent);
var current = $(this);
console.log(current);
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
$.get(url + '?question=' + qid + '&answer=' + aid, function (data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}
This is my jQuery function. The one that I want to be called exactly once for each answer when I press the accept ans div element, which is:
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}" >
<div class="accept"
title="Accept this answer"
data-url="{url('controller/api/questions/mark_as_solved')}"
data-refresh="{url('controller/api/questions/refresh_accepted_answers')}"
data-answer="{$answer['answerid']}"
data-question="{$question['publicationid']}">
<div class="accepted ans"
id="{$answer['answerid']}"
title="Unnacept this answer">
</div>
</div>
</blockquote>
I thought this was happening because everytime I want to call that function , since I have $(".accepted.ans") it will apply to all the accepted ans it can find on the document. So I thought in adding an id to the class, something like:
id="{$answer['answerid']}"
but as I read somewhere here, it is supposed to work without that.
I really don't know why it triggers more than once, I did all kind of debug, checked the html structure and everything seems flawless.
Any kind soul got an idea in what is wrong?
Regards
I suspect that somehow the $(document).ready() function is executed as many times as your answers, so the click event handler is binded the same number of times for each answer. Perhaps it's the template that does that?
If that's indeed the problem and you can't find a solution for the template, try changing
$(".accepted.ans").on('click', function (e) {
to
$(".accepted.ans").off('click').on('click', function (e) {
to unbind all click event handlers but the last one.
try changing .closest(... to .parent(). Snippet below...
$(document).ready(function() {
$(".accepted.ans").on('click', function(e) {
e.preventDefault();
var current = $(this),
parent = current.parent();
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
console.log(aid);
$.get(url + '?question=' + qid + '&answer=' + aid, function(data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}
.ans {
position: static;
width: 90%;
height: 5em;
background: #f90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="one" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="two" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
<blockquote class="accept-answer text-right {if !$isMine} hidden{/if}">
<div class="accept" title="Accept this answer" data-url="{url('controller/api/questions/mark_as_solved')}" data-refresh="{url('controller/api/questions/refresh_accepted_answers')}" data-answer="three" data-question="{$question['publicationid']}">
<div class="accepted ans" id="{$answer['answerid']}" title="Unnacept this answer">
</div>
</div>
</blockquote>
Using jQuery, you need to prevent it's function listened by other event attached to its parental tags. So try the stopPropagation(); instead.
$(document).ready(function () {
$(".accepted.ans").on('click', function (e) {
e.stopPropagation();
e.preventDefault();
var parent = $(this).closest('.accept');
console.log(parent);
var current = $(this);
console.log(current);
var url = parent.data('url');
var qid = parent.data('question');
var aid = parent.data('answer');
$.get(url + '?question=' + qid + '&answer=' + aid, function (data) {
console.log("Reading...");
data = $.parseJSON(data);
console.log(aid);
console.log(e);
setAcceptedStatus(current, data.result);
});
});
});
function setAcceptedStatus(object, status) {
if (status === true) {
object.addClass('active');
}
}

Javascript innerHTML animation

I have a Countdown in Javascript and HTML. Its working through innerHTML and I want a animation when changing the values from innerHTML.
Countdown is working perfectly!
Javascript:
var jahr=2016, monat=5, tag=15, stunde=11, minute=2, sekunde=00; var zielDatum=new Date(jahr,monat-1,tag,stunde,minute,sekunde); function countdown() {
startDatum=new Date(); // Aktuelles Datum
if(startDatum<zielDatum) {
var jahre=0, monate=0, tage=0, stunden=0, minuten=0, sekunden=0;
while(startDatum<zielDatum) {
jahre++;
startDatum.setFullYear(startDatum.getFullYear()+1);
}
startDatum.setFullYear(startDatum.getFullYear()-1);
jahre--;
while(startDatum<zielDatum) {
monate++;
startDatum.setMonth(startDatum.getMonth()+1);
}
startDatum.setMonth(startDatum.getMonth()-1);
monate--;
while(startDatum.getTime()+(24*60*60*1000)<zielDatum) {
tage++;
startDatum.setTime(startDatum.getTime()+(24*60*60*1000));
}
stunden=Math.floor((zielDatum-startDatum)/(60*60*1000));
startDatum.setTime(startDatum.getTime()+stunden*60*60*1000);
minuten=Math.floor((zielDatum-startDatum)/(60*1000));
startDatum.setTime(startDatum.getTime()+minuten*60*1000);
sekunden=Math.floor((zielDatum-startDatum)/1000);
(jahre!=1)?jahre=jahre+"":jahre=jahre+"";
(monate!=1)?monate=monate+"":monate=monate+"";
(tage!=1)?tage=tage+"":tage=tage+"";
(stunden!=1)?stunden=stunden+"":stunden=stunden+"";
(minuten!=1)?minuten=minuten+"":minuten=minuten+"";
if(sekunden<10) sekunden="0"+sekunden;
(sekunden!=1)?sekunden=sekunden+"":sekunden=sekunden+"";
document.getElementById('days').innerHTML = ""+tage+"";
document.getElementById('hours').innerHTML = ""+stunden+"";
document.getElementById('minutes').innerHTML = ""+minuten+"";
document.getElementById('seconds').innerHTML = ""+sekunden+"";
if(tage==1){
dayText = "Tag";
} else {
dayText = "Tage";
}
if(stunden==1){
hoursText = "Stunde";
} else {
hoursText = "Stunden";
}
if(minuten==1){
minutesText = "Minute";
} else {
minutesText = "Minuten";
}
if(sekunden==1){
secondsText = "Sekunde";
} else {
secondsText = "Sekunden";
}
document.getElementById('daysText').innerHTML = ""+dayText+"";
document.getElementById('hoursText').innerHTML = ""+hoursText+"";
document.getElementById('minutesText').innerHTML = ""+minutesText+"";
document.getElementById('secondsText').innerHTML = ""+secondsText+"";
setTimeout('countdown()',200);
} else {
}
}
HTML:
<div class="time days">
<div id="days" class="value">00</div>
<div id="daysText" class="unit">Days</div>
</div>
<div class="time hours">
<div id="hours" class="value">00</div>
<div id="hoursText" class="unit">Hours</div>
</div>
<div class="time minutes">
<div id="minutes" class="value">00</div>
<div id="minutesText" class="unit">Minutes</div>
</div>
<div class="time seconds">
<div id="seconds" class="value">00</div>
<div id="secondsText" class="unit">Seconds</div>
</div>
And how can I do for example a fadeInDown animation?
Thanks!
The easiest way to do this would probably be JQuery, found at JQuery.com.
I also found a similar question here: jquery animation on div innerhtml on change
As for your code, you'll want something like:
$('#daysText').fadeOut(1000, function()
{
$(this).html(dayText).fadeIn(1000);
});
$('#hoursText').fadeOut(1000, function()
{
$(this).html(hoursText).fadeIn(1000);
});
$('#minutesText').fadeOut(1000, function()
{
$(this).html(minutesText).fadeIn(1000);
});
$('#secondsText').fadeOut(1000, function()
{
$(this).html(secondsText).fadeIn(1000);
});
Note that this will only work with JQuery installed. Instructions to this can be found at http://jquery.com/download/
Short version of said instructions: Add the following code to your HTML (Commonly done near the bottom of the document) to include the JQuery library
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
You can't animate a text-node directly.
You'll have to animate a wrapping element, which will have dynamically set style values. Something like:
<span style="opacity:0;">your content</span>
Also, changing innerHTML is a complete replacement of existing elements, it will "break" any ongoing animations inside the parent element.

jquery trouble - onclick for gallery

I am trying to use image gallery for my website that I found here. I want to add one more functionality to this gallery.. I want a large image to be linked and when clicked on it to open in new tab url that is defined in code.
I have included the full code here:
<script type="text/javascript">
$(document).ready(function()
{
/*Your ShineTime Welcome Image*/
var default_image = 'images/large/default.jpg';
var default_caption = 'Welcome to my portfolio';
/*Load The Default Image*/
loadPhoto(default_image, default_caption);
function loadPhoto($url, $caption)
{
/*Image pre-loader*/
showPreloader();
var img = new Image();
jQuery(img).load( function()
{
jQuery(img).hide();
hidePreloader();
}).attr({ "src": $url });
$('#largephoto').css('background-image','url("' + $url + '")');
$('#largephoto').data('caption', $caption);
}
/* When a thumbnail is clicked*/
$('.thumb_container').click(function()
{
var handler = $(this).find('.large_image');
var newsrc = handler.attr('src');
var newcaption = handler.attr('rel');
loadPhoto(newsrc, newcaption);
});
/*When the main photo is hovered over*/
$('#largephoto').hover(function()
{
var currentCaption = ($(this).data('caption'));
var largeCaption = $(this).find('#largecaption');
largeCaption.stop();
largeCaption.css('opacity','0.9');
largeCaption.find('.captionContent').html(currentCaption);
largeCaption.fadeIn()
largeCaption.find('.captionShine').stop();
largeCaption.find('.captionShine').css("background-position","-550px 0");
largeCaption.find('.captionShine').animate({backgroundPosition: '550px 0'},700);
Cufon.replace('.captionContent');
},
function()
{
var largeCaption = $(this).find('#largecaption');
largeCaption.find('.captionContent').html('');
largeCaption.fadeOut();
});
/* When a thumbnail is hovered over*/
$('.thumb_container').hover(function()
{
$(this).find(".large_thumb").stop().animate({marginLeft:-7, marginTop:-7},200);
$(this).find(".large_thumb_shine").stop();
$(this).find(".large_thumb_shine").css("background-position","-99px 0");
$(this).find(".large_thumb_shine").animate({backgroundPosition: '99px 0'},700);
}, function()
{
$(this).find(".large_thumb").stop().animate({marginLeft:0, marginTop:0},200);
});
function showPreloader()
{
$('#loader').css('background-image','url("images/interface/loader.gif")');
}
function hidePreloader()
{
$('#loader').css('background-image','url("")');
}
});
</script>
And I have 15 thumbnails/photos like this:
<div class="thumbnails">
<br><br><br>
<!-- start entry-->
<div class="thumbnailimage">
<div class="thumb_container">
<div class="large_thumb">
<img src="images/thumbnails/sample1.jpg" class="large_thumb_image" alt="thumb">
<img alt="" src="images/large/sample1.jpg" class="large_image" rel="Image Sample">
<div class="large_thumb_border"> </div>
<div class="large_thumb_shine"> </div>
</div>
</div>
</div>
<!-- end entry-->
</div>
Any help? Thanks.
This should work, all you have to do is add data-large attributes to each image and on hover it displays a tooltip with the large image inside.
http://jsfiddle.net/DSjLk/

Categories

Resources