├── .gitignore ├── README.md ├── bower.json ├── build ├── css │ └── drag-and-drop.css └── js │ ├── angular-drag-and-drop.js │ └── angular-drag-and-drop.min.js ├── examples ├── index.html ├── js │ └── sample-app.js └── vendor │ └── angular │ └── angular.min.js ├── gulpfile.coffee ├── package.json └── src ├── app └── angular-drag-and-drop.coffee └── less └── drag-and-drop.less /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | .DS_Store 3 | node_modules/ 4 | **/*/.DS_Store 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Drag and Drop 2 | Customizable drag and drop behaviour for Angular. 3 | 4 | ### [Demo](http://lane.github.io/angular-drag-and-drop/) 5 | 6 | ## Getting Started 7 | 8 | ### Bower 9 | bower install angular-drag-and-drop-directives 10 | 11 | Or download the files from github, then: 12 | 13 | **In your HTML:** 14 | 15 | 1. Add `angular-drag-and-drop.js` 16 | 2. Add `angular-drag-and-drop.css` 17 | 3. Add required markup 18 | 19 | ```html 20 | 21 | 22 | 23 |

Anything in here

24 |

will be draggable

25 |
26 | 27 | 28 |

Drop Here

29 |
30 | 31 |
32 | ``` 33 | 34 | **In your Angular module:** 35 | 36 | 1. Add `"laneolson.ui.dragdrop"` as a dependency to the module. 37 | 2. In your controller, add functions for handling various events in the drag and drop. 38 | 39 | ## Customizing 40 | 41 | ### Directive Attributes 42 | You can pass various functions and options to the directive by assigning the following attributes: 43 | 44 | #### `drag-and-drop` - element or attribute 45 | - `on-drag-start`: function - fired when an item starts being dragged 46 | - `on-drag-end`: function - fired when an item is released 47 | - `on-drag-enter`: function - fired when an item is dragged over a drop spot 48 | - `on-drag-leave`: function - fired when an item is dragged outside of a drop spot 49 | - `on-item-placed`: function - fired when an item is dropped inside of a drop spot 50 | - `on-item-removed`: function - fired when and item is removed from its drop spot 51 | - `enable-swap`: boolean - an item will be swapped out when dropping a drag item on to a drop spot that has reached its maximum number of items 52 | - `fixed-positions`: boolean - when set to true, items return to their start positions when dropped outside of a drop spot 53 | 54 | #### `drag-item` - element or attribute 55 | - `drag-id`: an identifier that is used for this drag item. When set, the `drag-item` element will have a class that matches the `drag-id`. 56 | - `drag-data`: object - use to associate any additional data you may want for the draggable item. 57 | - `drop-to`: string - used to position the element within the drop spot (e.g. "top", or "bottom left") 58 | - `x`: int - the pixel x offset of the drag item from it's original position 59 | - `y`: int - the pixel y offset of the drag item from it's original position 60 | - `clone` : boolean - a clone item is dragged instead of the original item 61 | - `lock-vertical`: boolean - locks the item so it may only be moved left and right 62 | 63 | #### `drop-spot` - element or attribute 64 | - `drop-id`: string - an identifier that is used for this drop item. When set, the `drop-spot` element will have a class that matches the `drag-id`. 65 | - `max-items`: int - Used to specify the maximum number of items allowed in this drop spot 66 | 67 | ### Classes 68 | The following classes are added to elements to allow styling based on the current state of the drag and drop. 69 | 70 | - `dragging`: Added to the `drag-and-drop` wrapper when an item is being dragged. 71 | - `drop-hovering`: Added to an `drop-spot` element when an item has been dragged over top of the drop spot. 72 | - `drop-full`: Added to an `drop-spot` when it has reached its maximum number of items (assigned through `max-items`) 73 | - `drag-active`: added to a `drag-item` element when it is being dragged 74 | - `{{DRAG_ID}}`: added to an `drag-item` element if the `drag-id` attribute is set 75 | - `{{DROP_ID}}`: added to an `drop-spot` element if the `drop-id` attribute is set. An `drag-item` element will be given the class `in-{{DROP_ID}}` when it is placed within that drop spot. 76 | 77 | ## Todo 78 | 79 | - proper z-indexing when lifting and placing drag items 80 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-drag-and-drop-directives", 3 | "description": "angular directives that provide drag and drop behaviour with ability to specify callbacks for certain actions", 4 | "main": "build/js/angular-drag-and-drop.js", 5 | "authors": [ 6 | "Lane Olson" 7 | ], 8 | "license": "ISC", 9 | "keywords": [ 10 | "angular", 11 | "drag", 12 | "drop" 13 | ], 14 | "homepage": "https://github.com/Lane/angular-drag-and-drop", 15 | "moduleType": [], 16 | "ignore": [ 17 | "**/.*", 18 | "examples", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ], 24 | "dependencies": { 25 | "angular": "*" 26 | }, 27 | "version": "1.0.4" 28 | } 29 | -------------------------------------------------------------------------------- /build/css/drag-and-drop.css: -------------------------------------------------------------------------------- 1 | .drag-return drag-item, 2 | .drag-return .drag-item { 3 | -webkit-transition: all ease-in-out 0.5s; 4 | transition: all ease-in-out 0.5s; 5 | } 6 | drag-item, 7 | [drag-item], 8 | .drag-item { 9 | position: relative; 10 | -webkit-user-select: none; 11 | -moz-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | cursor: -webkit-grab; 15 | cursor: grab; 16 | z-index: 10; 17 | } 18 | drag-item:active, 19 | [drag-item]:active, 20 | .drag-item:active { 21 | cursor: -webkit-grabbing; 22 | cursor: grabbing; 23 | } 24 | .drag-content { 25 | -webkit-transform: scale(1); 26 | -ms-transform: scale(1); 27 | transform: scale(1); 28 | -webkit-transition: all 0.1s ease-in-out; 29 | transition: all 0.1s ease-in-out; 30 | } 31 | .drag-active { 32 | z-index: 20; 33 | } 34 | .clone { 35 | opacity: 0; 36 | z-index: 0; 37 | } 38 | .clone-active { 39 | opacity: 1; 40 | z-index: 9999; 41 | } 42 | -------------------------------------------------------------------------------- /build/js/angular-drag-and-drop.js: -------------------------------------------------------------------------------- 1 | var module; 2 | 3 | module = angular.module("laneolson.ui.dragdrop", []); 4 | 5 | module.directive('dragAndDrop', [ 6 | '$document', function($document) { 7 | return { 8 | restrict: 'AE', 9 | scope: { 10 | onItemPlaced: "&", 11 | onItemRemoved: "&", 12 | onDrag: "&", 13 | onDragStart: "&", 14 | onDragEnd: "&", 15 | onDragEnter: "&", 16 | onDragLeave: "&", 17 | enableSwap: "=", 18 | fixedPositions: "=" 19 | }, 20 | require: 'dragAndDrop', 21 | controller: [ 22 | '$q', '$scope', function($q, $scope) { 23 | var currentDroppable, draggables, droppables, element, handlers, isInside, isIntersecting, isReady; 24 | $scope.draggables = draggables = []; 25 | $scope.droppables = droppables = []; 26 | $scope.isDragging = false; 27 | $scope.currentDraggable = null; 28 | currentDroppable = null; 29 | element = null; 30 | isReady = false; 31 | handlers = []; 32 | isInside = function(point, bounds) { 33 | var ref, ref1; 34 | return (bounds.left < (ref = point[0]) && ref < bounds.right) && (bounds.top < (ref1 = point[1]) && ref1 < bounds.bottom); 35 | }; 36 | isIntersecting = function(r1, r2) { 37 | return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); 38 | }; 39 | this.on = function(e, cb) { 40 | if (e === "ready" && isReady) { 41 | cb(); 42 | } 43 | return handlers.push({ 44 | name: e, 45 | cb: cb 46 | }); 47 | }; 48 | this.trigger = function(e) { 49 | var h, i, len, results; 50 | if (e === "ready") { 51 | isReady = true; 52 | } 53 | results = []; 54 | for (i = 0, len = handlers.length; i < len; i++) { 55 | h = handlers[i]; 56 | if (h.name === e) { 57 | results.push(h.cb()); 58 | } else { 59 | results.push(void 0); 60 | } 61 | } 62 | return results; 63 | }; 64 | this.isReady = function() { 65 | return isReady; 66 | }; 67 | this.setDragAndDropElement = function(el) { 68 | return element = el; 69 | }; 70 | this.getDragAndDropElement = function() { 71 | return element; 72 | }; 73 | this.checkForIntersection = function() { 74 | var dropSpot, i, len, results; 75 | results = []; 76 | for (i = 0, len = droppables.length; i < len; i++) { 77 | dropSpot = droppables[i]; 78 | if (isInside($scope.currentDraggable.midPoint, dropSpot)) { 79 | if (!dropSpot.isActive) { 80 | this.setCurrentDroppable(dropSpot); 81 | dropSpot.activate(); 82 | results.push(this.fireCallback('drag-enter')); 83 | } else { 84 | results.push(void 0); 85 | } 86 | } else { 87 | if (dropSpot.isActive) { 88 | this.setCurrentDroppable(null); 89 | dropSpot.deactivate(); 90 | results.push(this.fireCallback('drag-leave')); 91 | } else { 92 | results.push(void 0); 93 | } 94 | } 95 | } 96 | return results; 97 | }; 98 | this.setCurrentDraggable = function(draggable) { 99 | $scope.currentDraggable = draggable; 100 | if (draggable) { 101 | this.fireCallback('drag-start'); 102 | } 103 | return $scope.$evalAsync(function() { 104 | $scope.currentDraggable = draggable; 105 | if (draggable) { 106 | return $scope.isDragging = true; 107 | } else { 108 | return $scope.isDragging = false; 109 | } 110 | }); 111 | }; 112 | this.getCurrentDraggable = function() { 113 | return $scope.currentDraggable; 114 | }; 115 | this.setCurrentDroppable = function(droppable) { 116 | return currentDroppable = droppable; 117 | }; 118 | this.getCurrentDroppable = function() { 119 | return currentDroppable; 120 | }; 121 | this.addDroppable = function(droppable) { 122 | return droppables.push(droppable); 123 | }; 124 | this.addDraggable = function(draggable) { 125 | return draggables.push(draggable); 126 | }; 127 | this.fireCallback = function(type, e) { 128 | var state; 129 | state = { 130 | draggable: this.getCurrentDraggable(), 131 | droppable: this.getCurrentDroppable(), 132 | dragEvent: e 133 | }; 134 | switch (type) { 135 | case 'drag-end': 136 | if (typeof $scope.onDragEnd === "function") { 137 | $scope.onDragEnd(state); 138 | } 139 | return this.trigger("drag-end"); 140 | case 'drag-start': 141 | if (typeof $scope.onDragStart === "function") { 142 | $scope.onDragStart(state); 143 | } 144 | return this.trigger("drag-start"); 145 | case 'drag': 146 | return typeof $scope.onDrag === "function" ? $scope.onDrag(state) : void 0; 147 | case 'item-assigned': 148 | return typeof $scope.onItemPlaced === "function" ? $scope.onItemPlaced(state) : void 0; 149 | case 'item-removed': 150 | return typeof $scope.onItemRemoved === "function" ? $scope.onItemRemoved(state) : void 0; 151 | case 'drag-leave': 152 | return typeof $scope.onDragLeave === "function" ? $scope.onDragLeave(state) : void 0; 153 | case 'drag-enter': 154 | return typeof $scope.onDragEnter === "function" ? $scope.onDragEnter(state) : void 0; 155 | } 156 | }; 157 | } 158 | ], 159 | link: function(scope, element, attrs, ngDragAndDrop) { 160 | var bindEvents, moveEvents, onMove, onRelease, releaseEvents, unbindEvents; 161 | moveEvents = "touchmove mousemove"; 162 | releaseEvents = "touchend mouseup"; 163 | ngDragAndDrop.setDragAndDropElement(element); 164 | bindEvents = function() { 165 | $document.on(moveEvents, onMove); 166 | $document.on(releaseEvents, onRelease); 167 | ngDragAndDrop.on("drag-start", function() { 168 | return element.addClass("dragging"); 169 | }); 170 | return ngDragAndDrop.on("drag-end", function() { 171 | return element.removeClass("dragging"); 172 | }); 173 | }; 174 | unbindEvents = function() { 175 | $document.off(moveEvents, onMove); 176 | return $document.off(releaseEvents, onRelease); 177 | }; 178 | onRelease = function(e) { 179 | var draggable, dropSpot; 180 | draggable = ngDragAndDrop.getCurrentDraggable(); 181 | dropSpot = ngDragAndDrop.getCurrentDroppable(); 182 | if (draggable) { 183 | element.addClass("drag-return"); 184 | setTimeout(function() { 185 | return element.removeClass("drag-return"); 186 | }, 500); 187 | ngDragAndDrop.fireCallback('drag-end', e); 188 | draggable.deactivate(); 189 | if (dropSpot && !dropSpot.isFull) { 190 | ngDragAndDrop.fireCallback('item-assigned', e); 191 | draggable.assignTo(dropSpot); 192 | dropSpot.itemDropped(draggable); 193 | } else if (dropSpot && dropSpot.isFull && scope.enableSwap) { 194 | dropSpot.items[0].returnToStartPosition(); 195 | dropSpot.items[0].removeFrom(dropSpot); 196 | ngDragAndDrop.fireCallback('item-assigned', e); 197 | draggable.assignTo(dropSpot); 198 | dropSpot.itemDropped(draggable); 199 | ngDragAndDrop.fireCallback('item-removed', e); 200 | } else { 201 | draggable.isAssigned = false; 202 | if (scope.fixedPositions) { 203 | draggable.returnToStartPosition(); 204 | } 205 | } 206 | if (dropSpot) { 207 | dropSpot.deactivate(); 208 | } 209 | return ngDragAndDrop.setCurrentDraggable(null); 210 | } 211 | }; 212 | onMove = function(e) { 213 | var draggable; 214 | draggable = ngDragAndDrop.getCurrentDraggable(); 215 | if (draggable) { 216 | ngDragAndDrop.fireCallback('drag', e); 217 | if (e.touches && e.touches.length === 1) { 218 | draggable.updateOffset(e.touches[0].clientX ? e.touches[0].clientX : e.touches[0].pageX, 219 | e.touches[0].clientY ? e.touches[0].clientY : e.touches[0].pageY); 220 | } else { 221 | draggable.updateOffset(e.clientX, e.clientY); 222 | } 223 | return ngDragAndDrop.checkForIntersection(); 224 | } 225 | }; 226 | bindEvents(); 227 | return ngDragAndDrop.trigger("ready"); 228 | } 229 | }; 230 | } 231 | ]); 232 | 233 | module.directive('dragItem', [ 234 | '$window', '$document', '$compile', function($window, $document, $compile) { 235 | return { 236 | restrict: 'EA', 237 | require: '^dragAndDrop', 238 | scope: { 239 | x: "@", 240 | y: "@", 241 | dropTo: "@", 242 | dragId: "@", 243 | dragEnabled: "=", 244 | dragData: "=", 245 | clone: "=", 246 | lockHorizontal: "=", 247 | lockVertical: "=" 248 | }, 249 | link: function(scope, element, attrs, ngDragAndDrop) { 250 | var bindEvents, cloneEl, eventOffset, height, init, onPress, pressEvents, setClonePosition, startPosition, transformEl, unbindEvents, updateDimensions, w, width; 251 | cloneEl = width = height = startPosition = transformEl = eventOffset = pressEvents = w = null; 252 | updateDimensions = function() { 253 | scope.left = scope.x + element[0].offsetLeft; 254 | scope.right = scope.left + width; 255 | scope.top = scope.y + element[0].offsetTop; 256 | scope.bottom = scope.top + height; 257 | scope.midPoint = [scope.left + width / 2, scope.top + height / 2]; 258 | if (scope.lockVertical) { 259 | scope.percent = 100 * (scope.left + element[0].clientWidth / 2) / element.parent()[0].clientWidth; 260 | return scope.percent = Math.min(100, Math.max(0, scope.percent)); 261 | } 262 | }; 263 | setClonePosition = function() { 264 | var elemRect, leftOffset, topOffset; 265 | elemRect = element[0].getBoundingClientRect(); 266 | leftOffset = elemRect.left + eventOffset[0]; 267 | topOffset = elemRect.top + eventOffset[1]; 268 | return scope.updateOffset(leftOffset, topOffset); 269 | }; 270 | scope.setPercentPostion = function(xPercent, yPercent) { 271 | var newX, newY; 272 | newY = (element.parent()[0].clientHeight * (yPercent / 100)) - element[0].clientHeight / 2; 273 | newX = (element.parent()[0].clientWidth * (xPercent / 100)) - element[0].clientWidth / 2; 274 | return scope.setPosition(newX, newY); 275 | }; 276 | scope.setPosition = function(x, y) { 277 | scope.x = scope.lockHorizontal ? 0 : x; 278 | scope.y = scope.lockVertical ? 0 : y; 279 | updateDimensions(); 280 | return transformEl.css({ 281 | "transform": "translate(" + scope.x + "px, " + scope.y + "px)", 282 | "-webkit-transform": "translate(" + scope.x + "px, " + scope.y + "px)", 283 | "-ms-transform": "translate(" + scope.x + "px, " + scope.y + "px)" 284 | }); 285 | }; 286 | scope.updateOffset = function(x, y) { 287 | if (scope.clone) { 288 | return scope.setPosition(x - (eventOffset[0] + element[0].offsetLeft), y - (eventOffset[1] + element[0].offsetTop)); 289 | } else { 290 | return scope.setPosition(x - (eventOffset[0] + element[0].offsetLeft), y - (eventOffset[1] + element[0].offsetTop)); 291 | } 292 | }; 293 | scope.returnToStartPosition = function() { 294 | return scope.setPosition(startPosition[0], startPosition[1]); 295 | }; 296 | scope.assignTo = function(dropSpot) { 297 | scope.dropSpots.push(dropSpot); 298 | scope.isAssigned = true; 299 | if (dropSpot.dropId) { 300 | return element.addClass("in-" + dropSpot.dropId); 301 | } 302 | }; 303 | scope.removeFrom = function(dropSpot) { 304 | var index; 305 | index = scope.dropSpots.indexOf(dropSpot); 306 | if (index > -1) { 307 | if (dropSpot.dropId) { 308 | element.removeClass("in-" + dropSpot.dropId); 309 | } 310 | scope.dropSpots.splice(index, 1); 311 | if (scope.dropSpots.length < 1) { 312 | scope.isAssigned = false; 313 | } 314 | return dropSpot.removeItem(scope); 315 | } 316 | }; 317 | scope.addClass = function(className) { 318 | return element.addClass(className); 319 | }; 320 | scope.removeClass = function(className) { 321 | return element.removeClass(className); 322 | }; 323 | scope.toggleClass = function(className) { 324 | if (element.hasClass(className)) { 325 | return element.removeClass(className); 326 | } else { 327 | return element.addClass(className); 328 | } 329 | }; 330 | scope.activate = function() { 331 | element.addClass("drag-active"); 332 | return scope.isDragging = true; 333 | }; 334 | scope.deactivate = function() { 335 | eventOffset = [0, 0]; 336 | if (scope.clone) { 337 | cloneEl.removeClass("clone-active"); 338 | } 339 | element.removeClass("drag-active"); 340 | return scope.isDragging = false; 341 | }; 342 | bindEvents = function() { 343 | element.on(pressEvents, onPress); 344 | return w.bind("resize", updateDimensions); 345 | }; 346 | unbindEvents = function() { 347 | element.off(pressEvents, onPress); 348 | return w.unbind("resize", updateDimensions); 349 | }; 350 | onPress = function(e) { 351 | var dropSpot, elemRect, i, len, ref, spot; 352 | if (!scope.dragEnabled) { 353 | return; 354 | } 355 | if (e.touches && e.touches.length === 1) { 356 | eventOffset = [e.touches[0].clientX - scope.left, e.touches[0].clientY - scope.top]; 357 | } else { 358 | elemRect = element[0].getBoundingClientRect(); 359 | eventOffset = [e.clientX - elemRect.left, e.clientY - elemRect.top]; 360 | } 361 | if (scope.clone) { 362 | scope.returnToStartPosition(); 363 | cloneEl.addClass("clone-active"); 364 | setClonePosition(); 365 | } 366 | ngDragAndDrop.setCurrentDraggable(scope); 367 | scope.activate(); 368 | scope.isAssigned = false; 369 | ngDragAndDrop.checkForIntersection(); 370 | dropSpot = ngDragAndDrop.getCurrentDroppable(); 371 | ref = scope.dropSpots; 372 | for (i = 0, len = ref.length; i < len; i++) { 373 | spot = ref[i]; 374 | scope.removeFrom(spot); 375 | ngDragAndDrop.fireCallback('item-removed', e); 376 | } 377 | return e.preventDefault(); 378 | }; 379 | init = function() { 380 | var testing; 381 | if (scope.dragId) { 382 | element.addClass(scope.dragId); 383 | } 384 | eventOffset = [0, 0]; 385 | width = element[0].offsetWidth; 386 | height = element[0].offsetHeight; 387 | scope.dropSpots = []; 388 | scope.isAssigned = false; 389 | if (scope.x == null) { 390 | scope.x = 0; 391 | } 392 | if (scope.y == null) { 393 | scope.y = 0; 394 | } 395 | startPosition = [scope.x, scope.y]; 396 | pressEvents = "touchstart mousedown"; 397 | w = angular.element($window); 398 | updateDimensions(); 399 | ngDragAndDrop.addDraggable(scope); 400 | bindEvents(); 401 | if (scope.dragData) { 402 | angular.extend(scope, scope.dragData); 403 | } 404 | if (scope.clone) { 405 | scope[scope.dragData.key] = scope.dragData.value; 406 | testing = $compile(angular.element("
" + element.html() + "
"))(scope); 407 | cloneEl = testing; 408 | cloneEl.addClass("clone"); 409 | cloneEl.addClass(element.attr("class")); 410 | angular.element(ngDragAndDrop.getDragAndDropElement()).append(cloneEl); 411 | transformEl = cloneEl; 412 | } else { 413 | transformEl = element; 414 | } 415 | scope.returnToStartPosition(); 416 | scope.$emit('drag-ready', scope); 417 | return scope.$on('$destroy', function() { 418 | return unbindEvents(); 419 | }); 420 | }; 421 | return ngDragAndDrop.on("ready", init); 422 | } 423 | }; 424 | } 425 | ]); 426 | 427 | module.directive('dropSpot', [ 428 | '$window', function($window) { 429 | return { 430 | restrict: 'AE', 431 | require: '^dragAndDrop', 432 | transclude: true, 433 | template: "
", 434 | scope: { 435 | dropId: "@", 436 | maxItems: "=" 437 | }, 438 | link: function(scope, element, attrs, ngDragAndDrop) { 439 | var addItem, bindEvents, getDroppedPosition, handleResize, unbindEvents, updateDimensions, w; 440 | updateDimensions = function() { 441 | scope.left = element[0].offsetLeft; 442 | scope.top = element[0].offsetTop; 443 | scope.right = scope.left + element[0].offsetWidth; 444 | return scope.bottom = scope.top + element[0].offsetHeight; 445 | }; 446 | getDroppedPosition = function(item) { 447 | var dropSize, itemSize, xPos, yPos; 448 | dropSize = [scope.right - scope.left, scope.bottom - scope.top]; 449 | itemSize = [item.right - item.left, item.bottom - item.top]; 450 | switch (item.dropTo) { 451 | case "top": 452 | xPos = scope.left + (dropSize[0] - itemSize[0]) / 2; 453 | yPos = scope.top; 454 | break; 455 | case "bottom": 456 | xPos = scope.left + (dropSize[0] - itemSize[0]) / 2; 457 | yPos = scope.top + (dropSize[1] - itemSize[1]); 458 | break; 459 | case "left": 460 | xPos = scope.left; 461 | yPos = scope.top + (dropSize[1] - itemSize[1]) / 2; 462 | break; 463 | case "right": 464 | xPos = scope.left + (dropSize[0] - itemSize[0]); 465 | yPos = scope.top + (dropSize[1] - itemSize[1]) / 2; 466 | break; 467 | case "top left": 468 | xPos = scope.left; 469 | yPos = scope.top; 470 | break; 471 | case "bottom right": 472 | xPos = scope.left + (dropSize[0] - itemSize[0]); 473 | yPos = scope.top + (dropSize[1] - itemSize[1]); 474 | break; 475 | case "bottom left": 476 | xPos = scope.left; 477 | yPos = scope.top + (dropSize[1] - itemSize[1]); 478 | break; 479 | case "top right": 480 | xPos = scope.left + (dropSize[0] - itemSize[0]); 481 | yPos = scope.top; 482 | break; 483 | case "center": 484 | xPos = scope.left + (dropSize[0] - itemSize[0]) / 2; 485 | yPos = scope.top + (dropSize[1] - itemSize[1]) / 2; 486 | break; 487 | default: 488 | if (item.dropOffset) { 489 | xPos = scope.left + item.dropOffset[0]; 490 | yPos = scope.top + item.dropOffset[1]; 491 | } 492 | } 493 | return [xPos, yPos]; 494 | }; 495 | scope.itemDropped = function(item) { 496 | var added, newPos; 497 | added = addItem(item); 498 | if (added) { 499 | if (item.dropTo) { 500 | newPos = getDroppedPosition(item); 501 | return item.updateOffset(newPos[0], newPos[1]); 502 | } else { 503 | return item.dropOffset = [item.left - scope.left, item.top - scope.top]; 504 | } 505 | } else { 506 | if (scope.fixedPositions) { 507 | return item.returnToStartPosition(); 508 | } 509 | } 510 | }; 511 | addItem = function(item) { 512 | if (!scope.isFull) { 513 | scope.items.push(item); 514 | if (scope.items.length >= scope.maxItems) { 515 | scope.isFull = true; 516 | } 517 | return item; 518 | } 519 | return false; 520 | }; 521 | scope.removeItem = function(item) { 522 | var index; 523 | index = scope.items.indexOf(item); 524 | if (index > -1) { 525 | scope.items.splice(index, 1); 526 | if (scope.items.length < scope.maxItems) { 527 | return scope.isFull = false; 528 | } 529 | } 530 | }; 531 | scope.activate = function() { 532 | scope.isActive = true; 533 | return element.addClass("drop-hovering"); 534 | }; 535 | scope.deactivate = function() { 536 | scope.isActive = false; 537 | ngDragAndDrop.setCurrentDroppable(null); 538 | return element.removeClass("drop-hovering"); 539 | }; 540 | handleResize = function() { 541 | var i, item, len, newPos, ref, results; 542 | updateDimensions(); 543 | ref = scope.items; 544 | results = []; 545 | for (i = 0, len = ref.length; i < len; i++) { 546 | item = ref[i]; 547 | newPos = getDroppedPosition(item); 548 | results.push(item.updateOffset(newPos[0], newPos[1])); 549 | } 550 | return results; 551 | }; 552 | bindEvents = function() { 553 | return w.bind("resize", handleResize); 554 | }; 555 | unbindEvents = function() { 556 | return w.unbind("resize", handleResize); 557 | }; 558 | if (scope.dropId) { 559 | element.addClass(scope.dropId); 560 | } 561 | w = angular.element($window); 562 | bindEvents(); 563 | scope.$on('$destroy', function() { 564 | return unbindEvents(); 565 | }); 566 | updateDimensions(); 567 | scope.isActive = false; 568 | scope.items = []; 569 | return ngDragAndDrop.addDroppable(scope); 570 | } 571 | }; 572 | } 573 | ]); 574 | -------------------------------------------------------------------------------- /build/js/angular-drag-and-drop.min.js: -------------------------------------------------------------------------------- 1 | var module;module=angular.module("laneolson.ui.dragdrop",[]),module.directive("dragAndDrop",["$document",function(t){return{restrict:"AE",scope:{onItemPlaced:"&",onItemRemoved:"&",onDrag:"&",onDragStart:"&",onDragEnd:"&",onDragEnter:"&",onDragLeave:"&",enableSwap:"=",fixedPositions:"="},require:"dragAndDrop",controller:["$q","$scope",function(t,e){var r,n,o,a,i,s,u,l;e.draggables=n=[],e.droppables=o=[],e.isDragging=!1,e.currentDraggable=null,r=null,a=null,l=!1,i=[],s=function(t,e){var r,n;return e.left<(r=t[0])&&rt.right||e.rightt.bottom||e.bottomr;r++)e=i[r],e.name===t?o.push(e.cb()):o.push(void 0);return o},this.isReady=function(){return l},this.setDragAndDropElement=function(t){return a=t},this.getDragAndDropElement=function(){return a},this.checkForIntersection=function(){var t,r,n,a;for(a=[],r=0,n=o.length;n>r;r++)t=o[r],s(e.currentDraggable.midPoint,t)?t.isActive?a.push(void 0):(this.setCurrentDroppable(t),t.activate(),a.push(this.fireCallback("drag-enter"))):t.isActive?(this.setCurrentDroppable(null),t.deactivate(),a.push(this.fireCallback("drag-leave"))):a.push(void 0);return a},this.setCurrentDraggable=function(t){return e.currentDraggable=t,t&&this.fireCallback("drag-start"),e.$evalAsync(function(){return e.currentDraggable=t,t?e.isDragging=!0:e.isDragging=!1})},this.getCurrentDraggable=function(){return e.currentDraggable},this.setCurrentDroppable=function(t){return r=t},this.getCurrentDroppable=function(){return r},this.addDroppable=function(t){return o.push(t)},this.addDraggable=function(t){return n.push(t)},this.fireCallback=function(t,r){var n;switch(n={draggable:this.getCurrentDraggable(),droppable:this.getCurrentDroppable(),dragEvent:r},t){case"drag-end":return"function"==typeof e.onDragEnd&&e.onDragEnd(n),this.trigger("drag-end");case"drag-start":return"function"==typeof e.onDragStart&&e.onDragStart(n),this.trigger("drag-start");case"drag":return"function"==typeof e.onDrag?e.onDrag(n):void 0;case"item-assigned":return"function"==typeof e.onItemPlaced?e.onItemPlaced(n):void 0;case"item-removed":return"function"==typeof e.onItemRemoved?e.onItemRemoved(n):void 0;case"drag-leave":return"function"==typeof e.onDragLeave?e.onDragLeave(n):void 0;case"drag-enter":return"function"==typeof e.onDragEnter?e.onDragEnter(n):void 0}}}],link:function(e,r,n,o){var a,i,s,u,l,d;return i="touchmove mousemove",l="touchend mouseup",o.setDragAndDropElement(r),a=function(){return t.on(i,s),t.on(l,u),o.on("drag-start",function(){return r.addClass("dragging")}),o.on("drag-end",function(){return r.removeClass("dragging")})},d=function(){return t.off(i,s),t.off(l,u)},u=function(t){var n,a;return n=o.getCurrentDraggable(),a=o.getCurrentDroppable(),n?(r.addClass("drag-return"),setTimeout(function(){return r.removeClass("drag-return")},500),o.fireCallback("drag-end",t),n.deactivate(),a&&!a.isFull?(o.fireCallback("item-assigned",t),n.assignTo(a),a.itemDropped(n)):a&&a.isFull&&e.enableSwap?(a.items[0].returnToStartPosition(),a.items[0].removeFrom(a),o.fireCallback("item-assigned",t),n.assignTo(a),a.itemDropped(n),o.fireCallback("item-removed",t)):(n.isAssigned=!1,e.fixedPositions&&n.returnToStartPosition()),a&&a.deactivate(),o.setCurrentDraggable(null)):void 0},s=function(t){var e;return e=o.getCurrentDraggable(),e?(o.fireCallback("drag",t),t.touches&&1===t.touches.length?e.updateOffset(t.touches[0].clientX,t.touches[0].clientY):e.updateOffset(t.clientX,t.clientY),o.checkForIntersection()):void 0},a(),o.trigger("ready")}}}]),module.directive("dragItem",["$window","$document","$compile",function(t,e,r){return{restrict:"EA",require:"^dragAndDrop",scope:{x:"@",y:"@",dropTo:"@",dragId:"@",dragEnabled:"=",dragData:"=",clone:"=",lockHorizontal:"=",lockVertical:"="},link:function(e,n,o,a){var i,s,u,l,d,c,f,g,p,m,v,h,b,D;return s=D=l=p=m=u=f=b=null,h=function(){return e.left=e.x+n[0].offsetLeft,e.right=e.left+D,e.top=e.y+n[0].offsetTop,e.bottom=e.top+l,e.midPoint=[e.left+D/2,e.top+l/2],e.lockVertical?(e.percent=100*(e.left+n[0].clientWidth/2)/n.parent()[0].clientWidth,e.percent=Math.min(100,Math.max(0,e.percent))):void 0},g=function(){var t,r,o;return t=n[0].getBoundingClientRect(),r=t.left+u[0],o=t.top+u[1],e.updateOffset(r,o)},e.setPercentPostion=function(t,r){var o,a;return a=n.parent()[0].clientHeight*(r/100)-n[0].clientHeight/2,o=n.parent()[0].clientWidth*(t/100)-n[0].clientWidth/2,e.setPosition(o,a)},e.setPosition=function(t,r){return e.x=e.lockHorizontal?0:t,e.y=e.lockVertical?0:r,h(),m.css({transform:"translate("+e.x+"px, "+e.y+"px)","-webkit-transform":"translate("+e.x+"px, "+e.y+"px)","-ms-transform":"translate("+e.x+"px, "+e.y+"px)"})},e.updateOffset=function(t,r){return e.clone?e.setPosition(t-(u[0]+n[0].offsetLeft),r-(u[1]+n[0].offsetTop)):e.setPosition(t-(u[0]+n[0].offsetLeft),r-(u[1]+n[0].offsetTop))},e.returnToStartPosition=function(){return e.setPosition(p[0],p[1])},e.assignTo=function(t){return e.dropSpots.push(t),e.isAssigned=!0,t.dropId?n.addClass("in-"+t.dropId):void 0},e.removeFrom=function(t){var r;return r=e.dropSpots.indexOf(t),r>-1?(t.dropId&&n.removeClass("in-"+t.dropId),e.dropSpots.splice(r,1),e.dropSpots.length<1&&(e.isAssigned=!1),t.removeItem(e)):void 0},e.addClass=function(t){return n.addClass(t)},e.removeClass=function(t){return n.removeClass(t)},e.toggleClass=function(t){return n.hasClass(t)?n.removeClass(t):n.addClass(t)},e.activate=function(){return n.addClass("drag-active"),e.isDragging=!0},e.deactivate=function(){return u=[0,0],e.clone&&s.removeClass("clone-active"),n.removeClass("drag-active"),e.isDragging=!1},i=function(){return n.on(f,c),b.bind("resize",h)},v=function(){return n.off(f,c),b.unbind("resize",h)},c=function(t){var r,o,i,l,d,c;if(e.dragEnabled){for(t.touches&&1===t.touches.length?u=[t.touches[0].clientX-e.left,t.touches[0].clientY-e.top]:(o=n[0].getBoundingClientRect(),u=[t.clientX-o.left,t.clientY-o.top]),e.clone&&(e.returnToStartPosition(),s.addClass("clone-active"),g()),a.setCurrentDraggable(e),e.activate(),e.isAssigned=!1,a.checkForIntersection(),r=a.getCurrentDroppable(),d=e.dropSpots,i=0,l=d.length;l>i;i++)c=d[i],e.removeFrom(c),a.fireCallback("item-removed",t);return t.preventDefault()}},d=function(){var o;return e.dragId&&n.addClass(e.dragId),u=[0,0],D=n[0].offsetWidth,l=n[0].offsetHeight,e.dropSpots=[],e.isAssigned=!1,null==e.x&&(e.x=0),null==e.y&&(e.y=0),p=[e.x,e.y],f="touchstart mousedown",b=angular.element(t),h(),a.addDraggable(e),i(),e.dragData&&angular.extend(e,e.dragData),e.clone?(e[e.dragData.key]=e.dragData.value,o=r(angular.element("
"+n.html()+"
"))(e),s=o,s.addClass("clone"),s.addClass(n.attr("class")),angular.element(a.getDragAndDropElement()).append(s),m=s):m=n,e.returnToStartPosition(),e.$emit("drag-ready",e),e.$on("$destroy",function(){return v()})},a.on("ready",d)}}}]),module.directive("dropSpot",["$window",function(t){return{restrict:"AE",require:"^dragAndDrop",transclude:!0,template:"
",scope:{dropId:"@",maxItems:"="},link:function(e,r,n,o){var a,i,s,u,l,d,c;return d=function(){return e.left=r[0].offsetLeft,e.top=r[0].offsetTop,e.right=e.left+r[0].offsetWidth,e.bottom=e.top+r[0].offsetHeight},s=function(t){var r,n,o,a;switch(r=[e.right-e.left,e.bottom-e.top],n=[t.right-t.left,t.bottom-t.top],t.dropTo){case"top":o=e.left+(r[0]-n[0])/2,a=e.top;break;case"bottom":o=e.left+(r[0]-n[0])/2,a=e.top+(r[1]-n[1]);break;case"left":o=e.left,a=e.top+(r[1]-n[1])/2;break;case"right":o=e.left+(r[0]-n[0]),a=e.top+(r[1]-n[1])/2;break;case"top left":o=e.left,a=e.top;break;case"bottom right":o=e.left+(r[0]-n[0]),a=e.top+(r[1]-n[1]);break;case"bottom left":o=e.left,a=e.top+(r[1]-n[1]);break;case"top right":o=e.left+(r[0]-n[0]),a=e.top;break;case"center":o=e.left+(r[0]-n[0])/2,a=e.top+(r[1]-n[1])/2;break;default:t.dropOffset&&(o=e.left+t.dropOffset[0],a=e.top+t.dropOffset[1])}return[o,a]},e.itemDropped=function(t){var r,n;return r=a(t),r?t.dropTo?(n=s(t),t.updateOffset(n[0],n[1])):t.dropOffset=[t.left-e.left,t.top-e.top]:e.fixedPositions?t.returnToStartPosition():void 0},a=function(t){return e.isFull?!1:(e.items.push(t),e.items.length>=e.maxItems&&(e.isFull=!0),t)},e.removeItem=function(t){var r;return r=e.items.indexOf(t),r>-1&&(e.items.splice(r,1),e.items.lengtht;t++)r=a[t],o=s(r),i.push(r.updateOffset(o[0],o[1]));return i},i=function(){return c.bind("resize",u)},l=function(){return c.unbind("resize",u)},e.dropId&&r.addClass(e.dropId),c=angular.element(t),i(),e.$on("$destroy",function(){return l()}),d(),e.isActive=!1,e.items=[],o.addDroppable(e)}}}]); -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 115 | 116 | 117 | 120 | 121 |
122 |
123 |
131 | 132 |
133 |

