Merge branch 'builder-ui' into develop

Conflicts:
	modules/system/assets/ui/js/input.monitor.js
	modules/system/assets/ui/js/inspector.editor.object.js
	modules/system/assets/ui/storm-min.js
This commit is contained in:
alekseybobkov 2015-12-24 14:36:31 -08:00
commit 7d9d2176ef
55 changed files with 2085 additions and 176 deletions

View File

@ -228,6 +228,10 @@
.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{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 > div.controls > a.control:before{font-size:17px}
.control-filelist.hero ul li:hover > div.controls{display:block} .control-filelist.hero ul li:hover > div.controls{display:block}
.control-filelist.hero ul li.separator{position:relative;border-bottom:1px solid #95a5a6;padding:17px 15px 18px 15px}
.control-filelist.hero ul li.separator:before{z-index:31;content:'';display:block;width:0;height:0;border-left:9.5px solid transparent;border-right:9.5px solid transparent;border-top:11px solid #ffffff;border-bottom-width:0;position:absolute;left:13px;bottom:-8px}
.control-filelist.hero ul li.separator:after{z-index:30;content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #95a5a6;border-bottom-width:0;position:absolute;left:14px;bottom:-9px}
.control-filelist.hero ul li.separator h5{color:#2b3e50;font-size:15px;margin:0;font-weight:600;padding:0}
.control-filelist.hero ul > li.group > ul > li > a{padding-left:66px} .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{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{background:#58b6f7;border-bottom:1px solid #58b6f7 !important}
@ -618,6 +622,7 @@ body{webkit-font-smoothing:antialiased;font-family:'Open Sans',Arial,sans-serif;
.layout > .layout-cell.center{text-align:center} .layout > .layout-cell.center{text-align:center}
.layout > .layout-cell.middle{vertical-align:middle} .layout > .layout-cell.middle{vertical-align:middle}
.whiteboard{background:white} .whiteboard{background:white}
.layout-fill-container{position:absolute;left:0;top:0;width:100%;height:100%}
.layout-cell.width-fix > form,[data-calculate-width] > form,.layout-cell.width-fix > div,[data-calculate-width] > div{display:inline-block} .layout-cell.width-fix > form,[data-calculate-width] > form,.layout-cell.width-fix > div,[data-calculate-width] > div{display:inline-block}
body.compact-container .layout.layout-container,body.compact-container .layout .layout-container{padding:0 !important} body.compact-container .layout.layout-container,body.compact-container .layout .layout-container{padding:0 !important}
body.slim-container .layout.layout-container,body.slim-container .layout .layout-container{padding-left:0 !important;padding-right:0 !important} body.slim-container .layout.layout-container,body.slim-container .layout .layout-container{padding-left:0 !important;padding-right:0 !important}
@ -627,6 +632,24 @@ body.slim-container .layout.layout-container,body.slim-container .layout .layout
.layout.responsive-sidebar > .layout-cell:last-child{display:table-header-group;width:auto;height:auto} .layout.responsive-sidebar > .layout-cell:last-child{display:table-header-group;width:auto;height:auto}
.layout.responsive-sidebar > .layout-cell:last-child .layout-absolute{position:static} .layout.responsive-sidebar > .layout-cell:last-child .layout-absolute{position:static}
} }
.flex-layout-column{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}
.flex-layout-column.full-height-strict{height:100%}
.flex-layout-column.absolute{position:absolute !important}
.flex-layout-column.fill-container{position:absolute;left:0;top:0;width:100%;height:100%}
.flex-layout-row{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:row;-moz-flex-direction:row;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row}
.flex-layout-column.justify-center,.flex-layout-row.justify-center{-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:;-webkit-box-pack:center;justify-content:center}
.flex-layout-column.align-center,.flex-layout-row.align-center{-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;align-items:center;-webkit-align-content:center;-moz-align-content:center;-webkit-box-align:center;-ms-align-content:center;align-content:center}
.flex-layout-column.full-height,.flex-layout-row.full-height{min-height:100%}
.flex-layout-item{margin:0}
.flex-layout-item.fix{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}
.flex-layout-item.stretch{-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}
.flex-layout-item.stretch-constrain{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;flex:1}
.flex-layout-item.center{-webkit-align-self:center;-moz-align-self:center;-ms-align-self:center;align-self:center}
.flex-layout-item.relative{position:relative}
.flex-layout-item.layout-container{max-width:none}
.flex-layout-item.width-100{width:100px}
.flex-layout-item.width-200{width:200px}
.flex-layout-item.width-300{width:300px}
body.mainmenu-open{overflow:hidden} body.mainmenu-open{overflow:hidden}
nav#layout-mainmenu.navbar{background-color:#111111;padding:0 0 0 20px;line-height:0;white-space:nowrap} nav#layout-mainmenu.navbar{background-color:#111111;padding:0 0 0 20px;line-height:0;white-space:nowrap}
nav#layout-mainmenu.navbar a{text-decoration:none} nav#layout-mainmenu.navbar a{text-decoration:none}
@ -782,7 +805,7 @@ html.csstransitions body.outer.preload .outer-form-container{-webkit-transform:s
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title{background-color:#e67e22;z-index:105} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title{background-color:#e67e22;z-index:105}
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:before,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:before{background-position:left -40px;z-index:107} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:before,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:before{background-position:left -40px;z-index:107}
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:after,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:after{background-position:-80px -40px;z-index:107} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:after,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li.active a > span.title:after{background-position:-80px -40px;z-index:107}
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i{top:4px;font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i{top:3px;font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i:before,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f111";font-size:9px} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i:before,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li[data-modified] span.tab-close i:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f111";font-size:9px}
.fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li:first-child,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li:first-child{margin-left:0} .fancy-layout .control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li:first-child,.fancy-layout.control-tabs.master-tabs > div > div.tabs-container > ul.nav-tabs > li:first-child{margin-left:0}
.fancy-layout .control-tabs.master-tabs[data-closable] > div > div.tabs-container > ul.nav-tabs > li a > span.title,.fancy-layout.control-tabs.master-tabs[data-closable] > div > div.tabs-container > ul.nav-tabs > li a > span.title{padding-right:10px} .fancy-layout .control-tabs.master-tabs[data-closable] > div > div.tabs-container > ul.nav-tabs > li a > span.title,.fancy-layout.control-tabs.master-tabs[data-closable] > div > div.tabs-container > ul.nav-tabs > li a > span.title{padding-right:10px}
@ -800,7 +823,7 @@ html.csstransitions body.outer.preload .outer-form-container{-webkit-transform:s
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs{background:#f9f9f9} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs{background:#f9f9f9}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li{margin-left:-19px} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li{margin-left:-19px}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li:first-child,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li:first-child{margin-left:0;padding-left:8px} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li:first-child,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li:first-child{margin-left:0;padding-left:8px}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a{padding:8px 16px 0 16px;font-weight:400;color:#2b3e50;opacity:0.6;filter:alpha(opacity=60)} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a{padding:8px 16px 0 16px;font-weight:400;height:33px;color:#2b3e50;opacity:0.6;filter:alpha(opacity=60)}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title{position:relative;display:inline-block;padding:4px 5px 9px 5px;font-size:13px;z-index:100;height:25px !important;background-color:transparent} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title{position:relative;display:inline-block;padding:4px 5px 9px 5px;font-size:13px;z-index:100;height:25px !important;background-color:transparent}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:after,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:after{content:' ';position:absolute;background:transparent url(../images/secondary-tab-shape-content.svg) no-repeat left top;width:15px;height:25px;top:0;z-index:100;display:none} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:after,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:after{content:' ';position:absolute;background:transparent url(../images/secondary-tab-shape-content.svg) no-repeat left top;width:15px;height:25px;top:0;z-index:100;display:none}
.fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before{left:-15px} .fancy-layout .control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before,.fancy-layout.control-tabs.secondary-tabs.secondary-content-tabs > div > ul.nav-tabs > li a > span.title:before{left:-15px}

View File

@ -745,7 +745,8 @@ this.scrollbarSize=null
this.updateScrollbarTimer=null this.updateScrollbarTimer=null
this.dragOffset=null this.dragOffset=null
Base.call(this) Base.call(this)
this.init()} this.init()
$.oc.foundation.controlUtils.markDisposable(element)}
Scrollpad.prototype=Object.create(BaseProto) Scrollpad.prototype=Object.create(BaseProto)
Scrollpad.prototype.constructor=Scrollpad Scrollpad.prototype.constructor=Scrollpad
Scrollpad.prototype.dispose=function(){this.unregisterHandlers() Scrollpad.prototype.dispose=function(){this.unregisterHandlers()
@ -771,10 +772,12 @@ this.scrollbarElement=el.querySelector('.scrollpad-scrollbar')
this.dragHandleElement=el.querySelector('.scrollpad-scrollbar > .drag-handle')} this.dragHandleElement=el.querySelector('.scrollpad-scrollbar > .drag-handle')}
Scrollpad.prototype.registerHandlers=function(){this.$el.on('mouseenter',this.proxy(this.onMouseEnter)) Scrollpad.prototype.registerHandlers=function(){this.$el.on('mouseenter',this.proxy(this.onMouseEnter))
this.$el.on('mouseleave',this.proxy(this.onMouseLeave)) this.$el.on('mouseleave',this.proxy(this.onMouseLeave))
this.$el.one('dispose-control',this.proxy(this.dispose))
this.scrollContentElement.addEventListener('scroll',this.proxy(this.onScroll)) this.scrollContentElement.addEventListener('scroll',this.proxy(this.onScroll))
this.dragHandleElement.addEventListener('mousedown',this.proxy(this.onStartDrag))} this.dragHandleElement.addEventListener('mousedown',this.proxy(this.onStartDrag))}
Scrollpad.prototype.unregisterHandlers=function(){this.$el.off('mouseenter',this.proxy(this.onMouseEnter)) Scrollpad.prototype.unregisterHandlers=function(){this.$el.off('mouseenter',this.proxy(this.onMouseEnter))
this.$el.off('mouseleave',this.proxy(this.onMouseLeave)) this.$el.off('mouseleave',this.proxy(this.onMouseLeave))
this.$el.off('dispose-control',this.proxy(this.dispose))
this.scrollContentElement.removeEventListener('scroll',this.proxy(this.onScroll)) this.scrollContentElement.removeEventListener('scroll',this.proxy(this.onScroll))
this.dragHandleElement.removeEventListener('mousedown',this.proxy(this.onStartDrag)) this.dragHandleElement.removeEventListener('mousedown',this.proxy(this.onStartDrag))
document.removeEventListener('mousemove',this.proxy(this.onMouseMove)) document.removeEventListener('mousemove',this.proxy(this.onMouseMove))
@ -1133,16 +1136,19 @@ this.$fixButton=$('<a href="#" class="fix-button"><i class="icon-thumb-tack"></i
this.$fixButton.click(function(){self.fixPanel() this.$fixButton.click(function(){self.fixPanel()
return false}) return false})
$('.fix-button-container',this.$el).append(this.$fixButton) $('.fix-button-container',this.$el).append(this.$fixButton)
this.$sideNavItems.click(function(){if(Modernizr.touch&&$(window).width()<self.options.breakpoint){if($(this).data('menu-item')==self.visibleItemId&&self.panelVisible){self.hideSidePanel() this.$sideNavItems.click(function(){if($(this).data('no-side-panel')){return}
if(Modernizr.touch&&$(window).width()<self.options.breakpoint){if($(this).data('menu-item')==self.visibleItemId&&self.panelVisible){self.hideSidePanel()
return}else return}else
self.displaySidePanel()} self.displaySidePanel()}
self.displayTab(this) self.displayTab(this)
return false}) return false})
if(!Modernizr.touch){self.$sideNav.mouseenter(function(){if($(window).width()<self.options.breakpoint||!self.panelFixed()){self.panelOpenTimeout=setTimeout(function(){self.displaySidePanel()},self.tabOpenDelay)}}) if(!Modernizr.touch){self.$sideNav.mouseleave(function(){clearTimeout(self.panelOpenTimeout)})
self.$sideNav.mouseleave(function(){clearTimeout(self.panelOpenTimeout)})
self.$el.mouseleave(function(){self.hideSidePanel()}) self.$el.mouseleave(function(){self.hideSidePanel()})
self.$sideNavItems.mouseenter(function(){if($(window).width()<self.options.breakpoint||!self.panelFixed()){var _this=this self.$sideNavItems.mouseenter(function(){if($(window).width()<self.options.breakpoint||!self.panelFixed()){if($(this).data('no-side-panel')){self.hideSidePanel()
self.tabOpenTimeout=setTimeout(function(){self.displayTab(_this)},self.tabOpenDelay)}}) return}
var _this=this
self.tabOpenTimeout=setTimeout(function(){self.displaySidePanel()
self.displayTab(_this)},self.tabOpenDelay)}})
self.$sideNavItems.mouseleave(function(){clearTimeout(self.tabOpenTimeout)}) self.$sideNavItems.mouseleave(function(){clearTimeout(self.tabOpenTimeout)})
$(window).resize(function(){self.updatePanelPosition() $(window).resize(function(){self.updatePanelPosition()
self.updateActiveTab()})}else{$('#layout-body').click(function(){if(self.panelVisible){self.hideSidePanel() self.updateActiveTab()})}else{$('#layout-body').click(function(){if(self.panelVisible){self.hideSidePanel()
@ -1186,7 +1192,7 @@ $.fn.sidePanelTab=function(option){return this.each(function(){var $this=$(this)
var data=$this.data('oc.sidePanelTab') var data=$this.data('oc.sidePanelTab')
var options=$.extend({},SidePanelTab.DEFAULTS,$this.data(),typeof option=='object'&&option) var options=$.extend({},SidePanelTab.DEFAULTS,$this.data(),typeof option=='object'&&option)
if(!data)$this.data('oc.sidePanelTab',(data=new SidePanelTab(this,options))) if(!data)$this.data('oc.sidePanelTab',(data=new SidePanelTab(this,options)))
if(typeof option=='string')data[option].call($this)})} if(typeof option=='string')data[option].call(data)})}
$.fn.sidePanelTab.Constructor=SidePanelTab $.fn.sidePanelTab.Constructor=SidePanelTab
$.fn.sidePanelTab.noConflict=function(){$.fn.sidePanelTab=old $.fn.sidePanelTab.noConflict=function(){$.fn.sidePanelTab=old
return this} return this}
@ -1260,9 +1266,12 @@ this.shown=false
this.listen()} this.listen()}
Autocomplete.prototype={constructor:Autocomplete,select:function(){var val=this.$menu.find('.active').attr('data-value') Autocomplete.prototype={constructor:Autocomplete,select:function(){var val=this.$menu.find('.active').attr('data-value')
this.$element.val(this.updater(val)).change() this.$element.val(this.updater(val)).change()
return this.hide()},updater:function(item){return item},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight}),cssOptions={top:pos.top+pos.height,left:pos.left} return this.hide()},updater:function(item){return item},show:function(){var offset=this.options.bodyContainer?this.$element.offset():this.$element.position(),pos=$.extend({},offset,{height:this.$element[0].offsetHeight}),cssOptions={top:pos.top+pos.height,left:pos.left}
if(this.options.matchWidth){cssOptions.width=this.$element[0].offsetWidth} if(this.options.matchWidth){cssOptions.width=this.$element[0].offsetWidth}
this.$menu.insertAfter(this.$element).css(cssOptions).show() this.$menu.css(cssOptions)
if(this.options.bodyContainer){$(document.body).append(this.$menu)}
else{this.$menu.insertAfter(this.$element)}
this.$menu.show()
this.shown=true this.shown=true
return this},hide:function(){this.$menu.hide() return this},hide:function(){this.$menu.hide()
this.shown=false this.shown=false
@ -1339,7 +1348,7 @@ var old=$.fn.autocomplete
$.fn.autocomplete=function(option){return this.each(function(){var $this=$(this),data=$this.data('autocomplete'),options=typeof option=='object'&&option $.fn.autocomplete=function(option){return this.each(function(){var $this=$(this),data=$this.data('autocomplete'),options=typeof option=='object'&&option
if(!data)$this.data('autocomplete',(data=new Autocomplete(this,options))) if(!data)$this.data('autocomplete',(data=new Autocomplete(this,options)))
if(typeof option=='string')data[option]()})} if(typeof option=='string')data[option]()})}
$.fn.autocomplete.defaults={source:[],items:8,menu:'<ul class="autocomplete dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1} $.fn.autocomplete.defaults={source:[],items:8,menu:'<ul class="autocomplete dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1,bodyContainer:false}
$.fn.autocomplete.Constructor=Autocomplete $.fn.autocomplete.Constructor=Autocomplete
$.fn.autocomplete.noConflict=function(){$.fn.autocomplete=old $.fn.autocomplete.noConflict=function(){$.fn.autocomplete=old
return this} return this}

View File

@ -51,7 +51,8 @@
}, },
show: function () { show: function () {
var pos = $.extend({}, this.$element.position(), { var offset = this.options.bodyContainer ? this.$element.offset() : this.$element.position(),
pos = $.extend({}, offset, {
height: this.$element[0].offsetHeight height: this.$element[0].offsetHeight
}), }),
cssOptions = { cssOptions = {
@ -63,10 +64,16 @@
cssOptions.width = this.$element[0].offsetWidth cssOptions.width = this.$element[0].offsetWidth
} }
this.$menu this.$menu.css(cssOptions)
.insertAfter(this.$element)
.css(cssOptions) if (this.options.bodyContainer) {
.show() $(document.body).append(this.$menu)
}
else {
this.$menu.insertAfter(this.$element)
}
this.$menu.show()
this.shown = true this.shown = true
return this return this
@ -347,7 +354,8 @@
items: 8, items: 8,
menu: '<ul class="autocomplete dropdown-menu"></ul>', menu: '<ul class="autocomplete dropdown-menu"></ul>',
item: '<li><a href="#"></a></li>', item: '<li><a href="#"></a></li>',
minLength: 1 minLength: 1,
bodyContainer: false
} }
$.fn.autocomplete.Constructor = Autocomplete $.fn.autocomplete.Constructor = Autocomplete

View File

@ -38,6 +38,8 @@
var $cells = this.$el.find('> .layout-cell'), var $cells = this.$el.find('> .layout-cell'),
$flyout = this.$el.find('> .flyout') $flyout = this.$el.find('> .flyout')
$('[data-control=layout-sidepanel]').sidePanelTab('hideSidePanel')
this.removeOverlay() this.removeOverlay()
for (var i = 0; i < $cells.length; i++) { for (var i = 0; i < $cells.length; i++) {

View File

@ -62,6 +62,8 @@
// //
this.init() this.init()
$.oc.foundation.controlUtils.markDisposable(element)
} }
Scrollpad.prototype = Object.create(BaseProto) Scrollpad.prototype = Object.create(BaseProto)
@ -113,6 +115,9 @@
Scrollpad.prototype.registerHandlers = function() { Scrollpad.prototype.registerHandlers = function() {
this.$el.on('mouseenter', this.proxy(this.onMouseEnter)) this.$el.on('mouseenter', this.proxy(this.onMouseEnter))
this.$el.on('mouseleave', this.proxy(this.onMouseLeave)) this.$el.on('mouseleave', this.proxy(this.onMouseLeave))
this.$el.one('dispose-control', this.proxy(this.dispose))
this.scrollContentElement.addEventListener('scroll', this.proxy(this.onScroll)) this.scrollContentElement.addEventListener('scroll', this.proxy(this.onScroll))
this.dragHandleElement.addEventListener('mousedown', this.proxy(this.onStartDrag)) this.dragHandleElement.addEventListener('mousedown', this.proxy(this.onStartDrag))
} }
@ -120,6 +125,7 @@
Scrollpad.prototype.unregisterHandlers = function() { Scrollpad.prototype.unregisterHandlers = function() {
this.$el.off('mouseenter', this.proxy(this.onMouseEnter)) this.$el.off('mouseenter', this.proxy(this.onMouseEnter))
this.$el.off('mouseleave', this.proxy(this.onMouseLeave)) this.$el.off('mouseleave', this.proxy(this.onMouseLeave))
this.$el.off('dispose-control', this.proxy(this.dispose))
this.scrollContentElement.removeEventListener('scroll', this.proxy(this.onScroll)) this.scrollContentElement.removeEventListener('scroll', this.proxy(this.onScroll))
this.dragHandleElement.removeEventListener('mousedown', this.proxy(this.onStartDrag)) this.dragHandleElement.removeEventListener('mousedown', this.proxy(this.onStartDrag))

View File

@ -31,6 +31,10 @@
$('.fix-button-container', this.$el).append(this.$fixButton) $('.fix-button-container', this.$el).append(this.$fixButton)
this.$sideNavItems.click(function(){ this.$sideNavItems.click(function(){
if ($(this).data('no-side-panel')) {
return
}
if (Modernizr.touch && $(window).width() < self.options.breakpoint) { if (Modernizr.touch && $(window).width() < self.options.breakpoint) {
if ($(this).data('menu-item') == self.visibleItemId && self.panelVisible) { if ($(this).data('menu-item') == self.visibleItemId && self.panelVisible) {
self.hideSidePanel() self.hideSidePanel()
@ -45,13 +49,16 @@
}) })
if (!Modernizr.touch) { if (!Modernizr.touch) {
self.$sideNav.mouseenter(function(){ // The side panel now opens only when a menu item is hovered and
if ($(window).width() < self.options.breakpoint || !self.panelFixed()) { // when the item doesn't have the "data-no-side-panel" attribute.
self.panelOpenTimeout = setTimeout(function () { // TODO: remove the comment and the code below if no issues noticed.
self.displaySidePanel() // self.$sideNav.mouseenter(function(){
}, self.tabOpenDelay) // if ($(window).width() < self.options.breakpoint || !self.panelFixed()) {
} // self.panelOpenTimeout = setTimeout(function () {
}) // self.displaySidePanel()
// }, self.tabOpenDelay)
// }
// })
self.$sideNav.mouseleave(function(){ self.$sideNav.mouseleave(function(){
clearTimeout(self.panelOpenTimeout) clearTimeout(self.panelOpenTimeout)
@ -63,8 +70,14 @@
self.$sideNavItems.mouseenter(function(){ self.$sideNavItems.mouseenter(function(){
if ($(window).width() < self.options.breakpoint || !self.panelFixed()) { if ($(window).width() < self.options.breakpoint || !self.panelFixed()) {
if ($(this).data('no-side-panel')) {
self.hideSidePanel()
return
}
var _this = this var _this = this
self.tabOpenTimeout = setTimeout(function () { self.tabOpenTimeout = setTimeout(function () {
self.displaySidePanel()
self.displayTab(_this) self.displayTab(_this)
}, self.tabOpenDelay) }, self.tabOpenDelay)
} }
@ -74,7 +87,6 @@
clearTimeout(self.tabOpenTimeout) clearTimeout(self.tabOpenTimeout)
}) })
$(window).resize(function() { $(window).resize(function() {
self.updatePanelPosition() self.updatePanelPosition()
self.updateActiveTab() self.updateActiveTab()
@ -198,7 +210,7 @@
var data = $this.data('oc.sidePanelTab') var data = $this.data('oc.sidePanelTab')
var options = $.extend({}, SidePanelTab.DEFAULTS, $this.data(), typeof option == 'object' && option) var options = $.extend({}, SidePanelTab.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('oc.sidePanelTab', (data = new SidePanelTab(this, options))) if (!data) $this.data('oc.sidePanelTab', (data = new SidePanelTab(this, options)))
if (typeof option == 'string') data[option].call($this) if (typeof option == 'string') data[option].call(data)
}) })
} }

View File

@ -336,6 +336,36 @@
&:hover > div.controls { &:hover > div.controls {
display: block; display: block;
} }
&.separator {
position: relative;
border-bottom: 1px solid #95a5a6;
padding: 17px 15px 18px 15px;
&:before {
z-index: 31;
.triangle(down, 19px, 11px, white);
position: absolute;
left: 13px;
bottom: -8px;
}
&:after {
z-index: 30;
.triangle(down, 17px, 9px, #95a5a6);
position: absolute;
left: 14px;
bottom: -9px;
}
h5 {
color: #2b3e50;
font-size: 15px;
margin: 0;
font-weight: 600;
padding: 0;
}
}
} }
> li.group { > li.group {

View File

@ -146,7 +146,7 @@
&[data-modified] { &[data-modified] {
span.tab-close i { span.tab-close i {
top: 4px; top: 3px;
.hide-text(); .hide-text();
&:before { &:before {
@ -232,6 +232,7 @@
a { a {
padding: 8px 16px 0 16px; padding: 8px 16px 0 16px;
font-weight: 400; font-weight: 400;
height: 33px;
color: #2b3e50; color: #2b3e50;
.opacity(0.6); .opacity(0.6);

View File

@ -0,0 +1,54 @@
.flex-layout-column {
.flex-display();
.flex-direction-column();
&.full-height-strict {
height: 100%;
}
&.absolute {
position: absolute!important;
}
&.fill-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
}
.flex-layout-row {
.flex-display();
.flex-direction-row();
}
.flex-layout-column, .flex-layout-row {
&.justify-center {.justify-content(center);}
&.align-center {
.align-items(center);
.align-content(center);
}
&.full-height {
min-height: 100%;
// height: 100%;
}
}
.flex-layout-item {
margin: 0;
&.fix {.flex-fix();}
&.stretch {.flex-stretch();}
&.stretch-constrain {.flex-stretch-constrain();}
&.center {.align-self(center);}
&.relative {position: relative;}
&.layout-container {max-width: none;}
&.width-100 {width: 100px;}
&.width-200 {width: 200px;}
&.width-300 {width: 300px;}
}

View File

@ -142,6 +142,14 @@ body {
background: white; background: white;
} }
.layout-fill-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
// //
// Calculated fixed width // Calculated fixed width
// //

View File

@ -56,6 +56,7 @@
// Layout // Layout
@import "layout/layout.less"; @import "layout/layout.less";
@import "layout/flexlayout.less";
@import "layout/mainmenu.less"; @import "layout/mainmenu.less";
@import "layout/sidenav.less"; @import "layout/sidenav.less";
@import "layout/sidepanel.less"; @import "layout/sidepanel.less";

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,7 @@
=require ../vendor/ace/mode-css.js =require ../vendor/ace/mode-css.js
=require ../vendor/ace/mode-scss.js =require ../vendor/ace/mode-scss.js
=require ../vendor/ace/mode-sass.js =require ../vendor/ace/mode-sass.js
=require ../vendor/ace/mode-yaml.js
=require ../vendor/ace/mode-javascript.js =require ../vendor/ace/mode-javascript.js
=require codeeditor.js =require codeeditor.js

View File

@ -0,0 +1,256 @@
ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var YamlHighlightRules = function() {
this.$rules = {
"start" : [
{
token : "comment",
regex : "#.*$"
}, {
token : "list.markup",
regex : /^(?:-{3}|\.{3})\s*(?=#|$)/
}, {
token : "list.markup",
regex : /^\s*[\-?](?:$|\s)/
}, {
token: "constant",
regex: "!![\\w//]+"
}, {
token: "constant.language",
regex: "[&\\*][a-zA-Z0-9-_]+"
}, {
token: ["meta.tag", "keyword"],
regex: /^(\s*\w.*?)(\:(?:\s+|$))/
},{
token: ["meta.tag", "keyword"],
regex: /(\w+?)(\s*\:(?:\s+|$))/
}, {
token : "keyword.operator",
regex : "<<\\w*:\\w*"
}, {
token : "keyword.operator",
regex : "-\\s*(?=[{])"
}, {
token : "string", // single line
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
}, {
token : "string", // multi line string start
regex : '[|>][-+\\d\\s]*$',
next : "qqstring"
}, {
token : "string", // single quoted string
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
}, {
token : "constant.numeric", // float
regex : /(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)/
}, {
token : "constant.numeric", // other number
regex : /[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/
}, {
token : "constant.language.boolean",
regex : "(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"
}, {
token : "paren.lparen",
regex : "[[({]"
}, {
token : "paren.rparen",
regex : "[\\])}]"
}
],
"qqstring" : [
{
token : "string",
regex : '(?=(?:(?:\\\\.)|(?:[^:]))*?:)',
next : "start"
}, {
token : "string",
regex : '.+'
}
]};
};
oop.inherits(YamlHighlightRules, TextHighlightRules);
exports.YamlHighlightRules = YamlHighlightRules;
});
ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) {
"use strict";
var Range = require("../range").Range;
var MatchingBraceOutdent = function() {};
(function() {
this.checkOutdent = function(line, input) {
if (! /^\s+$/.test(line))
return false;
return /^\s*\}/.test(input);
};
this.autoOutdent = function(doc, row) {
var line = doc.getLine(row);
var match = line.match(/^(\s*\})/);
if (!match) return 0;
var column = match[1].length;
var openBracePos = doc.findMatchingBracket({row: row, column: column});
if (!openBracePos || openBracePos.row == row) return 0;
var indent = this.$getIndent(doc.getLine(openBracePos.row));
doc.replace(new Range(row, 0, row, column-1), indent);
};
this.$getIndent = function(line) {
return line.match(/^\s*/)[0];
};
}).call(MatchingBraceOutdent.prototype);
exports.MatchingBraceOutdent = MatchingBraceOutdent;
});
ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"], function(require, exports, module) {
"use strict";
var oop = require("../../lib/oop");
var BaseFoldMode = require("./fold_mode").FoldMode;
var Range = require("../../range").Range;
var FoldMode = exports.FoldMode = function() {};
oop.inherits(FoldMode, BaseFoldMode);
(function() {
this.getFoldWidgetRange = function(session, foldStyle, row) {
var range = this.indentationBlock(session, row);
if (range)
return range;
var re = /\S/;
var line = session.getLine(row);
var startLevel = line.search(re);
if (startLevel == -1 || line[startLevel] != "#")
return;
var startColumn = line.length;
var maxRow = session.getLength();
var startRow = row;
var endRow = row;
while (++row < maxRow) {
line = session.getLine(row);
var level = line.search(re);
if (level == -1)
continue;
if (line[level] != "#")
break;
endRow = row;
}
if (endRow > startRow) {
var endColumn = session.getLine(endRow).length;
return new Range(startRow, startColumn, endRow, endColumn);
}
};
this.getFoldWidget = function(session, foldStyle, row) {
var line = session.getLine(row);
var indent = line.search(/\S/);
var next = session.getLine(row + 1);
var prev = session.getLine(row - 1);
var prevIndent = prev.search(/\S/);
var nextIndent = next.search(/\S/);
if (indent == -1) {
session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
return "";
}
if (prevIndent == -1) {
if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
session.foldWidgets[row - 1] = "";
session.foldWidgets[row + 1] = "";
return "start";
}
} else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
if (session.getLine(row - 2).search(/\S/) == -1) {
session.foldWidgets[row - 1] = "start";
session.foldWidgets[row + 1] = "";
return "";
}
}
if (prevIndent!= -1 && prevIndent < indent)
session.foldWidgets[row - 1] = "start";
else
session.foldWidgets[row - 1] = "";
if (indent < nextIndent)
return "start";
else
return "";
};
}).call(FoldMode.prototype);
});
ace.define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee"], function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var YamlHighlightRules = require("./yaml_highlight_rules").YamlHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var FoldMode = require("./folding/coffee").FoldMode;
var Mode = function() {
this.HighlightRules = YamlHighlightRules;
this.$outdent = new MatchingBraceOutdent();
this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = "#";
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);
if (state == "start") {
var match = line.match(/^.*[\{\(\[]\s*$/);
if (match) {
indent += tab;
}
}
return indent;
};
this.checkOutdent = function(state, line, input) {
return this.$outdent.checkOutdent(line, input);
};
this.autoOutdent = function(state, doc, row) {
this.$outdent.autoOutdent(doc, row);
};
this.$id = "ace/mode/yaml";
}).call(Mode.prototype);
exports.Mode = Mode;
});

View File

@ -2203,4 +2203,4 @@ data[option].apply(data,methodArgs)}})}
$.fn.richEditor.Constructor=RichEditor $.fn.richEditor.Constructor=RichEditor
$.fn.richEditor.noConflict=function(){$.fn.richEditor=old $.fn.richEditor.noConflict=function(){$.fn.richEditor=old
return this} return this}
$(document).render(function(){$('[data-control="richeditor"]').richEditor()})}(window.jQuery); $(document).render(function(){$('[data-control="richeditor"]').richEditor()})}(window.jQuery);

View File

@ -178,6 +178,8 @@ return [
'saving_name' => 'Saving :name...', 'saving_name' => 'Saving :name...',
'delete' => 'Delete', 'delete' => 'Delete',
'deleting' => 'Deleting...', 'deleting' => 'Deleting...',
'confirm_delete' => 'Do you really want to delete this record?',
'confirm_delete_multiple' => 'Do you really want to delete the selected records?',
'deleting_name' => 'Deleting :name...', 'deleting_name' => 'Deleting :name...',
'reset_default' => 'Reset to default', 'reset_default' => 'Reset to default',
'resetting' => 'Resetting', 'resetting' => 'Resetting',
@ -206,7 +208,8 @@ return [
'insert_row_below' => 'Insert Row Below', 'insert_row_below' => 'Insert Row Below',
'delete_row' => 'Delete Row', 'delete_row' => 'Delete Row',
'concurrency_file_changed_title' => 'File was changed', 'concurrency_file_changed_title' => 'File was changed',
'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk." 'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk.",
'return_to_list' => 'Return to the list'
], ],
'recordfinder' => [ 'recordfinder' => [
'find_record' => 'Find Record' 'find_record' => 'Find Record'

View File

@ -197,4 +197,21 @@ class Table extends WidgetBase
'options' => $options 'options' => $options
]; ];
} }
public function onGetAutocompleteOptions()
{
$columnName = Input::get('column');
$rowData = Input::get('rowData');
$eventResults = $this->fireEvent('table.getAutocompleteOptions', [$columnName, $rowData]);
$options = [];
if (count($eventResults)) {
$options = $eventResults[0];
}
return [
'options' => $options
];
}
} }

View File

@ -161,6 +161,24 @@ Multiple fields are allowed as well:
**Note:** Dependent drop-down should always be defined after their master columns. **Note:** Dependent drop-down should always be defined after their master columns.
### Autocomplete cell processor
The autocomplete column type can load options from the column configuration or with AJAX. Example column configuration:
color:
title: Color
type: autocomplete
options:
red: Red
green: Green
blue: Blue
If the `options` element is not presented in the configuration, the options will be loaded with AJAX.
**TODO:** Document the AJAX interface
The editor can have the `dependsOn` property similar to the drop-down editor.
# Server-side table widget (Backend\Widgets\Table) # Server-side table widget (Backend\Widgets\Table)
## Configuration ## Configuration

View File

@ -72,16 +72,16 @@
padding: 1px; padding: 1px;
} }
.control-table table.data td.active { .control-table table.data td.active {
border-color: #5fb6f5 !important; border-color: #4da7e8 !important;
} }
.control-table table.data td.active .content-container { .control-table table.data td.active .content-container {
padding: 0; padding: 0;
border: 1px solid #5fb6f5; border: 1px solid #4da7e8;
} }
.control-table table.data td.active .content-container:before, .control-table table.data td.active .content-container:before,
.control-table table.data td.active .content-container:after { .control-table table.data td.active .content-container:after {
content: ' '; content: ' ';
background: #5fb6f5; background: #4da7e8;
position: absolute; position: absolute;
left: -2px; left: -2px;
top: -2px; top: -2px;
@ -189,7 +189,7 @@
color: #95a5a6; color: #95a5a6;
} }
.control-table .pagination ul li.active { .control-table .pagination ul li.active {
background: #5fb6f5; background: #4da7e8;
} }
.control-table .pagination ul li.active a { .control-table .pagination ul li.active a {
color: #ffffff; color: #ffffff;
@ -207,9 +207,10 @@
} }
} }
/* /*
* String editor * String and autocomplete editors
*/ */
.control-table td[data-column-type=string] input[type=text] { .control-table td[data-column-type=string] input[type=text],
.control-table td[data-column-type=autocomplete] input[type=text] {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
@ -217,6 +218,18 @@
border: none; border: none;
padding: 5px 10px; padding: 5px 10px;
} }
ul.table-widget-autocomplete {
background: white;
font-size: 13px;
margin-top: 0;
border: 1px solid #808c8d;
border-top: 1px solid #ecf0f1;
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
}
ul.table-widget-autocomplete li a {
padding: 5px 10px;
}
/* /*
* Checkbox editor * Checkbox editor
*/ */
@ -254,7 +267,7 @@
top: -4px; top: -4px;
} }
.control-table td[data-column-type=checkbox] div[data-checkbox-element]:focus { .control-table td[data-column-type=checkbox] div[data-checkbox-element]:focus {
border-color: #5fb6f5; border-color: #4da7e8;
outline: none; outline: none;
} }
/* /*
@ -366,6 +379,6 @@ html.cssanimations .control-table td[data-column-type=dropdown] [data-view-conta
.table-control-dropdown-list li:hover, .table-control-dropdown-list li:hover,
.table-control-dropdown-list li:focus, .table-control-dropdown-list li:focus,
.table-control-dropdown-list li.selected { .table-control-dropdown-list li.selected {
background: #5fb6f5; background: #4da7e8;
color: white; color: white;
} }

View File

@ -221,6 +221,7 @@ this.navigation.pageIndex=newPageIndex}
this.recordsAddedOrDeleted++ this.recordsAddedOrDeleted++
var keyColumn=this.options.keyColumn,recordData={},self=this var keyColumn=this.options.keyColumn,recordData={},self=this
recordData[keyColumn]=-1*this.recordsAddedOrDeleted recordData[keyColumn]=-1*this.recordsAddedOrDeleted
this.$el.trigger('oc.tableNewRow',[recordData])
this.dataSource.createRecord(recordData,placement,relativeToKey,this.navigation.getPageFirstRowOffset(),this.options.recordsPerPage,function onAddRecordDataTableSuccess(records,totalCount){self.buildDataTable(records,totalCount) this.dataSource.createRecord(recordData,placement,relativeToKey,this.navigation.getPageFirstRowOffset(),this.options.recordsPerPage,function onAddRecordDataTableSuccess(records,totalCount){self.buildDataTable(records,totalCount)
var row=self.findRowByKey(recordData[keyColumn]) var row=self.findRowByKey(recordData[keyColumn])
if(!row) if(!row)
@ -863,6 +864,54 @@ DropdownProcessor.prototype.elementBelongsToProcessor=function(element){if(!this
return false return false
return this.tableObj.parentContainsElement(this.itemListElement,element)} return this.tableObj.parentContainsElement(this.itemListElement,element)}
$.oc.table.processor.dropdown=DropdownProcessor;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined) $.oc.table.processor.dropdown=DropdownProcessor;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined)
throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.processor===undefined)
throw new Error("The $.oc.table.processor namespace is not defined. Make sure that the table.processor.base.js script is loaded.");var Base=$.oc.table.processor.string,BaseProto=Base.prototype
var AutocompleteProcessor=function(tableObj,columnName,columnConfiguration){this.cachedOptionPromises={}
Base.call(this,tableObj,columnName,columnConfiguration)}
AutocompleteProcessor.prototype=Object.create(BaseProto)
AutocompleteProcessor.prototype.constructor=AutocompleteProcessor
AutocompleteProcessor.prototype.dispose=function(){this.cachedOptionPromises=null
BaseProto.dispose.call(this)}
AutocompleteProcessor.prototype.onUnfocus=function(){if(!this.activeCell)
return
this.removeAutocomplete()
BaseProto.onUnfocus.call(this)}
AutocompleteProcessor.prototype.renderCell=function(value,cellContentContainer){BaseProto.renderCell.call(this,value,cellContentContainer)}
AutocompleteProcessor.prototype.buildEditor=function(cellElement,cellContentContainer,isClick){BaseProto.buildEditor.call(this,cellElement,cellContentContainer,isClick)
var self=this
this.fetchOptions(cellElement,function autocompleteFetchOptions(options){self.buildAutoComplete(options)
self=null})}
AutocompleteProcessor.prototype.fetchOptions=function(cellElement,onSuccess){if(this.columnConfiguration.options){if(onSuccess!==undefined){onSuccess(this.columnConfiguration.options)}}else{if(this.triggerGetOptions(onSuccess)===false){return}
var row=cellElement.parentNode,cachingKey=this.createOptionsCachingKey(row),viewContainer=this.getViewContainer(cellElement)
$.oc.foundation.element.addClass(viewContainer,'loading')
if(!this.cachedOptionPromises[cachingKey]){var requestData={column:this.columnName,rowData:this.tableObj.getRowData(row)},handlerName=this.tableObj.getAlias()+'::onGetAutocompleteOptions'
this.cachedOptionPromises[cachingKey]=this.tableObj.$el.request(handlerName,{data:requestData})}
this.cachedOptionPromises[cachingKey].done(function onAutocompleteLoadOptionsSuccess(data){if(onSuccess!==undefined){onSuccess(data.options)}}).always(function onAutocompleteLoadOptionsAlways(){$.oc.foundation.element.removeClass(viewContainer,'loading')})}}
AutocompleteProcessor.prototype.createOptionsCachingKey=function(row){var cachingKey='non-dependent',dependsOn=this.columnConfiguration.dependsOn
if(dependsOn){if(typeof dependsOn=='object'){for(var i=0,len=dependsOn.length;i<len;i++)
cachingKey+=dependsOn[i]+this.tableObj.getRowCellValueByColumnName(row,dependsOn[i])}else
cachingKey=dependsOn+this.tableObj.getRowCellValueByColumnName(row,dependsOn)}
return cachingKey}
AutocompleteProcessor.prototype.triggerGetOptions=function(callback){var tableElement=this.tableObj.getElement()
if(!tableElement){return}
var optionsEvent=$.Event('autocompleteitems.oc.table'),values={}
$(tableElement).trigger(optionsEvent,[{values:values,callback:callback,column:this.columnName,columnConfiguration:this.columnConfiguration}])
if(optionsEvent.isDefaultPrevented()){return false}
return true}
AutocompleteProcessor.prototype.getInput=function(){if(!this.activeCell){return null}
return this.activeCell.querySelector('.string-input')}
AutocompleteProcessor.prototype.buildAutoComplete=function(items){if(!this.activeCell){return}
var input=this.getInput()
if(!input){return}
if(items===undefined){items=[]}
$(input).autocomplete({source:this.prepareItems(items),matchWidth:true,menu:'<ul class="autocomplete dropdown-menu table-widget-autocomplete"></ul>',bodyContainer:true})}
AutocompleteProcessor.prototype.prepareItems=function(items){var result={}
if($.isArray(items)){for(var i=0,len=items.length;i<len;i++){result[items[i]]=items[i]}}
else{result=items}
return result}
AutocompleteProcessor.prototype.removeAutocomplete=function(){var input=this.getInput()
$(input).autocomplete('destroy')}
$.oc.table.processor.autocomplete=AutocompleteProcessor;}(window.jQuery);+function($){"use strict";if($.oc.table===undefined)
throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined) throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");if($.oc.table.validator===undefined)
$.oc.table.validator={} $.oc.table.validator={}
var Base=function(options){this.options=options} var Base=function(options){this.options=options}

View File

@ -15,6 +15,7 @@
=require table.processor.string.js =require table.processor.string.js
=require table.processor.checkbox.js =require table.processor.checkbox.js
=require table.processor.dropdown.js =require table.processor.dropdown.js
=require table.processor.autocomplete.js
=require table.validator.base.js =require table.validator.base.js
=require table.validator.required.js =require table.validator.required.js
=require table.validator.basenumber.js =require table.validator.basenumber.js

View File

@ -577,6 +577,10 @@
recordData[keyColumn] = -1*this.recordsAddedOrDeleted recordData[keyColumn] = -1*this.recordsAddedOrDeleted
this.$el.trigger('oc.tableNewRow', [
recordData
])
this.dataSource.createRecord(recordData, placement, relativeToKey, this.dataSource.createRecord(recordData, placement, relativeToKey,
this.navigation.getPageFirstRowOffset(), this.navigation.getPageFirstRowOffset(),
this.options.recordsPerPage, this.options.recordsPerPage,

View File

@ -0,0 +1,215 @@
/*
* Autocomplete cell processor for the table control.
*/
+function ($) { "use strict";
// NAMESPACE CHECK
// ============================
if ($.oc.table === undefined)
throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");
if ($.oc.table.processor === undefined)
throw new Error("The $.oc.table.processor namespace is not defined. Make sure that the table.processor.base.js script is loaded.");
// CLASS DEFINITION
// ============================
var Base = $.oc.table.processor.string,
BaseProto = Base.prototype
var AutocompleteProcessor = function(tableObj, columnName, columnConfiguration) {
//
// State properties
//
this.cachedOptionPromises = {}
//
// Parent constructor
//
Base.call(this, tableObj, columnName, columnConfiguration)
}
AutocompleteProcessor.prototype = Object.create(BaseProto)
AutocompleteProcessor.prototype.constructor = AutocompleteProcessor
AutocompleteProcessor.prototype.dispose = function() {
this.cachedOptionPromises = null
BaseProto.dispose.call(this)
}
/*
* Forces the processor to hide the editor when the user navigates
* away from the cell. Processors can update the sell value in this method.
* Processors must clear the reference to the active cell in this method.
*/
AutocompleteProcessor.prototype.onUnfocus = function() {
if (!this.activeCell)
return
this.removeAutocomplete()
BaseProto.onUnfocus.call(this)
}
/*
* Renders the cell in the normal (no edit) mode
*/
AutocompleteProcessor.prototype.renderCell = function(value, cellContentContainer) {
BaseProto.renderCell.call(this, value, cellContentContainer)
// this.fetchOptions(cellContentContainer.parentNode)
}
AutocompleteProcessor.prototype.buildEditor = function(cellElement, cellContentContainer, isClick) {
BaseProto.buildEditor.call(this, cellElement, cellContentContainer, isClick)
var self = this
this.fetchOptions(cellElement, function autocompleteFetchOptions(options) {
self.buildAutoComplete(options)
self = null
})
}
AutocompleteProcessor.prototype.fetchOptions = function(cellElement, onSuccess) {
if (this.columnConfiguration.options) {
if (onSuccess !== undefined) {
onSuccess(this.columnConfiguration.options)
}
} else {
// If options are not provided and not found in the cache,
// request them from the server. For dependent autocomplete editors
// the caching key contains the master column values.
if (this.triggerGetOptions(onSuccess) === false) {
return
}
var row = cellElement.parentNode,
cachingKey = this.createOptionsCachingKey(row),
viewContainer = this.getViewContainer(cellElement)
// Request options from the server. When the table widget builds,
// multiple cells in the column could require loading the options.
// The AJAX promises are cached here so that we have a single
// request per caching key.
$.oc.foundation.element.addClass(viewContainer, 'loading')
if (!this.cachedOptionPromises[cachingKey]) {
var requestData = {
column: this.columnName,
rowData: this.tableObj.getRowData(row)
},
handlerName = this.tableObj.getAlias()+'::onGetAutocompleteOptions'
this.cachedOptionPromises[cachingKey] = this.tableObj.$el.request(handlerName, {data: requestData})
}
this.cachedOptionPromises[cachingKey].done(function onAutocompleteLoadOptionsSuccess(data){
if (onSuccess !== undefined) {
onSuccess(data.options)
}
}).always(function onAutocompleteLoadOptionsAlways(){
$.oc.foundation.element.removeClass(viewContainer, 'loading')
})
}
}
AutocompleteProcessor.prototype.createOptionsCachingKey = function(row) {
var cachingKey = 'non-dependent',
dependsOn = this.columnConfiguration.dependsOn
if (dependsOn) {
if (typeof dependsOn == 'object') {
for (var i = 0, len = dependsOn.length; i < len; i++ )
cachingKey += dependsOn[i] + this.tableObj.getRowCellValueByColumnName(row, dependsOn[i])
} else
cachingKey = dependsOn + this.tableObj.getRowCellValueByColumnName(row, dependsOn)
}
return cachingKey
}
AutocompleteProcessor.prototype.triggerGetOptions = function(callback) {
var tableElement = this.tableObj.getElement()
if (!tableElement) {
return
}
var optionsEvent = $.Event('autocompleteitems.oc.table'),
values = {} // TODO - implement loading values from the current row.
$(tableElement).trigger(optionsEvent, [{
values: values,
callback: callback,
column: this.columnName,
columnConfiguration: this.columnConfiguration
}])
if (optionsEvent.isDefaultPrevented()) {
return false
}
return true
}
AutocompleteProcessor.prototype.getInput = function() {
if (!this.activeCell) {
return null
}
return this.activeCell.querySelector('.string-input')
}
AutocompleteProcessor.prototype.buildAutoComplete = function(items) {
if (!this.activeCell) {
return
}
var input = this.getInput()
if (!input) {
return
}
if (items === undefined) {
items = []
}
$(input).autocomplete({
source: this.prepareItems(items),
matchWidth: true,
menu: '<ul class="autocomplete dropdown-menu table-widget-autocomplete"></ul>',
bodyContainer: true
})
}
AutocompleteProcessor.prototype.prepareItems = function(items) {
var result = {}
if ($.isArray(items)) {
for (var i = 0, len = items.length; i < len; i++) {
result[items[i]] = items[i]
}
}
else {
result = items
}
return result
}
AutocompleteProcessor.prototype.removeAutocomplete = function() {
var input = this.getInput()
$(input).autocomplete('destroy')
}
$.oc.table.processor.autocomplete = AutocompleteProcessor;
}(window.jQuery);

View File

@ -212,7 +212,7 @@
if (!this.cachedOptionPromises[cachingKey]) { if (!this.cachedOptionPromises[cachingKey]) {
var requestData = { var requestData = {
column: this.columnName, column: this.columnName,
rowData: this.tableObj.getRowData(row) rowData: this.tableObj.getRowData(row)
}, },
handlerName = this.tableObj.getAlias()+'::onGetDropdownOptions' handlerName = this.tableObj.getAlias()+'::onGetDropdownOptions'

View File

@ -265,11 +265,12 @@
} }
/* /*
* String editor * String and autocomplete editors
*/ */
.control-table { .control-table {
td[data-column-type=string] { td[data-column-type=string],
td[data-column-type=autocomplete] {
input[type=text] { input[type=text] {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -281,6 +282,19 @@
} }
} }
ul.table-widget-autocomplete {
background: white;
font-size: 13px;
margin-top: 0;
border: 1px solid #808c8d;
border-top: 1px solid #ecf0f1;
.border-bottom-radius(4px);
li a {
padding: 5px 10px;
}
}
/* /*
* Checkbox editor * Checkbox editor
*/ */

View File

@ -51,6 +51,7 @@ Click the "Mark changed" button and "Reload page".
- changed.oc.changeMonitor - triggered when the form data changes. - changed.oc.changeMonitor - triggered when the form data changes.
- unchanged.oc.changeMonitor - triggered when the form data unchanges. - unchanged.oc.changeMonitor - triggered when the form data unchanges.
- ready.oc.changeMonitor triggered when the change monitor instance finishes initialization.
## JavaScript API ## JavaScript API

View File

@ -131,6 +131,15 @@
input = null input = null
}, 0) }, 0)
} }
},
elementContainsPoint: function(element, point) {
var elementPosition = $.oc.foundation.element.absolutePosition(element),
elementRight = elementPosition.left + element.offsetWidth,
elementBottom = elementPosition.top + element.offsetHeight
return point.x >= elementPosition.left && point.x <= elementRight
&& point.y >= elementPosition.top && point.y <= elementBottom
} }
} }

View File

@ -39,6 +39,7 @@
$(window).on('beforeunload', this.proxy(this.onBeforeUnload)) $(window).on('beforeunload', this.proxy(this.onBeforeUnload))
this.$el.one('dispose-control', this.proxy(this.dispose)) this.$el.one('dispose-control', this.proxy(this.dispose))
this.$el.trigger('ready.oc.changeMonitor')
} }
ChangeMonitor.prototype.dispose = function() { ChangeMonitor.prototype.dispose = function() {

View File

@ -139,6 +139,10 @@
$.oc.foundation.element.addClass(container, 'loading-indicator-container size-small') $.oc.foundation.element.addClass(container, 'loading-indicator-container size-small')
this.showLoadingIndicator() this.showLoadingIndicator()
if (this.triggerGetItems(data) === false) {
return
}
data['inspectorProperty'] = this.propertyDefinition.property data['inspectorProperty'] = this.propertyDefinition.property
data['inspectorClassName'] = this.inspector.options.inspectorClass data['inspectorClassName'] = this.inspector.options.inspectorClass
@ -149,13 +153,37 @@
.always(this.proxy(this.hideLoadingIndicator)) .always(this.proxy(this.hideLoadingIndicator))
} }
AutocompleteEditor.prototype.itemsRequestDone = function(data, currentValue, initialization) { AutocompleteEditor.prototype.triggerGetItems = function(values) {
var $inspectable = this.getInspectableElement()
if (!$inspectable) {
return true
}
var itemsEvent = $.Event('autocompleteitems.oc.inspector')
$inspectable.trigger(itemsEvent, [{
values: values,
callback: this.proxy(this.itemsRequestDone),
property: this.inspector.getPropertyPath(this.propertyDefinition.property),
propertyDefinition: this.propertyDefinition
}])
if (itemsEvent.isDefaultPrevented()) {
return false
}
return true
}
AutocompleteEditor.prototype.itemsRequestDone = function(data) {
if (this.isDisposed()) { if (this.isDisposed()) {
// Handle the case when the asynchronous request finishes after // Handle the case when the asynchronous request finishes after
// the editor is disposed // the editor is disposed
return return
} }
this.hideLoadingIndicator()
var loadedItems = {} var loadedItems = {}
if (data.options) { if (data.options) {

View File

@ -111,6 +111,18 @@
throw new Error(errorMessage + ' Property: ' + this.propertyDefinition.property) throw new Error(errorMessage + ' Property: ' + this.propertyDefinition.property)
} }
BaseEditor.prototype.getInspectableElement = function() {
return this.getRootSurface().getInspectableElement()
}
BaseEditor.prototype.isEmptyValue = function(value) {
return value === undefined
|| value === null
|| (typeof value == 'object' && $.isEmptyObject(value) )
|| (typeof value == 'string' && $.trim(value).length === 0)
|| (Object.prototype.toString.call(value) === '[object Array]' && value.length === 0)
}
// //
// Validation // Validation
// //
@ -127,7 +139,7 @@
return this.inspector.getPropertyValue(this.propertyDefinition.property) return this.inspector.getPropertyValue(this.propertyDefinition.property)
} }
BaseEditor.prototype.validate = function() { BaseEditor.prototype.validate = function(silentMode) {
var value = this.getValueToValidate() var value = this.getValueToValidate()
if (value === undefined) { if (value === undefined) {
@ -136,7 +148,9 @@
var validationResult = this.validationSet.validate(value) var validationResult = this.validationSet.validate(value)
if (validationResult !== null) { if (validationResult !== null) {
$.oc.flashMsg({text: validationResult, 'class': 'error', 'interval': 5}) if (!silentMode) {
$.oc.flashMsg({text: validationResult, 'class': 'error', 'interval': 5})
}
return false return false
} }

View File

@ -79,6 +79,14 @@
this.getInput().checked = this.normalizeCheckedValue(value) this.getInput().checked = this.normalizeCheckedValue(value)
} }
CheckboxEditor.prototype.isEmptyValue = function(value) {
if (value === 0 || value === '0' || value === 'false') {
return true
}
return BaseProto.isEmptyValue.call(this, value)
}
CheckboxEditor.prototype.registerHandlers = function() { CheckboxEditor.prototype.registerHandlers = function() {
var input = this.getInput() var input = this.getInput()

View File

@ -54,11 +54,41 @@
} }
} }
DropdownEditor.prototype.formatSelectOption = function(state) {
if (!state.id)
return state.text; // optgroup
var option = state.element,
iconClass = option.getAttribute('data-icon'),
imageSrc = option.getAttribute('data-image')
if (iconClass) {
return '<i class="select-icon '+iconClass+'"></i> ' + state.text
}
if (imageSrc) {
return '<img class="select-image" src="'+imageSrc+'" alt="" /> ' + state.text
}
return state.text
}
DropdownEditor.prototype.createOption = function(select, title, value) { DropdownEditor.prototype.createOption = function(select, title, value) {
var option = document.createElement('option') var option = document.createElement('option')
if (title !== null) { if (title !== null) {
option.textContent = title if (!$.isArray(title)) {
option.textContent = title
} else {
if (title[1].indexOf('.') !== -1) {
option.setAttribute('data-image', title[1])
}
else {
option.setAttribute('data-icon', title[1])
}
option.textContent = title[0]
}
} }
if (value !== null) { if (value !== null) {
@ -89,6 +119,12 @@
options.placeholder = this.propertyDefinition.placeholder options.placeholder = this.propertyDefinition.placeholder
} }
options.templateResult = this.formatSelectOption
options.templateSelection = this.formatSelectOption
options.escapeMarkup = function(m) {
return m
}
$(select).select2(options) $(select).select2(options)
if (!Modernizr.touch) { if (!Modernizr.touch) {
@ -135,6 +171,24 @@
return false return false
} }
DropdownEditor.prototype.normalizeValue = function(value) {
if (!this.propertyDefinition.booleanValues) {
return value
}
var str = String(value)
if (str.length === 0) {
return ''
}
if (str === 'true') {
return true
}
return false
}
// //
// Event handlers // Event handlers
// //
@ -148,7 +202,7 @@
DropdownEditor.prototype.onSelectionChange = function() { DropdownEditor.prototype.onSelectionChange = function() {
var select = this.getSelect() var select = this.getSelect()
this.inspector.setPropertyValue(this.propertyDefinition.property, select.value, this.initialization) this.inspector.setPropertyValue(this.propertyDefinition.property, this.normalizeValue(select.value), this.initialization)
} }
DropdownEditor.prototype.onInspectorPropertyChanged = function(property, value) { DropdownEditor.prototype.onInspectorPropertyChanged = function(property, value) {
@ -192,12 +246,24 @@
var select = this.getSelect() var select = this.getSelect()
if (select) { if (select) {
return select.value return this.normalizeValue(select.value)
} }
return undefined return undefined
} }
DropdownEditor.prototype.isEmptyValue = function(value) {
if (this.propertyDefinition.booleanValues) {
if (value === '') {
return true
}
return false
}
return BaseProto.isEmptyValue.call(this, value)
}
// //
// Disposing // Disposing
// //
@ -248,6 +314,11 @@
currentValue = this.propertyDefinition.default currentValue = this.propertyDefinition.default
} }
var callback = function dropdownOptionsRequestDoneClosure(data) {
self.hideLoadingIndicator()
self.optionsRequestDone(data, currentValue, true)
}
if (this.propertyDefinition.depends) { if (this.propertyDefinition.depends) {
this.saveDependencyValues() this.saveDependencyValues()
} }
@ -257,15 +328,39 @@
this.showLoadingIndicator() this.showLoadingIndicator()
if (this.triggerGetOptions(data, callback) === false) {
return
}
$form.request('onInspectableGetOptions', { $form.request('onInspectableGetOptions', {
data: data, data: data,
}).done(function dropdownOptionsRequestDoneClosure(data) { }).done(callback).always(
self.optionsRequestDone(data, currentValue, true)
}).always(
this.proxy(this.hideLoadingIndicator) this.proxy(this.hideLoadingIndicator)
) )
} }
DropdownEditor.prototype.triggerGetOptions = function(values, callback) {
var $inspectable = this.getInspectableElement()
if (!$inspectable) {
return true
}
var optionsEvent = $.Event('dropdownoptions.oc.inspector')
$inspectable.trigger(optionsEvent, [{
values: values,
callback: callback,
property: this.inspector.getPropertyPath(this.propertyDefinition.property),
propertyDefinition: this.propertyDefinition
}])
if (optionsEvent.isDefaultPrevented()) {
return false
}
return true
}
DropdownEditor.prototype.saveDependencyValues = function() { DropdownEditor.prototype.saveDependencyValues = function() {
this.prevDependencyValues = this.getDependencyValues() this.prevDependencyValues = this.getDependencyValues()
} }

