root / drupal7 / sites / all / modules / media / modules / media_wysiwyg / js / media_wysiwyg.filter.js @ ca0757b9
1 | ca0757b9 | Assos Assos | /**
|
---|---|---|---|
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); |