john_hancock 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f5a5c2680aba0b53a5f20fdef9c392bab937ff3
4
+ data.tar.gz: 948112f9245c0816c45f55ed38db12f1e81b3632
5
+ SHA512:
6
+ metadata.gz: 07c96186acc9a025e686ec8755c3e0b325fa1fffa7680a4c9bc5e6ee5e7c3b22ed45d79104e5ce8d80272c92ecefb1538eace03bd20692b4b491de19cf6e7d7f
7
+ data.tar.gz: 163fab1062cda7ce48c7dd32cea0eb442dd15809efddaddfeccfea38486079b051a48e1deeacdc20dfce3ed4f6a4656474949851717035e04d2067ee76926dd7
@@ -0,0 +1,15 @@
1
+ //= require signature_pad
2
+ $( document ).ready(function() {
3
+ if(document.getElementById("JohnHancock-canvas")){
4
+ var canvas = document.getElementById("JohnHancock-canvas"),
5
+ hidden_field = document.getElementById("JohnHancock-hidden"),
6
+ parent_form = $(canvas).closest("form"),
7
+ signaturePad;
8
+
9
+ signaturePad = new SignaturePad(canvas);
10
+
11
+ $(parent_form).submit(function(e) {
12
+ $(hidden_field).val(signaturePad.toDataURL());
13
+ });
14
+ }
15
+ })
@@ -0,0 +1,352 @@
1
+ var SignaturePad = (function (document) {
2
+ "use strict";
3
+
4
+ var SignaturePad = function (canvas, options) {
5
+ var self = this,
6
+ opts = options || {};
7
+
8
+ this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
9
+ this.minWidth = opts.minWidth || 0.5;
10
+ this.maxWidth = opts.maxWidth || 2.5;
11
+ this.dotSize = opts.dotSize || function () {
12
+ return (this.minWidth + this.maxWidth) / 2;
13
+ };
14
+ this.penColor = opts.penColor || "black";
15
+ this.backgroundColor = opts.backgroundColor || "rgba(0,0,0,0)";
16
+ this.onEnd = opts.onEnd;
17
+ this.onBegin = opts.onBegin;
18
+
19
+ this._canvas = canvas;
20
+ this._ctx = canvas.getContext("2d");
21
+ this.clear();
22
+
23
+ // we need add these inline so they are available to unbind while still having
24
+ // access to 'self' we could use _.bind but it's not worth adding a dependency
25
+ this._handleMouseDown = function (event) {
26
+ if (event.which === 1) {
27
+ self._mouseButtonDown = true;
28
+ self._strokeBegin(event);
29
+ }
30
+ };
31
+
32
+ this._handleMouseMove = function (event) {
33
+ if (self._mouseButtonDown) {
34
+ self._strokeUpdate(event);
35
+ }
36
+ };
37
+
38
+ this._handleMouseUp = function (event) {
39
+ if (event.which === 1 && self._mouseButtonDown) {
40
+ self._mouseButtonDown = false;
41
+ self._strokeEnd(event);
42
+ }
43
+ };
44
+
45
+ this._handleTouchStart = function (event) {
46
+ if (event.targetTouches.length == 1) {
47
+ var touch = event.changedTouches[0];
48
+ self._strokeBegin(touch);
49
+ }
50
+ };
51
+
52
+ this._handleTouchMove = function (event) {
53
+ // Prevent scrolling.
54
+ event.preventDefault();
55
+
56
+ var touch = event.targetTouches[0];
57
+ self._strokeUpdate(touch);
58
+ };
59
+
60
+ this._handleTouchEnd = function (event) {
61
+ var wasCanvasTouched = event.target === self._canvas;
62
+ if (wasCanvasTouched) {
63
+ event.preventDefault();
64
+ self._strokeEnd(event);
65
+ }
66
+ };
67
+
68
+ this._handleMouseEvents();
69
+ this._handleTouchEvents();
70
+ };
71
+
72
+ SignaturePad.prototype.clear = function () {
73
+ var ctx = this._ctx,
74
+ canvas = this._canvas;
75
+
76
+ ctx.fillStyle = this.backgroundColor;
77
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
78
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
79
+ this._reset();
80
+ };
81
+
82
+ SignaturePad.prototype.toDataURL = function (imageType, quality) {
83
+ var canvas = this._canvas;
84
+ return canvas.toDataURL.apply(canvas, arguments);
85
+ };
86
+
87
+ SignaturePad.prototype.fromDataURL = function (dataUrl) {
88
+ var self = this,
89
+ image = new Image(),
90
+ ratio = window.devicePixelRatio || 1,
91
+ width = this._canvas.width / ratio,
92
+ height = this._canvas.height / ratio;
93
+
94
+ this._reset();
95
+ image.src = dataUrl;
96
+ image.onload = function () {
97
+ self._ctx.drawImage(image, 0, 0, width, height);
98
+ };
99
+ this._isEmpty = false;
100
+ };
101
+
102
+ SignaturePad.prototype._strokeUpdate = function (event) {
103
+ var point = this._createPoint(event);
104
+ this._addPoint(point);
105
+ };
106
+
107
+ SignaturePad.prototype._strokeBegin = function (event) {
108
+ this._reset();
109
+ this._strokeUpdate(event);
110
+ if (typeof this.onBegin === 'function') {
111
+ this.onBegin(event);
112
+ }
113
+ };
114
+
115
+ SignaturePad.prototype._strokeDraw = function (point) {
116
+ var ctx = this._ctx,
117
+ dotSize = typeof(this.dotSize) === 'function' ? this.dotSize() : this.dotSize;
118
+
119
+ ctx.beginPath();
120
+ this._drawPoint(point.x, point.y, dotSize);
121
+ ctx.closePath();
122
+ ctx.fill();
123
+ };
124
+
125
+ SignaturePad.prototype._strokeEnd = function (event) {
126
+ var canDrawCurve = this.points.length > 2,
127
+ point = this.points[0];
128
+
129
+ if (!canDrawCurve && point) {
130
+ this._strokeDraw(point);
131
+ }
132
+ if (typeof this.onEnd === 'function') {
133
+ this.onEnd(event);
134
+ }
135
+ };
136
+
137
+ SignaturePad.prototype._handleMouseEvents = function () {
138
+ this._mouseButtonDown = false;
139
+
140
+ this._canvas.addEventListener("mousedown", this._handleMouseDown);
141
+ this._canvas.addEventListener("mousemove", this._handleMouseMove);
142
+ document.addEventListener("mouseup", this._handleMouseUp);
143
+ };
144
+
145
+ SignaturePad.prototype._handleTouchEvents = function () {
146
+ // Pass touch events to canvas element on mobile IE11 and Edge.
147
+ this._canvas.style.msTouchAction = 'none';
148
+ this._canvas.style.touchAction = 'none';
149
+
150
+ this._canvas.addEventListener("touchstart", this._handleTouchStart);
151
+ this._canvas.addEventListener("touchmove", this._handleTouchMove);
152
+ this._canvas.addEventListener("touchend", this._handleTouchEnd);
153
+ };
154
+
155
+ SignaturePad.prototype.on = function () {
156
+ this._handleMouseEvents();
157
+ this._handleTouchEvents();
158
+ };
159
+
160
+ SignaturePad.prototype.off = function () {
161
+ this._canvas.removeEventListener("mousedown", this._handleMouseDown);
162
+ this._canvas.removeEventListener("mousemove", this._handleMouseMove);
163
+ document.removeEventListener("mouseup", this._handleMouseUp);
164
+
165
+ this._canvas.removeEventListener("touchstart", this._handleTouchStart);
166
+ this._canvas.removeEventListener("touchmove", this._handleTouchMove);
167
+ this._canvas.removeEventListener("touchend", this._handleTouchEnd);
168
+ };
169
+
170
+ SignaturePad.prototype.isEmpty = function () {
171
+ return this._isEmpty;
172
+ };
173
+
174
+ SignaturePad.prototype._reset = function () {
175
+ this.points = [];
176
+ this._lastVelocity = 0;
177
+ this._lastWidth = (this.minWidth + this.maxWidth) / 2;
178
+ this._isEmpty = true;
179
+ this._ctx.fillStyle = this.penColor;
180
+ };
181
+
182
+ SignaturePad.prototype._createPoint = function (event) {
183
+ var rect = this._canvas.getBoundingClientRect();
184
+ return new Point(
185
+ event.clientX - rect.left,
186
+ event.clientY - rect.top
187
+ );
188
+ };
189
+
190
+ SignaturePad.prototype._addPoint = function (point) {
191
+ var points = this.points,
192
+ c2, c3,
193
+ curve, tmp;
194
+
195
+ points.push(point);
196
+
197
+ if (points.length > 2) {
198
+ // To reduce the initial lag make it work with 3 points
199
+ // by copying the first point to the beginning.
200
+ if (points.length === 3) points.unshift(points[0]);
201
+
202
+ tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
203
+ c2 = tmp.c2;
204
+ tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
205
+ c3 = tmp.c1;
206
+ curve = new Bezier(points[1], c2, c3, points[2]);
207
+ this._addCurve(curve);
208
+
209
+ // Remove the first element from the list,
210
+ // so that we always have no more than 4 points in points array.
211
+ points.shift();
212
+ }
213
+ };
214
+
215
+ SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
216
+ var dx1 = s1.x - s2.x, dy1 = s1.y - s2.y,
217
+ dx2 = s2.x - s3.x, dy2 = s2.y - s3.y,
218
+
219
+ m1 = {x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0},
220
+ m2 = {x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0},
221
+
222
+ l1 = Math.sqrt(dx1*dx1 + dy1*dy1),
223
+ l2 = Math.sqrt(dx2*dx2 + dy2*dy2),
224
+
225
+ dxm = (m1.x - m2.x),
226
+ dym = (m1.y - m2.y),
227
+
228
+ k = l2 / (l1 + l2),
229
+ cm = {x: m2.x + dxm*k, y: m2.y + dym*k},
230
+
231
+ tx = s2.x - cm.x,
232
+ ty = s2.y - cm.y;
233
+
234
+ return {
235
+ c1: new Point(m1.x + tx, m1.y + ty),
236
+ c2: new Point(m2.x + tx, m2.y + ty)
237
+ };
238
+ };
239
+
240
+ SignaturePad.prototype._addCurve = function (curve) {
241
+ var startPoint = curve.startPoint,
242
+ endPoint = curve.endPoint,
243
+ velocity, newWidth;
244
+
245
+ velocity = endPoint.velocityFrom(startPoint);
246
+ velocity = this.velocityFilterWeight * velocity
247
+ + (1 - this.velocityFilterWeight) * this._lastVelocity;
248
+
249
+ newWidth = this._strokeWidth(velocity);
250
+ this._drawCurve(curve, this._lastWidth, newWidth);
251
+
252
+ this._lastVelocity = velocity;
253
+ this._lastWidth = newWidth;
254
+ };
255
+
256
+ SignaturePad.prototype._drawPoint = function (x, y, size) {
257
+ var ctx = this._ctx;
258
+
259
+ ctx.moveTo(x, y);
260
+ ctx.arc(x, y, size, 0, 2 * Math.PI, false);
261
+ this._isEmpty = false;
262
+ };
263
+
264
+ SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
265
+ var ctx = this._ctx,
266
+ widthDelta = endWidth - startWidth,
267
+ drawSteps, width, i, t, tt, ttt, u, uu, uuu, x, y;
268
+
269
+ drawSteps = Math.floor(curve.length());
270
+ ctx.beginPath();
271
+ for (i = 0; i < drawSteps; i++) {
272
+ // Calculate the Bezier (x, y) coordinate for this step.
273
+ t = i / drawSteps;
274
+ tt = t * t;
275
+ ttt = tt * t;
276
+ u = 1 - t;
277
+ uu = u * u;
278
+ uuu = uu * u;
279
+
280
+ x = uuu * curve.startPoint.x;
281
+ x += 3 * uu * t * curve.control1.x;
282
+ x += 3 * u * tt * curve.control2.x;
283
+ x += ttt * curve.endPoint.x;
284
+
285
+ y = uuu * curve.startPoint.y;
286
+ y += 3 * uu * t * curve.control1.y;
287
+ y += 3 * u * tt * curve.control2.y;
288
+ y += ttt * curve.endPoint.y;
289
+
290
+ width = startWidth + ttt * widthDelta;
291
+ this._drawPoint(x, y, width);
292
+ }
293
+ ctx.closePath();
294
+ ctx.fill();
295
+ };
296
+
297
+ SignaturePad.prototype._strokeWidth = function (velocity) {
298
+ return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
299
+ };
300
+
301
+
302
+ var Point = function (x, y, time) {
303
+ this.x = x;
304
+ this.y = y;
305
+ this.time = time || new Date().getTime();
306
+ };
307
+
308
+ Point.prototype.velocityFrom = function (start) {
309
+ return (this.time !== start.time) ? this.distanceTo(start) / (this.time - start.time) : 1;
310
+ };
311
+
312
+ Point.prototype.distanceTo = function (start) {
313
+ return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
314
+ };
315
+
316
+ var Bezier = function (startPoint, control1, control2, endPoint) {
317
+ this.startPoint = startPoint;
318
+ this.control1 = control1;
319
+ this.control2 = control2;
320
+ this.endPoint = endPoint;
321
+ };
322
+
323
+ // Returns approximated length.
324
+ Bezier.prototype.length = function () {
325
+ var steps = 10,
326
+ length = 0,
327
+ i, t, cx, cy, px, py, xdiff, ydiff;
328
+
329
+ for (i = 0; i <= steps; i++) {
330
+ t = i / steps;
331
+ cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
332
+ cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
333
+ if (i > 0) {
334
+ xdiff = cx - px;
335
+ ydiff = cy - py;
336
+ length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
337
+ }
338
+ px = cx;
339
+ py = cy;
340
+ }
341
+ return length;
342
+ };
343
+
344
+ Bezier.prototype._point = function (t, start, c1, c2, end) {
345
+ return start * (1.0 - t) * (1.0 - t) * (1.0 - t)
346
+ + 3.0 * c1 * (1.0 - t) * (1.0 - t) * t
347
+ + 3.0 * c2 * (1.0 - t) * t * t
348
+ + end * t * t * t;
349
+ };
350
+
351
+ return SignaturePad;
352
+ })(document);
@@ -0,0 +1,10 @@
1
+ module JohnHancock
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ require 'jquery-rails'
5
+ initializer 'john_hancock.form_helpers' do |_app|
6
+ ActiveSupport.on_load(:action_view) { require 'john_hancock/rails/form_helper' }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ module JohnHancock
2
+ module Rails
3
+ module FormBuilder
4
+ include ActionView::Helpers::TagHelper
5
+
6
+ def signature_canvas
7
+ content_tag(:canvas, nil, id: 'JohnHancock-canvas')
8
+ end
9
+
10
+ def hidden_signature_field(attribute)
11
+ hidden_field(attribute.to_sym, id: 'JohnHancock-hidden')
12
+ end
13
+
14
+ def signature_field(attribute)
15
+ tags = []
16
+ tags << signature_canvas
17
+ tags << hidden_signature_field(attribute)
18
+ tags.join(' ').html_safe
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ JohnHancock::FormBuilder = JohnHancock::Rails::FormBuilder
@@ -0,0 +1,16 @@
1
+ require 'action_view/helpers'
2
+ require 'john_hancock/rails/form_builder'
3
+
4
+ module JohnHancock
5
+ module Rails
6
+ module FormHelper
7
+ def self.included(_base)
8
+ ActionView::Helpers::FormBuilder.instance_eval do
9
+ include FormBuilder
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActionView::Base.send :include, JohnHancock::Rails::FormHelper
@@ -0,0 +1,9 @@
1
+ require 'rails'
2
+ require 'rails/engine'
3
+ require 'john_hancock/rails/engine'
4
+ # begin; require 'sassc-rails'; rescue LoadError; end # rubocop:disable Lint/HandleExceptions
5
+
6
+ module JohnHancock
7
+ module Rails
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module JohnHancock
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'john_hancock/rails' if defined?(Rails)
2
+
3
+ module JohnHancock
4
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: john_hancock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Lawrence
8
+ - Ben Miller
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2016-07-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sqlite3
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: jquery-rails
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: test-unit
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: capybara
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: poltergeist
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: launchy
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: bundler
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '1.12'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '1.12'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '10.0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '10.0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: minitest
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: '5.0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: '5.0'
154
+ description: This Gem gives you access to a signature pad form helper so you can save
155
+ touchpad signatures as encoded png data
156
+ email:
157
+ - bvbrandonbv@gmail.com
158
+ - bjmllr@gmail.com
159
+ executables: []
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - app/assets/javascript/john_hancock.js
164
+ - app/assets/javascript/signature_pad.js
165
+ - lib/john_hancock.rb
166
+ - lib/john_hancock/rails.rb
167
+ - lib/john_hancock/rails/engine.rb
168
+ - lib/john_hancock/rails/form_builder.rb
169
+ - lib/john_hancock/rails/form_helper.rb
170
+ - lib/john_hancock/version.rb
171
+ homepage: https://github.com/Brantron/john_hancock
172
+ licenses:
173
+ - MIT
174
+ metadata: {}
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ requirements: []
190
+ rubyforge_project:
191
+ rubygems_version: 2.5.1
192
+ signing_key:
193
+ specification_version: 4
194
+ summary: The best Signature Pad gem you will ever find!
195
+ test_files: []