file.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * @file
  3. * Provides JavaScript additions to the managed file field type.
  4. *
  5. * This file provides progress bar support (if available), popup windows for
  6. * file previews, and disabling of other file fields during Ajax uploads (which
  7. * prevents separate file fields from accidentally uploading files).
  8. */
  9. (function ($) {
  10. /**
  11. * Attach behaviors to managed file element upload fields.
  12. */
  13. Drupal.behaviors.fileValidateAutoAttach = {
  14. attach: function (context, settings) {
  15. if (settings.file && settings.file.elements) {
  16. $.each(settings.file.elements, function(selector) {
  17. var extensions = settings.file.elements[selector];
  18. $(selector, context).bind('change', {extensions: extensions}, Drupal.file.validateExtension);
  19. });
  20. }
  21. },
  22. detach: function (context, settings) {
  23. if (settings.file && settings.file.elements) {
  24. $.each(settings.file.elements, function(selector) {
  25. $(selector, context).unbind('change', Drupal.file.validateExtension);
  26. });
  27. }
  28. }
  29. };
  30. /**
  31. * Attach behaviors to the file upload and remove buttons.
  32. */
  33. Drupal.behaviors.fileButtons = {
  34. attach: function (context) {
  35. $('input.form-submit', context).bind('mousedown', Drupal.file.disableFields);
  36. $('div.form-managed-file input.form-submit', context).bind('mousedown', Drupal.file.progressBar);
  37. },
  38. detach: function (context) {
  39. $('input.form-submit', context).unbind('mousedown', Drupal.file.disableFields);
  40. $('div.form-managed-file input.form-submit', context).unbind('mousedown', Drupal.file.progressBar);
  41. }
  42. };
  43. /**
  44. * Attach behaviors to links within managed file elements.
  45. */
  46. Drupal.behaviors.filePreviewLinks = {
  47. attach: function (context) {
  48. $('div.form-managed-file .file a, .file-widget .file a', context).bind('click',Drupal.file.openInNewWindow);
  49. },
  50. detach: function (context){
  51. $('div.form-managed-file .file a, .file-widget .file a', context).unbind('click', Drupal.file.openInNewWindow);
  52. }
  53. };
  54. /**
  55. * File upload utility functions.
  56. */
  57. Drupal.file = Drupal.file || {
  58. /**
  59. * Client-side file input validation of file extensions.
  60. */
  61. validateExtension: function (event) {
  62. // Remove any previous errors.
  63. $('.file-upload-js-error').remove();
  64. // Add client side validation for the input[type=file].
  65. var extensionPattern = event.data.extensions.replace(/,\s*/g, '|');
  66. if (extensionPattern.length > 1 && this.value.length > 0) {
  67. var acceptableMatch = new RegExp('\\.(' + extensionPattern + ')$', 'gi');
  68. if (!acceptableMatch.test(this.value)) {
  69. var error = Drupal.t("The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.", {
  70. // According to the specifications of HTML5, a file upload control
  71. // should not reveal the real local path to the file that a user
  72. // has selected. Some web browsers implement this restriction by
  73. // replacing the local path with "C:\fakepath\", which can cause
  74. // confusion by leaving the user thinking perhaps Drupal could not
  75. // find the file because it messed up the file path. To avoid this
  76. // confusion, therefore, we strip out the bogus fakepath string.
  77. '%filename': this.value.replace('C:\\fakepath\\', ''),
  78. '%extensions': extensionPattern.replace(/\|/g, ', ')
  79. });
  80. $(this).closest('div.form-managed-file').prepend('<div class="messages error file-upload-js-error" aria-live="polite">' + error + '</div>');
  81. this.value = '';
  82. return false;
  83. }
  84. }
  85. },
  86. /**
  87. * Prevent file uploads when using buttons not intended to upload.
  88. */
  89. disableFields: function (event){
  90. var clickedButton = this;
  91. // Only disable upload fields for Ajax buttons.
  92. if (!$(clickedButton).hasClass('ajax-processed')) {
  93. return;
  94. }
  95. // Check if we're working with an "Upload" button.
  96. var $enabledFields = [];
  97. if ($(this).closest('div.form-managed-file').length > 0) {
  98. $enabledFields = $(this).closest('div.form-managed-file').find('input.form-file');
  99. }
  100. // Temporarily disable upload fields other than the one we're currently
  101. // working with. Filter out fields that are already disabled so that they
  102. // do not get enabled when we re-enable these fields at the end of behavior
  103. // processing. Re-enable in a setTimeout set to a relatively short amount
  104. // of time (1 second). All the other mousedown handlers (like Drupal's Ajax
  105. // behaviors) are excuted before any timeout functions are called, so we
  106. // don't have to worry about the fields being re-enabled too soon.
  107. // @todo If the previous sentence is true, why not set the timeout to 0?
  108. var $fieldsToTemporarilyDisable = $('div.form-managed-file input.form-file').not($enabledFields).not(':disabled');
  109. $fieldsToTemporarilyDisable.attr('disabled', 'disabled');
  110. setTimeout(function (){
  111. $fieldsToTemporarilyDisable.attr('disabled', false);
  112. }, 1000);
  113. },
  114. /**
  115. * Add progress bar support if possible.
  116. */
  117. progressBar: function (event) {
  118. var clickedButton = this;
  119. var $progressId = $(clickedButton).closest('div.form-managed-file').find('input.file-progress');
  120. if ($progressId.length) {
  121. var originalName = $progressId.attr('name');
  122. // Replace the name with the required identifier.
  123. $progressId.attr('name', originalName.match(/APC_UPLOAD_PROGRESS|UPLOAD_IDENTIFIER/)[0]);
  124. // Restore the original name after the upload begins.
  125. setTimeout(function () {
  126. $progressId.attr('name', originalName);
  127. }, 1000);
  128. }
  129. // Show the progress bar if the upload takes longer than half a second.
  130. setTimeout(function () {
  131. $(clickedButton).closest('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
  132. }, 500);
  133. },
  134. /**
  135. * Open links to files within forms in a new window.
  136. */
  137. openInNewWindow: function (event) {
  138. $(this).attr('target', '_blank');
  139. window.open(this.href, 'filePreview', 'toolbar=0,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1,width=500,height=550');
  140. return false;
  141. }
  142. };
  143. })(jQuery);