jQuery in the back-end updated to v.2.1.3. Fixed several memory management issues in select2 (an event attached to the mask element is never unbound), framework.js (onunload event attached to window is never unbound and holds references to the Request instances). Added popup adaptive size option. Started media manager popup API.
This commit is contained in:
parent
16cb546f30
commit
9ed3d03484
|
|
@ -68,6 +68,7 @@ label{font-size:12px}
|
|||
.form-buttons:before,.form-buttons:after{content:" ";display:table}
|
||||
.form-buttons:after{clear:both}
|
||||
.form-buttons .btn{margin-right:10px}
|
||||
.form-buttons .btn.no-margin-right{margin-right:0}
|
||||
.form-buttons .pull-right{margin-right:0;margin-left:10px}
|
||||
.form-buttons.buttons-offset{padding-left:20px}
|
||||
body.slim-container .form-buttons{padding:0 20px 20px}
|
||||
|
|
@ -339,6 +340,9 @@ table.table.data tr.list-tree-level-25 td.list-cell-index-1{padding-left:275px}
|
|||
.modal-footer{background:transparent;border:none;margin-top:0;padding:0 20px 20px 20px}
|
||||
.modal-body{padding-bottom:0}
|
||||
.modal-body > p:last-child{margin-bottom:20px}
|
||||
.modal-dialog.size-adaptive{width:100%;padding-right:50px;padding-left:50px}
|
||||
.modal-dialog.adaptive-height{height:100%;min-height:600px;margin-top:0;margin-bottom:0;padding-top:50px;padding-bottom:50px}
|
||||
.modal-dialog.adaptive-height .modal-content{height:100%}
|
||||
@media (min-width:768px){.modal-dialog.size-tiny{width:300px}
|
||||
.modal-dialog.size-small{width:400px}
|
||||
}
|
||||
|
|
@ -346,6 +350,8 @@ table.table.data tr.list-tree-level-25 td.list-cell-index-1{padding-left:275px}
|
|||
.modal-dialog.size-huge{width:900px}
|
||||
.modal-dialog.size-giant{width:982px}
|
||||
}
|
||||
@media (max-width:768px){.modal-dialog.size-adaptive{width:auto;padding:5px 0;margin:0}
|
||||
}
|
||||
.control-popup.fade .modal-dialog{opacity:0;filter:alpha(opacity=0);-webkit-transition:all 0.3s,width 0s;transition:all 0.3s,width 0s;-webkit-transform:scale(0.7);-ms-transform:scale(0.7);transform:scale(0.7)}
|
||||
.control-popup.fade.in .modal-dialog{opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
|
||||
.popup-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000000;background-color:rgba(0,0,0,0.2);opacity:1;filter:alpha(opacity=100)}
|
||||
|
|
@ -1125,6 +1131,7 @@ div.panel.transparent{background:transparent}
|
|||
div.panel.border-left{border-left:1px solid #e8eaeb}
|
||||
div.panel.border-right{border-right:1px solid #e8eaeb}
|
||||
div.panel.border-bottom{border-bottom:1px solid #e8eaeb}
|
||||
div.panel.border-top{border-top:1px solid #e8eaeb}
|
||||
div.panel.triangle-down{position:relative}
|
||||
div.panel.triangle-down:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #ffffff;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101}
|
||||
div.panel.triangle-down:before{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #e8eaeb;border-bottom-width:0;position:absolute;left:14px;bottom:-9px;z-index:100}
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@ this.$modal.on('shown.bs.modal',function(){self.triggerEvent('shown.oc.popup')})
|
|||
this.$modal.on('close.oc.popup',function(){self.hide()
|
||||
return false})
|
||||
this.init()}
|
||||
Popup.DEFAULTS={ajax:null,handler:null,keyboard:true,extraData:{},content:null,size:null}
|
||||
Popup.DEFAULTS={ajax:null,handler:null,keyboard:true,extraData:{},content:null,size:null,adaptiveHeight:false}
|
||||
Popup.prototype.init=function(){var self=this
|
||||
if(self.isOpen)
|
||||
return
|
||||
|
|
@ -892,6 +892,8 @@ Popup.prototype.createPopupContainer=function(){var
|
|||
modal=$('<div />').prop({class:'control-popup modal fade',role:'dialog',tabindex:-1}),modalDialog=$('<div />').addClass('modal-dialog'),modalContent=$('<div />').addClass('modal-content')
|
||||
if(this.options.size)
|
||||
modalDialog.addClass('size-'+this.options.size)
|
||||
if(this.options.adaptiveHeight)
|
||||
modalDialog.addClass('adaptive-height')
|
||||
return modal.append(modalDialog.append(modalContent))}
|
||||
Popup.prototype.setContent=function(contents){this.$content.html(contents)
|
||||
this.setLoading(false)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@
|
|||
keyboard: true,
|
||||
extraData: {},
|
||||
content: null,
|
||||
size: null
|
||||
size: null,
|
||||
adaptiveHeight: false
|
||||
}
|
||||
|
||||
Popup.prototype.init = function(){
|
||||
|
|
@ -170,6 +171,9 @@
|
|||
if (this.options.size)
|
||||
modalDialog.addClass('size-' + this.options.size)
|
||||
|
||||
if (this.options.adaptiveHeight)
|
||||
modalDialog.addClass('adaptive-height')
|
||||
|
||||
return modal.append(modalDialog.append(modalContent))
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -811,6 +811,7 @@ var disabled=opts.element.prop("disabled");if(disabled===undefined)disabled=fals
|
|||
if(this.propertyObserver){this.propertyObserver.disconnect();this.propertyObserver=null;}
|
||||
this._sync=null;if(select2!==undefined){select2.container.remove();select2.liveRegion.remove();select2.dropdown.remove();element.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||false);if(this.elementTabIndex){element.attr({tabindex:this.elementTabIndex});}else{element.removeAttr("tabindex");}
|
||||
element.show();}
|
||||
var mask=$("#select2-drop-mask");if(mask.length!==0){mask.off("mousedown touchstart click");mask.remove();}
|
||||
cleanupJQueryElements.call(this,"container","liveRegion","dropdown","results","search");},optionToData:function(element){if(element.is("option")){return{id:element.prop("value"),text:element.text(),element:element.get(),css:element.attr("class"),disabled:element.prop("disabled"),locked:equal(element.attr("locked"),"locked")||equal(element.data("locked"),true)};}else if(element.is("optgroup")){return{text:element.attr("label"),children:[],element:element.get(),css:element.attr("class")};}},prepareOpts:function(opts){var element,select,idKey,ajaxUrl,self=this;element=opts.element;if(element.get(0).tagName.toLowerCase()==="select"){this.select=select=opts.element;}
|
||||
if(select){$.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in opts){throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.");}});}
|
||||
opts=$.extend({},{populateResults:function(container,results,query){var populate,id=this.opts.id,liveRegion=this.liveRegion;populate=function(results,container,depth){var i,l,result,selectable,disabled,compound,node,label,innerContainer,formatted;results=opts.sortResults(results,container,query);var nodes=[];for(i=0,l=results.length;i<l;i=i+1){result=results[i];disabled=(result.disabled===true);selectable=(!disabled)&&(id(result)!==undefined);compound=result.children&&result.children.length>0;node=$("<li></li>");node.addClass("select2-results-dept-"+depth);node.addClass("select2-result");node.addClass(selectable?"select2-result-selectable":"select2-result-unselectable");if(disabled){node.addClass("select2-disabled");}
|
||||
|
|
|
|||
|
|
@ -324,6 +324,10 @@ label {
|
|||
|
||||
.btn {
|
||||
margin-right: 10px;
|
||||
|
||||
&.no-margin-right {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ div.panel {
|
|||
border-bottom: 1px solid @panel-border-color;
|
||||
}
|
||||
|
||||
&.border-top {
|
||||
border-top: 1px solid @panel-border-color;
|
||||
}
|
||||
|
||||
&.triangle-down {
|
||||
position: relative;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,25 @@
|
|||
}
|
||||
|
||||
.modal-dialog {
|
||||
&.size-adaptive {
|
||||
width: 100%;
|
||||
padding-right: 50px;
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
&.adaptive-height {
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
|
||||
.modal-content {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
&.size-tiny { width: @popup-size-tiny; }
|
||||
&.size-small { width: @popup-size-small; }
|
||||
|
|
@ -52,6 +71,13 @@
|
|||
&.size-huge { width: @popup-size-huge; }
|
||||
&.size-giant { width: @popup-size-giant; }
|
||||
}
|
||||
@media (max-width: @screen-sm) {
|
||||
&.size-adaptive {
|
||||
width: auto;
|
||||
padding: 5px 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.control-popup {
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
There's a hack in line 885 in select2.js. The hack prevents DOM element leakage through the event that is not unbound in the destroy() method. --ab Mar 29 2015
|
||||
|
|
@ -878,6 +878,16 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
element.show();
|
||||
}
|
||||
|
||||
// Hack. This removes the mask element from the DOM when a select2 element is destroyed.
|
||||
// That prevents DOM leakage as the mask element keeps a reference to the select2 object
|
||||
// through the bound event. It should be safe to remove the mask as other select2 objects
|
||||
// will create a new mask element if needed.
|
||||
var mask = $("#select2-drop-mask");
|
||||
if (mask.length !== 0) {
|
||||
mask.off("mousedown touchstart click");
|
||||
mask.remove();
|
||||
}
|
||||
|
||||
cleanupJQueryElements.call(this,
|
||||
"container",
|
||||
"liveRegion",
|
||||
|
|
|
|||
|
|
@ -272,6 +272,8 @@ return [
|
|||
'move_destination' => 'Destination folder',
|
||||
'please_select_move_dest' => 'Please select a destination folder.',
|
||||
'move_dest_src_match' => 'Please select another destination folder.',
|
||||
'empty_library' => 'The Media Library is empty. Upload files or create folders to get started.'
|
||||
'empty_library' => 'The Media Library is empty. Upload files or create folders to get started.',
|
||||
'insert' => 'Insert',
|
||||
'crop_and_insert' => 'Crop & Insert'
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -356,6 +356,11 @@ class MediaManager extends WidgetBase
|
|||
$this->setSidebarVisible($visible);
|
||||
}
|
||||
|
||||
public function onLoadPopup()
|
||||
{
|
||||
return $this->makePartial('popup-body');
|
||||
}
|
||||
|
||||
//
|
||||
// Methods for th internal use
|
||||
//
|
||||
|
|
@ -508,7 +513,10 @@ class MediaManager extends WidgetBase
|
|||
protected function loadAssets()
|
||||
{
|
||||
$this->addCss('css/mediamanager.css', 'core');
|
||||
|
||||
// TODO: combine and load combined
|
||||
$this->addJs('js/mediamanager.js', 'core');
|
||||
$this->addJs('js/mediamanager.popup.js', 'core');
|
||||
}
|
||||
|
||||
protected function setViewMode($viewMode)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
+function ($) { "use strict";
|
||||
|
||||
$.oc.mediaManager = {}
|
||||
|
||||
var Base = $.oc.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
|
|
@ -77,6 +79,14 @@
|
|||
MediaManager.prototype.init = function() {
|
||||
this.itemListElement = this.$el.find('[data-control="item-list"]').get(0)
|
||||
this.scrollContentElement = this.itemListElement.querySelector('.scroll-wrapper')
|
||||
|
||||
if (this.options.bottomToolbar) {
|
||||
this.$el.find('[data-control="bottom-toolbar"]').removeClass('hide')
|
||||
|
||||
if (this.options.cropAndInsertButton)
|
||||
this.$el.find('[data-command="crop-and-insert"]').removeClass('hide')
|
||||
}
|
||||
|
||||
this.registerHandlers()
|
||||
|
||||
this.updateSidebarPreview()
|
||||
|
|
@ -1054,7 +1064,9 @@
|
|||
alias: '',
|
||||
deleteEmpty: 'Please select files to delete.',
|
||||
deleteConfirm: 'Do you really want to delete the selected file(s)?',
|
||||
moveEmpty: 'Please select files to move.'
|
||||
moveEmpty: 'Please select files to move.',
|
||||
bottomToolbar: false,
|
||||
cropAndInsertButton: false
|
||||
}
|
||||
|
||||
var old = $.fn.mediaManager
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Media manager popup
|
||||
*
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
|
||||
var Base = $.oc.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
var MediaManagerPopup = function(options) {
|
||||
this.options = $.extend({}, MediaManagerPopup.DEFAULTS, options)
|
||||
|
||||
Base.call(this)
|
||||
|
||||
this.show()
|
||||
}
|
||||
|
||||
MediaManagerPopup.prototype = Object.create(BaseProto)
|
||||
MediaManagerPopup.prototype.constructor = MediaManagerPopup
|
||||
|
||||
MediaManagerPopup.prototype.show = function() {
|
||||
var $popupRootElement = $('<div/>')
|
||||
|
||||
if (this.options.alias === undefined)
|
||||
throw new Error('Media Manager popup option "alias" is not set.')
|
||||
|
||||
$popupRootElement.popup({
|
||||
size: 'adaptive',
|
||||
adaptiveHeight: true,
|
||||
handler: this.options.alias + '::onLoadPopup'
|
||||
})
|
||||
}
|
||||
|
||||
MediaManagerPopup.DEFAULTS = {
|
||||
alias: undefined
|
||||
}
|
||||
|
||||
$.oc.mediaManager.popup = MediaManagerPopup
|
||||
}(window.jQuery);
|
||||
|
|
@ -24,10 +24,9 @@
|
|||
</div>
|
||||
<div class="layout-row">
|
||||
<!-- Main area -->
|
||||
<div class="layout">
|
||||
<div class="layout-cell ">
|
||||
<div class="layout">
|
||||
<div class="layout-row">
|
||||
<div class="layout">
|
||||
<!-- Main area - list -->
|
||||
<div data-control="item-list">
|
||||
<div class="control-scrollpad">
|
||||
|
|
@ -38,17 +37,44 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-row min-size">
|
||||
<!-- Main area - bottom toolbar -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-cell width-300 panel border-left no-padding <?= !$sidebarVisible ? 'hide' : null ?>" data-control="preview-sidebar">
|
||||
<!-- Right sidebar -->
|
||||
<?= $this->makePartial('right-sidebar') ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-row min-size hide" data-control="bottom-toolbar">
|
||||
<div class="panel no-padding-bottom border-top">
|
||||
<div class="form-buttons">
|
||||
<div class="pull-right">
|
||||
<button
|
||||
type="button"
|
||||
data-command="insert"
|
||||
class="btn btn-primary">
|
||||
<?= e(trans('cms::lang.media.insert')) ?>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-command="crop-and-insert"
|
||||
class="btn btn-primary hide">
|
||||
<?= e(trans('cms::lang.media.crop_and_insert')) ?>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-command="insert"
|
||||
class="btn btn-default no-margin-right">
|
||||
<?= e(trans('backend::lang.form.cancel')) ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<?= Form::open(['class'=>'layout', 'onsubmit'=>'return false']) ?>
|
||||
<?= $this->render() ?>
|
||||
<?= Form::close() ?>
|
||||
|
|
@ -14,7 +14,6 @@ if (window.jQuery === undefined)
|
|||
var Request = function (element, handler, options) {
|
||||
var $el = this.$el = $(element);
|
||||
this.options = options || {};
|
||||
|
||||
/*
|
||||
* Validate handler name
|
||||
*/
|
||||
|
|
@ -25,13 +24,6 @@ if (window.jQuery === undefined)
|
|||
if (!handler.match(/^(?:\w+\:{2})?on*/))
|
||||
throw new Error('Invalid handler name. The correct handler name format is: "onEvent".')
|
||||
|
||||
/*
|
||||
* Detect if page is refreshed to stop any active ajax errors
|
||||
*/
|
||||
|
||||
var isUnloading = false
|
||||
$(window).on('beforeunload', function() { isUnloading = true })
|
||||
|
||||
/*
|
||||
* Custom function, requests confirmation from the user
|
||||
*/
|
||||
|
|
@ -59,6 +51,10 @@ if (window.jQuery === undefined)
|
|||
if (options.confirm && !handleConfirmMessage(options.confirm))
|
||||
return
|
||||
|
||||
/*
|
||||
* Prepare the options and execute the request
|
||||
*/
|
||||
|
||||
var
|
||||
form = $el.closest('form'),
|
||||
context = { handler: handler, options: options },
|
||||
|
|
@ -71,7 +67,7 @@ if (window.jQuery === undefined)
|
|||
|
||||
var data = [form.serialize()]
|
||||
|
||||
$.each($el.parents('[data-request-data]').toArray().reverse(), function(){
|
||||
$.each($el.parents('[data-request-data]').toArray().reverse(), function extendReque(){
|
||||
data.push($.param(paramToObj('data-request-data', $(this).data('request-data'))))
|
||||
})
|
||||
|
||||
|
|
@ -120,7 +116,7 @@ if (window.jQuery === undefined)
|
|||
var errorMsg,
|
||||
updatePromise = $.Deferred()
|
||||
|
||||
if (isUnloading || errorThrown == 'abort')
|
||||
if ((window.ocUnloading !== undefined && window.ocUnloading) || errorThrown == 'abort')
|
||||
return
|
||||
|
||||
/*
|
||||
|
|
@ -227,7 +223,7 @@ if (window.jQuery === undefined)
|
|||
*/
|
||||
if (data['X_OCTOBER_ERROR_FIELDS']) {
|
||||
var isFirstInvalidField = true
|
||||
$.each(data['X_OCTOBER_ERROR_FIELDS'], function(fieldName, fieldMessages){
|
||||
$.each(data['X_OCTOBER_ERROR_FIELDS'], function focusErrorField(fieldName, fieldMessages){
|
||||
var fieldElement = form.find('[name="'+fieldName+'"], [name="'+fieldName+'[]"], [name$="['+fieldName+']"], [name$="['+fieldName+'][]"]').filter(':enabled').first()
|
||||
if (fieldElement.length > 0) {
|
||||
|
||||
|
|
@ -246,7 +242,7 @@ if (window.jQuery === undefined)
|
|||
* Handle asset injection
|
||||
*/
|
||||
if (data['X_OCTOBER_ASSETS']) {
|
||||
assetManager.load(data['X_OCTOBER_ASSETS'], function(){
|
||||
assetManager.load(data['X_OCTOBER_ASSETS'], function assetsLoaded(){
|
||||
updatePromise.resolve()
|
||||
})
|
||||
}
|
||||
|
|
@ -362,16 +358,16 @@ if (window.jQuery === undefined)
|
|||
}
|
||||
}
|
||||
|
||||
$(document).on('change', 'select[data-request], input[type=radio][data-request], input[type=checkbox][data-request]', function(){
|
||||
$(document).on('change', 'select[data-request], input[type=radio][data-request], input[type=checkbox][data-request]', function documentOnChange(){
|
||||
$(this).request()
|
||||
})
|
||||
|
||||
$(document).on('click', 'a[data-request], button[data-request], input[type=button][data-request], input[type=submit][data-request]', function(){
|
||||
$(document).on('click', 'a[data-request], button[data-request], input[type=button][data-request], input[type=submit][data-request]', function documentOnClick(){
|
||||
$(this).request()
|
||||
return false
|
||||
})
|
||||
|
||||
$(document).on('keydown', 'input[type=text][data-request], input[type=submit][data-request], input[type=password][data-request]', function(e){
|
||||
$(document).on('keydown', 'input[type=text][data-request], input[type=submit][data-request], input[type=password][data-request]', function documentOnKeydown(e){
|
||||
if (e.keyCode == 13) {
|
||||
if (this.dataTrackInputTimer !== undefined)
|
||||
window.clearTimeout(this.dataTrackInputTimer)
|
||||
|
|
@ -381,7 +377,7 @@ if (window.jQuery === undefined)
|
|||
}
|
||||
})
|
||||
|
||||
$(document).on('keyup', 'input[type=text][data-request][data-track-input], input[type=password][data-request][data-track-input]', function(e){
|
||||
$(document).on('keyup', 'input[type=text][data-request][data-track-input], input[type=password][data-request][data-track-input]', function documentOnKeyup(e){
|
||||
var
|
||||
$el = $(this),
|
||||
lastValue = $el.data('oc.lastvalue')
|
||||
|
|
@ -404,11 +400,15 @@ if (window.jQuery === undefined)
|
|||
}, interval)
|
||||
})
|
||||
|
||||
$(document).on('submit', '[data-request]', function(){
|
||||
$(document).on('submit', '[data-request]', function documentOnsubmit(){
|
||||
$(this).request()
|
||||
return false
|
||||
})
|
||||
|
||||
$(window).on('beforeunload', function documentOnBeforeunload() {
|
||||
window.ocUnloading = true
|
||||
})
|
||||
|
||||
/*
|
||||
* Invent our own event that unifies document.ready with window.ajaxUpdateComplete
|
||||
*
|
||||
|
|
@ -416,11 +416,11 @@ if (window.jQuery === undefined)
|
|||
* $(document).on('render', function(){ })
|
||||
*/
|
||||
|
||||
$(document).ready(function(){
|
||||
$(document).ready(function triggerRenderOnReady(){
|
||||
$(document).trigger('render')
|
||||
})
|
||||
|
||||
$(window).on('ajaxUpdateComplete', function() {
|
||||
$(window).on('ajaxUpdateComplete', function triggerRenderOnAjaxUpdateComplete() {
|
||||
$(document).trigger('render')
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue