3 var __slice = Array.prototype.slice;
4 iOSCheckbox = (function() {
5 function iOSCheckbox(elem, options) {
8 opts = $.extend({}, iOSCheckbox.defaults, options);
13 this.elem.data(this.dataName, this);
14 this.wrapCheckboxWithDivs();
16 this.disableTextSelection();
17 if (this.resizeHandle) {
18 this.optionallyResize('handle');
20 if (this.resizeContainer) {
21 this.optionallyResize('container');
23 this.initialPosition();
25 iOSCheckbox.prototype.isDisabled = function() {
26 return this.elem.is(':disabled');
28 iOSCheckbox.prototype.wrapCheckboxWithDivs = function() {
29 this.elem.wrap("<div class='" + this.containerClass + "' />");
30 this.container = this.elem.parent();
31 this.offLabel = $("<label class='" + this.labelOffClass + "'>\n <span>" + this.uncheckedLabel + "</span>\n</label>").appendTo(this.container);
32 this.offSpan = this.offLabel.children('span');
33 this.onLabel = $("<label class='" + this.labelOnClass + "'>\n <span>" + this.checkedLabel + "</span>\n</label>").appendTo(this.container);
34 this.onSpan = this.onLabel.children('span');
35 return this.handle = $("<div class='" + this.handleClass + "'>\n <div class='" + this.handleRightClass + "'>\n <div class='" + this.handleCenterClass + "' />\n </div>\n</div>").appendTo(this.container);
37 iOSCheckbox.prototype.disableTextSelection = function() {
39 return $([this.handle, this.offLabel, this.onLabel, this.container]).attr("unselectable", "on");
42 iOSCheckbox.prototype._getDimension = function(elem, dimension) {
43 if ($.fn.actual != null) {
44 return elem.actual(dimension);
46 return elem[dimension]();
49 iOSCheckbox.prototype.optionallyResize = function(mode) {
50 var newWidth, offLabelWidth, onLabelWidth;
51 onLabelWidth = this._getDimension(this.onLabel, "width");
52 offLabelWidth = this._getDimension(this.offLabel, "width");
53 if (mode === "container") {
54 newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
55 newWidth += this._getDimension(this.handle, "width") + this.handleMargin;
56 return this.container.css({
60 newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
61 return this.handle.css({
66 iOSCheckbox.prototype.onMouseDown = function(event) {
68 event.preventDefault();
69 if (this.isDisabled()) {
72 x = event.pageX || event.originalEvent.changedTouches[0].pageX;
73 iOSCheckbox.currentlyClicking = this.handle;
74 iOSCheckbox.dragStartPosition = x;
75 return iOSCheckbox.handleLeftOffset = parseInt(this.handle.css('left'), 10) || 0;
77 iOSCheckbox.prototype.onDragMove = function(event, x) {
79 if (iOSCheckbox.currentlyClicking !== this.handle) {
82 p = (x + iOSCheckbox.handleLeftOffset - iOSCheckbox.dragStartPosition) / this.rightSide;
89 newWidth = p * this.rightSide;
94 width: newWidth + this.handleRadius
97 marginRight: -newWidth
99 return this.onSpan.css({
100 marginLeft: -(1 - p) * this.rightSide
103 iOSCheckbox.prototype.onDragEnd = function(event, x) {
105 if (iOSCheckbox.currentlyClicking !== this.handle) {
108 if (this.isDisabled()) {
111 if (iOSCheckbox.dragging) {
112 p = (x - iOSCheckbox.dragStartPosition) / this.rightSide;
113 this.elem.prop('checked', p >= 0.5);
115 this.elem.prop('checked', !this.elem.prop('checked'));
117 iOSCheckbox.currentlyClicking = null;
118 iOSCheckbox.dragging = null;
119 return this.didChange();
121 iOSCheckbox.prototype.refresh = function() {
122 return this.didChange();
124 iOSCheckbox.prototype.didChange = function() {
126 if (typeof this.onChange === "function") {
127 this.onChange(this.elem, this.elem.prop('checked'));
129 if (this.isDisabled()) {
130 this.container.addClass(this.disabledClass);
133 this.container.removeClass(this.disabledClass);
135 new_left = this.elem.prop('checked') ? this.rightSide : 0;
136 this.handle.animate({
139 this.onLabel.animate({
140 width: new_left + this.handleRadius
142 this.offSpan.animate({
143 marginRight: -new_left
145 return this.onSpan.animate({
146 marginLeft: new_left - this.rightSide
149 iOSCheckbox.prototype.attachEvents = function() {
150 var localMouseMove, localMouseUp, self;
152 localMouseMove = function(event) {
153 return self.onGlobalMove.apply(self, arguments);
155 localMouseUp = function(event) {
156 self.onGlobalUp.apply(self, arguments);
157 $(document).unbind('mousemove touchmove', localMouseMove);
158 return $(document).unbind('mouseup touchend', localMouseUp);
160 this.elem.change(function() {
161 return self.refresh();
163 return this.container.bind('mousedown touchstart', function(event) {
164 self.onMouseDown.apply(self, arguments);
165 $(document).bind('mousemove touchmove', localMouseMove);
166 return $(document).bind('mouseup touchend', localMouseUp);
169 iOSCheckbox.prototype.initialPosition = function() {
170 var containerWidth, offset;
171 containerWidth = this._getDimension(this.container, "width");
173 width: containerWidth - this.containerRadius
175 offset = this.containerRadius + 1;
176 if ($.browser.msie && $.browser.version < 7) {
179 this.rightSide = containerWidth - this._getDimension(this.handle, "width") - offset;
180 if (this.elem.is(':checked')) {
185 width: this.rightSide + this.handleRadius
188 marginRight: -this.rightSide
195 marginLeft: -this.rightSide
198 if (this.isDisabled()) {
199 return this.container.addClass(this.disabledClass);
202 iOSCheckbox.prototype.onGlobalMove = function(event) {
204 if (!(!this.isDisabled() && iOSCheckbox.currentlyClicking)) {
207 event.preventDefault();
208 x = event.pageX || event.originalEvent.changedTouches[0].pageX;
209 if (!iOSCheckbox.dragging && (Math.abs(iOSCheckbox.dragStartPosition - x) > this.dragThreshold)) {
210 iOSCheckbox.dragging = true;
212 return this.onDragMove(event, x);
214 iOSCheckbox.prototype.onGlobalUp = function(event) {
216 if (!iOSCheckbox.currentlyClicking) {
219 event.preventDefault();
220 x = event.pageX || event.originalEvent.changedTouches[0].pageX;
221 this.onDragEnd(event, x);
224 iOSCheckbox.defaults = {
227 uncheckedLabel: 'OFF',
229 resizeContainer: true,
230 disabledClass: 'iPhoneCheckDisabled',
231 containerClass: 'iPhoneCheckContainer',
232 labelOnClass: 'iPhoneCheckLabelOn',
233 labelOffClass: 'iPhoneCheckLabelOff',
234 handleClass: 'iPhoneCheckHandle',
235 handleCenterClass: 'iPhoneCheckHandleCenter',
236 handleRightClass: 'iPhoneCheckHandleRight',
241 dataName: "iphoneStyle",
242 onChange: function() {}
246 $.iphoneStyle = this.iOSCheckbox = iOSCheckbox;
247 $.fn.iphoneStyle = function() {
248 var args, checkbox, dataName, existingControl, method, params, _i, _len, _ref, _ref2, _ref3, _ref4;
249 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
250 dataName = (_ref = (_ref2 = args[0]) != null ? _ref2.dataName : void 0) != null ? _ref : iOSCheckbox.defaults.dataName;
251 _ref3 = this.filter(':checkbox');
252 for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
253 checkbox = _ref3[_i];
254 existingControl = $(checkbox).data(dataName);
255 if (existingControl != null) {
256 method = args[0], params = 2 <= args.length ? __slice.call(args, 1) : [];
257 if ((_ref4 = existingControl[method]) != null) {
258 _ref4.apply(existingControl, params);
261 new iOSCheckbox(checkbox, args[0]);
266 $.fn.iOSCheckbox = function(options) {
268 if (options == null) {
271 opts = $.extend({}, options, {
273 disabledClass: 'iOSCheckDisabled',
274 containerClass: 'iOSCheckContainer',
275 labelOnClass: 'iOSCheckLabelOn',
276 labelOffClass: 'iOSCheckLabelOff',
277 handleClass: 'iOSCheckHandle',
278 handleCenterClass: 'iOSCheckHandleCenter',
279 handleRightClass: 'iOSCheckHandleRight',
280 dataName: 'iOSCheckbox'
282 return this.iphoneStyle(opts);