jquery-knob-rails 1.2.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }));