diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c66ae8d..46cb6bf75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +* **Build 279** (2015-07-14) + - Plugins can now be frozen to prevent them from receiving updates via the plugin management area. + - A plugin version can now be flagged as "Important" by prepending `!!!` to the version history comment. + * **Build 275** (2015-07-04) - List columns now support specifying a `default` option used when the value would otherwise be null. - Implement a custom autoloader for plugins that use composer. Now only one instance of composer is used, all packages are now added to a global pool to prevent double loading and the load order is respected. diff --git a/modules/backend/assets/js/october-min.js b/modules/backend/assets/js/october-min.js index 9227d21d0..c74267e8f 100644 --- a/modules/backend/assets/js/october-min.js +++ b/modules/backend/assets/js/october-min.js @@ -4095,27 +4095,29 @@ if(this.options.triggerCondition.indexOf('value')==0){var match=this.options.tri this.triggerCondition='value' this.triggerConditionValue=(match)?match:""} this.triggerParent=this.options.triggerClosestParent!==undefined?$el.closest(this.options.triggerClosestParent):undefined -if(this.triggerCondition=='checked'||this.triggerCondition=='value'){$(document).on('change',this.options.trigger,$.proxy(this.onConditionChanged,this))} +if(this.triggerCondition=='checked'||this.triggerCondition=='unchecked'||this.triggerCondition=='value'){$(document).on('change',this.options.trigger,$.proxy(this.onConditionChanged,this))} var self=this $el.on('oc.triggerOn.update',function(e){e.stopPropagation() self.onConditionChanged()}) self.onConditionChanged()} -TriggerOn.prototype.onConditionChanged=function(){if(this.triggerCondition=='checked'){this.updateTarget($(this.options.trigger+':checked',this.triggerParent).length>0)} -else if(this.triggerCondition=='value'){var trigger=$(this.options.trigger+':checked',this.triggerParent),needle=trigger.length?trigger.val():$(this.options.trigger,this.triggerParent).val() -this.updateTarget($.inArray(needle,this.triggerConditionValue)!=-1)}} -TriggerOn.prototype.updateTarget=function(status){if(this.options.triggerAction=='show') -this.$el.toggleClass('hide',!status).trigger('hide.oc.triggerapi',[!status]) -else if(this.options.triggerAction=='hide') -this.$el.toggleClass('hide',status).trigger('hide.oc.triggerapi',[status]) -else if(this.options.triggerAction=='enable') -this.$el.prop('disabled',!status).trigger('disable.oc.triggerapi',[!status]).toggleClass('control-disabled',!status) -else if(this.options.triggerAction=='disable') -this.$el.prop('disabled',status).trigger('disable.oc.triggerapi',[status]).toggleClass('control-disabled',status) -else if(this.options.triggerAction=='empty'&&status) -this.$el.trigger('empty.oc.triggerapi').val('') -if(this.options.triggerAction=='show'||this.options.triggerAction=='hide') -this.fixButtonClasses() +TriggerOn.prototype.onConditionChanged=function(){if(this.triggerCondition=='checked'){this.updateTarget(!!$(this.options.trigger+':checked',this.triggerParent).length)} +else if(this.triggerCondition=='unchecked'){this.updateTarget(!$(this.options.trigger+':checked',this.triggerParent).length)} +else if(this.triggerCondition=='value'){var trigger,triggerValue='' +trigger=$(this.options.trigger,this.triggerParent).not('input[type=checkbox], input[type=radio], input[type=button], input[type=submit]') +if(!trigger.length){trigger=$(this.options.trigger,this.triggerParent).not(':not(input[type=checkbox]:checked, input[type=radio]:checked)')} +if(!!trigger.length){triggerValue=trigger.val()} +this.updateTarget($.inArray(triggerValue,this.triggerConditionValue)!=-1)}} +TriggerOn.prototype.updateTarget=function(status){var self=this,actions=this.options.triggerAction.split('|') +$.each(actions,function(index,action){self.updateTargetAction(action,status)}) $(window).trigger('resize')} +TriggerOn.prototype.updateTargetAction=function(action,status){if(action=='show'){this.$el.toggleClass('hide',!status).trigger('hide.oc.triggerapi',[!status])} +else if(action=='hide'){this.$el.toggleClass('hide',status).trigger('hide.oc.triggerapi',[status])} +else if(action=='enable'){this.$el.prop('disabled',!status).toggleClass('control-disabled',!status).trigger('disable.oc.triggerapi',[!status])} +else if(action=='disable'){this.$el.prop('disabled',status).toggleClass('control-disabled',status).trigger('disable.oc.triggerapi',[status])} +else if(action=='empty'&&status){this.$el.not('input[type=checkbox], input[type=radio], input[type=button], input[type=submit]').val('') +this.$el.not(':not(input[type=checkbox], input[type=radio])').prop('checked',false) +this.$el.trigger('empty.oc.triggerapi').trigger('change')} +if(action=='show'||action=='hide'){this.fixButtonClasses()}} TriggerOn.prototype.fixButtonClasses=function(){var group=this.$el.closest('.btn-group') if(group.length>0&&this.$el.is(':last-child')) this.$el.prev().toggleClass('last',this.$el.hasClass('hide'))} diff --git a/modules/system/assets/ui/docs/input-trigger.md b/modules/system/assets/ui/docs/input-trigger.md index bf27e124b..18e61aab0 100644 --- a/modules/system/assets/ui/docs/input-trigger.md +++ b/modules/system/assets/ui/docs/input-trigger.md @@ -8,6 +8,7 @@ The API allows to change elements' visibility or status (enabled/disabled) basin - data-trigger: a CSS selector for elements that trigger the action (checkboxes) - data-trigger-condition, values: - checked: determines the condition the elements specified in the data-trigger should satisfy in order the condition to be considered as "true". + - unchecked: inverse condition of "checked". - value[somevalue]: determines if the value of data-trigger equals the specified value (somevalue) the condition is considered "true". - data-trigger-closest-parent: optional, specifies a CSS selector for a closest common parent for the source and destination input elements. @@ -18,6 +19,14 @@ Example code: data-trigger="#cblist input[type=checkbox]" data-trigger-condition="checked" ... > +Multiple actions are supported: + + data-trigger-action="hide|empty" + +Multie value conditions are supported: + + data-trigger-condition="value[foo][bar]" + ### Supported events: - oc.triggerOn.update - triggers the update. Trigger this event on the element the plugin is bound to to diff --git a/modules/system/assets/ui/js/input.trigger.js b/modules/system/assets/ui/js/input.trigger.js index d86b2263b..7a5fd6653 100644 --- a/modules/system/assets/ui/js/input.trigger.js +++ b/modules/system/assets/ui/js/input.trigger.js @@ -35,7 +35,11 @@ ? $el.closest(this.options.triggerClosestParent) : undefined - if (this.triggerCondition == 'checked' || this.triggerCondition == 'value') { + if ( + this.triggerCondition == 'checked' || + this.triggerCondition == 'unchecked' || + this.triggerCondition == 'value' + ) { $(document).on('change', this.options.trigger, $.proxy(this.onConditionChanged, this)) } @@ -50,34 +54,83 @@ TriggerOn.prototype.onConditionChanged = function() { if (this.triggerCondition == 'checked') { - this.updateTarget($(this.options.trigger + ':checked', this.triggerParent).length > 0) + this.updateTarget(!!$(this.options.trigger + ':checked', this.triggerParent).length) + } + else if (this.triggerCondition == 'unchecked') { + this.updateTarget(!$(this.options.trigger + ':checked', this.triggerParent).length) } else if (this.triggerCondition == 'value') { - var trigger = $(this.options.trigger + ':checked', this.triggerParent), - needle = trigger.length ? trigger.val() : $(this.options.trigger, this.triggerParent).val() + var trigger, triggerValue = '' - this.updateTarget($.inArray(needle, this.triggerConditionValue) != -1) + trigger = $(this.options.trigger, this.triggerParent) + .not('input[type=checkbox], input[type=radio], input[type=button], input[type=submit]') + + if (!trigger.length) { + trigger = $(this.options.trigger, this.triggerParent) + .not(':not(input[type=checkbox]:checked, input[type=radio]:checked)') + } + + if (!!trigger.length) { + triggerValue = trigger.val() + } + + this.updateTarget($.inArray(triggerValue, this.triggerConditionValue) != -1) } } TriggerOn.prototype.updateTarget = function(status) { - if (this.options.triggerAction == 'show') - this.$el.toggleClass('hide', !status).trigger('hide.oc.triggerapi', [!status]) - else if (this.options.triggerAction == 'hide') - this.$el.toggleClass('hide', status).trigger('hide.oc.triggerapi', [status]) - else if (this.options.triggerAction == 'enable') - this.$el.prop('disabled', !status).trigger('disable.oc.triggerapi', [!status]).toggleClass('control-disabled', !status) - else if (this.options.triggerAction == 'disable') - this.$el.prop('disabled', status).trigger('disable.oc.triggerapi', [status]).toggleClass('control-disabled', status) - else if (this.options.triggerAction == 'empty' && status) - this.$el.trigger('empty.oc.triggerapi').val('') + var self = this, + actions = this.options.triggerAction.split('|') - if (this.options.triggerAction == 'show' || this.options.triggerAction == 'hide') - this.fixButtonClasses() + $.each(actions, function(index, action) { + self.updateTargetAction(action, status) + }) $(window).trigger('resize') } + TriggerOn.prototype.updateTargetAction = function(action, status) { + if (action == 'show') { + this.$el + .toggleClass('hide', !status) + .trigger('hide.oc.triggerapi', [!status]) + } + else if (action == 'hide') { + this.$el + .toggleClass('hide', status) + .trigger('hide.oc.triggerapi', [status]) + } + else if (action == 'enable') { + this.$el + .prop('disabled', !status) + .toggleClass('control-disabled', !status) + .trigger('disable.oc.triggerapi', [!status]) + } + else if (action == 'disable') { + this.$el + .prop('disabled', status) + .toggleClass('control-disabled', status) + .trigger('disable.oc.triggerapi', [status]) + } + else if (action == 'empty' && status) { + this.$el + .not('input[type=checkbox], input[type=radio], input[type=button], input[type=submit]') + .val('') + + this.$el + .not(':not(input[type=checkbox], input[type=radio])') + .prop('checked', false) + + this.$el + .trigger('empty.oc.triggerapi') + .trigger('change') + } + + if (action == 'show' || action == 'hide') { + this.fixButtonClasses() + } + } + TriggerOn.prototype.fixButtonClasses = function() { var group = this.$el.closest('.btn-group')