rademade_admin 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +5 -12
  3. data/app/assets/javascripts/rademade_admin/app/common/related-index.coffee +5 -24
  4. data/app/assets/javascripts/rademade_admin/form/form-ajax-submit.coffee +4 -0
  5. data/app/assets/javascripts/rademade_admin.coffee +28 -7
  6. data/app/assets/stylesheets/rademade_admin/detail_admin/icons.scss.erb +1 -1
  7. data/app/assets/stylesheets/rademade_admin.scss.erb +19 -0
  8. data/app/controllers/rademade_admin/abstract_controller.rb +2 -0
  9. data/app/controllers/rademade_admin/admin_users_controller.rb +2 -1
  10. data/app/controllers/rademade_admin/application_controller.rb +3 -0
  11. data/app/controllers/rademade_admin/dashboard_controller.rb +1 -1
  12. data/app/controllers/rademade_admin/model_controller.rb +48 -25
  13. data/app/controllers/rademade_admin/sessions_controller.rb +2 -1
  14. data/app/helpers/rademade_admin/field_helper.rb +30 -3
  15. data/app/helpers/rademade_admin/form_helper.rb +12 -18
  16. data/app/helpers/rademade_admin/menu_helper.rb +2 -1
  17. data/app/helpers/rademade_admin/name_helper.rb +2 -1
  18. data/app/helpers/rademade_admin/upload_preview_helper.rb +2 -1
  19. data/app/helpers/rademade_admin/uri_helper.rb +16 -0
  20. data/app/inputs/rademade_admin/admin_file_input.rb +2 -1
  21. data/app/inputs/rademade_admin/admin_select_input.rb +2 -1
  22. data/app/inputs/rademade_admin/admin_textarea_input.rb +2 -1
  23. data/app/inputs/rademade_admin/boolean_input.rb +2 -1
  24. data/app/models/rademade_admin/ability.rb +1 -1
  25. data/app/serializers/autocomplete/base_serializer.rb +49 -0
  26. data/app/serializers/autocomplete/link_serializer.rb +20 -0
  27. data/app/services/form_builder.rb +2 -1
  28. data/app/services/linker.rb +34 -0
  29. data/app/services/loader_service.rb +2 -1
  30. data/app/services/login/error.rb +2 -1
  31. data/app/services/login.rb +2 -1
  32. data/app/services/model_controller/instance_options.rb +1 -0
  33. data/app/services/model_controller/model_options.rb +2 -1
  34. data/app/services/model_controller/notifier.rb +2 -1
  35. data/app/services/model_controller/templates.rb +10 -12
  36. data/app/services/saver.rb +2 -1
  37. data/app/services/search/conditions/abstract.rb +42 -38
  38. data/app/services/search/conditions/autocomplete.rb +34 -28
  39. data/app/services/search/conditions/list.rb +30 -23
  40. data/app/services/search/conditions/part/where.rb +28 -0
  41. data/app/services/search/conditions/related_list.rb +54 -0
  42. data/app/services/search/query_adapter/abstract.rb +30 -39
  43. data/app/services/search/query_adapter/active_record.rb +33 -21
  44. data/app/services/search/query_adapter/mongoid.rb +38 -20
  45. data/app/services/search/searcher.rb +5 -4
  46. data/app/services/sortable_service.rb +2 -1
  47. data/app/services/video_service.rb +2 -1
  48. data/app/views/rademade_admin/_blocks/_menu.html.erb +7 -1
  49. data/app/views/rademade_admin/_blocks/_sub_menu.html.erb +0 -8
  50. data/app/views/rademade_admin/_layouts/inner/related_index_table.html.erb +1 -2
  51. data/app/views/rademade_admin/abstract/index.html.erb +6 -5
  52. data/app/views/rademade_admin/abstract/related_index.html.erb +11 -4
  53. data/config/initializers/bower_rails.rb +6 -0
  54. data/config/initializers/devise.rb +1 -0
  55. data/config/initializers/formtastic.rb +13 -0
  56. data/config/initializers/routes.rb +2 -1
  57. data/config/routes.rb +2 -1
  58. data/lib/rademade_admin/bower/performer.rb +14 -0
  59. data/lib/rademade_admin/configuration.rb +2 -1
  60. data/lib/rademade_admin/engine.rb +5 -1
  61. data/lib/rademade_admin/file_info_formatter.rb +2 -1
  62. data/lib/rademade_admin/hrml_buffer.rb +2 -1
  63. data/lib/rademade_admin/model/configuration/fields.rb +2 -1
  64. data/lib/rademade_admin/model/configuration.rb +2 -1
  65. data/lib/rademade_admin/model/data_adapter/active_record.rb +10 -4
  66. data/lib/rademade_admin/model/data_adapter/mongoid.rb +6 -1
  67. data/lib/rademade_admin/model/data_adapter.rb +6 -1
  68. data/lib/rademade_admin/model/graph.rb +2 -1
  69. data/lib/rademade_admin/model/info.rb +4 -3
  70. data/lib/rademade_admin/model/reflection/data.rb +2 -1
  71. data/lib/rademade_admin/model/reflection/uploader.rb +2 -2
  72. data/lib/rademade_admin/model/reflection.rb +5 -13
  73. data/lib/rademade_admin/routing/mapper.rb +4 -1
  74. data/lib/rademade_admin/routing/resource.rb +2 -1
  75. data/lib/rademade_admin/routing.rb +2 -1
  76. data/lib/rademade_admin/sortable.rb +1 -0
  77. data/lib/rademade_admin/uploader/photo.rb +2 -1
  78. data/lib/rademade_admin/uploader/video.rb +2 -1
  79. data/lib/rademade_admin/user.rb +1 -0
  80. data/lib/rademade_admin/version.rb +2 -1
  81. data/lib/rademade_admin.rb +8 -6
  82. data/lib/tasks/rademade_bower_install.rake +9 -0
  83. metadata +92 -339
  84. data/MIT-LICENSE +0 -20
  85. data/app/assets/fonts/rademade_admin/glyphicons-halflings-regular.eot +0 -0
  86. data/app/assets/fonts/rademade_admin/glyphicons-halflings-regular.svg +0 -228
  87. data/app/assets/fonts/rademade_admin/glyphicons-halflings-regular.ttf +0 -0
  88. data/app/assets/fonts/rademade_admin/glyphicons-halflings-regular.woff +0 -0
  89. data/app/assets/images/rademade_admin/datatables/back_disabled.png +0 -0
  90. data/app/assets/images/rademade_admin/datatables/back_enabled.png +0 -0
  91. data/app/assets/images/rademade_admin/datatables/back_enabled_hover.png +0 -0
  92. data/app/assets/images/rademade_admin/datatables/forward_disabled.png +0 -0
  93. data/app/assets/images/rademade_admin/datatables/forward_enabled.png +0 -0
  94. data/app/assets/images/rademade_admin/datatables/forward_enabled_hover.png +0 -0
  95. data/app/assets/images/rademade_admin/datatables/sort_asc.png +0 -0
  96. data/app/assets/images/rademade_admin/datatables/sort_asc_disabled.png +0 -0
  97. data/app/assets/images/rademade_admin/datatables/sort_both.png +0 -0
  98. data/app/assets/images/rademade_admin/datatables/sort_desc.png +0 -0
  99. data/app/assets/images/rademade_admin/datatables/sort_desc_disabled.png +0 -0
  100. data/app/assets/images/rademade_admin/jquery-ui/animated-overlay.gif +0 -0
  101. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  102. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  103. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  104. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  105. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  106. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  107. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  108. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  109. data/app/assets/images/rademade_admin/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  110. data/app/assets/images/rademade_admin/jquery-ui/ui-icons_222222_256x240.png +0 -0
  111. data/app/assets/images/rademade_admin/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  112. data/app/assets/images/rademade_admin/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  113. data/app/assets/images/rademade_admin/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  114. data/app/assets/images/rademade_admin/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  115. data/app/assets/images/rademade_admin/select2/select2.png +0 -0
  116. data/app/assets/images/rademade_admin/select2/select2x2.png +0 -0
  117. data/app/assets/images/rademade_admin/select2/spinner.gif +0 -0
  118. data/app/assets/images/rademade_admin/uniform/bg-input-focus.png +0 -0
  119. data/app/assets/images/rademade_admin/uniform/bg-input.png +0 -0
  120. data/app/assets/images/rademade_admin/uniform/sprite.png +0 -0
  121. data/app/assets/javascripts/rademade_admin/form/library/jquery.form-serialize.js +0 -54
  122. data/app/assets/javascripts/rademade_admin/form/library/jquery.form.js +0 -1121
  123. data/app/assets/javascripts/rademade_admin/form/library/jquery.formrestrict.js +0 -27
  124. data/app/assets/javascripts/rademade_admin/form/library/jquery.validate.js +0 -1231
  125. data/app/assets/javascripts/rademade_admin/form/library/jquery.validate.messages_ru.js +0 -27
  126. data/app/assets/javascripts/rademade_admin/library/backbone.js +0 -1581
  127. data/app/assets/javascripts/rademade_admin/library/bootstrap/bootstrap.datepicker.js +0 -989
  128. data/app/assets/javascripts/rademade_admin/library/bootstrap/bootstrap.js +0 -1992
  129. data/app/assets/javascripts/rademade_admin/library/jquery/jquery-ui-1.10.4.custom.min.js +0 -6
  130. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.dataTables.js +0 -12099
  131. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.flot.js +0 -2960
  132. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.flot.resize.js +0 -60
  133. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.flot.stack.js +0 -188
  134. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.knob.js +0 -661
  135. data/app/assets/javascripts/rademade_admin/library/jquery/jquery.uniform.min.js +0 -1
  136. data/app/assets/javascripts/rademade_admin/library/notifier.custom.js +0 -431
  137. data/app/assets/javascripts/rademade_admin/library/underscore.js +0 -1276
  138. data/app/assets/javascripts/rademade_admin/library/wysihtml5-0.3.0.js +0 -9463
  139. data/app/assets/stylesheets/rademade_admin/bootstrap/bootstrap.css.erb +0 -5911
  140. data/app/assets/stylesheets/rademade_admin/lib/jquery-ui-1.10.2.custom.css.erb +0 -544
  141. data/app/assets/stylesheets/rademade_admin/lib/select2.css.erb +0 -513
  142. data/app/assets/stylesheets/rademade_admin/lib/uniform.default.css.erb +0 -366
  143. data/app/assets/stylesheets/rademade_admin.css +0 -14
  144. data/app/models/rademade_admin/user.rb +0 -6
  145. data/app/serializers/autocomplete_serializer.rb +0 -46
  146. data/app/services/model_controller/linker.rb +0 -49
  147. data/test/dummy/README.rdoc +0 -28
  148. data/test/dummy/Rakefile +0 -6
  149. data/test/dummy/app/assets/javascripts/application.js +0 -13
  150. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  151. data/test/dummy/app/controllers/application_controller.rb +0 -5
  152. data/test/dummy/app/controllers/rademade_admin/posts_controller.rb +0 -9
  153. data/test/dummy/app/controllers/rademade_admin/users_controller.rb +0 -14
  154. data/test/dummy/app/helpers/application_helper.rb +0 -2
  155. data/test/dummy/app/models/post.rb +0 -9
  156. data/test/dummy/app/models/user.rb +0 -7
  157. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  158. data/test/dummy/bin/bundle +0 -3
  159. data/test/dummy/bin/rails +0 -4
  160. data/test/dummy/bin/rake +0 -4
  161. data/test/dummy/config/application.rb +0 -29
  162. data/test/dummy/config/boot.rb +0 -5
  163. data/test/dummy/config/environment.rb +0 -5
  164. data/test/dummy/config/environments/development.rb +0 -29
  165. data/test/dummy/config/environments/production.rb +0 -80
  166. data/test/dummy/config/environments/test.rb +0 -36
  167. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  168. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  169. data/test/dummy/config/initializers/inflections.rb +0 -16
  170. data/test/dummy/config/initializers/mime_types.rb +0 -5
  171. data/test/dummy/config/initializers/rademade_admin.rb +0 -3
  172. data/test/dummy/config/initializers/secret_token.rb +0 -12
  173. data/test/dummy/config/initializers/session_store.rb +0 -3
  174. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  175. data/test/dummy/config/locales/en.yml +0 -23
  176. data/test/dummy/config/mongoid.yml +0 -6
  177. data/test/dummy/config/routes.rb +0 -8
  178. data/test/dummy/config.ru +0 -4
  179. data/test/dummy/db/development.sqlite3 +0 -0
  180. data/test/dummy/public/404.html +0 -58
  181. data/test/dummy/public/422.html +0 -58
  182. data/test/dummy/public/500.html +0 -57
  183. data/test/dummy/public/favicon.ico +0 -0
  184. data/test/integration/navigation_test.rb +0 -10
  185. data/test/rademade_admin_test.rb +0 -7
  186. data/test/test_helper.rb +0 -15
