Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.542 diff -u -F^f -r1.542 common.inc --- includes/common.inc 8 Jun 2006 21:23:40 -0000 1.542 +++ includes/common.inc 30 Jun 2006 02:53:56 -0000 @@ -1202,17 +1202,22 @@ function drupal_add_link($attributes) { * Add a JavaScript file to the output. * * The first time this function is invoked per page request, - * it adds "misc/drupal.js" to the output. Other scripts - * depends on the 'killswitch' inside it. + * it adds "misc/drupal.js" and "misc/jquery.js" to the output for other + * scripts to use. */ function drupal_add_js($file, $nocache = FALSE) { + _drupal_add_js('misc/jquery.js', FALSE); + _drupal_add_js('misc/drupal.js', FALSE); + _drupal_add_js($file, $nocache); +} + +/** + * Helper function for drupal_add_js() + */ +function _drupal_add_js($file, $nocache) { static $sent = array(); $postfix = $nocache ? '?'. time() : ''; - if (!isset($sent['misc/drupal.js'])) { - drupal_set_html_head(''); - $sent['misc/drupal.js'] = true; - } if (!isset($sent[$file])) { drupal_set_html_head(''); $sent[$file] = true; Index: misc/autocomplete.js =================================================================== RCS file: /cvs/drupal/drupal/misc/autocomplete.js,v retrieving revision 1.12 diff -u -F^f -r1.12 autocomplete.js --- misc/autocomplete.js 20 May 2006 07:23:47 -0000 1.12 +++ misc/autocomplete.js 30 Jun 2006 02:53:56 -0000 @@ -2,7 +2,7 @@ // Global Killswitch if (isJsEnabled()) { - addLoadEvent(autocompleteAutoAttach); + $(document).ready(autocompleteAutoAttach); } /** @@ -10,34 +10,29 @@ */ function autocompleteAutoAttach() { var acdb = []; - var inputs = document.getElementsByTagName('input'); - for (i = 0; input = inputs[i]; i++) { - if (input && hasClass(input, 'autocomplete')) { - uri = input.value; - if (!acdb[uri]) { - acdb[uri] = new ACDB(uri); - } - input = $(input.id.substr(0, input.id.length - 13)); - input.setAttribute('autocomplete', 'OFF'); - addSubmitEvent(input.form, autocompleteSubmit); - new jsAC(input, acdb[uri]); + $('input.autocomplete').each(function () { + var uri = this.value; + if (!acdb[uri]) { + acdb[uri] = new ACDB(uri); } - } + var input = $('#' + this.id.substr(0, this.id.length - 13)) + .set('autocomplete', 'OFF') + .get(0); + $(input.form).submit(autocompleteSubmit); + new jsAC(input, acdb[uri]); + }); } /** * Prevents the form from submitting if the suggestions popup is open + * and closes the suggestions popup when doing so. */ function autocompleteSubmit() { - var popup = document.getElementById('autocomplete'); - if (popup) { - popup.owner.hidePopup(); - return false; - } - return true; + return $('#autocomplete').each(function () { + this.owner.hidePopup(); + }).size() == 0; } - /** * An AutoComplete object */ @@ -45,12 +40,12 @@ function jsAC(input, db) { var ac = this; this.input = input; this.db = db; - this.input.onkeydown = function (event) { return ac.onkeydown(this, event); }; - this.input.onkeyup = function (event) { ac.onkeyup(this, event) }; - this.input.onblur = function () { ac.hidePopup(); ac.db.cancel(); }; - this.popup = document.createElement('div'); - this.popup.id = 'autocomplete'; - this.popup.owner = this; + + $(this.input) + .keydown(function (event) { return ac.onkeydown(this, event); }) + .keyup(function (event) { ac.onkeyup(this, event) }) + .blur(function () { ac.hidePopup(); ac.db.cancel(); }); + }; /** @@ -60,8 +55,9 @@ function jsAC(input, db) { if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) { this.input.value = this.selected.autocompleteValue; } - if (this.popup.parentNode && this.popup.parentNode.tagName) { - removeNode(this.popup); + if (this.popup && this.popup.shown) { + $(this.popup).fadeOut('fast'); + this.popup.shown = false; } this.selected = false; } @@ -138,9 +134,9 @@ function jsAC(input, db) { this.highlight(this.selected.nextSibling); } else { - var lis = this.popup.getElementsByTagName('li'); - if (lis.length > 0) { - this.highlight(lis[0]); + var lis = $('li', this.popup); + if (lis.size() > 0) { + this.highlight(lis.get(0)); } } } @@ -158,8 +154,10 @@ function jsAC(input, db) { * Highlights a suggestion */ jsAC.prototype.highlight = function (node) { - removeClass(this.selected, 'selected'); - addClass(node, 'selected'); + if (this.selected) { + $(this.selected).removeClass('selected'); + } + $(node).addClass('selected'); this.selected = node; } @@ -167,7 +165,7 @@ function jsAC(input, db) { * Unhighlights a suggestion */ jsAC.prototype.unhighlight = function (node) { - removeClass(node, 'selected'); + $(node).removeClass('selected'); this.selected = false; } @@ -178,9 +176,20 @@ function jsAC(input, db) { var ac = this; var pos = absolutePosition(this.input); this.selected = false; - this.popup.style.top = (pos.y + this.input.offsetHeight) +'px'; - this.popup.style.left = pos.x +'px'; - this.popup.style.width = (this.input.offsetWidth - 4) +'px'; + + if (this.popup) { + $(this.popup).remove(); + } + this.popup = document.createElement('div'); + this.popup.id = 'autocomplete'; + this.popup.owner = this; + $(this.popup).css({ + top: (pos.y + this.input.offsetHeight) +'px', + left: pos.x +'px', + width: (this.input.offsetWidth - 4) +'px', + display: 'none' + }); + $('body').append(this.popup); this.db.owner = this; this.db.search(this.input.value); } @@ -189,29 +198,26 @@ function jsAC(input, db) { * Fills the suggestion popup with any matches received */ jsAC.prototype.found = function (matches) { - while (this.popup.hasChildNodes()) { - this.popup.removeChild(this.popup.childNodes[0]); - } - if (!this.popup.parentNode || !this.popup.parentNode.tagName) { - document.getElementsByTagName('body')[0].appendChild(this.popup); - } + // Show popup + $(this.popup).show(); + this.popup.shown = true; + // Prepare matches var ul = document.createElement('ul'); var ac = this; - for (key in matches) { var li = document.createElement('li'); - var div = document.createElement('div'); - div.innerHTML = matches[key]; - li.appendChild(div); + $(li) + .html('
'+ matches[key] +'
') + .mousedown(function () { ac.select(this); }) + .mouseover(function () { ac.highlight(this); }) + .mouseout(function () { ac.unhighlight(this); }); li.autocompleteValue = key; - li.onmousedown = function() { ac.select(this); }; - li.onmouseover = function() { ac.highlight(this); }; - li.onmouseout = function() { ac.unhighlight(this); }; - ul.appendChild(li); + $(ul).append(li); } + // Show popup with matches, if any if (ul.childNodes.length > 0) { - this.popup.appendChild(ul); + $(this.popup).append(ul); } else { this.hidePopup(); @@ -221,12 +227,12 @@ function jsAC(input, db) { jsAC.prototype.setStatus = function (status) { switch (status) { case 'begin': - addClass(this.input, 'throbbing'); + $(this.input).addClass('throbbing'); break; case 'cancel': case 'error': case 'found': - removeClass(this.input, 'throbbing'); + $(this.input).removeClass('throbbing'); break; } } Index: misc/collapse.js =================================================================== RCS file: /cvs/drupal/drupal/misc/collapse.js,v retrieving revision 1.6 diff -u -F^f -r1.6 collapse.js --- misc/collapse.js 14 Apr 2006 13:48:56 -0000 1.6 +++ misc/collapse.js 30 Jun 2006 02:53:57 -0000 @@ -1,59 +1,56 @@ // $Id: collapse.js,v 1.6 2006/04/14 13:48:56 killes Exp $ if (isJsEnabled()) { - addLoadEvent(collapseAutoAttach); + $(document).ready(collapseAutoAttach); } function collapseAutoAttach() { - var fieldsets = document.getElementsByTagName('fieldset'); - var legend, fieldset; - for (var i = 0; fieldset = fieldsets[i]; i++) { - if (!hasClass(fieldset, 'collapsible')) { - continue; - } - legend = fieldset.getElementsByTagName('legend'); - if (legend.length == 0) { - continue; - } - legend = legend[0]; + $('fieldset.collapsible legend').each(function () { + // Turn the legend into clickable link var a = document.createElement('a'); a.href = '#'; - a.onclick = function() { - toggleClass(this.parentNode.parentNode, 'collapsed'); - if (!hasClass(this.parentNode.parentNode, 'collapsed')) { - collapseScrollIntoView(this.parentNode.parentNode); - if (typeof textAreaAutoAttach != 'undefined') { - // Add the grippie to a textarea in a collapsed fieldset. - textAreaAutoAttach(null, this.parentNode.parentNode); + $(a) + .click(function() { + var fieldset = this.parentNode.parentNode; + if ($.hasWord(fieldset, 'collapsed')) { + $(fieldset.contentWrapper).hide(); + $(fieldset).removeClass('collapsed') + $(fieldset.contentWrapper).slideDown('medium'); + if (typeof textAreaAutoAttach != 'undefined') { + // Initialize resizable textareas that are now revealed + textAreaAutoAttach(null, fieldset); + } } - } - this.blur(); - return false; - }; - a.innerHTML = legend.innerHTML; - while (legend.hasChildNodes()) { - removeNode(legend.childNodes[0]); + else { + $(fieldset.contentWrapper).slideUp('medium'); + $(fieldset).addClass('collapsed') + $(fieldset.contentWrapper).show(); + } + this.blur(); + return false; + }) + .html(this.innerHTML); + $(this) + .html('') + .append(a); + + // Wrap other fieldsets contents into a wrapper div for animating + var div = document.createElement('div'); + $(this).after(div); + var el = div.nextSibling; + while (el != null) { + var next = el.nextSibling; + $(el).remove(); + $(div).append(el); + el = next; } - legend.appendChild(a); - collapseEnsureErrorsVisible(fieldset); - } -} + this.parentNode.contentWrapper = div; -function collapseEnsureErrorsVisible(fieldset) { - if (!hasClass(fieldset, 'collapsed')) { - return; - } - var inputs = []; - inputs = inputs.concat(fieldset.getElementsByTagName('input')); - inputs = inputs.concat(fieldset.getElementsByTagName('textarea')); - inputs = inputs.concat(fieldset.getElementsByTagName('select')); - for (var j = 0; j<3; j++) { - for (var i = 0; i < inputs[j].length; i++) { - if (hasClass(inputs[j][i], 'error')) { - return removeClass(fieldset, 'collapsed'); - } + // Expand if there are errors inside + if ($('input.error, textarea.error, select.error', this.parentNode).size() > 0) { + $(fieldset).removeClass('collapsed'); } - } + }); } function collapseScrollIntoView(node) { Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.24 diff -u -F^f -r1.24 drupal.js --- misc/drupal.js 7 Jun 2006 09:34:11 -0000 1.24 +++ misc/drupal.js 30 Jun 2006 02:53:58 -0000 @@ -22,22 +22,6 @@ function isJsEnabled() { } /** - * Make IE's XMLHTTP object accessible through XMLHttpRequest() - */ -if (typeof XMLHttpRequest == 'undefined') { - XMLHttpRequest = function () { - var msxmls = ['MSXML3', 'MSXML2', 'Microsoft'] - for (var i=0; i < msxmls.length; i++) { - try { - return new ActiveXObject(msxmls[i]+'.XMLHTTP') - } - catch (e) { } - } - throw new Error("No XML component installed!"); - } -} - -/** * Creates an HTTP GET request and sends the response to the callback function. * * Note that dynamic arguments in the URI should be escaped with encodeURIComponent(). @@ -132,7 +116,7 @@ function redirectFormButton(uri, button, // Set iframe handler for later window.iframeHandler = function () { - var iframe = $('redirect-target'); + var iframe = $('#redirect-target').get(0); // Restore form submission button.form.action = action; button.form.target = target; @@ -151,8 +135,7 @@ function redirectFormButton(uri, button, response = null; } - $('redirect-target').onload = null; - $('redirect-target').src = 'about:blank'; + iframe.onload = null; response = parseJson(response); // Check response code @@ -172,37 +155,6 @@ function redirectFormButton(uri, button, } /** - * Adds a function to the window onload event - */ -function addLoadEvent(func) { - var oldOnload = window.onload; - if (typeof window.onload != 'function') { - window.onload = func; - } - else { - window.onload = function() { - oldOnload(); - func(); - } - } -} - -/** - * Adds a function to a given form's submit event - */ -function addSubmitEvent(form, func) { - var oldSubmit = form.onsubmit; - if (typeof oldSubmit != 'function') { - form.onsubmit = func; - } - else { - form.onsubmit = function() { - return oldSubmit() && func(); - } - } -} - -/** * Retrieves the absolute position of an element on the screen */ function absolutePosition(el) { @@ -228,53 +180,6 @@ function dimensions(el) { } /** - * Returns true if an element has a specified class name - */ -function hasClass(node, className) { - if (node.className == className) { - return true; - } - var reg = new RegExp('(^| )'+ className +'($| )') - if (reg.test(node.className)) { - return true; - } - return false; -} - -/** - * Adds a class name to an element - */ -function addClass(node, className) { - if (hasClass(node, className)) { - return false; - } - node.className += ' '+ className; - return true; -} - -/** - * Removes a class name from an element - */ -function removeClass(node, className) { - if (!hasClass(node, className)) { - return false; - } - // Replaces words surrounded with whitespace or at a string border with a space. Prevents multiple class names from being glued together. - node.className = eregReplace('(^|\\s+)'+ className +'($|\\s+)', ' ', node.className); - return true; -} - -/** - * Toggles a class name on or off for an element - */ -function toggleClass(node, className) { - if (!removeClass(node, className) && !addClass(node, className)) { - return false; - } - return true; -} - -/** * Emulate PHP's ereg_replace function in javascript */ function eregReplace(search, replace, subject) { @@ -282,21 +187,6 @@ function eregReplace(search, replace, su } /** - * Removes an element from the page - */ -function removeNode(node) { - if (typeof node == 'string') { - node = $(node); - } - if (node && node.parentNode) { - return node.parentNode.removeChild(node); - } - else { - return false; - } -} - -/** * Prevents an event from propagating. */ function stopEvent(event) { @@ -327,13 +217,13 @@ function parseJson(data) { */ function createIframe() { // Delete any previous iframe - deleteIframe(); + $('#redirect-holder').remove(); // Note: some browsers require the literal name/id attributes on the tag, // some want them set through JS. We do both. window.iframeHandler = function () {}; var div = document.createElement('div'); div.id = 'redirect-holder'; - div.innerHTML = ''; + $(div).html(''); var iframe = div.firstChild; with (iframe) { name = 'redirect-target'; @@ -346,22 +236,5 @@ function createIframe() { width = '1px'; visibility = 'hidden'; } - document.body.appendChild(div); -} - -/** - * Delete the invisible iframe for form submissions. - */ -function deleteIframe() { - var holder = $('redirect-holder'); - if (holder != null) { - removeNode(holder); - } -} - -/** - * Wrapper around document.getElementById(). - */ -function $(id) { - return document.getElementById(id); + $('body').append(div); } Index: misc/progress.js =================================================================== RCS file: /cvs/drupal/drupal/misc/progress.js,v retrieving revision 1.10 diff -u -F^f -r1.10 progress.js --- misc/progress.js 28 Mar 2006 09:29:23 -0000 1.10 +++ misc/progress.js 30 Jun 2006 02:53:58 -0000 @@ -20,30 +20,20 @@ function progressBar(id, updateCallback, this.element = document.createElement('div'); this.element.id = id; this.element.className = 'progress'; - this.element.innerHTML = '
'+ - '
 
'+ - '
'; + $(this.element).html('
'+ + '
 
'+ + '
'); } /** * Set the percentage and status message for the progressbar. */ progressBar.prototype.setProgress = function (percentage, message) { - var divs = this.element.getElementsByTagName('div'); - var div; - for (var i = 0; div = divs[i]; ++i) { - if (percentage >= 0) { - if (hasClass(divs[i], 'filled')) { - divs[i].style.width = percentage + '%'; - } - if (hasClass(divs[i], 'percentage')) { - divs[i].innerHTML = percentage + '%'; - } - } - if (hasClass(divs[i], 'message')) { - divs[i].innerHTML = message; - } + if (percentage >= 0 && percentage <= 100) { + $('div.filled', this.element).css('width', percentage +'%'); + $('div.percentage', this.element).html(percentage +'%'); } + $('div.message', this.element).html(message); if (this.updateCallback) { this.updateCallback(percentage, message, this); } @@ -109,8 +99,7 @@ function progressBar(id, updateCallback, error.className = 'error'; error.innerHTML = string; - this.element.style.display = 'none'; - this.element.parentNode.insertBefore(error, this.element); + $(this.element).before(error).hide(); if (this.errorCallback) { this.errorCallback(this); Index: misc/textarea.js =================================================================== RCS file: /cvs/drupal/drupal/misc/textarea.js,v retrieving revision 1.9 diff -u -F^f -r1.9 textarea.js --- misc/textarea.js 14 Apr 2006 13:48:56 -0000 1.9 +++ misc/textarea.js 30 Jun 2006 02:53:58 -0000 @@ -1,55 +1,48 @@ // $Id: textarea.js,v 1.9 2006/04/14 13:48:56 killes Exp $ if (isJsEnabled()) { - addLoadEvent(textAreaAutoAttach); + $(document).ready(textAreaAutoAttach); } function textAreaAutoAttach(event, parent) { - if (typeof parent == 'undefined') { - // Attach to all visible textareas. - textareas = document.getElementsByTagName('textarea'); - } - else { - // Attach to all visible textareas inside parent. - textareas = parent.getElementsByTagName('textarea'); - } - var textarea; - for (var i = 0; textarea = textareas[i]; ++i) { - if (hasClass(textarea, 'resizable') && !hasClass(textarea.nextSibling, 'grippie')) { - if (typeof dimensions(textarea).width != 'undefined' && dimensions(textarea).width != 0) { - new textArea(textarea); - } + $('textarea.resizable', parent).each(function() { + if (!this.resizable + && typeof dimensions(this).width != 'undefined' + && dimensions(this).width != 0) { + new textArea(this); } - } + }); } function textArea(element) { var ta = this; this.element = element; - this.parent = this.element.parentNode; + this.element.resizable = true; this.dimensions = dimensions(element); // Prepare wrapper this.wrapper = document.createElement('div'); this.wrapper.className = 'resizable-textarea'; - this.parent.insertBefore(this.wrapper, this.element); + $(this.element).before(this.wrapper); // Add grippie and measure it this.grippie = document.createElement('div'); this.grippie.className = 'grippie'; - this.wrapper.appendChild(this.grippie); + $(this.wrapper).append(this.grippie); this.grippie.dimensions = dimensions(this.grippie); - this.grippie.onmousedown = function (e) { ta.beginDrag(e); }; + $(this.grippie).mousedown(function (e) { ta.beginDrag(e); }); // Set wrapper and textarea dimensions - this.wrapper.style.height = this.dimensions.height + this.grippie.dimensions.height + 1 +'px'; - this.element.style.marginBottom = '0px'; - this.element.style.width = '100%'; - this.element.style.height = this.dimensions.height +'px'; + $(this.wrapper).css('height', this.dimensions.height + this.grippie.dimensions.height + 1 +'px'); + $(this.element).css({ + marginBottom: '0px', + width: '100%', + height: this.dimensions.height +'px' + }); // Wrap textarea - removeNode(this.element); - this.wrapper.insertBefore(this.element, this.grippie); + $(this.element).remove(); + $(this.grippie).before(this.element); // Measure difference between desired and actual textarea dimensions to account for padding/borders this.widthOffset = dimensions(this.wrapper).width - this.dimensions.width; @@ -57,15 +50,17 @@ function textArea(element) { // Make the grippie line up in various browsers if (window.opera) { // Opera - this.grippie.style.marginRight = '4px'; + $(this.grippie).css('marginRight', '4px'); } if (document.all && !window.opera) { // IE - this.grippie.style.width = '100%'; - this.grippie.style.paddingLeft = '2px'; + $(this.grippie).css({ + width: '100%', + paddingLeft: '2px' + }); } // Mozilla - this.element.style.MozBoxSizing = 'border-box'; + $(this.element).css('MozBoxSizing', 'border-box'); this.heightOffset = absolutePosition(this.grippie).y - absolutePosition(this.element).y - this.dimensions.height; } @@ -118,5 +113,4 @@ function textArea(element) { // Restore opacity this.element.style.opacity = 1.0; document.isDragging = false; -} - +} \ No newline at end of file Index: misc/update.js =================================================================== RCS file: /cvs/drupal/drupal/misc/update.js,v retrieving revision 1.8 diff -u -F^f -r1.8 update.js --- misc/update.js 28 Mar 2006 09:29:23 -0000 1.8 +++ misc/update.js 30 Jun 2006 02:53:58 -0000 @@ -1,12 +1,11 @@ // $Id: update.js,v 1.8 2006/03/28 09:29:23 killes Exp $ if (isJsEnabled()) { - addLoadEvent(function() { - if ($('edit-has_js')) { - $('edit-has_js').value = 1; - } + $(document).ready(function() { + $('#edit-has_js').each(function() { this.value = 1; }); + $('#progress').each(function () { + var holder = this; - if ($('progress')) { // Success: redirect to the summary. var updateCallback = function (progress, status, pb) { if (progress == 100) { @@ -19,15 +18,15 @@ var errorCallback = function (pb) { var div = document.createElement('p'); div.className = 'error'; - div.innerHTML = 'An unrecoverable error has occured. You can find the error message below. It is advised to copy it to the clipboard for reference. Please continue to the update summary'; - $('progress').insertBefore(div, $('progress').firstChild); - $('wait').style.display = 'none'; + $(div).html('An unrecoverable error has occured. You can find the error message below. It is advised to copy it to the clipboard for reference. Please continue to the update summary'); + holder.prepend(div); + $('#wait').hide(); } var progress = new progressBar('updateprogress', updateCallback, HTTPPost, errorCallback); progress.setProgress(-1, 'Starting updates'); - $('progress').appendChild(progress.element); + $(holder).append(progress.element); progress.startMonitoring('update.php?op=do_update', 0); - } + }); }); } Index: misc/upload.js =================================================================== RCS file: /cvs/drupal/drupal/misc/upload.js,v retrieving revision 1.9 diff -u -F^f -r1.9 upload.js --- misc/upload.js 5 May 2006 10:47:20 -0000 1.9 +++ misc/upload.js 30 Jun 2006 02:53:59 -0000 @@ -2,63 +2,103 @@ // Global killswitch if (isJsEnabled()) { - addLoadEvent(uploadAutoAttach); + $(document).ready(uploadAutoAttach); } /** * Attaches the upload behaviour to the upload form. */ function uploadAutoAttach() { - var inputs = document.getElementsByTagName('input'); - for (i = 0; input = inputs[i]; i++) { - if (input && hasClass(input, 'upload')) { - var uri = input.value; - // Extract the button ID based on a substring of the input name: edit[foo][bar] -> foo-bar - var button = input.name.substr(5, input.name.length - 6).replace('][', '-'); - var wrapper = button + '-wrapper'; - var hide = button + '-hide'; - var upload = new jsUpload(uri, button, wrapper, hide); - } - } + $('input.upload').each(function () { + var uri = this.value; + // Extract the button ID based on a substring of the input name: edit[foo][bar] -> foo-bar + var button = this.name.substr(5, this.name.length - 6).replace('][', '-'); + var wrapper = button + '-wrapper'; + var hide = button + '-hide'; + var upload = new jsUpload(uri, button, wrapper, hide); + }); } /** * JS upload object. */ function jsUpload(uri, button, wrapper, hide) { - this.button = button; - this.wrapper = wrapper; - this.hide = hide; - redirectFormButton(uri, $(button), this); + // Note: these elements are replaced after an upload, so we re-select them + // everytime they are needed. + this.button = '#'+ button; + this.wrapper = '#'+ wrapper; + this.hide = '#'+ hide; + redirectFormButton(uri, $(this.button).get(0), this); } /** * Handler for the form redirection submission. */ jsUpload.prototype.onsubmit = function () { - var hide = $(this.hide); // Insert progressbar and stretch to take the same space. this.progress = new progressBar('uploadprogress'); this.progress.setProgress(-1, 'Uploading file'); - this.progress.element.style.width = '28em'; - this.progress.element.style.height = hide.offsetHeight +'px'; - hide.parentNode.insertBefore(this.progress.element, hide); - // Hide file form (cannot use display: none, this mysteriously aborts form - // submission in Konqueror) - hide.style.position = 'absolute'; - hide.style.left = '-2000px'; + $(this.progress.element).css({ + width: '28em', + height: ($(this.hide).get(0).offsetHeight - 10) +'px', + marginBottom: -$(this.hide).get(0).offsetHeight +'px', + paddingTop: '10px', + display: 'none' + }); + + // Hide file form and replace by progress bar (cannot use display: none, + // this mysteriously aborts form submission in Konqueror) +/* $(this.hide) + .css({ + position: 'absolute', + left: '-2000px' + }) + .before(this.progress.element); +*/ + $(this.hide).before(this.progress.element).fadeOut('slow'); + $(this.progress.element).fadeIn('slow'); } /** * Handler for the form redirection completion. */ jsUpload.prototype.oncomplete = function (data) { - // Remove progressbar - removeNode(this.progress.element); - this.progress = null; - // Replace form and re-attach behaviour - $(this.wrapper).innerHTML = data; - uploadAutoAttach(); + // Remove old form + $(this.wrapper).html(''); + + // Place HTML into temporary div + var div = document.createElement('div'); + $(div).html(data); + + // If uploading the first attachment fade in everything + if ($('tr', div).size() == 2) { + // Replace form and re-attach behaviour + $(div).hide(); + $(this.wrapper).html(''); + $(this.wrapper).append(div); + $(div).fadeIn('slow'); + uploadAutoAttach(); + } + // Else fade in only the last table row + else { + // Hide form and last table row + $('table tr:last-of-type td', div).hide(); + + // Note: workaround because jQuery's #id selector does not work outside of 'document' + // Should be: $(this.hide, div).hide(); + var hide = this.hide; + $('div', div).each(function() { + if (('#'+ this.id) == hide) { + this.style.display = 'none'; + } + }); + + // Replace form, fade in items and re-attach behaviour + $(this.wrapper).append(div); + $('table tr:last-of-type td', div).fadeIn('slow'); + $(this.hide, div).fadeIn('slow'); + uploadAutoAttach(); + } } /** @@ -67,9 +107,11 @@ function jsUpload(uri, button, wrapper, jsUpload.prototype.onerror = function (error) { alert('An error occurred:\n\n'+ error); // Remove progressbar - removeNode(this.progress.element); + $(this.progress.element).remove(); this.progress = null; // Undo hide - $(this.hide).style.position = 'static'; - $(this.hide).style.left = '0px'; + $(this.hide).css({ + position: 'static', + left: '0px' + }); }