View File

@ -49,7 +49,8 @@
this.inspector.getInspectorUniqueId() + '-' + this.propertyDefinition.property, this.inspector.getInspectorUniqueId() + '-' + this.propertyDefinition.property,
options, options,
this.inspector, this.inspector,
this.group) this.group,
this.propertyDefinition.property)
this.inspector.mergeChildSurface(this.childInspector, currentRow) this.inspector.mergeChildSurface(this.childInspector, currentRow)
} }
@ -70,14 +71,6 @@
return this.getValueOrRemove(value) return this.getValueOrRemove(value)
} }
ObjectEditor.prototype.isEmptyValue = function(value) {
return value === undefined
|| value === null
|| $.isEmptyObject(value)
|| (typeof value == 'string' && $.trim(value).length === 0)
|| (Object.prototype.toString.call(value) === '[object Array]' && value.length === 0)
}
ObjectEditor.prototype.getValueOrRemove = function(value) { ObjectEditor.prototype.getValueOrRemove = function(value) {
if (this.propertyDefinition.ignoreIfPropertyEmpty === undefined) { if (this.propertyDefinition.ignoreIfPropertyEmpty === undefined) {
return value return value
@ -120,8 +113,8 @@
return this.getValueOrRemove(result) return this.getValueOrRemove(result)
} }
ObjectEditor.prototype.validate = function() { ObjectEditor.prototype.validate = function(silentMode) {
var values = this.childInspector.getValues() var values = values = this.childInspector.getValues()
if (this.cleanUpValue(values) === $.oc.inspector.removedProperty) { if (this.cleanUpValue(values) === $.oc.inspector.removedProperty) {
// Ignore any validation rules if the object's required // Ignore any validation rules if the object's required
@ -130,7 +123,7 @@
return true return true
} }
return this.childInspector.validate() return this.childInspector.validate(silentMode)
} }
// //

View File

@ -319,19 +319,21 @@
currentValue = [] currentValue = []
} }
if (isChecked) { var resultValue = []
if (currentValue.indexOf(checkboxValue) === -1) { for (var itemValue in this.propertyDefinition.items) {
currentValue.push(checkboxValue) if (itemValue !== checkboxValue) {
} if (currentValue.indexOf(itemValue) !== -1) {
} resultValue.push(itemValue)
else { }
var index = currentValue.indexOf(checkboxValue) }
if (index !== -1) { else {
currentValue.splice(index, 1) if (isChecked) {
resultValue.push(itemValue)
}
} }
} }
this.inspector.setPropertyValue(this.propertyDefinition.property, this.cleanUpValue(currentValue)) this.inspector.setPropertyValue(this.propertyDefinition.property, this.cleanUpValue(resultValue))
this.setLinkText(this.getLink()) this.setLinkText(this.getLink())
} }

View File

@ -65,6 +65,8 @@
} }
$textarea.focus() $textarea.focus()
this.configureComment(popup)
} }
StringListEditor.prototype.handleSubmit = function($form) { StringListEditor.prototype.handleSubmit = function($form) {
@ -88,7 +90,6 @@
} }
this.inspector.setPropertyValue(this.propertyDefinition.property, resultValue) this.inspector.setPropertyValue(this.propertyDefinition.property, resultValue)
// TODO: validate here
} }
$.oc.inspector.propertyEditors.stringList = StringListEditor $.oc.inspector.propertyEditors.stringList = StringListEditor

View File

@ -46,6 +46,7 @@
</div> \ </div> \
<div class="modal-body"> \ <div class="modal-body"> \
<div class="form-group"> \ <div class="form-group"> \
<p class="inspector-field-comment"></p> \
<textarea class="form-control size-small field-textarea" name="name" value=""/> \ <textarea class="form-control size-small field-textarea" name="name" value=""/> \
</div> \ </div> \
</div> \ </div> \
@ -56,6 +57,15 @@
</form>' </form>'
} }
TextEditor.prototype.configureComment = function(popup) {
if (!this.propertyDefinition.description) {
return
}
var descriptionElement = $(popup).find('p.inspector-field-comment')
descriptionElement.text(this.propertyDefinition.description)
}
TextEditor.prototype.configurePopup = function(popup) { TextEditor.prototype.configurePopup = function(popup) {
var $textarea = $(popup).find('textarea'), var $textarea = $(popup).find('textarea'),
value = this.inspector.getPropertyValue(this.propertyDefinition.property) value = this.inspector.getPropertyValue(this.propertyDefinition.property)
@ -70,6 +80,8 @@
$textarea.val(value) $textarea.val(value)
$textarea.focus() $textarea.focus()
this.configureComment(popup)
} }
TextEditor.prototype.handleSubmit = function($form) { TextEditor.prototype.handleSubmit = function($form) {

View File

@ -40,6 +40,17 @@
}, },
groupIndex = 0 groupIndex = 0
for (var i = 0, len = properties.length; i < len; i++) {
var property = properties[i]
if (property['sortOrder'] === undefined) {
property['sortOrder'] = (i+1)*20
}
}
properties.sort(function(a, b){
return a['sortOrder'] - b['sortOrder']
})
for (var i = 0, len = properties.length; i < len; i++) { for (var i = 0, len = properties.length; i < len; i++) {
var property = properties[i] var property = properties[i]

View File

@ -241,12 +241,14 @@
this.getInput().focus() this.getInput().focus()
} }
ExternalParameterEditor.prototype.validate = function() { ExternalParameterEditor.prototype.validate = function(silentMode) {
var value = $.trim(this.getValue()) var value = $.trim(this.getValue())
if (value.length === 0) { if (value.length === 0) {
$.oc.flashMsg({text: 'Please enter the external parameter name.', 'class': 'error', 'interval': 5}) if (!silentMode) {
this.focus() $.oc.flashMsg({text: 'Please enter the external parameter name.', 'class': 'error', 'interval': 5})
this.focus()
}
return false return false
} }

View File

@ -163,6 +163,9 @@
if (this.createInspector($element) === false) { if (this.createInspector($element) === false) {
return false return false
} }
ev.stopPropagation()
return false
} }
$.oc.inspector.manager = new InspectorManager() $.oc.inspector.manager = new InspectorManager()

View File

