Al Ex Tsm Al Ex Tsm - 5 months ago 24
Javascript Question

angular ui-sortable offset on drag if page scrolled before

I have found that if a page is scrollable, after scroll if intended to drag and drop an item(in order to sort an ng-repeat list) then the dragged element appears with as much offset on the y-axis as distance I have scrolled down the page before dragging the element.

I am using:
https://github.com/angular-ui/ui-sortable

The issue is documented here:
https://github.com/angular-ui/ui-sortable/issues/286

I don't seem to be able to call the ui.item.sort('refreshPosition') method. Neither sure if should do so by editing the original code, or in my own controller!?

This is my relevant template code:

<script type="text/ng-template" id="form_field_ref2">
<div ng-init="tmp = dbo.get(attobj.name)" ng-controller="sortController">
<!-- <div ng-model="tmp" ui-sortable="{ 'ui-floating': 'auto'}">-->
<div ng-model="tmp" ui-sortable="sortableOptions">
<div ng-repeat="dbo2 in dbo.get(attobj.name) track by $index" id="sort_{{$index}}" style="float:left; padding-right: 3px; padding-bottom: 5px;">
<div class="tag sortableTag">
<a href="#/view/{{ dbo2.cid }}" target="_blank">{{ dbo2.displayName() }}</a>
<a href="" class="glyphicon glyphicon-remove" ng-click="dbo.removeValue(attobj.name, $index)"></a>
</div>
</div>

</div>
</div>

<div ng-include="'typeaheadtemplate2'" style="width: 100%;"></div>
</script>


controller:

app.controller('sortController', function ($scope) {

$scope.sortableOptions = {
'ui-floating': 'auto',
activate: function() {
console.log("activate");
},
beforeStop: function() {
console.log("beforeStop");
},
change: function() {
console.log("change");
},
create: function() {
console.log("create");
},
deactivate: function() {
console.log("deactivate");
},
out: function() {
console.log("out");
},
over: function() {
console.log("over");
},
receive: function() {
console.log("receive");
},
remove: function() {
console.log("remove");
},
sort: function() {
console.log("sort");
},
start: function(e, ui) {
console.log("start");
console.log(ui.item);
var tag= '#'+ui.item.context.id;
$(tag).sortable('refreshPositions');
// $(this).sortable('refreshPositions');
},
update: function(e, ui) {
console.log("update");

},
stop: function(e, ui) {
console.log("stop");

}
};
});


Attempt to drag the highlighted tag in blue:
enter image description here

Appears with an offset by respect of the mouse cursor which is in the tags original position(sorry the cursor doesn't appear on image):
enter image description here

Error with unique selector id:
enter image description here

T J T J
Answer

The issue is that, you're trying to invoke refreshPositions on ui.item.sortable which is an object that ui-sortable uses to store data. You should call refreshPositions on the element which is sortable.

try

<script type="text/ng-template" id="form_field_ref2">
  <div ng-init="tmp = dbo.get(attobj.name)" ng-controller="sortController">
   <!-- <div ng-model="tmp" ui-sortable="{ 'ui-floating': 'auto'}">-->
    <div ng-model="tmp" ui-sortable="sortableOptions">
      <div ng-repeat="dbo2 in dbo.get(attobj.name) track by $index" style="float:left; padding-right: 3px; padding-bottom: 5px;">
        <div class="tag sortableTag">
          <a href="#/view/{{ dbo2.cid }}" target="_blank">{{ dbo2.displayName() }}</a>
          <a href="" class="glyphicon glyphicon-remove" ng-click="dbo.removeValue(attobj.name, $index)"></a>
        </div>
      </div>

    </div>
  </div>

  <div ng-include="'typeaheadtemplate2'" style="width: 100%;"></div>
</script>

controller:

app.controller('sortController', function ($scope) {

   $scope.sortableOptions = {
                start: function(event, ui) {
                    $(this).sortable({
                            sort: function(event, ui) {
                                var $target = $(event.target);
                                if (!/html|body/i.test($target.offsetParent()[0].tagName)) {
                                    var top = event.pageY - $target.offsetParent().offset().top - (ui.helper.outerHeight(true) / 2);
                                    ui.helper.css({'top' : top + 'px'});
                                }
                            }
                    });

                }
            };


});