Saving The Location of Multiple Objects Using JQuery - javascript

So I have multiple objects of the same class type, which are draggable. I want to save each of their location after dragging, so that when the page is reloaded, they are at the saved location.
Here is the code:
$(function(){
var Pos = JSON.parse(localStorage.getItem("position"));
var currentPos = {
top : 0,
left : 0
};
var c = [];
$('.framewrap').each(function(){
id = $(this).attr("id");
alert(Pos[id].top);
$(this).css({
top : Pos[id].top,
left : Pos[id].left
});
$(this).draggable({
drag: function(event,ui){
currentPos = $(this).position();
c.push(currentPos);
localStorage.setItem("position", JSON.stringify(c))
}
});
});
});
The position gets saved, but the problem is that both the objects are assigned to the same position, rather than different. Looks like the position gets over-written each time.
Any one highlight what I might be doing wrong ?

Related

How to trigger events in dynamically changed element in javascript

I need to trigger mousedown event in dynamically changed element. I am making a image galary where if I click on small image then large image should be displayed with high quality image and user can view image by dragging large image in small div. For this is just changing the src of large image container image from jquery. Below is my code:
$(document).on("click", "#thumb_img", function () {
$("#loading").show();
var smallimg = $(this).attr("src");
var img = new Image();
img.src = smallimg.replace('thumbnail/', 'images/');
img.onload = function () {
$(".large-img").prop("src", this.src);
$("#loading").hide();
};
$("img.large-img").css({
width: "500px",
height: "100%",
position: "unset"
});
});
Above code changes the src of large image when small image is clicked and below code is for enabling drag on the large image generated.
var selected = null, // Object of the element to be moved
x_pos = 0, y_pos = 0, // Stores x & y coordinates of the mouse pointer
x_elem = 0, y_elem = 0; // Stores top, left values (edge) of the element
// Will be called when user starts dragging an element
function _drag_init(elem) {
// Store the object of the element which needs to be moved
selected = elem;
x_elem = x_pos - selected.offsetLeft;
y_elem = y_pos - selected.offsetTop;
}
// Will be called when user dragging an element
function _move_elem(e) {
// alert("ASdf");
x_pos = document.all ? window.event.clientX : e.pageX;
y_pos = document.all ? window.event.clientY : e.pageY;
if (selected !== null) {
selected.style.left = (x_pos - x_elem) + 'px';
selected.style.top = (y_pos - y_elem) + 'px';
}
}
// Destroy the object when we are done
function _destroy() {
selected = null;
}
// Bind the functions...
document.getElementById('large-img').onmousedown = function () {
_drag_init(this);
return false;
};
document.onmousemove = _move_elem;
document.onmouseup = _destroy;
This code works fine when page loads first time. Then When I clicked in another small image and It doesn't works.
EDITED
I had mentioned my code in JSFIDDLE. You can see the image is draggable when page loads in large image container but when you click on other thumbnail and try to drag the image in large image container then drag event is not triggering.
position: "unset" is the problem. Removed it and the problem gone.
http://jsfiddle.net/3abLhrep/3/
From your description and code, it looks like you have more than one element with id thumb_img, but IDs must be unique.

Continuous/infinite horizontal scroll on hover

