revert mootools sortable move - javascript

I'm using mootools sortable to handle a simple image gallery function. If you move the image from the left column to the right column, the photo is added into the user's "photos" table by a storeImage call in the onComplete event.
Here's a simple fiddle of it: http://jsfiddle.net/JQja3/1/
My question is, if the storeImage call from the onComplete event fails, how can I revert the image back to the "available" left stack?

you need to store the groups and parents in a var and then revert, this will totally restore the old group and order.
this pattern will create a restore function that can undo it - every time.
http://jsfiddle.net/JQja3/6/
new Sortables('#example2 UL', {
clone: true,
revert: true,
opacity: 0.7,
onStart: function(el, clone) {
this.restore = (function() {
var oldParent = el.getParent(),
oldList = oldParent.getChildren();
return function() {
oldParent.adopt(oldList);
}
})();
},
onComplete: function(el, clone){
var storeImage = false; // this is false to simulate a bad return from the DB store call
if (!storeImage){
this.restore();
}
}
});

Related

fancytree drag n drop node revert back to original position

How do you make a node in fancytree revert back to it's original position after being dragged to a new place in the tree, for example after dropping the node to a new position I would have a confirmation dialog yes or no to move the object if the user says no it reverts back so in the drop there needs to be a move to a new destination shown but also have the confirmation and revert back yes or no. Or on drag start get the position and on drag drop revert to original position
$("#tree").fancytree({
extensions: ["dnd"],
// .. other options...
dnd: {
autoExpandMS: 400,
draggable: { // modify default jQuery draggable options
zIndex: 1000,
scroll: false,
containment: "parent",
revert: "invalid"
},
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
dragStart: function(node, data) {
// This function MUST be defined to enable dragging for the tree.
// Return false to cancel dragging of node.
// if( data.originalEvent.shiftKey ) ...
// if( node.isFolder() ) { return false; }
return true;
},
dragEnter: function(node, data) {
return true;
},
dragExpand: function(node, data) {
// return false to prevent auto-expanding data.node on hover
},
dragOver: function(node, data) {
},
dragLeave: function(node, data) {
},
dragStop: function(node, data) {
},
dragDrop: function(node, data) {
// revert node to back to it's original place
data.otherNode.moveTo(node, data.hitMode);
}
}
});
It's been a while since I've worked in fancytree, so I don't know the full details, but I think I can come up with an idea that might work:
When dropping your node, you should do 2 actions:
Persist your original position in node.data (node.data.prevParent = node.parent() or prevSibling if you want to keep the position in the siblings)
Fire off your dialog with your 2 options and pass the node reference
Your dialog basicly has 2 options:
Accept: delete node.data.prevParent and close the dialog
Reject: retrieve node.data.prevParent and move the node as a new child/sibling. Close the dialog afterwards
I hope this helps out a bit. Just in case you haven't found it: This also helps: fancytree documentation

iScroll page currently scrolling to detection

I use the following iScroll 5 code (generally, not so important: just a common scrolling page-by-page):
var myScroll = new IScroll('.scroller', {
mouseWheel: true,
scrollbars: true,
keyBindings: {
// doesn't matter
},
preventDefault: false,
fadeScrollbars: true,
snap: 'section', // <-- that's the key
wheelAction: 'scroll',
});
myScroll.on('beforeScrollStart', function (e) {
myScroll.preventDisabling = true;
});
myScroll.on('scrollMove', function (e) {
});
myScroll.on('scrollStart', function (e) {
// !!! I need the detection somewhere here !!!
if (!myScroll.preventDisabling) {
myScroll.disable();
disabledWasCalledInMeanwhile = true;
}
myScroll.preventDisabling = false;
});
var disabledWasCalledInMeanwhile = false;
// that's just to prevent jumping to another page before scrolling is finished
myScroll.on('scrollEnd', function (e) {
disabledWasCalledInMeanwhile = false;
window.setTimeout(function () {
if (!disabledWasCalledInMeanwhile)
myScroll.enable();
}, 250);
$('.labels>*').toggleClass('active', false)
.eq(this.currentPage.pageY).toggleClass('active', true);
});
myScroll.on('scrollCancel', function (e) {
myScroll.enable();
});
So, is there any chance to detect in beforeScrollStart or scrollStart the page I am going to scroll to? That's important to know for triggering that page items animation. Thanks!
I've used iScroll for a number of years (it is a excellent library), and I don't know of a built-in method of doing it. All the scroll events (except scrollEnd) before the iScroll snap is determined. However, with a slight modification of the library, I believe it is possible.
First, go into iScroll.js source and find the _nearestSnap method. At the bottom of the method, you will find the object you seek returned. Before the return, grab that data and pass it to a custom event. Unfortunately, iScroll's event system doesn't permit you to pass custom variables to events, so you'll have to do a work-around. In addition, you'll need to track the "flick" event because it won't trigger the _nearestSnap method.
iScroll modification in _nearestSnap method
this.customSnap({
x: x,
y: y,
pageX: i,
pageY: m
});
Update to class instance. Note the addition of "customSnap" method and the flick event.
myScroll = new IScroll('#wrapper', {snap: "p"});
myScroll.customSnap = function(data) {
console.log(data);
};
myScroll.on('flick', function() {
console.log(data.currentPage);
});
That should do it. Not necessarily the cleanest update, but in my testing, it does work.
http://jsfiddle.net/9pa4th4y/

