diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 461080942..49cb0a604 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -166,8 +166,8 @@ .control-filelist ul{padding:0;margin:0} .control-filelist ul li{font-weight:300;line-height:150%;position:relative;list-style:none} .control-filelist ul li a:hover{background:#dddddd} -.control-filelist ul li.active a{background:#dddddd;position:relative} -.control-filelist ul li.active a:after{position:absolute;height:100%;width:4px;left:0;top:0;background:#e67e22;display:block;content:' '} +.control-filelist ul li.active > a{background:#dddddd;position:relative} +.control-filelist ul li.active > a:after{position:absolute;height:100%;width:4px;left:0;top:0;background:#e67e22;display:block;content:' '} .control-filelist ul li a{display:block;padding:10px 40px 10px 20px;outline:none} .control-filelist ul li a:hover,.control-filelist ul li a:focus,.control-filelist ul li a:active{text-decoration:none} .control-filelist ul li a span{display:block} @@ -197,11 +197,14 @@ .control-filelist ul li .checkbox{position:absolute;top:13px;right:17px} .control-filelist ul li .checkbox label{margin-right:0} .control-filelist ul li .checkbox label:before{border-color:#cccccc} +.control-filelist.single-line ul li a span.title{text-overflow:ellipsis;overflow:hidden;white-space:nowrap} .control-filelist.hero ul li{background:#ffffff;border-bottom:none} .control-filelist.hero ul li > a{padding:16px 45px 15px 50px;font-size:13px;border-bottom:1px solid #ecf0f1} .control-filelist.hero ul li > a span.title{font-size:13px;font-weight:600;color:#2b3e50} +.control-filelist.hero ul li > a .list-icon{position:absolute;left:14px;top:20px;font-size:22px;color:#b7c0c2} .control-filelist.hero ul li > a:hover{background:#58b6f7;border-bottom:1px solid #58b6f7 !important} .control-filelist.hero ul li > a:hover span.title,.control-filelist.hero ul li > a:hover span.description{color:#ffffff !important} +.control-filelist.hero ul li > a:hover .list-icon{color:#ffffff !important} .control-filelist.hero ul li .checkbox{top:17px;right:17px} .control-filelist.hero ul li.active > a{border-bottom:1px solid #dddddd} .control-filelist.hero ul li.active > a:after{top:-1px;bottom:-1px;height:auto} @@ -209,7 +212,15 @@ .control-filelist.hero ul li.active > a > span.borders:before{top:-1px} .control-filelist.hero ul li.active > a:hover > span.borders:before{background-color:#58b6f7} .control-filelist.hero ul li > h4{padding-top:7px;padding-bottom:6px;border-bottom:1px solid #ecf0f1} +.control-filelist.hero ul li > div.controls{display:none;position:absolute;right:16px;top:15px} +.control-filelist.hero ul li > div.controls > a.control{width:16px;height:23px;background:transparent;overflow:hidden;display:inline-block;color:#ffffff !important;padding:0} +.control-filelist.hero ul li > div.controls > a.control:before{font-size:17px} +.control-filelist.hero ul li:hover > div.controls{display:block} .control-filelist.hero ul > li.group > ul > li > a{padding-left:66px} +.control-filelist.hero.single-level ul li:hover{background:#58b6f7} +.control-filelist.hero.single-level ul li:hover > a{background:#58b6f7;border-bottom:1px solid #58b6f7 !important} +.control-filelist.hero.single-level ul li:hover > a span.title,.control-filelist.hero.single-level ul li:hover > a span.description{color:#ffffff !important} +.control-filelist.hero.single-level ul li:hover > a .list-icon{color:#ffffff !important} .touch .control-filelist li:not(.active) a:hover{background:transparent} .control-scrollpanel{position:relative;background:#ecf0f1} .control-scrollpanel .control-scrollbar.vertical > .scrollbar-scrollbar{right:0} @@ -1629,7 +1640,7 @@ ul.status-list li span.status.info{background:#5bc0de} .control-toolbar .toolbar-item .btn-group .dropdown.last > .btn{border-bottom-right-radius:2px !important;border-top-right-radius:2px !important} .control-toolbar input.form-control[type=text]{height:auto;padding:8px 10px} [data-control=toolbar]{white-space:nowrap;width:100%;overflow:hidden} -#layout-side-panel .control-toolbar{padding:20px 0 20px 20px} +#layout-side-panel .control-toolbar,.panel-contents .control-toolbar{padding:20px 0 20px 20px} div.scoreboard{position:relative;padding:0} div.scoreboard:after,div.scoreboard:before{display:none;position:absolute;top:50%;margin-top:-7px;height:9px;font-size:10px;color:#bbbbbb} div.scoreboard:before{left:-6px;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f104"} @@ -3194,6 +3205,10 @@ body.mainmenu-open .mainmenu-collapsed ul{position:fixed;left:0;top:10px;bottom: #layout-side-panel .fix-button{position:absolute;right:2px;top:1px;display:block;width:20px;height:20px;font-size:13px} #layout-side-panel .fix-button i{display:block;text-align:center;margin-top:5px;color:#aaaaaa} #layout-side-panel .fix-button:hover{text-decoration:none;opacity:1 !important;filter:alpha(opacity=100) !important} +#layout-side-panel .fix-button-content-header .fix-button{top:9px;right:7px} +#layout-side-panel .fix-button-content-header .fix-button i{color:#eeeeee} +#layout-side-panel .sidepanel-content-header{background:#95a5a6;color:white;font-size:14px;padding:10px 15px;position:relative} +#layout-side-panel .sidepanel-content-header:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #95a5a6;border-bottom-width:0;position:absolute;left:14px;bottom:-8px} body.side-panel-not-fixed #layout-side-panel{display:none} body.side-panel-not-fixed #layout-side-panel .fix-button{opacity:0.5;filter:alpha(opacity=50)} body.display-side-panel #layout-side-panel{display:block;position:absolute;z-index:500;width:300px;-webkit-box-shadow:2px 0px 2px 0 rgba(0,0,0,0.3);box-shadow:2px 0px 2px 0 rgba(0,0,0,0.3)} @@ -3342,6 +3357,13 @@ html.csstransitions body.outer.preload .outer-form-container{-webkit-transform:s .fancy-layout .field-richeditor{border:none;border-left:1px solid #e0e0e0 !important} .fancy-layout .field-richeditor,.fancy-layout .field-richeditor .redactor_box,.fancy-layout .field-richeditor .redactor_toolbar{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border-top-right-radius:0;border-top-left-radius:0} .fancy-layout .field-richeditor .redactor-box textarea{background:white;padding:20px !important;color:#333333;font-size:14px} -.fancy-layout .secondary-content-tabs .field-richeditor .redactor-box .redactor-toolbar{margin:20px 20px 0 20px!important;-webkit-border-radius:3px !important;-moz-border-radius:3px !important;border-radius:3px !important} +.fancy-layout .secondary-content-tabs .field-richeditor .redactor-box .redactor-toolbar{margin:20px 20px 0 20px !important;-webkit-border-radius:3px !important;-moz-border-radius:3px !important;border-radius:3px !important} body.side-panel-not-fixed .fancy-layout .field-richeditor{border-left:none} -html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-container .loading-indicator > span{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;background-image:url(../../../../../modules/system/assets/ui/images/loader-white.svg);background-size:20px 20px} \ No newline at end of file +html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-container .loading-indicator > span{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;background-image:url('../../../system/assets/ui/images/loader-white.svg');background-size:20px 20px} +.flyout-container > .flyout{overflow:hidden;width:0;left:0 !important;-webkit-transition:width 0.1s;transition:width 0.1s} +.flyout-overlay{width:100%;height:100%;top:0;z-index:5000;position:absolute;background-color:rgba(0,0,0,0);-webkit-transition:background-color 0.3s;transition:background-color 0.3s} +.flyout-toggle{position:absolute;top:20px;left:0;width:23px;height:25px;background:#2b3e50;cursor:pointer;border-bottom-right-radius:4px;border-top-right-radius:4px;color:#bdc3c7;font-size:10px} +.flyout-toggle i{margin:7px 0 0 6px;display:inline-block} +.flyout-toggle:hover i{color:#ffffff} +body.flyout-visible{overflow:hidden} +body.flyout-visible .flyout-overlay{background-color:rgba(0,0,0,0.3)} diff --git a/modules/backend/assets/js/october-min.js b/modules/backend/assets/js/october-min.js index 8090547ea..8af52ee68 100644 --- a/modules/backend/assets/js/october-min.js +++ b/modules/backend/assets/js/october-min.js @@ -4083,7 +4083,10 @@ this.$src=$(options.inputPreset,parent),this.$src.on('keyup',function(){if(self. return $el.val(prefix+self.formatValue())}) this.$el.on('change',function(){self.cancelled=true})} -InputPreset.prototype.formatValue=function(){if(this.options.inputPresetType=='camel') +InputPreset.prototype.formatNamespace=function(){var value=toCamel(this.$src.val()) +return value.substr(0,1).toUpperCase()+value.substr(1)} +InputPreset.prototype.formatValue=function(){if(this.options.inputPresetType=='namespace'){return this.formatNamespace()} +if(this.options.inputPresetType=='camel') var value=toCamel(this.$src.val()) else{var value=slugify(this.$src.val())} if(this.options.inputPresetType=='url') @@ -4368,8 +4371,12 @@ this.init()} Sortable.prototype=Object.create(BaseProto) Sortable.prototype.constructor=Sortable Sortable.prototype.init=function(){this.$el.one('dispose-control',this.proxy(this.dispose)) -var sortableOptions={onDragStart:this.proxy(this.onDragStart),onDrag:this.proxy(this.onDrag),onDrop:this.proxy(this.onDrop)} -this.$el.jqSortable($.extend(sortableOptions,this.options))} +var +self=this,sortableOverrides={},sortableDefaults={onDragStart:this.proxy(this.onDragStart),onDrag:this.proxy(this.onDrag),onDrop:this.proxy(this.onDrop)} +if(this.options.onDragStart){sortableOverrides.onDragStart=function($item,container,_super,event){self.options.onDragStart($item,container,sortableDefaults.onDragStart,event)}} +if(this.options.onDrag){sortableOverrides.onDrag=function($item,position,_super,event){self.options.onDrag($item,position,sortableDefaults.onDrag,event)}} +if(this.options.onDrop){sortableOverrides.onDrop=function($item,container,_super,event){self.options.onDrop($item,container,sortableDefaults.onDrop,event)}} +this.$el.jqSortable($.extend({},sortableDefaults,this.options,sortableOverrides))} Sortable.prototype.dispose=function(){this.$el.jqSortable('destroy') this.$el.off('dispose-control',this.proxy(this.dispose)) this.$el.removeData('oc.sortable') @@ -4377,8 +4384,6 @@ this.$el=null this.options=null this.cursorAdjustment=null BaseProto.dispose.call(this)} -Sortable.prototype.onDrag=function($item,position,_super,event){if(this.cursorAdjustment){$item.css({left:position.left-this.cursorAdjustment.left,top:position.top-this.cursorAdjustment.top})} -else{$item.css(position)}} Sortable.prototype.onDragStart=function($item,container,_super,event){var offset=$item.offset(),pointer=container.rootGroup.pointer if(pointer){this.cursorAdjustment={left:pointer.left-offset.left,top:pointer.top-offset.top}} else{this.cursorAdjustment=null} @@ -4388,6 +4393,8 @@ $item.addClass('dragged') $('body').addClass('dragging') if(this.options.useAnimation){$item.data('oc.animated',true)} if(this.options.usePlaceholderClone){$(container.rootGroup.placeholder).html($item.html())}} +Sortable.prototype.onDrag=function($item,position,_super,event){if(this.cursorAdjustment){$item.css({left:position.left-this.cursorAdjustment.left,top:position.top-this.cursorAdjustment.top})} +else{$item.css(position)}} Sortable.prototype.onDrop=function($item,container,_super,event){$item.removeClass('dragged').removeAttr('style') $('body').removeClass('dragging') if($item.data('oc.animated')){$item.hide().slideDown(200)}} @@ -4953,12 +4960,12 @@ return this} $(document).render(function(){$('[data-control=scrollbar]').scrollbar()})}(window.jQuery);+function($){"use strict";var FileList=function(element,options){this.options=options this.$el=$(element) this.init();} -FileList.DEFAULTS={} +FileList.DEFAULTS={ignoreItemClick:false} FileList.prototype.init=function(){var self=this this.$el.on('click','li.group > h4 > a, li.group > div.group',function(){self.toggleGroup($(this).closest('li')) -return false;});this.$el.on('click','li.item > a',function(event){var e=$.Event('open.oc.list',{relatedTarget:$(this).parent().get(0),clickEvent:event}) +return false;});if(!this.options.ignoreItemClick){this.$el.on('click','li.item > a',function(event){var e=$.Event('open.oc.list',{relatedTarget:$(this).parent().get(0),clickEvent:event}) self.$el.trigger(e,this) -return false}) +return false})} this.$el.on('ajaxUpdate',$.proxy(this.update,this))} FileList.prototype.toggleGroup=function(group){var $group=$(group);$group.attr('data-status')=='expanded'?this.collapseGroup($group):this.expandGroup($group)} FileList.prototype.collapseGroup=function(group){var diff --git a/modules/backend/assets/js/october.filelist.js b/modules/backend/assets/js/october.filelist.js index 998abd7c2..97963724e 100644 --- a/modules/backend/assets/js/october.filelist.js +++ b/modules/backend/assets/js/october.filelist.js @@ -30,7 +30,7 @@ } FileList.DEFAULTS = { - + ignoreItemClick: false } FileList.prototype.init = function (){ @@ -42,12 +42,14 @@ return false; }); - this.$el.on('click', 'li.item > a', function(event) { - var e = $.Event('open.oc.list', {relatedTarget: $(this).parent().get(0), clickEvent: event}) - self.$el.trigger(e, this) + if (!this.options.ignoreItemClick) { + this.$el.on('click', 'li.item > a', function(event) { + var e = $.Event('open.oc.list', {relatedTarget: $(this).parent().get(0), clickEvent: event}) + self.$el.trigger(e, this) - return false - }) + return false + }) + } this.$el.on('ajaxUpdate', $.proxy(this.update, this)) } diff --git a/modules/backend/assets/js/october.flyout.js b/modules/backend/assets/js/october.flyout.js new file mode 100644 index 000000000..22f2e4d1c --- /dev/null +++ b/modules/backend/assets/js/october.flyout.js @@ -0,0 +1,222 @@ +/* + * Flyout plugin. + */ ++function ($) { "use strict"; + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + // SCROLLPAD CLASS DEFINITION + // ============================ + + var Flyout = function(element, options) { + this.$el = $(element) + this.$overlay = null + this.options = options + + Base.call(this) + + this.init() + } + + Flyout.prototype = Object.create(BaseProto) + Flyout.prototype.constructor = Flyout + + Flyout.prototype.dispose = function() { + this.removeOverlay() + this.$el.removeData('oc.flyout') + this.$el = null + + if (this.options.flyoutToggle) { + this.removeToggle() + } + + BaseProto.dispose.call(this) + } + + Flyout.prototype.show = function() { + var $cells = this.$el.find('> .layout-cell'), + $flyout = this.$el.find('> .flyout') + + this.removeOverlay() + + for (var i = 0; i < $cells.length; i++) { + var $cell = $($cells[i]), + width = $cell.width() + + $cell.css('width', width) + } + + this.createOverlay() + + window.setTimeout(this.proxy(this.setBodyClass), 1) + $flyout.css('width', this.options.flyoutWidth) + + this.hideToggle() + } + + Flyout.prototype.hide = function() { + var $cells = this.$el.find('> .layout-cell'), + $flyout = this.$el.find('> .flyout') + + for (var i = 0; i < $cells.length; i++) { + var $cell = $($cells[i]) + + $cell.css('width', '') + } + + $flyout.css('width', 0) + + window.setTimeout(this.proxy(this.removeBodyClass), 1) + window.setTimeout(this.proxy(this.removeOverlayAndShowToggle), 300) + } + + // FLYOUT INTERNAL METHODS + // ============================ + + Flyout.prototype.init = function() { + this.build() + } + + Flyout.prototype.build = function() { + if (this.options.flyoutToggle) { + this.buildToggle() + } + } + + Flyout.prototype.buildToggle = function() { + var $toggleContainer = $(this.options.flyoutToggle), + $toggle = $('
') + + $toggle.on('click', this.proxy(this.show)) + $toggleContainer.append($toggle) + } + + Flyout.prototype.removeToggle = function() { + var $toggle = this.getToggle() + + $toggle.off('click', this.proxy(this.show)) + $toggle.remove() + } + + Flyout.prototype.hideToggle = function() { + if (!this.options.flyoutToggle) { + return + } + + this.getToggle().hide() + } + + Flyout.prototype.showToggle = function() { + if (!this.options.flyoutToggle) { + return + } + + this.getToggle().show() + } + + Flyout.prototype.getToggle = function() { + var $toggleContainer = $(this.options.flyoutToggle) + + return $toggleContainer.find('.flyout-toggle') + } + + Flyout.prototype.setBodyClass = function() { + $(document.body).addClass('flyout-visible') + } + + Flyout.prototype.removeBodyClass = function() { + $(document.body).removeClass('flyout-visible') + } + + Flyout.prototype.createOverlay = function() { + this.$overlay = $('
') + + var position = this.$el.offset() + + this.$overlay.css({ + top: position.top, + left: this.options.flyoutWidth + }) + + this.$overlay.on('click', this.proxy(this.onOverlayClick)) + $(document.body).on('keydown', this.proxy(this.onDocumentKeydown)) + + $(document.body).append(this.$overlay) + } + + Flyout.prototype.removeOverlay = function() { + if (!this.$overlay) { + return + } + + this.$overlay.off('click', this.proxy(this.onOverlayClick)) + $(document.body).off('keydown', this.proxy(this.onDocumentKeydown)) + + this.$overlay.remove() + this.$overlay = null + } + + Flyout.prototype.removeOverlayAndShowToggle = function() { + this.removeOverlay() + this.showToggle() + } + + // EVENT HANDLERS + // ============================ + + Flyout.prototype.onOverlayClick = function() { + this.hide() + } + + Flyout.prototype.onDocumentKeydown = function(ev) { + if (ev.which == 27) { + this.hide(); + } + } + + // FLYOUT PLUGIN DEFINITION + // ============================ + + Flyout.DEFAULTS = { + flyoutWidth: 400, + flyoutToggle: null + } + + var old = $.fn.flyout + + $.fn.flyout = function (option) { + var args = Array.prototype.slice.call(arguments, 1), + result = undefined + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.flyout') + var options = $.extend({}, Flyout.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.flyout', (data = new Flyout(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.flyout.Constructor = Flyout + + // FLYOUT NO CONFLICT + // ================= + + $.fn.flyout.noConflict = function () { + $.fn.flyout = old + return this + } + + // FLYOUT DATA-API + // =============== + + // Currently flyouts don't use the document render event + // and can't be created dynamically (performance considerations). + $(document).on('ready', function(){ + $('div[data-control=flyout]').flyout() + }) +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/less/controls/filelist.less b/modules/backend/assets/less/controls/filelist.less index 697a1a442..66511f4b7 100644 --- a/modules/backend/assets/less/controls/filelist.less +++ b/modules/backend/assets/less/controls/filelist.less @@ -41,7 +41,7 @@ background: @color-list-hover; } - &.active a { + &.active > a { background: @color-list-active; position: relative; &:after { @@ -167,7 +167,29 @@ } } + &.single-line { + ul { + li a span.title { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + } + &.hero { + .a-hover() { + background: @color-filelist-hero-hover-bg; + border-bottom: 1px solid @color-filelist-hero-hover-bg!important; + span.title, span.description { + color: @color-filelist-hero-hover-text!important; + } + + .list-icon { + color: @color-filelist-hero-hover-text!important; + } + } + ul { li { background: @color-filelist-hero-item-bg; @@ -184,12 +206,16 @@ color: @color-filelist-title-hero; } + .list-icon { + position: absolute; + left: 14px; + top: 20px; + font-size: 22px; + color: #b7c0c2; + } + &:hover { - background: @color-filelist-hero-hover-bg; - border-bottom: 1px solid @color-filelist-hero-hover-bg!important; - span.title, span.description { - color: @color-filelist-hero-hover-text!important; - } + .a-hover(); } } @@ -233,6 +259,31 @@ padding-bottom: 6px; border-bottom: 1px solid @color-panel-light; } + + > div.controls { + display: none; + position: absolute; + right: 16px; + top: 15px; + + > a.control { + width: 16px; + height: 23px; + background: transparent; + overflow: hidden; + display: inline-block; + color: @color-filelist-hero-hover-text!important; + padding: 0; + + &:before { + font-size: 17px; + } + } + } + + &:hover > div.controls { + display: block; + } } > li.group { @@ -241,6 +292,16 @@ } } } + + &.single-level { + ul li:hover { + background: @color-filelist-hero-hover-bg; + + > a { + .a-hover(); + } + } + } } } diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less index c7f0bbc58..0abb8e833 100644 --- a/modules/backend/assets/less/core/variables.less +++ b/modules/backend/assets/less/core/variables.less @@ -72,6 +72,7 @@ @color-scrollbar-thumb: #aaa; @color-scrollpanel-border: #efefef; @color-scrollpanel-fix-button: #aaaaaa; +@color-scrollpanel-fix-button-light: #eeeeee; @color-scroll-indicator: #bbbbbb; @color-richeditor-toolbar: #dddddd; diff --git a/modules/backend/assets/less/layout/fancylayout.less b/modules/backend/assets/less/layout/fancylayout.less index d90cb338c..f9853a496 100644 --- a/modules/backend/assets/less/layout/fancylayout.less +++ b/modules/backend/assets/less/layout/fancylayout.less @@ -544,7 +544,7 @@ .field-richeditor { border: none; - border-left: 1px solid @color-form-field-border!important; + border-left: 1px solid @color-form-field-border !important; &, .redactor_box, .redactor_toolbar { .border-radius(0); @@ -553,7 +553,7 @@ .redactor-box textarea { background: white; - padding: 20px!important; + padding: 20px !important; color: #333333; font-size: 14px; } @@ -561,8 +561,8 @@ .secondary-content-tabs .field-richeditor { .redactor-box .redactor-toolbar { - margin: 20px 20px 0 20px!important; - .border-radius(3px)!important; + margin: 20px 20px 0 20px !important; + .border-radius(3px) !important; } } } @@ -581,7 +581,7 @@ html.cssanimations { .loading-indicator-container { .loading-indicator > span { .animation(spin 1s linear infinite); - background-image: url(../../../../../modules/system/assets/ui/images/loader-white.svg); + background-image: url('../../../system/assets/ui/images/loader-white.svg'); background-size: 20px 20px; } } diff --git a/modules/backend/assets/less/layout/flyout.less b/modules/backend/assets/less/layout/flyout.less new file mode 100644 index 000000000..a276396d0 --- /dev/null +++ b/modules/backend/assets/less/layout/flyout.less @@ -0,0 +1,48 @@ +.flyout-container { + > .flyout { + overflow: hidden; + width: 0; + left: 0!important; + .transition(width 0.1s); + } +} + +.flyout-overlay { + width: 100%; + height: 100%; + top: 0; + z-index: 5000; + position: absolute; + background-color: rgba(0,0,0,0); + .transition(background-color 0.3s); +} + +.flyout-toggle { + position: absolute; + top: 20px; + left: 0; + width: 23px; + height: 25px; + background: #2b3e50; + cursor: pointer; + .border-right-radius(4px); + color: #bdc3c7; + font-size: 10px; + + i { + margin: 7px 0 0 6px; + display: inline-block; + } + + &:hover i { + color: #ffffff; + } +} + +body.flyout-visible { + overflow: hidden; + + .flyout-overlay { + background-color: rgba(0,0,0,0.3); + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/layout/sidepanel.less b/modules/backend/assets/less/layout/sidepanel.less index 4288e79c3..d154528d3 100644 --- a/modules/backend/assets/less/layout/sidepanel.less +++ b/modules/backend/assets/less/layout/sidepanel.less @@ -24,6 +24,30 @@ .opacity(1)!important; } } + + .fix-button-content-header .fix-button { + top: 9px; + right: 7px; + + i { + color: @color-scrollpanel-fix-button-light; + } + } + + .sidepanel-content-header { + background: #95a5a6; + color: white; + font-size: 14px; + padding: 10px 15px; + position: relative; + + &:after { + .triangle(down, 15px, 8px, #95a5a6); + position: absolute; + left: 14px; + bottom: -8px; + } + } } body.side-panel-not-fixed { diff --git a/modules/backend/assets/less/october.less b/modules/backend/assets/less/october.less index 7dadd4d85..4bc1adfcf 100644 --- a/modules/backend/assets/less/october.less +++ b/modules/backend/assets/less/october.less @@ -59,4 +59,5 @@ @import "layout/footer.less"; @import "layout/outerlayout.less"; @import "layout/fancylayout.less"; +@import "layout/flyout.less"; diff --git a/modules/backend/layouts/_head.htm b/modules/backend/layouts/_head.htm index 91b4a7616..72c0d1067 100644 --- a/modules/backend/layouts/_head.htm +++ b/modules/backend/layouts/_head.htm @@ -14,6 +14,8 @@ + + makeAssets() ?> makeLayoutPartial('custom_styles') ?> \ No newline at end of file diff --git a/modules/backend/layouts/default.htm b/modules/backend/layouts/default.htm index 53ae0febd..c800347fd 100644 --- a/modules/backend/layouts/default.htm +++ b/modules/backend/layouts/default.htm @@ -12,8 +12,19 @@ makeLayoutPartial('mainmenu') ?>
+ +
-
+
+ data-control="flyout" + data-flyout-width="400" + data-flyout-toggle="#layout-sidenav" + + > + +
+ makeLayoutPartial('sidenav') ?> diff --git a/modules/system/assets/ui/js/drag.sort.js b/modules/system/assets/ui/js/drag.sort.js index 17017abd3..fc9df56ac 100644 --- a/modules/system/assets/ui/js/drag.sort.js +++ b/modules/system/assets/ui/js/drag.sort.js @@ -28,13 +28,37 @@ Sortable.prototype.init = function() { this.$el.one('dispose-control', this.proxy(this.dispose)) - var sortableOptions = { - onDragStart: this.proxy(this.onDragStart), - onDrag: this.proxy(this.onDrag), - onDrop: this.proxy(this.onDrop) + var + self = this, + sortableOverrides = {}, + sortableDefaults = { + onDragStart: this.proxy(this.onDragStart), + onDrag: this.proxy(this.onDrag), + onDrop: this.proxy(this.onDrop) + } + + /* + * Override _super object for each option/event + */ + if (this.options.onDragStart) { + sortableOverrides.onDragStart = function ($item, container, _super, event) { + self.options.onDragStart($item, container, sortableDefaults.onDragStart, event) + } } - this.$el.jqSortable($.extend(sortableOptions, this.options)) + if (this.options.onDrag) { + sortableOverrides.onDrag = function ($item, position, _super, event) { + self.options.onDrag($item, position, sortableDefaults.onDrag, event) + } + } + + if (this.options.onDrop) { + sortableOverrides.onDrop = function ($item, container, _super, event) { + self.options.onDrop($item, container, sortableDefaults.onDrop, event) + } + } + + this.$el.jqSortable($.extend({}, sortableDefaults, this.options, sortableOverrides)) } Sortable.prototype.dispose = function() { @@ -47,24 +71,6 @@ BaseProto.dispose.call(this) } - Sortable.prototype.onDrag = function ($item, position, _super, event) { - if (this.cursorAdjustment) { - /* - * Relative cursor position - */ - $item.css({ - left: position.left - this.cursorAdjustment.left, - top: position.top - this.cursorAdjustment.top - }) - } - else { - /* - * Default behavior - */ - $item.css(position) - } - } - Sortable.prototype.onDragStart = function ($item, container, _super, event) { /* * Relative cursor position @@ -109,6 +115,24 @@ } } + Sortable.prototype.onDrag = function ($item, position, _super, event) { + if (this.cursorAdjustment) { + /* + * Relative cursor position + */ + $item.css({ + left: position.left - this.cursorAdjustment.left, + top: position.top - this.cursorAdjustment.top + }) + } + else { + /* + * Default behavior + */ + $item.css(position) + } + } + Sortable.prototype.onDrop = function ($item, container, _super, event) { $item.removeClass('dragged').removeAttr('style') $('body').removeClass('dragging') diff --git a/modules/system/assets/ui/js/input.preset.js b/modules/system/assets/ui/js/input.preset.js index 428ed85b7..64d43284a 100644 --- a/modules/system/assets/ui/js/input.preset.js +++ b/modules/system/assets/ui/js/input.preset.js @@ -225,7 +225,17 @@ }) } + InputPreset.prototype.formatNamespace = function() { + var value = toCamel(this.$src.val()) + + return value.substr(0, 1).toUpperCase() + value.substr(1) + } + InputPreset.prototype.formatValue = function() { + if (this.options.inputPresetType == 'namespace') { + return this.formatNamespace() + } + if (this.options.inputPresetType == 'camel') var value = toCamel(this.$src.val()) else { diff --git a/modules/system/assets/ui/less/toolbar.less b/modules/system/assets/ui/less/toolbar.less index 591c40f9e..07b940c83 100644 --- a/modules/system/assets/ui/less/toolbar.less +++ b/modules/system/assets/ui/less/toolbar.less @@ -104,7 +104,7 @@ overflow: hidden; } -#layout-side-panel { +#layout-side-panel, .panel-contents { .control-toolbar { padding: 20px 0 20px 20px; } diff --git a/modules/system/classes/PluginBase.php b/modules/system/classes/PluginBase.php index ea7d5c0ad..830b6120a 100644 --- a/modules/system/classes/PluginBase.php +++ b/modules/system/classes/PluginBase.php @@ -1,6 +1,9 @@ getConfigurationFromYaml(sprintf('Plugin configuration file plugin.yaml is not '. + 'found for the plugin class %s. Create the file or override pluginDetails() '. + 'method in the plugin class.', $thisClass)); + + if (!array_key_exists('plugin', $configuration)) { + throw new SystemException('The plugin configuration file plugin.yaml should contain the "plugin" section: %s.', $thisClass); + } + + return $configuration['plugin']; + } /** * Register method, called when the plugin is first registered. @@ -147,4 +165,31 @@ abstract class PluginBase extends ServiceProviderBase $this->commands($key); } + + protected function getConfigurationFromYaml($exceptionMessage = null) + { + if ($this->loadedYamlConfigration !== false) { + return $this->loadedYamlConfigration; + } + + $reflection = new ReflectionClass(get_class($this)); + $yamlFilePath = dirname($reflection->getFileName()).'/plugin.yaml'; + + if (!file_exists($yamlFilePath)) { + if ($exceptionMessage) { + throw new SystemException($exceptionMessage); + } + else { + $this->loadedYamlConfigration = []; + } + } + else { + $this->loadedYamlConfigration = Yaml::parse(file_get_contents($yamlFilePath)); + if (!is_array($this->loadedYamlConfigration)) { + throw new SystemException('Invalid format of the plugin configuration file: %s. The file should define an array.', $filePath); + } + } + + return $this->loadedYamlConfigration; + } }