This page demonstrates the very basics of the
jQuery UI Signature plugin.
It contains the minimum requirements for using the plugin and
can be used as the basis for your own experimentation.
PK
—I˜Q}¿=C¿ ¿ css/jquery.signature.css/* Styles for signature plugin v1.2.0. */
.kbw-signature {
display: inline-block;
border: 1px solid #a0a0a0;
-ms-touch-action: none;
}
.kbw-signature-disabled {
opacity: 0.35;
}
PK
—I˜Qq¤\¼9 ¼9 js/jquery.signature.js/*! http://keith-wood.name/signature.html
Signature plugin for jQuery UI v1.2.1.
Requires excanvas.js in IE.
Written by Keith Wood (wood.keith{at}optusnet.com.au) April 2012.
Available under the MIT (http://keith-wood.name/licence.html) license.
Please attribute the author if you use it. */
/* globals G_vmlCanvasManager */
(function($) { // Hide scope, no $ conflict
'use strict';
/** Signature capture and display.
Depends on jquery.ui.widget, jquery.ui.mouse.
Expects HTML like:
<div></div>
@namespace Signature
@augments $.Widget
@example $(selector).signature()
$(selector).signature({color: 'blue', guideline: true}) */
var signatureOverrides = {
/** Be notified when a signature changes.
@callback SignatureChange
@global
@this Signature
@example change: function() {
console.log('Signature changed');
} */
/** Global defaults for signature.
@memberof Signature
@property {number} [distance=0] The minimum distance to start a drag.
@property {string} [background='#fff'] The background colour.
@property {string} [color='#000'] The colour of the signature.
@property {number} [thickness=2] The thickness of the lines.
@property {boolean} [guideline=false] true to add a guideline.
@property {string} [guidelineColor='#a0a0a0'] The guideline colour.
@property {number} [guidelineOffset=50] The guideline offset (pixels) from the bottom.
@property {number} [guidelineIndex=10] The guideline indent (pixels) from the edges.
@property {string} [notAvailable='Your browser doesn\'t support signing']
The error message to show when no canvas is available.
@property {number} [scale=1] A scaling factor for rendering the signature (only applies to redraws).
@property {string|Element|jQuery} [syncField=null] The selector, DOM element, or jQuery object
for a field to automatically synchronise with a text version of the signature.
@property {string} [syncFormat='JSON'] The output representation: 'JSON', 'SVG', 'PNG', 'JPEG'.
@property {boolean} [svgStyles=false] true to use the style attribute in SVG.
@property {SignatureChange} [change=null] A callback triggered when the signature changes.
@example $.extend($.kbw.signature.options, {guideline: true}) */
options: {
distance: 0,
background: '#fff',
color: '#000',
thickness: 2,
guideline: false,
guidelineColor: '#a0a0a0',
guidelineOffset: 50,
guidelineIndent: 10,
notAvailable: 'Your browser doesn\'t support signing',
scale: 1,
syncField: null,
syncFormat: 'JSON',
svgStyles: false,
change: null
},
/** Initialise a new signature area.
@memberof Signature
@private */
_create: function() {
this.element.addClass(this.widgetFullName || this.widgetBaseClass);
try {
this.canvas = $('')[0];
this.element.append(this.canvas);
}
catch (e) {
$(this.canvas).remove();
this.resize = true;
this.canvas = document.createElement('canvas');
this.canvas.setAttribute('width', this.element.width());
this.canvas.setAttribute('height', this.element.height());
this.canvas.innerHTML = this.options.notAvailable;
this.element.append(this.canvas);
/* jshint -W106 */
if (G_vmlCanvasManager) { // Requires excanvas.js
G_vmlCanvasManager.initElement(this.canvas);
}
/* jshint +W106 */
}
this.ctx = this.canvas.getContext('2d');
this._refresh(true);
this._mouseInit();
},
/** Refresh the appearance of the signature area.
@memberof Signature
@private
@param {boolean} init true if initialising. */
_refresh: function(init) {
if (this.resize) {
var parent = $(this.canvas);
$('div', this.canvas).css({width: parent.width(), height: parent.height()});
}
this.ctx.fillStyle = this.options.background;
this.ctx.strokeStyle = this.options.color;
this.ctx.lineWidth = this.options.thickness;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
this.clear(init);
},
/** Clear the signature area.
@memberof Signature
@param {boolean} init true if initialising - internal use only.
@example $(selector).signature('clear') */
clear: function(init) {
if (this.options.disabled) {
return;
}
this.ctx.clearRect(0, 0, this.element.width(), this.element.height());
this.ctx.fillRect(0, 0, this.element.width(), this.element.height());
if (this.options.guideline) {
this.ctx.save();
this.ctx.strokeStyle = this.options.guidelineColor;
this.ctx.lineWidth = 1;
this.ctx.beginPath();
this.ctx.moveTo(this.options.guidelineIndent,
this.element.height() - this.options.guidelineOffset);
this.ctx.lineTo(this.element.width() - this.options.guidelineIndent,
this.element.height() - this.options.guidelineOffset);
this.ctx.stroke();
this.ctx.restore();
}
this.lines = [];
if (!init) {
this._changed();
}
},
/** Synchronise changes and trigger a change event.
@memberof Signature
@private
@param {Event} event The triggering event. */
_changed: function(event) {
if (this.options.syncField) {
var output = '';
switch (this.options.syncFormat) {
case 'PNG':
output = this.toDataURL();
break;
case 'JPEG':
output = this.toDataURL('image/jpeg');
break;
case 'SVG':
output = this.toSVG();
break;
default:
output = this.toJSON();
}
$(this.options.syncField).val(output);
}
this._trigger('change', event, {});
},
/** Refresh the signature when options change.
@memberof Signature
@private
@param {object} options The new option values. */
_setOptions: function(/* options */) {
if (this._superApply) {
this._superApply(arguments); // Base widget handling
}
else {
$.Widget.prototype._setOptions.apply(this, arguments); // Base widget handling
}
var count = 0;
var onlyDisable = true;
for (var name in arguments[0]) {
if (arguments[0].hasOwnProperty(name)) {
count++;
onlyDisable = onlyDisable && name === 'disabled';
}
}
if (count > 1 || !onlyDisable) {
this._refresh();
}
},
/** Determine if dragging can start.
@memberof Signature
@private
@param {Event} event The triggering mouse event.
@return {boolean} true if allowed, false if not */
_mouseCapture: function(/* event */) {
return !this.options.disabled;
},
/** Start a new line.
@memberof Signature
@private
@param {Event} event The triggering mouse event. */
_mouseStart: function(event) {
this.offset = this.element.offset();
this.offset.left -= document.documentElement.scrollLeft || document.body.scrollLeft;
this.offset.top -= document.documentElement.scrollTop || document.body.scrollTop;
this.lastPoint = [this._round(event.clientX - this.offset.left),
this._round(event.clientY - this.offset.top)];
this.curLine = [this.lastPoint];
this.lines.push(this.curLine);
},
/** Track the mouse.
@memberof Signature
@private
@param {Event} event The triggering mouse event. */
_mouseDrag: function(event) {
var point = [this._round(event.clientX - this.offset.left),
this._round(event.clientY - this.offset.top)];
this.curLine.push(point);
this.ctx.beginPath();
this.ctx.moveTo(this.lastPoint[0], this.lastPoint[1]);
this.ctx.lineTo(point[0], point[1]);
this.ctx.stroke();
this.lastPoint = point;
},
/** End a line.
@memberof Signature
@private
@param {Event} event The triggering mouse event. */
_mouseStop: function(event) {
if (this.curLine.length === 1) {
event.clientY += this.options.thickness;
this._mouseDrag(event);
}
this.lastPoint = null;
this.curLine = null;
this._changed(event);
},
/** Round to two decimal points.
@memberof Signature
@private
@param {number} value The value to round.
@return {number} The rounded value. */
_round: function(value) {
return Math.round(value * 100) / 100;
},
/** Convert the captured lines to JSON text.
@memberof Signature
@return {string} The JSON text version of the lines.
@example var json = $(selector).signature('toJSON') */
toJSON: function() {
return '{"lines":[' + $.map(this.lines, function(line) {
return '[' + $.map(line, function(point) {
return '[' + point + ']';
}) + ']';
}) + ']}';
},
/** Convert the captured lines to SVG text.
@memberof Signature
@return {string} The SVG text version of the lines.
@example var svg = $(selector).signature('toSVG') */
toSVG: function() {
var attrs1 = (this.options.svgStyles ? 'style="fill: ' + this.options.background + ';"' :
'fill="' + this.options.background + '"');
var attrs2 = (this.options.svgStyles ?
'style="fill: none; stroke: ' + this.options.color + '; stroke-width: ' + this.options.thickness + ';"' :
'fill="none" stroke="' + this.options.color + '" stroke-width="' + this.options.thickness + '"');
return '\n\n' +
'\n';
},
/** Convert the captured lines to an image encoded in a data: URL.
@memberof Signature
@param {string} [type='image/png'] The MIME type of the image.
@param {number} [quality=0.92] The image quality, between 0 and 1.
@return {string} The signature as a data: URL image.
@example var data = $(selector).signature('toDataURL', 'image/jpeg') */
toDataURL: function(type, quality) {
return this.canvas.toDataURL(type, quality);
},
/** Draw a signature from its JSON or SVG description or data: URL.
Note that drawing a data: URL does not reconstruct the internal representation!
@memberof Signature
@param {object|string} sig An object with attribute lines being an array of arrays of points
or the text version of the JSON or SVG or a data: URL containing an image.
@example $(selector).signature('draw', sigAsJSON) */
draw: function(sig) {
if (this.options.disabled) {
return;
}
this.clear(true);
if (typeof sig === 'string' && sig.indexOf('data:') === 0) { // Data URL
this._drawDataURL(sig, this.options.scale);
} else if (typeof sig === 'string' && sig.indexOf('