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 } |