      1 /*
      2  * code review by Pavel Yaschenko
      3  *
      4  * No event's unbindings when component would be destroyed
      5  * Hint: easy way to unbind - use namespaces when bind event handlers
      6  *
      7  */
      8
      9 (function ($, rf) {
     10
     11     rf.ui = rf.ui || {};
     12
     13     var defaultIndicatorClasses = {
     14         rejectClass : "rf-ind-rejt",
     15         acceptClass : "rf-ind-acpt",
     16         draggingClass : "rf-ind-drag"
     17     };
     18
     19     rf.ui.Draggable = function(id, options) {
     20         this.options = {};
     21         $.extend(this.options, defaultOptions, options || {});
     22         $super.constructor.call(this, id);
     23
     24         this.id = id;
     25
     26         this.namespace = this.namespace || "."
     27             + rf.Event.createNamespace(this.name, this.id);
     28
     29         this.parentId = this.options.parentId;
     30         this.attachToDom(this.parentId);
     31         this.dragElement = $(document.getElementById(this.options.parentId));
     32         this.dragElement.draggable();
     33
     34         if (options.indicator) {
     35             var element = $(document.getElementById(options.indicator));
     36             var clone = element.clone();
     37             $("*[id]", clone).andSelf().each(function() {
     38                 $(this).removeAttr("id");
     39             });
     40             if (element.attr("id")) {
     41                 clone.attr("id", element.attr("id") + "Clone");
     42             }
     43
     44             this.dragElement.data("indicator", true);
     45             this.dragElement.draggable("option", "helper", function() {
     46                 return clone;
     47             });
     48         } else {
     49             this.dragElement.data("indicator", false);
     50             this.dragElement.draggable("option", "helper", 'clone');
     51         }
     52
     53         this.dragElement.draggable("option", "addClasses", false);
     54         this.dragElement.draggable( "option", "appendTo", "body" );
     55
     56
     57         this.dragElement.data('type', this.options.type);
     58         this.dragElement.data("init", true);
     59         this.dragElement.data("id", this.id);
     60         rf.Event.bind(this.dragElement, 'dragstart' + this.namespace, this.dragStart, this);
     61         rf.Event.bind(this.dragElement, 'drag' + this.namespace, this.drag, this);
     62     };
     63
     64     rf.BaseNonVisualComponent.extend(rf.ui.Draggable);
     65
     66     // define super class link
     67     var $super = rf.ui.Draggable.$super;
     68
     69     var defaultOptions = {
     70     };
     71
     72     $.extend(rf.ui.Draggable.prototype, ( function () {
     73         return {
     74             name : "Draggable",
     75             dragStart: function(e) {
     76                 var ui = e.rf.data;
     77                 var element = ui.helper[0];
     78                 this.parentElement = element.parentNode;
     79
     80                 if (this.__isCustomDragIndicator()) {
     81                     ui.helper.detach().appendTo("body").show();
     82
     83                     // move cursor to the center of custom dragIndicator;
     84                     var left = (ui.helper.width() / 2);
     85                     var top = (ui.helper.height() / 2);
     86                     this.dragElement.data('ui-draggable').offset.click.left = left;
     87                     this.dragElement.data('ui-draggable').offset.click.top = top;
     88
     89                 }
     90             },
     91
     92             drag: function(e) {
     93                 var ui = e.rf.data;
     94                 if (this.__isCustomDragIndicator()) {
     95                     var indicator = rf.component(this.options.indicator);
     96                     if (indicator) {
     97                         ui.helper.addClass(indicator.getDraggingClass());
     98                     } else {
     99                         ui.helper.addClass(defaultIndicatorClasses.draggingClass);
    100                     }
    101                 }
    102                 this.__clearDraggableCss(ui.helper);
    103             },
    104
    105             __isCustomDragIndicator: function() {
    106                 return this.dragElement.data("indicator");
    107             },
    108
    109             __clearDraggableCss: function(element) {
    110                 if (element && element.removeClass) {
    111                     //draggable 'addClasses: false' doesn't work so clear jQuery style
    112                     element.removeClass("ui-draggable-dragging");
    113                 }
    114             },
    115
    116             destroy : function() {
    117                 // clean up code here
    118                 this.detach(this.parentId);
    119                 rf.Event.unbind(this.dragElement, this.namespace);
    120                 // call parent's destroy method
    121                 $super.destroy.call(this);
    122             }
    123         }
    124     })());
    125 })(RichFaces.jQuery, window.RichFaces);
    126