forked from qwerty/tupali
282 lines
7.2 KiB
JavaScript
282 lines
7.2 KiB
JavaScript
/*
|
|
* jQuery Infinite Drag
|
|
* Version 0.3
|
|
* Copyright (c) 2010 Ian Li (http://ianli.com)
|
|
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
|
|
*
|
|
* Requires:
|
|
* jQuery http://jquery.com
|
|
*
|
|
* Reference:
|
|
* http://ianli.com/infinitedrag/ for Usage
|
|
*
|
|
* Versions:
|
|
* 0.3
|
|
* - Added move
|
|
* 0.2
|
|
* - Fixed problem with IE 8.0
|
|
* 0.1
|
|
* - Initial implementation
|
|
*/
|
|
|
|
(function($) {
|
|
/**
|
|
* Function to create InfiniteDrag object.
|
|
*/
|
|
$.infinitedrag = function(draggable, draggable_options, tile_options) {
|
|
return new InfiniteDrag(draggable, draggable_options, tile_options);
|
|
};
|
|
|
|
$.infinitedrag.VERSION = 0.3;
|
|
|
|
/**
|
|
* The InfiniteDrag object.
|
|
*/
|
|
var InfiniteDrag = function(draggable, draggable_options, tile_options) {
|
|
// Use self to reduce confusion about this.
|
|
var self = this;
|
|
|
|
var $draggable = $(draggable);
|
|
var $viewport = $draggable.parent();
|
|
$draggable.css({
|
|
position: "relative",
|
|
cursor: "move"
|
|
});
|
|
|
|
// Draggable options
|
|
var _do = (draggable_options) ? draggable_options : {};
|
|
|
|
// Tile options (DEFAULT)
|
|
var _to = {
|
|
class_name: "_tile",
|
|
width: 100,
|
|
height: 100,
|
|
start_col: 0,
|
|
start_row: 0,
|
|
range_col: [-1000000, 1000000],
|
|
range_row: [-1000000, 1000000],
|
|
oncreate: function($element, i, j) {
|
|
$element.text("");
|
|
// $element.css("background","url(librerias/notas/img/corcho.jpg)");
|
|
$element.css("background","url(./librerias/notas/img/corcho.jpg)");
|
|
// $element.class("holam");
|
|
|
|
}
|
|
};
|
|
// Override tile options.
|
|
for (var i in tile_options) {
|
|
if (tile_options[i] !== undefined) {
|
|
_to[i] = tile_options[i];
|
|
}
|
|
}
|
|
|
|
// Override tile options based on draggable options.
|
|
if (_do.axis == "x") {
|
|
_to.range_row = [_to.start_row, _to.start_row];
|
|
} else if (_do.axis == "y") {
|
|
_to.range_col = [_to.start_col, _to.start_col];
|
|
}
|
|
|
|
// Creates the tile at (i, j).
|
|
function create_tile(i, j) {
|
|
if (i < _to.range_col[0] || _to.range_col[1] < i) {
|
|
return;
|
|
} else if (j < _to.range_row[0] || _to.range_row[1] < j) {
|
|
return;
|
|
}
|
|
|
|
grid[i][j] = true;
|
|
var x = i * _to.width;
|
|
var y = j * _to.height;
|
|
var $e = $draggable.append('<div></div>');
|
|
|
|
var $new_tile = $e.children(":last");
|
|
$new_tile.attr({
|
|
"class": _to.class_name,
|
|
col: i,
|
|
row: j
|
|
}).css({
|
|
position: "absolute",
|
|
left: x,
|
|
top: y,
|
|
width: _to.width,
|
|
height: _to.height
|
|
});
|
|
|
|
_to.oncreate($new_tile, i, j);
|
|
};
|
|
|
|
// Updates the containment box wherein the draggable can be dragged.
|
|
var update_containment = function() {
|
|
// Update viewport info.
|
|
viewport_width = $viewport.width(),
|
|
viewport_height = $viewport.height(),
|
|
viewport_cols = Math.ceil(viewport_width / _to.width),
|
|
viewport_rows = Math.ceil(viewport_height / _to.height);
|
|
|
|
// Create containment box.
|
|
var half_width = _to.width / 2,
|
|
half_height = _to.height / 2,
|
|
viewport_offset = $viewport.offset(),
|
|
viewport_draggable_width = viewport_width - _to.width,
|
|
viewport_draggable_height = viewport_height - _to.height;
|
|
|
|
var containment = [
|
|
(-_to.range_col[1] * _to.width) + viewport_offset.left + viewport_draggable_width,
|
|
(-_to.range_row[1] * _to.height) + viewport_offset.top + viewport_draggable_height,
|
|
(-_to.range_col[0] * _to.width) + viewport_offset.left,
|
|
(-_to.range_row[0] * _to.height) + viewport_offset.top
|
|
];
|
|
|
|
$draggable.draggable("option", "containment", containment);
|
|
};
|
|
|
|
var update_tiles = function() {
|
|
var $this = $draggable;
|
|
var $parent = $this.parent();
|
|
|
|
// Problem with .position() in Chrome/WebKit:
|
|
// var pos = $(this).position();
|
|
// So, we compute it ourselves.
|
|
var pos = {
|
|
left: $this.offset().left - $parent.offset().left,
|
|
top: $this.offset().top - $parent.offset().top
|
|
}
|
|
|
|
var visible_left_col = Math.ceil(-pos.left / _to.width) - 1,
|
|
visible_top_row = Math.ceil(-pos.top / _to.height) - 1;
|
|
|
|
for (var i = visible_left_col; i <= visible_left_col + viewport_cols; i++) {
|
|
for (var j = visible_top_row; j <= visible_top_row + viewport_rows; j++) {
|
|
if (grid[i] === undefined) {
|
|
grid[i] = {};
|
|
} else if (grid[i][j] === undefined) {
|
|
create_tile(i, j);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// Public Methods
|
|
//-----------------
|
|
|
|
self.draggable = function() {
|
|
return $draggable;
|
|
};
|
|
|
|
self.disabled = function(value) {
|
|
if (value === undefined) {
|
|
return $draggable;
|
|
}
|
|
|
|
$draggable.draggable("option", "disabled", value);
|
|
|
|
$draggable.css({ cursor: (value) ? "default" : "move" });
|
|
};
|
|
|
|
self.move = function(col, row) {
|
|
var offset = $draggable.offset();
|
|
var move = {
|
|
left: col * _to.width,
|
|
top: row * _to.height
|
|
};
|
|
|
|
var new_offset = {
|
|
left: offset.left - move.left,
|
|
top: offset.top - move.top
|
|
};
|
|
|
|
if (_do.axis == "x") {
|
|
new_offset.top = offset.top;
|
|
} else if (_do.axis == "y") {
|
|
new_offset.left = offset.left;
|
|
}
|
|
|
|
var containment = $draggable.draggable("option", "containment");
|
|
|
|
if (containment[0] <= new_offset.left && new_offset.left <= containment[2]
|
|
&& containment[1] <= new_offset.top && new_offset.top <= containment[3]) {
|
|
$draggable.offset(new_offset);
|
|
update_tiles();
|
|
} else {
|
|
// Don't let the tile go beyond the right edge.
|
|
if (new_offset.left < containment[0]) {
|
|
new_offset.left = containment[0];
|
|
}
|
|
|
|
// Don't let the tile go beyond the left edge.
|
|
if (new_offset.left > containment[2]) {
|
|
new_offset.left = containment[2];
|
|
}
|
|
|
|
$draggable.offset(new_offset);
|
|
update_tiles();
|
|
}
|
|
};
|
|
|
|
self.center = function(col, row) {
|
|
var x = _to.width * col,
|
|
y = _to.height * row,
|
|
half_width = _to.width / 2,
|
|
half_height = _to.height / 2,
|
|
half_vw_width = $viewport.width() / 2,
|
|
half_vw_height = $viewport.height() / 2,
|
|
offset = $draggable.offset();
|
|
|
|
var new_offset = {
|
|
left: -x - (half_width - half_vw_width),
|
|
top: -y - (half_height - half_vw_height)
|
|
};
|
|
|
|
if (_do.axis == "x") {
|
|
new_offset.top = offset.top;
|
|
} else if (_do.axis == "y") {
|
|
new_offset.left = offset.left;
|
|
}
|
|
|
|
$draggable.offset(new_offset);
|
|
|
|
update_tiles();
|
|
};
|
|
|
|
// Setup
|
|
//--------
|
|
|
|
var viewport_width = $viewport.width(),
|
|
viewport_height = $viewport.height(),
|
|
viewport_cols = Math.ceil(viewport_width / _to.width),
|
|
viewport_rows = Math.ceil(viewport_height / _to.height);
|
|
|
|
$draggable.offset({
|
|
left: $viewport.offset().left - (_to.start_col * _to.width),
|
|
top: $viewport.offset().top - (_to.start_row * _to.height)
|
|
});
|
|
|
|
var grid = {};
|
|
for (var i = _to.start_col, m = _to.start_col + viewport_cols; i < m && (_to.range_col[0] <= i && i <= _to.range_col[1]); i++) {
|
|
grid[i] = {}
|
|
for (var j = _to.start_row, n = _to.start_row + viewport_rows; j < n && (_to.range_row[0] <= j && j <= _to.range_row[1]); j++) {
|
|
create_tile(i, j);
|
|
}
|
|
}
|
|
|
|
// Handle resize of window.
|
|
$(window).resize(function() {
|
|
// HACK:
|
|
// Update the containment when the window is resized
|
|
// because the containment boundaries depend on the offset of the viewport.
|
|
update_containment();
|
|
});
|
|
|
|
// The drag event handler.
|
|
_do.drag = function(e, ui) {
|
|
update_tiles();
|
|
};
|
|
|
|
$draggable.draggable(_do);
|
|
|
|
update_containment();
|
|
};
|
|
})(jQuery);
|