root / drupal7 / sites / all / modules / media / modules / media_wysiwyg / js / media_wysiwyg.filter.js @ ca0757b9
1 |
/**
|
---|---|
2 |
* @file
|
3 |
* File with utilities to handle media in html editing.
|
4 |
*/
|
5 |
(function ($) { |
6 |
|
7 |
Drupal.media = Drupal.media || {}; |
8 |
/**
|
9 |
* Utility to deal with media tokens / placeholders.
|
10 |
*/
|
11 |
Drupal.media.filter = { |
12 |
/**
|
13 |
* Replaces media tokens with the placeholders for html editing.
|
14 |
* @param content
|
15 |
*/
|
16 |
replaceTokenWithPlaceholder: function(content) { |
17 |
Drupal.media.filter.ensure_tagmap(); |
18 |
var matches = content.match(/\[\[.*?\]\]/g); |
19 |
|
20 |
if (matches) {
|
21 |
for (var i = 0; i < matches.length; i++) { |
22 |
var match = matches[i];
|
23 |
if (match.indexOf('"type":"media"') == -1) { |
24 |
continue;
|
25 |
} |
26 |
|
27 |
// Check if the macro exists in the tagmap. This ensures backwards
|
28 |
// compatibility with existing media and is moderately more efficient
|
29 |
// than re-building the element.
|
30 |
var media = Drupal.settings.tagmap[match];
|
31 |
var media_json = match.replace('[[', '').replace(']]', ''); |
32 |
|
33 |
// Ensure that the media JSON is valid.
|
34 |
try {
|
35 |
var media_definition = JSON.parse(media_json);
|
36 |
} |
37 |
catch (err) {
|
38 |
// @todo: error logging.
|
39 |
// Content should be returned to prevent an empty editor.
|
40 |
return content;
|
41 |
} |
42 |
|
43 |
// Re-build the media if the macro has changed from the tagmap.
|
44 |
if (!media && media_definition.fid) {
|
45 |
Drupal.media.filter.ensureSourceMap(); |
46 |
var source = Drupal.settings.mediaSourceMap[media_definition.fid];
|
47 |
media = document.createElement(source.tagName); |
48 |
media.src = source.src; |
49 |
} |
50 |
|
51 |
// Apply attributes.
|
52 |
var element = Drupal.media.filter.create_element(media, media_definition);
|
53 |
var markup = Drupal.media.filter.outerHTML(element);
|
54 |
|
55 |
// Use split and join to replace all instances of macro with markup.
|
56 |
content = content.split(match).join(markup); |
57 |
} |
58 |
} |
59 |
|
60 |
return content;
|
61 |
}, |
62 |
|
63 |
/**
|
64 |
* Replaces media elements with tokens.
|
65 |
*
|
66 |
* @param content (string)
|
67 |
* The markup within the wysiwyg instance.
|
68 |
*/
|
69 |
replacePlaceholderWithToken: function(content) { |
70 |
Drupal.media.filter.ensure_tagmap(); |
71 |
|
72 |
// Rewrite the tagmap in case any of the macros have changed.
|
73 |
Drupal.settings.tagmap = {}; |
74 |
|
75 |
// Wrap the content to be able to use replaceWith() and html().
|
76 |
content = $('<div>').append(content); |
77 |
var media = $('.media-element', content); |
78 |
|
79 |
if (media.length) {
|
80 |
// Replace all media elements with their respective macros.
|
81 |
media.replaceWith(function() {
|
82 |
var el = $(this), |
83 |
macro = Drupal.media.filter.create_macro(el); |
84 |
|
85 |
// Store the markup for more efficient rendering later.
|
86 |
// @see replaceTokenWidthPlaceholder()
|
87 |
Drupal.settings.tagmap[macro] = Drupal.media.filter.outerHTML(el); |
88 |
|
89 |
return macro;
|
90 |
}); |
91 |
} |
92 |
|
93 |
return content.html();
|
94 |
}, |
95 |
|
96 |
/**
|
97 |
* Serializes file information as a url-encoded JSON object and stores it
|
98 |
* as a data attribute on the html element.
|
99 |
*
|
100 |
* @param html (string)
|
101 |
* A html element to be used to represent the inserted media element.
|
102 |
* @param info (object)
|
103 |
* A object containing the media file information (fid, view_mode, etc).
|
104 |
*/
|
105 |
create_element: function (html, info) { |
106 |
if ($('<div>').append(html).text().length === html.length) { |
107 |
// Element is not an html tag. Surround it in a span element so we can
|
108 |
// pass the file attributes.
|
109 |
html = '<span>' + html + '</span>'; |
110 |
} |
111 |
var element = $(html); |
112 |
|
113 |
// Parse out link wrappers. They will be re-applied when the image is
|
114 |
// rendered on the front-end.
|
115 |
if (element.is('a')) { |
116 |
element = element.children(); |
117 |
} |
118 |
|
119 |
// Move attributes from the file info array to the placeholder element.
|
120 |
if (info.attributes) {
|
121 |
$.each(Drupal.settings.media.wysiwyg_allowed_attributes, function(i, a) { |
122 |
if (info.attributes[a]) {
|
123 |
element.attr(a, info.attributes[a]); |
124 |
} |
125 |
}); |
126 |
delete(info.attributes);
|
127 |
|
128 |
// Store information to rebuild the element later, if necessary.
|
129 |
Drupal.media.filter.ensureSourceMap(); |
130 |
Drupal.settings.mediaSourceMap[info.fid] = { |
131 |
tagName: element[0].tagName, |
132 |
src: element[0].src |
133 |
} |
134 |
} |
135 |
|
136 |
info.type = info.type || "media";
|
137 |
|
138 |
// Store the data in the data map.
|
139 |
Drupal.media.filter.ensureDataMap(); |
140 |
Drupal.settings.mediaDataMap[info.fid] = info; |
141 |
|
142 |
// Store the fid in the DOM to retrieve the data from the info map.
|
143 |
element.attr('data-fid', info.fid);
|
144 |
|
145 |
// Add media-element class so we can find markup element later.
|
146 |
var classes = ['media-element']; |
147 |
|
148 |
if (info.view_mode) {
|
149 |
classes.push('file-' + info.view_mode.replace(/_/g, '-')); |
150 |
} |
151 |
element.addClass(classes.join(' '));
|
152 |
|
153 |
return element;
|
154 |
}, |
155 |
|
156 |
/**
|
157 |
* Create a macro representation of the inserted media element.
|
158 |
*
|
159 |
* @param element (jQuery object)
|
160 |
* A media element with attached serialized file info.
|
161 |
*/
|
162 |
create_macro: function (element) { |
163 |
var file_info = Drupal.media.filter.extract_file_info(element);
|
164 |
if (file_info) {
|
165 |
return '[[' + JSON.stringify(file_info) + ']]'; |
166 |
} |
167 |
return false; |
168 |
}, |
169 |
|
170 |
/**
|
171 |
* Extract the file info from a WYSIWYG placeholder element as JSON.
|
172 |
*
|
173 |
* @param element (jQuery object)
|
174 |
* A media element with associated file info via a file id (fid).
|
175 |
*/
|
176 |
extract_file_info: function (element) { |
177 |
var fid, file_info, value;
|
178 |
|
179 |
if (fid = element.data('fid')) { |
180 |
Drupal.media.filter.ensureDataMap(); |
181 |
|
182 |
if (file_info = Drupal.settings.mediaDataMap[fid]) {
|
183 |
file_info.attributes = {}; |
184 |
|
185 |
$.each(Drupal.settings.media.wysiwyg_allowed_attributes, function(i, a) { |
186 |
if (value = element.attr(a)) {
|
187 |
// Replace " by \" to avoid error with JSON format.
|
188 |
if (typeof value == 'string') { |
189 |
value = value.replace('"', '\\"'); |
190 |
} |
191 |
file_info.attributes[a] = value; |
192 |
} |
193 |
}); |
194 |
|
195 |
// Extract the link text, if there is any.
|
196 |
file_info.link_text = element.find('a').html();
|
197 |
} |
198 |
} |
199 |
|
200 |
return file_info;
|
201 |
}, |
202 |
|
203 |
/**
|
204 |
* Gets the HTML content of an element.
|
205 |
*
|
206 |
* @param element (jQuery object)
|
207 |
*/
|
208 |
outerHTML: function (element) { |
209 |
return element[0].outerHTML || $('<div>').append(element.eq(0).clone()).html(); |
210 |
}, |
211 |
|
212 |
/**
|
213 |
* Gets the wrapped HTML content of an element to insert into the wysiwyg.
|
214 |
*
|
215 |
* It also registers the element in the tag map so that the token
|
216 |
* replacement works.
|
217 |
*
|
218 |
* @param element (jQuery object) The element to insert.
|
219 |
*
|
220 |
* @see Drupal.media.filter.replacePlaceholderWithToken()
|
221 |
*/
|
222 |
getWysiwygHTML: function (element) { |
223 |
// Create the markup and the macro.
|
224 |
var markup = Drupal.media.filter.outerHTML(element),
|
225 |
macro = Drupal.media.filter.create_macro(element); |
226 |
|
227 |
// Store macro/markup in the tagmap.
|
228 |
Drupal.media.filter.ensure_tagmap(); |
229 |
Drupal.settings.tagmap[macro] = markup; |
230 |
|
231 |
// Return the html code to insert in an editor and use it with
|
232 |
// replacePlaceholderWithToken()
|
233 |
return markup;
|
234 |
}, |
235 |
|
236 |
/**
|
237 |
* Ensures the src tracking has been initialized and returns it.
|
238 |
*/
|
239 |
ensureSourceMap: function() { |
240 |
Drupal.settings.mediaSourceMap = Drupal.settings.mediaSourceMap || {}; |
241 |
return Drupal.settings.mediaSourceMap;
|
242 |
}, |
243 |
|
244 |
/**
|
245 |
* Ensures the data tracking has been initialized and returns it.
|
246 |
*/
|
247 |
ensureDataMap: function() { |
248 |
Drupal.settings.mediaDataMap = Drupal.settings.mediaDataMap || {}; |
249 |
return Drupal.settings.mediaDataMap;
|
250 |
}, |
251 |
|
252 |
/**
|
253 |
* Ensures the tag map has been initialized and returns it.
|
254 |
*/
|
255 |
ensure_tagmap: function () { |
256 |
Drupal.settings.tagmap = Drupal.settings.tagmap || {}; |
257 |
return Drupal.settings.tagmap;
|
258 |
} |
259 |
} |
260 |
|
261 |
})(jQuery); |