@@ -1,60 +0,0 @@
1
- /* Flot plugin for automatically redrawing plots as the placeholder resizes.
2
-
3
- Copyright (c) 2007-2013 IOLA and Ole Laursen.
4
- Licensed under the MIT license.
5
-
6
- It works by listening for changes on the placeholder div (through the jQuery
7
- resize event plugin) - if the size changes, it will redraw the plot.
8
-
9
- There are no options. If you need to disable the plugin for some plots, you
10
- can just fix the size of their placeholders.
11
-
12
- */
13
-
14
- /* Inline dependency:
15
- * jQuery resize event - v1.1 - 3/14/2010
16
- * http://benalman.com/projects/jquery-resize-plugin/
17
- *
18
- * Copyright (c) 2010 "Cowboy" Ben Alman
19
- * Dual licensed under the MIT and GPL licenses.
20
- * http://benalman.com/about/license/
21
- */
22
-
23
- (function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
24
-
25
- (function ($) {
26
- var options = { }; // no options
27
-
28
- function init(plot) {
29
- function onResize() {
30
- var placeholder = plot.getPlaceholder();
31
-
32
- // somebody might have hidden us and we can't plot
33
- // when we don't have the dimensions
34
- if (placeholder.width() == 0 || placeholder.height() == 0)
35
- return;
36
-
37
- plot.resize();
38
- plot.setupGrid();
39
- plot.draw();
40
- }
41
-
42
- function bindEvents(plot, eventHolder) {
43
- plot.getPlaceholder().resize(onResize);
44
- }
45
-
46
- function shutdown(plot, eventHolder) {
47
- plot.getPlaceholder().unbind("resize", onResize);
48
- }
49
-
50
- plot.hooks.bindEvents.push(bindEvents);
51
- plot.hooks.shutdown.push(shutdown);
52
- }
53
-
54
- $.plot.plugins.push({
55
- init: init,
56
- options: options,
57
- name: 'resize',
58
- version: '1.0'
59
- });
60
- })(jQuery);
@@ -1,188 +0,0 @@
1
- /* Flot plugin for stacking data sets rather than overlyaing them.
2
-
3
- Copyright (c) 2007-2013 IOLA and Ole Laursen.
4
- Licensed under the MIT license.
5
-
6
- The plugin assumes the data is sorted on x (or y if stacking horizontally).
7
- For line charts, it is assumed that if a line has an undefined gap (from a
8
- null point), then the line above it should have the same gap - insert zeros
9
- instead of "null" if you want another behaviour. This also holds for the start
10
- and end of the chart. Note that stacking a mix of positive and negative values
11
- in most instances doesn't make sense (so it looks weird).
12
-
13
- Two or more series are stacked when their "stack" attribute is set to the same
14
- key (which can be any number or string or just "true"). To specify the default
15
- stack, you can set the stack option like this:
16
-
17
- series: {
18
- stack: null/false, true, or a key (number/string)
19
- }
20
-
21
- You can also specify it for a single series, like this:
22
-
23
- $.plot( $("#placeholder"), [{
24
- data: [ ... ],
25
- stack: true
26
- }])
27
-
28
- The stacking order is determined by the order of the data series in the array
29
- (later series end up on top of the previous).
30
-
31
- Internally, the plugin modifies the datapoints in each series, adding an
32
- offset to the y value. For line series, extra data points are inserted through
33
- interpolation. If there's a second y value, it's also adjusted (e.g for bar
34
- charts or filled areas).
35
-
36
- */
37
-
38
- (function ($) {
39
- var options = {
40
- series: { stack: null } // or number/string
41
- };
42
-
43
- function init(plot) {
44
- function findMatchingSeries(s, allseries) {
45
- var res = null;
46
- for (var i = 0; i < allseries.length; ++i) {
47
- if (s == allseries[i])
48
- break;
49
-
50
- if (allseries[i].stack == s.stack)
51
- res = allseries[i];
52
- }
53
-
54
- return res;
55
- }
56
-
57
- function stackData(plot, s, datapoints) {
58
- if (s.stack == null || s.stack === false)
59
- return;
60
-
61
- var other = findMatchingSeries(s, plot.getData());
62
- if (!other)
63
- return;
64
-
65
- var ps = datapoints.pointsize,
66
- points = datapoints.points,
67
- otherps = other.datapoints.pointsize,
68
- otherpoints = other.datapoints.points,
69
- newpoints = [],
70
- px, py, intery, qx, qy, bottom,
71
- withlines = s.lines.show,
72
- horizontal = s.bars.horizontal,
73
- withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
74
- withsteps = withlines && s.lines.steps,
75
- fromgap = true,
76
- keyOffset = horizontal ? 1 : 0,
77
- accumulateOffset = horizontal ? 0 : 1,
78
- i = 0, j = 0, l, m;
79
-
80
- while (true) {
81
- if (i >= points.length)
82
- break;
83
-
84
- l = newpoints.length;
85
-
86
- if (points[i] == null) {
87
- // copy gaps
88
- for (m = 0; m < ps; ++m)
89
- newpoints.push(points[i + m]);
90
- i += ps;
91
- }
92
- else if (j >= otherpoints.length) {
93
- // for lines, we can't use the rest of the points
94
- if (!withlines) {
95
- for (m = 0; m < ps; ++m)
96
- newpoints.push(points[i + m]);
97
- }
98
- i += ps;
99
- }
100
- else if (otherpoints[j] == null) {
101
- // oops, got a gap
102
- for (m = 0; m < ps; ++m)
103
- newpoints.push(null);
104
- fromgap = true;
105
- j += otherps;
106
- }
107
- else {
108
- // cases where we actually got two points
109
- px = points[i + keyOffset];
110
- py = points[i + accumulateOffset];
111
- qx = otherpoints[j + keyOffset];
112
- qy = otherpoints[j + accumulateOffset];
113
- bottom = 0;
114
-
115
- if (px == qx) {
116
- for (m = 0; m < ps; ++m)
117
- newpoints.push(points[i + m]);
118
-
119
- newpoints[l + accumulateOffset] += qy;
120
- bottom = qy;
121
-
122
- i += ps;
123
- j += otherps;
124
- }
125
- else if (px > qx) {
126
- // we got past point below, might need to
127
- // insert interpolated extra point
128
- if (withlines && i > 0 && points[i - ps] != null) {
129
- intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
130
- newpoints.push(qx);
131
- newpoints.push(intery + qy);
132
- for (m = 2; m < ps; ++m)
133
- newpoints.push(points[i + m]);
134
- bottom = qy;
135
- }
136
-
137
- j += otherps;
138
- }
139
- else { // px < qx
140
- if (fromgap && withlines) {
141
- // if we come from a gap, we just skip this point
142
- i += ps;
143
- continue;
144
- }
145
-
146
- for (m = 0; m < ps; ++m)
147
- newpoints.push(points[i + m]);
148
-
149
- // we might be able to interpolate a point below,
150
- // this can give us a better y
151
- if (withlines && j > 0 && otherpoints[j - otherps] != null)
152
- bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);
153
-
154
- newpoints[l + accumulateOffset] += bottom;
155
-
156
- i += ps;
157
- }
158
-
159
- fromgap = false;
160
-
161
- if (l != newpoints.length && withbottom)
162
- newpoints[l + 2] += bottom;
163
- }
164
-
165
- // maintain the line steps invariant
166
- if (withsteps && l != newpoints.length && l > 0
167
- && newpoints[l] != null
168
- && newpoints[l] != newpoints[l - ps]
169
- && newpoints[l + 1] != newpoints[l - ps + 1]) {
170
- for (m = 0; m < ps; ++m)
171
- newpoints[l + ps + m] = newpoints[l + m];
172
- newpoints[l + 1] = newpoints[l - ps + 1];
173
- }
174
- }
175
-
176
- datapoints.points = newpoints;
177
- }
178
-
179
- plot.hooks.processDatapoints.push(stackData);
180
- }
181
-
182
- $.plot.plugins.push({
183
- init: init,
184
- options: options,
185
- name: 'stack',
186
- version: '1.2'
187
- });
188
- })(jQuery);
@@ -1,661 +0,0 @@
1
- /*!jQuery Knob*/
2
- /**
3
- * Downward compatible, touchable dial
4
- *
5
- * Version: 1.2.0 (15/07/2012)
6
- * Requires: jQuery v1.7+
7
- *
8
- * Copyright (c) 2012 Anthony Terrien
9
- * Under MIT and GPL licenses:
10
- * http://www.opensource.org/licenses/mit-license.php
11
- * http://www.gnu.org/licenses/gpl.html
12
- *
13
- * Thanks to vor, eskimoblood, spiffistan, FabrizioC
14
- */
15
- (function($) {
16
-
17
- /**
18
- * Kontrol library
19
- */
20
- "use strict";
21
-
22
- /**
23
- * Definition of globals and core
24
- */
25
- var k = {}, // kontrol
26
- max = Math.max,
27
- min = Math.min;
28
-
29
- k.c = {};
30
- k.c.d = $(document);
31
- k.c.t = function (e) {
32
- return e.originalEvent.touches.length - 1;
33
- };
34
-
35
- /**
36
- * Kontrol Object
37
- *
38
- * Definition of an abstract UI control
39
- *
40
- * Each concrete component must call this one.
41
- * <code>
42
- * k.o.call(this);
43
- * </code>
44
- */
45
- k.o = function () {
46
- var s = this;
47
-
48
- this.o = null; // array of options
49
- this.$ = null; // jQuery wrapped element
50
- this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
51
- this.g = null; // 2D graphics context for 'pre-rendering'
52
- this.v = null; // value ; mixed array or integer
53
- this.cv = null; // change value ; not commited value
54
- this.x = 0; // canvas x position
55
- this.y = 0; // canvas y position
56
- this.$c = null; // jQuery canvas element
57
- this.c = null; // rendered canvas context
58
- this.t = 0; // touches index
59
- this.isInit = false;
60
- this.fgColor = null; // main color
61
- this.pColor = null; // previous color
62
- this.dH = null; // draw hook
63
- this.cH = null; // change hook
64
- this.eH = null; // cancel hook
65
- this.rH = null; // release hook
66
-
67
- this.run = function () {
68
- var cf = function (e, conf) {
69
- var k;
70
- for (k in conf) {
71
- s.o[k] = conf[k];
72
- }
73
- s.init();
74
- s._configure()
75
- ._draw();
76
- };
77
-
78
- if(this.$.data('kontroled')) return;
79
- this.$.data('kontroled', true);
80
-
81
- this.extend();
82
- this.o = $.extend(
83
- {
84
- // Config
85
- min : this.$.data('min') || 0,
86
- max : this.$.data('max') || 100,
87
- stopper : true,
88
- readOnly : this.$.data('readonly'),
89
-
90
- // UI
91
- cursor : (this.$.data('cursor') === true && 30)
92
- || this.$.data('cursor')
93
- || 0,
94
- thickness : this.$.data('thickness') || 0.35,
95
- lineCap : this.$.data('linecap') || 'butt',
96
- width : this.$.data('width') || 200,
97
- height : this.$.data('height') || 200,
98
- displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'),
99
- displayPrevious : this.$.data('displayprevious'),
100
- fgColor : this.$.data('fgcolor') || '#87CEEB',
101
- inputColor: this.$.data('inputcolor') || this.$.data('fgcolor') || '#87CEEB',
102
- inline : false,
103
- step : this.$.data('step') || 1,
104
-
105
- // Hooks
106
- draw : null, // function () {}
107
- change : null, // function (value) {}
108
- cancel : null, // function () {}
109
- release : null // function (value) {}
110
- }, this.o
111
- );
112
-
113
- // routing value
114
- if(this.$.is('fieldset')) {
115
-
116
- // fieldset = array of integer
117
- this.v = {};
118
- this.i = this.$.find('input')
119
- this.i.each(function(k) {
120
- var $this = $(this);
121
- s.i[k] = $this;
122
- s.v[k] = $this.val();
123
-
124
- $this.bind(
125
- 'change'
126
- , function () {
127
- var val = {};
128
- val[k] = $this.val();
129
- s.val(val);
130
- }
131
- );
132
- });
133
- this.$.find('legend').remove();
134
-
135
- } else {
136
- // input = integer
137
- this.i = this.$;
138
- this.v = this.$.val();
139
- (this.v == '') && (this.v = this.o.min);
140
-
141
- this.$.bind(
142
- 'change'
143
- , function () {
144
- s.val(s._validate(s.$.val()));
145
- }
146
- );
147
- }
148
-
149
- (!this.o.displayInput) && this.$.hide();
150
-
151
- this.$c = $('<canvas width="' +
152
- this.o.width + 'px" height="' +
153
- this.o.height + 'px"></canvas>');
154
- this.c = this.$c[0].getContext("2d");
155
-
156
- this.$
157
- .wrap($('<div style="' + (this.o.inline ? 'display:inline;' : '') +
158
- 'width:' + this.o.width + 'px;height:' +
159
- this.o.height + 'px;"></div>'))
160
- .before(this.$c);
161
-
162
- if (this.v instanceof Object) {
163
- this.cv = {};
164
- this.copy(this.v, this.cv);
165
- } else {
166
- this.cv = this.v;
167
- }
168
-
169
- this.$
170
- .bind("configure", cf)
171
- .parent()
172
- .bind("configure", cf);
173
-
174
- this._listen()
175
- ._configure()
176
- ._xy()
177
- .init();
178
-
179
- this.isInit = true;
180
-
181
- this._draw();
182
-
183
- return this;
184
- };
185
-
186
- this._draw = function () {
187
-
188
- // canvas pre-rendering
189
- var d = true,
190
- c = document.createElement('canvas');
191
-
192
- c.width = s.o.width;
193
- c.height = s.o.height;
194
- s.g = c.getContext('2d');
195
-
196
- s.clear();
197
-
198
- s.dH
199
- && (d = s.dH());
200
-
201
- (d !== false) && s.draw();
202
-
203
- s.c.drawImage(c, 0, 0);
204
- c = null;
205
- };
206
-
207
- this._touch = function (e) {
208
-
209
- var touchMove = function (e) {
210
-
211
- var v = s.xy2val(
212
- e.originalEvent.touches[s.t].pageX,
213
- e.originalEvent.touches[s.t].pageY
214
- );
215
-
216
- if (v == s.cv) return;
217
-
218
- if (
219
- s.cH
220
- && (s.cH(v) === false)
221
- ) return;
222
-
223
-
224
- s.change(s._validate(v));
225
- s._draw();
226
- };
227
-
228
- // get touches index
229
- this.t = k.c.t(e);
230
-
231
- // First touch
232
- touchMove(e);
233
-
234
- // Touch events listeners
235
- k.c.d
236
- .bind("touchmove.k", touchMove)
237
- .bind(
238
- "touchend.k"
239
- , function () {
240
- k.c.d.unbind('touchmove.k touchend.k');
241
-
242
- if (
243
- s.rH
244
- && (s.rH(s.cv) === false)
245
- ) return;
246
-
247
- s.val(s.cv);
248
- }
249
- );
250
-
251
- return this;
252
- };
253
-
254
- this._mouse = function (e) {
255
-
256
- var mouseMove = function (e) {
257
- var v = s.xy2val(e.pageX, e.pageY);
258
- if (v == s.cv) return;
259
-
260
- if (
261
- s.cH
262
- && (s.cH(v) === false)
263
- ) return;
264
-
265
- s.change(s._validate(v));
266
- s._draw();
267
- };
268
-
269
- // First click
270
- mouseMove(e);
271
-
272
- // Mouse events listeners
273
- k.c.d
274
- .bind("mousemove.k", mouseMove)
275
- .bind(
276
- // Escape key cancel current change
277
- "keyup.k"
278
- , function (e) {
279
- if (e.keyCode === 27) {
280
- k.c.d.unbind("mouseup.k mousemove.k keyup.k");
281
-
282
- if (
283
- s.eH
284
- && (s.eH() === false)
285
- ) return;
286
-
287
- s.cancel();
288
- }
289
- }
290
- )
291
- .bind(
292
- "mouseup.k"
293
- , function (e) {
294
- k.c.d.unbind('mousemove.k mouseup.k keyup.k');
295
-
296
- if (
297
- s.rH
298
- && (s.rH(s.cv) === false)
299
- ) return;
300
-
301
- s.val(s.cv);
302
- }
303
- );
304
-
305
- return this;
306
- };
307
-
308
- this._xy = function () {
309
- var o = this.$c.offset();
310
- this.x = o.left;
311
- this.y = o.top;
312
- return this;
313
- };
314
-
315
- this._listen = function () {
316
-
317
- if (!this.o.readOnly) {
318
- this.$c
319
- .bind(
320
- "mousedown"
321
- , function (e) {
322
- e.preventDefault();
323
- s._xy()._mouse(e);
324
- }
325
- )
326
- .bind(
327
- "touchstart"
328
- , function (e) {
329
- e.preventDefault();
330
- s._xy()._touch(e);
331
- }
332
- );
333
- this.listen();
334
- } else {
335
- this.$.attr('readonly', 'readonly');
336
- }
337
-
338
- return this;
339
- };
340
-
341
- this._configure = function () {
342
-
343
- // Hooks
344
- if (this.o.draw) this.dH = this.o.draw;
345
- if (this.o.change) this.cH = this.o.change;
346
- if (this.o.cancel) this.eH = this.o.cancel;
347
- if (this.o.release) this.rH = this.o.release;
348
-
349
- if (this.o.displayPrevious) {
350
- this.pColor = this.h2rgba(this.o.fgColor, "0.4");
351
- this.fgColor = this.h2rgba(this.o.fgColor, "0.6");
352
- } else {
353
- this.fgColor = this.o.fgColor;
354
- }
355
-
356
- return this;
357
- };
358
-
359
- this._clear = function () {
360
- this.$c[0].width = this.$c[0].width;
361
- };
362
-
363
- this._validate = function(v) {
364
- return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;
365
- };
366
-
367
- // Abstract methods
368
- this.listen = function () {}; // on start, one time
369
- this.extend = function () {}; // each time configure triggered
370
- this.init = function () {}; // each time configure triggered
371
- this.change = function (v) {}; // on change
372
- this.val = function (v) {}; // on release
373
- this.xy2val = function (x, y) {}; //
374
- this.draw = function () {}; // on change / on release
375
- this.clear = function () { this._clear(); };
376
-
377
- // Utils
378
- this.h2rgba = function (h, a) {
379
- var rgb;
380
- h = h.substring(1,7)
381
- rgb = [parseInt(h.substring(0,2),16)
382
- ,parseInt(h.substring(2,4),16)
383
- ,parseInt(h.substring(4,6),16)];
384
- return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")";
385
- };
386
-
387
- this.copy = function (f, t) {
388
- for (var i in f) { t[i] = f[i]; }
389
- };
390
- };
391
-
392
-
393
- /**
394
- * k.Dial
395
- */
396
- k.Dial = function () {
397
- k.o.call(this);
398
-
399
- this.startAngle = null;
400
- this.xy = null;
401
- this.radius = null;
402
- this.lineWidth = null;
403
- this.cursorExt = null;
404
- this.w2 = null;
405
- this.PI2 = 2*Math.PI;
406
-
407
- this.extend = function () {
408
- this.o = $.extend(
409
- {
410
- bgColor : this.$.data('bgcolor') || '#EEEEEE',
411
- angleOffset : this.$.data('angleoffset') || 0,
412
- angleArc : this.$.data('anglearc') || 360,
413
- inline : true
414
- }, this.o
415
- );
416
- };
417
-
418
- this.val = function (v) {
419
- if (null != v) {
420
- this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;
421
- this.v = this.cv;
422
- this.$.val(this.v);
423
- this._draw();
424
- } else {
425
- return this.v;
426
- }
427
- };
428
-
429
- this.xy2val = function (x, y) {
430
- var a, ret;
431
-
432
- a = Math.atan2(
433
- x - (this.x + this.w2)
434
- , - (y - this.y - this.w2)
435
- ) - this.angleOffset;
436
-
437
- if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {
438
- // if isset angleArc option, set to min if .5 under min
439
- a = 0;
440
- } else if (a < 0) {
441
- a += this.PI2;
442
- }
443
-
444
- ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc))
445
- + this.o.min;
446
-
447
- this.o.stopper
448
- && (ret = max(min(ret, this.o.max), this.o.min));
449
-
450
- return ret;
451
- };
452
-
453
- this.listen = function () {
454
- // bind MouseWheel
455
- var s = this,
456
- mw = function (e) {
457
- e.preventDefault();
458
- var ori = e.originalEvent
459
- ,deltaX = ori.detail || ori.wheelDeltaX
460
- ,deltaY = ori.detail || ori.wheelDeltaY
461
- ,v = parseInt(s.$.val()) + (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0);
462
-
463
- if (
464
- s.cH
465
- && (s.cH(v) === false)
466
- ) return;
467
-
468
- s.val(v);
469
- }
470
- , kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step};
471
-
472
- this.$
473
- .bind(
474
- "keydown"
475
- ,function (e) {
476
- var kc = e.keyCode;
477
-
478
- // numpad support
479
- if(kc >= 96 && kc <= 105) {
480
- kc = e.keyCode = kc - 48;
481
- }
482
-
483
- kval = parseInt(String.fromCharCode(kc));
484
-
485
- if (isNaN(kval)) {
486
-
487
- (kc !== 13) // enter
488
- && (kc !== 8) // bs
489
- && (kc !== 9) // tab
490
- && (kc !== 189) // -
491
- && e.preventDefault();
492
-
493
- // arrows
494
- if ($.inArray(kc,[37,38,39,40]) > -1) {
495
- e.preventDefault();
496
-
497
- var v = parseInt(s.$.val()) + kv[kc] * m;
498
-
499
- s.o.stopper
500
- && (v = max(min(v, s.o.max), s.o.min));
501
-
502
- s.change(v);
503
- s._draw();
504
-
505
- // long time keydown speed-up
506
- to = window.setTimeout(
507
- function () { m*=2; }
508
- ,30
509
- );
510
- }
511
- }
512
- }
513
- )
514
- .bind(
515
- "keyup"
516
- ,function (e) {
517
- if (isNaN(kval)) {
518
- if (to) {
519
- window.clearTimeout(to);
520
- to = null;
521
- m = 1;
522
- s.val(s.$.val());
523
- }
524
- } else {
525
- // kval postcond
526
- (s.$.val() > s.o.max && s.$.val(s.o.max))
527
- || (s.$.val() < s.o.min && s.$.val(s.o.min));
528
- }
529
-
530
- }
531
- );
532
-
533
- this.$c.bind("mousewheel DOMMouseScroll", mw);
534
- this.$.bind("mousewheel DOMMouseScroll", mw)
535
- };
536
-
537
- this.init = function () {
538
-
539
- if (
540
- this.v < this.o.min
541
- || this.v > this.o.max
542
- ) this.v = this.o.min;
543
-
544
- this.$.val(this.v);
545
- this.w2 = this.o.width / 2;
546
- this.cursorExt = this.o.cursor / 100;
547
- this.xy = this.w2;
548
- this.lineWidth = this.xy * this.o.thickness;
549
- this.lineCap = this.o.lineCap;
550
- this.radius = this.xy - this.lineWidth / 2;
551
-
552
- this.o.angleOffset
553
- && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);
554
-
555
- this.o.angleArc
556
- && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);
557
-
558
- // deg to rad
559
- this.angleOffset = this.o.angleOffset * Math.PI / 180;
560
- this.angleArc = this.o.angleArc * Math.PI / 180;
561
-
562
- // compute start and end angles
563
- this.startAngle = 1.5 * Math.PI + this.angleOffset;
564
- this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;
565
-
566
- var s = max(
567
- String(Math.abs(this.o.max)).length
568
- , String(Math.abs(this.o.min)).length
569
- , 2
570
- ) + 2;
571
-
572
- this.o.displayInput
573
- && this.i.css({
574
- 'width' : ((this.o.width / 2 + 4) >> 0) + 'px'
575
- ,'height' : ((this.o.width / 3) >> 0) + 'px'
576
- ,'position' : 'absolute'
577
- ,'vertical-align' : 'middle'
578
- ,'margin-top' : ((this.o.width / 3) >> 0) + 'px'
579
- ,'margin-left' : '-' + ((this.o.width * 3 / 4 + 2) >> 0) + 'px'
580
- ,'border' : 0
581
- ,'background' : 'none'
582
- ,'font' : 'bold ' + ((this.o.width / s) >> 0) + 'px Arial'
583
- ,'text-align' : 'center'
584
- ,'color' : this.o.inputColor || this.o.fgColor
585
- ,'padding' : '0px'
586
- ,'-webkit-appearance': 'none'
587
- })
588
- || this.i.css({
589
- 'width' : '0px'
590
- ,'visibility' : 'hidden'
591
- });
592
- };
593
-
594
- this.change = function (v) {
595
- this.cv = v;
596
- this.$.val(v);
597
- };
598
-
599
- this.angle = function (v) {
600
- return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);
601
- };
602
-
603
- this.draw = function () {
604
-
605
- var c = this.g, // context
606
- a = this.angle(this.cv) // Angle
607
- , sat = this.startAngle // Start angle
608
- , eat = sat + a // End angle
609
- , sa, ea // Previous angles
610
- , r = 1;
611
-
612
- c.lineWidth = this.lineWidth;
613
-
614
- c.lineCap = this.lineCap;
615
-
616
- this.o.cursor
617
- && (sat = eat - this.cursorExt)
618
- && (eat = eat + this.cursorExt);
619
-
620
- c.beginPath();
621
- c.strokeStyle = this.o.bgColor;
622
- c.arc(this.xy, this.xy, this.radius, this.endAngle, this.startAngle, true);
623
- c.stroke();
624
-
625
- if (this.o.displayPrevious) {
626
- ea = this.startAngle + this.angle(this.v);
627
- sa = this.startAngle;
628
- this.o.cursor
629
- && (sa = ea - this.cursorExt)
630
- && (ea = ea + this.cursorExt);
631
-
632
- c.beginPath();
633
- c.strokeStyle = this.pColor;
634
- c.arc(this.xy, this.xy, this.radius, sa, ea, false);
635
- c.stroke();
636
- r = (this.cv == this.v);
637
- }
638
-
639
- c.beginPath();
640
- c.strokeStyle = r ? this.o.fgColor : this.fgColor ;
641
- c.arc(this.xy, this.xy, this.radius, sat, eat, false);
642
- c.stroke();
643
- };
644
-
645
- this.cancel = function () {
646
- this.val(this.v);
647
- };
648
- };
649
-
650
- $.fn.dial = $.fn.knob = function (o) {
651
- return this.each(
652
- function () {
653
- var d = new k.Dial();
654
- d.o = o;
655
- d.$ = $(this);
656
- d.run();
657
- }
658
- ).parent();
659
- };
660
-
661
- })(jQuery);