meteor reactive client code: asking for best / right practise of writing code

Attached you find an example of client code: handling a jQuery simple slider which can changed its value by manual dragging or getting new values from server by message stream.
On Template.SLIDER.rendered event, I create the jQuery UI Slider on a Div element.
I save a reference var to the Div element in var Div_Slider
I did this, because I have to update the slider value also by event from server (here by stream notification)
I subscribed to the reactive Session var "slider_value" by Deps.autorun().
When Session.set is called, event should also update the Slider.value if this element was already rendered.
Instead using $('#servo-slide'). more than once and have to inspect the DOM again and again I prepared this local Div_Slider var as a reference and use it during interaction with the jQuery UI Slider.
Q: Is this the best and perfomant technic? - Creating local .js file scope vars to reference to commonly used elements?
Q: Do you have any suggestion to my sample code?
{ ... }
/*
--------------- Slider
*/
// save reference to slider
var Div_Slider = undefined;
// be reactive on Session value slider_value
Deps.autorun(function () {
// we just operate when available
if (Session.equals('slider_value', undefined))
return;
// be reactive on slider_value
var slider_value = Session.get('slider_value');
// set jQuery slider position
if (!_.isUndefined(Div_Slider)) {
Servo_Slider.slider({value: slider_value});
}
});
// listen to the stream
notifications.on('change_slider_value', function(new_value) {
// we are updating the sliders value, this will also update the Session value in onChange event
Session.set("slider_value", new_value);
});
Template.SLIDER.rendered = function () {
// save reference to elements
Div_Slider = $(this.find('#servo-slide'));
// update div as slider
Servo_Slider.slider({
min: 0,
max: 100,
step: 1,
range: "min",
value: Session.get("slider_value"),
change:
function(event, ui) {
// only do something if the event was generated here
if (event.originalEvent) {
// do your actions
}
}
});
}
{ ... }
Using Nathans comment and answer on another question from me, I optimized the code and report best case writing meteor code for jQuery slider.
// listen to the stream
notifications.on('change_slider_value', function(new_value) {
// we are updating the sliders value, this will also update the Session value in onChange event
Session.set("slider_value", new_value);
});
Template.SLIDER.rendered = function () {
// save reference to elements
var slider = $(this.find('#servo-slide'));
// update div as slider
slider.slider({
min: 0,
max: 100,
step: 1,
range: "min",
value: Session.get("slider_value"),
change:
function(event, ui) {
// only do something if the event was generated here
if (event.originalEvent) {
// do your actions
}
}
});
// be reactive on Session value slider_value
this.computation = Deps.autorun(function () {
// set jQuery slider position
slider.slider({value: Session.get('slider_value')});
});
}
Template.SLIDER.destroyed = function () {
// check if we added a computation and stop
if (this.computation)
this.computation.stop();
}

How to slideToggle Selectize.js dropdown?

