Projet

Général

Profil

Paste
Télécharger (8,08 ko) Statistiques
| Branche: | Révision:

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 &quot; by \" to avoid error with JSON format.
188
              if (typeof value == 'string') {
189
                value = value.replace('&quot;', '\\"');
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);