clipbucket/upload/styles/cb_28/theme/js/jcf_new/jcf.radio.js

195 lines
5.4 KiB
JavaScript

/*!
* JavaScript Custom Forms : Radio Module
*
* Copyright 2014-2015 PSD2HTML - http://psd2html.com/jcf
* Released under the MIT license (LICENSE.txt)
*
* Version: 1.2.1
*/
(function(jcf) {
jcf.addModule(function($) {
'use strict';
return {
name: 'Radio',
selector: 'input[type="radio"]',
options: {
wrapNative: true,
checkedClass: 'jcf-checked',
uncheckedClass: 'jcf-unchecked',
labelActiveClass: 'jcf-label-active',
fakeStructure: '<span class="jcf-radio"><span></span></span>'
},
matchElement: function(element) {
return element.is(':radio');
},
init: function() {
this.initStructure();
this.attachEvents();
this.refresh();
},
initStructure: function() {
// prepare structure
this.doc = $(document);
this.realElement = $(this.options.element);
this.fakeElement = $(this.options.fakeStructure).insertAfter(this.realElement);
this.labelElement = this.getLabelFor();
if (this.options.wrapNative) {
// wrap native radio inside fake block
this.realElement.prependTo(this.fakeElement).css({
position: 'absolute',
opacity: 0
});
} else {
// just hide native radio
this.realElement.addClass(this.options.hiddenClass);
}
},
attachEvents: function() {
// add event handlers
this.realElement.on({
focus: this.onFocus,
click: this.onRealClick
});
this.fakeElement.on('click', this.onFakeClick);
this.fakeElement.on('jcf-pointerdown', this.onPress);
},
onRealClick: function(e) {
// redraw current radio and its group (setTimeout handles click that might be prevented)
var self = this;
this.savedEventObject = e;
setTimeout(function() {
self.refreshRadioGroup();
}, 0);
},
onFakeClick: function(e) {
// skip event if clicked on real element inside wrapper
if (this.options.wrapNative && this.realElement.is(e.target)) {
return;
}
// toggle checked class
if (!this.realElement.is(':disabled')) {
delete this.savedEventObject;
this.currentActiveRadio = this.getCurrentActiveRadio();
this.stateChecked = this.realElement.prop('checked');
this.realElement.prop('checked', true);
this.fireNativeEvent(this.realElement, 'click');
if (this.savedEventObject && this.savedEventObject.isDefaultPrevented()) {
this.realElement.prop('checked', this.stateChecked);
this.currentActiveRadio.prop('checked', true);
} else {
this.fireNativeEvent(this.realElement, 'change');
}
delete this.savedEventObject;
}
},
onFocus: function() {
if (!this.pressedFlag || !this.focusedFlag) {
this.focusedFlag = true;
this.fakeElement.addClass(this.options.focusClass);
this.realElement.on('blur', this.onBlur);
}
},
onBlur: function() {
if (!this.pressedFlag) {
this.focusedFlag = false;
this.fakeElement.removeClass(this.options.focusClass);
this.realElement.off('blur', this.onBlur);
}
},
onPress: function(e) {
if (!this.focusedFlag && e.pointerType === 'mouse') {
this.realElement.focus();
}
this.pressedFlag = true;
this.fakeElement.addClass(this.options.pressedClass);
this.doc.on('jcf-pointerup', this.onRelease);
},
onRelease: function(e) {
if (this.focusedFlag && e.pointerType === 'mouse') {
this.realElement.focus();
}
this.pressedFlag = false;
this.fakeElement.removeClass(this.options.pressedClass);
this.doc.off('jcf-pointerup', this.onRelease);
},
getCurrentActiveRadio: function() {
return this.getRadioGroup(this.realElement).filter(':checked');
},
getRadioGroup: function(radio) {
// find radio group for specified radio button
var name = radio.attr('name'),
parentForm = radio.parents('form');
if (name) {
if (parentForm.length) {
return parentForm.find('input[name="' + name + '"]');
} else {
return $('input[name="' + name + '"]:not(form input)');
}
} else {
return radio;
}
},
getLabelFor: function() {
var parentLabel = this.realElement.closest('label'),
elementId = this.realElement.prop('id');
if (!parentLabel.length && elementId) {
parentLabel = $('label[for="' + elementId + '"]');
}
return parentLabel.length ? parentLabel : null;
},
refreshRadioGroup: function() {
// redraw current radio and its group
this.getRadioGroup(this.realElement).each(function() {
jcf.refresh(this);
});
},
refresh: function() {
// redraw current radio button
var isChecked = this.realElement.is(':checked'),
isDisabled = this.realElement.is(':disabled');
this.fakeElement.toggleClass(this.options.checkedClass, isChecked)
.toggleClass(this.options.uncheckedClass, !isChecked)
.toggleClass(this.options.disabledClass, isDisabled);
if (this.labelElement) {
this.labelElement.toggleClass(this.options.labelActiveClass, isChecked);
}
},
destroy: function() {
// restore structure
if (this.options.wrapNative) {
this.realElement.insertBefore(this.fakeElement).css({
position: '',
width: '',
height: '',
opacity: '',
margin: ''
});
} else {
this.realElement.removeClass(this.options.hiddenClass);
}
// removing element will also remove its event handlers
this.fakeElement.off('jcf-pointerdown', this.onPress);
this.fakeElement.remove();
// remove other event handlers
this.doc.off('jcf-pointerup', this.onRelease);
this.realElement.off({
blur: this.onBlur,
focus: this.onFocus,
click: this.onRealClick
});
}
};
});
}(jcf));