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