I'm using the awesome Selectize.js plugin, and I'm trying to add a simple slide animation when the dropdown is opened using jQuery. And I also change the position to static.
http://jsfiddle.net/TAuEH/1/
I changed a this:
/**
* Shows the autocomplete dropdown containing
* the available options.
*/
open: function() {
var self = this;
if (self.isLocked || self.isOpen || (self.settings.mode === 'multi' && self.isFull())) return;
self.focus(true);
self.isOpen = true;
self.refreshClasses();
self.$dropdown.css({visibility: 'hidden', display: 'block'});
self.positionDropdown();
self.$dropdown.css({visibility: 'visible'});
self.trigger('dropdown_open', this.$dropdown);
},
/**
* Closes the autocomplete dropdown menu.
*/
close: function() {
var self = this;
if (!self.isOpen) return;
self.$dropdown.hide();
self.setActiveOption(null);
self.isOpen = false;
self.refreshClasses();
self.trigger('dropdown_close', self.$dropdown);
},
By this:
/**
* Shows the autocomplete dropdown containing
* the available options.
*/
open: function() {
var self = this;
if (self.isLocked || self.isOpen || (self.settings.mode === 'multi' && self.isFull())) return;
self.focus(true);
self.isOpen = true;
self.refreshClasses();
self.$dropdown.slideDown();
self.positionDropdown();
self.trigger('dropdown_open', this.$dropdown);
},
/**
* Closes the autocomplete dropdown menu.
*/
close: function() {
var self = this;
if (!self.isOpen) return;
self.$dropdown.slideUp();
self.setActiveOption(null);
self.isOpen = false;
self.refreshClasses();
self.trigger('dropdown_close', self.$dropdown);
},
Well, as you see, I'm afraid it does not open properly, and does not do the slideup animation when you close it... anyone has better idea to do it?
Any advice, tip or help will be appreciated, and if you need more info i'll edit the post.
Without any change on the plugin code, you can try using the events onDropdownOpen and onDropdownClose and force an animation.
It's a bit hacky, but it works.
Code:
$(document).ready(function () {
$('#sel').selectize({
create: false,
sortField: 'text',
onDropdownOpen: function () {
$(".selectize-dropdown").hide().slideToggle();
},
onDropdownClose: function () {
$(".selectize-dropdown").show().slideToggle();
}
});
});
Demo: http://jsfiddle.net/IrvinDominin/cHxcZ/
EDIT
In the previous version there is an issue when you try to close it pressing the input again, solved using stop.
Ref:
When .stop() is called on an element, the currently-running animation
(if any) is immediately stopped. If, for instance, an element is being
hidden with .slideUp() when .stop() is called, the element will now
still be displayed, but will be a fraction of its previous height.
Callback functions are not called.
If more than one animation method is called on the same element, the
later animations are placed in the effects queue for the element.
These animations will not begin until the first one completes. When
.stop() is called, the next animation in the queue begins immediately.
If the clearQueue parameter is provided with a value of true, then the
rest of the animations in the queue are removed and never run.
Code:
$(document).ready(function () {
$('#sel').selectize({
create: false,
sortField: 'text',
onDropdownOpen: function ($dropdown) {
$dropdown.stop().hide().slideToggle();
},
onDropdownClose: function ($dropdown) {
$dropdown.stop().show().slideToggle();
}
});
});
Demo: http://jsfiddle.net/IrvinDominin/cHxcZ/1/

Script.aculo.us Drag 'n' Drop - Revert onEnd condition

I'm trying to revert a draggable if a condition returns false. So for instance, I'd like to do the following:
new Draggable('myelement', {
onStart: function() {
// do something
},
onEnd: function() {
var condition = getConditionVal();
if (!condition) revert to original position
else {
// do something else
}
}
});
Would this be possible? Not sure if "droppables" would work in this case since the droppable area changes dynamically.
Scriptaculous drag/drop is designed to have all kinds of fancy stuff easily added.
Of course you can edit the revert option any time.
To change the value of the revert-option of an draggable, just reset the revert-option:
var myDraggable = new Draggable('myelement', {
onStart: function() {
// do something
},
onEnd: function() {
var condition = getConditionVal();
if (!condition){
myDraggable.options.revert = true;
}
else {
myDraggable.options.revert = false;
// do something else
}
};
});
Scriptaculous does the revert right after the onEnd event call,
which gives us the possibility of changing it before it will be executed.
Scriptaculous's drag/drop code wasn't designed to have conditional revert. You can have revert or no revert. That's all, sadly.
This feature has been requested many times but scripty/prototype has waned in popularity over the years, so it's doubtful this feature will ever be added.

Categories

Resources