diff options
author | Dries Buytaert <dries@buytaert.net> | 2005-08-31 18:37:30 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2005-08-31 18:37:30 +0000 |
commit | e03ce2f99670b75a7f3e0709dd8705a2a3f4625e (patch) | |
tree | a7678fa8a55ccd2927cbbc8d0e30bbacf630ad3d /modules | |
parent | 3029da00d62c20a4d97d668931bf9f0c918d1b09 (diff) | |
download | brdo-e03ce2f99670b75a7f3e0709dd8705a2a3f4625e.tar.gz brdo-e03ce2f99670b75a7f3e0709dd8705a2a3f4625e.tar.bz2 |
- Patch #28483 by Steven: JavaScript enabled uploading.
Comment from Steven: It does this by redirecting the submission of the form to a hidden <iframe> when you click "Attach" (we cannot submit data through Ajax directly because you cannot read file contents from JS for security reasons). Once the file is submitted, the upload-section of the form is updated. Things to note:
* The feature degrades back to the current behaviour without JS.
* If there are errors with the uploaded file (disallowed type, too big, ...), they are displayed at the top of the file attachments fieldset.
* Though the hidden-iframe method sounds dirty, it's quite compact and is 100% implemented in .js files. The drupal.js api makes it a snap to use.
* I included some minor improvements to the Drupal JS API and code.
* I added an API drupal_call_js() to bridge the PHP/JS gap: it takes a function name and arguments, and outputs a <script> tag. The kicker is that it preserves the structure and type of arguments, so e.g. PHP associative arrays end up as objects in JS.
* I also included a progressbar widget that I wrote for drumm's ongoing update.php work. It includes Ajax status updating/monitoring, but it is only used as a pure throbber in this patch. But as the code was already written and is going to be used in the near future, I left that part in. It's pretty small ;). If PHP supports ad-hoc upload info in the future like Ruby on Rails, we can implement that in 5 minutes.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/upload.module | 38 | ||||
-rw-r--r-- | modules/upload/upload.module | 38 |
2 files changed, 70 insertions, 6 deletions
diff --git a/modules/upload.module b/modules/upload.module index 3cf56d16c..335fd8dfc 100644 --- a/modules/upload.module +++ b/modules/upload.module @@ -60,6 +60,12 @@ function upload_menu($may_cache) { 'access' => user_access('administer site configuration'), 'type' => MENU_NORMAL_ITEM ); + $items[] = array( + 'path' => 'upload/js', + 'callback' => 'upload_js', + 'access' => user_access('upload files'), + 'type' => MENU_CALLBACK + ); } else { // Add handlers for previewing new uploads. @@ -378,8 +384,18 @@ function upload_delete($node) { } function upload_form($node) { + drupal_add_js('misc/progress.js'); + drupal_add_js('misc/upload.js'); + + $output = '<div id="fileop-wrapper">'. _upload_form($node) .'</div>'; + + return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>'; +} + +function _upload_form($node) { $header = array(t('Delete'), t('List'), t('Url'), t('Size')); $rows = array(); + $output = ''; if (is_array($node->files)) { foreach ($node->files as $key => $file) { @@ -393,15 +409,19 @@ function upload_form($node) { } if (count($node->files)) { - $output = theme('table', $header, $rows); + $output .= theme('table', $header, $rows); } if (user_access('upload files')) { + $output .= '<div id="fileop-hide">'; $output .= form_file(t('Attach new file'), "upload", 40); $output .= form_button(t('Attach'), 'fileop'); + // The class triggers the js upload behaviour. + $output .= form_hidden('fileop', url('upload/js', NULL, NULL, TRUE), 'edit', array('class' => 'upload')); + $output .= '</div>'; } - return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>'; + return $output; } function upload_load($node) { @@ -438,4 +458,16 @@ function _upload_image($file) { return $file; } - +/** + * Menu-callback for JavaScript-based uploads. + */ +function upload_js() { + // We only do the upload.module part of the node validation process. + $node = array2object($_POST['edit']); + upload_nodeapi(&$node, 'validate', NULL); + $output = theme('status_messages') . _upload_form($node); + + // We send the updated file attachments form. + print drupal_call_js('window.parent.iframeHandler', $output); + exit; +} diff --git a/modules/upload/upload.module b/modules/upload/upload.module index 3cf56d16c..335fd8dfc 100644 --- a/modules/upload/upload.module +++ b/modules/upload/upload.module @@ -60,6 +60,12 @@ function upload_menu($may_cache) { 'access' => user_access('administer site configuration'), 'type' => MENU_NORMAL_ITEM ); + $items[] = array( + 'path' => 'upload/js', + 'callback' => 'upload_js', + 'access' => user_access('upload files'), + 'type' => MENU_CALLBACK + ); } else { // Add handlers for previewing new uploads. @@ -378,8 +384,18 @@ function upload_delete($node) { } function upload_form($node) { + drupal_add_js('misc/progress.js'); + drupal_add_js('misc/upload.js'); + + $output = '<div id="fileop-wrapper">'. _upload_form($node) .'</div>'; + + return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>'; +} + +function _upload_form($node) { $header = array(t('Delete'), t('List'), t('Url'), t('Size')); $rows = array(); + $output = ''; if (is_array($node->files)) { foreach ($node->files as $key => $file) { @@ -393,15 +409,19 @@ function upload_form($node) { } if (count($node->files)) { - $output = theme('table', $header, $rows); + $output .= theme('table', $header, $rows); } if (user_access('upload files')) { + $output .= '<div id="fileop-hide">'; $output .= form_file(t('Attach new file'), "upload", 40); $output .= form_button(t('Attach'), 'fileop'); + // The class triggers the js upload behaviour. + $output .= form_hidden('fileop', url('upload/js', NULL, NULL, TRUE), 'edit', array('class' => 'upload')); + $output .= '</div>'; } - return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>'; + return $output; } function upload_load($node) { @@ -438,4 +458,16 @@ function _upload_image($file) { return $file; } - +/** + * Menu-callback for JavaScript-based uploads. + */ +function upload_js() { + // We only do the upload.module part of the node validation process. + $node = array2object($_POST['edit']); + upload_nodeapi(&$node, 'validate', NULL); + $output = theme('status_messages') . _upload_form($node); + + // We send the updated file attachments form. + print drupal_call_js('window.parent.iframeHandler', $output); + exit; +} |