@ -35,7 +35,7 @@
* not associated with an element. Inspector uses the ID for storing configuration * not associated with an element. Inspector uses the ID for storing configuration
* related to an element in the document DOM. * related to an element in the document DOM.
*/ */
var Surface = function(containerElement, properties, values, inspectorUniqueId, options, parentSurface, group) { var Surface = function(containerElement, properties, values, inspectorUniqueId, options, parentSurface, group, propertyName) {
if (inspectorUniqueId === undefined) { if (inspectorUniqueId === undefined) {
throw new Error('Inspector surface unique ID should be defined.') throw new Error('Inspector surface unique ID should be defined.')
} }
@ -50,6 +50,7 @@
this.idCounter = 1 this.idCounter = 1
this.popupCounter = 0 this.popupCounter = 0
this.parentSurface = parentSurface this.parentSurface = parentSurface
this.propertyName = propertyName
this.editors = [] this.editors = []
this.externalParameterEditors = [] this.externalParameterEditors = []
@ -91,6 +92,7 @@
this.options.onChange = null this.options.onChange = null
this.options.onPopupDisplayed = null this.options.onPopupDisplayed = null
this.options.onPopupHidden = null this.options.onPopupHidden = null
this.options.onGetInspectableElement = null
this.parentSurface = null this.parentSurface = null
this.groupManager = null this.groupManager = null
this.group = null this.group = null
@ -484,8 +486,6 @@
var editor = new $.oc.inspector.propertyEditors[type](this, property, cell, group) var editor = new $.oc.inspector.propertyEditors[type](this, property, cell, group)
if (editor.isGroupedEditor()) { if (editor.isGroupedEditor()) {
// property.groupedControl = true
$.oc.foundation.element.addClass(dataTable, 'has-groups') $.oc.foundation.element.addClass(dataTable, 'has-groups')
$.oc.foundation.element.addClass(row, 'control-group') $.oc.foundation.element.addClass(row, 'control-group')
@ -646,6 +646,31 @@
} }
} }
Surface.prototype.getInspectableElement = function() {
if (this.options.onGetInspectableElement !== null) {
return this.options.onGetInspectableElement()
}
}
Surface.prototype.getPropertyPath = function(propertyName) {
var result = [],
current = this
result.push(propertyName)
while (current) {
if (current.propertyName) {
result.push(current.propertyName)
}
current = current.parentSurface
}
result.reverse()
return result.join('.')
}
// //
// Nested surfaces support // Nested surfaces support
// //
@ -775,9 +800,9 @@
if (!externalParameterEditor || !externalParameterEditor.isEditorVisible()) { if (!externalParameterEditor || !externalParameterEditor.isEditorVisible()) {
value = this.getPropertyValue(property.property) value = this.getPropertyValue(property.property)
if (value === undefined) { var editor = this.findPropertyEditor(property.property)
var editor = this.findPropertyEditor(property.property)
if (value === undefined) {
if (editor) { if (editor) {
value = editor.getUndefinedValue() value = editor.getUndefinedValue()
} }
@ -789,6 +814,22 @@
if (value === $.oc.inspector.removedProperty) { if (value === $.oc.inspector.removedProperty) {
continue continue
} }
if (property.ignoreIfEmpty !== undefined && (property.ignoreIfEmpty === true || property.ignoreIfEmpty === "true") && editor) {
if (editor.isEmptyValue(value)) {
continue
}
}
if (property.ignoreIfDefault !== undefined && (property.ignoreIfDefault === true || property.ignoreIfDefault === "true") && editor) {
if (property.default === undefined) {
throw new Error('The ignoreIfDefault feature cannot be used without the default property value.')
}
if (this.comparePropertyValues(value, property.default)) {
continue
}
}
} }
else { else {
value = externalParameterEditor.getValue() value = externalParameterEditor.getValue()
@ -801,7 +842,35 @@
return result return result
} }
Surface.prototype.validate = function() { Surface.prototype.getValidValues = function() {
var allValues = this.getValues(),
result = {}
for (var property in allValues) {
var editor = this.findPropertyEditor(property)
if (!editor) {
throw new Error('Cannot find editor for property ' + property)
}
var externalEditor = this.findExternalParameterEditor(property)
if (externalEditor && externalEditor.isEditorVisible() && !externalEditor.validate(true)) {
result[property] = $.oc.inspector.invalidProperty
continue
}
if (!editor.validate(true)) {
result[property] = $.oc.inspector.invalidProperty
continue
}
result[property] = allValues[property]
}
return result
}
Surface.prototype.validate = function(silentMode) {
this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) this.getGroupManager().unmarkInvalidGroups(this.getRootTable())
for (var i = 0, len = this.editors.length; i < len; i++) { for (var i = 0, len = this.editors.length; i < len; i++) {
@ -809,8 +878,10 @@
externalEditor = this.findExternalParameterEditor(editor.propertyDefinition.property) externalEditor = this.findExternalParameterEditor(editor.propertyDefinition.property)
if (externalEditor && externalEditor.isEditorVisible()) { if (externalEditor && externalEditor.isEditorVisible()) {
if (!externalEditor.validate()) { if (!externalEditor.validate(silentMode)) {
editor.markInvalid() if (!silentMode) {
editor.markInvalid()
}
return false return false
} }
else { else {
@ -818,8 +889,10 @@
} }
} }
if (!editor.validate()) { if (!editor.validate(silentMode)) {
editor.markInvalid() if (!silentMode) {
editor.markInvalid()
}
return false return false
} }
} }
@ -827,8 +900,10 @@
return true return true
} }
Surface.prototype.hasChanges = function() { Surface.prototype.hasChanges = function(originalValues) {
return !this.comparePropertyValues(this.originalValues, this.values) var values = originalValues !== undefined ? originalValues : this.originalValues
return !this.comparePropertyValues(values, this.values)
} }
// EVENT HANDLERS // EVENT HANDLERS
@ -850,7 +925,8 @@
enableExternalParameterEditor: false, enableExternalParameterEditor: false,
onChange: null, onChange: null,
onPopupDisplayed: null, onPopupDisplayed: null,
onPopupHidden: null onPopupHidden: null,
onGetInspectableElement: null
} }
// REGISTRATION // REGISTRATION
@ -858,4 +934,5 @@
$.oc.inspector.surface = Surface $.oc.inspector.surface = Surface
$.oc.inspector.removedProperty = {removed: true} $.oc.inspector.removedProperty = {removed: true}
$.oc.inspector.invalidProperty = {invalid: true}
}(window.jQuery); }(window.jQuery);

View File

@ -23,6 +23,7 @@
this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options) this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options)
this.switched = false this.switched = false
this.configuration = null
Base.call(this) Base.call(this)
@ -59,10 +60,15 @@
this.$element.trigger('hidden.oc.inspector') this.$element.trigger('hidden.oc.inspector')
} }
if (this.surface !== null && this.surface.options.onGetInspectableElement === this.proxy(this.onGetInspectableElement)) {
this.surface.options.onGetInspectableElement = null
}
this.surface = null this.surface = null
this.$element = null this.$element = null
this.title = null this.title = null
this.description = null this.description = null
this.configuration = null
BaseProto.dispose.call(this) BaseProto.dispose.call(this)
} }
@ -91,7 +97,7 @@
// //
BaseWrapper.prototype.getElementValuesInput = function() { BaseWrapper.prototype.getElementValuesInput = function() {
return this.$element.find('input[data-inspector-values]') return this.$element.find('> input[data-inspector-values]')
} }
BaseWrapper.prototype.normalizePropertyCode = function(code, configuration) { BaseWrapper.prototype.normalizePropertyCode = function(code, configuration) {
@ -116,6 +122,7 @@
var options = this.$element.data() || {} var options = this.$element.data() || {}
options.enableExternalParameterEditor = this.isExternalParametersEditorEnabled() options.enableExternalParameterEditor = this.isExternalParametersEditorEnabled()
options.onGetInspectableElement = this.proxy(this.onGetInspectableElement)
this.surface = new $.oc.inspector.surface( this.surface = new $.oc.inspector.surface(
containerElement, containerElement,
@ -125,6 +132,10 @@
options) options)
} }
BaseWrapper.prototype.isLiveUpdateEnabled = function() {
return false
}
// //
// Wrapper API // Wrapper API
// //
@ -138,7 +149,7 @@
} }
BaseWrapper.prototype.adoptSurface = function() { BaseWrapper.prototype.adoptSurface = function() {
this.surface.options.onGetInspectableElement = this.proxy(this.onGetInspectableElement)
} }
BaseWrapper.prototype.cleanupAfterSwitch = function() { BaseWrapper.prototype.cleanupAfterSwitch = function() {
@ -195,9 +206,39 @@
return values return values
} }
BaseWrapper.prototype.applyValues = function() { BaseWrapper.prototype.applyValues = function(liveUpdateMode) {
var $valuesField = this.getElementValuesInput(), var $valuesField = this.getElementValuesInput(),
values = this.surface.getValues() values = liveUpdateMode ?
this.surface.getValidValues() :
this.surface.getValues()
if (liveUpdateMode) {
// In the live update mode, when only valid values are applied,
// we don't want to change all other values (invalid properties).
var existingValues = this.loadValues(this.configuration)
for (var property in values) {
if (values[property] !== $.oc.inspector.invalidProperty) {
existingValues[property] = values[property]
}
}
// Properties that use settings like ignoreIfPropertyEmpty could
// be removed from the list returned by getValidValues(). Removed
// properties should be removed from the result list.
var filteredValues = {}
for (var property in existingValues) {
if (values.hasOwnProperty(property)) {
filteredValues[property] = existingValues[property]
}
}
values = filteredValues
}
if ($valuesField.length > 0) { if ($valuesField.length > 0) {
$valuesField.val(JSON.stringify(values)) $valuesField.val(JSON.stringify(values))
@ -214,8 +255,34 @@
} }
} }
if (this.surface.hasChanges()) { // In the live update mode the livechange event is triggered
this.$element.trigger('change') // regardless of whether Surface properties match or don't match
// the original properties of the inspectable element. Without it
// there could be undesirable side effects.
if (liveUpdateMode) {
this.$element.trigger('livechange')
}
else {
var hasChanges = false
if (this.isLiveUpdateEnabled()) {
var currentValues = this.loadValues(this.configuration)
// If the Inspector setup supports the live update mode,
// evaluate changes as a difference between the current element
// properties and internal properties stored in the Surface.
// If there is no differences, the properties have already
// been applied with a preceding live update.
hasChanges = this.surface.hasChanges(currentValues)
}
else {
hasChanges = this.surface.hasChanges()
}
if (hasChanges) {
this.$element.trigger('change')
}
} }
} }
@ -241,7 +308,7 @@
return return
} }
var $configurationField = this.$element.find('input[data-inspector-config]') var $configurationField = this.$element.find('> input[data-inspector-config]')
if ($configurationField.length > 0) { if ($configurationField.length > 0) {
result.properties = this.parseConfiguration($configurationField.val()) result.properties = this.parseConfiguration($configurationField.val())
@ -287,6 +354,7 @@
this.title = configuration.title this.title = configuration.title
this.description = configuration.description this.description = configuration.description
this.configuration = configuration
this.createSurfaceAndUi(configuration.properties, values) this.createSurfaceAndUi(configuration.properties, values)
} }
@ -332,6 +400,10 @@
return !hidingEvent.isDefaultPrevented(); return !hidingEvent.isDefaultPrevented();
} }
BaseWrapper.prototype.onGetInspectableElement = function() {
return this.$element
}
BaseWrapper.DEFAULTS = { BaseWrapper.DEFAULTS = {
containerSupported: false containerSupported: false
} }

View File

@ -41,12 +41,22 @@
this.buildUi() this.buildUi()
this.initSurface(this.surfaceContainer, properties, values) this.initSurface(this.surfaceContainer, properties, values)
if (this.isLiveUpdateEnabled()) {
this.surface.options.onChange = this.proxy(this.onLiveUpdate)
}
} }
InspectorContainer.prototype.adoptSurface = function() { InspectorContainer.prototype.adoptSurface = function() {
this.buildUi() this.buildUi()
this.surface.moveToContainer(this.surfaceContainer) this.surface.moveToContainer(this.surfaceContainer)
if (this.isLiveUpdateEnabled()) {
this.surface.options.onChange = this.proxy(this.onLiveUpdate)
}
BaseProto.adoptSurface.call(this)
} }
InspectorContainer.prototype.buildUi = function() { InspectorContainer.prototype.buildUi = function() {
@ -115,18 +125,11 @@
InspectorContainer.prototype.buildLayout = function() { InspectorContainer.prototype.buildLayout = function() {
var layout = document.createElement('div'), var layout = document.createElement('div'),
headRow = document.createElement('div'), headRow = document.createElement('div'),
bodyRow = document.createElement('div'), bodyRow = document.createElement('div')
bodyCell = document.createElement('div'),
layoutRelative = document.createElement('div')
layout.setAttribute('class', 'layout') layout.setAttribute('class', 'flex-layout-column fill-container')
headRow.setAttribute('class', 'layout-row min-size') headRow.setAttribute('class', 'flex-layout-item fix')
bodyRow.setAttribute('class', 'layout-row') bodyRow.setAttribute('class', 'flex-layout-item stretch relative')
bodyCell.setAttribute('class', 'layout-cell')
layoutRelative.setAttribute('class', 'layout-relative')
bodyCell.appendChild(layoutRelative)
bodyRow.appendChild(bodyCell)
layout.appendChild(headRow) layout.appendChild(headRow)
layout.appendChild(bodyRow) layout.appendChild(bodyRow)
@ -138,7 +141,7 @@
return { return {
headContainer: headRow, headContainer: headRow,
bodyContainer: layoutRelative bodyContainer: bodyRow
} }
} }
@ -155,8 +158,12 @@
return this.options.container.data('inspector-scrollable') !== undefined return this.options.container.data('inspector-scrollable') !== undefined
} }
InspectorContainer.prototype.isLiveUpdateEnabled = function() {
return this.options.container.data('inspector-live-update') !== undefined
}
InspectorContainer.prototype.getLayout = function() { InspectorContainer.prototype.getLayout = function() {
return this.options.container.get(0).querySelector('div.layout') return this.options.container.get(0).querySelector('div.flex-layout-column')
} }
InspectorContainer.prototype.registerLayoutHandlers = function(layout) { InspectorContainer.prototype.registerLayoutHandlers = function(layout) {
@ -181,6 +188,10 @@
$layout.off('dispose-control', this.proxy(this.dispose)) $layout.off('dispose-control', this.proxy(this.dispose))
$layout.off('click', 'span.close', this.proxy(this.onClose)) $layout.off('click', 'span.close', this.proxy(this.onClose))
$layout.off('click', 'span.detach', this.proxy(this.onDetach)) $layout.off('click', 'span.detach', this.proxy(this.onDetach))
if (this.surface !== null && this.surface.options.onChange === this.proxy(this.onLiveUpdate)) {
this.surface.options.onChange = null
}
} }
InspectorContainer.prototype.removeControls = function() { InspectorContainer.prototype.removeControls = function() {
@ -222,6 +233,10 @@
this.dispose() this.dispose()
} }
InspectorContainer.prototype.onLiveUpdate = function() {
this.applyValues(true)
}
InspectorContainer.prototype.onDetach = function() { InspectorContainer.prototype.onDetach = function() {
$.oc.inspector.manager.switchToPopup(this) $.oc.inspector.manager.switchToPopup(this)
} }

View File

