Reputation: 14917
After write this question, I have been working in a example to develope two history buttons (undo and redo) with some divs which can be resized or draggable.
More or less, it's working, but I have a problem because I don't know how to do that the buttons undo or redo don't need to be pressed two times by the user.
I am storing the star event of drag and resize for undo, and I'm storing the stop event of drag and resize for the redo.
I have some ideas in mind for solve the problem, but I don't like, one of them if check if the div has the same style, make another redo or undo.
Can anybody explain me how can I do that in a correct way? Here you have a Fiddle with all the funcionality
HTML
Undo Redo<div class="workspace">
<div class="editable" id="panel1" style="width:50px; height:50px; left: 10px; top:10px; background-color: #3498db;"></div>
<div class="editable" id="panel2" style="width:50px; height:50px; left: 70px; top:10px; background-color: #f1c40f"></div>
<div class="editable" id="panel3" style="width:50px; height:50px; left: 130px; top:10px; background-color: #16a085;"></div>
</div>
CSS
.editable
{
position: absolute;
display: inline-block;
}
.workspace
{
top: 50px;
width: 100%;
height: 100%;
position: absolute;
}
.buttonsMenu
{
position:absolute;
padding:20px;
height: 30px;
}
JAVASCRIPT
//History Object
var historyApp = {
stackStyle : [],
stackId : [],
counter : -1,
add : function(style, id){
++this.counter;
this.stackStyle[this.counter] = style;
this.stackId[this.counter] = id;
this.doSomethingWith(style, id);
// delete anything forward of the counter
this.stackStyle.splice(this.counter+1);
},
undo : function(){
--this.counter;
this.doSomethingWith(this.stackStyle[this.counter],this.stackId[this.counter]);
},
redo : function(){
++this.counter;
this.doSomethingWith(this.stackStyle[this.counter],this.stackId[this.counter]);
},
doSomethingWith : function(style, id){
//Check if make buttons undo/redo disabled or enabled
if(this.counter <= -1)
{
$('#undo').addClass('disabled');
$('#redo').removeClass('disabled');
return;
}
else
{
$('#undo').removeClass('disabled');
}
if(this.counter == this.stackStyle.length)
{
$('#redo').addClass('disabled');
$('#undo').removeClass('disabled');
return;
}
else
{
$('#redo').removeClass('disabled');
}
console.log(style + ' - ' + id);
//Apply history style
$('#' + id).attr('style', style);
console.log(this.counter + ' - ' + this.stackStyle.length);
}
};
$(document).ready(function (e) {
//make class .editable draggable
$('.editable').draggable(
{
stop: stopHandlerDrag,
start: startHandlerDrag
});
//make class .editable resizable
$('.editable').resizable(
{
stop: stopHandlerResize,
start: startHandlerResize
});
});
//Stop Handler Drag
function stopHandlerDrag(event, ui)
{
var style = $(ui.helper).attr('style');
var id = $(ui.helper).attr('id');
historyApp.add(style, id);
}
//Star Handler Drag
function startHandlerDrag(event, ui)
{
var style = $(ui.helper).attr('style');
var id = $(ui.helper).attr('id');
historyApp.add(style, id);
}
//Stop Handler Resize
function stopHandlerResize(event, ui)
{
var style = $(ui.helper).attr('style');
var id = $(ui.helper).attr('id');
historyApp.add(style, id);
}
//Star Handler Resize
function startHandlerResize(event, ui)
{
var style = $(ui.helper).attr('style');
var id = $(ui.helper).attr('id');
historyApp.add(style, id);
}
//Click Events For Redo and Undo
$(document).on('click', '#redo', function () {
historyApp.redo();
});
$(document).on('click', '#undo', function () {
historyApp.undo();
});
Upvotes: 1
Views: 1937
Reputation: 137084
Apparently your main issue is that you call history.add()
twice per event (start
+ stop
).
One solution could be to bind the start
event to trigger only once per ui
function startHandlerDrag(event, ui)
{
console.log('start drag');
var style = $(ui.helper).attr('style');
var id = $(ui.helper).attr('id');
historyApp.add(style, id);
//Dettach all events
$('#'+id).draggable("option", "revert", false);
$('#'+id).resizable("destroy");
//reassign stop events
$('#'+id).draggable(
{
stop: stopHandlerDrag,
start: ''
});
$('#'+id).resizable(
{
stop: stopHandlerResize,
start: ''
});
}
do the same with startHandlerResize
Ps: there seems to be a bug in your redo
function : I had some issues while I restarted from an "undone" position. But I let you look at this.
Upvotes: 1