Clone

134 |
135 | 136 |
137 |

Vertical postion locked

138 |
139 | 140 |
141 |

Item Three

142 |
143 | 144 |
145 |

Item Four

146 |
147 | 148 | 149 |

Drop Here

150 |
151 | 152 | 153 |
154 |
155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /examples/js/sample-app.js: -------------------------------------------------------------------------------- 1 | var app; 2 | 3 | app = angular.module('example', ['laneolson.ui.dragdrop']); 4 | 5 | app.controller("ExampleController", [ 6 | '$scope', function($scope) { 7 | $scope.$on("drag-ready", function(e,d) { console.log("Drag ready", e,d); }); 8 | return $scope.logThis = function(message, draggable, droppable) { 9 | return console.log(message, { 10 | 'draggable': draggable, 11 | 'droppable': droppable 12 | }); 13 | }; 14 | } 15 | ]); 16 | -------------------------------------------------------------------------------- /examples/vendor/angular/angular.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.4.7 3 | (c) 2010-2015 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(Q,X,w){'use strict';function I(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.7/"+(b?b+"/":"")+a;for(a=1;a").append(b).html();try{return b[0].nodeType===Pa?F(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+F(b)})}catch(d){return F(c)}}function xc(b){try{return decodeURIComponent(b)}catch(a){}} 17 | function yc(b){var a={};m((b||"").split("&"),function(b){var d,e,f;b&&(e=b=b.replace(/\+/g,"%20"),d=b.indexOf("="),-1!==d&&(e=b.substring(0,d),f=b.substring(d+1)),e=xc(e),A(e)&&(f=A(f)?xc(f):!0,ta.call(a,e)?J(a[e])?a[e].push(f):a[e]=[a[e],f]:a[e]=f))});return a}function Pb(b){var a=[];m(b,function(b,d){J(b)?m(b,function(b){a.push(la(d,!0)+(!0===b?"":"="+la(b,!0)))}):a.push(la(d,!0)+(!0===b?"":"="+la(b,!0)))});return a.length?a.join("&"):""}function ob(b){return la(b,!0).replace(/%26/gi,"&").replace(/%3D/gi, 18 | "=").replace(/%2B/gi,"+")}function la(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Qa.length;for(d=0;d/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=fb(a,c.strictDi);d.invoke(["$rootScope", 20 | "$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;Q&&e.test(Q.name)&&(c.debugInfoEnabled=!0,Q.name=Q.name.replace(e,""));if(Q&&!f.test(Q.name))return d();Q.name=Q.name.replace(f,"");da.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};x(da.resumeDeferredBootstrap)&&da.resumeDeferredBootstrap()}function $d(){Q.name="NG_ENABLE_DEBUG_INFO!"+Q.name;Q.location.reload()} 21 | function ae(b){b=da.element(b).injector();if(!b)throw Ea("test");return b.get("$$testability")}function Ac(b,a){a=a||"_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Bc){var a=pb();(ra=v(a)?Q.jQuery:a?Q[a]:w)&&ra.fn.on?(B=ra,P(ra.fn,{scope:Ra.scope,isolateScope:Ra.isolateScope,controller:Ra.controller,injector:Ra.injector,inheritedData:Ra.inheritedData}),b=ra.cleanData,ra.cleanData=function(a){var d;if(Qb)Qb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d= 22 | ra._data(f,"events"))&&d.$destroy&&ra(f).triggerHandler("$destroy");b(a)}):B=R;da.element=B;Bc=!0}}function qb(b,a,c){if(!b)throw Ea("areq",a||"?",c||"required");return b}function Sa(b,a,c){c&&J(b)&&(b=b[b.length-1]);qb(x(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ta(b,a){if("hasOwnProperty"===b)throw Ea("badname",a);}function Cc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,h=0;h")+d[2];for(d=d[0];d--;)c=c.lastChild;f=db(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function R(b){if(b instanceof R)return b;var a;G(b)&&(b=T(b), 30 | a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Tb("nosel");return new R(b)}if(a){a=X;var c;b=(c=Ef.exec(b))?[a.createElement(c[1])]:(c=Mc(b,a))?c.childNodes:[]}Nc(this,b)}function Ub(b){return b.cloneNode(!0)}function ub(b,a){a||vb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;dk&&this.remove(r.key);return b}},get:function(a){if(k").parent()[0])});var f= 53 | S(a,b,a,c,d,e);W.$$addScopeClass(a);var g=null;return function(b,c,d){qb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==wa(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Xb(g,B("
").append(a).html())):c?Ra.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);W.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a, 54 | b,c,d,e,f){function g(a,c,d,e){var f,k,l,r,n,t,O;if(q)for(O=Array(c.length),r=0;rD.priority)break;if(M=D.scope)D.templateUrl||(C(M)?(Q("new/isolated scope", 63 | u||S,D,v),u=D):Q("new/isolated scope",u,D,v)),S=S||D;y=D.name;!D.templateUrl&&D.controller&&(M=D.controller,ba=ba||fa(),Q("'"+y+"' controller",ba[y],D,v),ba[y]=D);if(M=D.transclude)N=!0,D.$$tlb||(Q("transclusion",z,D,v),z=D),"element"==M?(ia=!0,H=D.priority,M=v,v=d.$$element=B(X.createComment(" "+y+": "+d[y]+" ")),b=v[0],U(f,ua.call(M,0),b),Ka=W(M,e,H,g&&g.name,{nonTlbTranscludeDirective:z})):(M=B(Ub(b)).contents(),v.empty(),Ka=W(M,e));if(D.template)if(m=!0,Q("template",L,D,v),L=D,M=x(D.template)? 64 | D.template(v,d):D.template,M=ha(M),D.replace){g=D;M=Sb.test(M)?Xc(Xb(D.templateNamespace,T(M))):[];b=M[0];if(1!=M.length||b.nodeType!==pa)throw ga("tplrt",y,"");U(f,v,b);F={$attr:{}};M=ca(b,[],F);var Lf=a.splice(I+1,a.length-(I+1));u&&A(M);a=a.concat(M).concat(Lf);Yc(d,F);F=a.length}else v.html(M);if(D.templateUrl)m=!0,Q("template",L,D,v),L=D,D.replace&&(g=D),K=Mf(a.splice(I,a.length-I),v,d,f,N&&Ka,h,k,{controllerDirectives:ba,newScopeDirective:S!==D&&S,newIsolateScopeDirective:u,templateDirective:L, 65 | nonTlbTranscludeDirective:z}),F=a.length;else if(D.compile)try{na=D.compile(v,d,Ka),x(na)?n(null,na,P,R):na&&n(na.pre,na.post,P,R)}catch(V){c(V,xa(v))}D.terminal&&(K.terminal=!0,H=Math.max(H,D.priority))}K.scope=S&&!0===S.scope;K.transcludeOnThisElement=N;K.templateOnThisElement=m;K.transclude=Ka;r.hasElementTranscludeDirective=ia;return K}function A(a){for(var b=0,c=a.length;bn.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Nb(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(H){c(H)}}return h}function I(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==b)return ia.HTML;var c=wa(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b|| 71 | "ngSrc"==b))return ia.RESOURCE_URL}function V(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var l=b(d,!0,h,f);if(l){if("multiple"===e&&"select"===wa(a))throw ga("selmulti",xa(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers=fa());if(k.test(e))throw ga("nodomevents");var r=g[e];r!==d&&(l=r&&b(r,!0,h,f),d=r);l&&(g[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e, 72 | a)}))}}}})}}function U(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=a)return b;for(;a--;)8===b[a].nodeType&&Nf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ta(a,"controller");C(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!C(a.$scope))throw I("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,h,g,l){var k,n,p;g=!0===g;l&&G(l)&&(p=l);if(G(f)){l=f.match(Vc);if(!l)throw Of("ctrlfmt",f); 80 | n=l[1];p=p||l[3];f=b.hasOwnProperty(n)?b[n]:Cc(h.$scope,n,!0)||(a?Cc(d,n,!0):w);Sa(f,n,!0)}if(g)return g=(J(f)?f[f.length-1]:f).prototype,k=Object.create(g||null),p&&e(h,p,k,n||f.name),P(function(){var a=c.invoke(f,k,h,n);a!==k&&(C(a)||x(a))&&(k=a,p&&e(h,p,k,n||f.name));return k},{instance:k,identifier:p});k=c.instantiate(f,h,n);p&&e(h,p,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return B(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b, 81 | arguments)}}]}function Yb(b){return C(b)?ea(b)?b.toISOString():eb(b):b}function df(){this.$get=function(){return function(b){if(!b)return"";var a=[];nc(b,function(b,d){null===b||v(b)||(J(b)?m(b,function(b,c){a.push(la(d)+"="+la(Yb(b)))}):a.push(la(d)+"="+la(Yb(b))))});return a.join("&")}}}function ef(){this.$get=function(){return function(b){function a(b,e,f){null===b||v(b)||(J(b)?m(b,function(b,c){a(b,e+"["+(C(b)?c:"")+"]")}):C(b)&&!ea(b)?nc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(la(e)+ 82 | "="+la(Yb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function Zb(b,a){if(G(b)){var c=b.replace(Pf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(ad))||(d=(d=c.match(Qf))&&Rf[d[0]].test(c));d&&(b=vc(c))}}return b}function bd(b){var a=fa(),c;G(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=F(T(b.substr(0,c)));b=T(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):C(b)&&m(b,function(b,c){var f=F(c),h=T(b);f&&(a[f]=a[f]?a[f]+", "+h:h)});return a}function cd(b){var a; 83 | return function(c){a||(a=bd(b));return c?(c=a[F(c)],void 0===c&&(c=null),c):a}}function dd(b,a,c,d){if(x(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function cf(){var b=this.defaults={transformResponse:[Zb],transformRequest:[function(a){return C(a)&&"[object File]"!==va.call(a)&&"[object Blob]"!==va.call(a)&&"[object FormData]"!==va.call(a)?eb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ja($b),put:ja($b),patch:ja($b)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN", 84 | paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return A(b)?(a=!!b,this):a};var c=!0;this.useLegacyPromiseExtensions=function(a){return A(a)?(c=!!a,this):c};var d=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(e,f,h,g,l,k){function n(a){function d(a){var b=P({},a);b.data=a.data?dd(a.data,a.headers,a.status,f.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:l.reject(b)}function e(a,b){var c, 85 | d={};m(a,function(a,e){x(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}if(!da.isObject(a))throw I("$http")("badreq",a);var f=P({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);f.headers=function(a){var c=b.headers,d=P({},a.headers),f,g,h,c=P({},c.common,c[F(a.method)]);a:for(f in c){g=F(f);for(h in d)if(F(h)===g)continue a;d[f]=c[f]}return e(d,ja(a))}(a);f.method=sb(f.method);f.paramSerializer=G(f.paramSerializer)?k.get(f.paramSerializer): 86 | f.paramSerializer;var g=[function(a){var c=a.headers,e=dd(a.data,cd(c),w,a.transformRequest);v(e)&&m(c,function(a,b){"content-type"===F(b)&&delete c[b]});v(a.withCredentials)&&!v(b.withCredentials)&&(a.withCredentials=b.withCredentials);return p(a,e).then(d,d)},w],h=l.when(f);for(m(E,function(a){(a.request||a.requestError)&&g.unshift(a.request,a.requestError);(a.response||a.responseError)&&g.push(a.response,a.responseError)});g.length;){a=g.shift();var r=g.shift(),h=h.then(a,r)}c?(h.success=function(a){Sa(a, 87 | "fn");h.then(function(b){a(b.data,b.status,b.headers,f)});return h},h.error=function(a){Sa(a,"fn");h.then(null,function(b){a(b.data,b.status,b.headers,f)});return h}):(h.success=ed("success"),h.error=ed("error"));return h}function p(c,d){function h(b,c,d,e){function f(){k(c,b,d,e)}L&&(200<=b&&300>b?L.put(ba,[b,c,bd(d),e]):L.remove(ba));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function k(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?O.resolve:O.reject)({data:a,status:b,headers:cd(d),config:c,statusText:e})} 88 | function p(a){k(a.data,a.status,ja(a.headers()),a.statusText)}function E(){var a=n.pendingRequests.indexOf(c);-1!==a&&n.pendingRequests.splice(a,1)}var O=l.defer(),H=O.promise,L,m,S=c.headers,ba=r(c.url,c.paramSerializer(c.params));n.pendingRequests.push(c);H.then(E,E);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(L=C(c.cache)?c.cache:C(b.cache)?b.cache:t);L&&(m=L.get(ba),A(m)?m&&x(m.then)?m.then(p,p):J(m)?k(m[1],m[0],ja(m[2]),m[3]):k(m,200,{},"OK"):L.put(ba,H));v(m)&&((m= 89 | fd(c.url)?f()[c.xsrfCookieName||b.xsrfCookieName]:w)&&(S[c.xsrfHeaderName||b.xsrfHeaderName]=m),e(c.method,ba,d,h,S,c.timeout,c.withCredentials,c.responseType));return H}function r(a,b){0=l&&(u.resolve(E), 97 | t(q.$$intervalId),delete f[q.$$intervalId]);K||b.$apply()},g);f[q.$$intervalId]=u;return q}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ac(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function gd(b,a){var c=Aa(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=Y(c.port)||Tf[c.protocol]||null}function hd(b,a){var c="/"!==b.charAt(0); 98 | c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=yc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function sa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Cb(b){return b.replace(/(#.+)|#$/,"$1")}function bc(b,a,c){this.$$html5=!0;c=c||"";gd(b,this);this.$$parse=function(b){var c=sa(a, 99 | b);if(!G(c))throw Db("ipthprfx",b,a);hd(c,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var b=Pb(this.$$search),c=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=ac(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=a+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,h;A(f=sa(b,d))?(h=f,h=A(f=sa(c,f))?a+(sa("/",f)||f):b+h):A(f=sa(a,d))?h=a+f:a==d+"/"&&(h=a);h&&this.$$parse(h);return!!h}}function cc(b,a,c){gd(b,this); 100 | this.$$parse=function(d){var e=sa(b,d)||sa(a,d),f;v(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",v(e)&&(b=d,this.replace())):(f=sa(c,e),v(f)&&(f=e));hd(f,this);d=this.$$path;var e=b,h=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));h.exec(f)||(d=(f=h.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var a=Pb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=ac(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+(this.$$url?c+this.$$url:"")};this.$$parseLinkUrl= 101 | function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function id(b,a,c){this.$$html5=!0;cc.apply(this,arguments);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,h;b==Ja(d)?f=d:(h=sa(a,d))?f=b+c+h:a===d+"/"&&(f=a);f&&this.$$parse(f);return!!f};this.$$compose=function(){var a=Pb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=ac(this.$$path)+(a?"?"+a:"")+e;this.$$absUrl=b+c+this.$$url}}function Eb(b){return function(){return this[b]}}function jd(b, 102 | a){return function(c){if(v(c))return this[b];this[b]=a(c);this.$$compose();return this}}function hf(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return A(a)?(b=a,this):b};this.html5Mode=function(b){return bb(b)?(a.enabled=b,this):C(b)?(bb(b.enabled)&&(a.enabled=b.enabled),bb(b.requireBase)&&(a.requireBase=b.requireBase),bb(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c, 103 | d,e,f,h){function g(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var p=d.url(),r;if(a.enabled){if(!n&&a.requireBase)throw Db("nobase");r=p.substring(0,p.indexOf("/",p.indexOf("//")+2))+(n||"/");n=e.history?bc:id}else r=Ja(p),n=cc;var t=r.substr(0,Ja(r).lastIndexOf("/")+1);k=new n(r,t,"#"+b);k.$$parseLinkUrl(p,p);k.$$state=d.state(); 104 | var E=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=B(b.target);"a"!==wa(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var g=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");C(g)&&"[object SVGAnimatedString]"===g.toString()&&(g=Aa(g.animVal).href);E.test(g)||!g||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(g,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),h.angular["ff-684208-preventDefault"]= 105 | !0))}});Cb(k.absUrl())!=Cb(p)&&d.url(k.absUrl(),!0);var K=!0;d.onUrlChange(function(a,b){v(sa(t,a))?h.location.href=a:(c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,g(d,!1,e)):(K=!1,l(d,e)))}),c.$$phase||c.$digest())});c.$watch(function(){var a=Cb(d.url()),b=Cb(k.absUrl()),f=d.state(),h=k.$$replace,r=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(K||r)K=!1, 106 | c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(r&&g(b,h,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function jf(){var b=!0,a=this;this.debugEnabled=function(a){return A(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a= 107 | a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||y;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function Xa(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"=== 108 | b||"__proto__"===b)throw Z("isecfld",a);return b}function kd(b,a){b+="";if(!G(b))throw Z("iseccst",a);return b}function Ba(b,a){if(b){if(b.constructor===b)throw Z("isecfn",a);if(b.window===b)throw Z("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw Z("isecdom",a);if(b===Object)throw Z("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw Z("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw Z("isecff",a);}}function md(b,a){if(b&&(b===(0).constructor||b===(!1).constructor|| 109 | b==="".constructor||b==={}.constructor||b===[].constructor||b===Function.constructor))throw Z("isecaf",a);}function Xf(b,a){return"undefined"!==typeof b?b:a}function nd(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function U(b,a){var c,d;switch(b.type){case s.Program:c=!0;m(b.body,function(b){U(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case s.Literal:b.constant=!0;b.toWatch=[];break;case s.UnaryExpression:U(b.argument,a);b.constant=b.argument.constant;b.toWatch= 110 | b.argument.toWatch;break;case s.BinaryExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case s.LogicalExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case s.ConditionalExpression:U(b.test,a);U(b.alternate,a);U(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case s.Identifier:b.constant= 111 | !1;b.toWatch=[b];break;case s.MemberExpression:U(b.object,a);b.computed&&U(b.property,a);b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case s.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case s.AssignmentExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant; 112 | b.toWatch=[b];break;case s.ArrayExpression:c=!0;d=[];m(b.elements,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case s.ObjectExpression:c=!0;d=[];m(b.properties,function(b){U(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case s.ThisExpression:b.constant=!1,b.toWatch=[]}}function od(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:w}} 113 | function pd(b){return b.type===s.Identifier||b.type===s.MemberExpression}function qd(b){if(1===b.body.length&&pd(b.body[0].expression))return{type:s.AssignmentExpression,left:b.body[0].expression,right:{type:s.NGValueParameter},operator:"="}}function rd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===s.Literal||b.body[0].expression.type===s.ArrayExpression||b.body[0].expression.type===s.ObjectExpression)}function sd(b,a){this.astBuilder=b;this.$filter=a}function td(b, 114 | a){this.astBuilder=b;this.$filter=a}function Fb(b){return"constructor"==b}function dc(b){return x(b.valueOf)?b.valueOf():Yf.call(b)}function kf(){var b=fa(),a=fa();this.$get=["$filter",function(c){function d(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=dc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function e(a,b,c,e,f){var g=e.inputs,h;if(1===g.length){var k=d,g=g[0];return a.$watch(function(a){var b=g(a);d(b,k)||(h=e(a,w,w,[b]),k=b&&dc(b));return h},b,c,f)}for(var l=[],n=[],p=0, 115 | m=g.length;p=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)for(b in l++,f)ta.call(e,b)||(t--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1 131 | t&&(D=4-t,u[D]||(u[D]=[]),u[D].push({msg:x(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:g}));else if(b===d){r=!1;break a}}catch(y){h(y)}if(!(k=m.$$watchersCount&&m.$$childHead||m!==this&&m.$$nextSibling))for(;m!==this&&!(k=m.$$nextSibling);)m=m.$parent}while(m=k);if((r||z.length)&&!t--)throw q.$$phase=null,c("infdig",a,u);}while(r||z.length);for(q.$$phase=null;N.length;)try{N.shift()()}catch(A){h(A)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy"); 132 | this.$$destroyed=!0;this===q&&l.$$applicationDestroyed();r(this,-this.$$watchersCount);for(var b in this.$$listenerCount)t(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=y;this.$on= 133 | this.$watch=this.$watchGroup=function(){return y};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){q.$$phase||z.length||l.defer(function(){z.length&&q.$digest()});z.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){N.push(a)},$apply:function(a){try{p("$apply");try{return this.$eval(a)}finally{q.$$phase=null}}catch(b){h(b)}finally{try{q.$digest()}catch(c){throw h(c), 134 | c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&w.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,t(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,g={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){g.defaultPrevented=!0},defaultPrevented:!1}, 135 | k=db([g],arguments,1),l,n;do{d=e.$$listeners[a]||c;g.currentScope=e;l=0;for(n=d.length;lWa)throw Ca("iequirks");var d=ja(oa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=$a);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,h=d.trustAs;m(oa,function(a,b){var c=F(b);d[gb("parse_as_"+c)]=function(b){return e(a,b)};d[gb("get_trusted_"+c)]=function(b){return f(a,b)};d[gb("trust_as_"+ 142 | c)]=function(b){return h(a,b)}});return d}]}function qf(){this.$get=["$window","$document",function(b,a){var c={},d=Y((/android (\d+)/.exec(F((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},h,g=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var p in l)if(k=g.exec(p)){h=k[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||h+"Transition"in l);n=!!("animation"in l||h+"Animation"in 143 | l);!d||k&&n||(k=G(l.webkitTransition),n=G(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Wa)return!1;if(v(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:Fa(),vendorPrefix:h,transitions:k,animations:n,android:d}}]}function sf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,h){e.totalPendingRequests++;G(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var g=a.defaults&&a.defaults.transformResponse; 144 | J(g)?g=g.filter(function(a){return a!==Zb}):g===Zb&&(g=null);return a.get(f,{cache:b,transformResponse:g})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f,a.data);return a.data},function(a){if(!h)throw ga("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function tf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var h=[];m(a,function(a){var d= 145 | da.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+vd(b)+"(\\s|\\||$)")).test(d)&&h.push(a):-1!=d.indexOf(b)&&h.push(a)})});return h},findModels:function(a,b,c){for(var h=["ng-","data-ng-","ng\\:"],g=0;gb;b=Math.abs(b);var h=Infinity===b;if(!h&&!isFinite(b))return"";var g=b+"",l="",k=!1,n=[];h&&(l="\u221e");if(!h&&-1!==g.indexOf("e")){var p=g.match(/([\d\.]+)e(-?)(\d+)/);p&&"-"==p[2]&&p[3]>e+1?b=0:(l=g,k=!0)}if(h||k)0b&&(l=b.toFixed(e),b=parseFloat(l),l=l.replace(hc,d));else{h=(g.split(hc)[1]||"").length;v(e)&&(e=Math.min(Math.max(a.minFrac,h),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var h=(""+b).split(hc),g=h[0],h=h[1]||"",p=0, 153 | r=a.lgSize,t=a.gSize;if(g.length>=r+t)for(p=g.length-r,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=sb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function ic(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function Ad(b){function a(a){var b;if(b= 155 | a.match(c)){a=new Date(0);var f=0,h=0,g=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Y(b[9]+b[10]),h=Y(b[9]+b[11]));g.call(a,Y(b[1]),Y(b[2])-1,Y(b[3]));f=Y(b[4]||0)-f;h=Y(b[5]||0)-h;g=Y(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,h,g,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var h="",g=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;G(c)&&(c= 156 | fg.test(c)?Y(c):a(c));V(c)&&(c=new Date(c));if(!ea(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(g=db(g,k,1),e=g.pop()):(g.push(e),e=null);var n=c.getTimezoneOffset();f&&(n=wc(f,c.getTimezoneOffset()),c=Ob(c,f,!0));m(g,function(a){l=hg[a];h+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return h}}function ag(){return function(b,a){v(a)&&(a=2);return eb(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):Y(a);if(isNaN(a))return b; 157 | V(b)&&(b=b.toString());if(!J(b)&&!G(b))return b;c=!c||isNaN(c)?0:Y(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0,c+a),c)}}function Cd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,g=$a;if(x(a))g=a;else if(G(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(g=b(a),g.constant))var l=g(),g=function(a){return a[l]}}return{get:g,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0; 158 | default:return!1}}return function(b,e,f){if(!Da(b))return b;J(e)||(e=[e]);0===e.length&&(e=["+"]);var h=a(e,f);h.push({get:function(){return{}},descending:f?-1:1});b=Array.prototype.map.call(b,function(a,b){return{value:a,predicateValues:h.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(qc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}}); 159 | b.sort(function(a,b){for(var c=0,d=0,e=h.length;db||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){var b=d.$isEmpty(d.$viewValue)? 164 | "":d.$viewValue;a.val()!==b&&a.val(b)}}function Kb(b,a){return function(c,d){var e,f;if(ea(c))return c;if(G(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c=s};h.$observe("min",function(a){s=r(a);g.$validate()})}if(A(h.max)||h.ngMax){var u;g.$validators.max=function(a){return!p(a)||v(u)||c(a)<=u};h.$observe("max",function(a){u=r(a);g.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=C(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?w:b})}function Jd(b,a,c,d,e){if(A(d)){b= 167 | b(d);if(!b.constant)throw lb("constexpr",c,d);return b(a)}return e}function kc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,Sb=/<|&#?\w+;/,Cf=/<([\w:-]+)/,Df=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, 174 | ma={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option;ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead;ma.th=ma.td;var Ra=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===X.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(Q).on("load",a))}, 175 | toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?B(this[b]):B(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Bb={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Bb[F(b)]=b});var Sc={};m("input select option textarea button form details".split(" "),function(b){Sc[b]=!0});var $c={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"}; 176 | m({data:Vb,removeData:vb,hasData:function(b){for(var a in hb[b.ng339])return!0;return!1}},function(b,a){R[a]=b});m({data:Vb,inheritedData:Ab,scope:function(b){return B.data(b,"$scope")||Ab(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return B.data(b,"$isolateScope")||B.data(b,"$isolateScopeNoTemplate")},controller:Pc,injector:function(b){return Ab(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:xb,css:function(b,a,c){a=gb(a);if(A(c))b.style[a]=c;else return b.style[a]}, 177 | attr:function(b,a,c){var d=b.nodeType;if(d!==Pa&&2!==d&&8!==d)if(d=F(a),Bb[d])if(A(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||y).specified?d:w;else if(A(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?w:b},prop:function(b,a,c){if(A(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(v(b)){var d=a.nodeType;return d===pa||d===Pa?a.textContent:""}a.textContent=b}b.$dv="";return b}(), 178 | val:function(b,a){if(v(a)){if(b.multiple&&"select"===wa(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(v(a))return b.innerHTML;ub(b,!0);b.innerHTML=a},empty:Qc},function(b,a){R.prototype[a]=function(a,d){var e,f,h=this.length;if(b!==Qc&&v(2==b.length&&b!==xb&&b!==Pc?a:d)){if(C(a)){for(e=0;e <= >= && || ! = |".split(" "),function(a){Lb[a]=!0});var rg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},ec=function(a){this.options=a};ec.prototype={constructor:ec,lex:function(a){this.text=a;this.index=0;for(this.tokens= 196 | [];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"=== 198 | a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=A(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw Z("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">=");)a={type:s.BinaryExpression,operator:c.text, 205 | left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:s.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:s.BinaryExpression,operator:c.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:s.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()}, 206 | primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=ha(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:s.CallExpression,callee:a,arguments:this.parseArguments()}, 207 | this.consume(")")):"["===c.text?(a={type:s.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:s.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:s.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression()); 208 | while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:s.Identifier,name:a.text}},constant:function(){return{type:s.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:s.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break; 209 | c={type:s.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:s.ObjectExpression,properties:a}},throwError:function(a,c){throw Z("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw Z("ueoe",this.text);var c=this.expect(a); 210 | c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw Z("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var h=a.text;if(h===c||h===d||h===e||h===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:s.Literal,value:!0}, 211 | "false":{type:s.Literal,value:!1},"null":{type:s.Literal,value:null},undefined:{type:s.Literal,value:w},"this":{type:s.ThisExpression}}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};U(e,d.$filter);var f="",h;this.stage="assign";if(h=qd(e))this.state.computing="assign",f=this.nextId(),this.recurse(h,f),this.return_(f),f="fn.assign="+this.generateFunction("assign", 212 | "s,v,l");h=od(e.body);d.stage="inputs";m(h,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue", 213 | "ensureSafeAssignContext","ifDefined","plus","text",f))(this.$filter,Xa,Ba,ld,kd,md,Xf,nd,a);this.state=this.stage=w;f.literal=rd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")},generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a= 214 | [],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,h){var g,l,k=this,n,p;e=e||y;if(!h&&A(a.watchId))c=c||this.nextId(),this.if_("i",this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case s.Program:m(a.body, 215 | function(c,d){k.recurse(c.expression,w,w,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case s.Literal:p=this.escape(a.value);this.assign(c,p);e(p);break;case s.UnaryExpression:this.recurse(a.argument,w,w,function(a){l=a});p=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,p);e(p);break;case s.BinaryExpression:this.recurse(a.left,w,w,function(a){g=a});this.recurse(a.right,w,w,function(a){l=a});p="+"===a.operator?this.plus(g,l):"-"===a.operator?this.ifDefined(g, 216 | 0)+a.operator+this.ifDefined(l,0):"("+g+")"+a.operator+"("+l+")";this.assign(c,p);e(p);break;case s.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case s.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c);break;case s.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l", 217 | a.name)+"?l:s"),d.computed=!1,d.name=a.name);Xa(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case s.MemberExpression:g=d&&(d.context=this.nextId())|| 218 | this.nextId();c=c||this.nextId();k.recurse(a.object,g,w,function(){k.if_(k.notNull(g),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.getStringValue(l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(g,l)),k.lazyAssign(k.computedMember(g,l),"{}")),p=k.ensureSafeObject(k.computedMember(g,l)),k.assign(c,p),d&&(d.computed=!0,d.name=l);else{Xa(a.property.name);f&&1!==f&&k.if_(k.not(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name), 219 | "{}"));p=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))p=k.ensureSafeObject(p);k.assign(c,p);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case s.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),p=l+"("+n.join(",")+")",k.assign(c,p),e(c)):(l=k.nextId(),g={},n=[],k.recurse(a.callee,l,g,function(){k.if_(k.notNull(l), 220 | function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),w,function(a){n.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),p=k.member(g.context,g.name,g.computed)+"("+n.join(",")+")"):p=l+"("+n.join(",")+")";p=k.ensureSafeObject(p);k.assign(c,p)},function(){k.assign(c,"undefined")});e(c)}));break;case s.AssignmentExpression:l=this.nextId();g={};if(!pd(a.left))throw Z("lval");this.recurse(a.left,w,g,function(){k.if_(k.notNull(g.context), 221 | function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);p=k.member(g.context,g.name,g.computed)+a.operator+l;k.assign(c,p);e(c||p)})},1);break;case s.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),w,function(a){n.push(a)})});p="["+n.join(",")+"]";this.assign(c,p);e(p);break;case s.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value,k.nextId(),w,function(c){n.push(k.escape(a.key.type=== 222 | s.Identifier?a.key.name:""+a.key.value)+":"+c)})});p="{"+n.join(",")+"}";this.assign(c,p);e(p);break;case s.ThisExpression:this.assign(c,"s");e("s");break;case s.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]= 223 | this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+"."+c},computedMember:function(a, 224 | c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+ 225 | a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+",text)")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+a+",text)"},lazyRecurse:function(a,c,d,e,f,h){var g=this;return function(){g.recurse(a,c,d,e,f,h)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g, 226 | stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(G(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw Z("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}}; 227 | td.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;U(e,d.$filter);var f,h;if(f=qd(e))h=this.recurse(f);f=od(e.body);var g;f&&(g=[],m(f,function(a,c){var e=d.recurse(a);a.input=e;g.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};h&&(f.assign=function(a,c,d){return h(a,d,c)});g&&(f.inputs= 228 | g);f.literal=rd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,h=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case s.Literal:return this.value(a.value,c);case s.UnaryExpression:return f=this.recurse(a.argument),this["unary"+a.operator](f,c);case s.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case s.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e, 229 | f,c);case s.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case s.Identifier:return Xa(a.name,h.expression),h.identifier(a.name,h.expensiveChecks||Fb(a.name),c,d,h.expression);case s.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Xa(a.property.name,h.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,h.expression):this.nonComputedMember(e,f, 230 | h.expensiveChecks,c,d,h.expression);case s.CallExpression:return g=[],m(a.arguments,function(a){g.push(h.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,h){for(var r=[],m=0;m":function(a,c,d){return function(e,f,h,g){e=a(e,f,h,g)>c(e,f,h,g);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e,f,h,g){e=a(e,f,h,g)<=c(e,f,h,g);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,h,g){e=a(e,f,h,g)>=c(e,f,h,g);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e, 236 | f,h,g){e=a(e,f,h,g)&&c(e,f,h,g);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,h,g){e=a(e,f,h,g)||c(e,f,h,g);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,h,g,l){f=a(f,h,g,l)?c(f,h,g,l):d(f,h,g,l);return e?{value:f}:f}},value:function(a,c){return function(){return c?{context:w,name:w,value:a}:a}},identifier:function(a,c,d,e,f){return function(h,g,l,k){h=g&&a in g?g:h;e&&1!==e&&h&&!h[a]&&(h[a]={});g=h?h[a]:w;c&&Ba(g,f);return d?{context:h,name:a,value:g}: 237 | g}},computedMember:function(a,c,d,e,f){return function(h,g,l,k){var n=a(h,g,l,k),p,m;null!=n&&(p=c(h,g,l,k),p=kd(p),Xa(p,f),e&&1!==e&&n&&!n[p]&&(n[p]={}),m=n[p],Ba(m,f));return d?{context:n,name:p,value:m}:m}},nonComputedMember:function(a,c,d,e,f,h){return function(g,l,k,n){g=a(g,l,k,n);f&&1!==f&&g&&!g[c]&&(g[c]={});l=null!=g?g[c]:w;(d||Fb(c))&&Ba(l,h);return e?{context:g,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,h){return h?h[c]:a(d,e,f)}}};var fc=function(a,c,d){this.lexer= 238 | a;this.$filter=c;this.options=d;this.ast=new s(this.lexer);this.astCompiler=d.csp?new td(this.ast,c):new sd(this.ast,c)};fc.prototype={constructor:fc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};fa();fa();var Yf=Object.prototype.valueOf,Ca=I("$sce"),oa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ga=I("$compile"),$=X.createElement("a"),xd=Aa(Q.location.href);yd.$inject=["$document"];Kc.$inject=["$provide"];zd.$inject=["$locale"];Bd.$inject= 239 | ["$locale"];var hc=".",hg={yyyy:aa("FullYear",4),yy:aa("FullYear",2,0,!0),y:aa("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:aa("Month",2,1),M:aa("Month",1,1),dd:aa("Date",2),d:aa("Date",1),HH:aa("Hours",2),H:aa("Hours",1),hh:aa("Hours",2,-12),h:aa("Hours",1,-12),mm:aa("Minutes",2),m:aa("Minutes",1),ss:aa("Seconds",2),s:aa("Seconds",1),sss:aa("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<= 240 | a?"+":"")+(Gb(Math[0=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;Ad.$inject=["$locale"];var cg=qa(F),dg=qa(sb);Cd.$inject=["$parse"];var he=qa({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"=== 241 | va.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),tb={};m(Bb,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=ya("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});tb[e]=function(){return{restrict:"A",priority:100,link:f}}}});m($c,function(a,c){tb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern", 242 | new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=ya("ng-"+a);tb[c]=function(){return{priority:99,link:function(d,e,f){var h=a,g=a;"href"===a&&"[object SVGAnimatedString]"===va.call(e.prop("href"))&&(g="xlinkHref",f.$attr[g]="xlink:href",h=null);f.$observe(c,function(c){c?(f.$set(g,c),Wa&&h&&e.prop(h,f[g])):"href"===a&&f.$set(g,null)})}}}});var Ib={$addControl:y,$$renameControl:function(a,c){a.$name=c},$removeControl:y,$setValidity:y, 243 | $setDirty:y,$setPristine:y,$setSubmitted:y};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout","$parse",function(c,d){function e(a){return""===a?d('this[""]').assign:d(a).assign||y}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Gd,compile:function(d,h){d.addClass(Ya).addClass(mb);var g=h.name?"name":a&&h.ngForm?"ngForm":!1;return{pre:function(a,d,f,h){var m=h[0];if(!("action"in f)){var t=function(c){a.$apply(function(){m.$commitViewValue(); 244 | m.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",t,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",t,!1)},0,!1)})}(h[1]||m.$$parentForm).$addControl(m);var s=g?e(m.$name):y;g&&(s(a,m),f.$observe(g,function(c){m.$name!==c&&(s(a,w),m.$$parentForm.$$renameControl(m,c),s=e(m.$name),s(a,m))}));d.on("$destroy",function(){m.$$parentForm.$removeControl(m);s(a,w);P(m,Ib)})}}}}}]},ie=Od(),ve=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/, 245 | sg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,tg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,ug=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,lc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/,Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,h){jb(a,c,d,e,f,h);jc(e)},date:kb("date", 246 | Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":kb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:kb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:kb("week",lc,function(a,c){if(ea(a))return a;if(G(a)){lc.lastIndex=0;var d=lc.exec(a);if(d){var e=+d[1],f=+d[2],h=d=0,g=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),h=c.getMinutes(),g=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,h,g,l)}}return NaN},"yyyy-Www"), 247 | month:kb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,h){Id(a,c,d,e);jb(a,c,d,e,f,h);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:ug.test(a)?parseFloat(a):w});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw lb("numfmt",a);a=a.toString()}return a});if(A(d.min)||d.ngMin){var g;e.$validators.min=function(a){return e.$isEmpty(a)||v(g)||a>=g};d.$observe("min",function(a){A(a)&&!V(a)&&(a=parseFloat(a,10));g=V(a)&&!isNaN(a)?a:w;e.$validate()})}if(A(d.max)|| 248 | d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||v(l)||a<=l};d.$observe("max",function(a){A(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:w;e.$validate()})}},url:function(a,c,d,e,f,h){jb(a,c,d,e,f,h);jc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},email:function(a,c,d,e,f,h){jb(a,c,d,e,f,h);jc(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||tg.test(d)}},radio:function(a,c, 249 | d,e){v(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,h,g,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a, 250 | k)});e.$parsers.push(function(a){return a?k:n})},hidden:y,button:y,submit:y,reset:y,file:y},Ec=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,h,g,l){l[0]&&(Td[F(g.type)]||Td.text)(f,h,g,l[0],c,a,d,e)}}}}],vg=/^(true|false|\d+)$/,Ne=function(){return{restrict:"A",priority:100,compile:function(a,c){return vg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value", 251 | a)})}}}},ne=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=v(a)?"":a})}}}}],pe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,h){d=a(f.attr(h.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];h.$observe("ngBindTemplate",function(a){f.textContent=v(a)?"":a})}}}}],oe=["$sce","$parse", 252 | "$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var h=c(f.ngBindHtml),g=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(g,function(){e.html(a.getTrustedHtml(h(c))||"")})}}}}],Me=qa({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),qe=kc("",!0),se=kc("Odd",0),re=kc("Even",1),te=Na({compile:function(a,c){c.$set("ngCloak", 253 | w);a.removeClass("ng-cloak")}}),ue=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Jc={},wg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Jc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,h){var g=d(h[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){g(c,{$event:d})}; 254 | wg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var xe=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,h){var g,l,k;c.$watch(e.ngIf,function(c){c?l||h(function(c,f){l=f;c[c.length++]=X.createComment(" end ngIf: "+e.ngIf+" ");g={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),g&&(k=rb(g.clone),a.leave(k).then(function(){k=null}),g=null))})}}}],ye=["$templateRequest","$anchorScroll", 255 | "$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:da.noop,compile:function(e,f){var h=f.ngInclude||f.src,g=f.onload||"",l=f.autoscroll;return function(e,f,m,r,t){var s=0,v,u,q,z=function(){u&&(u.remove(),u=null);v&&(v.$destroy(),v=null);q&&(d.leave(q).then(function(){u=null}),u=q,q=null)};e.$watch(h,function(h){var m=function(){!A(l)||l&&!e.$eval(l)||c()},p=++s;h?(a(h,!0).then(function(a){if(p===s){var c=e.$new();r.template=a;a=t(c,function(a){z(); 256 | d.enter(a,null,f).then(m)});v=c;q=a;v.$emit("$includeContentLoaded",h);e.$eval(g)}},function(){p===s&&(z(),e.$emit("$includeContentError",h))}),e.$emit("$includeContentRequested",h)):(z(),r.template=null)})}}}}],Pe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Mc(f.template,X).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ze=Na({priority:450, 257 | compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Le=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",h="false"!==d.ngTrim,g=h?T(f):f;e.$parsers.push(function(a){if(!v(a)){var c=[];a&&m(a.split(g),function(a){a&&c.push(h?T(a):a)});return c}});e.$formatters.push(function(a){return J(a)?a.join(f):w});e.$isEmpty=function(a){return!a||!a.length}}}},mb="ng-valid",Kd="ng-invalid",Ya="ng-pristine",Jb="ng-dirty",Md= 258 | "ng-pending",lb=I("ngModel"),xg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,h,g,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=w;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending= 259 | w;this.$name=n(d.name||"",!1)(a);this.$$parentForm=Ib;var p=f(d.ngModel),r=p.assign,t=p,s=r,K=null,u,q=this;this.$$setOptions=function(a){if((q.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");t=function(a){var d=p(a);x(d)&&(d=c(a));return d};s=function(a,c){x(p(a))?g(a,{$$$p:q.$modelValue}):r(a,q.$modelValue)}}else if(!p.assign)throw lb("nonassign",d.ngModel,xa(e));};this.$render=y;this.$isEmpty=function(a){return v(a)||""===a||null===a||a!==a};var z=0;Hd({ctrl:this,$element:e, 260 | set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},$animate:h});this.$setPristine=function(){q.$dirty=!1;q.$pristine=!0;h.removeClass(e,Jb);h.addClass(e,Ya)};this.$setDirty=function(){q.$dirty=!0;q.$pristine=!1;h.removeClass(e,Ya);h.addClass(e,Jb);q.$$parentForm.$setDirty()};this.$setUntouched=function(){q.$touched=!1;q.$untouched=!0;h.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){q.$touched=!0;q.$untouched=!1;h.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue= 261 | function(){g.cancel(K);q.$viewValue=q.$$lastCommittedViewValue;q.$render()};this.$validate=function(){if(!V(q.$modelValue)||!isNaN(q.$modelValue)){var a=q.$$rawModelValue,c=q.$valid,d=q.$modelValue,e=q.$options&&q.$options.allowInvalid;q.$$runValidators(a,q.$$lastCommittedViewValue,function(f){e||c===f||(q.$modelValue=f?a:w,q.$modelValue!==d&&q.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d){function e(){var d=!0;m(q.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d? 262 | !0:(m(q.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(q.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!x(k.then))throw lb("$asyncValidators",k);g(h,w);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},y):h(!0)}function g(a,c){l===z&&q.$setValidity(a,c)}function h(a){l===z&&d(a)}z++;var l=z;(function(){var a=q.$$parserName||"parse";if(v(u))g(a,null);else return u||(m(q.$validators,function(a,c){g(c,null)}),m(q.$asyncValidators, 263 | function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=q.$viewValue;g.cancel(K);if(q.$$lastCommittedViewValue!==a||""===a&&q.$$hasNativeValidators)q.$$lastCommittedViewValue=a,q.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=q.$$lastCommittedViewValue;if(u=v(c)?w:!0)for(var d=0;df||e.$isEmpty(c)||c.length<=f}}}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=Y(a)||0;e.$validate()}); 291 | e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};Q.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(da),da.module("ngLocale",[],["$provide",function(a){function c(a){a+="";var c=a.indexOf(".");return-1==c?0:a.length-c-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "), 292 | SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3, 293 | maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",pluralCat:function(a,e){var f=a|0,h=e;w===h&&(h=Math.min(c(a),3));Math.pow(10,h);return 1==f&&0==h?"one":"other"}})}]),B(X).ready(function(){Zd(X,zc)}))})(window,document);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend(''); 294 | //# sourceMappingURL=angular.min.js.map 295 | -------------------------------------------------------------------------------- /gulpfile.coffee: -------------------------------------------------------------------------------- 1 | gulp = require 'gulp' 2 | plumber = require 'gulp-plumber' 3 | coffee = require 'gulp-coffee' 4 | concat = require 'gulp-concat' 5 | less = require 'gulp-less' 6 | autoprefixer = require 'gulp-autoprefixer' 7 | gutil = require 'gulp-util' 8 | uglify = require 'gulp-uglify' 9 | browserSync = require 'browser-sync' 10 | 11 | config = 12 | source: 13 | coffee: "./src/app/angular-drag-and-drop.coffee" 14 | less: "./src/less/**/*.less" 15 | target: "./build" 16 | demo: "./examples" 17 | 18 | log = 19 | info: (path, type) -> 20 | console.log "\nFile #{path} was #{type}, running tasks...\n" 21 | error: (err) -> 22 | gutil.log err.toString() 23 | this.emit 'end' 24 | 25 | gulp.task "less", -> 26 | 27 | gulp.src config.source.less 28 | .pipe less() 29 | .pipe autoprefixer "browsers": [ 30 | 'last 2 version' 31 | '> 1%' 32 | 'ie >= 8' 33 | 'opera 12.1' 34 | 'bb 10' 35 | 'android 4' 36 | ] 37 | .pipe gulp.dest "#{config.target}/css" 38 | 39 | gulp.task "coffee", -> 40 | gulp.src config.source.coffee 41 | .pipe coffee bare: true 42 | .pipe concat "angular-drag-and-drop.js" 43 | .pipe gulp.dest "#{config.target}/js" 44 | .pipe uglify() 45 | .pipe concat "angular-drag-and-drop.min.js" 46 | .pipe gulp.dest "#{config.target}/js" 47 | 48 | gulp.task "watch", -> 49 | gulp.watch config.source.less, ["less"] 50 | gulp.watch config.source.coffee, ["coffee"] 51 | 52 | gulp.task "browser-sync", -> 53 | browserSync.init [ 54 | config.target + '/**/*' 55 | config.demo + '/**/*' 56 | ], 57 | server: 58 | baseDir: './' 59 | directory: true 60 | index: './examples/index.html' 61 | notify: true 62 | open: true 63 | ui: 64 | enabled: true 65 | 66 | gulp.task "default", [ 67 | "less", "coffee", "watch", "browser-sync" 68 | ] 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-drag-and-drop", 3 | "version": "1.0.1", 4 | "description": "drag and drop functionality in angular", 5 | "main": "build/js/angular-drag-and-drop.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/Lane/angular-drag-and-drop.git" 15 | }, 16 | "keywords": [ 17 | "angular", 18 | "drag", 19 | "drop" 20 | ], 21 | "author": "Lane Olson", 22 | "license": "ISC", 23 | "bugs": { 24 | "url": "https://github.com/Lane/angular-drag-and-drop/issues" 25 | }, 26 | "homepage": "https://github.com/Lane/angular-drag-and-drop", 27 | "dependencies": { 28 | "browser-sync": "^2.9.11", 29 | "coffee-script": "^1.10.0", 30 | "gulp": "^3.9.0", 31 | "gulp-autoprefixer": "^3.0.2", 32 | "gulp-coffee": "^2.3.1", 33 | "gulp-concat": "^2.6.0", 34 | "gulp-less": "^3.0.3", 35 | "gulp-plumber": "^1.0.1", 36 | "gulp-util": "^3.0.6", 37 | "gulp-watch": "^4.3.5", 38 | "gulp-uglify": "^1.5.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/app/angular-drag-and-drop.coffee: -------------------------------------------------------------------------------- 1 | # # Drag and Drop Directive 2 | 3 | module = angular.module "laneolson.ui.dragdrop", [] 4 | 5 | module.directive 'dragAndDrop', ['$document', ($document) -> 6 | restrict: 'AE' 7 | scope: 8 | onItemPlaced: "&" 9 | onItemRemoved: "&" 10 | onDrag: "&" 11 | onDragStart: "&" 12 | onDragEnd: "&" 13 | onDragEnter: "&" 14 | onDragLeave: "&" 15 | enableSwap: "=" 16 | fixedPositions: "=" 17 | require: 'dragAndDrop' 18 | controller: [ 19 | '$q' 20 | '$scope' 21 | ($q, $scope) -> 22 | 23 | $scope.draggables = draggables = [] 24 | $scope.droppables = droppables = [] 25 | $scope.isDragging = false 26 | $scope.currentDraggable = null 27 | currentDroppable = null 28 | element = null 29 | isReady = false 30 | 31 | handlers = [] 32 | 33 | # Checks if a provided point is within the bounds object 34 | isInside = (point, bounds) -> 35 | return (bounds.left < point[0] < bounds.right and 36 | bounds.top < point[1] < bounds.bottom) 37 | 38 | # Checks if two rectangles intersect each other 39 | isIntersecting = (r1, r2) -> 40 | return !(r2.left > r1.right or 41 | r2.right < r1.left or 42 | r2.top > r1.bottom or 43 | r2.bottom < r1.top) 44 | 45 | # registers a callback function to a specific event 46 | @on = (e, cb) -> 47 | # fire ready immediately if it's already ready 48 | if e is "ready" and isReady 49 | cb() 50 | handlers.push 51 | name: e 52 | cb: cb 53 | 54 | # triggers an event 55 | @trigger = (e) -> 56 | if e is "ready" 57 | isReady = true 58 | for h in handlers 59 | if h.name is e 60 | h.cb() 61 | 62 | # returns true if the drag and drop is ready 63 | @isReady = -> 64 | return isReady 65 | 66 | # set the element for the drag and drop 67 | @setDragAndDropElement = (el) -> 68 | element = el 69 | 70 | # get the element for the drag and drop 71 | @getDragAndDropElement = -> 72 | return element 73 | 74 | # checks all of the drop spots to see if the currently dragged 75 | # item is overtop of them 76 | @checkForIntersection = () -> 77 | for dropSpot in droppables 78 | if isInside $scope.currentDraggable.midPoint, dropSpot 79 | if !dropSpot.isActive 80 | @setCurrentDroppable dropSpot 81 | dropSpot.activate() 82 | @fireCallback 'drag-enter' 83 | else 84 | if dropSpot.isActive 85 | @setCurrentDroppable null 86 | dropSpot.deactivate() 87 | @fireCallback 'drag-leave' 88 | 89 | # sets the item that is currently being dragged 90 | @setCurrentDraggable = (draggable) -> 91 | $scope.currentDraggable = draggable 92 | if draggable 93 | @fireCallback 'drag-start' 94 | $scope.$evalAsync -> 95 | $scope.currentDraggable = draggable 96 | if draggable 97 | $scope.isDragging = true 98 | else 99 | $scope.isDragging = false 100 | 101 | # returns the item that is currently being dragged 102 | @getCurrentDraggable = () -> 103 | return $scope.currentDraggable 104 | 105 | # sets the drop spot that the current drag item is over 106 | @setCurrentDroppable = (droppable) -> 107 | currentDroppable = droppable 108 | 109 | # returns the drop spot that the current drag item is over 110 | @getCurrentDroppable = () -> 111 | return currentDroppable 112 | 113 | # add a drop spot to the drag and drop 114 | @addDroppable = (droppable) -> 115 | droppables.push droppable 116 | 117 | # add a drag item to the drag and drop 118 | @addDraggable = (draggable) -> 119 | draggables.push draggable 120 | 121 | # fire any callback functions with the current state of the 122 | # drag and drop. 123 | @fireCallback = (type, e) -> 124 | state = 125 | draggable: @getCurrentDraggable() 126 | droppable: @getCurrentDroppable() 127 | dragEvent: e 128 | switch type 129 | when 'drag-end' 130 | $scope.onDragEnd?(state) 131 | @trigger "drag-end" 132 | when 'drag-start' 133 | $scope.onDragStart?(state) 134 | @trigger "drag-start" 135 | when 'drag' 136 | $scope.onDrag?(state) 137 | when 'item-assigned' 138 | $scope.onItemPlaced?(state) 139 | when 'item-removed' 140 | $scope.onItemRemoved?(state) 141 | when 'drag-leave' 142 | $scope.onDragLeave?(state) 143 | when 'drag-enter' 144 | $scope.onDragEnter?(state) 145 | 146 | return 147 | 148 | ] 149 | link: (scope, element, attrs, ngDragAndDrop) -> 150 | 151 | moveEvents = "touchmove mousemove" 152 | releaseEvents = "touchend mouseup" 153 | ngDragAndDrop.setDragAndDropElement element 154 | 155 | # binds touch / mouse events for moving and releasing items 156 | bindEvents = () -> 157 | $document.on moveEvents, onMove 158 | $document.on releaseEvents, onRelease 159 | ngDragAndDrop.on "drag-start", -> 160 | element.addClass "dragging" 161 | ngDragAndDrop.on "drag-end", -> 162 | element.removeClass "dragging" 163 | 164 | # unbinds events attached to the drag and drop container 165 | unbindEvents = () -> 166 | $document.off moveEvents, onMove 167 | $document.off releaseEvents, onRelease 168 | 169 | # when an item is released 170 | onRelease = (e) -> 171 | 172 | # get the item that is currently being dragged 173 | draggable = ngDragAndDrop.getCurrentDraggable() 174 | 175 | # get any drop spots that the draggable is currently over 176 | dropSpot = ngDragAndDrop.getCurrentDroppable() 177 | 178 | # deactivate the draggable 179 | if draggable 180 | element.addClass "drag-return" 181 | # NOTE: This is kind of a hack to allow the drag item to have 182 | # a return animation. ngAnimate could be used for the animation 183 | # to prevent this. 184 | setTimeout -> 185 | element.removeClass "drag-return" 186 | , 500 187 | ngDragAndDrop.fireCallback 'drag-end', e 188 | draggable.deactivate() 189 | if dropSpot and not dropSpot.isFull 190 | # add the draggable to the drop spot if it isn't full 191 | ngDragAndDrop.fireCallback 'item-assigned', e 192 | draggable.assignTo dropSpot 193 | dropSpot.itemDropped draggable 194 | else if dropSpot and dropSpot.isFull and scope.enableSwap 195 | # swap 196 | dropSpot.items[0].returnToStartPosition() 197 | dropSpot.items[0].removeFrom dropSpot 198 | ngDragAndDrop.fireCallback 'item-assigned', e 199 | draggable.assignTo dropSpot 200 | dropSpot.itemDropped draggable 201 | ngDragAndDrop.fireCallback 'item-removed', e 202 | else 203 | # if released over nothing, remove the assignment 204 | 205 | draggable.isAssigned = false 206 | if scope.fixedPositions 207 | draggable.returnToStartPosition() 208 | if dropSpot 209 | dropSpot.deactivate() 210 | ngDragAndDrop.setCurrentDraggable null 211 | 212 | # when an item is moved 213 | onMove = (e) -> 214 | # if we're dragging, update the position 215 | draggable = ngDragAndDrop.getCurrentDraggable() 216 | if draggable 217 | ngDragAndDrop.fireCallback 'drag', e 218 | if e.touches and e.touches.length is 1 219 | # update position based on touch event 220 | draggable.updateOffset e.touches[0].clientX, e.touches[0].clientY 221 | else 222 | # update position based on mouse event 223 | draggable.updateOffset e.clientX, e.clientY 224 | # check if dragging over a drop spot 225 | ngDragAndDrop.checkForIntersection() 226 | 227 | # initialize 228 | bindEvents() 229 | 230 | ngDragAndDrop.trigger "ready" 231 | ] 232 | 233 | # Drag Directive 234 | # ---------- 235 | module.directive 'dragItem', [ 236 | '$window', '$document', '$compile', 237 | ($window, $document, $compile) -> 238 | restrict: 'EA' 239 | require: '^dragAndDrop' 240 | scope: 241 | x: "@" 242 | y: "@" 243 | dropTo: "@" 244 | dragId: "@" 245 | dragEnabled: "=" 246 | dragData: "=" 247 | clone: "=" 248 | lockHorizontal: "=" 249 | lockVertical: "=" 250 | link: (scope, element, attrs, ngDragAndDrop) -> 251 | 252 | cloneEl = width = height = startPosition = transformEl = eventOffset = 253 | pressEvents = w = null 254 | 255 | 256 | # set the position values on the drag item 257 | updateDimensions = () -> 258 | scope.left = scope.x + element[0].offsetLeft 259 | scope.right = scope.left + width 260 | scope.top = scope.y + element[0].offsetTop 261 | scope.bottom = scope.top + height 262 | scope.midPoint = [ 263 | scope.left + width/2 264 | scope.top + height/2 265 | ] 266 | if scope.lockVertical 267 | # track the horizontal percentage position in the container 268 | # if we're locked vertically 269 | scope.percent = 100 * 270 | (scope.left + element[0].clientWidth/2) / 271 | element.parent()[0].clientWidth 272 | 273 | scope.percent = Math.min(100, Math.max(0, scope.percent)) 274 | 275 | # set the position of the clone to where the element is 276 | setClonePosition = -> 277 | elemRect = element[0].getBoundingClientRect() 278 | leftOffset = elemRect.left + eventOffset[0] 279 | topOffset = elemRect.top + eventOffset[1] 280 | scope.updateOffset leftOffset, topOffset 281 | 282 | # set the position of an element based on a percentage 283 | # value, relative to the parent element 284 | scope.setPercentPostion = (xPercent,yPercent) -> 285 | newY = 286 | (element.parent()[0].clientHeight * (yPercent/100)) - 287 | element[0].clientHeight/2 288 | newX = 289 | (element.parent()[0].clientWidth * (xPercent/100)) - 290 | element[0].clientWidth/2 291 | scope.setPosition(newX, newY) 292 | 293 | # set the position of the transform element 294 | scope.setPosition = (x, y) -> 295 | scope.x = if scope.lockHorizontal then 0 else x 296 | scope.y = if scope.lockVertical then 0 else y 297 | updateDimensions() 298 | transformEl.css 299 | "transform": "translate(#{scope.x}px, #{scope.y}px)" 300 | "-webkit-transform": "translate(#{scope.x}px, #{scope.y}px)" 301 | "-ms-transform": "translate(#{scope.x}px, #{scope.y}px)" 302 | 303 | # update the x / y offset of the drag item and set the style 304 | scope.updateOffset = (x,y) -> 305 | if scope.clone 306 | # sometimes, you may want to offset the clone 307 | # scope.setPosition( 308 | # x - cloneEl.prop("offsetWidth")/2, 309 | # y - cloneEl.prop("offsetHeight") 310 | # ) 311 | scope.setPosition( 312 | x - (eventOffset[0] + element[0].offsetLeft), 313 | y - (eventOffset[1] + element[0].offsetTop) 314 | ) 315 | else 316 | scope.setPosition( 317 | x - (eventOffset[0] + element[0].offsetLeft), 318 | y - (eventOffset[1] + element[0].offsetTop) 319 | ) 320 | 321 | # return the drag item to its original position 322 | scope.returnToStartPosition = -> 323 | scope.setPosition( 324 | startPosition[0], 325 | startPosition[1] 326 | ) 327 | 328 | # assign the drag item to a drop spot 329 | scope.assignTo = (dropSpot) -> 330 | scope.dropSpots.push dropSpot 331 | scope.isAssigned = true 332 | if dropSpot.dropId 333 | element.addClass "in-#{dropSpot.dropId}" 334 | 335 | # finds the provided drop spot in the list of assigned drop spots 336 | # removes the drop spot from the list, and removes the draggable from 337 | # the drop spot. 338 | scope.removeFrom = (dropSpot) -> 339 | index = scope.dropSpots.indexOf dropSpot 340 | if index > -1 341 | if dropSpot.dropId 342 | element.removeClass "in-#{dropSpot.dropId}" 343 | scope.dropSpots.splice index, 1 344 | if scope.dropSpots.length < 1 345 | scope.isAssigned = false 346 | dropSpot.removeItem scope 347 | 348 | scope.addClass = (className) -> 349 | element.addClass className 350 | 351 | scope.removeClass = (className) -> 352 | element.removeClass className 353 | 354 | scope.toggleClass = (className) -> 355 | if element.hasClass className 356 | element.removeClass className 357 | else 358 | element.addClass className 359 | 360 | # sets dragging status on the drag item 361 | scope.activate = () -> 362 | element.addClass "drag-active" 363 | scope.isDragging = true 364 | 365 | # removes dragging status and resets the event offset 366 | scope.deactivate = () -> 367 | eventOffset = [0, 0] 368 | if scope.clone 369 | cloneEl.removeClass "clone-active" 370 | 371 | element.removeClass "drag-active" 372 | scope.isDragging = false 373 | 374 | # bind press and window resize to the drag item 375 | bindEvents = () -> 376 | element.on pressEvents, onPress 377 | w.bind "resize", updateDimensions 378 | 379 | # unbind press and window resize from the drag item 380 | unbindEvents = () -> 381 | element.off pressEvents, onPress 382 | w.unbind "resize", updateDimensions 383 | 384 | onPress = (e) -> 385 | unless scope.dragEnabled 386 | return 387 | if e.touches and e.touches.length is 1 388 | eventOffset = [ 389 | (e.touches[0].clientX-scope.left) 390 | (e.touches[0].clientY-scope.top) 391 | ] 392 | else 393 | elemRect = element[0].getBoundingClientRect() 394 | eventOffset = [e.clientX - elemRect.left, e.clientY - elemRect.top] 395 | if scope.clone 396 | scope.returnToStartPosition() 397 | cloneEl.addClass "clone-active" 398 | setClonePosition() 399 | ngDragAndDrop.setCurrentDraggable scope 400 | scope.activate() 401 | scope.isAssigned = false 402 | ngDragAndDrop.checkForIntersection() 403 | dropSpot = ngDragAndDrop.getCurrentDroppable() 404 | for spot in scope.dropSpots 405 | scope.removeFrom spot 406 | ngDragAndDrop.fireCallback 'item-removed', e 407 | e.preventDefault() 408 | 409 | init = -> 410 | # add a class based on the drag ID 411 | if scope.dragId 412 | element.addClass scope.dragId 413 | 414 | # set starting values 415 | eventOffset = [0, 0] 416 | width = element[0].offsetWidth 417 | height = element[0].offsetHeight 418 | scope.dropSpots = [] 419 | scope.isAssigned = false 420 | scope.x ?= 0 421 | scope.y ?= 0 422 | startPosition = [scope.x, scope.y] 423 | 424 | pressEvents = "touchstart mousedown" 425 | w = angular.element $window 426 | updateDimensions() 427 | ngDragAndDrop.addDraggable scope 428 | bindEvents() 429 | 430 | if scope.dragData 431 | angular.extend scope, scope.dragData 432 | 433 | if scope.clone 434 | scope[scope.dragData.key] = scope.dragData.value 435 | testing = 436 | $compile(angular.element("
"+element.html()+"
"))(scope) 437 | cloneEl = testing 438 | cloneEl.addClass "clone" 439 | cloneEl.addClass element.attr "class" 440 | angular.element(ngDragAndDrop.getDragAndDropElement()).append cloneEl 441 | 442 | transformEl = cloneEl 443 | else 444 | transformEl = element 445 | scope.returnToStartPosition() 446 | 447 | scope.$emit 'drag-ready', scope 448 | 449 | scope.$on '$destroy', -> 450 | unbindEvents() 451 | 452 | # initialization 453 | ngDragAndDrop.on "ready", init 454 | 455 | ] 456 | 457 | # Drop Directive 458 | # ---------- 459 | module.directive 'dropSpot', [ '$window', ($window) -> 460 | restrict: 'AE' 461 | require: '^dragAndDrop' 462 | transclude: true 463 | template: "
" 465 | scope: 466 | dropId: "@" 467 | maxItems: "=" 468 | link: (scope, element, attrs, ngDragAndDrop) -> 469 | 470 | updateDimensions = -> 471 | scope.left = element[0].offsetLeft 472 | scope.top = element[0].offsetTop 473 | scope.right = scope.left + element[0].offsetWidth 474 | scope.bottom = scope.top + element[0].offsetHeight 475 | 476 | # calculates where the item should be dropped to based on its config 477 | getDroppedPosition = (item) -> 478 | dropSize = [ 479 | (scope.right-scope.left) 480 | (scope.bottom-scope.top) 481 | ] 482 | itemSize = [ 483 | (item.right-item.left) 484 | (item.bottom-item.top) 485 | ] 486 | switch item.dropTo 487 | when "top" 488 | xPos = scope.left + (dropSize[0] - itemSize[0])/2 489 | yPos = scope.top 490 | when "bottom" 491 | xPos = scope.left + (dropSize[0] - itemSize[0])/2 492 | yPos = scope.top + (dropSize[1] - itemSize[1]) 493 | when "left" 494 | xPos = scope.left 495 | yPos = scope.top + (dropSize[1] - itemSize[1])/2 496 | when "right" 497 | xPos = scope.left + (dropSize[0] - itemSize[0]) 498 | yPos = scope.top + (dropSize[1] - itemSize[1])/2 499 | when "top left" 500 | xPos = scope.left 501 | yPos = scope.top 502 | when "bottom right" 503 | xPos = scope.left + (dropSize[0] - itemSize[0]) 504 | yPos = scope.top + (dropSize[1] - itemSize[1]) 505 | when "bottom left" 506 | xPos = scope.left 507 | yPos = scope.top + (dropSize[1] - itemSize[1]) 508 | when "top right" 509 | xPos = scope.left + (dropSize[0] - itemSize[0]) 510 | yPos = scope.top 511 | when "center" 512 | xPos = scope.left + (dropSize[0] - itemSize[0])/2 513 | yPos = scope.top + (dropSize[1] - itemSize[1])/2 514 | else 515 | if item.dropOffset 516 | xPos = scope.left + item.dropOffset[0] 517 | yPos = scope.top + item.dropOffset[1] 518 | 519 | return [xPos, yPos] 520 | 521 | scope.itemDropped = (item) -> 522 | added = addItem item 523 | if added 524 | if item.dropTo 525 | newPos = getDroppedPosition item 526 | item.updateOffset newPos[0], newPos[1] 527 | else 528 | item.dropOffset = [ 529 | item.left - scope.left 530 | item.top - scope.top 531 | ] 532 | else 533 | if scope.fixedPositions 534 | item.returnToStartPosition() 535 | 536 | addItem = (item) -> 537 | unless scope.isFull 538 | scope.items.push item 539 | if scope.items.length >= scope.maxItems 540 | scope.isFull = true 541 | return item 542 | return false 543 | 544 | scope.removeItem = (item) -> 545 | index = scope.items.indexOf item 546 | if index > -1 547 | scope.items.splice index, 1 548 | if scope.items.length < scope.maxItems 549 | scope.isFull = false 550 | 551 | scope.activate = () -> 552 | scope.isActive = true 553 | element.addClass "drop-hovering" 554 | 555 | scope.deactivate = () -> 556 | scope.isActive = false 557 | ngDragAndDrop.setCurrentDroppable null 558 | element.removeClass "drop-hovering" 559 | 560 | handleResize = () -> 561 | updateDimensions() 562 | for item in scope.items 563 | newPos = getDroppedPosition(item) 564 | item.updateOffset newPos[0], newPos[1] 565 | 566 | bindEvents = -> 567 | w.bind "resize", handleResize 568 | 569 | unbindEvents = -> 570 | w.unbind "resize", handleResize 571 | 572 | if scope.dropId 573 | element.addClass scope.dropId 574 | 575 | w = angular.element $window 576 | bindEvents() 577 | 578 | scope.$on '$destroy', -> 579 | unbindEvents() 580 | 581 | # initialization 582 | updateDimensions() 583 | scope.isActive = false 584 | scope.items = [] 585 | ngDragAndDrop.addDroppable scope 586 | 587 | ] 588 | -------------------------------------------------------------------------------- /src/less/drag-and-drop.less: -------------------------------------------------------------------------------- 1 | // enable transitions for when items are released 2 | .drag-return drag-item, 3 | .drag-return .drag-item { 4 | transition: all ease-in-out 0.5s; 5 | } 6 | // drag item base styling 7 | drag-item, 8 | [drag-item], 9 | .drag-item { 10 | position:relative; 11 | // display:inline-block; 12 | user-select: none; 13 | cursor:grab; 14 | z-index:10; 15 | &:active { 16 | cursor:grabbing; 17 | } 18 | } 19 | // .drag-transform { 20 | // transition: transform 0.25s ease-out; 21 | // transform-origin: center center; 22 | // &.drag-active { transition: transform 0.25s cubic-bezier(0,.5,0,1); } 23 | // } 24 | .drag-content { 25 | transform: scale(1); 26 | transition: all 0.1s ease-in-out; 27 | } 28 | .drag-active { 29 | z-index:20; 30 | .drag-content { 31 | //transform: scale(1.15); 32 | } 33 | } 34 | 35 | .clone { 36 | opacity:0; 37 | z-index:0; 38 | } 39 | .clone-active { 40 | opacity:1; 41 | z-index:9999; 42 | } 43 | --------------------------------------------------------------------------------