236 lines
6.8 KiB
JavaScript
236 lines
6.8 KiB
JavaScript
/*
|
|
* Form Widget
|
|
*
|
|
* Dependences:
|
|
* - Nil
|
|
*/
|
|
+function ($) { "use strict";
|
|
var Base = $.oc.foundation.base,
|
|
BaseProto = Base.prototype
|
|
|
|
var FormWidget = function (element, options) {
|
|
this.$el = $(element)
|
|
this.options = options || {}
|
|
|
|
/*
|
|
* Throttle dependency updating
|
|
*/
|
|
this.dependantUpdateInterval = 300
|
|
this.dependantUpdateTimers = {}
|
|
|
|
$.oc.foundation.controlUtils.markDisposable(element)
|
|
Base.call(this)
|
|
this.init()
|
|
}
|
|
|
|
FormWidget.prototype = Object.create(BaseProto)
|
|
FormWidget.prototype.constructor = FormWidget
|
|
|
|
FormWidget.prototype.init = function() {
|
|
|
|
this.$form = this.$el.closest('form')
|
|
|
|
this.bindDependants()
|
|
this.bindCheckboxlist()
|
|
this.toggleEmptyTabs()
|
|
this.bindCollapsibleSections()
|
|
|
|
this.$el.on('oc.triggerOn.afterUpdate', this.proxy(this.toggleEmptyTabs))
|
|
this.$el.one('dispose-control', this.proxy(this.dispose))
|
|
}
|
|
|
|
FormWidget.prototype.dispose = function() {
|
|
this.$el.off('dispose-control', this.proxy(this.dispose))
|
|
this.$el.removeData('oc.formwidget')
|
|
|
|
this.$el = null
|
|
this.options = null
|
|
|
|
BaseProto.dispose.call(this)
|
|
}
|
|
|
|
/*
|
|
* Logic for checkboxlist
|
|
*/
|
|
FormWidget.prototype.bindCheckboxlist = function() {
|
|
|
|
var checkAllBoxes = function($field, flag) {
|
|
$('input[type=checkbox]', $field)
|
|
.prop('checked', flag)
|
|
.first()
|
|
.trigger('change')
|
|
}
|
|
|
|
this.$el.on('click', '[data-field-checkboxlist-all]', function() {
|
|
checkAllBoxes($(this).closest('.field-checkboxlist'), true)
|
|
})
|
|
|
|
this.$el.on('click', '[data-field-checkboxlist-none]', function() {
|
|
checkAllBoxes($(this).closest('.field-checkboxlist'), false)
|
|
})
|
|
|
|
}
|
|
|
|
/*
|
|
* Bind dependant fields
|
|
*/
|
|
FormWidget.prototype.bindDependants = function() {
|
|
var self = this,
|
|
form = this.$el,
|
|
fieldMap = {}
|
|
|
|
/*
|
|
* Map master and slave fields
|
|
*/
|
|
form.find('[data-field-depends]').each(function() {
|
|
var name = $(this).data('field-name'),
|
|
depends = $(this).data('field-depends')
|
|
|
|
$.each(depends, function(index, depend){
|
|
if (!fieldMap[depend])
|
|
fieldMap[depend] = { fields: [] }
|
|
|
|
fieldMap[depend].fields.push(name)
|
|
})
|
|
})
|
|
|
|
/*
|
|
* When a master is updated, refresh its slaves
|
|
*/
|
|
$.each(fieldMap, function(fieldName, toRefresh){
|
|
form
|
|
.find('[data-field-name="'+fieldName+'"]')
|
|
.on('change.oc.formwidget', $.proxy(self.onRefreshDependants, self, fieldName, toRefresh))
|
|
})
|
|
}
|
|
|
|
/*
|
|
* Refresh a dependancy field
|
|
* Uses a throttle to prevent duplicate calls and click spamming
|
|
*/
|
|
FormWidget.prototype.onRefreshDependants = function(fieldName, toRefresh) {
|
|
var self = this,
|
|
form = this.$el,
|
|
formEl = this.$form
|
|
|
|
if (this.dependantUpdateTimers[fieldName] !== undefined) {
|
|
window.clearTimeout(this.dependantUpdateTimers[fieldName])
|
|
}
|
|
|
|
this.dependantUpdateTimers[fieldName] = window.setTimeout(function() {
|
|
formEl.request(self.options.refreshHandler, {
|
|
data: toRefresh
|
|
}).success(function() {
|
|
self.toggleEmptyTabs()
|
|
})
|
|
}, this.dependantUpdateInterval)
|
|
|
|
$.each(toRefresh.fields, function(index, field) {
|
|
form.find('[data-field-name="'+field+'"]:visible')
|
|
.addClass('loading-indicator-container size-form-field')
|
|
.loadIndicator()
|
|
})
|
|
}
|
|
|
|
/*
|
|
* Hides tabs that have no content, it is possible this can be
|
|
* called multiple times in a single cycle due to input.trigger.
|
|
*/
|
|
FormWidget.prototype.toggleEmptyTabs = function() {
|
|
var self = this,
|
|
form = this.$el
|
|
|
|
if (this.toggleEmptyTabsTimer !== undefined) {
|
|
window.clearTimeout(this.toggleEmptyTabsTimer)
|
|
}
|
|
|
|
this.toggleEmptyTabsTimer = window.setTimeout(function() {
|
|
|
|
var tabControl = $('[data-control=tab]', this.$el),
|
|
tabContainer = $('.nav-tabs', tabControl)
|
|
|
|
if (!tabControl.length || !$.contains(form.get(0), tabControl.get(0)))
|
|
return
|
|
|
|
/*
|
|
* Check each tab pane for form field groups
|
|
*/
|
|
$('.tab-pane', tabControl).each(function() {
|
|
$('[data-target="#' + $(this).attr('id') + '"]', tabControl)
|
|
.closest('li')
|
|
.toggle(!!$('.form-group:not(:empty):not(.hide)', $(this)).length)
|
|
})
|
|
|
|
/*
|
|
* If a hidden tab was selected, select the first visible tab
|
|
*/
|
|
if (!$('> li.active:visible', tabContainer).length) {
|
|
$('> li:visible:first', tabContainer)
|
|
.find('> a:first')
|
|
.tab('show')
|
|
}
|
|
|
|
}, 1)
|
|
}
|
|
|
|
/*
|
|
* Makes sections collapsible by targeting every field after
|
|
* up until the next section
|
|
*/
|
|
FormWidget.prototype.bindCollapsibleSections = function() {
|
|
$('.section-field[data-field-collapsible]', this.$form)
|
|
.addClass('collapsed')
|
|
.find('.field-section:first')
|
|
.addClass('is-collapsible')
|
|
.end()
|
|
.on('click', function() {
|
|
$(this)
|
|
.toggleClass('collapsed')
|
|
.nextUntil('.section-field').toggle()
|
|
})
|
|
.nextUntil('.section-field').hide()
|
|
}
|
|
|
|
FormWidget.DEFAULTS = {
|
|
refreshHandler: null
|
|
}
|
|
|
|
// FORM WIDGET PLUGIN DEFINITION
|
|
// ============================
|
|
|
|
var old = $.fn.formWidget
|
|
|
|
$.fn.formWidget = function (option) {
|
|
var args = arguments,
|
|
result
|
|
|
|
this.each(function () {
|
|
var $this = $(this)
|
|
var data = $this.data('oc.formwidget')
|
|
var options = $.extend({}, FormWidget.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
|
if (!data) $this.data('oc.formwidget', (data = new FormWidget(this, options)))
|
|
if (typeof option == 'string') result = data[option].call($this)
|
|
if (typeof result != 'undefined') return false
|
|
})
|
|
|
|
return result ? result : this
|
|
}
|
|
|
|
$.fn.formWidget.Constructor = FormWidget
|
|
|
|
// FORM WIDGET NO CONFLICT
|
|
// =================
|
|
|
|
$.fn.formWidget.noConflict = function () {
|
|
$.fn.formWidget = old
|
|
return this
|
|
}
|
|
|
|
// FORM WIDGET DATA-API
|
|
// ==============
|
|
|
|
$(document).render(function() {
|
|
$('[data-control="formwidget"]').formWidget();
|
|
})
|
|
|
|
}(window.jQuery); |