/* * Drag Value plugin * * Uses native dragging to allow elements to be dragged in to inputs, textareas, etc * * Data attributes: * - data-control="dragvalue" - enables the plugin on an element * - data-text-value="text to include" - text value to include when dragging * - data-drag-click="false" - allow click event, tries to cache the last active element * and insert the text at the current cursor position * * JavaScript API: * $('a#someElement').dragValue({ textValue: 'insert this text' }) * */ +function ($) { "use strict"; // DRAG VALUE CLASS DEFINITION // ============================ var DragValue = function(element, options) { this.options = options this.$el = $(element) // Init this.init() } DragValue.DEFAULTS = { dragClick: false } DragValue.prototype.init = function() { this.$el.prop('draggable', true) this.textValue = this.$el.data('textValue') this.$el.on('dragstart', $.proxy(this.handleDragStart, this)) this.$el.on('drop', $.proxy(this.handleDrop, this)) this.$el.on('dragend', $.proxy(this.handleDragEnd, this)) if (this.options.dragClick) { this.$el.on('click', $.proxy(this.handleClick, this)) this.$el.on('mouseover', $.proxy(this.handleMouseOver, this)) } } // // Drag events // DragValue.prototype.handleDragStart = function(event) { var e = event.originalEvent e.dataTransfer.effectAllowed = 'all' e.dataTransfer.setData('text/plain', this.textValue) this.$el .css({ opacity: 0.5 }) .addClass('dragvalue-dragging') } DragValue.prototype.handleDrop = function(event) { event.stopPropagation() return false } DragValue.prototype.handleDragEnd = function(event) { this.$el .css({ opacity: 1 }) .removeClass('dragvalue-dragging') } // // Click events // DragValue.prototype.handleMouseOver = function(event) { var el = document.activeElement if (!el) return if (el.isContentEditable || ( el.tagName.toLowerCase() == 'input' && el.type == 'text' || el.tagName.toLowerCase() == 'textarea' )) { this.lastElement = el } } DragValue.prototype.handleClick = function(event) { if (!this.lastElement) return var $el = $(this.lastElement) if ($el.hasClass('ace_text-input')) return this.handleClickCodeEditor(event, $el) if (this.lastElement.isContentEditable) return this.handleClickContentEditable() this.insertAtCaret(this.lastElement, this.textValue) } DragValue.prototype.handleClickCodeEditor = function(event, $el) { var $editorArea = $el.closest('[data-control=codeeditor]') if (!$editorArea.length) return $editorArea.codeEditor('getEditorObject').insert(this.textValue) } DragValue.prototype.handleClickContentEditable = function() { var sel, range, html; if (window.getSelection) { sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { range = sel.getRangeAt(0); range.deleteContents(); range.insertNode( document.createTextNode(this.textValue) ); } } else if (document.selection && document.selection.createRange) { document.selection.createRange().text = this.textValue; } } // // Helpers // DragValue.prototype.insertAtCaret = function(el, insertValue) { // IE if (document.selection) { el.focus() sel = document.selection.createRange() sel.text = insertValue el.focus() } // Real browsers else if (el.selectionStart || el.selectionStart == '0') { var startPos = el.selectionStart, endPos = el.selectionEnd, scrollTop = el.scrollTop el.value = el.value.substring(0, startPos) + insertValue + el.value.substring(endPos, el.value.length) el.focus() el.selectionStart = startPos + insertValue.length el.selectionEnd = startPos + insertValue.length el.scrollTop = scrollTop } else { el.value += insertValue el.focus() } } // DRAG VALUE PLUGIN DEFINITION // ============================ var old = $.fn.dragValue $.fn.dragValue = function (option) { var args = Array.prototype.slice.call(arguments, 1), result this.each(function () { var $this = $(this) var data = $this.data('oc.dragvalue') var options = $.extend({}, DragValue.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('oc.dragvalue', (data = new DragValue(this, options))) if (typeof option == 'string') result = data[option].apply(data, args) if (typeof result != 'undefined') return false }) return result ? result : this } $.fn.dragValue.Constructor = DragValue // DRAG VALUE NO CONFLICT // ================= $.fn.dragValue.noConflict = function () { $.fn.dragValue = old return this } // DRAG VALUE DATA-API // =============== $(document).render(function() { $('[data-control="dragvalue"]').dragValue() }); }(window.jQuery);