Mercurial > defr > drupal > scald > dnd
comparison js/dnd-library.js @ 17:1a77f87927dd
Fixed :empty custom selector behavior in IE, a little refactoring, etc.
| author | David Eads <eads@chicagotech.org> |
|---|---|
| date | Wed, 04 Mar 2009 13:29:31 -0600 |
| parents | bb68dc3ad56f |
| children | 0d557e6e73f7 |
comparison
equal
deleted
inserted
replaced
| 16:bb68dc3ad56f | 17:1a77f87927dd |
|---|---|
| 9 | 9 |
| 10 /** | 10 /** |
| 11 * Extend jQuery a bit | 11 * Extend jQuery a bit |
| 12 * | 12 * |
| 13 * We add a selector to look for "empty" elements (empty elements in TinyMCE | 13 * We add a selector to look for "empty" elements (empty elements in TinyMCE |
| 14 * often have non-breaking spaces and <br /> tags). | 14 * often have non-breaking spaces and <br /> tags). An exception is required |
| 15 * to make this work in IE. | |
| 15 */ | 16 */ |
| 16 (function($) { | 17 (function($) { |
| 17 // Custom selectors | 18 // Custom selectors |
| 18 $.extend($.expr[":"], { | 19 $.extend($.expr[":"], { |
| 19 'empty' : function(a, i, m) { | 20 'empty' : function(a, i, m) { |
| 20 var text = $(a).html(); | 21 return !$(a).filter(function(i) { |
| 21 text.replace(/\u00a0/g,''); // Remove | 22 return !$(this).is('br'); |
| 22 $('br', $(text)).remove(); // Remove breaks | 23 }).length && !$.trim(a.textContent || a.innerText||$(a).text()||""); |
| 23 return !$.trim(text); | |
| 24 } | 24 } |
| 25 }); | 25 }); |
| 26 }) (jQuery); | 26 }) (jQuery); |
| 27 | 27 |
| 28 Drupal.behaviors.dndLibrary = function(context) { | 28 Drupal.behaviors.dndLibrary = function(context) { |
| 29 $('.dnd-library-wrapper', context).each(function() { | 29 $('.dnd-library-wrapper', context).each(function() { |
| 30 var $this = $(this); | 30 var $this = $(this); |
| 31 | 31 |
| 32 // This is a bad hack to lop off '-dnd-library' from the id to get the editor name | 32 // This is a bad hack to lop off '-dnd-library' from the id to get the editor name |
| 33 var editor = this.id.slice(0, -12); | 33 var $editor = $('#' + this.id.slice(0, -12)); |
| 34 | |
| 34 | 35 |
| 35 // Bind Drag and Drop plugin invocation to events emanating from Wysiwyg | 36 // Bind Drag and Drop plugin invocation to events emanating from Wysiwyg |
| 36 $('#' + editor).bind('wysiwygAttach', Drupal.behaviors.dndLibrary.attach_library); | 37 $editor.bind('wysiwygAttach', Drupal.behaviors.dndLibrary.attach_library); |
| 37 $('#' + editor).bind('wysiwygDetach', Drupal.behaviors.dndLibrary.detach_library); | 38 $editor.bind('wysiwygDetach', Drupal.behaviors.dndLibrary.detach_library); |
| 39 | |
| 40 // Add basic hover behavior to editor items | |
| 41 $('.editor-item', context).hover(function() { | |
| 42 var $this = $(this); | |
| 43 var p = $('#edit-body-wrapper').position(); | |
| 44 var preview = $(Drupal.settings.dndLibraryPreviews[this.id]).css({ | |
| 45 'position' : 'absolute', | |
| 46 'top' : p.top + 150, | |
| 47 'left' : p.left + $('#edit-body-wrapper').width() + 150, | |
| 48 'display' : 'none', | |
| 49 'width' : '300px', | |
| 50 'background-color' : '#ddd', | |
| 51 'border' : '3px solid #999', | |
| 52 'padding' : '4px', | |
| 53 'z-index' : 10 | |
| 54 }); | |
| 55 $('body').prepend(preview); | |
| 56 preview.fadeIn('slow'); | |
| 57 }, function() { | |
| 58 $('#' + this.id.replace(/test/,'preview')).fadeOut('fast', function() { $(this).remove(); }); | |
| 59 }); | |
| 38 | 60 |
| 39 // Ajax pager | 61 // Ajax pager |
| 40 $('.pager a', $this).click(function(e, data) { | 62 $('.pager a', $this).click(function() { |
| 41 $.getJSON(this.href, function(data) { | 63 $.getJSON(this.href, function(data) { |
| 42 $('.header', $this).html(data.header); | 64 Drupal.behaviors.dndLibrary.refreshLibrary.call($this.get(0), data, $editor); |
| 43 $('.library', $this).html(data.library); | |
| 44 //$('.footer', $this).html(data.footer); | |
| 45 for (editor_id in data.editor_representations) { | |
| 46 Drupal.settings.dndEditorRepresentations[editor_id] = data.editor_representations[editor_id]; | |
| 47 } | |
| 48 var params = Drupal.wysiwyg.instances[editor]; | |
| 49 $('#' + editor).trigger('wysiwygDetach', params); | |
| 50 $('#' + editor).trigger('wysiwygAttach', params); | |
| 51 }); | 65 }); |
| 66 | |
| 67 // Reattach behaviors | |
| 68 Drupal.behaviors.dndLibrary(); | |
| 69 | |
| 52 return false; | 70 return false; |
| 53 }); | 71 }); |
| 72 | |
| 73 // Preload images in editor representations | |
| 74 var cached = $.data($editor, 'dnd_preload') || {}; | |
| 75 for (editor_id in Drupal.settings.dndEditorRepresentations) { | |
| 76 if (!cached[editor_id]) { | |
| 77 $representation = $(Drupal.settings.dndEditorRepresentations[editor_id]); | |
| 78 if ($representation.is('img') && $representation.get(0).src) { | |
| 79 $representation.attr('src', $representation.get(0).src); | |
| 80 } else { | |
| 81 $('img', $representation).each(function() { | |
| 82 this.attr('src', this.src); | |
| 83 }); | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 $.data($editor, 'dnd_preload', cached); | |
| 54 }); | 88 }); |
| 55 } | 89 } |
| 90 | |
| 91 Drupal.behaviors.dndLibrary.refreshLibrary = function(data, editor) { | |
| 92 $this = $(this); | |
| 93 | |
| 94 $('.header', $this).html(data.header); | |
| 95 $('.library', $this).html(data.library); | |
| 96 $('.footer', $this).html(data.footer); | |
| 97 | |
| 98 var params = Drupal.wysiwyg.instances[editor.get(0).id]; | |
| 99 editor.trigger('wysiwygDetach', params); | |
| 100 editor.trigger('wysiwygAttach', params); | |
| 101 | |
| 102 for (editor_id in data.editor_representations) { | |
| 103 Drupal.settings.dndEditorRepresentations[editor_id] = data.editor_representations[editor_id]; | |
| 104 } | |
| 105 for (preview_id in data.library_previews) { | |
| 106 Drupal.settings.dndLibraryPreviews[preview_id] = data.library_previews[preview_id]; | |
| 107 } | |
| 108 } | |
| 109 | |
| 56 | 110 |
| 57 // Dynamically compose a callback based on the editor name | 111 // Dynamically compose a callback based on the editor name |
| 58 Drupal.behaviors.dndLibrary.attach_library = function(e, data) { | 112 Drupal.behaviors.dndLibrary.attach_library = function(e, data) { |
| 113 var settings = $.extend({idSelector: Drupal.behaviors.dndLibrary.idSelector}, Drupal.settings.dndEnabledLibraries[data.field]); | |
| 59 var editor_fn = 'attach_' + data.editor; | 114 var editor_fn = 'attach_' + data.editor; |
| 60 if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) { | 115 if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) { |
| 61 window.Drupal.behaviors.dndLibrary[editor_fn](data, Drupal.settings.dndEnabledLibraries[data.field]); | 116 window.Drupal.behaviors.dndLibrary[editor_fn](data, settings); |
| 62 } | 117 } |
| 63 } | 118 } |
| 64 | 119 |
| 65 // Do garbage collection on detach | 120 // Do garbage collection on detach |
| 66 Drupal.behaviors.dndLibrary.detach_library = function(e, data) { | 121 Drupal.behaviors.dndLibrary.detach_library = function(e, data) { |
| 72 | 127 |
| 73 // Basic textareas | 128 // Basic textareas |
| 74 Drupal.behaviors.dndLibrary.attach_none = function(data, settings) { | 129 Drupal.behaviors.dndLibrary.attach_none = function(data, settings) { |
| 75 settings = $.extend({ | 130 settings = $.extend({ |
| 76 targets: $('#'+ data.field), | 131 targets: $('#'+ data.field), |
| 77 procressTextAreaDrop: function(target, clicked, representation_id, e, data) { | 132 processTextAreaDrop: function(target, clicked, representation_id, e, data) { |
| 78 var snippet = Drupal.settings.dndEditorRepresentations[representation_id]; | 133 var snippet = '<p class="dnd-dropped-wrapper">' + Drupal.settings.dndEditorRepresentations[representation_id] + '</p>'; |
| 79 $(target).replaceSelection(snippet, true); | 134 $(target).replaceSelection(snippet, true); |
| 80 } | 135 } |
| 81 }, settings); | 136 }, settings); |
| 82 $(settings.drop_selector).dnd(settings); | 137 $(settings.drop_selector).dnd(settings); |
| 83 } | 138 } |
| 99 } | 154 } |
| 100 }, 100); | 155 }, 100); |
| 101 } | 156 } |
| 102 } | 157 } |
| 103 | 158 |
| 159 Drupal.behaviors.dndLibrary.idSelector = function(element) { | |
| 160 if ($(element).is('img')) { | |
| 161 return $.url.setUrl(element.src).param('dnd_id'); | |
| 162 } | |
| 163 return false; | |
| 164 } | |
| 165 | |
| 104 // Really attach TinyMCE | 166 // Really attach TinyMCE |
| 105 Drupal.behaviors.dndLibrary._attach_tinymce = function(data, settings, tiny_instance) { | 167 Drupal.behaviors.dndLibrary._attach_tinymce = function(data, settings, tiny_instance) { |
| 106 var ed = tiny_instance, dom = ed.dom, s = ed.selection; | 168 var ed = tiny_instance, dom = ed.dom, s = ed.selection; |
| 107 | 169 |
| 108 settings = $.extend({ | 170 settings = $.extend({ |
| 109 targets: $('#'+ data.field +'-wrapper iframe'), | 171 targets: $('#'+ data.field +'-wrapper iframe'), |
| 110 idSelector: function(element) { | |
| 111 if ($(element).is('img')) { | |
| 112 return $.url.setUrl(element.src).param('dnd_id'); | |
| 113 } | |
| 114 return false; | |
| 115 }, | |
| 116 interval: 100, | 172 interval: 100, |
| 117 processIframeDrop: function(target, dragged, dropped, representation_id) { | 173 processIframeDrop: function(target, dragged, dropped, representation_id) { |
| 118 var representation = Drupal.settings.dndEditorRepresentations[representation_id]; | 174 var representation = Drupal.settings.dndEditorRepresentations[representation_id]; |
| 119 var $target = $(target), $dropped = $(dropped), $dragged = $(dragged), block; | 175 var $target = $(target), $dropped = $(dropped), $dragged = $(dragged), block; |
| 120 | 176 |
| 133 // Create an element to insert | 189 // Create an element to insert |
| 134 var insert = dom.create('p', {'class' : 'dnd-dropped-wrapper', 'id' : 'dnd-inserted'}, representation); | 190 var insert = dom.create('p', {'class' : 'dnd-dropped-wrapper', 'id' : 'dnd-inserted'}, representation); |
| 135 | 191 |
| 136 // The no-parent case | 192 // The no-parent case |
| 137 if ($(block).is('body')) { | 193 if ($(block).is('body')) { |
| 138 | |
| 139 s.setNode(insert); | 194 s.setNode(insert); |
| 140 } | 195 } |
| 141 else { | 196 else { |
| 142 var old_id = block.id; | 197 var old_id = block.id; |
| 143 block.id = 'target-block'; | 198 block.id = 'target-block'; |
| 146 // @TODO is finding the parent broken in safari?? | 201 // @TODO is finding the parent broken in safari?? |
| 147 $block.after('<p class="dnd-dropped-wrapper" id="dnd-inserted">' + representation + '</p>'); | 202 $block.after('<p class="dnd-dropped-wrapper" id="dnd-inserted">' + representation + '</p>'); |
| 148 | 203 |
| 149 // The active target block should be empty | 204 // The active target block should be empty |
| 150 if ($('#target-block:empty', $target.contents()).length > 0) { | 205 if ($('#target-block:empty', $target.contents()).length > 0) { |
| 151 var c = dom.get('target-block'); | 206 $('#target-block', $target.contents()).remove(); |
| 152 s.select(dom.get('target-block')); | |
| 153 ed.execCommand('Delete', false, null); | |
| 154 dom.remove(c); | |
| 155 } else if (old_id) { | 207 } else if (old_id) { |
| 156 block.id = old_id; | 208 block.id = old_id; |
| 157 } else { | 209 } else { |
| 158 $block.removeAttr('id'); | 210 $block.removeAttr('id'); |
| 159 } | 211 } |
