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