Further modules included.
[yaffs-website] / web / modules / contrib / filefield_sources / js / filefield_sources.js
1 /**
2  * @file
3  * Defines Javascript behaviors for the filefield_sources module.
4  */
5
6 (function ($, Drupal) {
7
8 "use strict";
9
10 // Behavior to add source options to configured fields.
11 Drupal.behaviors.fileFieldSources = {};
12 Drupal.behaviors.fileFieldSources.attach = function(context, settings) {
13   $('div.filefield-sources-list:not(.filefield-sources-processed)', context).each(function() {
14     $(this).addClass('filefield-sources-processed');
15     var $fileFieldElement = $(this).parents('div.form-managed-file:first');
16     $(this).find('a').click(function() {
17       // Remove the active class.
18       $(this).parents('div.filefield-sources-list').find('a.active').removeClass('active');
19
20       // Find the unique FileField Source class name.
21       var fileFieldSourceClass = this.className.match(/filefield-source-[0-9a-z_]+/i)[0];
22
23       // The default upload element is a special case.
24       if ($(this).is('.filefield-source-upload')) {
25         $fileFieldElement.find('div.filefield-sources-list').siblings('.form-file, .form-submit').css('display', '');
26         $fileFieldElement.find('div.filefield-source').css('display', 'none');
27       }
28       else {
29         $fileFieldElement.find('div.filefield-sources-list').siblings('.form-file, .form-submit').css('display', 'none');
30         $fileFieldElement.find('div.filefield-source').not('div.' + fileFieldSourceClass).css('display', 'none');
31         $fileFieldElement.find('div.' + fileFieldSourceClass).css('display', '');
32       }
33
34       // Add the active class.
35       $(this).addClass('active');
36       Drupal.fileFieldSources.updateHintText($fileFieldElement.get(0));
37     }).first().triggerHandler('click');
38
39     // Clipboard support.
40     $fileFieldElement.find('.filefield-source-clipboard-capture')
41       .bind('paste', Drupal.fileFieldSources.pasteEvent)
42       .bind('focus', Drupal.fileFieldSources.pasteFocus)
43       .bind('blur', Drupal.fileFieldSources.pasteBlur);
44
45     // Imce support.
46     $fileFieldElement.find('.filefield-sources-imce-browse')
47       .bind('click', Drupal.fileFieldSources.imceBrowse);
48   });
49
50   if (context === document) {
51     $('form').submit(function() {
52       Drupal.fileFieldSources.removeHintText();
53     });
54   }
55 };
56
57 // Helper functions used by FileField Sources.
58 Drupal.fileFieldSources = {
59   /**
60    * Update the hint text when clicking between source types.
61    */
62   updateHintText: function(fileFieldElement) {
63     // Add default value hint text to text fields.
64     $(fileFieldElement).find('div.filefield-source').each(function() {
65       var matches = this.className.match(/filefield-source-([a-z]+)/);
66       var sourceType = matches[1];
67       var textfield = $(this).find('input.form-text:first').get(0);
68       var defaultText = (drupalSettings.fileFieldSources && drupalSettings.fileFieldSources[sourceType]) ? drupalSettings.fileFieldSources[sourceType].hintText : '';
69
70       // If the field doesn't exist, just return.
71       if (!textfield) {
72         return;
73       }
74
75       // If this field is not shown, remove its value and be done.
76       if (!$(this).is(':visible') && textfield.value == defaultText) {
77         textfield.value = '';
78         return;
79       }
80
81       // Set a default value:
82       if (textfield.value == '') {
83         textfield.value = defaultText;
84       }
85
86       // Set a default class.
87       if (textfield.value == defaultText) {
88         $(textfield).addClass('hint');
89       }
90
91       $(textfield).focus(hideHintText);
92       $(textfield).blur(showHintText);
93
94       function showHintText() {
95         if (this.value == '') {
96           this.value = defaultText;
97           $(this).addClass('hint');
98         }
99       }
100
101       function hideHintText() {
102         if (this.value == defaultText) {
103           this.value = '';
104           $(this).removeClass('hint');
105         }
106       }
107     });
108   },
109
110   /**
111    * Delete all hint text from a form before submit.
112    */
113   removeHintText: function() {
114     $('div.filefield-source input.hint').val('').removeClass('hint');
115   },
116
117   /**
118    * Clean up the default value on focus.
119    */
120   pasteFocus: function(e) {
121     // Set default text.
122     if (!this.defaultText) {
123       this.defaultText = this.innerHTML;
124       this.innerHTML = '';
125     }
126     // Remove non-text nodes.
127     $(this).children().remove();
128   },
129
130   /**
131    * Restore default value on blur.
132    */
133   pasteBlur: function(e) {
134     if (this.defaultText && !this.innerHTML) {
135       this.innerHTML = this.defaultText;
136     }
137   },
138
139   pasteEvent: function(e) {
140     var clipboardData = null;
141     var targetElement = this;
142     var userAgent = navigator.userAgent.toLowerCase();
143
144     // Chrome.
145     if (window.event && window.event.clipboardData && window.event.clipboardData.items) {
146       clipboardData = window.event.clipboardData;
147     }
148     // All browsers in the future (hopefully).
149     else if (e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.items) {
150       clipboardData = e.originalEvent.clipboardData;
151     }
152     // Firefox with content editable pastes as img tag with data href.
153     else if (userAgent.match(/mozilla/) && !userAgent.match(/webkit/)) {
154       Drupal.fileFieldSources.waitForPaste(targetElement);
155       return true;
156     }
157     else {
158       Drupal.fileFieldSources.pasteError(targetElement, Drupal.t('Paste from clipboard not supported in this browser.'));
159       return false;
160     }
161
162     var items = clipboardData.items;
163     var types = clipboardData.types;
164     var filename = targetElement.firstChild ? targetElement.firstChild.textContent : '';
165
166     // Handle files and image content directly in the clipboard.
167     var fileFound = false;
168     for (var n = 0; n < items.length; n++) {
169       if (items[n] && items[n].kind === 'file') {
170         var fileBlob = items[n].getAsFile();
171         var fileReader = new FileReader();
172         // Define events to fire after the file is read into memory.
173         fileReader.onload = function() {
174           Drupal.fileFieldSources.pasteSubmit(targetElement, filename, this.result);
175         };
176         fileReader.onerror = function() {
177           Drupal.fileFieldSources.pasteError(targetElement, Drupal.t('Error reading file from clipboard.'));
178         };
179         // Read in the file to fire the above events.
180         fileReader.readAsDataURL(fileBlob);
181         fileFound = true;
182         break;
183       }
184       // Handle files that a copy/pasted as a file reference.
185       /* if (types[n] && types[n] === 'Files') {
186           TODO: Figure out how to capture copy/paste of entire files from desktop.
187        }*/
188     }
189     if (!fileFound) {
190       Drupal.fileFieldSources.pasteError(targetElement, Drupal.t('No file in clipboard.'));
191     }
192     return false;
193   },
194
195   /**
196    * For browsers that don't support native clipboardData attributes.
197    */
198   waitForPaste: function(targetElement) {
199     if (targetElement.children && targetElement.children.length > 0) {
200       var filename = targetElement.firstChild ? targetElement.firstChild.textContent : '';
201       var tagFound = false;
202       $(targetElement).find('img[src^="data:image"]').each(function(n, element) {
203         Drupal.fileFieldSources.pasteSubmit(targetElement, filename, element.src);
204         tagFound = true;
205       });
206       $(targetElement).html(filename);
207       if (!tagFound) {
208         Drupal.fileFieldSources.pasteError(targetElement, Drupal.t('No file in clipboard.'));
209       }
210     }
211     else {
212       setTimeout(function() {
213         Drupal.fileFieldSources.waitForPaste(targetElement);
214       }, 200);
215     }
216   },
217
218   /**
219    * Set an error on the paste field temporarily then clear it.
220    */
221   pasteError: function(domElement, errorMessage) {
222     var $description = $(domElement).parents('.filefield-source-clipboard:first').find('.description');
223     if (!$description.data('originalDescription')) {
224       $description.data('originalDescription', $description.html())
225     }
226     $description.html(errorMessage);
227     var errorTimeout = setTimeout(function() {
228       $description.html($description.data('originalDescription'));
229       $(this).unbind('click.pasteError');
230     }, 3000);
231     $(domElement).bind('click.pasteError', function() {
232       clearTimeout(errorTimeout);
233       $description.html($description.data('originalDescription'));
234       $(this).unbind('click.pasteError');
235     });
236   },
237
238   /**
239    * After retreiving a clipboard, post the results to the server.
240    */
241   pasteSubmit: function(targetElement, filename, contents) {
242     var $wrapper = $(targetElement).parents('.filefield-source-clipboard');
243     $wrapper.find('.filefield-source-clipboard-filename').val(filename);
244     $wrapper.find('.filefield-source-clipboard-contents').val(contents);
245     $wrapper.find('input.form-submit').trigger('mousedown');
246   },
247
248   /**
249    * Click event for the imce browse link.
250    */
251   imceBrowse: function (e) {
252     window.open(this.href, '', 'width=760,height=560,resizable=1');
253     e.preventDefault();
254   }
255 };
256
257 // Override triggerUploadButton method from file.js.
258 Drupal.file.triggerUploadButton = function (event) {
259   $(event.target).closest('.form-managed-file').find('.form-submit.upload-button').trigger('mousedown');
260 }
261
262 })(jQuery, Drupal);