From 06d7bb77c08a54032f1d49f4c99d50f271ff9609 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Thu, 12 Dec 2013 13:17:57 +0000 Subject: [PATCH] FIX: Defer loading of UploadField EditForm iframes (fixes #2711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also addresses issue #1439. I don’t like the binding iframe.on('load') events in the onclick handler, but apparently Entwine doesn't support binding on iframes. AssetAdmin and HtmlEditorField support added --- css/AssetUploadField.css | 4 +- css/UploadField.css | 2 + javascript/HtmlEditorField.js | 16 +++-- javascript/UploadField.js | 65 +++++++++++++------ javascript/UploadField_downloadtemplate.js | 2 +- scss/AssetUploadField.scss | 13 ++++ scss/UploadField.scss | 15 ++++- .../Includes/HtmlEditorField_viewfile.ss | 24 ++++--- templates/UploadField.ss | 4 +- 9 files changed, 100 insertions(+), 45 deletions(-) diff --git a/css/AssetUploadField.css b/css/AssetUploadField.css index 1988119ae..7fb70211d 100644 --- a/css/AssetUploadField.css +++ b/css/AssetUploadField.css @@ -42,7 +42,7 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse .ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info { background-color: #c11f1d; padding-right: 130px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c11f1d), color-stop(4%, #bf1d1b), color-stop(8%, #b71b1c), color-stop(15%, #b61e1d), color-stop(27%, #b11d1d), color-stop(31%, #ab1d1c), color-stop(42%, #a51b1b), color-stop(46%, #9f1b19), color-stop(50%, #9f1b19), color-stop(54%, #991c1a), color-stop(58%, #971a18), color-stop(62%, #911b1b), color-stop(65%, #911b1b), color-stop(88%, #7e1816), color-stop(92%, #771919), color-stop(100%, #731817)); background-image: -webkit-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: -moz-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: -o-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); } .ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name { width: 100%; cursor: default; background: #bcb9b9; background: rgba(201, 198, 198, 0.9); } .ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.7); } -.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #ff9300; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eba547), color-stop(8%, #e89a30), color-stop(50%, #e68f19), color-stop(54%, #e68e19), color-stop(96%, #e17519), color-stop(100%, #dc6718)); background-image: -webkit-linear-gradient(top, #eba547 0%, #e89a30 8%, #e68f19 50%, #e68e19 54%, #e17519 96%, #dc6718 100%); background-image: -moz-linear-gradient(top, #eba547 0%, #e89a30 8%, #e68f19 50%, #e68e19 54%, #e17519 96%, #dc6718 100%); background-image: -o-linear-gradient(top, #eba547 0%, #e89a30 8%, #e68f19 50%, #e68e19 54%, #e17519 96%, #dc6718 100%); background-image: linear-gradient(top, #eba547 0%, #e89a30 8%, #e68f19 50%, #e68e19 54%, #e17519 96%, #dc6718 100%); } +.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #e9d104; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e5d33b), color-stop(8%, #e2ce24), color-stop(50%, #d1be1c), color-stop(54%, #d1bc1b), color-stop(96%, #d09a1a), color-stop(100%, #ce8719)); background-image: -webkit-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: -moz-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: -o-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name { position: relative; z-index: 1; margin: 3px 0 3px 50px; width: 50%; color: #5e5e5e; background: #eeeded; background: rgba(255, 255, 255, 0.8); -webkit-border-radius: 3px; -moz-border-radius: 3px; -ms-border-radius: 3px; -o-border-radius: 3px; border-radius: 3px; line-height: 24px; height: 22px; padding: 0 5px; text-align: left; cursor: pointer; display: table; table-layout: fixed; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); display: inline; float: left; max-width: 50%; font-weight: normal; padding: 0 5px 0 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .ss-uploadfield-item-status { position: relative; float: right; padding: 0 0 0 5px; max-width: 30%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); } @@ -67,6 +67,8 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-progress .ss-uploadfield-item-progressbar { background-color: #92a6b3; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #92a6b3), color-stop(11%, #90aab8), color-stop(22%, #96b1bf), color-stop(33%, #9eb4c1), color-stop(44%, #a7bac7), color-stop(100%, #c1d5dc)); background-image: -webkit-linear-gradient(top, #92a6b3 0%, #90aab8 11%, #96b1bf 22%, #9eb4c1 33%, #a7bac7 44%, #c1d5dc 100%); background-image: -moz-linear-gradient(top, #92a6b3 0%, #90aab8 11%, #96b1bf 22%, #9eb4c1 33%, #a7bac7 44%, #c1d5dc 100%); background-image: -o-linear-gradient(top, #92a6b3 0%, #90aab8 11%, #96b1bf 22%, #9eb4c1 33%, #a7bac7 44%, #c1d5dc 100%); background-image: linear-gradient(top, #92a6b3 0%, #90aab8 11%, #96b1bf 22%, #9eb4c1 33%, #a7bac7 44%, #c1d5dc 100%); } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-progress .ss-uploadfield-item-progressbarvalue { width: 0; background: #60b3dd url(../images/progressbar_blue.gif) repeat left center; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; } +.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { width: 100%; height: 22px; padding: 15px 0; background: url(../admin/images/spinner.gif) no-repeat 50% 50%; } +.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading iframe { /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ padding-top: 0; margin-top: 37px; border: none; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { width: 100%; } .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-info { float: left; margin: 25px 0 0; } .ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-info { margin: 10px 0px 0 20px; } diff --git a/css/UploadField.css b/css/UploadField.css index 5d6468336..a0ec3ed48 100644 --- a/css/UploadField.css +++ b/css/UploadField.css @@ -39,6 +39,8 @@ Used in side panels and action tabs .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-cancel button span.ui-button-text, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-start button span.ui-button-text { display: none; } .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-start { right: 20px; } .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; } +.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { width: 100%; height: 22px; margin: 15px 0 0; background: url(../admin/images/spinner.gif) no-repeat 50% 0; } +.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading iframe { /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ padding-top: 0; margin-top: 22px; border: none; } .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid #d0d3d5; width: 100%; } .ss-uploadfield .ss-uploadfield-addfile.borderTop { border-top: 1px solid #b3b3b3; } diff --git a/javascript/HtmlEditorField.js b/javascript/HtmlEditorField.js index 6399deb16..fed30bfc9 100644 --- a/javascript/HtmlEditorField.js +++ b/javascript/HtmlEditorField.js @@ -1311,14 +1311,20 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; onclick: function(e) { var editForm = this.getEditForm(); - - editForm.parent('.ss-uploadfield-item').removeClass('ui-state-warning'); + + // Make sure we're in an HtmlEditorField here, or fall-back to _super(). HtmlEditorField with + // AssetUploadField doesn't use iframes, so needs its own toggleEditForm() logic + if (this.closest('.ss-uploadfield-item').hasClass('ss-htmleditorfield-file')) { + editForm.parent('ss-uploadfield-item').removeClass('ui-state-warning'); - editForm.toggleEditForm(); + editForm.toggleEditForm(); - e.preventDefault(); // Avoid a form submit + e.preventDefault(); // Avoid a form submit - return false; // Avoid duplication from button + return false; // Avoid duplication from button + } + + this._super(e); } }); diff --git a/javascript/UploadField.js b/javascript/UploadField.js index 640ea8a6d..630a4a547 100644 --- a/javascript/UploadField.js +++ b/javascript/UploadField.js @@ -396,11 +396,50 @@ }); $( 'div.ss-upload:not(.disabled):not(.readonly) .ss-uploadfield-item-edit').entwine({ onclick: function(e) { - var editform = this.closest('.ss-uploadfield-item').find('.ss-uploadfield-item-editform'); - var itemInfo = editform.prev('.ss-uploadfield-item-info'); - var disabled; - var iframe = editform.find('iframe'); + var self = this, + editform = self.closest('.ss-uploadfield-item').find('.ss-uploadfield-item-editform'), + itemInfo = editform.prev('.ss-uploadfield-item-info'), + iframe = editform.find('iframe'); + // Ignore clicks while the iframe is loading + if (iframe.parent().hasClass('loading')) { + e.preventDefault(); + return false; + } + + if (iframe.attr('src') == 'about:blank') { + // Lazy-load the iframe on editform toggle + iframe.attr('src', iframe.data('src')); + + // Add loading class, disable buttons while loading is in progress + // (_prepareIframe() handles re-enabling them when appropriate) + iframe.parent().addClass('loading'); + disabled=this.siblings(); + disabled.addClass('ui-state-disabled'); + disabled.attr('disabled', 'disabled'); + + iframe.on('load', function() { + iframe.parent().removeClass('loading'); + + // This ensures we only call _prepareIframe() on load once - otherwise it'll + // be superfluously called after clicking 'save' in the editform + if (iframe.data('src')) { + self._prepareIframe(iframe, editform, itemInfo); + iframe.data('src', ''); + } + + if (editform.hasClass('opened')) editform.fitHeight(); + }); + } else { + self._prepareIframe(iframe, editform, itemInfo); + } + + e.preventDefault(); // Avoid a form submit + return false; + }, + _prepareIframe: function(iframe, editform, itemInfo) { + var disabled; + // Mark the row as changed if any of its form fields are edited iframe.contents().ready(function() { // Need to use the iframe's own jQuery, as custom event triggers @@ -431,8 +470,6 @@ disabled.removeAttr('disabled'); } } - e.preventDefault(); // Avoid a form submit - return false; } }); @@ -453,7 +490,7 @@ if(!$.browser.msie && $.browser.version.slice(0,3) != "8.0"){ iframe.contents().find('body').css({'height':(h-padding)}); } - + // Set iframe to match its contents height iframe.height(h); @@ -504,20 +541,6 @@ status.attr('title',text).text(text); } }); - $('div.ss-upload .ss-uploadfield-item-editform iframe').entwine({ - onmatch: function() { - var form = this.closest('.ss-uploadfield-item-editform'); - // TODO entwine event binding doesn't work for iframes - this.load(function() { - $(this).parent().removeClass('loading'); - if(form.hasClass('opened')) form.fitHeight(); - }); - this._super(); - }, - onunmatch: function() { - this._super(); - } - }); $('div.ss-upload .ss-uploadfield-fromfiles').entwine({ onclick: function(e) { this.getUploadField().openSelectDialog(this.closest('.ss-uploadfield-item')); diff --git a/javascript/UploadField_downloadtemplate.js b/javascript/UploadField_downloadtemplate.js index 46d9b27dc..02500b389 100644 --- a/javascript/UploadField_downloadtemplate.js +++ b/javascript/UploadField_downloadtemplate.js @@ -27,7 +27,7 @@ window.tmpl.cache['ss-uploadfield-downloadtemplate'] = tmpl( '{% } %}' + '' + '{% if (!file.error) { %}' + - '
' + + '
' + '{% } %}' + '' + '{% } %}' diff --git a/scss/AssetUploadField.scss b/scss/AssetUploadField.scss index 4234c7517..fcc64af6d 100644 --- a/scss/AssetUploadField.scss +++ b/scss/AssetUploadField.scss @@ -263,6 +263,19 @@ body.cms.ss-uploadfield-edit-iframe, .composite.ss-assetuploadfield .details fie overflow: hidden; clear: both; + &.loading { + width: 100%; + height: 22px; + padding: 15px 0; + background: url(../admin/images/spinner.gif) no-repeat 50% 50%; + + iframe { + /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ + padding-top: 0; margin-top: 37px; + border: none; + } + } + iframe { width: 100%; } diff --git a/scss/UploadField.scss b/scss/UploadField.scss index 01efe3ef7..a4aa878f2 100644 --- a/scss/UploadField.scss +++ b/scss/UploadField.scss @@ -189,14 +189,25 @@ overflow: hidden; clear: both; + &.loading { + width: 100%; + height: 22px; + margin: 15px 0 0; + background: url(../admin/images/spinner.gif) no-repeat 50% 0; + + iframe { + /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ + padding-top: 0; margin-top: 22px; + border: none; + } + } + iframe { margin-top: $grid-y; padding-top: $grid-y; border-top: 1px solid $color-light-separator; width: 100%; } - - } } .ss-uploadfield-addfile { diff --git a/templates/Includes/HtmlEditorField_viewfile.ss b/templates/Includes/HtmlEditorField_viewfile.ss index 997fa0e46..a1cf734cb 100644 --- a/templates/Includes/HtmlEditorField_viewfile.ss +++ b/templates/Includes/HtmlEditorField_viewfile.ss @@ -23,23 +23,21 @@
-
- + +
+ - -
- -
<% if $Info %>
$Info
<% end_if %> -
+
<% loop $Fields %> $FieldHolder diff --git a/templates/UploadField.ss b/templates/UploadField.ss index d67406589..143344a1b 100644 --- a/templates/UploadField.ss +++ b/templates/UploadField.ss @@ -18,8 +18,8 @@ <% end_if %>
-
- +
+
<% end_loop %>