I have a shelf which when you hover the left or right buttons scrolls left and right. However, at the moment this only scrolls a defined amount.. and this shelf will be populated via lazy loading, so there is no real way of knowing how wide the shelf is.
Sure, I could set the number to 99999999 and the animation speed to a similarly high number, but surely there's a smarter way to do it? Without plug-ins!
Thanks for the help..
Fiddle
$('.scroll-arrow').each(function(){
var modifier = ($(this).hasClass('right')) ? 1 : -1;
var sib = ('.shelf-slide');
var sl = 0;
$(this).hover(function() {
sl = $(this).siblings(sib).scrollLeft();
$(this).siblings(sib).stop();
$(this).siblings(sib).animate({scrollLeft: sl + (modifier * 1000)}, 5000, 'linear');
}, function() {
$(this).siblings(sib).stop();
});
});
you can create a function to keep animating while you hover the arrow like this
function animatecontent(ele,modifier){//function to scroll
var sl = ele.scrollLeft();
//120 should be the width of the ".content" and 500 the time to scroll 1 ".content"
ele.animate({scrollLeft: sl + (modifier * 120)}, 500, 'linear',function(){
if(hover){//on callback if it is still hover call the same function
animatecontent(ele,modifier);
}
});
};
var hover=false;
$('.scroll-arrow').each(function(){
var modifier = ($(this).hasClass('right')) ? 1 : -1;
var sib = ('.shelf-slide');
$(this).hover(function() {
hover=true;
$(this).siblings(sib).stop();
animatecontent($(this).siblings(sib),modifier);//pass the element to animate and the modifier
}, function() {
hover=false;
$(this).siblings(sib).stop();
});
});
http://jsfiddle.net/A3mPw/7/

Clicking on Same button to Reverse Javascript effect

So I am very very new to JavaScript and unfortunately I don't know the basics too well also.
I was working on a code to make an element hidden after clicking it and again reversing back the effect by clicking the same button but I am unable to do so. Please help me here is the code:
$(function() {
$('#boxclose').click(function(){
$('#md-share-window').animate({'bottom':'-90px'},500,function(){});
});
});
You can use a class to identify the state of the element you are animating.
Here's an example: http://jsfiddle.net/FgDaq/
$('#boxclose').click(function() {
var c = 'on',
el = '#md-share-window',
duration = 500;
if ($(el).hasClass(c)) {
$(el).animate({'bottom': 0}, duration)
.removeClass(c);
} else {
$(el).animate({'bottom': '-90px'}, duration)
.addClass(c);
}
});
You'll need to get the initial position (or hard code it) and keep track of whether you are in the initial or updated position:
$(function() {
var shareWindow = $('#md-share-window');
var initialPosition = shareWindow.css('bottom'); //get initial position
var atInitialPos = true; //whether this is the initial or updated position
$('#boxclose').on('click', function(){
var newPosition = atInitialPos ? '-90px' : initialPosition; //determines new position
shareWindow.animate({'bottom': newPosition}, 500);
atInitialPos = !atInitialPos; //toggle initial position boolean
});
});

jQuery drag and drop with sortable

