eads@16: /**
eads@16: * Drag and Drop Library For Drupal
eads@16: *
eads@16: * This builds on the DnD jQuery plugin written to provide drag and drop media
eads@16: * handling to Rich Text Editors to consume, display, and attach behavior to
eads@16: * a "media library" provided via JSON and implemented for Drupal running
eads@16: * the Wysiwyg plugin.
eads@16: */
eads@16:
eads@16: /**
eads@16: * Extend jQuery a bit
eads@16: *
eads@16: * We add a selector to look for "empty" elements (empty elements in TinyMCE
eads@17: * often have non-breaking spaces and
tags). An exception is required
eads@17: * to make this work in IE.
eads@16: */
eads@16: (function($) {
eads@16: // Custom selectors
eads@16: $.extend($.expr[":"], {
eads@31: 'dnd_empty' : function(a, i, m) {
eads@17: return !$(a).filter(function(i) {
eads@17: return !$(this).is('br');
eads@30: }).length && !$.trim(a.textContent || a.innerText||$(a).text() || "");
eads@16: }
eads@16: });
eads@16: }) (jQuery);
eads@16:
eads@30: /**
eads@30: * Initialize and load drag and drop library and pass off rendering and
eads@30: * behavior attachment.
eads@30: */
eads@2: Drupal.behaviors.dndLibrary = function(context) {
eads@16: $('.dnd-library-wrapper', context).each(function() {
eads@4: var $this = $(this);
eads@2:
eads@4: // This is a bad hack to lop off '-dnd-library' from the id to get the editor name
eads@17: var $editor = $('#' + this.id.slice(0, -12));
eads@17:
eads@30: // Set up some initial settings for BeautyTips
eads@30: var settings = Drupal.settings.dndEnabledLibraries[$editor.get(0).id] = $.extend({
eads@31: 'btSettings' : {
franck@35: 'trigger': ['click'],
franck@41: 'width': 480,
eads@20: 'spikeLength': 7,
eads@20: 'spikeGirth': 9,
eads@18: 'corner-radius' : 3,
eads@20: 'strokeWidth': 1,
eads@20: 'fill': '#ffd',
franck@35: 'strokeStyle': '#555',
franck@35: 'closeWhenOthersOpen': true
eads@31: },
eads@31: 'libraryHoverIntentSettings' : {
eads@31: 'interval': 500,
eads@31: 'timeout' : 0,
eads@31: 'over': function() {
eads@31: var $this = $(this);
eads@31: this.btOn();
eads@31: // Remove the preview once dragging of any image has commenced
eads@31: $('img', $this).bind('drag', function(e) {
eads@31: $this.btOff();
eads@31: });
eads@31: $('img', $this).bind('click', function(e) {
eads@31: $this.btOff();
eads@31: });
eads@31: },
eads@31: 'out': function() { this.btOff(); }
eads@31: }
eads@30: }, Drupal.settings.dndEnabledLibraries[$editor.get(0).id]);
eads@24:
eads@24: // Bind Drag and Drop plugin invocation to events emanating from Wysiwyg
eads@24: $editor.bind('wysiwygAttach', Drupal.behaviors.dndLibrary.attach_library);
eads@24: $editor.bind('wysiwygDetach', Drupal.behaviors.dndLibrary.detach_library);
eads@24:
eads@30: // Set up empty objects to keep track of things
eads@30: Drupal.settings.dndEditorRepresentations = {};
eads@30: Drupal.settings.dndLibraryPreviews = {};
franck@36:
franck@36: // Clean up the url if needed (this happen in case drupal_add_js is called
franck@36: // multiple time for the page)
franck@36: if (settings.url instanceof Object) {
franck@36: settings.url = settings.url[0];
franck@36: }
eads@30:
eads@31: // Initialize the library
eads@30: $.getJSON(Drupal.settings.basePath + settings.url, function(data) {
eads@30: Drupal.behaviors.dndLibrary.renderLibrary.call($this.get(0), data, $editor);
eads@17: });
eads@4:
eads@4: });
eads@4: }
eads@2:
eads@30: Drupal.behaviors.dndLibrary.renderLibrary = function(data, editor) {
eads@17: $this = $(this);
eads@17:
eads@30: $this.html(data.library);
eads@17:
eads@30: var settings = Drupal.settings.dndEnabledLibraries[editor.get(0).id];
eads@17: var params = Drupal.wysiwyg.instances[editor.get(0).id];
eads@30:
eads@17: editor.trigger('wysiwygDetach', params);
eads@17: editor.trigger('wysiwygAttach', params);
eads@17:
eads@17: for (editor_id in data.editor_representations) {
eads@17: Drupal.settings.dndEditorRepresentations[editor_id] = data.editor_representations[editor_id];
eads@17: }
eads@17: for (preview_id in data.library_previews) {
eads@17: Drupal.settings.dndLibraryPreviews[preview_id] = data.library_previews[preview_id];
eads@17: }
eads@19:
eads@30: // Add preview behavior to editor items (thanks, BeautyTips!)
eads@30: $('.editor-item', $this).each(function () {
eads@31: $(this).bt(Drupal.settings.dndLibraryPreviews[this.id], settings.btSettings);
franck@43: //$(this).hoverIntent(settings.libraryHoverIntentSettings);
eads@30: });
eads@30:
eads@30: // Preload images in editor representations
eads@30: var cached = $.data($(editor), 'dnd_preload') || {};
eads@31: for (editor_id in Drupal.settings.dndEditorRepresentations) {
eads@30: if (!cached[editor_id]) {
eads@30: $representation = $(Drupal.settings.dndEditorRepresentations[editor_id].body);
eads@30: if ($representation.is('img') && $representation.get(0).src) {
eads@30: $representation.attr('src', $representation.get(0).src);
eads@30: } else {
eads@30: $('img', $representation).each(function() {
eads@31: $(this).attr('src', this.src);
eads@30: });
eads@30: }
eads@30: }
eads@30: }
eads@31: $.data($(editor), 'dnd_preload', cached);
eads@30:
eads@31: $('.pager a', $this).click(function() {
franck@42: // At page switching, close all opened BeautyTips.
franck@42: $('.editor-item.bt-active').btOff();
eads@31: $.getJSON(this.href, function(data) {
eads@31: Drupal.behaviors.dndLibrary.renderLibrary.call($this.get(0), data, $(editor));
eads@31: });
eads@31: return false;
eads@31: });
eads@31: $('.view-filters input[type=submit]', $this).click(function() {
franck@32: $('.view-filters form', $this).ajaxSubmit({
eads@31: 'url' : Drupal.settings.basePath + settings.url,
eads@31: 'dataType' : 'json',
eads@31: 'success' : function(data) {
eads@31: Drupal.behaviors.dndLibrary.renderLibrary.call($this.get(0), data, $(editor));
eads@31: }
eads@31: });
eads@31: return false;
eads@31: });
franck@37: Drupal.attachBehaviors($this);
eads@17: }
eads@17:
eads@16: // Dynamically compose a callback based on the editor name
eads@4: Drupal.behaviors.dndLibrary.attach_library = function(e, data) {
eads@17: var settings = $.extend({idSelector: Drupal.behaviors.dndLibrary.idSelector}, Drupal.settings.dndEnabledLibraries[data.field]);
eads@4: var editor_fn = 'attach_' + data.editor;
eads@4: if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) {
eads@17: window.Drupal.behaviors.dndLibrary[editor_fn](data, settings);
eads@2: }
eads@2: }
eads@2:
eads@16: // Do garbage collection on detach
eads@31: Drupal.behaviors.dndLibrary.detach_library = function(e, data) {}
eads@4:
eads@16: // Basic textareas
eads@16: Drupal.behaviors.dndLibrary.attach_none = function(data, settings) {
eads@16: settings = $.extend({
eads@16: targets: $('#'+ data.field),
eads@25: processTextAreaClick: function(clicked, representation_id, e, data) {
eads@25: var target = this, $target = $(target);
eads@25:
eads@25: // Update element count
eads@25: Drupal.behaviors.dndLibrary.countElements.call(target, representation_id);
eads@25:
franck@38: var rep = Drupal.settings.dndEditorRepresentations[representation_id];
franck@38: var snippet = '