Skip to content
This repository has been archived by the owner on Nov 22, 2021. It is now read-only.

Commit

Permalink
Merge f8e78bb into 87d0e6b
Browse files Browse the repository at this point in the history
  • Loading branch information
landonsilla committed Sep 12, 2017
2 parents 87d0e6b + f8e78bb commit af295dc
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 7 deletions.
4 changes: 3 additions & 1 deletion scss/tags-input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ tags-input {
outline: none;
@include box-shadow($tags-outline-box-shadow);
}

.tag-item-dragtag {
cursor:move;
}
.tag-list {
margin: 0;
padding: 0;
Expand Down
104 changes: 102 additions & 2 deletions src/tags-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
* promise is returned, the tag will not be removed.
* @param {expression=} [onTagRemoved=NA] Expression to evaluate upon removing an existing tag. The removed tag is available as $tag.
* @param {expression=} [onTagClicked=NA] Expression to evaluate upon clicking an existing tag. The clicked tag is available as $tag.
* @param {boolean=} [dragtag=false] Whether or not the labels can be dragged to be ordered differently
* @param {expression=} [onTagDragged=NA] Expression to evaluate upon a dropping a dragged tag. The clicked tag is available as $tag.
*/
export default function TagsInputDirective($timeout, $document, $window, $q, tagsInputConfig, tiUtil, tiConstants) {
'ngInject';
Expand Down Expand Up @@ -115,6 +117,13 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
return tag;
});
};

self.reorder = (prevOffset, newOffset) => {
if(prevOffset<0 || newOffset<0 || prevOffset > self.items.length || newOffset > self.items.length || prevOffset==newOffset) return;
self.items.splice(newOffset, 0, self.items.splice(prevOffset, 1)[0]);
self.clearSelection();
events.trigger('tag-dragged');
};

self.select = index => {
if (index < 0) {
Expand Down Expand Up @@ -168,6 +177,7 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
onTagRemoving: '&',
onTagRemoved: '&',
onTagClicked: '&',
onTagDragged: '&'
},
replace: false,
transclude: true,
Expand Down Expand Up @@ -201,7 +211,8 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
allowLeftoverText: [Boolean, false],
addFromAutocompleteOnly: [Boolean, false],
spellcheck: [Boolean, true],
useStrings: [Boolean, false]
useStrings: [Boolean, false],
dragtag: [Boolean, false]
});