I am having an issue trying to get an array out of JS using the sortable on some drag and drop elements.
A working demo can be found at:
Example
What I need to achieve:
Drag item on image, get x,y (done)
after all items have been placed, use jQuery sortable? to get array of id's with x,y coordinates.
array(23456->{xpos:234,ypos:234},23456->{xpos:234,ypos:234},....etc
I am not sure how to bind the sortable to the items only dropped on the image, and then get those values into an array
Here is the code so far:
jQuery(function($){
$('.dragThis').bind('click', function(){
$(this).css("border","3px solid #fff");
$(this).draggable({
containment: $('body'),
drag: function(){
$('#dropHere').droppable({
accept: '.dragThis',
over : function(){
$(this).animate({'border-width' : '3px', 'border-color' : '#0f0'}, 500);
}
});
},
stop: function(){
var position = $(this).position();
var parentPos = $('#dropHere').offset();
var xPos = position.left - parentPos.left;
var yPos = position.top - parentPos.top;
var finalOffset = $(this).position();
var finalxPos = xPos;
var finalyPos = yPos;
$('#finalX').text('Final X: ' + finalxPos);
$('#finalY').text('Final Y: ' + finalyPos);
//$('.dragThis').sortable();
console.log (finalxPos,finalyPos,$(this).attr("id"));
},
revert: 'invalid'
//connectToSortable: '#dropHere'
});
});
});
Any help getting pointed in the right direction, is greatly appreciated.
Just to clarify, I will be writing the values via AJAX to a DB for recall later.
Thanks in advance
Simple solution:
Add a class for those elements on their own 'drop' event, then get all of those have classes with a selector.
After that, a handy $.fn.each() and $.fn.offset() will help.
You can then work on those coordinates with top, left instead of your mentioned xpos, ypos.
Here is an example:
var coordinates = {};
$(".dropped").each(function(item) {
coordinates[$(item).attr("id")] = $(item).offset();
});

JQuery - animate moving DOM element to new parent?

I have an image tag inside of a table cell, that I'd love to move to another table cell, and have that movement animated.
The code looks something like this...
<td id="cell1"><img src="arrow.png" alt="Arrow"/></td>
<td id="cell2"></td>
I'd like to move "arrow.png" to "cell2", and have some kind of transition effect, preferably with JQuery.
Any ideas?
Thanks!
This is actually quite difficult because you have to remove and add it to the DOM but keep its position. I think you're looking for something like this. Basically we don't animate either the arrow in #cell1 or #cell2. We just create a new one in the body-tag and animate that. That way we don't have to worry about the table cell positions because we can position relative to the document.
var $old = $('#cell1 img');
//First we copy the arrow to the new table cell and get the offset to the document
var $new = $old.clone().appendTo('#cell2');
var newOffset = $new.offset();
//Get the old position relative to document
var oldOffset = $old.offset();
//we also clone old to the document for the animation
var $temp = $old.clone().appendTo('body');
//hide new and old and move $temp to position
//also big z-index, make sure to edit this to something that works with the page
$temp
.css('position', 'absolute')
.css('left', oldOffset.left)
.css('top', oldOffset.top)
.css('zIndex', 1000);
$new.hide();
$old.hide();
//animate the $temp to the position of the new img
$temp.animate( {'top': newOffset.top, 'left':newOffset.left}, 'slow', function(){
//callback function, we remove $old and $temp and show $new
$new.show();
$old.remove();
$temp.remove();
});
I think this should point you in the right direction.
#Pim Jager's answer is pretty good, however if you have object references to the original element they would break since the the original element was replaced with a clone
I came up with what I think is a slightly cleaner solution in that it only has a single clone that show up for animation then goes away, leaving the original in the new location.
function moveAnimate(element, newParent){
//Allow passing in either a jQuery object or selector
element = $(element);
newParent= $(newParent);
var oldOffset = element.offset();
element.appendTo(newParent);
var newOffset = element.offset();
var temp = element.clone().appendTo('body');
temp.css({
'position': 'absolute',
'left': oldOffset.left,
'top': oldOffset.top,
'z-index': 1000
});
element.hide();
temp.animate({'top': newOffset.top, 'left': newOffset.left}, 'slow', function(){
element.show();
temp.remove();
});
}
To use: moveAnimate('#ElementToMove', '#newContainer')
You'll need to do this in two steps: (1) animation (2) rehoming.
The animation you can take care of with .animate(), as #Ballsacian points out. The rehoming can be accomplished with .html() - for the example above,
var arrowMarkup = $('#cell1').html(); //grab the arrow
$('#cell1').html(""); //delete it from the first cell
$('#cell2').html(arrowMarkup); //add it to the second cell
Of course, you'll have to complicate that code to integrate the animation. And this way of doing it won't cause the selection (I'm assuming you're selecting a table row?) to activate rows between the old selection and the new one, as the arrow passes by them. That'd be even more complex to achieve.
I have extended one of the other answers a little further so that now you can pass an object as a third parameter which serves as a vehicle during the animation. For example, if you want to move some <li> from one <ul> to another, your <ul> likely has a certain class that gives the <li> its styling. So, it would really be handy to animate your <li> inside a temporary vehicle <ul> that provides for the same styling as either the source or the target <ul> of the animation:
//APPENDS AN ELEMENT IN AN ANIMATED FASHION
function animateAppendTo(el, where, float){
var pos0 = el.offset();
el.appendTo(where);
var pos1 = el.offset();
el.clone().appendTo(float ? float : 'body');
float.css({
'position': 'absolute',
'left': pos0.left,
'top': pos0.top,
'zIndex': 1000
});
el.hide();
float.animate(
{'top': pos1.top,'left': pos1.left},
'slow',
function(){
el.show();
float.remove();
});
}
I was trying #Davy8's function which is quite good, but I found it quite jarring when the moved element snapped off the page at the start then back in at the end. The other page elements suddenly shifting interrupted an otherwise smooth animation, but this likely would depend on your page layout.
So this is a modified version of #Davy8's function, which should also smoothly shrink and grow space between parents.
function moveAnimate(element, newParent,
slideAnimationSpeed/*=800*/, spacerAnimationSpeed/*=600*/)
{
//Allow passing in either a jQuery object or selector
element = $(element);
newParent= $(newParent);
slideAnimationSpeed=slideAnimationSpeed||800;
spacerAnimationSpeed=spacerAnimationSpeed||600;
var oldOffset = element.offset();
var tempOutgoing=element.clone().insertAfter(element);
tempOutgoing.hide(); //Don't take up space yet so 'newOffset' can be calculated correctly
element.appendTo(newParent);
var newOffset = element.offset();
var tempMover = element.clone().appendTo('body');
tempMover.css({
'position': 'absolute',
'left': oldOffset.left,
'top': oldOffset.top,
'z-index': 1000,
'margin':0 //Necessary for animation alignment if the source element had margin
});
element.hide();
element.show(spacerAnimationSpeed).css('visibility', 'hidden'); //Smoothly grow space at the target
tempMover.animate({'top': newOffset.top, 'left': newOffset.left}, slideAnimationSpeed, function(){
element.css('visibility', 'visible');
tempMover.remove();
});
tempOutgoing.show().css('visibility', 'hidden');
tempOutgoing.hide(spacerAnimationSpeed, function(){ tempOutgoing.remove() }); //smoothly shrink space at the source
}
If the animation doesn't have to be the thing moving, this question which uses fadeIn and fadeOut gives a simple, clean answer with no cloning and still conveys the motion quite well:
Re-ordering div positions with jQuery?
For anyone still viewing this, I found the provided examples didn't fit exactly what I wanted and they didn't account for margins, so here's my version:
jQuery.fn.extend({
moveElement : function (newParent, speed, after) {
var origEl = $(this);
var moveToEl = $(newParent);
var oldOffset = origEl.offset();
var temp = origEl.clone().appendTo('body');
temp.css({
'position' : 'absolute',
'left' : parseInt(oldOffset.left) - parseInt(origEl.css('margin-left')),
'margin' : origEl.css('margin'),
'top' : oldOffset.top,
'z-index' : 1000,
'height' : moveToEl.innerHeight(),
'width' : moveToEl.innerWidth()
});
var blankEl = $('<div></div>').css({
height : moveToEl.innerHeight(),
margin : moveToEl.css('margin'),
position : 'relative',
width : moveToEl.innerWidth()
});
if (after) {
origEl.insertAfter(moveToEl);
blankEl.insertAfter(newParent);
}
else {
origEl.insertBefore(moveToEl);
blankEl.insertBefore(newParent);
}
origEl.hide();
var newOffset = blankEl.offset();
temp.animate({
'top' : blankEl.offset().top - parseInt(moveToEl.css('margin-top')),
'left' : newOffset.left - parseInt(moveToEl.css('margin-left'))
}, speed, function () {
blankEl.remove();
origEl.show();
temp.remove();
});
}
});
Move an element before another: $('.elementToFind').moveElement('.targetElement', 1000);
Move an element after another: $('.elementToFind').moveElement('.targetElement', 1000, 'after');
JQuery http://docs.jquery.com/Downloading_jQuery
JQuery Effects http://docs.jquery.com/Effects/animate#paramsoptions
Example
$("#go1").click(function(){
$("#block1").animate( { width:"90%" }, { queue:false, duration:3000 } )
.animate( { fontSize:"24px" }, 1500 )
.animate( { borderRightWidth:"15px" }, 1500);
});

Categories

Resources