vendor/assets/javascripts/metro-ui/tile-drag.js in metro-ui-rails-0.15.8.12 vs vendor/assets/javascripts/metro-ui/tile-drag.js in metro-ui-rails-0.15.8.13
- old
+ new
@@ -1,71 +1,68 @@
/**
- * jQuery plugin for drag'n'drop tiles
+ * drag'n'drop plugin
*
- * to init plugin just add class 'tile-drag' to your tile-group element
- * or add attribute data-role="tile-drag"
+ * this plugin allows to drag tiles between groups
*
+ * this plugin auto enabled to 'tile-group' elements
+ * or elements with attribute data-role="tile-group"
+ *
* to handle drag/drop events use next code
+ *
-$(function(){
+ $(function(){
$('#tile_group_id').on('drag', function(e, draggingTile, parentGroup){
... your code ...
});
$('#tile_group_id').on('drop', function(e, draggingTile, targetGroup){
... your code ...
});
});
*
- * if you want to use drag'n'drop between groups use attribute data-param-group="any_id" to link groups
*/
(function($) {
$.TileDrag = function(element, options) {
- var defaults = {
- // if group sets and exists other same groups, it is possible to drag'n'drop from one group to another
- group: null
- };
+ var defaults = {};
var plugin = this;
plugin.settings = {};
var $element = $(element),
+ $startMenu,
$groups,
settings,
tiles,
$draggingTile,
$parentGroup, // parent group for dragging tile
draggingTileWidth,
draggingTileHeight,
$phantomTile,
tileDeltaX,
tileDeltaY,
- groupOffsetX,
- groupOffsetY,
tilesCoordinates,
tileSearchCount = 0, // uses for findTileUnderCursor function
tileUnderCursorIndex,
- tileUnderCursorSide;
+ tileUnderCursorSide,
+ newGroupsCoordinates,
+ newGroupSearchCount = 0,
+ newGroupPhantom,
+ targetType, // 'new' or 'existing' group
+ groupsMaxHeight,
+ mouseMoved,
+ tileDragTimer;
plugin.init = function() {
settings = plugin.settings = $.extend({}, defaults, options);
- // if group is set
- if (settings.group) {
- // search other elements with same group
- $groups = $('[data-role=tile-drag], .tile-drag').filter('[data-param-group=' + settings.group + ']');
- } else {
- $groups = $element;
- }
+ $startMenu = $('.tiles');
- // any tile-group must be relative
- $groups.css({
- 'position': 'relative'
- });
+ // search other 'tile-group' elements
+ $groups = $('[data-role=tile-group], .tile-group');
// select all tiles within group
tiles = $groups.children('.tile');
tiles.on('mousedown', startDrag);
@@ -74,21 +71,17 @@
var startDrag = function(event) {
var $tile,
tilePosition,
tilePositionX,
- tilePositionY,
- groupOffset;
+ tilePositionY;
event.preventDefault();
// currently dragging tile
- $draggingTile = $tile = $(this);
+ $tile = $draggingTile = $(this);
- // search parent group
- $parentGroup = $tile.parents('.tile-drag');
-
// dragging tile dimentions
draggingTileWidth = $tile.outerWidth();
draggingTileHeight = $tile.outerHeight();
// hidden tile to place it where dragging tile will dropped
@@ -101,109 +94,157 @@
$phantomTile.addClass('double');
} else if ($tile.hasClass('triple')) {
$phantomTile.addClass('triple');
} else if ($tile.hasClass('quadro')) {
$phantomTile.addClass('quadro');
- } else if ($tile.hasClass('double-vertical')) {
+ }
+ if ($tile.hasClass('double-vertical')) {
$phantomTile.addClass('double-vertical');
} else if ($tile.hasClass('triple-vertical')) {
$phantomTile.addClass('triple-vertical');
} else if ($tile.hasClass('quadro-vertical')) {
$phantomTile.addClass('quadro-vertical');
}
+
+ // place phantom tile instead dragging one
+ $phantomTile.insertAfter($tile);
+ targetType = 'existing';
+
+ // search parent group
+ $parentGroup = $tile.parents('.tile-group');
// dragging tile position within group
- tilePosition = $tile.position();
- tilePositionX = tilePosition.left;
- tilePositionY = tilePosition.top;
+ tilePosition = $tile.offset();
+ tilePositionX = tilePosition.left - (event.pageX - event.clientX);
+ tilePositionY = tilePosition.top - (event.pageY - event.clientY);
- // group element offset relate to document border
- groupOffset = $parentGroup.offset();
- groupOffsetX = groupOffset.left;
- groupOffsetY = groupOffset.top;
-
// pixels count between cursor and dragging tile border
- tileDeltaX = event.pageX - groupOffsetX - tilePositionX;
- tileDeltaY = event.pageY - groupOffsetY - tilePositionY;
+ tileDeltaX = event.clientX - tilePositionX;
+ tileDeltaY = event.clientY - tilePositionY;
- // place phantom tile instead dragging one
- $phantomTile.insertAfter($tile);
+ // move tile element to $draggingTileContainer
+ $tile.detach();
+ $tile.insertAfter($($groups.get(-1))); // it need for invalid IE z-index
- /*$tile.detach();
- $tile.appendTo($parentGroup);*/
-
- // still now it absolutely positioned
+ // from now it fixed positioned
$tile.css({
- 'position': 'absolute',
+ 'position': 'fixed',
'left': tilePositionX,
'top': tilePositionY,
'z-index': 100000
});
// store it for future
$tile.data('dragging', true);
storeTilesCoordinates();
+ storeNewGroupsCoordinates();
// some necessary event handlers
$(document).on('mousemove.tiledrag', dragTile);
- $(document).on('mouseup.tiledrag', dragStop);
+ $(document).one('mouseup.tiledrag', dragStop);
+ mouseMoved = false;
+
// triggering event
$groups.trigger('drag', [$draggingTile, $parentGroup]);
};
/**
* it function called on every mousemove event
*/
var dragTile = function (event) {
+ mouseMoved = true;
- // all we need is index of tile under cursor (and under dragging tile) if it exists
- var findTileIndex;
-
event.preventDefault();
// move dragging tile
$draggingTile.css({
- 'left': event.pageX - groupOffsetX - tileDeltaX,
- 'top': event.pageY - groupOffsetY - tileDeltaY
+ 'left': event.clientX - tileDeltaX,
+ 'top': event.clientY - tileDeltaY
});
+ clearTimeout(tileDragTimer);
+ tileDragTimer = setTimeout(function(){
+ findPlace(event);
+ }, 50);
+ };
+
+ // finding place where put dragging tile
+ var findPlace = function (event) {
+ // all we need is index of tile under cursor (and under dragging tile) if it exists
+ var findTileIndex,
+ findNewGroup;
+
findTileIndex = findTileUnderCursor(event);
if (findTileIndex) {
clearPlaceForTile($(tiles[findTileIndex]));
+ } else {
+ findNewGroup = findNewGroupUnderCursor(event);
+ if (findNewGroup) {
+ showNewGroupPhantom(findNewGroup.group, findNewGroup.side);
+ }
}
};
/**
* when this function called dragging tile dropping to clear place (instead phantom tile)
* removing events
* and some other necessary changes
*/
var dragStop = function (event) {
var targetGroup;
+
+ if (!mouseMoved) {
+ // emulate default click behavior
+ if ($draggingTile.is('a')) {
+ window.location.href = $draggingTile.attr('href');
+ }
+ } else {
+ event.preventDefault();
+ }
- event.preventDefault();
+ clearTimeout(tileDragTimer);
+ findPlace(event);
- $(document).off('mousemove.tiledrag');
- $(document).off('mouseup.tiledrag');
-
$draggingTile.detach();
- $draggingTile.insertAfter($phantomTile);
+ // it is two way now: drop to existing group or drop to new group
+ // first drop to existing group
+ if (targetType === 'existing') {
+ $draggingTile.insertAfter($phantomTile);
+ targetGroup = $phantomTile.parents('.tile-group');
+ $phantomTile.remove();
+ } else {
+ newGroupPhantom.css({
+ 'backgroundColor': '',
+ 'width': 'auto',
+ 'max-width': '322px',
+ 'height': ''
+ });
+ $draggingTile.appendTo(newGroupPhantom);
+ targetGroup = newGroupPhantom;
+ newGroupPhantom = undefined;
+ }
- targetGroup = $phantomTile.parents('.tile-drag');
- $phantomTile.remove();
+ // remove parent group if it was a last tile there
+ if ($parentGroup.find('.tile').length === 0) {
+ $parentGroup.remove();
+ }
$draggingTile.css({
'position': '',
'left': '',
'top': '',
'z-index': ''
});
$draggingTile.data('dragging', false);
+ $(document).off('mousemove.tiledrag');
+ $groups = $('[data-role=tile-group], .tile-group');
$groups.trigger('drop', [$draggingTile, targetGroup]);
+
+ $startMenu.trigger('changed');
};
/*
* stores tiles coordinates for future finding one tile under cursor
* excluding current dragging tile
@@ -229,24 +270,65 @@
}
});
};
/**
+ * if tile dragging under this place it will creating new group there
+ */
+ var storeNewGroupsCoordinates = function () {
+ groupsMaxHeight = 0;
+ newGroupsCoordinates = [];
+ $groups.each(function(index){
+ var offset,
+ width,
+ height,
+ $group;
+
+ $group = $(this);
+
+ offset = $group.offset();
+
+ width = $group.width();
+ height = $group.height();
+
+ // make it possible to insert new group before first one
+ if (index === 0) {
+ newGroupsCoordinates.push({
+ x1: offset.left - 70 + tileDeltaX - draggingTileWidth / 2,
+ x2: offset.left + tileDeltaX - draggingTileWidth / 2,
+ y1: offset.top + tileDeltaY - draggingTileHeight / 2,
+ y2: offset.top + height + tileDeltaY - draggingTileHeight / 2,
+ side: 'before',
+ group: $group
+ });
+ }
+
+ newGroupsCoordinates.push({
+ x1: offset.left + width + tileDeltaX - draggingTileWidth / 2,
+ x2: offset.left + width + 70 + tileDeltaX - draggingTileWidth / 2,
+ y1: offset.top + tileDeltaY - draggingTileHeight / 2,
+ y2: offset.top + height + tileDeltaY - draggingTileHeight / 2,
+ side: 'after',
+ group: $group
+ });
+
+ if (groupsMaxHeight < height) {
+ groupsMaxHeight = height;
+ }
+
+ });
+ };
+
+ /**
* search tile under cursor using tileCoordinates from storeTilesCoordinates function
* search occurred only one time per ten times for less load and more smooth
*/
var findTileUnderCursor = function (event) {
var i, coord,
tileIndex = false,
tileSide;
- if (tileSearchCount < 10) {
- tileSearchCount++;
- return false;
- }
- tileSearchCount = 0;
-
for (i in tilesCoordinates) {
if (!tilesCoordinates.hasOwnProperty(i)) return;
coord = tilesCoordinates[i];
if (coord.x1 < event.pageX && event.pageX < coord.x2 && coord.y1 < event.pageY && event.pageY < coord.y2) {
tileIndex = i;
@@ -269,35 +351,107 @@
tileUnderCursorIndex = tileIndex;
return tileIndex;
};
+ var findNewGroupUnderCursor = function (event) {
+ var i, coord, newGroup = false;
+
+ for (i in newGroupsCoordinates) {
+ if (!newGroupsCoordinates.hasOwnProperty(i)) return;
+ coord = newGroupsCoordinates[i];
+ if (coord.x1 < event.pageX && event.pageX < coord.x2 && coord.y1 < event.pageY && event.pageY < coord.y2) {
+ newGroup = coord;
+ break;
+ }
+ }
+
+ if (!newGroup) {
+ return false;
+ } else {
+ return newGroup;
+ }
+ };
+
/**
* just put phantom tile near tile under cursor (before or after)
* and remove previous phantom tile
*/
var clearPlaceForTile = function ($tileUnderCursor) {
var $oldPhantomTile,
- groupOffset;
+ $newParentGroup;
$oldPhantomTile = $phantomTile;
$phantomTile = $oldPhantomTile.clone();
+ targetType = 'existing';
// before or after, this is question ...
if (tileUnderCursorSide === 'before') {
$phantomTile.insertBefore($tileUnderCursor);
} else {
$phantomTile.insertAfter($tileUnderCursor);
}
+ if (newGroupPhantom) {
+ newGroupPhantom.remove();
+ }
$oldPhantomTile.remove();
- // it is necessary to store new tile coordinates
+
+ // check if it was last tile in group and it drag out
+ if ($parentGroup.find('.tile').length === 0) {
+ $newParentGroup = $tileUnderCursor.parent('.tile-group');
+ if ($parentGroup[0] !== $newParentGroup[0]) {
+ // and if it true, make parent group invisible
+ $parentGroup.css({
+ 'width': 0,
+ 'margin': 0
+ });
+ }
+ }
+
+ $startMenu.trigger('changed');
+ storeAllNecessaryCoordinates();
+ };
+
+ /**
+ * makes visible new group place
+ * @param relGroup relative group
+ * @param side 'after' or 'before'
+ */
+ var showNewGroupPhantom = function (relGroup, side) {
+ if ($phantomTile) {
+ $phantomTile.remove()
+ }
+ if (newGroupPhantom) {
+ newGroupPhantom.remove();
+ }
+
+ newGroupPhantom = $('<div class="tile-group"></div>');
+ newGroupPhantom.css({
+ 'height': groupsMaxHeight,
+ 'width': '70px',
+ 'backgroundColor': '#333333',
+ 'position': 'relative'
+ });
+ relGroup[side](newGroupPhantom);
+ targetType = 'new';
+
+ // check if it was last tile in group and it drag out
+ if ($parentGroup.find('.tile').length === 0) {
+ $parentGroup.css({
+ 'width': 0,
+ 'margin': 0
+ });
+ }
+
+ $startMenu.trigger('changed');
+ storeAllNecessaryCoordinates();
+ };
+
+ var storeAllNecessaryCoordinates = function () {
storeTilesCoordinates();
- // and parent group coordinates
- groupOffset = $parentGroup.offset();
- groupOffsetX = groupOffset.left;
- groupOffsetY = groupOffset.top;
+ storeNewGroupsCoordinates();
};
// return all groups involved to this plugin
plugin.getGroups = function () {
return $groups;
@@ -307,26 +461,24 @@
};
$.fn.TileDrag = function(options) {
- return this.each(function() {
- if (undefined == $(this).data('TileDrag')) {
- var plugin = new $.TileDrag(this, options);
- var $groups = plugin.getGroups();
- $groups.data('TileDrag', plugin);
- }
- });
+ //this.each(function() {
+ var group = $(this[0]);
+ if (undefined == group.data('TileDrag')) {
+ var plugin = new $.TileDrag(group, options);
+ var $groups = plugin.getGroups();
+ $groups.data('TileDrag', plugin);
+ }
+ //});
};
})(jQuery);
$(function(){
- var allTileGroups = $('[data-role=tile-drag], .tile-drag');
- allTileGroups.each(function (index, tileGroup) {
- var params = {};
- $tileGroup = $(tileGroup);
- params.group = $tileGroup.data('paramGroup');
- $tileGroup.TileDrag(params);
- });
+ var allTileGroups = $('[data-role=tile-group], .tile-group');
+ if (allTileGroups.length > 0) {
+ $(allTileGroups).TileDrag({});
+ }
});
\ No newline at end of file