$scope.tagList = new TagList($scope.options, $scope.events,
Expand Down Expand Up @@ -280,10 +291,12 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag

scope.getTagClass = (tag, index) => {
let selected = tag === tagList.selected;
return [
var ret = [
scope.tagClass({$tag: tag, $index: index, $selected: selected}),
{ selected: selected }
];
if(options.dragtag)ret.push('tag-item-dragtag')
return ret;
};

scope.$watch('tags', value => {
Expand Down Expand Up @@ -351,11 +364,98 @@ export default function TagsInputDirective($timeout, $document, $window, $q, tag
return;
}
focusInput();
},
mousemove(event){
if(options.dragtag && scope.draggedElement){
var zoomFactor = window.innerWidth / window.outerWidth//accounting for browser zoom in/out
scope.draggedElement.elem.style.left=zoomFactor*(event.screenX - scope.draggedElement.x)+'px';
scope.draggedElement.elem.style.top=zoomFactor*(event.screenY - scope.draggedElement.y)+'px';
}
}
},
tag: {
click(tag) {
events.trigger('tag-clicked', { $tag: tag });
},
mousedown(event){
if(options.dragtag){
var target = event.target || event.srcElement || event.currentTarget;
if(target.tagName=='A')return;//if you hit the A, don't do this
while(target.tagName!='LI')target = target.parentElement //go up parents until you find the LI
target.style.position='relative';
scope.draggedElement = {'elem':target,'x':event.screenX,'y':event.screenY}

//console.log('pick up element at '+scope.draggedElement.x+" "+scope.draggedElement.y)

event.preventDefault();
event.stopImmediatePropagation();
}
},
mouseup(event){
if(options.dragtag && scope.draggedElement){
//console.log('put down element at '+event.screenX+" "+event.screenY)

var listHolder = scope.draggedElement.elem.parentElement
var allElems = listHolder.getElementsByTagName("LI")
var prevOffset = -1;
var newOffset = -1;

//find elem's offset
for(var i=0;i<allElems.length;i++){
if(allElems[i].style.position=='relative')
prevOffset = i;
}


//which coordinate do you want to consider for elem? top left? center? mouse position? .... this does the midpoint
var elem_x = scope.draggedElement.elem.offsetLeft + scope.draggedElement.elem.offsetWidth/2
var elem_y = scope.draggedElement.elem.offsetTop + scope.draggedElement.elem.offsetHeight/2

for(var i=0;i<allElems.length;i++){
if(i==prevOffset)continue;//don't consider yourself

var x_lo = allElems[i].offsetLeft
var x_hi = allElems[i].offsetLeft + allElems[i].offsetWidth
var y_lo = allElems[i].offsetTop
var y_hi = allElems[i].offsetTop + allElems[i].offsetHeight

//it's the end of the list OR the next one's upper bound is greater than current low bound
var end_of_line = i==allElems.length-1 || allElems[i+1].offsetTop > y_hi

//option 1: elem's position is inside the bounding box of this considered element
if(x_lo <= elem_x && elem_x <= x_hi && y_lo <= elem_y && elem_y <= y_hi ){
newOffset=i;
break;
}

//option 2: elem's y is within bounding box AND x is greater AND it's end of the line
if( y_lo <= elem_y && elem_y <= y_hi && elem_x > x_hi && end_of_line){
newOffset=i;
break;
}

//option 3: the last line is empty, and you drop it there, so it has to consider the last element, and elem_y is higher than the y val
if(i==allElems.length-1 && elem_y > y_hi){
newOffset=i;
break;
}

//option 4: you drop it to the left of a guy that's on the beginning of the line
if((i==0 || allElems[i-1].offsetTop < y_lo) && y_lo < elem_y && elem_y <y_hi && elem_x < x_lo){
newOffset=i;
break;
}
}

if(prevOffset!=-1 && newOffset!=-1 && newOffset!=prevOffset){
//console.log('moving:'+prevOffset+" to:"+newOffset)
tagList.reorder(prevOffset,newOffset);
}

//undo the "temp" stuff to be ready for the next one ...
scope.draggedElement.elem.style.position='static'
scope.draggedElement = null
}
}
}
};
Expand Down
6 changes: 4 additions & 2 deletions templates/tags-input.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<div class="host" tabindex="-1" ng-click="eventHandlers.host.click()" ti-transclude-append>
<div class="host" tabindex="-1" ng-click="eventHandlers.host.click()" ng-mousemove="eventHandlers.host.mousemove($event)" ti-transclude-append>
<div class="tags" ng-class="{focused: hasFocus}">
<ul class="tag-list">
<li class="tag-item"
ng-repeat="tag in tagList.items track by track(tag)"
ng-class="getTagClass(tag, $index)"
ng-click="eventHandlers.tag.click(tag)">
ng-click="eventHandlers.tag.click(tag)"
ng-mousedown="eventHandlers.tag.mousedown($event)"
ng-mouseup="eventHandlers.tag.mouseup($event)">
<ti-tag-item scope="templateScope" data="::tag"></ti-tag-item>
</li>
</ul>
Expand Down
4 changes: 2 additions & 2 deletions test/test-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="lib/ng-stats.min.js"></script>
<script type="text/javascript" src="../build/ng-tags-input.min.js"></script>
<link rel="stylesheet" href="../build/ng-tags-input.min.css"/>
<link rel="stylesheet" href="http://mbenford.github.io/ngTagsInput/css/ng-tags-input.min.css"/>

<style>
.stats {
Expand All @@ -23,7 +23,7 @@
</head>

<body ng-controller="Ctrl">
<tags-input ng-model="tags" add-on-blur="false" ng-focus="focus()" ng-blur="blur()" add-on-paste="true" paste-split-pattern="[,;|]" spellcheck="false" display-property="name" template="tag-template">
<tags-input ng-model="tags" add-on-blur="false" ng-focus="focus()" ng-blur="blur()" add-on-paste="true" paste-split-pattern="[,;|]" spellcheck="false" display-property="name" template="tag-template" dragtag="true">
<auto-complete source="loadItems($query)" min-length="1" load-on-down-arrow="true" load-on-focus="true" load-on-empty="true" template="autocomplete-template"></auto-complete>
</tags-input>

Expand Down

0 comments on commit af295dc

Please sign in to comment.