UNPKG

front-angular-resizable

Version:

A directive for creating resizable containers in angular.

161 lines (146 loc) 7.3 kB
angular.module('angularResizable', []) .directive('resizable', function() { var toCall; function throttle(fun) { if (toCall === undefined) { toCall = fun; setTimeout(function() { toCall(); toCall = undefined; }, 100); } else { toCall = fun; } } return { restrict: 'AE', scope: { rDirections: '=', rCenteredX: '=', rCenteredY: '=', rWidth: '=', rHeight: '=', rFlex: '=', rGrabber: '@', rDisabled: '@', rNoThrottle: '=' }, link: function(scope, element, attr) { var flexBasis = 'flexBasis' in document.documentElement.style ? 'flexBasis' : 'webkitFlexBasis' in document.documentElement.style ? 'webkitFlexBasis' : 'msFlexPreferredSize' in document.documentElement.style ? 'msFlexPreferredSize' : 'flexBasis'; // register watchers on width and height attributes if they are set scope.$watch('rWidth', function(value){ element[0].style[scope.rFlex ? flexBasis : 'width'] = scope.rWidth + 'px'; }); scope.$watch('rHeight', function(value){ element[0].style[scope.rFlex ? flexBasis : 'height'] = scope.rHeight + 'px'; }); element.addClass('resizable'); var style = window.getComputedStyle(element[0], null), w, h, dir = scope.rDirections || ['right'], vx = scope.rCenteredX ? 2 : 1, // if centered double velocity vy = scope.rCenteredY ? 2 : 1, // if centered double velocity inner = scope.rGrabber ? scope.rGrabber : '<span></span>', start, dragDir, axis, info = {}; var updateInfo = function(e) { info.width = false; info.height = false; if(axis === 'x') info.width = parseInt(element[0].style[scope.rFlex ? flexBasis : 'width']); else info.height = parseInt(element[0].style[scope.rFlex ? flexBasis : 'height']); info.id = element[0].id; info.evt = e; }; var getClientX = function(e) { return e.touches ? e.touches[0].clientX : e.clientX; }; var getClientY = function(e) { return e.touches ? e.touches[0].clientY : e.clientY; }; var dragging = function(e) { var prop, offset = axis === 'x' ? start - getClientX(e) : start - getClientY(e); switch(dragDir) { case 'top': prop = scope.rFlex ? flexBasis : 'height'; element[0].style[prop] = h + (offset * vy) + 'px'; break; case 'bottom': prop = scope.rFlex ? flexBasis : 'height'; element[0].style[prop] = h - (offset * vy) + 'px'; break; case 'right': prop = scope.rFlex ? flexBasis : 'width'; element[0].style[prop] = w - (offset * vx) + 'px'; break; case 'left': prop = scope.rFlex ? flexBasis : 'width'; element[0].style[prop] = w + (offset * vx) + 'px'; break; } updateInfo(e); function resizingEmit(){ scope.$emit('angular-resizable.resizing', info); } if (scope.rNoThrottle) { resizingEmit(); } else { throttle(resizingEmit); } }; var dragEnd = function(e) { updateInfo(); scope.$emit('angular-resizable.resizeEnd', info); scope.$apply(); document.removeEventListener('mouseup', dragEnd, false); document.removeEventListener('mousemove', dragging, false); document.removeEventListener('touchend', dragEnd, false); document.removeEventListener('touchmove', dragging, false); element.removeClass('no-transition'); }; var dragStart = function(e, direction) { dragDir = direction; axis = dragDir === 'left' || dragDir === 'right' ? 'x' : 'y'; start = axis === 'x' ? getClientX(e) : getClientY(e); w = parseInt(style.getPropertyValue('width')); h = parseInt(style.getPropertyValue('height')); //prevent transition while dragging element.addClass('no-transition'); document.addEventListener('mouseup', dragEnd, false); document.addEventListener('mousemove', dragging, false); document.addEventListener('touchend', dragEnd, false); document.addEventListener('touchmove', dragging, false); // Disable highlighting while dragging if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble = true; e.returnValue = false; updateInfo(e); scope.$emit('angular-resizable.resizeStart', info); scope.$apply(); }; dir.forEach(function (direction) { var grabber = document.createElement('div'); // add class for styling purposes grabber.setAttribute('class', 'rg-' + direction); grabber.innerHTML = inner; element[0].appendChild(grabber); grabber.ondragstart = function() { return false; }; var down = function(e) { var disabled = (scope.rDisabled === 'true'); if (!disabled && (e.which === 1 || e.touches)) { // left mouse click or touch screen dragStart(e, direction); } }; grabber.addEventListener('mousedown', down, false); grabber.addEventListener('touchstart', down, false); }); } }; });