2014-05-08

[AngularJS] 製作 jQuery UI Sortable directive

Html
<div jq-sortable="selectedList">
    <div ng-repeat="item in selectedList">
        <img ng-src="{{item.src}}" />
    </div>
</div>


JavaScript
app.directive('jqSortable', ['$parse', function($parse) {
    return function(scope, element, attrs) {
        /*解析並取得表達式*/
        var expr = $parse(attrs['jqSortable']);
        var $oldChildren;

        element.sortable({
            opacity: 0.7,
            scroll: false,
            tolerance: "pointer",
            start: function() {
                /*紀錄移動前的 children 順序*/
                $oldChildren = element.children('[ng-repeat]');
            },
            update: function(){
                var newList = [];
                var oldList = expr(scope);
                var $children = element.children('[ng-repeat]');

                /*產生新順序的陣列*/
                $oldChildren.each(function(i){
                    var index = $children.index(this);
                    if(index == -1){ return; }

                    newList[index] = oldList[i];
                });

                /*將新順序的陣列寫回 scope 變數*/
                expr.assign(scope, newList);

                /*通知 scope 有異動發生*/
                scope.$digest();
            }
        });

        /*在 destroy 時解除 Sortable*/
        scope.$on('$destroy', function(){
            element.sortable('destroy');
        });
    };
}]);

[AngularJS] 製作 Mouse Drag Event directive

Html
<div ng-style="{'top': itemTop, 'left': itemLeft}"
    my-mousedrag="itemTop = itemTop - $deltaY; itemLeft = itemLeft - $deltaX"
></div>

JavaScript
app.directive('myMousedrag', function() {
    return function(scope, element, attrs) {
        var prevEvent;
        element.mousedown(function(event){
            prevEvent = event;

        }).mouseup(function(event){
            prevEvent = null;

        }).mousemove(function(event){
            if(!prevEvent){ return; }

            /*將 element 拖移事件傳遞到 scope 上*/
            scope.$eval(attrs['myMousedrag'], {
                $event: event,
                $deltaX: event.clientX - prevEvent.clientX,
                $deltaY: event.clientY - prevEvent.clientY
            });

            /*通知 scope 有異動發生*/
            scope.$digest();

            prevEvent = event;
        });

        /*在 destroy 時清除事件註冊*/
        scope.$on('$destroy', function(){
            element.off('mousedown mouseup mousemove');
        });
    };
});

[AngularJS] 製作 jQuery MouseWheel directive

相依套件:jquery-mousewheel

Html
<div jq-mousewheel="changeSize($event, $delta, $deltaX, $deltaY)"></div>

JavaScript
app.directive('jqMousewheel', function(){
    return function(scope, element, attrs) {

        /*將 element 滾輪事件傳遞到 scope 上*/
        element.on('mousewheel', function (event) {
            scope.$eval(attrs['jqMousewheel'], {
                $event: event,
                $delta: event.delta,
                $deltaX: event.deltaX,
                $deltaY: event.deltaY
            });

            /*通知 scope 有異動發生*/
            scope.$digest();
        });

        /*在 destroy 時清除事件註冊*/
        scope.$on('$destroy', function(){
            element.off('mousewheel');
        });
    };
});

[AngularJS] 製作 jQuery scrollTop scrollLeft directive

Html
<div jq-scroll-top="viewerScrollTop" 
      jq-scroll-left="viewerScrollLeft"
></div>

JavaScript
app.directive('jqScrollTop', ['$parse', function($parse){
    return function(scope, element, attrs) {
        /*解析並取得表達式*/
        var expr = $parse(attrs['jqScrollTop']);

        /*監聽變數異動,並更新到 element 上*/
        scope.$watch(attrs['jqScrollTop'], function(value) {
            element.scrollTop(value);
        });

        /*當 element 捲動時更新到變數上*/
        element.on('scroll', function() {
            expr.assign(scope, element.scrollTop());
        });

        /*在 destroy 時清除事件註冊*/
        scope.$on('$destroy', function(){
            element.off('scroll');
        });
    };
}]);

app.directive('jqScrollLeft', ['$parse', function($parse){
    return function(scope, element, attrs) {
        /*解析並取得表達式*/
        var expr = $parse(attrs['jqScrollLeft']);

        /*監聽變數異動,並更新到 element 上*/
        scope.$watch(attrs['jqScrollLeft'], function(value) {
            element.scrollLeft(value);
        });

        /*當 element 捲動時更新到變數上*/
        element.on('scroll', function() {
            expr.assign(scope, element.scrollLeft());
        });

        /*在 destroy 時清除事件註冊*/
        scope.$on('$destroy', function(){
            element.off('scroll');
        });
    };
}]);