/* * DragComponents plugin * * Data attributes: * - data-control="dragcomponents" - enables the plugin on an element * - data-option="value" - an option with a value * * JavaScript API: * $('a#someElement').dragComponents({ option: 'value' }) * * Dependences: * - Some other plugin (filename.js) */ +function ($) { "use strict"; // DRAGCOMPONENTS CLASS DEFINITION // ============================ var DragComponents = function(element, options) { var self = this this.options = options this.$el = $(element) var $el = this.$el, $clone, $editorArea, $editor, $componentList, adjX = 0, adjY = 0, dragging = false, startPos, editorPos $el.mousedown(function(event){ if ($el.data('component-attached')) return startDrag(event) return false }) $el.on('touchstart', function(event){ if ($el.data('component-attached')) return var touchEvent = event.originalEvent; if (touchEvent.touches.length == 1) { startDrag(touchEvent.touches[0]) event.stopPropagation() } }) function initDrag(event) { $componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist') $el.addClass(self.options.placeholderClass) $clone.show() $editorArea = $('#cms-master-tabs > div.tab-content > .tab-pane.active [data-control="codeeditor"]') if (!$editorArea.length) return $editor = $editorArea.codeEditor('getEditorObject') $editor.focus() $editor.on('mousemove', function (event) { editorPos = event.getDocumentPosition() $editor.clearSelection() $editor.moveCursorToPosition(editorPos) }); } /* * Internal event, drag has started */ function startDrag(event) { startPos = $el.offset() $clone = $el.clone().appendTo($(document.body)) $clone .css({ zIndex: '99999', position: 'absolute', pointerEvents: 'none' }) .addClass('draggable-component-item') .width($el.width()) .height($el.height()) .hide() var objX = (event.pageX - startPos.left), objY = (event.pageY - startPos.top) $clone.data('dragComponents', { x: objX, y: objY }) if (Modernizr.touch) { $(window).on('touchmove.oc.dragcomponents', function(event){ var touchEvent = event.originalEvent moveDrag(touchEvent.touches[0]) event.preventDefault() }) $(window).on('touchend.oc.dragcomponents', function(event) { stopDrag() }) } else { $(window).on('mousemove.oc.dragcomponents', function(event){ moveDrag(event) $(document.body).addClass(self.options.dragClass) return false }) $(window).on('mouseup.oc.dragcomponents', function(mouseUpEvent){ var isClick = event.pageX == mouseUpEvent.pageX && event.pageY == mouseUpEvent.pageY stopDrag(isClick) return false }) } } /* * Internal event, drag is active */ function moveDrag(event) { if (!dragging) { dragging = true initDrag(event) } adjY = $(window).scrollTop() adjX = $(window).scrollLeft() var offset = $clone.data('dragComponents') $clone.css({ left: (event.pageX - adjX - offset.x), top: (event.pageY - adjY - offset.y) }) if (collision($clone, $componentList)) $componentList.addClass('droppable') else $componentList.removeClass('droppable') } /* * Internal event, drag has ended */ function stopDrag(click) { dragging = false if (click) $(document.body).removeClass(self.options.dragClass) $el.removeClass(self.options.placeholderClass) $(window) .off('mousemove.oc.dragcomponents mouseup.oc.dragcomponents') .removeData('dragComponents') if (!click) finishDrag() $clone.remove() window.setTimeout(function(){ if (!click) { $(document.body).removeClass(self.options.dragClass) } }, 100) } function finishDrag() { // Dragged to the code editor if (collision($clone, $editorArea)) { // Add the component to the page $el.click() // Can only attach to page or layouts if ($componentList.length && $editor) { // Inject {% component %} tag var alias = $('input[name="component_aliases[]"]', $el).val() $editor.insert("{% component '" + alias + "' %}") } } // Dragged to the component list else if (collision($clone, $componentList)) { // Add the component to the page $el.click() } if ($editor) { $editor.removeAllListeners('mousemove') $editor.blur() } if ($componentList.length) { $componentList.removeClass('droppable') } } function collision($div1, $div2) { if (!$div1 || !$div2 || !$div1.length || !$div2.length) return false var x1 = $div1.offset().left, y1 = $div1.offset().top, h1 = $div1.outerHeight(true), w1 = $div1.outerWidth(true), b1 = y1 + h1, r1 = x1 + w1, x2 = $div2.offset().left, y2 = $div2.offset().top, h2 = $div2.outerHeight(true), w2 = $div2.outerWidth(true), b2 = y2 + h2, r2 = x2 + w2 return !(b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) } } DragComponents.DEFAULTS = { dragClass: 'drag', placeholderClass: 'placeholder' } // DRAGCOMPONENTS PLUGIN DEFINITION // ============================ var old = $.fn.dragComponents $.fn.dragComponents = function (option) { var args = Array.prototype.slice.call(arguments, 1) return this.each(function () { var $this = $(this) var data = $this.data('oc.dragcomponents') var options = $.extend({}, DragComponents.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('oc.dragcomponents', (data = new DragComponents(this, options))) else if (typeof option == 'string') data[option].apply(data, args) }) } $.fn.dragComponents.Constructor = DragComponents // DRAGCOMPONENTS NO CONFLICT // ================= $.fn.dragComponents.noConflict = function () { $.fn.dragComponents = old return this } // DRAGCOMPONENTS DATA-API // =============== $(document).on('mouseenter.oc.dragcomponents', '[data-control="dragcomponent"]', function() { $(this).dragComponents() }); }(window.jQuery);