jquery-knob-rails 1.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ Dummy::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # Code is not reloaded between requests
5
+ config.cache_classes = true
6
+
7
+ # Full error reports are disabled and caching is turned on
8
+ config.consider_all_requests_local = false
9
+ config.action_controller.perform_caching = true
10
+
11
+ # Disable Rails's static asset server (Apache or nginx will already do this)
12
+ config.serve_static_assets = false
13
+
14
+ # Compress JavaScripts and CSS
15
+ config.assets.compress = true
16
+
17
+ # Don't fallback to assets pipeline if a precompiled asset is missed
18
+ config.assets.compile = false
19
+
20
+ # Generate digests for assets URLs
21
+ config.assets.digest = true
22
+
23
+ # Defaults to nil and saved in location specified by config.assets.prefix
24
+ # config.assets.manifest = YOUR_PATH
25
+
26
+ # Specifies the header that your server uses for sending files
27
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29
+
30
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31
+ # config.force_ssl = true
32
+
33
+ # See everything in the log (default is :info)
34
+ # config.log_level = :debug
35
+
36
+ # Prepend all log lines with the following tags
37
+ # config.log_tags = [ :subdomain, :uuid ]
38
+
39
+ # Use a different logger for distributed setups
40
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
41
+
42
+ # Use a different cache store in production
43
+ # config.cache_store = :mem_cache_store
44
+
45
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server
46
+ # config.action_controller.asset_host = "http://assets.example.com"
47
+
48
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
49
+ # config.assets.precompile += %w( search.js )
50
+
51
+ # Disable delivery errors, bad email addresses will be ignored
52
+ # config.action_mailer.raise_delivery_errors = false
53
+
54
+ # Enable threaded mode
55
+ # config.threadsafe!
56
+
57
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58
+ # the I18n.default_locale when a translation can not be found)
59
+ config.i18n.fallbacks = true
60
+
61
+ # Send deprecation notices to registered listeners
62
+ config.active_support.deprecation = :notify
63
+
64
+ end
@@ -0,0 +1,35 @@
1
+ Dummy::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Configure static asset server for tests with Cache-Control for performance
11
+ config.serve_static_assets = true
12
+ config.static_cache_control = "public, max-age=3600"
13
+
14
+ # Log error messages when you accidentally call methods on nil
15
+ config.whiny_nils = true
16
+
17
+ # Show full error reports and disable caching
18
+ config.consider_all_requests_local = true
19
+ config.action_controller.perform_caching = false
20
+
21
+ # Raise exceptions instead of rendering exception templates
22
+ config.action_dispatch.show_exceptions = false
23
+
24
+ # Disable request forgery protection in test environment
25
+ config.action_controller.allow_forgery_protection = false
26
+
27
+ # Tell Action Mailer not to deliver emails to the real world.
28
+ # The :test delivery method accumulates sent emails in the
29
+ # ActionMailer::Base.deliveries array.
30
+ config.action_mailer.delivery_method = :test
31
+
32
+
33
+ # Print deprecation notices to the stderr
34
+ config.active_support.deprecation = :stderr
35
+ end
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
+ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
+
6
+ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
+ # Rails.backtrace_cleaner.remove_silencers!
@@ -0,0 +1,15 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format
4
+ # (all these examples are active by default):
5
+ # ActiveSupport::Inflector.inflections do |inflect|
6
+ # inflect.plural /^(ox)$/i, '\1en'
7
+ # inflect.singular /^(ox)en/i, '\1'
8
+ # inflect.irregular 'person', 'people'
9
+ # inflect.uncountable %w( fish sheep )
10
+ # end
11
+ #
12
+ # These inflection rules are supported but not enabled by default:
13
+ # ActiveSupport::Inflector.inflections do |inflect|
14
+ # inflect.acronym 'RESTful'
15
+ # end
@@ -0,0 +1,5 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new mime types for use in respond_to blocks:
4
+ # Mime::Type.register "text/richtext", :rtf
5
+ # Mime::Type.register_alias "text/html", :iphone
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+ # Make sure the secret is at least 30 characters and all random,
6
+ # no regular words or you'll be exposed to dictionary attacks.
7
+ Dummy::Application.config.secret_token = '49dfd6e5e224394dc63086a6507249b44ff1ca26e4a474ceb4e57f19aeacc345d514ee349e42e82b7a83d287041cf85487c0753f213534e4dbd02f355202a00b'
@@ -0,0 +1,8 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
4
+
5
+ # Use the database for sessions instead of the cookie-based default,
6
+ # which shouldn't be used to store highly confidential information
7
+ # (create the session table with "rails generate session_migration")
8
+ # Dummy::Application.config.session_store :active_record_store
@@ -0,0 +1,10 @@
1
+ # Be sure to restart your server when you modify this file.
2
+ #
3
+ # This file contains settings for ActionController::ParamsWrapper which
4
+ # is enabled by default.
5
+
6
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
+ ActiveSupport.on_load(:action_controller) do
8
+ wrap_parameters format: [:json]
9
+ end
10
+
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: "Hello world"
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class NavigationTest < ActionDispatch::IntegrationTest
4
+ test 'can access jquery-knob' do
5
+ get '/assets/jquery.knob.js'
6
+ assert_response :success
7
+ end
8
+
9
+ test 'can access jquery-knob min version' do
10
+ get '/assets/jquery.knob.min.js'
11
+ assert_response :success
12
+ end
13
+
14
+ test 'jquery-knob response is for the expected version' do
15
+ get '/assets/jquery.knob.js'
16
+ assert_match(/Version: 1\.2\.12/, @response.body)
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class JqueryKnobRailsTest < ActiveSupport::TestCase
4
+ test 'truth' do
5
+ assert_kind_of Module, JqueryKnob::Rails
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # Configure Rails Environment
2
+ ENV['RAILS_ENV'] = 'test'
3
+
4
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
5
+ require 'rails/test_help'
6
+
7
+ Rails.backtrace_cleaner.remove_silencers!
8
+
9
+ # Load support files
10
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
11
+
12
+ # Load fixtures from the engine
13
+ if ActiveSupport::TestCase.method_defined?(:fixture_path=)
14
+ ActiveSupport::TestCase.fixture_path = File.expand_path('../fixtures', __FILE__)
15
+ end
@@ -0,0 +1,805 @@
1
+ /*!jQuery Knob*/
2
+ /**
3
+ * Downward compatible, touchable dial
4
+ *
5
+ * Version: 1.2.12
6
+ * Requires: jQuery v1.7+
7
+ *
8
+ * Copyright (c) 2012 Anthony Terrien
9
+ * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
10
+ *
11
+ * Thanks to vor, eskimoblood, spiffistan, FabrizioC
12
+ */
13
+ (function (factory) {
14
+ if (typeof exports === 'object') {
15
+ // CommonJS
16
+ module.exports = factory(require('jquery'));
17
+ } else if (typeof define === 'function' && define.amd) {
18
+ // AMD. Register as an anonymous module.
19
+ define(['jquery'], factory);
20
+ } else {
21
+ // Browser globals
22
+ factory(jQuery);
23
+ }
24
+ }(function ($) {
25
+
26
+ /**
27
+ * Kontrol library
28
+ */
29
+ "use strict";
30
+
31
+ /**
32
+ * Definition of globals and core
33
+ */
34
+ var k = {}, // kontrol
35
+ max = Math.max,
36
+ min = Math.min;
37
+
38
+ k.c = {};
39
+ k.c.d = $(document);
40
+ k.c.t = function (e) {
41
+ return e.originalEvent.touches.length - 1;
42
+ };
43
+
44
+ /**
45
+ * Kontrol Object
46
+ *
47
+ * Definition of an abstract UI control
48
+ *
49
+ * Each concrete component must call this one.
50
+ * <code>
51
+ * k.o.call(this);
52
+ * </code>
53
+ */
54
+ k.o = function () {
55
+ var s = this;
56
+
57
+ this.o = null; // array of options
58
+ this.$ = null; // jQuery wrapped element
59
+ this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
60
+ this.g = null; // deprecated 2D graphics context for 'pre-rendering'
61
+ this.v = null; // value ; mixed array or integer
62
+ this.cv = null; // change value ; not commited value
63
+ this.x = 0; // canvas x position
64
+ this.y = 0; // canvas y position
65
+ this.w = 0; // canvas width
66
+ this.h = 0; // canvas height
67
+ this.$c = null; // jQuery canvas element
68
+ this.c = null; // rendered canvas context
69
+ this.t = 0; // touches index
70
+ this.isInit = false;
71
+ this.fgColor = null; // main color
72
+ this.pColor = null; // previous color
73
+ this.dH = null; // draw hook
74
+ this.cH = null; // change hook
75
+ this.eH = null; // cancel hook
76
+ this.rH = null; // release hook
77
+ this.scale = 1; // scale factor
78
+ this.relative = false;
79
+ this.relativeWidth = false;
80
+ this.relativeHeight = false;
81
+ this.$div = null; // component div
82
+
83
+ this.run = function () {
84
+ var cf = function (e, conf) {
85
+ var k;
86
+ for (k in conf) {
87
+ s.o[k] = conf[k];
88
+ }
89
+ s._carve().init();
90
+ s._configure()
91
+ ._draw();
92
+ };
93
+
94
+ if (this.$.data('kontroled')) return;
95
+ this.$.data('kontroled', true);
96
+
97
+ this.extend();
98
+ this.o = $.extend({
99
+ // Config
100
+ min: this.$.data('min') !== undefined ? this.$.data('min') : 0,
101
+ max: this.$.data('max') !== undefined ? this.$.data('max') : 100,
102
+ stopper: true,
103
+ readOnly: this.$.data('readonly') || (this.$.attr('readonly') === 'readonly'),
104
+
105
+ // UI
106
+ cursor: this.$.data('cursor') === true && 30
107
+ || this.$.data('cursor') || 0,
108
+ thickness: this.$.data('thickness')
109
+ && Math.max(Math.min(this.$.data('thickness'), 1), 0.01)
110
+ || 0.35,
111
+ lineCap: this.$.data('linecap') || 'butt',
112
+ width: this.$.data('width') || 200,
113
+ height: this.$.data('height') || 200,
114
+ displayInput: this.$.data('displayinput') == null || this.$.data('displayinput'),
115
+ displayPrevious: this.$.data('displayprevious'),
116
+ fgColor: this.$.data('fgcolor') || '#87CEEB',
117
+ inputColor: this.$.data('inputcolor'),
118
+ font: this.$.data('font') || 'Arial',
119
+ fontWeight: this.$.data('font-weight') || 'bold',
120
+ inline: false,
121
+ step: this.$.data('step') || 1,
122
+ rotation: this.$.data('rotation'),
123
+
124
+ // Hooks
125
+ draw: null, // function () {}
126
+ change: null, // function (value) {}
127
+ cancel: null, // function () {}
128
+ release: null, // function (value) {}
129
+
130
+ // Output formatting, allows to add unit: %, ms ...
131
+ format: function(v) {
132
+ return v;
133
+ },
134
+ parse: function (v) {
135
+ return parseFloat(v);
136
+ }
137
+ }, this.o
138
+ );
139
+
140
+ // finalize options
141
+ this.o.flip = this.o.rotation === 'anticlockwise' || this.o.rotation === 'acw';
142
+ if (!this.o.inputColor) {
143
+ this.o.inputColor = this.o.fgColor;
144
+ }
145
+
146
+ // routing value
147
+ if (this.$.is('fieldset')) {
148
+
149
+ // fieldset = array of integer
150
+ this.v = {};
151
+ this.i = this.$.find('input');
152
+ this.i.each(function(k) {
153
+ var $this = $(this);
154
+ s.i[k] = $this;
155
+ s.v[k] = s.o.parse($this.val());
156
+
157
+ $this.bind(
158
+ 'change blur',
159
+ function () {
160
+ var val = {};
161
+ val[k] = $this.val();
162
+ s.val(s._validate(val));
163
+ }
164
+ );
165
+ });
166
+ this.$.find('legend').remove();
167
+ } else {
168
+
169
+ // input = integer
170
+ this.i = this.$;
171
+ this.v = this.o.parse(this.$.val());
172
+ this.v === '' && (this.v = this.o.min);
173
+ this.$.bind(
174
+ 'change blur',
175
+ function () {
176
+ s.val(s._validate(s.o.parse(s.$.val())));
177
+ }
178
+ );
179
+
180
+ }
181
+
182
+ !this.o.displayInput && this.$.hide();
183
+
184
+ // adds needed DOM elements (canvas, div)
185
+ this.$c = $(document.createElement('canvas')).attr({
186
+ width: this.o.width,
187
+ height: this.o.height
188
+ });
189
+
190
+ // wraps all elements in a div
191
+ // add to DOM before Canvas init is triggered
192
+ this.$div = $('<div style="'
193
+ + (this.o.inline ? 'display:inline;' : '')
194
+ + 'width:' + this.o.width + 'px;height:' + this.o.height + 'px;'
195
+ + '"></div>');
196
+
197
+ this.$.wrap(this.$div).before(this.$c);
198
+ this.$div = this.$.parent();
199
+
200
+ if (typeof G_vmlCanvasManager !== 'undefined') {
201
+ G_vmlCanvasManager.initElement(this.$c[0]);
202
+ }
203
+
204
+ this.c = this.$c[0].getContext ? this.$c[0].getContext('2d') : null;
205
+
206
+ if (!this.c) {
207
+ throw {
208
+ name: "CanvasNotSupportedException",
209
+ message: "Canvas not supported. Please use excanvas on IE8.0.",
210
+ toString: function(){return this.name + ": " + this.message}
211
+ }
212
+ }
213
+
214
+ // hdpi support
215
+ this.scale = (window.devicePixelRatio || 1) / (
216
+ this.c.webkitBackingStorePixelRatio ||
217
+ this.c.mozBackingStorePixelRatio ||
218
+ this.c.msBackingStorePixelRatio ||
219
+ this.c.oBackingStorePixelRatio ||
220
+ this.c.backingStorePixelRatio || 1
221
+ );
222
+
223
+ // detects relative width / height
224
+ this.relativeWidth = this.o.width % 1 !== 0
225
+ && this.o.width.indexOf('%');
226
+ this.relativeHeight = this.o.height % 1 !== 0
227
+ && this.o.height.indexOf('%');
228
+ this.relative = this.relativeWidth || this.relativeHeight;
229
+
230
+ // computes size and carves the component
231
+ this._carve();
232
+
233
+ // prepares props for transaction
234
+ if (this.v instanceof Object) {
235
+ this.cv = {};
236
+ this.copy(this.v, this.cv);
237
+ } else {
238
+ this.cv = this.v;
239
+ }
240
+
241
+ // binds configure event
242
+ this.$
243
+ .bind("configure", cf)
244
+ .parent()
245
+ .bind("configure", cf);
246
+
247
+ // finalize init
248
+ this._listen()
249
+ ._configure()
250
+ ._xy()
251
+ .init();
252
+
253
+ this.isInit = true;
254
+
255
+ this.$.val(this.o.format(this.v));
256
+ this._draw();
257
+
258
+ return this;
259
+ };
260
+
261
+ this._carve = function() {
262
+ if (this.relative) {
263
+ var w = this.relativeWidth ?
264
+ this.$div.parent().width() *
265
+ parseInt(this.o.width) / 100
266
+ : this.$div.parent().width(),
267
+ h = this.relativeHeight ?
268
+ this.$div.parent().height() *
269
+ parseInt(this.o.height) / 100
270
+ : this.$div.parent().height();
271
+
272
+ // apply relative
273
+ this.w = this.h = Math.min(w, h);
274
+ } else {
275
+ this.w = this.o.width;
276
+ this.h = this.o.height;
277
+ }
278
+
279
+ // finalize div
280
+ this.$div.css({
281
+ 'width': this.w + 'px',
282
+ 'height': this.h + 'px'
283
+ });
284
+
285
+ // finalize canvas with computed width
286
+ this.$c.attr({
287
+ width: this.w,
288
+ height: this.h
289
+ });
290
+
291
+ // scaling
292
+ if (this.scale !== 1) {
293
+ this.$c[0].width = this.$c[0].width * this.scale;
294
+ this.$c[0].height = this.$c[0].height * this.scale;
295
+ this.$c.width(this.w);
296
+ this.$c.height(this.h);
297
+ }
298
+
299
+ return this;
300
+ };
301
+
302
+ this._draw = function () {
303
+
304
+ // canvas pre-rendering
305
+ var d = true;
306
+
307
+ s.g = s.c;
308
+
309
+ s.clear();
310
+
311
+ s.dH && (d = s.dH());
312
+
313
+ d !== false && s.draw();
314
+ };
315
+
316
+ this._touch = function (e) {
317
+ var touchMove = function (e) {
318
+ var v = s.xy2val(
319
+ e.originalEvent.touches[s.t].pageX,
320
+ e.originalEvent.touches[s.t].pageY
321
+ );
322
+
323
+ if (v == s.cv) return;
324
+
325
+ if (s.cH && s.cH(v) === false) return;
326
+
327
+ s.change(s._validate(v));
328
+ s._draw();
329
+ };
330
+
331
+ // get touches index
332
+ this.t = k.c.t(e);
333
+
334
+ // First touch
335
+ touchMove(e);
336
+
337
+ // Touch events listeners
338
+ k.c.d
339
+ .bind("touchmove.k", touchMove)
340
+ .bind(
341
+ "touchend.k",
342
+ function () {
343
+ k.c.d.unbind('touchmove.k touchend.k');
344
+ s.val(s.cv);
345
+ }
346
+ );
347
+
348
+ return this;
349
+ };
350
+
351
+ this._mouse = function (e) {
352
+ var mouseMove = function (e) {
353
+ var v = s.xy2val(e.pageX, e.pageY);
354
+
355
+ if (v == s.cv) return;
356
+
357
+ if (s.cH && (s.cH(v) === false)) return;
358
+
359
+ s.change(s._validate(v));
360
+ s._draw();
361
+ };
362
+
363
+ // First click
364
+ mouseMove(e);
365
+
366
+ // Mouse events listeners
367
+ k.c.d
368
+ .bind("mousemove.k", mouseMove)
369
+ .bind(
370
+ // Escape key cancel current change
371
+ "keyup.k",
372
+ function (e) {
373
+ if (e.keyCode === 27) {
374
+ k.c.d.unbind("mouseup.k mousemove.k keyup.k");
375
+
376
+ if (s.eH && s.eH() === false)
377
+ return;
378
+
379
+ s.cancel();
380
+ }
381
+ }
382
+ )
383
+ .bind(
384
+ "mouseup.k",
385
+ function (e) {
386
+ k.c.d.unbind('mousemove.k mouseup.k keyup.k');
387
+ s.val(s.cv);
388
+ }
389
+ );
390
+
391
+ return this;
392
+ };
393
+
394
+ this._xy = function () {
395
+ var o = this.$c.offset();
396
+ this.x = o.left;
397
+ this.y = o.top;
398
+
399
+ return this;
400
+ };
401
+
402
+ this._listen = function () {
403
+ if (!this.o.readOnly) {
404
+ this.$c
405
+ .bind(
406
+ "mousedown",
407
+ function (e) {
408
+ e.preventDefault();
409
+ s._xy()._mouse(e);
410
+ }
411
+ )
412
+ .bind(
413
+ "touchstart",
414
+ function (e) {
415
+ e.preventDefault();
416
+ s._xy()._touch(e);
417
+ }
418
+ );
419
+
420
+ this.listen();
421
+ } else {
422
+ this.$.attr('readonly', 'readonly');
423
+ }
424
+
425
+ if (this.relative) {
426
+ $(window).resize(function() {
427
+ s._carve().init();
428
+ s._draw();
429
+ });
430
+ }
431
+
432
+ return this;
433
+ };
434
+
435
+ this._configure = function () {
436
+
437
+ // Hooks
438
+ if (this.o.draw) this.dH = this.o.draw;
439
+ if (this.o.change) this.cH = this.o.change;
440
+ if (this.o.cancel) this.eH = this.o.cancel;
441
+ if (this.o.release) this.rH = this.o.release;
442
+
443
+ if (this.o.displayPrevious) {
444
+ this.pColor = this.h2rgba(this.o.fgColor, "0.4");
445
+ this.fgColor = this.h2rgba(this.o.fgColor, "0.6");
446
+ } else {
447
+ this.fgColor = this.o.fgColor;
448
+ }
449
+
450
+ return this;
451
+ };
452
+
453
+ this._clear = function () {
454
+ this.$c[0].width = this.$c[0].width;
455
+ };
456
+
457
+ this._validate = function (v) {
458
+ var val = (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;
459
+ return Math.round(val * 100) / 100;
460
+ };
461
+
462
+ // Abstract methods
463
+ this.listen = function () {}; // on start, one time
464
+ this.extend = function () {}; // each time configure triggered
465
+ this.init = function () {}; // each time configure triggered
466
+ this.change = function (v) {}; // on change
467
+ this.val = function (v) {}; // on release
468
+ this.xy2val = function (x, y) {}; //
469
+ this.draw = function () {}; // on change / on release
470
+ this.clear = function () { this._clear(); };
471
+
472
+ // Utils
473
+ this.h2rgba = function (h, a) {
474
+ var rgb;
475
+ h = h.substring(1,7);
476
+ rgb = [
477
+ parseInt(h.substring(0,2), 16),
478
+ parseInt(h.substring(2,4), 16),
479
+ parseInt(h.substring(4,6), 16)
480
+ ];
481
+
482
+ return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")";
483
+ };
484
+
485
+ this.copy = function (f, t) {
486
+ for (var i in f) {
487
+ t[i] = f[i];
488
+ }
489
+ };
490
+ };
491
+
492
+
493
+ /**
494
+ * k.Dial
495
+ */
496
+ k.Dial = function () {
497
+ k.o.call(this);
498
+
499
+ this.startAngle = null;
500
+ this.xy = null;
501
+ this.radius = null;
502
+ this.lineWidth = null;
503
+ this.cursorExt = null;
504
+ this.w2 = null;
505
+ this.PI2 = 2*Math.PI;
506
+
507
+ this.extend = function () {
508
+ this.o = $.extend({
509
+ bgColor: this.$.data('bgcolor') || '#EEEEEE',
510
+ angleOffset: this.$.data('angleoffset') || 0,
511
+ angleArc: this.$.data('anglearc') || 360,
512
+ inline: true
513
+ }, this.o);
514
+ };
515
+
516
+ this.val = function (v, triggerRelease) {
517
+ if (null != v) {
518
+
519
+ // reverse format
520
+ v = this.o.parse(v);
521
+
522
+ if (triggerRelease !== false
523
+ && v != this.v
524
+ && this.rH
525
+ && this.rH(v) === false) { return; }
526
+
527
+ this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;
528
+ this.v = this.cv;
529
+ this.$.val(this.o.format(this.v));
530
+ this._draw();
531
+ } else {
532
+ return this.v;
533
+ }
534
+ };
535
+
536
+ this.xy2val = function (x, y) {
537
+ var a, ret;
538
+
539
+ a = Math.atan2(
540
+ x - (this.x + this.w2),
541
+ - (y - this.y - this.w2)
542
+ ) - this.angleOffset;
543
+
544
+ if (this.o.flip) {
545
+ a = this.angleArc - a - this.PI2;
546
+ }
547
+
548
+ if (this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {
549
+
550
+ // if isset angleArc option, set to min if .5 under min
551
+ a = 0;
552
+ } else if (a < 0) {
553
+ a += this.PI2;
554
+ }
555
+
556
+ ret = (a * (this.o.max - this.o.min) / this.angleArc) + this.o.min;
557
+
558
+ this.o.stopper && (ret = max(min(ret, this.o.max), this.o.min));
559
+
560
+ return ret;
561
+ };
562
+
563
+ this.listen = function () {
564
+
565
+ // bind MouseWheel
566
+ var s = this, mwTimerStop,
567
+ mwTimerRelease,
568
+ mw = function (e) {
569
+ e.preventDefault();
570
+
571
+ var ori = e.originalEvent,
572
+ deltaX = ori.detail || ori.wheelDeltaX,
573
+ deltaY = ori.detail || ori.wheelDeltaY,
574
+ v = s._validate(s.o.parse(s.$.val()))
575
+ + (
576
+ deltaX > 0 || deltaY > 0
577
+ ? s.o.step
578
+ : deltaX < 0 || deltaY < 0 ? -s.o.step : 0
579
+ );
580
+
581
+ v = max(min(v, s.o.max), s.o.min);
582
+
583
+ s.val(v, false);
584
+
585
+ if (s.rH) {
586
+ // Handle mousewheel stop
587
+ clearTimeout(mwTimerStop);
588
+ mwTimerStop = setTimeout(function () {
589
+ s.rH(v);
590
+ mwTimerStop = null;
591
+ }, 100);
592
+
593
+ // Handle mousewheel releases
594
+ if (!mwTimerRelease) {
595
+ mwTimerRelease = setTimeout(function () {
596
+ if (mwTimerStop)
597
+ s.rH(v);
598
+ mwTimerRelease = null;
599
+ }, 200);
600
+ }
601
+ }
602
+ },
603
+ kval,
604
+ to,
605
+ m = 1,
606
+ kv = {
607
+ 37: -s.o.step,
608
+ 38: s.o.step,
609
+ 39: s.o.step,
610
+ 40: -s.o.step
611
+ };
612
+
613
+ this.$
614
+ .bind(
615
+ "keydown",
616
+ function (e) {
617
+ var kc = e.keyCode;
618
+
619
+ // numpad support
620
+ if (kc >= 96 && kc <= 105) {
621
+ kc = e.keyCode = kc - 48;
622
+ }
623
+
624
+ kval = parseInt(String.fromCharCode(kc));
625
+
626
+ if (isNaN(kval)) {
627
+ (kc !== 13) // enter
628
+ && kc !== 8 // bs
629
+ && kc !== 9 // tab
630
+ && kc !== 189 // -
631
+ && (kc !== 190
632
+ || s.$.val().match(/\./)) // . allowed once
633
+ && e.preventDefault();
634
+
635
+ // arrows
636
+ if ($.inArray(kc,[37,38,39,40]) > -1) {
637
+ e.preventDefault();
638
+
639
+ var v = s.o.parse(s.$.val()) + kv[kc] * m;
640
+ s.o.stopper && (v = max(min(v, s.o.max), s.o.min));
641
+
642
+ s.change(s._validate(v));
643
+ s._draw();
644
+
645
+ // long time keydown speed-up
646
+ to = window.setTimeout(function () {
647
+ m *= 2;
648
+ }, 30);
649
+ }
650
+ }
651
+ }
652
+ )
653
+ .bind(
654
+ "keyup",
655
+ function (e) {
656
+ if (isNaN(kval)) {
657
+ if (to) {
658
+ window.clearTimeout(to);
659
+ to = null;
660
+ m = 1;
661
+ s.val(s.$.val());
662
+ }
663
+ } else {
664
+ // kval postcond
665
+ (s.$.val() > s.o.max && s.$.val(s.o.max))
666
+ || (s.$.val() < s.o.min && s.$.val(s.o.min));
667
+ }
668
+ }
669
+ );
670
+
671
+ this.$c.bind("mousewheel DOMMouseScroll", mw);
672
+ this.$.bind("mousewheel DOMMouseScroll", mw);
673
+ };
674
+
675
+ this.init = function () {
676
+ if (this.v < this.o.min
677
+ || this.v > this.o.max) { this.v = this.o.min; }
678
+
679
+ this.$.val(this.v);
680
+ this.w2 = this.w / 2;
681
+ this.cursorExt = this.o.cursor / 100;
682
+ this.xy = this.w2 * this.scale;
683
+ this.lineWidth = this.xy * this.o.thickness;
684
+ this.lineCap = this.o.lineCap;
685
+ this.radius = this.xy - this.lineWidth / 2;
686
+
687
+ this.o.angleOffset
688
+ && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);
689
+
690
+ this.o.angleArc
691
+ && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);
692
+
693
+ // deg to rad
694
+ this.angleOffset = this.o.angleOffset * Math.PI / 180;
695
+ this.angleArc = this.o.angleArc * Math.PI / 180;
696
+
697
+ // compute start and end angles
698
+ this.startAngle = 1.5 * Math.PI + this.angleOffset;
699
+ this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;
700
+
701
+ var s = max(
702
+ String(Math.abs(this.o.max)).length,
703
+ String(Math.abs(this.o.min)).length,
704
+ 2
705
+ ) + 2;
706
+
707
+ this.o.displayInput
708
+ && this.i.css({
709
+ 'width' : ((this.w / 2 + 4) >> 0) + 'px',
710
+ 'height' : ((this.w / 3) >> 0) + 'px',
711
+ 'position' : 'absolute',
712
+ 'vertical-align' : 'middle',
713
+ 'margin-top' : ((this.w / 3) >> 0) + 'px',
714
+ 'margin-left' : '-' + ((this.w * 3 / 4 + 2) >> 0) + 'px',
715
+ 'border' : 0,
716
+ 'background' : 'none',
717
+ 'font' : this.o.fontWeight + ' ' + ((this.w / s) >> 0) + 'px ' + this.o.font,
718
+ 'text-align' : 'center',
719
+ 'color' : this.o.inputColor || this.o.fgColor,
720
+ 'padding' : '0px',
721
+ '-webkit-appearance': 'none'
722
+ }) || this.i.css({
723
+ 'width': '0px',
724
+ 'visibility': 'hidden'
725
+ });
726
+ };
727
+
728
+ this.change = function (v) {
729
+ this.cv = v;
730
+ this.$.val(this.o.format(v));
731
+ };
732
+
733
+ this.angle = function (v) {
734
+ return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);
735
+ };
736
+
737
+ this.arc = function (v) {
738
+ var sa, ea;
739
+ v = this.angle(v);
740
+ if (this.o.flip) {
741
+ sa = this.endAngle + 0.00001;
742
+ ea = sa - v - 0.00001;
743
+ } else {
744
+ sa = this.startAngle - 0.00001;
745
+ ea = sa + v + 0.00001;
746
+ }
747
+ this.o.cursor
748
+ && (sa = ea - this.cursorExt)
749
+ && (ea = ea + this.cursorExt);
750
+
751
+ return {
752
+ s: sa,
753
+ e: ea,
754
+ d: this.o.flip && !this.o.cursor
755
+ };
756
+ };
757
+
758
+ this.draw = function () {
759
+ var c = this.g, // context
760
+ a = this.arc(this.cv), // Arc
761
+ pa, // Previous arc
762
+ r = 1;
763
+
764
+ c.lineWidth = this.lineWidth;
765
+ c.lineCap = this.lineCap;
766
+
767
+ if (this.o.bgColor !== "none") {
768
+ c.beginPath();
769
+ c.strokeStyle = this.o.bgColor;
770
+ c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);
771
+ c.stroke();
772
+ }
773
+
774
+ if (this.o.displayPrevious) {
775
+ pa = this.arc(this.v);
776
+ c.beginPath();
777
+ c.strokeStyle = this.pColor;
778
+ c.arc(this.xy, this.xy, this.radius, pa.s, pa.e, pa.d);
779
+ c.stroke();
780
+ r = this.cv == this.v;
781
+ }
782
+
783
+ c.beginPath();
784
+ c.strokeStyle = r ? this.o.fgColor : this.fgColor ;
785
+ c.arc(this.xy, this.xy, this.radius, a.s, a.e, a.d);
786
+ c.stroke();
787
+ };
788
+
789
+ this.cancel = function () {
790
+ this.val(this.v);
791
+ };
792
+ };
793
+
794
+ $.fn.dial = $.fn.knob = function (o) {
795
+ return this.each(
796
+ function () {
797
+ var d = new k.Dial();
798
+ d.o = o;
799
+ d.$ = $(this);
800
+ d.run();
801
+ }
802
+ ).parent();
803
+ };
804
+
805
+ }));