root / drupal7 / sites / all / modules / media_ckeditor / js / plugins / media / library.js @ 59ae487e
1 |
|
---|---|
2 |
/**
|
3 |
* @file
|
4 |
* Attach Media ckeditor behaviors.
|
5 |
*/
|
6 |
|
7 |
(function ($) { |
8 |
Drupal.media = Drupal.media || {}; |
9 |
|
10 |
/**
|
11 |
* Attaches 'insert' button to media widget.
|
12 |
*/
|
13 |
Drupal.behaviors.mediaWidgetInsert = { |
14 |
attach: function (context, settings) { |
15 |
if (Drupal.ckeditorInstance && Drupal.settings.media_ckeditor && Drupal.settings.media_ckeditor.wysiwyg_insert) {
|
16 |
// Only add buttons on fields that have been configured so, by
|
17 |
// consulting the Drupal.settings.media_ckeditor.wysiwyg_insert var.
|
18 |
for (var fieldName in Drupal.settings.media_ckeditor.wysiwyg_insert) { |
19 |
var fieldId = '#edit-' + fieldName.replace(/_/g, '-'); |
20 |
// Within the field markup, look for the table of files.
|
21 |
$(fieldId, context).find('.media-widget').once('mediaInsertButton', function() { |
22 |
// For each file, check to see if there is a file ID.
|
23 |
if ($(this).find('input.fid').val() != 0) { |
24 |
// Now we add the button next to "Remove".
|
25 |
var insertButton = $('<a class="media-insert button">' + Drupal.t('Insert') + '</a>') |
26 |
.click(function(e) {
|
27 |
e.preventDefault(); |
28 |
var fid = $(this).parent().parent().find('.fid').val(); |
29 |
var mediaFile = {fid: fid} |
30 |
Drupal.ckeditorInstance.mediaInsert = {mediaFiles: [mediaFile]};
|
31 |
Drupal.ckeditorInstance.execCommand('media');
|
32 |
}); |
33 |
// Insert the button, differently for single vs. multi value.
|
34 |
var multiValue = $(fieldId + ' table', context).length; |
35 |
if (multiValue) {
|
36 |
insertButton.insertBefore($(this).parent().parent().find('input.remove')); |
37 |
} |
38 |
else {
|
39 |
insertButton.insertBefore($(this).find('input.remove')); |
40 |
} |
41 |
} |
42 |
}); |
43 |
} |
44 |
} |
45 |
} |
46 |
}; |
47 |
|
48 |
Drupal.settings.ckeditor.plugins['media'] = {
|
49 |
/**
|
50 |
* Execute the button.
|
51 |
*/
|
52 |
invoke: function (data, settings, instanceId) { |
53 |
if (data.format == 'html') { |
54 |
// CKEDITOR module support doesn't set this setting
|
55 |
if (typeof settings['global'] === 'undefined') { |
56 |
settings['global'] = {id: 'media_wysiwyg'}; |
57 |
} |
58 |
// If the selection is (or contains) an element with the attribute of
|
59 |
// "data-media-element", assume the user wants to edit that thing.
|
60 |
var $alreadyInsertedMedia; |
61 |
if (jQuery(data.node).is('[data-media-element]')) { |
62 |
$alreadyInsertedMedia = jQuery(data.node);
|
63 |
} |
64 |
else {
|
65 |
$alreadyInsertedMedia = jQuery(data.node).find('[data-media-element]'); |
66 |
} |
67 |
// First check to see if we are using an Insert button.
|
68 |
if (typeof Drupal.ckeditorInstance.mediaInsert !== 'undefined') { |
69 |
var mediaFile = Drupal.ckeditorInstance.mediaInsert.mediaFiles[0]; |
70 |
delete Drupal.ckeditorInstance.mediaInsert;
|
71 |
Drupal.media.popups.mediaStyleSelector(mediaFile, function (mediaFiles) {
|
72 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, mediaFiles, CKEDITOR.instances[instanceId]);
|
73 |
}, settings['global']);
|
74 |
} |
75 |
// Next check to see if we are editing already-inserted media.
|
76 |
else if ($alreadyInsertedMedia.length) { |
77 |
var mediaFile = Drupal.media.filter.extract_file_info($alreadyInsertedMedia); |
78 |
Drupal.media.popups.mediaStyleSelector(mediaFile, function (mediaFiles) {
|
79 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, mediaFiles, CKEDITOR.instances[instanceId]);
|
80 |
}, settings['global']);
|
81 |
} |
82 |
// Otherwise we are embedding new media.
|
83 |
else {
|
84 |
Drupal.media.popups.mediaBrowser(function (mediaFiles) {
|
85 |
Drupal.settings.ckeditor.plugins['media'].mediaBrowserOnSelect(mediaFiles, instanceId);
|
86 |
}, settings['global']);
|
87 |
} |
88 |
} |
89 |
}, |
90 |
|
91 |
/**
|
92 |
* Respond to the mediaBrowser's onSelect event.
|
93 |
*/
|
94 |
mediaBrowserOnSelect: function (mediaFiles, instanceId) { |
95 |
var mediaFile = mediaFiles[0]; |
96 |
var options = {};
|
97 |
Drupal.media.popups.mediaStyleSelector(mediaFile, function (formattedMedia) {
|
98 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, formattedMedia, CKEDITOR.instances[instanceId]);
|
99 |
}, options); |
100 |
|
101 |
return;
|
102 |
}, |
103 |
|
104 |
insertMediaFile: function (mediaFile, formattedMedia, ckeditorInstance, fullyRenderedFile) { |
105 |
|
106 |
// See if we should use ajax to get the fully rendered file.
|
107 |
if (typeof fullyRenderedFile === 'undefined' && |
108 |
Drupal.settings.media_ckeditor.fully_rendered_files) { |
109 |
|
110 |
$.ajax({
|
111 |
url: Drupal.settings.basePath + 'media/rendered-in-wysiwyg', |
112 |
type: 'GET', |
113 |
data: {
|
114 |
fid: mediaFile.fid,
|
115 |
view_mode: formattedMedia.type,
|
116 |
fields: formattedMedia.options
|
117 |
}, |
118 |
success: function(html) { |
119 |
// To work around an IE issue, preload any image. The issue is
|
120 |
// that IE requests the image 2 times, and one request gets a 503,
|
121 |
// causing a broken image icon in the WYSIWYG instead of the actual
|
122 |
// image.
|
123 |
var $images = $(html).find('img'); |
124 |
if (!$images.length || $(html).find('picture').length) { |
125 |
// If there are no images, just insert the html immediately, by
|
126 |
// re-calling this function with the ajax-retrieved HTML.
|
127 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, formattedMedia, ckeditorInstance, html);
|
128 |
} |
129 |
else {
|
130 |
// Otherwise do the same, but only after the first image preloads.
|
131 |
// Possible future improvement might be to handle multiple images
|
132 |
// instead of just the first, but even better would be to remove
|
133 |
// this workaround entirely, when/if IE's behavior changes.
|
134 |
var image = new Image(); |
135 |
image.onload = function() { |
136 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, formattedMedia, ckeditorInstance, html);
|
137 |
} |
138 |
image.src = $images.first().attr('src'); |
139 |
} |
140 |
}, |
141 |
error: function(data) { |
142 |
// Fallback to whatever the HTML was already going to be.
|
143 |
Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, formattedMedia, ckeditorInstance, formattedMedia.html);
|
144 |
} |
145 |
}); |
146 |
|
147 |
// Stop for now, because the callback above re-calls this same function.
|
148 |
return;
|
149 |
} |
150 |
|
151 |
// See if we already used ajax to get the fully rendered file.
|
152 |
if (typeof fullyRenderedFile !== 'undefined') { |
153 |
formattedMedia.html = fullyRenderedFile; |
154 |
} |
155 |
|
156 |
// Customization of Drupal.media.filter.registerNewElement().
|
157 |
var element = Drupal.media.filter.create_element(formattedMedia.html, {
|
158 |
fid: mediaFile.fid,
|
159 |
view_mode: formattedMedia.type,
|
160 |
attributes: mediaFile.attributes,
|
161 |
fields: formattedMedia.options
|
162 |
}); |
163 |
|
164 |
var hasWidgetSupport = typeof(CKEDITOR.plugins.registered.widget) != 'undefined'; |
165 |
|
166 |
// Use own wrapper element to be able to properly deal with selections.
|
167 |
// Check prepareDataForWysiwygMode() in plugin.js for details.
|
168 |
var wysiwygHTML = Drupal.media.filter.getWysiwygHTML(element);
|
169 |
|
170 |
if (wysiwygHTML.indexOf("<!--MEDIA-WRAPPER-START-") !== -1) { |
171 |
ckeditorInstance.plugins.media.mediaLegacyWrappers = true;
|
172 |
wysiwygHTML = wysiwygHTML.replace(/<!--MEDIA-WRAPPER-START-(\d+)-->(.*?)<!--MEDIA-WRAPPER-END-\d+-->/gi, ''); |
173 |
} |
174 |
|
175 |
// Insert element. Use CKEDITOR.dom.element.createFromHtml to ensure our
|
176 |
// custom wrapper element is preserved.
|
177 |
var editorElement = CKEDITOR.dom.element.createFromHtml(wysiwygHTML);
|
178 |
ckeditorInstance.insertElement(editorElement); |
179 |
|
180 |
// Initialize widget on our html if possible.
|
181 |
if (parseFloat(CKEDITOR.version) >= 4.3 && hasWidgetSupport) { |
182 |
ckeditorInstance.widgets.initOn( editorElement, 'mediabox' );
|
183 |
|
184 |
// Also support the image2 plugin.
|
185 |
ckeditorInstance.widgets.initOn( editorElement, 'image' );
|
186 |
} |
187 |
}, |
188 |
|
189 |
/**
|
190 |
* Forces custom attributes into the class field of the specified image.
|
191 |
*
|
192 |
* Due to a bug in some versions of Firefox
|
193 |
* (http://forums.mozillazine.org/viewtopic.php?f=9&t=1991855), the
|
194 |
* custom attributes used to share information about the image are
|
195 |
* being stripped as the image markup is set into the rich text
|
196 |
* editor. Here we encode these attributes into the class field so
|
197 |
* the data survives.
|
198 |
*
|
199 |
* @param imgElement
|
200 |
* The image
|
201 |
* @fid
|
202 |
* The file id.
|
203 |
* @param view_mode
|
204 |
* The view mode.
|
205 |
* @param additional
|
206 |
* Additional attributes to add to the image.
|
207 |
*/
|
208 |
forceAttributesIntoClass: function (imgElement, fid, view_mode, additional) { |
209 |
var wysiwyg = imgElement.attr('wysiwyg'); |
210 |
if (wysiwyg) {
|
211 |
imgElement.addClass('attr__wysiwyg__' + wysiwyg);
|
212 |
} |
213 |
var format = imgElement.attr('format'); |
214 |
if (format) {
|
215 |
imgElement.addClass('attr__format__' + format);
|
216 |
} |
217 |
var typeOf = imgElement.attr('typeof'); |
218 |
if (typeOf) {
|
219 |
imgElement.addClass('attr__typeof__' + typeOf);
|
220 |
} |
221 |
if (fid) {
|
222 |
imgElement.addClass('img__fid__' + fid);
|
223 |
} |
224 |
if (view_mode) {
|
225 |
imgElement.addClass('img__view_mode__' + view_mode);
|
226 |
} |
227 |
if (additional) {
|
228 |
for (var name in additional) { |
229 |
if (additional.hasOwnProperty(name)) {
|
230 |
switch (name) {
|
231 |
case 'field_file_image_alt_text[und][0][value]': |
232 |
imgElement.attr('alt', additional[name]);
|
233 |
break;
|
234 |
case 'field_file_image_title_text[und][0][value]': |
235 |
imgElement.attr('title', additional[name]);
|
236 |
break;
|
237 |
default:
|
238 |
imgElement.addClass('attr__' + name + '__' + additional[name]); |
239 |
break;
|
240 |
} |
241 |
} |
242 |
} |
243 |
} |
244 |
}, |
245 |
|
246 |
/**
|
247 |
* Retrieves encoded attributes from the specified class string.
|
248 |
*
|
249 |
* @param classString
|
250 |
* A string containing the value of the class attribute.
|
251 |
* @return
|
252 |
* An array containing the attribute names as keys, and an object
|
253 |
* with the name, value, and attribute type (either 'attr' or
|
254 |
* 'img', depending on whether it is an image attribute or should
|
255 |
* be it the attributes section)
|
256 |
*/
|
257 |
getAttributesFromClass: function (classString) { |
258 |
var actualClasses = [];
|
259 |
var otherAttributes = [];
|
260 |
var classes = classString.split(' '); |
261 |
var regexp = new RegExp('^(attr|img)__([^\S]*)__([^\S]*)$'); |
262 |
for (var index = 0; index < classes.length; index++) { |
263 |
var matches = classes[index].match(regexp);
|
264 |
if (matches && matches.length === 4) { |
265 |
otherAttributes[matches[2]] = {
|
266 |
name: matches[2], |
267 |
value: matches[3], |
268 |
type: matches[1] |
269 |
}; |
270 |
} |
271 |
else {
|
272 |
actualClasses.push(classes[index]); |
273 |
} |
274 |
} |
275 |
if (actualClasses.length > 0) { |
276 |
otherAttributes['class'] = {
|
277 |
name: 'class', |
278 |
value: actualClasses.join(' '), |
279 |
type: 'attr' |
280 |
}; |
281 |
} |
282 |
return otherAttributes;
|
283 |
}, |
284 |
|
285 |
sortAttributes: function (a, b) { |
286 |
var nameA = a.name.toLowerCase();
|
287 |
var nameB = b.name.toLowerCase();
|
288 |
if (nameA < nameB) {
|
289 |
return -1; |
290 |
} |
291 |
if (nameA > nameB) {
|
292 |
return 1; |
293 |
} |
294 |
return 0; |
295 |
} |
296 |
}; |
297 |
|
298 |
// If media_ckeditor is configured to render items in the wysiwyg as full
|
299 |
// rendered file entities, we need to completely hijack a function from
|
300 |
// media_wysiwyg.filter.js.
|
301 |
if (Drupal.settings.media_ckeditor.fully_rendered_files) {
|
302 |
|
303 |
// Replaces function of the same name, from media_wysiwyg.filter.js.
|
304 |
Drupal.media.filter.replacePlaceholderWithToken = function(content) { |
305 |
|
306 |
var $placeholder = $(content); |
307 |
if ($placeholder.hasClass('media-element')) { |
308 |
var macro = Drupal.media.filter.create_macro($placeholder); |
309 |
Drupal.media.filter.ensure_tagmap(); |
310 |
Drupal.settings.tagmap[macro] = content; |
311 |
return macro;
|
312 |
} |
313 |
return content;
|
314 |
} |
315 |
} |
316 |
})(jQuery); |