danielebarchiesi@0
|
1 /**
|
danielebarchiesi@0
|
2 * @file
|
danielebarchiesi@0
|
3 * JavaScript to activate "Insert" buttons on file and image fields.
|
danielebarchiesi@0
|
4 */
|
danielebarchiesi@0
|
5
|
danielebarchiesi@0
|
6 (function ($) {
|
danielebarchiesi@0
|
7
|
danielebarchiesi@0
|
8 /**
|
danielebarchiesi@0
|
9 * Behavior to add "Insert" buttons.
|
danielebarchiesi@0
|
10 */
|
danielebarchiesi@0
|
11 Drupal.behaviors.insert = {};
|
danielebarchiesi@0
|
12 Drupal.behaviors.insert.attach = function(context) {
|
danielebarchiesi@0
|
13 if (typeof(insertTextarea) == 'undefined') {
|
danielebarchiesi@0
|
14 insertTextarea = $('#edit-body textarea.text-full').get(0) || false;
|
danielebarchiesi@0
|
15 }
|
danielebarchiesi@0
|
16
|
danielebarchiesi@0
|
17 // Keep track of the last active textarea (if not using WYSIWYG).
|
danielebarchiesi@0
|
18 $('textarea:not([name$="[data][title]"]):not(.insert-processed)', context).addClass('insert-processed').focus(insertSetActive).blur(insertRemoveActive);
|
danielebarchiesi@0
|
19
|
danielebarchiesi@0
|
20 // Add the click handler to the insert button.
|
danielebarchiesi@0
|
21 $('.insert-button:not(.insert-processed)', context).addClass('insert-processed').click(insert);
|
danielebarchiesi@0
|
22
|
danielebarchiesi@0
|
23 function insertSetActive() {
|
danielebarchiesi@0
|
24 insertTextarea = this;
|
danielebarchiesi@0
|
25 this.insertHasFocus = true;
|
danielebarchiesi@0
|
26 }
|
danielebarchiesi@0
|
27
|
danielebarchiesi@0
|
28 function insertRemoveActive() {
|
danielebarchiesi@0
|
29 if (insertTextarea == this) {
|
danielebarchiesi@0
|
30 var thisTextarea = this;
|
danielebarchiesi@0
|
31 setTimeout(function() {
|
danielebarchiesi@0
|
32 thisTextarea.insertHasFocus = false;
|
danielebarchiesi@0
|
33 }, 1000);
|
danielebarchiesi@0
|
34 }
|
danielebarchiesi@0
|
35 }
|
danielebarchiesi@0
|
36
|
danielebarchiesi@0
|
37 function insert() {
|
danielebarchiesi@0
|
38 var widgetType = $(this).attr('rel');
|
danielebarchiesi@0
|
39 var settings = Drupal.settings.insert.widgets[widgetType];
|
danielebarchiesi@0
|
40 var wrapper = $(this).parents(settings.wrapper).filter(':first').get(0);
|
danielebarchiesi@0
|
41 var style = $('.insert-style', wrapper).val();
|
danielebarchiesi@0
|
42 var content = $('input.insert-template[name$="[' + style + ']"]', wrapper).val();
|
danielebarchiesi@0
|
43 var filename = $('input.insert-filename', wrapper).val();
|
danielebarchiesi@0
|
44 var options = {
|
danielebarchiesi@0
|
45 widgetType: widgetType,
|
danielebarchiesi@0
|
46 filename: filename,
|
danielebarchiesi@0
|
47 style: style,
|
danielebarchiesi@0
|
48 fields: {}
|
danielebarchiesi@0
|
49 };
|
danielebarchiesi@0
|
50
|
danielebarchiesi@0
|
51 // Update replacements.
|
danielebarchiesi@0
|
52 for (var fieldName in settings.fields) {
|
danielebarchiesi@0
|
53 var fieldValue = $(settings.fields[fieldName], wrapper).val();
|
danielebarchiesi@0
|
54 if (fieldValue) {
|
danielebarchiesi@0
|
55 fieldValue = fieldValue
|
danielebarchiesi@0
|
56 .replace(/&/g, '&')
|
danielebarchiesi@0
|
57 .replace(/"/g, '"')
|
danielebarchiesi@0
|
58 .replace(/'/g, ''')
|
danielebarchiesi@0
|
59 .replace(/</g, '<')
|
danielebarchiesi@0
|
60 .replace(/>/g, '>');
|
danielebarchiesi@0
|
61 }
|
danielebarchiesi@0
|
62 options['fields'][fieldName] = fieldValue;
|
danielebarchiesi@0
|
63 if (fieldValue) {
|
danielebarchiesi@0
|
64 var fieldRegExp = new RegExp('__' + fieldName + '(_or_filename)?__', 'g');
|
danielebarchiesi@0
|
65 content = content.replace(fieldRegExp, fieldValue);
|
danielebarchiesi@0
|
66 }
|
danielebarchiesi@0
|
67 else {
|
danielebarchiesi@0
|
68 var fieldRegExp = new RegExp('__' + fieldName + '_or_filename__', 'g');
|
danielebarchiesi@0
|
69 content = content.replace(fieldRegExp, filename);
|
danielebarchiesi@0
|
70 }
|
danielebarchiesi@0
|
71 }
|
danielebarchiesi@0
|
72
|
danielebarchiesi@0
|
73 // File name replacement.
|
danielebarchiesi@0
|
74 var fieldRegExp = new RegExp('__filename__', 'g');
|
danielebarchiesi@0
|
75 content = content.replace(fieldRegExp, filename);
|
danielebarchiesi@0
|
76
|
danielebarchiesi@0
|
77 // Check for a maximum dimension and scale down the width if necessary.
|
danielebarchiesi@0
|
78 // This is intended for use with Image Resize Filter.
|
danielebarchiesi@0
|
79 var widthMatches = content.match(/width[ ]*=[ ]*"(\d*)"/i);
|
danielebarchiesi@0
|
80 var heightMatches = content.match(/height[ ]*=[ ]*"(\d*)"/i);
|
danielebarchiesi@0
|
81 if (settings.maxWidth && widthMatches && parseInt(widthMatches[1]) > settings.maxWidth) {
|
danielebarchiesi@0
|
82 var insertRatio = settings.maxWidth / widthMatches[1];
|
danielebarchiesi@0
|
83 var width = settings.maxWidth;
|
danielebarchiesi@0
|
84 content = content.replace(/width[ ]*=[ ]*"?(\d*)"?/i, 'width="' + width + '"');
|
danielebarchiesi@0
|
85
|
danielebarchiesi@0
|
86 if (heightMatches) {
|
danielebarchiesi@0
|
87 var height = Math.round(heightMatches[1] * insertRatio);
|
danielebarchiesi@0
|
88 content = content.replace(/height[ ]*=[ ]*"?(\d*)"?/i, 'height="' + height + '"');
|
danielebarchiesi@0
|
89 }
|
danielebarchiesi@0
|
90 }
|
danielebarchiesi@0
|
91
|
danielebarchiesi@0
|
92 // Allow other modules to perform replacements.
|
danielebarchiesi@0
|
93 options['content'] = content;
|
danielebarchiesi@0
|
94 $.event.trigger('insertIntoActiveEditor', [options]);
|
danielebarchiesi@0
|
95 content = options['content'];
|
danielebarchiesi@0
|
96
|
danielebarchiesi@0
|
97 // Cleanup unused replacements.
|
danielebarchiesi@0
|
98 content = content.replace(/"__([a-z0-9_]+)__"/g, '""');
|
danielebarchiesi@0
|
99
|
danielebarchiesi@0
|
100 // Cleanup empty attributes (other than alt).
|
danielebarchiesi@0
|
101 content = content.replace(/([a-z]+)[ ]*=[ ]*""/g, function(match, tagName) {
|
danielebarchiesi@0
|
102 return (tagName === 'alt') ? match : '';
|
danielebarchiesi@0
|
103 });
|
danielebarchiesi@0
|
104
|
danielebarchiesi@0
|
105 // Insert the text.
|
danielebarchiesi@0
|
106 Drupal.insert.insertIntoActiveEditor(content);
|
danielebarchiesi@0
|
107 }
|
danielebarchiesi@0
|
108 };
|
danielebarchiesi@0
|
109
|
danielebarchiesi@0
|
110 // General Insert API functions.
|
danielebarchiesi@0
|
111 Drupal.insert = {
|
danielebarchiesi@0
|
112 /**
|
danielebarchiesi@0
|
113 * Insert content into the current (or last active) editor on the page. This
|
danielebarchiesi@0
|
114 * should work with most WYSIWYGs as well as plain textareas.
|
danielebarchiesi@0
|
115 *
|
danielebarchiesi@0
|
116 * @param content
|
danielebarchiesi@0
|
117 */
|
danielebarchiesi@0
|
118 insertIntoActiveEditor: function(content) {
|
danielebarchiesi@0
|
119 var editorElement;
|
danielebarchiesi@0
|
120
|
danielebarchiesi@0
|
121 // Always work in normal text areas that currently have focus.
|
danielebarchiesi@0
|
122 if (insertTextarea && insertTextarea.insertHasFocus) {
|
danielebarchiesi@0
|
123 editorElement = insertTextarea;
|
danielebarchiesi@0
|
124 Drupal.insert.insertAtCursor(insertTextarea, content);
|
danielebarchiesi@0
|
125 }
|
danielebarchiesi@0
|
126 // Direct tinyMCE support.
|
danielebarchiesi@0
|
127 else if (typeof(tinyMCE) != 'undefined' && tinyMCE.activeEditor) {
|
danielebarchiesi@0
|
128 editorElement = document.getElementById(tinyMCE.activeEditor.editorId);
|
danielebarchiesi@0
|
129 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
130 tinyMCE.activeEditor.execCommand('mceInsertContent', false, content);
|
danielebarchiesi@0
|
131 }
|
danielebarchiesi@0
|
132 // WYSIWYG support, should work in all editors if available.
|
danielebarchiesi@0
|
133 else if (Drupal.wysiwyg && Drupal.wysiwyg.activeId) {
|
danielebarchiesi@0
|
134 editorElement = document.getElementById(Drupal.wysiwyg.activeId);
|
danielebarchiesi@0
|
135 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
136 Drupal.wysiwyg.instances[Drupal.wysiwyg.activeId].insert(content)
|
danielebarchiesi@0
|
137 }
|
danielebarchiesi@0
|
138 // FCKeditor module support.
|
danielebarchiesi@0
|
139 else if (typeof(FCKeditorAPI) != 'undefined' && typeof(fckActiveId) != 'undefined') {
|
danielebarchiesi@0
|
140 editorElement = document.getElementById(fckActiveId);
|
danielebarchiesi@0
|
141 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
142 FCKeditorAPI.Instances[fckActiveId].InsertHtml(content);
|
danielebarchiesi@0
|
143 }
|
danielebarchiesi@0
|
144 // Direct FCKeditor support (only body field supported).
|
danielebarchiesi@0
|
145 else if (typeof(FCKeditorAPI) != 'undefined') {
|
danielebarchiesi@0
|
146 // Try inserting into the body.
|
danielebarchiesi@0
|
147 if (FCKeditorAPI.Instances[insertTextarea.id]) {
|
danielebarchiesi@0
|
148 editorElement = insertTextarea;
|
danielebarchiesi@0
|
149 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
150 FCKeditorAPI.Instances[insertTextarea.id].InsertHtml(content);
|
danielebarchiesi@0
|
151 }
|
danielebarchiesi@0
|
152 // Try inserting into the first instance we find (may occur with very
|
danielebarchiesi@0
|
153 // old versions of FCKeditor).
|
danielebarchiesi@0
|
154 else {
|
danielebarchiesi@0
|
155 for (var n in FCKeditorAPI.Instances) {
|
danielebarchiesi@0
|
156 editorElement = document.getElementById(n);
|
danielebarchiesi@0
|
157 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
158 FCKeditorAPI.Instances[n].InsertHtml(content);
|
danielebarchiesi@0
|
159 break;
|
danielebarchiesi@0
|
160 }
|
danielebarchiesi@0
|
161 }
|
danielebarchiesi@0
|
162 }
|
danielebarchiesi@0
|
163 // CKeditor module support.
|
danielebarchiesi@0
|
164 else if (typeof(CKEDITOR) != 'undefined' && typeof(Drupal.ckeditorActiveId) != 'undefined') {
|
danielebarchiesi@0
|
165 editorElement = document.getElementById(Drupal.ckeditorActiveId);
|
danielebarchiesi@0
|
166 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
167 CKEDITOR.instances[Drupal.ckeditorActiveId].insertHtml(content);
|
danielebarchiesi@0
|
168 }
|
danielebarchiesi@0
|
169 // Direct CKeditor support (only body field supported).
|
danielebarchiesi@0
|
170 else if (typeof(CKEDITOR) != 'undefined' && CKEDITOR.instances[insertTextarea.id]) {
|
danielebarchiesi@0
|
171 editorElement = insertTextarea;
|
danielebarchiesi@0
|
172 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
173 CKEDITOR.instances[insertTextarea.id].insertHtml(content);
|
danielebarchiesi@0
|
174 }
|
danielebarchiesi@0
|
175 else if (insertTextarea) {
|
danielebarchiesi@0
|
176 editorElement = insertTextarea;
|
danielebarchiesi@0
|
177 Drupal.insert.activateTabPane(editorElement);
|
danielebarchiesi@0
|
178 Drupal.insert.insertAtCursor(insertTextarea, content);
|
danielebarchiesi@0
|
179 }
|
danielebarchiesi@0
|
180
|
danielebarchiesi@0
|
181 if (editorElement) {
|
danielebarchiesi@0
|
182 Drupal.insert.contentWarning(editorElement, content);
|
danielebarchiesi@0
|
183 }
|
danielebarchiesi@0
|
184
|
danielebarchiesi@0
|
185 return false;
|
danielebarchiesi@0
|
186 },
|
danielebarchiesi@0
|
187
|
danielebarchiesi@0
|
188 /**
|
danielebarchiesi@0
|
189 * Check for vertical tabs and activate the pane containing the editor.
|
danielebarchiesi@0
|
190 *
|
danielebarchiesi@0
|
191 * @param editor
|
danielebarchiesi@0
|
192 * The DOM object of the editor that will be checked.
|
danielebarchiesi@0
|
193 */
|
danielebarchiesi@0
|
194 activateTabPane: function(editor) {
|
danielebarchiesi@0
|
195 var $pane = $(editor).parents('.vertical-tabs-pane:first');
|
danielebarchiesi@0
|
196 var $panes = $pane.parent('.vertical-tabs-panes');
|
danielebarchiesi@0
|
197 var $tabs = $panes.parents('.vertical-tabs:first').find('ul.vertical-tabs-list:first li a');
|
danielebarchiesi@0
|
198 if ($pane.size() && $pane.is(':hidden') && $panes.size() && $tabs.size()) {
|
danielebarchiesi@0
|
199 var index = $panes.children().index($pane);
|
danielebarchiesi@0
|
200 $tabs.eq(index).click();
|
danielebarchiesi@0
|
201 }
|
danielebarchiesi@0
|
202 },
|
danielebarchiesi@0
|
203
|
danielebarchiesi@0
|
204 /**
|
danielebarchiesi@0
|
205 * Warn users when attempting to insert an image into an unsupported field.
|
danielebarchiesi@0
|
206 *
|
danielebarchiesi@0
|
207 * This function is only a 90% use-case, as it doesn't support when the filter
|
danielebarchiesi@0
|
208 * tip are hidden, themed, or when only one format is available. However it
|
danielebarchiesi@0
|
209 * should fail silently in these situations.
|
danielebarchiesi@0
|
210 */
|
danielebarchiesi@0
|
211 contentWarning: function(editorElement, content) {
|
danielebarchiesi@0
|
212 if (!content.match(/<img /)) return;
|
danielebarchiesi@0
|
213
|
danielebarchiesi@0
|
214 var $wrapper = $(editorElement).parents('div.text-format-wrapper:first');
|
danielebarchiesi@0
|
215 if (!$wrapper.length) return;
|
danielebarchiesi@0
|
216
|
danielebarchiesi@0
|
217 $wrapper.find('.filter-guidelines-item:visible li').each(function(index, element) {
|
danielebarchiesi@0
|
218 var expression = new RegExp(Drupal.t('Allowed HTML tags'));
|
danielebarchiesi@0
|
219 if (expression.exec(element.textContent) && !element.textContent.match(/<img>/)) {
|
danielebarchiesi@0
|
220 alert(Drupal.t("The selected text format will not allow it to display images. The text format will need to be changed for this image to display properly when saved."));
|
danielebarchiesi@0
|
221 }
|
danielebarchiesi@0
|
222 });
|
danielebarchiesi@0
|
223 },
|
danielebarchiesi@0
|
224
|
danielebarchiesi@0
|
225 /**
|
danielebarchiesi@0
|
226 * Insert content into a textarea at the current cursor position.
|
danielebarchiesi@0
|
227 *
|
danielebarchiesi@0
|
228 * @param editor
|
danielebarchiesi@0
|
229 * The DOM object of the textarea that will receive the text.
|
danielebarchiesi@0
|
230 * @param content
|
danielebarchiesi@0
|
231 * The string to be inserted.
|
danielebarchiesi@0
|
232 */
|
danielebarchiesi@0
|
233 insertAtCursor: function(editor, content) {
|
danielebarchiesi@0
|
234 // Record the current scroll position.
|
danielebarchiesi@0
|
235 var scroll = editor.scrollTop;
|
danielebarchiesi@0
|
236
|
danielebarchiesi@0
|
237 // IE support.
|
danielebarchiesi@0
|
238 if (document.selection) {
|
danielebarchiesi@0
|
239 editor.focus();
|
danielebarchiesi@0
|
240 sel = document.selection.createRange();
|
danielebarchiesi@0
|
241 sel.text = content;
|
danielebarchiesi@0
|
242 }
|
danielebarchiesi@0
|
243
|
danielebarchiesi@0
|
244 // Mozilla/Firefox/Netscape 7+ support.
|
danielebarchiesi@0
|
245 else if (editor.selectionStart || editor.selectionStart == '0') {
|
danielebarchiesi@0
|
246 var startPos = editor.selectionStart;
|
danielebarchiesi@0
|
247 var endPos = editor.selectionEnd;
|
danielebarchiesi@0
|
248 editor.value = editor.value.substring(0, startPos) + content + editor.value.substring(endPos, editor.value.length);
|
danielebarchiesi@0
|
249 }
|
danielebarchiesi@0
|
250
|
danielebarchiesi@0
|
251 // Fallback, just add to the end of the content.
|
danielebarchiesi@0
|
252 else {
|
danielebarchiesi@0
|
253 editor.value += content;
|
danielebarchiesi@0
|
254 }
|
danielebarchiesi@0
|
255
|
danielebarchiesi@0
|
256 // Ensure the textarea does not unexpectedly scroll.
|
danielebarchiesi@0
|
257 editor.scrollTop = scroll;
|
danielebarchiesi@0
|
258 }
|
danielebarchiesi@0
|
259 };
|
danielebarchiesi@0
|
260
|
danielebarchiesi@0
|
261 })(jQuery);
|