@ -45,6 +45,8 @@
this.repositionPopover() this.repositionPopover()
this.registerPopupHandlers() this.registerPopupHandlers()
BaseProto.adoptSurface.call(this)
} }
InspectorPopup.prototype.cleanupAfterSwitch = function() { InspectorPopup.prototype.cleanupAfterSwitch = function() {

View File

@ -0,0 +1,461 @@
/*
* Sortable plugin.
*
* Status: experimental. The behavior is not perfect, but it's OK in terms of memory
* usage and disposing.
*
* This is a lightweight, October-style implementation of the drag & drop sorting
* functionality. The plugin uses only HTML5 Drag&Drop feature and completely
* disposable.
*
* During the dragging the plugin creates a placeholder element, which should be
* styled separately.
*
* Draggable elements should be marked with "draggable" HTML5 attribute.
*
* Current / planned features:
*
* [x] Sorting a single list.
* [ ] Dragging items between multiple lists.
* [ ] Sorting nested lists.
* JAVASCRIPT API
*
* $('#list').listSortable({})
*
* DATA ATTRIBUTES API
*
* In the simplest case the plugin can be initialized like this:
* <ul data-control="list-sortable">
* <li draggable="true">...</li>
*
* Multiple lists will not support this option and the plugin should be created
* and updated by a caller code.
*
* Options:
* - handle: optional selector for a drag handle element. Also available as data-handle attribute.
* - direction: direction of the list - horizontal or vertical. Also available as data-direction attribute. Default is vertical.
*
* Events:
* - dragged.list.sortable - triggered on a list element after it was moved
*/
+function ($) { "use strict";
var Base = $.oc.foundation.base,
BaseProto = Base.prototype,
listSortableIdCounter = 0,
elementsIdCounter = 0
var ListSortable = function (element, options) {
this.lists = []
this.options = options
this.listSortableId = null
this.lastMousePosition = null
Base.call(this)
$.oc.foundation.controlUtils.markDisposable(element)
this.init()
this.addList(element)
}
ListSortable.prototype = Object.create(BaseProto)
ListSortable.prototype.constructor = ListSortable
ListSortable.prototype.init = function () {
listSortableIdCounter++
this.listSortableId = 'listsortable/id/' + listSortableIdCounter
}
ListSortable.prototype.addList = function(list) {
this.lists.push(list)
this.registerListHandlers(list)
if (this.lists.length == 1) {
$(list).one('dispose-control', this.proxy(this.dispose))
}
}
//
// Event management
//
ListSortable.prototype.registerListHandlers = function(list) {
var $list = $(list)
$list.on('dragstart', '> li', this.proxy(this.onDragStart))
$list.on('dragover', '> li', this.proxy(this.onDragOver))
$list.on('dragenter', '> li', this.proxy(this.onDragEnter))
$list.on('dragleave', '> li', this.proxy(this.onDragLeave))
$list.on('drop', '> li', this.proxy(this.onDragDrop))
$list.on('dragend', '> li', this.proxy(this.onDragEnd))
}
ListSortable.prototype.unregisterListHandlers = function(list) {
$list.off('dragstart', '> li', this.proxy(this.onDragStart))
$list.off('dragover', '> li', this.proxy(this.onDragOver))
$list.off('dragenter', '> li', this.proxy(this.onDragEnter))
$list.off('dragleave', '> li', this.proxy(this.onDragLeave))
$list.off('drop', '> li', this.proxy(this.onDragDrop))
$list.off('dragend', '> li', this.proxy(this.onDragEnd))
}
ListSortable.prototype.unregisterHandlers = function() {
$(document).off('dragover', this.proxy(this.onDocumentDragOver))
$(document).off('mousemove', this.proxy(this.onDocumentMouseMove))
$(this.lists[0]).off('dispose-control', this.proxy(this.dispose))
}
//
// Disposing
//
ListSortable.prototype.unbindLists = function() {
for (var i=this.lists.length-1; i>0; i--) {
var list = this.lists[i]
this.unregisterListHandlers(this.lists[i])
$(list).removeData('oc.listSortable')
}
}
ListSortable.prototype.dispose = function() {
this.unbindLists()
this.unregisterHandlers()
this.options = null
this.lists = []
BaseProto.dispose.call(this)
}
//
// Internal helpers
//
ListSortable.prototype.elementBelongsToManagedList = function(element) {
for (var i=this.lists.length-1; i >= 0; i--) {
var list = this.lists[i],
children = [].slice.call(list.children) // Converts HTMLCollection to array
if (children.indexOf(element) !== -1) {
return true
}
}
return false
}
ListSortable.prototype.isDragStartAllowed = function(element) {
// TODO: if handle selector is specified - test if
// the element is a handle.
return true
}
ListSortable.prototype.elementIsPlaceholder = function(element) {
return element.getAttribute('class') === 'list-sortable-placeholder'
}
ListSortable.prototype.getElementSortableId = function(element) {
if (element.hasAttribute('data-list-sortable-element-id')) {
return element.getAttribute('data-list-sortable-element-id')
}
elementsIdCounter++
var elementId = elementsIdCounter
element.setAttribute('data-list-sortable-element-id', elementsIdCounter)
return elementsIdCounter
}
ListSortable.prototype.dataTransferContains = function(ev, element) {
if (ev.dataTransfer.types.indexOf !== undefined){
return ev.dataTransfer.types.indexOf(element) >= 0
}
return ev.dataTransfer.types.contains(element)
}
ListSortable.prototype.isSourceManagedList = function(ev) {
return this.dataTransferContains(ev, this.listSortableId)
}
ListSortable.prototype.removePlaceholders = function() {
for (var i=this.lists.length-1; i >= 0; i--) {
var list = this.lists[i],
placeholders = list.querySelectorAll('.list-sortable-placeholder')
for (var j=placeholders.length-1; j >= 0; j--) {
list.removeChild(placeholders[j])
}
}
}
ListSortable.prototype.createPlaceholder = function(element, ev) {
var placeholder = document.createElement('li'),
placement = this.getPlaceholderPlacement(element, ev)
this.removePlaceholders()
placeholder.setAttribute('class', 'list-sortable-placeholder')
placeholder.setAttribute('draggable', true)
if (placement == 'before') {
element.parentNode.insertBefore(placeholder, element)
}
else {
element.parentNode.insertBefore(placeholder, element.nextSibling)
}
}
ListSortable.prototype.moveElement = function(target, ev) {
var list = target.parentNode,
placeholder = list.querySelector('.list-sortable-placeholder')
if (!placeholder) {
return
}
var elementId = ev.dataTransfer.getData('listsortable/elementid')
if (!elementId) {
return
}
var item = this.findDraggedItem(elementId)
if (!item) {
return
}
placeholder.parentNode.insertBefore(item, placeholder)
$(item).trigger('dragged.list.sortable')
}
ListSortable.prototype.findDraggedItem = function(elementId) {
for (var i=this.lists.length-1; i >= 0; i--) {
var list = this.lists[i],
item = list.querySelector('[data-list-sortable-element-id="'+elementId+'"]')
if (item) {
return item
}
}
return null
}
ListSortable.prototype.getPlaceholderPlacement = function(hoverElement, ev) {
var mousePosition = $.oc.foundation.event.pageCoordinates(ev),
elementPosition = $.oc.foundation.element.absolutePosition(hoverElement)
if (this.options.direction == 'vertical') {
var elementCenter = elementPosition.top + hoverElement.offsetHeight/2
return mousePosition.y <= elementCenter ? 'before' : 'after'
}
else {
var elementCenter = elementPosition.left + hoverElement.offsetWidth/2
return mousePosition.x <= elementCenter ? 'before' : 'after'
}
}
ListSortable.prototype.lastMousePositionChanged = function(ev) {
var mousePosition = $.oc.foundation.event.pageCoordinates(ev.originalEvent)
if (this.lastMousePosition === null || this.lastMousePosition.x != mousePosition.x || this.lastMousePosition.y != mousePosition.y) {
this.lastMousePosition = mousePosition
return true
}
return false
}
ListSortable.prototype.mouseOutsideLists = function(ev) {
var mousePosition = $.oc.foundation.event.pageCoordinates(ev)
for (var i=this.lists.length-1; i >= 0; i--) {
if ($.oc.foundation.element.elementContainsPoint(this.lists[i], mousePosition)) {
return false
}
}
return true
}
ListSortable.prototype.getClosestDraggableParent = function(element) {
var current = element
while (current) {
if (current.tagName === 'LI' && current.hasAttribute('draggable') ) {
return current
}
current = current.parentNode
}
return null
}
// EVENT HANDLERS
// ============================
ListSortable.prototype.onDragStart = function(ev) {
if (!this.isDragStartAllowed(ev.target)) {
return
}
ev.originalEvent.dataTransfer.effectAllowed = 'move'
ev.originalEvent.dataTransfer.setData('listsortable/elementid', this.getElementSortableId(ev.target))
ev.originalEvent.dataTransfer.setData(this.listSortableId, this.listSortableId)
// The mousemove handler is used to remove the placeholder
// when the drag is canceled with Escape button. We can't use
// the dragend for removing the placeholders because dragend
// is triggered before drop, but we need placeholder to exists
// in the drop handler.
//
// Mouse events are suppressed during the drag and drop operations,
// so we only need to handle it once (but we still must the handler
// explicitly).
$(document).on('mousemove', this.proxy(this.onDocumentMouseMove))
// The dragover handler is used to hide the placeholder when
// the mouse is outside of any known list.
$(document).on('dragover', this.proxy(this.onDocumentDragOver))
}
ListSortable.prototype.onDragOver = function(ev) {
if (!this.isSourceManagedList(ev.originalEvent)) {
return
}
var draggable = this.getClosestDraggableParent(ev.target)
if (!draggable) {
return
}
if (!this.elementIsPlaceholder(draggable) && this.lastMousePositionChanged(ev)) {
this.createPlaceholder(draggable, ev.originalEvent)
}
ev.stopPropagation()
ev.preventDefault()
ev.originalEvent.dataTransfer.dropEffect = 'move'
}
ListSortable.prototype.onDragEnter = function(ev) {
if (!this.isSourceManagedList(ev.originalEvent)) {
return
}
var draggable = this.getClosestDraggableParent(ev.target)
if (!draggable) {
return
}
if (this.elementIsPlaceholder(draggable)) {
return
}
this.createPlaceholder(draggable, ev.originalEvent)
ev.stopPropagation()
ev.preventDefault()
}
ListSortable.prototype.onDragLeave = function(ev) {
if (!this.isSourceManagedList(ev.originalEvent)) {
return
}
ev.stopPropagation()
ev.preventDefault()
}
ListSortable.prototype.onDragDrop = function(ev) {
if (!this.isSourceManagedList(ev.originalEvent)) {
return
}
var draggable = this.getClosestDraggableParent(ev.target)
if (!draggable) {
return
}
this.moveElement(draggable, ev.originalEvent)
this.removePlaceholders()
}
ListSortable.prototype.onDragEnd = function(ev) {
$(document).off('dragover', this.proxy(this.onDocumentDragOver))
}
ListSortable.prototype.onDocumentDragOver = function(ev) {
if (!this.isSourceManagedList(ev.originalEvent)) {
return
}
if (this.mouseOutsideLists(ev.originalEvent)) {
this.removePlaceholders()
return
}
}
ListSortable.prototype.onDocumentMouseMove = function(ev) {
$(document).off('mousemove', this.proxy(this.onDocumentMouseMove))
this.removePlaceholders()
}
// PLUGIN DEFINITION
// ============================
ListSortable.DEFAULTS = {
handle: null,
direction: 'vertical'
}
var old = $.fn.listSortable
$.fn.listSortable = function (option) {
var args = arguments
return this.each(function () {
var $this = $(this),
data = $this.data('oc.listSortable'),
options = $.extend({}, ListSortable.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) {
$this.data('oc.listSortable', (data = new ListSortable(this, options)))
}
if (typeof option == 'string' && data) {
if (data[option]) {
var methodArguments = Array.prototype.slice.call(args) // Clone the arguments array
methodArguments.shift()
data[option].apply(data, methodArguments)
}
}
})
}
$.fn.listSortable.Constructor = ListSortable
// LISTSORTABLE NO CONFLICT
// =================
$.fn.listSortable.noConflict = function () {
$.fn.listSortable = old
return this
}
$(document).render(function(){
$('[data-control=list-sortable]').listSortable()
})
}(window.jQuery);

View File

@ -181,6 +181,15 @@
this.firstDiv = this.$content.find('>div:first') this.firstDiv = this.$content.find('>div:first')
if (this.firstDiv.length > 0) if (this.firstDiv.length > 0)
this.firstDiv.data('oc.popup', this) this.firstDiv.data('oc.popup', this)
var $defaultFocus = $('[default-focus]', this.$content)
if ($defaultFocus.is(":visible"))
{
window.setTimeout(function() {
$defaultFocus.focus()
$defaultFocus = null
}, 300)
}
} }
Popup.prototype.setBackdrop = function(val) { Popup.prototype.setBackdrop = function(val) {

View File

@ -213,7 +213,7 @@
if ($('> li > a', this.$tabsContainer).length == 0) if ($('> li > a', this.$tabsContainer).length == 0)
this.$el.trigger('afterAllClosed.oc.tab') this.$el.trigger('afterAllClosed.oc.tab')
this.$el.trigger('closed.oc.tab', [$tab]) this.$el.trigger('closed.oc.tab', [$tab, $pane])
$(window).trigger('resize') $(window).trigger('resize')
this.updateClasses() this.updateClasses()
@ -265,6 +265,13 @@
return tab return tab
} }
Tab.prototype.findPaneFromTab = function(tab) {
var id = $(tab).find('> a').data('target'),
pane = this.$pagesContainer.find(id)
return pane
}
Tab.prototype.goTo = function(identifier) { Tab.prototype.goTo = function(identifier) {
var $tab = $('[data-tab-id="'+identifier+'" ]', this.$tabsContainer) var $tab = $('[data-tab-id="'+identifier+'" ]', this.$tabsContainer)

View File

@ -29,6 +29,8 @@
font-size: 13px; font-size: 13px;
padding: 10px 30px 10px 15px; padding: 10px 30px 10px 15px;
z-index: 10000; z-index: 10000;
word-wrap: break-word;
.border-radius(@border-radius-base); .border-radius(@border-radius-base);
&.fade { &.fade {

View File

@ -471,6 +471,12 @@ div.control-popover {
} }
} }
html.gecko.mac {
.scroll-wrapper.inspector-wrapper > div {
margin-right: 17px;
}
}
.inspector-table-list { .inspector-table-list {
border-top: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2;
.user-select(none); .user-select(none);
@ -597,11 +603,21 @@ div.inspector-dictionary-container {
} }
.inspector-container { .inspector-container {
&:empty {
display: none;
}
.control-scrollpad { .control-scrollpad {
position: absolute; position: absolute;
} }
} }
.inspector-field-comment {
&:empty {
display: none;
}
}
.select2-dropdown { .select2-dropdown {
&.ocInspectorDropdown { &.ocInspectorDropdown {
font-size: 12px; font-size: 12px;
@ -619,6 +635,10 @@ div.inspector-dictionary-container {
li.select2-no-results { li.select2-no-results {
padding: 5px 12px 5px; padding: 5px 12px 5px;
} }
li > i, li > img {
margin-left: 6px;
}
} }
.select2-search { .select2-search {

View File

@ -237,6 +237,10 @@ div.control-popover {
background-color: @color-popover-danger-bg; background-color: @color-popover-danger-bg;
} }
} }
div.popover-fixed-height {
height: 300px;
}
} }
.popover-highlight { .popover-highlight {
@ -285,6 +289,11 @@ div.popover-overlay {
} }
} }
div.popover-fixed-height {
height: 100%;
min-height: 100%;
}
.popover-head:before { .popover-head:before {
display: none; display: none;
} }

View File

@ -124,7 +124,7 @@
// Automatically set modal's width for larger viewports // Automatically set modal's width for larger viewports
.modal-dialog { .modal-dialog {
width: @modal-md; width: @modal-md;
margin: 30px auto; margin: 80px auto 30px auto; // The top margin is increased to avoid overlapping with flash messages
} }
.modal-content { .modal-content {
.box-shadow(0 5px 15px rgba(0,0,0,.5)); .box-shadow(0 5px 15px rgba(0,0,0,.5));

View File

@ -1864,7 +1864,8 @@ range=null
input=null},0)} input=null},0)}
if(input.selectionStart!==undefined){setTimeout(function(){input.selectionStart=position if(input.selectionStart!==undefined){setTimeout(function(){input.selectionStart=position
input.selectionEnd=position input.selectionEnd=position
input=null},0)}}} input=null},0)}},elementContainsPoint:function(element,point){var elementPosition=$.oc.foundation.element.absolutePosition(element),elementRight=elementPosition.left+element.offsetWidth,elementBottom=elementPosition.top+element.offsetHeight
return point.x>=elementPosition.left&&point.x<=elementRight&&point.y>=elementPosition.top&&point.y<=elementBottom}}
$.oc.foundation.element=Element;}(window.jQuery);+function($){"use strict";if($.oc===undefined) $.oc.foundation.element=Element;}(window.jQuery);+function($){"use strict";if($.oc===undefined)
$.oc={} $.oc={}
if($.oc.foundation===undefined) if($.oc.foundation===undefined)
@ -2461,7 +2462,11 @@ this.setLoading(false)
this.show() this.show()
this.firstDiv=this.$content.find('>div:first') this.firstDiv=this.$content.find('>div:first')
if(this.firstDiv.length>0) if(this.firstDiv.length>0)
this.firstDiv.data('oc.popup',this)} this.firstDiv.data('oc.popup',this)
var $defaultFocus=$('[default-focus]',this.$content)
if($defaultFocus.is(":visible"))
{window.setTimeout(function(){$defaultFocus.focus()
$defaultFocus=null},300)}}
Popup.prototype.setBackdrop=function(val){if(val&&!this.$backdrop){this.$backdrop=$('<div class="popup-backdrop fade" />') Popup.prototype.setBackdrop=function(val){if(val&&!this.$backdrop){this.$backdrop=$('<div class="popup-backdrop fade" />')
if(this.options.zIndex!==null) if(this.options.zIndex!==null)
this.$backdrop.css('z-index',this.options.zIndex) this.$backdrop.css('z-index',this.options.zIndex)
@ -2682,8 +2687,9 @@ var href=link.attr('href'),onclick=(typeof link.get(0).onclick=="function")?link
$(this).find('td').not('.'+options.excludeClass).click(function(){if(onclick) $(this).find('td').not('.'+options.excludeClass).click(function(){if(onclick)
onclick.apply(link.get(0)) onclick.apply(link.get(0))
else else
window.location=href}) window.location=href;})
$(this).addClass(options.linkedClass)})} $(this).addClass(options.linkedClass)
link.hide().after(link.html())})}
RowLink.DEFAULTS={target:'a',excludeClass:'nolink',linkedClass:'rowlink'} RowLink.DEFAULTS={target:'a',excludeClass:'nolink',linkedClass:'rowlink'}
var old=$.fn.rowLink var old=$.fn.rowLink
$.fn.rowLink=function(option){var args=Array.prototype.slice.call(arguments,1) $.fn.rowLink=function(option){var args=Array.prototype.slice.call(arguments,1)
@ -2711,7 +2717,8 @@ this.$el.on('keyup input paste','input, textarea:not(.ace_text-input)',this.prox
$('input:not([type=hidden]), textarea:not(.ace_text-input)',this.$el).each(function(){$(this).data('oldval.oc.changeMonitor',$(this).val());}) $('input:not([type=hidden]), textarea:not(.ace_text-input)',this.$el).each(function(){$(this).data('oldval.oc.changeMonitor',$(this).val());})
if(this.options.windowCloseConfirm) if(this.options.windowCloseConfirm)
$(window).on('beforeunload',this.proxy(this.onBeforeUnload)) $(window).on('beforeunload',this.proxy(this.onBeforeUnload))
this.$el.one('dispose-control',this.proxy(this.dispose))} this.$el.one('dispose-control',this.proxy(this.dispose))
this.$el.trigger('ready.oc.changeMonitor')}
ChangeMonitor.prototype.dispose=function(){if(this.$el===null) ChangeMonitor.prototype.dispose=function(){if(this.$el===null)
return return
this.unregisterHandlers() this.unregisterHandlers()
@ -3242,7 +3249,7 @@ if(isActive)
$('> li > a',this.$tabsContainer).eq(tabIndex-1).tab('show') $('> li > a',this.$tabsContainer).eq(tabIndex-1).tab('show')
if($('> li > a',this.$tabsContainer).length==0) if($('> li > a',this.$tabsContainer).length==0)
this.$el.trigger('afterAllClosed.oc.tab') this.$el.trigger('afterAllClosed.oc.tab')
this.$el.trigger('closed.oc.tab',[$tab]) this.$el.trigger('closed.oc.tab',[$tab,$pane])
$(window).trigger('resize') $(window).trigger('resize')
this.updateClasses()} this.updateClasses()}
Tab.prototype.updateClasses=function(){if(this.$tabsContainer.children().length>0) Tab.prototype.updateClasses=function(){if(this.$tabsContainer.children().length>0)
@ -3268,6 +3275,8 @@ tabParent=this.$tabsContainer
return tabParent.children().index($(tabToFind))} return tabParent.children().index($(tabToFind))}
Tab.prototype.findTabFromPane=function(pane){var id='#'+$(pane).attr('id'),tab=$('[data-target="'+id+'"]',this.$tabsContainer) Tab.prototype.findTabFromPane=function(pane){var id='#'+$(pane).attr('id'),tab=$('[data-target="'+id+'"]',this.$tabsContainer)
return tab} return tab}
Tab.prototype.findPaneFromTab=function(tab){var id=$(tab).find('> a').data('target'),pane=this.$pagesContainer.find(id)
return pane}
Tab.prototype.goTo=function(identifier){var $tab=$('[data-tab-id="'+identifier+'" ]',this.$tabsContainer) Tab.prototype.goTo=function(identifier){var $tab=$('[data-tab-id="'+identifier+'" ]',this.$tabsContainer)
if($tab.length==0) if($tab.length==0)
return false return false
@ -3331,7 +3340,7 @@ $.oc={}
if($.oc.inspector===undefined) if($.oc.inspector===undefined)
$.oc.inspector={} $.oc.inspector={}
var Base=$.oc.foundation.base,BaseProto=Base.prototype var Base=$.oc.foundation.base,BaseProto=Base.prototype
var Surface=function(containerElement,properties,values,inspectorUniqueId,options,parentSurface,group){if(inspectorUniqueId===undefined){throw new Error('Inspector surface unique ID should be defined.')} var Surface=function(containerElement,properties,values,inspectorUniqueId,options,parentSurface,group,propertyName){if(inspectorUniqueId===undefined){throw new Error('Inspector surface unique ID should be defined.')}
this.options=$.extend({},Surface.DEFAULTS,typeof options=='object'&&options) this.options=$.extend({},Surface.DEFAULTS,typeof options=='object'&&options)
this.rawProperties=properties this.rawProperties=properties
this.parsedProperties=$.oc.inspector.engine.processPropertyGroups(properties) this.parsedProperties=$.oc.inspector.engine.processPropertyGroups(properties)
@ -3342,6 +3351,7 @@ this.originalValues=$.extend(true,{},this.values)
this.idCounter=1 this.idCounter=1
this.popupCounter=0 this.popupCounter=0
this.parentSurface=parentSurface this.parentSurface=parentSurface
this.propertyName=propertyName
this.editors=[] this.editors=[]
this.externalParameterEditors=[] this.externalParameterEditors=[]
this.tableContainer=null this.tableContainer=null
@ -3369,6 +3379,7 @@ this.originalValues=null
this.options.onChange=null this.options.onChange=null
this.options.onPopupDisplayed=null this.options.onPopupDisplayed=null
this.options.onPopupHidden=null this.options.onPopupHidden=null
this.options.onGetInspectableElement=null
this.parentSurface=null this.parentSurface=null
this.groupManager=null this.groupManager=null
this.group=null this.group=null
@ -3526,6 +3537,13 @@ this.popupCounter++}
Surface.prototype.popupHidden=function(){this.popupCounter-- Surface.prototype.popupHidden=function(){this.popupCounter--
if(this.popupCounter<0){this.popupCounter=0} if(this.popupCounter<0){this.popupCounter=0}
if(this.popupCounter===0&&this.options.onPopupHidden!==null){this.options.onPopupHidden()}} if(this.popupCounter===0&&this.options.onPopupHidden!==null){this.options.onPopupHidden()}}
Surface.prototype.getInspectableElement=function(){if(this.options.onGetInspectableElement!==null){return this.options.onGetInspectableElement()}}
Surface.prototype.getPropertyPath=function(propertyName){var result=[],current=this
result.push(propertyName)
while(current){if(current.propertyName){result.push(current.propertyName)}
current=current.parentSurface}
result.reverse()
return result.join('.')}
Surface.prototype.mergeChildSurface=function(surface,mergeAfterRow){var rows=surface.tableContainer.querySelectorAll('table.inspector-fields > tbody > tr') Surface.prototype.mergeChildSurface=function(surface,mergeAfterRow){var rows=surface.tableContainer.querySelectorAll('table.inspector-fields > tbody > tr')
surface.tableContainer=this.getRootSurface().tableContainer surface.tableContainer=this.getRootSurface().tableContainer
for(var i=rows.length-1;i>=0;i--){var row=rows[i] for(var i=rows.length-1;i>=0;i--){var row=rows[i]
@ -3558,30 +3576,45 @@ for(var i=0,len=this.parsedProperties.properties.length;i<len;i++){var property=
if(property.itemType!=='property'){continue} if(property.itemType!=='property'){continue}
var value=null,externalParameterEditor=this.findExternalParameterEditor(property.property) var value=null,externalParameterEditor=this.findExternalParameterEditor(property.property)
if(!externalParameterEditor||!externalParameterEditor.isEditorVisible()){value=this.getPropertyValue(property.property) if(!externalParameterEditor||!externalParameterEditor.isEditorVisible()){value=this.getPropertyValue(property.property)
if(value===undefined){var editor=this.findPropertyEditor(property.property) var editor=this.findPropertyEditor(property.property)
if(editor){value=editor.getUndefinedValue()} if(value===undefined){if(editor){value=editor.getUndefinedValue()}
else{value=property.default}} else{value=property.default}}
if(value===$.oc.inspector.removedProperty){continue}} if(value===$.oc.inspector.removedProperty){continue}
if(property.ignoreIfEmpty!==undefined&&(property.ignoreIfEmpty===true||property.ignoreIfEmpty==="true")&&editor){if(editor.isEmptyValue(value)){continue}}
if(property.ignoreIfDefault!==undefined&&(property.ignoreIfDefault===true||property.ignoreIfDefault==="true")&&editor){if(property.default===undefined){throw new Error('The ignoreIfDefault feature cannot be used without the default property value.')}
if(this.comparePropertyValues(value,property.default)){continue}}}
else{value=externalParameterEditor.getValue() else{value=externalParameterEditor.getValue()
value='{{ '+value+' }}'} value='{{ '+value+' }}'}
result[property.property]=value} result[property.property]=value}
return result} return result}
Surface.prototype.validate=function(){this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) Surface.prototype.getValidValues=function(){var allValues=this.getValues(),result={}
for(var property in allValues){var editor=this.findPropertyEditor(property)
if(!editor){throw new Error('Cannot find editor for property '+property)}
var externalEditor=this.findExternalParameterEditor(property)
if(externalEditor&&externalEditor.isEditorVisible()&&!externalEditor.validate(true)){result[property]=$.oc.inspector.invalidProperty
continue}
if(!editor.validate(true)){result[property]=$.oc.inspector.invalidProperty
continue}
result[property]=allValues[property]}
return result}
Surface.prototype.validate=function(silentMode){this.getGroupManager().unmarkInvalidGroups(this.getRootTable())
for(var i=0,len=this.editors.length;i<len;i++){var editor=this.editors[i],externalEditor=this.findExternalParameterEditor(editor.propertyDefinition.property) for(var i=0,len=this.editors.length;i<len;i++){var editor=this.editors[i],externalEditor=this.findExternalParameterEditor(editor.propertyDefinition.property)
if(externalEditor&&externalEditor.isEditorVisible()){if(!externalEditor.validate()){editor.markInvalid() if(externalEditor&&externalEditor.isEditorVisible()){if(!externalEditor.validate(silentMode)){if(!silentMode){editor.markInvalid()}
return false} return false}
else{continue}} else{continue}}
if(!editor.validate()){editor.markInvalid() if(!editor.validate(silentMode)){if(!silentMode){editor.markInvalid()}
return false}} return false}}
return true} return true}
Surface.prototype.hasChanges=function(){return!this.comparePropertyValues(this.originalValues,this.values)} Surface.prototype.hasChanges=function(originalValues){var values=originalValues!==undefined?originalValues:this.originalValues
return!this.comparePropertyValues(values,this.values)}
Surface.prototype.onGroupClick=function(ev){var row=ev.currentTarget Surface.prototype.onGroupClick=function(ev){var row=ev.currentTarget
this.toggleGroup(row) this.toggleGroup(row)
$.oc.foundation.event.stop(ev) $.oc.foundation.event.stop(ev)
return false} return false}
Surface.DEFAULTS={enableExternalParameterEditor:false,onChange:null,onPopupDisplayed:null,onPopupHidden:null} Surface.DEFAULTS={enableExternalParameterEditor:false,onChange:null,onPopupDisplayed:null,onPopupHidden:null,onGetInspectableElement:null}
$.oc.inspector.surface=Surface $.oc.inspector.surface=Surface
$.oc.inspector.removedProperty={removed:true}}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype $.oc.inspector.removedProperty={removed:true}
$.oc.inspector.invalidProperty={invalid:true}}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype
var InspectorManager=function(){Base.call(this) var InspectorManager=function(){Base.call(this)
this.init()} this.init()}
InspectorManager.prototype=Object.create(BaseProto) InspectorManager.prototype=Object.create(BaseProto)
@ -3627,7 +3660,9 @@ InspectorManager.prototype.containerHidingAllowed=function($container){var allow
$container.trigger(allowedEvent) $container.trigger(allowedEvent)
return!allowedEvent.isDefaultPrevented();} return!allowedEvent.isDefaultPrevented();}
InspectorManager.prototype.onInspectableClicked=function(ev){var $element=$(ev.currentTarget) InspectorManager.prototype.onInspectableClicked=function(ev){var $element=$(ev.currentTarget)
if(this.createInspector($element)===false){return false}} if(this.createInspector($element)===false){return false}
ev.stopPropagation()
return false}
$.oc.inspector.manager=new InspectorManager() $.oc.inspector.manager=new InspectorManager()
$.fn.inspector=function(){return this.each(function(){$.oc.inspector.manager.createInspector(this)})}}(window.jQuery);+function($){"use strict";if($.oc.inspector===undefined) $.fn.inspector=function(){return this.each(function(){$.oc.inspector.manager.createInspector(this)})}}(window.jQuery);+function($){"use strict";if($.oc.inspector===undefined)
$.oc.inspector={} $.oc.inspector={}
@ -3637,6 +3672,7 @@ var Base=$.oc.foundation.base,BaseProto=Base.prototype
var BaseWrapper=function($element,sourceWrapper,options){this.$element=$element var BaseWrapper=function($element,sourceWrapper,options){this.$element=$element
this.options=$.extend({},BaseWrapper.DEFAULTS,typeof options=='object'&&options) this.options=$.extend({},BaseWrapper.DEFAULTS,typeof options=='object'&&options)
this.switched=false this.switched=false
this.configuration=null
Base.call(this) Base.call(this)
if(!sourceWrapper){if(!this.triggerShowingAndInit()){return} if(!sourceWrapper){if(!this.triggerShowingAndInit()){return}
this.surface=null this.surface=null
@ -3652,15 +3688,17 @@ BaseWrapper.prototype.constructor=Base
BaseWrapper.prototype.dispose=function(){if(!this.switched){this.$element.removeClass('inspector-open') BaseWrapper.prototype.dispose=function(){if(!this.switched){this.$element.removeClass('inspector-open')
this.setInspectorVisibleFlag(false) this.setInspectorVisibleFlag(false)
this.$element.trigger('hidden.oc.inspector')} this.$element.trigger('hidden.oc.inspector')}
if(this.surface!==null&&this.surface.options.onGetInspectableElement===this.proxy(this.onGetInspectableElement)){this.surface.options.onGetInspectableElement=null}
this.surface=null this.surface=null
this.$element=null this.$element=null
this.title=null this.title=null
this.description=null this.description=null
this.configuration=null
BaseProto.dispose.call(this)} BaseProto.dispose.call(this)}
BaseWrapper.prototype.init=function(){if(!this.surface){this.loadConfiguration()} BaseWrapper.prototype.init=function(){if(!this.surface){this.loadConfiguration()}
else{this.adoptSurface()} else{this.adoptSurface()}
this.$element.addClass('inspector-open')} this.$element.addClass('inspector-open')}
BaseWrapper.prototype.getElementValuesInput=function(){return this.$element.find('input[data-inspector-values]')} BaseWrapper.prototype.getElementValuesInput=function(){return this.$element.find('> input[data-inspector-values]')}
BaseWrapper.prototype.normalizePropertyCode=function(code,configuration){var lowerCaseCode=code.toLowerCase() BaseWrapper.prototype.normalizePropertyCode=function(code,configuration){var lowerCaseCode=code.toLowerCase()
for(var index in configuration){var propertyInfo=configuration[index] for(var index in configuration){var propertyInfo=configuration[index]
if(propertyInfo.property.toLowerCase()==lowerCaseCode){return propertyInfo.property}} if(propertyInfo.property.toLowerCase()==lowerCaseCode){return propertyInfo.property}}
@ -3668,10 +3706,12 @@ return code}
BaseWrapper.prototype.isExternalParametersEditorEnabled=function(){return this.$element.closest('[data-inspector-external-parameters]').length>0} BaseWrapper.prototype.isExternalParametersEditorEnabled=function(){return this.$element.closest('[data-inspector-external-parameters]').length>0}
BaseWrapper.prototype.initSurface=function(containerElement,properties,values){var options=this.$element.data()||{} BaseWrapper.prototype.initSurface=function(containerElement,properties,values){var options=this.$element.data()||{}
options.enableExternalParameterEditor=this.isExternalParametersEditorEnabled() options.enableExternalParameterEditor=this.isExternalParametersEditorEnabled()
options.onGetInspectableElement=this.proxy(this.onGetInspectableElement)
this.surface=new $.oc.inspector.surface(containerElement,properties,values,$.oc.inspector.helpers.generateElementUniqueId(this.$element.get(0)),options)} this.surface=new $.oc.inspector.surface(containerElement,properties,values,$.oc.inspector.helpers.generateElementUniqueId(this.$element.get(0)),options)}
BaseWrapper.prototype.isLiveUpdateEnabled=function(){return false}
BaseWrapper.prototype.createSurfaceAndUi=function(properties,values){} BaseWrapper.prototype.createSurfaceAndUi=function(properties,values){}
BaseWrapper.prototype.setInspectorVisibleFlag=function(value){this.$element.data('oc.inspectorVisible',value)} BaseWrapper.prototype.setInspectorVisibleFlag=function(value){this.$element.data('oc.inspectorVisible',value)}
BaseWrapper.prototype.adoptSurface=function(){} BaseWrapper.prototype.adoptSurface=function(){this.surface.options.onGetInspectableElement=this.proxy(this.onGetInspectableElement)}
BaseWrapper.prototype.cleanupAfterSwitch=function(){this.switched=true BaseWrapper.prototype.cleanupAfterSwitch=function(){this.switched=true
this.dispose()} this.dispose()}
BaseWrapper.prototype.loadValues=function(configuration){var $valuesField=this.getElementValuesInput() BaseWrapper.prototype.loadValues=function(configuration){var $valuesField=this.getElementValuesInput()
@ -3683,19 +3723,29 @@ for(var i=0,len=attributes.length;i<len;i++){var attribute=attributes[i],matches
if(matches=attribute.name.match(/^data-property-(.*)$/)){var normalizedPropertyName=this.normalizePropertyCode(matches[1],configuration) if(matches=attribute.name.match(/^data-property-(.*)$/)){var normalizedPropertyName=this.normalizePropertyCode(matches[1],configuration)
values[normalizedPropertyName]=attribute.value}} values[normalizedPropertyName]=attribute.value}}
return values} return values}
BaseWrapper.prototype.applyValues=function(){var $valuesField=this.getElementValuesInput(),values=this.surface.getValues() BaseWrapper.prototype.applyValues=function(liveUpdateMode){var $valuesField=this.getElementValuesInput(),values=liveUpdateMode?this.surface.getValidValues():this.surface.getValues()
if(liveUpdateMode){var existingValues=this.loadValues(this.configuration)
for(var property in values){if(values[property]!==$.oc.inspector.invalidProperty){existingValues[property]=values[property]}}
var filteredValues={}
for(var property in existingValues){if(values.hasOwnProperty(property)){filteredValues[property]=existingValues[property]}}
values=filteredValues}
if($valuesField.length>0){$valuesField.val(JSON.stringify(values))} if($valuesField.length>0){$valuesField.val(JSON.stringify(values))}
else{for(var property in values){var value=values[property] else{for(var property in values){var value=values[property]
if($.isArray(value)||$.isPlainObject(value)){throw new Error('Inspector data-property-xxx attributes do not support complex values. Property: '+property)} if($.isArray(value)||$.isPlainObject(value)){throw new Error('Inspector data-property-xxx attributes do not support complex values. Property: '+property)}
this.$element.attr('data-property-'+property,value)}} this.$element.attr('data-property-'+property,value)}}
if(this.surface.hasChanges()){this.$element.trigger('change')}} if(liveUpdateMode){this.$element.trigger('livechange')}
else{var hasChanges=false
if(this.isLiveUpdateEnabled()){var currentValues=this.loadValues(this.configuration)
hasChanges=this.surface.hasChanges(currentValues)}
else{hasChanges=this.surface.hasChanges()}
if(hasChanges){this.$element.trigger('change')}}}
BaseWrapper.prototype.loadConfiguration=function(){var configString=this.$element.data('inspector-config'),result={properties:{},title:null,description:null} BaseWrapper.prototype.loadConfiguration=function(){var configString=this.$element.data('inspector-config'),result={properties:{},title:null,description:null}
result.title=this.$element.data('inspector-title') result.title=this.$element.data('inspector-title')
result.description=this.$element.data('inspector-description') result.description=this.$element.data('inspector-description')
if(configString!==undefined){result.properties=this.parseConfiguration(configString) if(configString!==undefined){result.properties=this.parseConfiguration(configString)
this.configurationLoaded(result) this.configurationLoaded(result)
return} return}
var $configurationField=this.$element.find('input[data-inspector-config]') var $configurationField=this.$element.find('> input[data-inspector-config]')
if($configurationField.length>0){result.properties=this.parseConfiguration($configurationField.val()) if($configurationField.length>0){result.properties=this.parseConfiguration($configurationField.val())
this.configurationLoaded(result) this.configurationLoaded(result)
return} return}
@ -3709,6 +3759,7 @@ else{return configuration}}
BaseWrapper.prototype.configurationLoaded=function(configuration){var values=this.loadValues(configuration.properties) BaseWrapper.prototype.configurationLoaded=function(configuration){var values=this.loadValues(configuration.properties)
this.title=configuration.title this.title=configuration.title
this.description=configuration.description this.description=configuration.description
this.configuration=configuration
this.createSurfaceAndUi(configuration.properties,values)} this.createSurfaceAndUi(configuration.properties,values)}
BaseWrapper.prototype.onConfigurartionRequestDone=function(data,result){result.properties=this.parseConfiguration(data.configuration.properties) BaseWrapper.prototype.onConfigurartionRequestDone=function(data,result){result.properties=this.parseConfiguration(data.configuration.properties)
if(data.configuration.title!==undefined){result.title=data.configuration.title} if(data.configuration.title!==undefined){result.title=data.configuration.title}
@ -3722,6 +3773,7 @@ if(!e.isPropagationStopped()){this.init()}}
BaseWrapper.prototype.triggerHiding=function(){var hidingEvent=$.Event('hiding.oc.inspector'),values=this.surface.getValues() BaseWrapper.prototype.triggerHiding=function(){var hidingEvent=$.Event('hiding.oc.inspector'),values=this.surface.getValues()
this.$element.trigger(hidingEvent,[{values:values}]) this.$element.trigger(hidingEvent,[{values:values}])
return!hidingEvent.isDefaultPrevented();} return!hidingEvent.isDefaultPrevented();}
BaseWrapper.prototype.onGetInspectableElement=function(){return this.$element}
BaseWrapper.DEFAULTS={containerSupported:false} BaseWrapper.DEFAULTS={containerSupported:false}
$.oc.inspector.wrappers.base=BaseWrapper}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.wrappers.base,BaseProto=Base.prototype $.oc.inspector.wrappers.base=BaseWrapper}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.wrappers.base,BaseProto=Base.prototype
var InspectorPopup=function($element,surface,options){this.$popoverContainer=null var InspectorPopup=function($element,surface,options){this.$popoverContainer=null
@ -3741,7 +3793,8 @@ this.registerPopupHandlers()}
InspectorPopup.prototype.adoptSurface=function(){this.showPopover() InspectorPopup.prototype.adoptSurface=function(){this.showPopover()
this.surface.moveToContainer(this.$popoverContainer.find('[data-surface-container]').get(0)) this.surface.moveToContainer(this.$popoverContainer.find('[data-surface-container]').get(0))
this.repositionPopover() this.repositionPopover()
this.registerPopupHandlers()} this.registerPopupHandlers()
BaseProto.adoptSurface.call(this)}
InspectorPopup.prototype.cleanupAfterSwitch=function(){this.cleaningUp=true InspectorPopup.prototype.cleanupAfterSwitch=function(){this.cleaningUp=true
this.switched=true this.switched=true
this.forceClose()} this.forceClose()}
@ -3814,9 +3867,12 @@ this.removeControls()
this.surfaceContainer=null this.surfaceContainer=null
BaseProto.dispose.call(this)} BaseProto.dispose.call(this)}
InspectorContainer.prototype.createSurfaceAndUi=function(properties,values){this.buildUi() InspectorContainer.prototype.createSurfaceAndUi=function(properties,values){this.buildUi()
this.initSurface(this.surfaceContainer,properties,values)} this.initSurface(this.surfaceContainer,properties,values)
if(this.isLiveUpdateEnabled()){this.surface.options.onChange=this.proxy(this.onLiveUpdate)}}
InspectorContainer.prototype.adoptSurface=function(){this.buildUi() InspectorContainer.prototype.adoptSurface=function(){this.buildUi()
this.surface.moveToContainer(this.surfaceContainer)} this.surface.moveToContainer(this.surfaceContainer)
if(this.isLiveUpdateEnabled()){this.surface.options.onChange=this.proxy(this.onLiveUpdate)}
BaseProto.adoptSurface.call(this)}
InspectorContainer.prototype.buildUi=function(){var scrollable=this.isScrollable(),head=this.buildHead(),layoutElements=this.buildLayout() InspectorContainer.prototype.buildUi=function(){var scrollable=this.isScrollable(),head=this.buildHead(),layoutElements=this.buildLayout()
layoutElements.headContainer.appendChild(head) layoutElements.headContainer.appendChild(head)
if(scrollable){var scrollpad=this.buildScrollpad() if(scrollable){var scrollpad=this.buildScrollpad()
@ -3843,25 +3899,22 @@ scrollWrapper.setAttribute('class','scroll-wrapper inspector-wrapper')
scrollpad.appendChild(scrollWrapper) scrollpad.appendChild(scrollWrapper)
scrollWrapper.appendChild(scrollableContainer) scrollWrapper.appendChild(scrollableContainer)
return{scrollpad:scrollpad,container:scrollableContainer}} return{scrollpad:scrollpad,container:scrollableContainer}}
InspectorContainer.prototype.buildLayout=function(){var layout=document.createElement('div'),headRow=document.createElement('div'),bodyRow=document.createElement('div'),bodyCell=document.createElement('div'),layoutRelative=document.createElement('div') InspectorContainer.prototype.buildLayout=function(){var layout=document.createElement('div'),headRow=document.createElement('div'),bodyRow=document.createElement('div')
layout.setAttribute('class','layout') layout.setAttribute('class','flex-layout-column fill-container')
headRow.setAttribute('class','layout-row min-size') headRow.setAttribute('class','flex-layout-item fix')
bodyRow.setAttribute('class','layout-row') bodyRow.setAttribute('class','flex-layout-item stretch relative')
bodyCell.setAttribute('class','layout-cell')
layoutRelative.setAttribute('class','layout-relative')
bodyCell.appendChild(layoutRelative)
bodyRow.appendChild(bodyCell)
layout.appendChild(headRow) layout.appendChild(headRow)
layout.appendChild(bodyRow) layout.appendChild(bodyRow)
this.options.container.get(0).appendChild(layout) this.options.container.get(0).appendChild(layout)
$.oc.foundation.controlUtils.markDisposable(layout) $.oc.foundation.controlUtils.markDisposable(layout)
this.registerLayoutHandlers(layout) this.registerLayoutHandlers(layout)
return{headContainer:headRow,bodyContainer:layoutRelative}} return{headContainer:headRow,bodyContainer:bodyRow}}
InspectorContainer.prototype.validateAndApply=function(){if(!this.surface.validate()){return false} InspectorContainer.prototype.validateAndApply=function(){if(!this.surface.validate()){return false}
this.applyValues() this.applyValues()
return true} return true}
InspectorContainer.prototype.isScrollable=function(){return this.options.container.data('inspector-scrollable')!==undefined} InspectorContainer.prototype.isScrollable=function(){return this.options.container.data('inspector-scrollable')!==undefined}
InspectorContainer.prototype.getLayout=function(){return this.options.container.get(0).querySelector('div.layout')} InspectorContainer.prototype.isLiveUpdateEnabled=function(){return this.options.container.data('inspector-live-update')!==undefined}
InspectorContainer.prototype.getLayout=function(){return this.options.container.get(0).querySelector('div.flex-layout-column')}
InspectorContainer.prototype.registerLayoutHandlers=function(layout){var $layout=$(layout) InspectorContainer.prototype.registerLayoutHandlers=function(layout){var $layout=$(layout)
$layout.one('dispose-control',this.proxy(this.dispose)) $layout.one('dispose-control',this.proxy(this.dispose))
$layout.on('click','span.close',this.proxy(this.onClose)) $layout.on('click','span.close',this.proxy(this.onClose))
@ -3873,7 +3926,8 @@ this.options.container.off('apply.oc.inspector',this.proxy(this.onApplyValues))
this.options.container.off('beforeContainerHide.oc.inspector',this.proxy(this.onBeforeHide)) this.options.container.off('beforeContainerHide.oc.inspector',this.proxy(this.onBeforeHide))
$layout.off('dispose-control',this.proxy(this.dispose)) $layout.off('dispose-control',this.proxy(this.dispose))
$layout.off('click','span.close',this.proxy(this.onClose)) $layout.off('click','span.close',this.proxy(this.onClose))
$layout.off('click','span.detach',this.proxy(this.onDetach))} $layout.off('click','span.detach',this.proxy(this.onDetach))
if(this.surface!==null&&this.surface.options.onChange===this.proxy(this.onLiveUpdate)){this.surface.options.onChange=null}}
InspectorContainer.prototype.removeControls=function(){if(this.isScrollable()){this.options.container.find('.control-scrollpad').scrollpad('dispose')} InspectorContainer.prototype.removeControls=function(){if(this.isScrollable()){this.options.container.find('.control-scrollpad').scrollpad('dispose')}
var layout=this.getLayout() var layout=this.getLayout()
layout.parentNode.removeChild(layout)} layout.parentNode.removeChild(layout)}
@ -3887,6 +3941,7 @@ if(!this.triggerHiding()){ev.preventDefault()
return false} return false}
this.surface.dispose() this.surface.dispose()
this.dispose()} this.dispose()}
InspectorContainer.prototype.onLiveUpdate=function(){this.applyValues(true)}
InspectorContainer.prototype.onDetach=function(){$.oc.inspector.manager.switchToPopup(this)} InspectorContainer.prototype.onDetach=function(){$.oc.inspector.manager.switchToPopup(this)}
$.oc.inspector.wrappers.container=InspectorContainer}(window.jQuery);+function($){"use strict";var GroupManager=function(controlId){this.controlId=controlId $.oc.inspector.wrappers.container=InspectorContainer}(window.jQuery);+function($){"use strict";var GroupManager=function(controlId){this.controlId=controlId
this.rootGroup=null this.rootGroup=null
@ -3975,6 +4030,9 @@ if(property.itemType!==undefined&&property.itemType=='group'&&property.title==gr
return null} return null}
$.oc.inspector.engine.processPropertyGroups=function(properties){var fields=[],result={hasGroups:false,properties:[]},groupIndex=0 $.oc.inspector.engine.processPropertyGroups=function(properties){var fields=[],result={hasGroups:false,properties:[]},groupIndex=0
for(var i=0,len=properties.length;i<len;i++){var property=properties[i] for(var i=0,len=properties.length;i<len;i++){var property=properties[i]
if(property['sortOrder']===undefined){property['sortOrder']=(i+1)*20}}
properties.sort(function(a,b){return a['sortOrder']-b['sortOrder']})
for(var i=0,len=properties.length;i<len;i++){var property=properties[i]
property.itemType='property' property.itemType='property'
if(property.group===undefined){fields.push(property)} if(property.group===undefined){fields.push(property)}
else{var group=findGroup(property.group,fields) else{var group=findGroup(property.group,fields)
@ -4034,13 +4092,15 @@ BaseEditor.prototype.updateDisplayedValue=function(value){}
BaseEditor.prototype.getPropertyName=function(){return this.propertyDefinition.property} BaseEditor.prototype.getPropertyName=function(){return this.propertyDefinition.property}
BaseEditor.prototype.getUndefinedValue=function(){return this.propertyDefinition.default===undefined?undefined:this.propertyDefinition.default} BaseEditor.prototype.getUndefinedValue=function(){return this.propertyDefinition.default===undefined?undefined:this.propertyDefinition.default}
BaseEditor.prototype.throwError=function(errorMessage){throw new Error(errorMessage+' Property: '+this.propertyDefinition.property)} BaseEditor.prototype.throwError=function(errorMessage){throw new Error(errorMessage+' Property: '+this.propertyDefinition.property)}
BaseEditor.prototype.getInspectableElement=function(){return this.getRootSurface().getInspectableElement()}
BaseEditor.prototype.isEmptyValue=function(value){return value===undefined||value===null||(typeof value=='object'&&$.isEmptyObject(value))||(typeof value=='string'&&$.trim(value).length===0)||(Object.prototype.toString.call(value)==='[object Array]'&&value.length===0)}
BaseEditor.prototype.initValidation=function(){this.validationSet=new $.oc.inspector.validationSet(this.propertyDefinition,this.propertyDefinition.property)} BaseEditor.prototype.initValidation=function(){this.validationSet=new $.oc.inspector.validationSet(this.propertyDefinition,this.propertyDefinition.property)}
BaseEditor.prototype.disposeValidation=function(){this.validationSet.dispose()} BaseEditor.prototype.disposeValidation=function(){this.validationSet.dispose()}
BaseEditor.prototype.getValueToValidate=function(){return this.inspector.getPropertyValue(this.propertyDefinition.property)} BaseEditor.prototype.getValueToValidate=function(){return this.inspector.getPropertyValue(this.propertyDefinition.property)}
BaseEditor.prototype.validate=function(){var value=this.getValueToValidate() BaseEditor.prototype.validate=function(silentMode){var value=this.getValueToValidate()
if(value===undefined){value=this.getUndefinedValue()} if(value===undefined){value=this.getUndefinedValue()}
var validationResult=this.validationSet.validate(value) var validationResult=this.validationSet.validate(value)
if(validationResult!==null){$.oc.flashMsg({text:validationResult,'class':'error','interval':5}) if(validationResult!==null){if(!silentMode){$.oc.flashMsg({text:validationResult,'class':'error','interval':5})}
return false} return false}
return true} return true}
BaseEditor.prototype.markInvalid=function(){$.oc.foundation.element.addClass(this.containerRow,'invalid') BaseEditor.prototype.markInvalid=function(){$.oc.foundation.element.addClass(this.containerRow,'invalid')
@ -4111,6 +4171,8 @@ return value}
CheckboxEditor.prototype.getInput=function(){return this.containerCell.querySelector('input')} CheckboxEditor.prototype.getInput=function(){return this.containerCell.querySelector('input')}
CheckboxEditor.prototype.focus=function(){this.getInput().parentNode.focus()} CheckboxEditor.prototype.focus=function(){this.getInput().parentNode.focus()}
CheckboxEditor.prototype.updateDisplayedValue=function(value){this.getInput().checked=this.normalizeCheckedValue(value)} CheckboxEditor.prototype.updateDisplayedValue=function(value){this.getInput().checked=this.normalizeCheckedValue(value)}
CheckboxEditor.prototype.isEmptyValue=function(value){if(value===0||value==='0'||value==='false'){return true}
return BaseProto.isEmptyValue.call(this,value)}
CheckboxEditor.prototype.registerHandlers=function(){var input=this.getInput() CheckboxEditor.prototype.registerHandlers=function(){var input=this.getInput()
input.addEventListener('change',this.proxy(this.onInputChange))} input.addEventListener('change',this.proxy(this.onInputChange))}
CheckboxEditor.prototype.unregisterHandlers=function(){var input=this.getInput() CheckboxEditor.prototype.unregisterHandlers=function(){var input=this.getInput()
@ -4136,8 +4198,15 @@ if(!this.dynamicOptions){this.loadStaticOptions(select)}
this.containerCell.appendChild(select) this.containerCell.appendChild(select)
this.initCustomSelect() this.initCustomSelect()
if(this.dynamicOptions){this.loadDynamicOptions(true)}} if(this.dynamicOptions){this.loadDynamicOptions(true)}}
DropdownEditor.prototype.formatSelectOption=function(state){if(!state.id)
return state.text;var option=state.element,iconClass=option.getAttribute('data-icon'),imageSrc=option.getAttribute('data-image')
if(iconClass){return'<i class="select-icon '+iconClass+'"></i> '+state.text}
if(imageSrc){return'<img class="select-image" src="'+imageSrc+'" alt="" /> '+state.text}
return state.text}
DropdownEditor.prototype.createOption=function(select,title,value){var option=document.createElement('option') DropdownEditor.prototype.createOption=function(select,title,value){var option=document.createElement('option')
if(title!==null){option.textContent=title} if(title!==null){if(!$.isArray(title)){option.textContent=title}else{if(title[1].indexOf('.')!==-1){option.setAttribute('data-image',title[1])}
else{option.setAttribute('data-icon',title[1])}
option.textContent=title[0]}}
if(value!==null){option.value=value} if(value!==null){option.value=value}
select.appendChild(option)} select.appendChild(option)}
DropdownEditor.prototype.createOptions=function(select,options){for(var value in options){this.createOption(select,options[value],value)}} DropdownEditor.prototype.createOptions=function(select,options){for(var value in options){this.createOption(select,options[value],value)}}
@ -4145,6 +4214,9 @@ DropdownEditor.prototype.initCustomSelect=function(){var select=this.getSelect()
if(Modernizr.touch){return} if(Modernizr.touch){return}
var options={dropdownCssClass:'ocInspectorDropdown'} var options={dropdownCssClass:'ocInspectorDropdown'}
if(this.propertyDefinition.placeholder!==undefined){options.placeholder=this.propertyDefinition.placeholder} if(this.propertyDefinition.placeholder!==undefined){options.placeholder=this.propertyDefinition.placeholder}
options.templateResult=this.formatSelectOption
options.templateSelection=this.formatSelectOption
options.escapeMarkup=function(m){return m}
$(select).select2(options) $(select).select2(options)
if(!Modernizr.touch){this.indicatorContainer=$('.select2-container',this.containerCell) if(!Modernizr.touch){this.indicatorContainer=$('.select2-container',this.containerCell)
this.indicatorContainer.addClass('loading-indicator-container size-small')}} this.indicatorContainer.addClass('loading-indicator-container size-small')}}
@ -4156,10 +4228,15 @@ DropdownEditor.prototype.clearOptions=function(select){while(select.firstChild){
DropdownEditor.prototype.hasOptionValue=function(select,value){var options=select.children DropdownEditor.prototype.hasOptionValue=function(select,value){var options=select.children
for(var i=0,len=options.length;i<len;i++){if(options[i].value==value){return true}} for(var i=0,len=options.length;i<len;i++){if(options[i].value==value){return true}}
return false} return false}
DropdownEditor.prototype.normalizeValue=function(value){if(!this.propertyDefinition.booleanValues){return value}
var str=String(value)
if(str.length===0){return''}
if(str==='true'){return true}
return false}
DropdownEditor.prototype.registerHandlers=function(){var select=this.getSelect() DropdownEditor.prototype.registerHandlers=function(){var select=this.getSelect()
$(select).on('change',this.proxy(this.onSelectionChange))} $(select).on('change',this.proxy(this.onSelectionChange))}
DropdownEditor.prototype.onSelectionChange=function(){var select=this.getSelect() DropdownEditor.prototype.onSelectionChange=function(){var select=this.getSelect()
this.inspector.setPropertyValue(this.propertyDefinition.property,select.value,this.initialization)} this.inspector.setPropertyValue(this.propertyDefinition.property,this.normalizeValue(select.value),this.initialization)}
DropdownEditor.prototype.onInspectorPropertyChanged=function(property,value){if(!this.propertyDefinition.depends||this.propertyDefinition.depends.indexOf(property)===-1){return} DropdownEditor.prototype.onInspectorPropertyChanged=function(property,value){if(!this.propertyDefinition.depends||this.propertyDefinition.depends.indexOf(property)===-1){return}
var dependencyValues=this.getDependencyValues() var dependencyValues=this.getDependencyValues()
if(this.prevDependencyValues===undefined||this.prevDependencyValues!=dependencyValues){this.loadDynamicOptions()}} if(this.prevDependencyValues===undefined||this.prevDependencyValues!=dependencyValues){this.loadDynamicOptions()}}
@ -4169,8 +4246,11 @@ select.value=value}
DropdownEditor.prototype.getUndefinedValue=function(){if(this.propertyDefinition.default!==undefined){return this.propertyDefinition.default} DropdownEditor.prototype.getUndefinedValue=function(){if(this.propertyDefinition.default!==undefined){return this.propertyDefinition.default}
if(this.propertyDefinition.placeholder!==undefined){return undefined} if(this.propertyDefinition.placeholder!==undefined){return undefined}
var select=this.getSelect() var select=this.getSelect()
if(select){return select.value} if(select){return this.normalizeValue(select.value)}
return undefined} return undefined}
DropdownEditor.prototype.isEmptyValue=function(value){if(this.propertyDefinition.booleanValues){if(value===''){return true}
return false}
return BaseProto.isEmptyValue.call(this,value)}
DropdownEditor.prototype.destroyCustomSelect=function(){var $select=$(this.getSelect()) DropdownEditor.prototype.destroyCustomSelect=function(){var $select=$(this.getSelect())
if($select.data('select2')!=null){$select.select2('destroy')}} if($select.data('select2')!=null){$select.select2('destroy')}}
DropdownEditor.prototype.unregisterHandlers=function(){var select=this.getSelect() DropdownEditor.prototype.unregisterHandlers=function(){var select=this.getSelect()
@ -4182,11 +4262,20 @@ if(value===undefined){value=this.propertyDefinition.default}
select.value=value} select.value=value}
DropdownEditor.prototype.loadDynamicOptions=function(initialization){var currentValue=this.inspector.getPropertyValue(this.propertyDefinition.property),data=this.inspector.getValues(),self=this,$form=$(this.getSelect()).closest('form') DropdownEditor.prototype.loadDynamicOptions=function(initialization){var currentValue=this.inspector.getPropertyValue(this.propertyDefinition.property),data=this.inspector.getValues(),self=this,$form=$(this.getSelect()).closest('form')
if(currentValue===undefined){currentValue=this.propertyDefinition.default} if(currentValue===undefined){currentValue=this.propertyDefinition.default}
var callback=function dropdownOptionsRequestDoneClosure(data){self.hideLoadingIndicator()
self.optionsRequestDone(data,currentValue,true)}
if(this.propertyDefinition.depends){this.saveDependencyValues()} if(this.propertyDefinition.depends){this.saveDependencyValues()}
data['inspectorProperty']=this.propertyDefinition.property data['inspectorProperty']=this.propertyDefinition.property
data['inspectorClassName']=this.inspector.options.inspectorClass data['inspectorClassName']=this.inspector.options.inspectorClass
this.showLoadingIndicator() this.showLoadingIndicator()
$form.request('onInspectableGetOptions',{data:data,}).done(function dropdownOptionsRequestDoneClosure(data){self.optionsRequestDone(data,currentValue,true)}).always(this.proxy(this.hideLoadingIndicator))} if(this.triggerGetOptions(data,callback)===false){return}
$form.request('onInspectableGetOptions',{data:data,}).done(callback).always(this.proxy(this.hideLoadingIndicator))}
DropdownEditor.prototype.triggerGetOptions=function(values,callback){var $inspectable=this.getInspectableElement()
if(!$inspectable){return true}
var optionsEvent=$.Event('dropdownoptions.oc.inspector')
$inspectable.trigger(optionsEvent,[{values:values,callback:callback,property:this.inspector.getPropertyPath(this.propertyDefinition.property),propertyDefinition:this.propertyDefinition}])
if(optionsEvent.isDefaultPrevented()){return false}
return true}
DropdownEditor.prototype.saveDependencyValues=function(){this.prevDependencyValues=this.getDependencyValues()} DropdownEditor.prototype.saveDependencyValues=function(){this.prevDependencyValues=this.getDependencyValues()}
DropdownEditor.prototype.getDependencyValues=function(){var result='' DropdownEditor.prototype.getDependencyValues=function(){var result=''
for(var i=0,len=this.propertyDefinition.depends.length;i<len;i++){var property=this.propertyDefinition.depends[i],value=this.inspector.getPropertyValue(property) for(var i=0,len=this.propertyDefinition.depends.length;i<len;i++){var property=this.propertyDefinition.depends[i],value=this.inspector.getPropertyValue(property)
@ -4287,6 +4376,7 @@ TextEditor.prototype.getPopupContent=function(){return'<form>
</div> \ </div> \
<div class="modal-body"> \ <div class="modal-body"> \
<div class="form-group"> \ <div class="form-group"> \
<p class="inspector-field-comment"></p> \
<textarea class="form-control size-small field-textarea" name="name" value=""/> \ <textarea class="form-control size-small field-textarea" name="name" value=""/> \
</div> \ </div> \
</div> \ </div> \
@ -4295,11 +4385,15 @@ TextEditor.prototype.getPopupContent=function(){return'<form>
<button type="button" class="btn btn-default" data-dismiss="popup">Cancel</button> \ <button type="button" class="btn btn-default" data-dismiss="popup">Cancel</button> \
</div> \ </div> \
</form>'} </form>'}
TextEditor.prototype.configureComment=function(popup){if(!this.propertyDefinition.description){return}
var descriptionElement=$(popup).find('p.inspector-field-comment')
descriptionElement.text(this.propertyDefinition.description)}
TextEditor.prototype.configurePopup=function(popup){var $textarea=$(popup).find('textarea'),value=this.inspector.getPropertyValue(this.propertyDefinition.property) TextEditor.prototype.configurePopup=function(popup){var $textarea=$(popup).find('textarea'),value=this.inspector.getPropertyValue(this.propertyDefinition.property)
if(this.propertyDefinition.placeholder){$textarea.attr('placeholder',this.propertyDefinition.placeholder)} if(this.propertyDefinition.placeholder){$textarea.attr('placeholder',this.propertyDefinition.placeholder)}
if(value===undefined){value=this.propertyDefinition.default} if(value===undefined){value=this.propertyDefinition.default}
$textarea.val(value) $textarea.val(value)
$textarea.focus()} $textarea.focus()
this.configureComment(popup)}
TextEditor.prototype.handleSubmit=function($form){var $textarea=$form.find('textarea'),link=this.getLink(),value=$.trim($textarea.val()) TextEditor.prototype.handleSubmit=function($form){var $textarea=$form.find('textarea'),link=this.getLink(),value=$.trim($textarea.val())
this.inspector.setPropertyValue(this.propertyDefinition.property,value)} this.inspector.setPropertyValue(this.propertyDefinition.property,value)}
$.oc.inspector.propertyEditors.text=TextEditor}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.propertyEditors.base,BaseProto=Base.prototype $.oc.inspector.propertyEditors.text=TextEditor}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.propertyEditors.base,BaseProto=Base.prototype
@ -4385,10 +4479,10 @@ return value.indexOf(checkboxValue)>-1}
SetEditor.prototype.setPropertyValue=function(checkboxValue,isChecked){var currentValue=this.getNormalizedValue() SetEditor.prototype.setPropertyValue=function(checkboxValue,isChecked){var currentValue=this.getNormalizedValue()
if(currentValue===undefined){currentValue=this.propertyDefinition.default} if(currentValue===undefined){currentValue=this.propertyDefinition.default}
if(!currentValue){currentValue=[]} if(!currentValue){currentValue=[]}
if(isChecked){if(currentValue.indexOf(checkboxValue)===-1){currentValue.push(checkboxValue)}} var resultValue=[]
else{var index=currentValue.indexOf(checkboxValue) for(var itemValue in this.propertyDefinition.items){if(itemValue!==checkboxValue){if(currentValue.indexOf(itemValue)!==-1){resultValue.push(itemValue)}}
if(index!==-1){currentValue.splice(index,1)}} else{if(isChecked){resultValue.push(itemValue)}}}
this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(currentValue)) this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(resultValue))
this.setLinkText(this.getLink())} this.setLinkText(this.getLink())}
SetEditor.prototype.generateSequencedId=function(){return this.inspector.generateSequencedId()} SetEditor.prototype.generateSequencedId=function(){return this.inspector.generateSequencedId()}
SetEditor.prototype.disposeEditors=function(){for(var i=0,len=this.editors.length;i<len;i++){var editor=this.editors[i] SetEditor.prototype.disposeEditors=function(){for(var i=0,len=this.editors.length;i<len;i++){var editor=this.editors[i]
@ -4664,12 +4758,11 @@ ObjectEditor.prototype.init=function(){this.initControlGroup()
BaseProto.init.call(this)} BaseProto.init.call(this)}
ObjectEditor.prototype.build=function(){var currentRow=this.containerCell.parentNode,inspectorContainer=document.createElement('div'),options={enableExternalParameterEditor:false,onChange:this.proxy(this.onInspectorDataChange),inspectorClass:this.inspector.options.inspectorClass},values=this.inspector.getPropertyValue(this.propertyDefinition.property) ObjectEditor.prototype.build=function(){var currentRow=this.containerCell.parentNode,inspectorContainer=document.createElement('div'),options={enableExternalParameterEditor:false,onChange:this.proxy(this.onInspectorDataChange),inspectorClass:this.inspector.options.inspectorClass},values=this.inspector.getPropertyValue(this.propertyDefinition.property)
if(values===undefined){values={}} if(values===undefined){values={}}
this.childInspector=new $.oc.inspector.surface(inspectorContainer,this.propertyDefinition.properties,values,this.inspector.getInspectorUniqueId()+'-'+this.propertyDefinition.property,options,this.inspector,this.group) this.childInspector=new $.oc.inspector.surface(inspectorContainer,this.propertyDefinition.properties,values,this.inspector.getInspectorUniqueId()+'-'+this.propertyDefinition.property,options,this.inspector,this.group,this.propertyDefinition.property)
this.inspector.mergeChildSurface(this.childInspector,currentRow)} this.inspector.mergeChildSurface(this.childInspector,currentRow)}
ObjectEditor.prototype.cleanUpValue=function(value){if(value===undefined||typeof value!=='object'){return undefined} ObjectEditor.prototype.cleanUpValue=function(value){if(value===undefined||typeof value!=='object'){return undefined}
if(this.propertyDefinition.ignoreIfPropertyEmpty===undefined){return value} if(this.propertyDefinition.ignoreIfPropertyEmpty===undefined){return value}
return this.getValueOrRemove(value)} return this.getValueOrRemove(value)}
ObjectEditor.prototype.isEmptyValue=function(value){return value===undefined||value===null||$.isEmptyObject(value)||(typeof value=='string'&&$.trim(value).length===0)||(Object.prototype.toString.call(value)==='[object Array]'&&value.length===0)}
ObjectEditor.prototype.getValueOrRemove=function(value){if(this.propertyDefinition.ignoreIfPropertyEmpty===undefined){return value} ObjectEditor.prototype.getValueOrRemove=function(value){if(this.propertyDefinition.ignoreIfPropertyEmpty===undefined){return value}
var targetProperty=this.propertyDefinition.ignoreIfPropertyEmpty,targetValue=value[targetProperty] var targetProperty=this.propertyDefinition.ignoreIfPropertyEmpty,targetValue=value[targetProperty]
if(this.isEmptyValue(targetValue)){return $.oc.inspector.removedProperty} if(this.isEmptyValue(targetValue)){return $.oc.inspector.removedProperty}
@ -4680,9 +4773,9 @@ ObjectEditor.prototype.getUndefinedValue=function(){var result={}
for(var i=0,len=this.propertyDefinition.properties.length;i<len;i++){var propertyName=this.propertyDefinition.properties[i].property,editor=this.childInspector.findPropertyEditor(propertyName) for(var i=0,len=this.propertyDefinition.properties.length;i<len;i++){var propertyName=this.propertyDefinition.properties[i].property,editor=this.childInspector.findPropertyEditor(propertyName)
if(editor){result[propertyName]=editor.getUndefinedValue()}} if(editor){result[propertyName]=editor.getUndefinedValue()}}
return this.getValueOrRemove(result)} return this.getValueOrRemove(result)}
ObjectEditor.prototype.validate=function(){var values=this.childInspector.getValues() ObjectEditor.prototype.validate=function(silentMode){var values=values=this.childInspector.getValues()
if(this.cleanUpValue(values)===$.oc.inspector.removedProperty){return true} if(this.cleanUpValue(values)===$.oc.inspector.removedProperty){return true}
return this.childInspector.validate()} return this.childInspector.validate(silentMode)}
ObjectEditor.prototype.onInspectorDataChange=function(property,value){var values=this.childInspector.getValues() ObjectEditor.prototype.onInspectorDataChange=function(property,value){var values=this.childInspector.getValues()
this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(values))} this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(values))}
$.oc.inspector.propertyEditors.object=ObjectEditor}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.propertyEditors.text,BaseProto=Base.prototype $.oc.inspector.propertyEditors.object=ObjectEditor}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.propertyEditors.text,BaseProto=Base.prototype
@ -4704,7 +4797,8 @@ if(this.propertyDefinition.placeholder){$textarea.attr('placeholder',this.proper
if(value===undefined){value=this.propertyDefinition.default} if(value===undefined){value=this.propertyDefinition.default}
this.checkValueType(value) this.checkValueType(value)
if(value&&value.length){$textarea.val(value.join('\n'))} if(value&&value.length){$textarea.val(value.join('\n'))}
$textarea.focus()} $textarea.focus()
this.configureComment(popup)}
StringListEditor.prototype.handleSubmit=function($form){var $textarea=$form.find('textarea'),link=this.getLink(),value=$.trim($textarea.val()),arrayValue=[],resultValue=[] StringListEditor.prototype.handleSubmit=function($form){var $textarea=$form.find('textarea'),link=this.getLink(),value=$.trim($textarea.val()),arrayValue=[],resultValue=[]
if(value.length){value=value.replace(/\r\n/g,'\n') if(value.length){value=value.replace(/\r\n/g,'\n')
arrayValue=value.split('\n') arrayValue=value.split('\n')
@ -4928,10 +5022,18 @@ $container.removeClass('loading-indicator-container')}
AutocompleteEditor.prototype.loadDynamicItems=function(){var container=this.getContainer(),data=this.inspector.getValues(),$form=$(container).closest('form') AutocompleteEditor.prototype.loadDynamicItems=function(){var container=this.getContainer(),data=this.inspector.getValues(),$form=$(container).closest('form')
$.oc.foundation.element.addClass(container,'loading-indicator-container size-small') $.oc.foundation.element.addClass(container,'loading-indicator-container size-small')
this.showLoadingIndicator() this.showLoadingIndicator()
if(this.triggerGetItems(data)===false){return}
data['inspectorProperty']=this.propertyDefinition.property data['inspectorProperty']=this.propertyDefinition.property
data['inspectorClassName']=this.inspector.options.inspectorClass data['inspectorClassName']=this.inspector.options.inspectorClass
$form.request('onInspectableGetOptions',{data:data,}).done(this.proxy(this.itemsRequestDone)).always(this.proxy(this.hideLoadingIndicator))} $form.request('onInspectableGetOptions',{data:data,}).done(this.proxy(this.itemsRequestDone)).always(this.proxy(this.hideLoadingIndicator))}
AutocompleteEditor.prototype.itemsRequestDone=function(data,currentValue,initialization){if(this.isDisposed()){return} AutocompleteEditor.prototype.triggerGetItems=function(values){var $inspectable=this.getInspectableElement()
if(!$inspectable){return true}
var itemsEvent=$.Event('autocompleteitems.oc.inspector')
$inspectable.trigger(itemsEvent,[{values:values,callback:this.proxy(this.itemsRequestDone),property:this.inspector.getPropertyPath(this.propertyDefinition.property),propertyDefinition:this.propertyDefinition}])
if(itemsEvent.isDefaultPrevented()){return false}
return true}
AutocompleteEditor.prototype.itemsRequestDone=function(data){if(this.isDisposed()){return}
this.hideLoadingIndicator()
var loadedItems={} var loadedItems={}
if(data.options){for(var i=data.options.length-1;i>=0;i--){loadedItems[data.options[i].value]=data.options[i].title}} if(data.options){for(var i=data.options.length-1;i>=0;i--){loadedItems[data.options[i].value]=data.options[i].title}}
this.buildAutoComplete(loadedItems)} this.buildAutoComplete(loadedItems)}
@ -5147,9 +5249,9 @@ if(show){$.oc.foundation.element.removeClass(element,'hide')}
else{container.style.height=height+'px' else{container.style.height=height+'px'
$.oc.foundation.element.addClass(element,'hide')}}} $.oc.foundation.element.addClass(element,'hide')}}}
ExternalParameterEditor.prototype.focus=function(){this.getInput().focus()} ExternalParameterEditor.prototype.focus=function(){this.getInput().focus()}
ExternalParameterEditor.prototype.validate=function(){var value=$.trim(this.getValue()) ExternalParameterEditor.prototype.validate=function(silentMode){var value=$.trim(this.getValue())
if(value.length===0){$.oc.flashMsg({text:'Please enter the external parameter name.','class':'error','interval':5}) if(value.length===0){if(!silentMode){$.oc.flashMsg({text:'Please enter the external parameter name.','class':'error','interval':5})
this.focus() this.focus()}
return false} return false}
return true} return true}
ExternalParameterEditor.prototype.registerHandlers=function(){var input=this.getInput() ExternalParameterEditor.prototype.registerHandlers=function(){var input=this.getInput()
@ -5170,4 +5272,137 @@ ExternalParameterEditor.prototype.getContainer=function(){return this.containerC
ExternalParameterEditor.prototype.getEditor=function(){return this.containerCell.querySelector('div.external-editor')} ExternalParameterEditor.prototype.getEditor=function(){return this.containerCell.querySelector('div.external-editor')}
ExternalParameterEditor.prototype.getPropertyName=function(){return this.propertyDefinition.property} ExternalParameterEditor.prototype.getPropertyName=function(){return this.propertyDefinition.property}
ExternalParameterEditor.prototype.isEditorVisible=function(){return $.oc.foundation.element.hasClass(this.getContainer(),'editor-visible')} ExternalParameterEditor.prototype.isEditorVisible=function(){return $.oc.foundation.element.hasClass(this.getContainer(),'editor-visible')}
$.oc.inspector.externalParameterEditor=ExternalParameterEditor}(window.jQuery); $.oc.inspector.externalParameterEditor=ExternalParameterEditor}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype,listSortableIdCounter=0,elementsIdCounter=0
var ListSortable=function(element,options){this.lists=[]
this.options=options
this.listSortableId=null
this.lastMousePosition=null
Base.call(this)
$.oc.foundation.controlUtils.markDisposable(element)
this.init()
this.addList(element)}
ListSortable.prototype=Object.create(BaseProto)
ListSortable.prototype.constructor=ListSortable
ListSortable.prototype.init=function(){listSortableIdCounter++
this.listSortableId='listsortable/id/'+listSortableIdCounter}
ListSortable.prototype.addList=function(list){this.lists.push(list)
this.registerListHandlers(list)
if(this.lists.length==1){$(list).one('dispose-control',this.proxy(this.dispose))}}
ListSortable.prototype.registerListHandlers=function(list){var $list=$(list)
$list.on('dragstart','> li',this.proxy(this.onDragStart))
$list.on('dragover','> li',this.proxy(this.onDragOver))
$list.on('dragenter','> li',this.proxy(this.onDragEnter))
$list.on('dragleave','> li',this.proxy(this.onDragLeave))
$list.on('drop','> li',this.proxy(this.onDragDrop))
$list.on('dragend','> li',this.proxy(this.onDragEnd))}
ListSortable.prototype.unregisterListHandlers=function(list){$list.off('dragstart','> li',this.proxy(this.onDragStart))
$list.off('dragover','> li',this.proxy(this.onDragOver))
$list.off('dragenter','> li',this.proxy(this.onDragEnter))
$list.off('dragleave','> li',this.proxy(this.onDragLeave))
$list.off('drop','> li',this.proxy(this.onDragDrop))
$list.off('dragend','> li',this.proxy(this.onDragEnd))}
ListSortable.prototype.unregisterHandlers=function(){$(document).off('dragover',this.proxy(this.onDocumentDragOver))
$(document).off('mousemove',this.proxy(this.onDocumentMouseMove))
$(this.lists[0]).off('dispose-control',this.proxy(this.dispose))}
ListSortable.prototype.unbindLists=function(){for(var i=this.lists.length-1;i>0;i--){var list=this.lists[i]
this.unregisterListHandlers(this.lists[i])
$(list).removeData('oc.listSortable')}}
ListSortable.prototype.dispose=function(){this.unbindLists()
this.unregisterHandlers()
this.options=null
this.lists=[]
BaseProto.dispose.call(this)}
ListSortable.prototype.elementBelongsToManagedList=function(element){for(var i=this.lists.length-1;i>=0;i--){var list=this.lists[i],children=[].slice.call(list.children)
if(children.indexOf(element)!==-1){return true}}
return false}
ListSortable.prototype.isDragStartAllowed=function(element){return true}
ListSortable.prototype.elementIsPlaceholder=function(element){return element.getAttribute('class')==='list-sortable-placeholder'}
ListSortable.prototype.getElementSortableId=function(element){if(element.hasAttribute('data-list-sortable-element-id')){return element.getAttribute('data-list-sortable-element-id')}
elementsIdCounter++
var elementId=elementsIdCounter
element.setAttribute('data-list-sortable-element-id',elementsIdCounter)
return elementsIdCounter}
ListSortable.prototype.dataTransferContains=function(ev,element){if(ev.dataTransfer.types.indexOf!==undefined){return ev.dataTransfer.types.indexOf(element)>=0}
return ev.dataTransfer.types.contains(element)}
ListSortable.prototype.isSourceManagedList=function(ev){return this.dataTransferContains(ev,this.listSortableId)}
ListSortable.prototype.removePlaceholders=function(){for(var i=this.lists.length-1;i>=0;i--){var list=this.lists[i],placeholders=list.querySelectorAll('.list-sortable-placeholder')
for(var j=placeholders.length-1;j>=0;j--){list.removeChild(placeholders[j])}}}
ListSortable.prototype.createPlaceholder=function(element,ev){var placeholder=document.createElement('li'),placement=this.getPlaceholderPlacement(element,ev)
this.removePlaceholders()
placeholder.setAttribute('class','list-sortable-placeholder')
placeholder.setAttribute('draggable',true)
if(placement=='before'){element.parentNode.insertBefore(placeholder,element)}
else{element.parentNode.insertBefore(placeholder,element.nextSibling)}}
ListSortable.prototype.moveElement=function(target,ev){var list=target.parentNode,placeholder=list.querySelector('.list-sortable-placeholder')
if(!placeholder){return}
var elementId=ev.dataTransfer.getData('listsortable/elementid')
if(!elementId){return}
var item=this.findDraggedItem(elementId)
if(!item){return}
placeholder.parentNode.insertBefore(item,placeholder)
$(item).trigger('dragged.list.sortable')}
ListSortable.prototype.findDraggedItem=function(elementId){for(var i=this.lists.length-1;i>=0;i--){var list=this.lists[i],item=list.querySelector('[data-list-sortable-element-id="'+elementId+'"]')
if(item){return item}}
return null}
ListSortable.prototype.getPlaceholderPlacement=function(hoverElement,ev){var mousePosition=$.oc.foundation.event.pageCoordinates(ev),elementPosition=$.oc.foundation.element.absolutePosition(hoverElement)
if(this.options.direction=='vertical'){var elementCenter=elementPosition.top+hoverElement.offsetHeight/2
return mousePosition.y<=elementCenter?'before':'after'}
else{var elementCenter=elementPosition.left+hoverElement.offsetWidth/2
return mousePosition.x<=elementCenter?'before':'after'}}
ListSortable.prototype.lastMousePositionChanged=function(ev){var mousePosition=$.oc.foundation.event.pageCoordinates(ev.originalEvent)
if(this.lastMousePosition===null||this.lastMousePosition.x!=mousePosition.x||this.lastMousePosition.y!=mousePosition.y){this.lastMousePosition=mousePosition
return true}
return false}
ListSortable.prototype.mouseOutsideLists=function(ev){var mousePosition=$.oc.foundation.event.pageCoordinates(ev)
for(var i=this.lists.length-1;i>=0;i--){if($.oc.foundation.element.elementContainsPoint(this.lists[i],mousePosition)){return false}}
return true}
ListSortable.prototype.getClosestDraggableParent=function(element){var current=element
while(current){if(current.tagName==='LI'&&current.hasAttribute('draggable')){return current}
current=current.parentNode}
return null}
ListSortable.prototype.onDragStart=function(ev){if(!this.isDragStartAllowed(ev.target)){return}
ev.originalEvent.dataTransfer.effectAllowed='move'
ev.originalEvent.dataTransfer.setData('listsortable/elementid',this.getElementSortableId(ev.target))
ev.originalEvent.dataTransfer.setData(this.listSortableId,this.listSortableId)
$(document).on('mousemove',this.proxy(this.onDocumentMouseMove))
$(document).on('dragover',this.proxy(this.onDocumentDragOver))}
ListSortable.prototype.onDragOver=function(ev){if(!this.isSourceManagedList(ev.originalEvent)){return}
var draggable=this.getClosestDraggableParent(ev.target)
if(!draggable){return}
if(!this.elementIsPlaceholder(draggable)&&this.lastMousePositionChanged(ev)){this.createPlaceholder(draggable,ev.originalEvent)}
ev.stopPropagation()
ev.preventDefault()
ev.originalEvent.dataTransfer.dropEffect='move'}
ListSortable.prototype.onDragEnter=function(ev){if(!this.isSourceManagedList(ev.originalEvent)){return}
var draggable=this.getClosestDraggableParent(ev.target)
if(!draggable){return}
if(this.elementIsPlaceholder(draggable)){return}
this.createPlaceholder(draggable,ev.originalEvent)
ev.stopPropagation()
ev.preventDefault()}
ListSortable.prototype.onDragLeave=function(ev){if(!this.isSourceManagedList(ev.originalEvent)){return}
ev.stopPropagation()
ev.preventDefault()}
ListSortable.prototype.onDragDrop=function(ev){if(!this.isSourceManagedList(ev.originalEvent)){return}
var draggable=this.getClosestDraggableParent(ev.target)
if(!draggable){return}
this.moveElement(draggable,ev.originalEvent)
this.removePlaceholders()}
ListSortable.prototype.onDragEnd=function(ev){$(document).off('dragover',this.proxy(this.onDocumentDragOver))}
ListSortable.prototype.onDocumentDragOver=function(ev){if(!this.isSourceManagedList(ev.originalEvent)){return}
if(this.mouseOutsideLists(ev.originalEvent)){this.removePlaceholders()
return}}
ListSortable.prototype.onDocumentMouseMove=function(ev){$(document).off('mousemove',this.proxy(this.onDocumentMouseMove))
this.removePlaceholders()}
ListSortable.DEFAULTS={handle:null,direction:'vertical'}
var old=$.fn.listSortable
$.fn.listSortable=function(option){var args=arguments
return this.each(function(){var $this=$(this),data=$this.data('oc.listSortable'),options=$.extend({},ListSortable.DEFAULTS,$this.data(),typeof option=='object'&&option)
if(!data){$this.data('oc.listSortable',(data=new ListSortable(this,options)))}
if(typeof option=='string'&&data){if(data[option]){var methodArguments=Array.prototype.slice.call(args)
methodArguments.shift()
data[option].apply(data,methodArguments)}}})}
$.fn.listSortable.Constructor=ListSortable
$.fn.listSortable.noConflict=function(){$.fn.listSortable=old
return this}
$(document).render(function(){$('[data-control=list-sortable]').listSortable()})}(window.jQuery);

View File

@ -1223,6 +1223,7 @@ div.control-popover.popover-danger.placement-top > div:after{content:'';display:
div.control-popover.popover-danger.placement-left > div:after{content:'';display:block;width:0;height:0;border-top:7.5px solid transparent;border-bottom:7.5px solid transparent;border-left:8px solid #ab2a1c} div.control-popover.popover-danger.placement-left > div:after{content:'';display:block;width:0;height:0;border-top:7.5px solid transparent;border-bottom:7.5px solid transparent;border-left:8px solid #ab2a1c}
div.control-popover.popover-danger.placement-right > div:after{content:'';display:block;width:0;height:0;border-top:7.5px solid transparent;border-bottom:7.5px solid transparent;border-right:8px solid #ab2a1c} div.control-popover.popover-danger.placement-right > div:after{content:'';display:block;width:0;height:0;border-top:7.5px solid transparent;border-bottom:7.5px solid transparent;border-right:8px solid #ab2a1c}
div.control-popover.popover-danger .popover-head{background-color:#ab2a1c} div.control-popover.popover-danger .popover-head{background-color:#ab2a1c}
div.control-popover div.popover-fixed-height{height:300px}
.popover-highlight{position:relative;z-index:562 !important} .popover-highlight{position:relative;z-index:562 !important}
.popover-highlight:hover,.popover-highlight:active,.popover-highlight:focus{z-index:562 !important} .popover-highlight:hover,.popover-highlight:active,.popover-highlight:focus{z-index:562 !important}
div.popover-overlay{position:fixed;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,0.3);z-index:560} div.popover-overlay{position:fixed;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,0.3);z-index:560}
@ -1230,6 +1231,7 @@ div.popover-overlay{position:fixed;left:0;top:0;right:0;bottom:0;background:rgba
body.popover-open .control-popover{overflow:auto;overflow-y:scroll;position:fixed;margin:0;padding:10px;width:100% !important;z-index:609;top:0 !important;right:0 !important;bottom:0 !important;left:0 !important} body.popover-open .control-popover{overflow:auto;overflow-y:scroll;position:fixed;margin:0;padding:10px;width:100% !important;z-index:609;top:0 !important;right:0 !important;bottom:0 !important;left:0 !important}
body.popover-open .control-popover > div{padding:0;min-height:100%;-webkit-box-shadow:none;box-shadow:none} body.popover-open .control-popover > div{padding:0;min-height:100%;-webkit-box-shadow:none;box-shadow:none}
body.popover-open .control-popover > div:before,body.popover-open .control-popover > div:after{display:none} body.popover-open .control-popover > div:before,body.popover-open .control-popover > div:after{display:none}
body.popover-open .control-popover div.popover-fixed-height{height:100%;min-height:100%}
body.popover-open .control-popover .popover-head:before{display:none} body.popover-open .control-popover .popover-head:before{display:none}
} }
.control-breadcrumb{font-size:12px;text-transform:uppercase;padding:15px 20px;margin:-20px -20px 20px -20px;background-color:#2b343d} .control-breadcrumb{font-size:12px;text-transform:uppercase;padding:15px 20px;margin:-20px -20px 20px -20px;background-color:#2b343d}
@ -1570,7 +1572,7 @@ div.scoreboard .control-chart .canvas + ul{margin-left:0}
div.scoreboard .scoreboard-offset{padding-left:20px} div.scoreboard .scoreboard-offset{padding-left:20px}
body.slim-container div.scoreboard{padding:0 20px} body.slim-container div.scoreboard{padding:0 20px}
#layout-canvas .flash-message{display:none} #layout-canvas .flash-message{display:none}
.flash-message{position:fixed;width:500px;left:50%;top:13px;margin-left:-250px;color:#ffffff;font-size:13px;padding:10px 30px 10px 15px;z-index:10000;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px} .flash-message{position:fixed;width:500px;left:50%;top:13px;margin-left:-250px;color:#ffffff;font-size:13px;padding:10px 30px 10px 15px;z-index:10000;word-wrap:break-word;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}
.flash-message.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:all 0.5s,width 0s;transition:all 0.5s,width 0s;-webkit-transform:scale(0.9);-ms-transform:scale(0.9);transform:scale(0.9)} .flash-message.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:all 0.5s,width 0s;transition:all 0.5s,width 0s;-webkit-transform:scale(0.9);-ms-transform:scale(0.9);transform:scale(0.9)}
.flash-message.fade.in{opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)} .flash-message.fade.in{opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
.flash-message.success{background:#8da85e} .flash-message.success{background:#8da85e}
@ -2510,6 +2512,7 @@ div.control-popover.inspector-temporary-placement{visibility:hidden;left:0 !impo
.inspector-columns-editor .items-column{width:250px} .inspector-columns-editor .items-column{width:250px}
.inspector-columns-editor .inspector-wrapper{background:#f2f2f2;border-left:2px solid #bdc3c7} .inspector-columns-editor .inspector-wrapper{background:#f2f2f2;border-left:2px solid #bdc3c7}
.inspector-columns-editor .toolbar{padding:20px} .inspector-columns-editor .toolbar{padding:20px}
html.gecko.mac .scroll-wrapper.inspector-wrapper > div{margin-right:17px}
.inspector-table-list{border-top:1px solid #e2e2e2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} .inspector-table-list{border-top:1px solid #e2e2e2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
div.inspector-dictionary-container{border:1px solid #e0e0e0} div.inspector-dictionary-container{border:1px solid #e0e0e0}
div.inspector-dictionary-container .values{height:300px} div.inspector-dictionary-container .values{height:300px}
@ -2532,11 +2535,14 @@ div.inspector-dictionary-container table.inspector-dictionary-table tbody tr:las
.inspector-header span:hover{opacity:1;filter:alpha(opacity=100);color:#ffffff} .inspector-header span:hover{opacity:1;filter:alpha(opacity=100);color:#ffffff}
.inspector-header .detach{right:26px} .inspector-header .detach{right:26px}
.inspector-header .close{right:11px;font-size:21px} .inspector-header .close{right:11px;font-size:21px}
.inspector-container:empty{display:none}
.inspector-container .control-scrollpad{position:absolute} .inspector-container .control-scrollpad{position:absolute}
.inspector-field-comment:empty{display:none}
.select2-dropdown.ocInspectorDropdown{font-size:12px;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:none !important} .select2-dropdown.ocInspectorDropdown{font-size:12px;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:none !important}
.select2-dropdown.ocInspectorDropdown > .select2-results > .select2-results__options{font-size:12px} .select2-dropdown.ocInspectorDropdown > .select2-results > .select2-results__options{font-size:12px}
.select2-dropdown.ocInspectorDropdown > .select2-results > li > div{padding:5px 12px 5px} .select2-dropdown.ocInspectorDropdown > .select2-results > li > div{padding:5px 12px 5px}
.select2-dropdown.ocInspectorDropdown > .select2-results li.select2-no-results{padding:5px 12px 5px} .select2-dropdown.ocInspectorDropdown > .select2-results li.select2-no-results{padding:5px 12px 5px}
.select2-dropdown.ocInspectorDropdown > .select2-results li > i,.select2-dropdown.ocInspectorDropdown > .select2-results li > img{margin-left:6px}
.select2-dropdown.ocInspectorDropdown .select2-search{min-height:26px;position:relative;border-bottom:1px solid #b2b9be} .select2-dropdown.ocInspectorDropdown .select2-search{min-height:26px;position:relative;border-bottom:1px solid #b2b9be}
.select2-dropdown.ocInspectorDropdown .select2-search:after{position:absolute;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f002";right:10px;top:10px;color:#95a5a6} .select2-dropdown.ocInspectorDropdown .select2-search:after{position:absolute;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f002";right:10px;top:10px;color:#95a5a6}
.select2-dropdown.ocInspectorDropdown .select2-search input.select2-search__field{min-height:26px;background:transparent !important;padding-left:12px;padding-right:12px;border:none} .select2-dropdown.ocInspectorDropdown .select2-search input.select2-search__field{min-height:26px;background:transparent !important;padding-left:12px;padding-right:12px;border:none}
@ -2602,7 +2608,7 @@ div.inspector-dictionary-container table.inspector-dictionary-table tbody tr:las
.modal-footer .btn + .btn{margin-left:5px;margin-bottom:0} .modal-footer .btn + .btn{margin-left:5px;margin-bottom:0}
.modal-footer .btn-group .btn + .btn{margin-left:-1px} .modal-footer .btn-group .btn + .btn{margin-left:-1px}
.modal-footer .btn-block + .btn-block{margin-left:0} .modal-footer .btn-block + .btn-block{margin-left:0}
@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto} @media (min-width:768px){.modal-dialog{width:600px;margin:80px auto 30px auto}
.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)} .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}
.modal-sm{width:300px} .modal-sm{width:300px}
} }

View File

@ -80,4 +80,5 @@
=require js/inspector.validator.float.js =require js/inspector.validator.float.js
=require js/inspector.validator.length.js =require js/inspector.validator.length.js
=require js/inspector.externalparametereditor.js =require js/inspector.externalparametereditor.js
=require js/list.sortable.js
*/ */

View File

@ -4,6 +4,7 @@ use Illuminate\Support\ServiceProvider as ServiceProviderBase;
use ReflectionClass; use ReflectionClass;
use SystemException; use SystemException;
use Yaml; use Yaml;
use Backend;
/** /**
* Plugin base class * Plugin base class
@ -99,7 +100,20 @@ class PluginBase extends ServiceProviderBase
*/ */
public function registerNavigation() public function registerNavigation()
{ {
return []; $configuration = $this->getConfigurationFromYaml();
if (array_key_exists('navigation', $configuration)) {
$navigation = $configuration['navigation'];
if (is_array($navigation)) {
array_walk_recursive($navigation, function(&$item, $key){
if ($key == 'url') {
$item = Backend::url($item);
}
});
}
return $navigation;
}
} }
/** /**
@ -109,7 +123,10 @@ class PluginBase extends ServiceProviderBase
*/ */
public function registerPermissions() public function registerPermissions()
{ {
return []; $configuration = $this->getConfigurationFromYaml();
if (array_key_exists('permissions', $configuration)) {
return $configuration['permissions'];
}
} }
/** /**

View File

@ -69,8 +69,10 @@ class VersionManager
/** /**
* Updates a single plugin by its code or object with it's latest changes. * Updates a single plugin by its code or object with it's latest changes.
* If the $stopOnVersion parameter is specified, the process stops after
* the specified version is applied.
*/ */
public function updatePlugin($plugin) public function updatePlugin($plugin, $stopOnVersion = null)
{ {
$code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin); $code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin);
@ -90,11 +92,30 @@ class VersionManager
$newUpdates = $this->getNewFileVersions($code, $databaseVersion); $newUpdates = $this->getNewFileVersions($code, $databaseVersion);
foreach ($newUpdates as $version => $details) { foreach ($newUpdates as $version => $details) {
$this->applyPluginUpdate($code, $version, $details); $this->applyPluginUpdate($code, $version, $details);
if ($stopOnVersion === $version) {
return true;
}
} }
return true; return true;
} }
/**
* Returns a list of unapplied plugin versions.
*/
public function listNewVersions($plugin)
{
$code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin);
if (!$this->hasVersionFile($code)) {
return [];
}
$databaseVersion = $this->getDatabaseVersion($code);
return $this->getNewFileVersions($code, $databaseVersion);
}
/** /**
* Applies a single version update to a plugin. * Applies a single version update to a plugin.
*/ */
@ -134,8 +155,10 @@ class VersionManager
/** /**
* Removes and packs down a plugin from the system. Files are left intact. * Removes and packs down a plugin from the system. Files are left intact.
* If the $stopOnVersion parameter is specified, the process stops after
* the specified version is rolled back.
*/ */
public function removePlugin($plugin) public function removePlugin($plugin, $stopOnVersion = null)
{ {
$code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin); $code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin);
@ -146,16 +169,31 @@ class VersionManager
$pluginHistory = $this->getDatabaseHistory($code); $pluginHistory = $this->getDatabaseHistory($code);
$pluginHistory = array_reverse($pluginHistory); $pluginHistory = array_reverse($pluginHistory);
$stopOnNextVersion = false;
$newPluginVersion = null;
foreach ($pluginHistory as $history) { foreach ($pluginHistory as $history) {
if ($stopOnNextVersion && $history->version !== $stopOnVersion) {
// Stop if the $stopOnVersion value was found and
// this is a new version. The history could contain
// multiple items for a single version (comments and scripts).
$newPluginVersion = $history->version;
break;
}
if ($history->type == self::HISTORY_TYPE_COMMENT) { if ($history->type == self::HISTORY_TYPE_COMMENT) {
$this->removeDatabaseComment($code, $history->version); $this->removeDatabaseComment($code, $history->version);
} }
elseif ($history->type == self::HISTORY_TYPE_SCRIPT) { elseif ($history->type == self::HISTORY_TYPE_SCRIPT) {
$this->removeDatabaseScript($code, $history->version, $history->detail); $this->removeDatabaseScript($code, $history->version, $history->detail);
} }
if ($stopOnVersion === $history->version) {
$stopOnNextVersion = true;
}
} }
$this->setDatabaseVersion($code); $this->setDatabaseVersion($code, $newPluginVersion);
if (isset($this->fileVersions[$code])) { if (isset($this->fileVersions[$code])) {
unset($this->fileVersions[$code]); unset($this->fileVersions[$code]);