From 62502bc775415320d3e9baba71c6c9d4eed134af Mon Sep 17 00:00:00 2001 From: "Serpent Consulting Services Pvt. Ltd" Date: Fri, 20 Feb 2015 13:09:41 +0530 Subject: [PATCH] [Add] Digital Signature Module --- web_digital_sign/__init__.py | 23 + web_digital_sign/__openerp__.py | 49 + web_digital_sign/static/lib/excanvas.js | 924 +++++++++++++ .../static/lib/jquery.signature.js | 244 ++++ web_digital_sign/static/src/css/digital.css | 10 + web_digital_sign/static/src/css/jquery-ui.css | 1225 +++++++++++++++++ .../static/src/css/jquery.signature.css | 5 + web_digital_sign/static/src/img/icon.png | Bin 0 -> 16349 bytes .../static/src/js/digital_sign.js | 132 ++ .../static/src/xml/digital_sign.xml | 18 + 10 files changed, 2630 insertions(+) create mode 100644 web_digital_sign/__init__.py create mode 100644 web_digital_sign/__openerp__.py create mode 100644 web_digital_sign/static/lib/excanvas.js create mode 100644 web_digital_sign/static/lib/jquery.signature.js create mode 100644 web_digital_sign/static/src/css/digital.css create mode 100644 web_digital_sign/static/src/css/jquery-ui.css create mode 100644 web_digital_sign/static/src/css/jquery.signature.css create mode 100644 web_digital_sign/static/src/img/icon.png create mode 100644 web_digital_sign/static/src/js/digital_sign.js create mode 100644 web_digital_sign/static/src/xml/digital_sign.xml diff --git a/web_digital_sign/__init__.py b/web_digital_sign/__init__.py new file mode 100644 index 00000000..433663e6 --- /dev/null +++ b/web_digital_sign/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 OpenERP SA () +# Copyright (C) 2011-2015 Serpent Consulting Services Pvt. Ltd. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/web_digital_sign/__openerp__.py b/web_digital_sign/__openerp__.py new file mode 100644 index 00000000..22a09d85 --- /dev/null +++ b/web_digital_sign/__openerp__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 OpenERP SA () +# Copyright (C) 2011-2015 Serpent Consulting Services Pvt. Ltd. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + "name" : "Web Digital Signature", + "version" : "1.0", + "author" : "Serpent Consulting Services Pvt. Ltd.", + "category": '', + 'complexity': "easy", + 'depends': ['web'], + "description": """ + This module provides the functionality to store digital signature image for a record. + """, + 'data': [], + 'js':[ + "static/lib/excanvas.js", + "static/lib/jquery.signature.js", + "static/src/js/digital_sign.js", + ], + 'css':[ + "static/src/css/digital.css", + "static/src/css/jquery.signature.css", + ], + 'website': 'http://www.serpentcs.com', + 'qweb': ['static/src/xml/digital_sign.xml'], + 'installable': True, + 'auto_install': False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/web_digital_sign/static/lib/excanvas.js b/web_digital_sign/static/lib/excanvas.js new file mode 100644 index 00000000..367764b4 --- /dev/null +++ b/web_digital_sign/static/lib/excanvas.js @@ -0,0 +1,924 @@ +// Copyright 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Known Issues: +// +// * Patterns are not implemented. +// * Radial gradient are not implemented. The VML version of these look very +// different from the canvas one. +// * Clipping paths are not implemented. +// * Coordsize. The width and height attribute have higher priority than the +// width and height style values which isn't correct. +// * Painting mode isn't implemented. +// * Canvas width/height should is using content-box by default. IE in +// Quirks mode will draw the canvas using border-box. Either change your +// doctype to HTML5 +// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) +// or use Box Sizing Behavior from WebFX +// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) +// * Non uniform scaling does not correctly scale strokes. +// * Optimize. There is always room for speed improvements. + +// Only add this code if we do not already have a canvas implementation +if (!document.createElement('canvas').getContext) { + +(function() { + + // alias some functions to make (compiled) code shorter + var m = Math; + var mr = m.round; + var ms = m.sin; + var mc = m.cos; + var abs = m.abs; + var sqrt = m.sqrt; + + // this is used for sub pixel precision + var Z = 10; + var Z2 = Z / 2; + + /** + * This funtion is assigned to the elements as element.getContext(). + * @this {HTMLElement} + * @return {CanvasRenderingContext2D_} + */ + function getContext() { + return this.context_ || + (this.context_ = new CanvasRenderingContext2D_(this)); + } + + var slice = Array.prototype.slice; + + /** + * Binds a function to an object. The returned function will always use the + * passed in {@code obj} as {@code this}. + * + * Example: + * + * g = bind(f, obj, a, b) + * g(c, d) // will do f.call(obj, a, b, c, d) + * + * @param {Function} f The function to bind the object to + * @param {Object} obj The object that should act as this when the function + * is called + * @param {*} var_args Rest arguments that will be used as the initial + * arguments when the function is called + * @return {Function} A new function that has bound this + */ + function bind(f, obj, var_args) { + var a = slice.call(arguments, 2); + return function() { + return f.apply(obj, a.concat(slice.call(arguments))); + }; + } + + var G_vmlCanvasManager_ = { + init: function(opt_doc) { + if (/MSIE/.test(navigator.userAgent) && !window.opera) { + var doc = opt_doc || document; + // Create a dummy element so that IE will allow canvas elements to be + // recognized. + doc.createElement('canvas'); + doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); + } + }, + + init_: function(doc) { + // create xmlns + if (!doc.namespaces['g_vml_']) { + doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml', + '#default#VML'); + + } + if (!doc.namespaces['g_o_']) { + doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office', + '#default#VML'); + } + + // Setup default CSS. Only add one style sheet per document + if (!doc.styleSheets['ex_canvas_']) { + var ss = doc.createStyleSheet(); + ss.owningElement.id = 'ex_canvas_'; + ss.cssText = 'canvas{display:inline-block;overflow:hidden;' + + // default size is 300x150 in Gecko and Opera + 'text-align:left;width:300px;height:150px}' + + 'g_vml_\\:*{behavior:url(#default#VML)}' + + 'g_o_\\:*{behavior:url(#default#VML)}'; + + } + + // find all canvas elements + var els = doc.getElementsByTagName('canvas'); + for (var i = 0; i < els.length; i++) { + this.initElement(els[i]); + } + }, + + /** + * Public initializes a canvas element so that it can be used as canvas + * element from now on. This is called automatically before the page is + * loaded but if you are creating elements using createElement you need to + * make sure this is called on the element. + * @param {HTMLElement} el The canvas element to initialize. + * @return {HTMLElement} the element that was created. + */ + initElement: function(el) { + if (!el.getContext) { + + el.getContext = getContext; + + // Remove fallback content. There is no way to hide text nodes so we + // just remove all childNodes. We could hide all elements and remove + // text nodes but who really cares about the fallback content. + el.innerHTML = ''; + + // do not use inline function because that will leak memory + el.attachEvent('onpropertychange', onPropertyChange); + el.attachEvent('onresize', onResize); + + var attrs = el.attributes; + if (attrs.width && attrs.width.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setWidth_(attrs.width.nodeValue); + el.style.width = attrs.width.nodeValue + 'px'; + } else { + el.width = el.clientWidth; + } + if (attrs.height && attrs.height.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setHeight_(attrs.height.nodeValue); + el.style.height = attrs.height.nodeValue + 'px'; + } else { + el.height = el.clientHeight; + } + //el.getContext().setCoordsize_() + } + return el; + } + }; + + function onPropertyChange(e) { + var el = e.srcElement; + + switch (e.propertyName) { + case 'width': + el.style.width = el.attributes.width.nodeValue + 'px'; + el.getContext().clearRect(); + break; + case 'height': + el.style.height = el.attributes.height.nodeValue + 'px'; + el.getContext().clearRect(); + break; + } + } + + function onResize(e) { + var el = e.srcElement; + if (el.firstChild) { + el.firstChild.style.width = el.clientWidth + 'px'; + el.firstChild.style.height = el.clientHeight + 'px'; + } + } + + G_vmlCanvasManager_.init(); + + // precompute "00" to "FF" + var dec2hex = []; + for (var i = 0; i < 16; i++) { + for (var j = 0; j < 16; j++) { + dec2hex[i * 16 + j] = i.toString(16) + j.toString(16); + } + } + + function createMatrixIdentity() { + return [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1] + ]; + } + + function matrixMultiply(m1, m2) { + var result = createMatrixIdentity(); + + for (var x = 0; x < 3; x++) { + for (var y = 0; y < 3; y++) { + var sum = 0; + + for (var z = 0; z < 3; z++) { + sum += m1[x][z] * m2[z][y]; + } + + result[x][y] = sum; + } + } + return result; + } + + function copyState(o1, o2) { + o2.fillStyle = o1.fillStyle; + o2.lineCap = o1.lineCap; + o2.lineJoin = o1.lineJoin; + o2.lineWidth = o1.lineWidth; + o2.miterLimit = o1.miterLimit; + o2.shadowBlur = o1.shadowBlur; + o2.shadowColor = o1.shadowColor; + o2.shadowOffsetX = o1.shadowOffsetX; + o2.shadowOffsetY = o1.shadowOffsetY; + o2.strokeStyle = o1.strokeStyle; + o2.globalAlpha = o1.globalAlpha; + o2.arcScaleX_ = o1.arcScaleX_; + o2.arcScaleY_ = o1.arcScaleY_; + o2.lineScale_ = o1.lineScale_; + } + + function processStyle(styleString) { + var str, alpha = 1; + + styleString = String(styleString); + if (styleString.substring(0, 3) == 'rgb') { + var start = styleString.indexOf('(', 3); + var end = styleString.indexOf(')', start + 1); + var guts = styleString.substring(start + 1, end).split(','); + + str = '#'; + for (var i = 0; i < 3; i++) { + str += dec2hex[Number(guts[i])]; + } + + if (guts.length == 4 && styleString.substr(3, 1) == 'a') { + alpha = guts[3]; + } + } else { + str = styleString; + } + + return {color: str, alpha: alpha}; + } + + function processLineCap(lineCap) { + switch (lineCap) { + case 'butt': + return 'flat'; + case 'round': + return 'round'; + case 'square': + default: + return 'square'; + } + } + + /** + * This class implements CanvasRenderingContext2D interface as described by + * the WHATWG. + * @param {HTMLElement} surfaceElement The element that the 2D context should + * be associated with + */ + function CanvasRenderingContext2D_(surfaceElement) { + this.m_ = createMatrixIdentity(); + + this.mStack_ = []; + this.aStack_ = []; + this.currentPath_ = []; + + // Canvas context properties + this.strokeStyle = '#000'; + this.fillStyle = '#000'; + + this.lineWidth = 1; + this.lineJoin = 'miter'; + this.lineCap = 'butt'; + this.miterLimit = Z * 1; + this.globalAlpha = 1; + this.canvas = surfaceElement; + + var el = surfaceElement.ownerDocument.createElement('div'); + el.style.width = surfaceElement.clientWidth + 'px'; + el.style.height = surfaceElement.clientHeight + 'px'; + el.style.overflow = 'hidden'; + el.style.position = 'absolute'; + surfaceElement.appendChild(el); + + this.element_ = el; + this.arcScaleX_ = 1; + this.arcScaleY_ = 1; + this.lineScale_ = 1; + } + + var contextPrototype = CanvasRenderingContext2D_.prototype; + contextPrototype.clearRect = function() { + this.element_.innerHTML = ''; + }; + + contextPrototype.beginPath = function() { + // TODO: Branch current matrix so that save/restore has no effect + // as per safari docs. + this.currentPath_ = []; + }; + + contextPrototype.moveTo = function(aX, aY) { + var p = this.getCoords_(aX, aY); + this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.lineTo = function(aX, aY) { + var p = this.getCoords_(aX, aY); + this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); + + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, + aCP2x, aCP2y, + aX, aY) { + var p = this.getCoords_(aX, aY); + var cp1 = this.getCoords_(aCP1x, aCP1y); + var cp2 = this.getCoords_(aCP2x, aCP2y); + bezierCurveTo(this, cp1, cp2, p); + }; + + // Helper function that takes the already fixed cordinates. + function bezierCurveTo(self, cp1, cp2, p) { + self.currentPath_.push({ + type: 'bezierCurveTo', + cp1x: cp1.x, + cp1y: cp1.y, + cp2x: cp2.x, + cp2y: cp2.y, + x: p.x, + y: p.y + }); + self.currentX_ = p.x; + self.currentY_ = p.y; + } + + contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { + // the following is lifted almost directly from + // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes + + var cp = this.getCoords_(aCPx, aCPy); + var p = this.getCoords_(aX, aY); + + var cp1 = { + x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), + y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_) + }; + var cp2 = { + x: cp1.x + (p.x - this.currentX_) / 3.0, + y: cp1.y + (p.y - this.currentY_) / 3.0 + }; + + bezierCurveTo(this, cp1, cp2, p); + }; + + contextPrototype.arc = function(aX, aY, aRadius, + aStartAngle, aEndAngle, aClockwise) { + aRadius *= Z; + var arcType = aClockwise ? 'at' : 'wa'; + + var xStart = aX + mc(aStartAngle) * aRadius - Z2; + var yStart = aY + ms(aStartAngle) * aRadius - Z2; + + var xEnd = aX + mc(aEndAngle) * aRadius - Z2; + var yEnd = aY + ms(aEndAngle) * aRadius - Z2; + + // IE won't render arches drawn counter clockwise if xStart == xEnd. + if (xStart == xEnd && !aClockwise) { + xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something + // that can be represented in binary + } + + var p = this.getCoords_(aX, aY); + var pStart = this.getCoords_(xStart, yStart); + var pEnd = this.getCoords_(xEnd, yEnd); + + this.currentPath_.push({type: arcType, + x: p.x, + y: p.y, + radius: aRadius, + xStart: pStart.x, + yStart: pStart.y, + xEnd: pEnd.x, + yEnd: pEnd.y}); + + }; + + contextPrototype.rect = function(aX, aY, aWidth, aHeight) { + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + }; + + contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.stroke(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.fill(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { + var gradient = new CanvasGradient_('gradient'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + return gradient; + }; + + contextPrototype.createRadialGradient = function(aX0, aY0, aR0, + aX1, aY1, aR1) { + var gradient = new CanvasGradient_('gradientradial'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.r0_ = aR0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + gradient.r1_ = aR1; + return gradient; + }; + + contextPrototype.drawImage = function(image, var_args) { + var dx, dy, dw, dh, sx, sy, sw, sh; + + // to find the original width we overide the width and height + var oldRuntimeWidth = image.runtimeStyle.width; + var oldRuntimeHeight = image.runtimeStyle.height; + image.runtimeStyle.width = 'auto'; + image.runtimeStyle.height = 'auto'; + + // get the original size + var w = image.width; + var h = image.height; + + // and remove overides + image.runtimeStyle.width = oldRuntimeWidth; + image.runtimeStyle.height = oldRuntimeHeight; + + if (arguments.length == 3) { + dx = arguments[1]; + dy = arguments[2]; + sx = sy = 0; + sw = dw = w; + sh = dh = h; + } else if (arguments.length == 5) { + dx = arguments[1]; + dy = arguments[2]; + dw = arguments[3]; + dh = arguments[4]; + sx = sy = 0; + sw = w; + sh = h; + } else if (arguments.length == 9) { + sx = arguments[1]; + sy = arguments[2]; + sw = arguments[3]; + sh = arguments[4]; + dx = arguments[5]; + dy = arguments[6]; + dw = arguments[7]; + dh = arguments[8]; + } else { + throw Error('Invalid number of arguments'); + } + + var d = this.getCoords_(dx, dy); + + var w2 = sw / 2; + var h2 = sh / 2; + + var vmlStr = []; + + var W = 10; + var H = 10; + + // For some reason that I've now forgotten, using divs didn't work + vmlStr.push(' ' , + '', + ''); + + this.element_.insertAdjacentHTML('BeforeEnd', + vmlStr.join('')); + }; + + contextPrototype.stroke = function(aFill) { + var lineStr = []; + var lineOpen = false; + var a = processStyle(aFill ? this.fillStyle : this.strokeStyle); + var color = a.color; + var opacity = a.alpha * this.globalAlpha; + + var W = 10; + var H = 10; + + lineStr.push(''); + + if (!aFill) { + var lineWidth = this.lineScale_ * this.lineWidth; + + // VML cannot correctly render a line if the width is less than 1px. + // In that case, we dilute the color to make the line look thinner. + if (lineWidth < 1) { + opacity *= lineWidth; + } + + lineStr.push( + '' + ); + } else if (typeof this.fillStyle == 'object') { + var fillStyle = this.fillStyle; + var angle = 0; + var focus = {x: 0, y: 0}; + + // additional offset + var shift = 0; + // scale factor for offset + var expansion = 1; + + if (fillStyle.type_ == 'gradient') { + var x0 = fillStyle.x0_ / this.arcScaleX_; + var y0 = fillStyle.y0_ / this.arcScaleY_; + var x1 = fillStyle.x1_ / this.arcScaleX_; + var y1 = fillStyle.y1_ / this.arcScaleY_; + var p0 = this.getCoords_(x0, y0); + var p1 = this.getCoords_(x1, y1); + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + angle = Math.atan2(dx, dy) * 180 / Math.PI; + + // The angle should be a non-negative number. + if (angle < 0) { + angle += 360; + } + + // Very small angles produce an unexpected result because they are + // converted to a scientific notation string. + if (angle < 1e-6) { + angle = 0; + } + } else { + var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_); + var width = max.x - min.x; + var height = max.y - min.y; + focus = { + x: (p0.x - min.x) / width, + y: (p0.y - min.y) / height + }; + + width /= this.arcScaleX_ * Z; + height /= this.arcScaleY_ * Z; + var dimension = m.max(width, height); + shift = 2 * fillStyle.r0_ / dimension; + expansion = 2 * fillStyle.r1_ / dimension - shift; + } + + // We need to sort the color stops in ascending order by offset, + // otherwise IE won't interpret it correctly. + var stops = fillStyle.colors_; + stops.sort(function(cs1, cs2) { + return cs1.offset - cs2.offset; + }); + + var length = stops.length; + var color1 = stops[0].color; + var color2 = stops[length - 1].color; + var opacity1 = stops[0].alpha * this.globalAlpha; + var opacity2 = stops[length - 1].alpha * this.globalAlpha; + + var colors = []; + for (var i = 0; i < length; i++) { + var stop = stops[i]; + colors.push(stop.offset * expansion + shift + ' ' + stop.color); + } + + // When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + lineStr.push(''); + } else { + lineStr.push(''); + } + + lineStr.push(''); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + contextPrototype.fill = function() { + this.stroke(true); + } + + contextPrototype.closePath = function() { + this.currentPath_.push({type: 'close'}); + }; + + /** + * @private + */ + contextPrototype.getCoords_ = function(aX, aY) { + var m = this.m_; + return { + x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, + y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 + } + }; + + contextPrototype.save = function() { + var o = {}; + copyState(this, o); + this.aStack_.push(o); + this.mStack_.push(this.m_); + this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); + }; + + contextPrototype.restore = function() { + copyState(this.aStack_.pop(), this); + this.m_ = this.mStack_.pop(); + }; + + function matrixIsFinite(m) { + for (var j = 0; j < 3; j++) { + for (var k = 0; k < 2; k++) { + if (!isFinite(m[j][k]) || isNaN(m[j][k])) { + return false; + } + } + } + return true; + } + + function setM(ctx, m, updateLineScale) { + if (!matrixIsFinite(m)) { + return; + } + ctx.m_ = m; + + if (updateLineScale) { + // Get the line scale. + // Determinant of this.m_ means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + var det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; + ctx.lineScale_ = sqrt(abs(det)); + } + } + + contextPrototype.translate = function(aX, aY) { + var m1 = [ + [1, 0, 0], + [0, 1, 0], + [aX, aY, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.rotate = function(aRot) { + var c = mc(aRot); + var s = ms(aRot); + + var m1 = [ + [c, s, 0], + [-s, c, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.scale = function(aX, aY) { + this.arcScaleX_ *= aX; + this.arcScaleY_ *= aY; + var m1 = [ + [aX, 0, 0], + [0, aY, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) { + var m1 = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) { + var m = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, m, true); + }; + + /******** STUBS ********/ + contextPrototype.clip = function() { + // TODO: Implement + }; + + contextPrototype.arcTo = function() { + // TODO: Implement + }; + + contextPrototype.createPattern = function() { + return new CanvasPattern_; + }; + + // Gradient / Pattern Stubs + function CanvasGradient_(aType) { + this.type_ = aType; + this.x0_ = 0; + this.y0_ = 0; + this.r0_ = 0; + this.x1_ = 0; + this.y1_ = 0; + this.r1_ = 0; + this.colors_ = []; + } + + CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { + aColor = processStyle(aColor); + this.colors_.push({offset: aOffset, + color: aColor.color, + alpha: aColor.alpha}); + }; + + function CanvasPattern_() {} + + // set up externs + G_vmlCanvasManager = G_vmlCanvasManager_; + CanvasRenderingContext2D = CanvasRenderingContext2D_; + CanvasGradient = CanvasGradient_; + CanvasPattern = CanvasPattern_; + +})(); + +} // if diff --git a/web_digital_sign/static/lib/jquery.signature.js b/web_digital_sign/static/lib/jquery.signature.js new file mode 100644 index 00000000..14731c7d --- /dev/null +++ b/web_digital_sign/static/lib/jquery.signature.js @@ -0,0 +1,244 @@ + +(function($) { // Hide scope, no $ conflict + +var signatureOverrides = { + + // Global defaults for signature + options: { + background: '#ffffff', // Colour of the background + color: '#000000', // Colour of the signature + thickness: 2, // Thickness of the lines + guideline: false, // Add a guide line or not? + guidelineColor: '#a0a0a0', // Guide line colour + guidelineOffset: 50, // Guide line offset from the bottom + guidelineIndent: 10, // Guide line indent from the edges + notAvailable: 'Your browser doesn\'t support signing', // Error message when no canvas + syncField: null, // Selector for synchronised text field + change: null // Callback when signature changed + }, + + /* Initialise a new signature area. */ + _create: function() { + + + this.element.addClass(this.widgetFullName || this.widgetBaseClass); + try { + this.canvas = $('' + '' + '')[0]; + this.element.prepend(this.canvas); + this.element.find('img').remove(); + this.ctx = this.canvas.getContext('2d'); + } + 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); + if (G_vmlCanvasManager) { // Requires excanvas.js + G_vmlCanvasManager.initElement(this.canvas); + } + this.ctx = this.canvas.getContext('2d'); + } + this._refresh(true); + this._mouseInit(); + }, + + /* Refresh the appearance of the signature area. + @param init (boolean, internal) 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. + @param init (boolean, internal) true if initialising */ + clear: function(init) { + 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 change event. + @param event (Event) the triggering event */ + _changed: function(event) { + if (this.options.syncField) { + $(this.options.syncField).val(this.toJSON()); + } + this._trigger('change', event, {}); + }, + + /* Custom options handling. + @param options (object) 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 + } + this._refresh(); + }, + + /* Determine if dragging can start. + @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. + @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. + @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. + @param event (Event) the triggering mouse event */ + _mouseStop: function(event) { + this.lastPoint = null; + this.curLine = null; + this._changed(event); + }, + + /* Round to two decimal points. + @param value (number) 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. + @return (string) the JSON text version of the lines */ + toJSON: function() { + return '{"lines":[' + $.map(this.lines, function(line) { + return '[' + $.map(line, function(point) { + return '[' + point + ']'; + }) + ']'; + }) + ']}'; + }, + + /* Convert the captured lines to SVG text. + @return (string) the SVG text version of the lines */ + toSVG: function() { + return '\n\n' + + '\n' + + ' \n' + + ' \n' + + ' \n'+ + $.map(this.lines, function(line) { + return ' \n'; + }).join('') + + ' \n \n\n'; + }, + + /* Draw a signature from its JSON description. + @param sigJSON (object) object with attribute lines + being an array of arrays of points or + (string) text version of the JSON */ + draw: function(sigJSON) { + this.clear(true); + if (typeof sigJSON === 'string') { + sigJSON = $.parseJSON(sigJSON); + } + this.lines = sigJSON.lines || []; + var ctx = this.ctx; + $.each(this.lines, function() { + ctx.beginPath(); + $.each(this, function(i) { + ctx[i === 0 ? 'moveTo' : 'lineTo'](this[0], this[1]); + }); + ctx.stroke(); + }); + this._changed(); + }, + + /* Determine whether or not any drawing has occurred. + @return (boolean) true if not signed, false if signed */ + isEmpty: function() { + return this.lines.length === 0; + }, + + /* Remove the signature functionality. */ + _destroy: function() { + this.element.removeClass(this.widgetFullName || this.widgetBaseClass); + $(this.canvas).remove(); + this.canvas = this.ctx = this.lines = null; + this._mouseDestroy(); + } +}; + +if (!$.Widget.prototype._destroy) { + $.extend(signatureOverrides, { + /* Remove the signature functionality. */ + destroy: function() { + this._destroy(); + $.Widget.prototype.destroy.call(this); // Base widget handling + } + }); +} + +if($.Widget.prototype._getCreateOptions === $.noop) { + $.extend(signatureOverrides, { + /* Restore the metadata functionality. */ + _getCreateOptions: function() { + return $.metadata && $.metadata.get(this.element[0])[this.widgetName]; + } + }); +} + +/* Signature capture and display. + Depends on jquery.ui.widget, jquery.ui.mouse. */ +$.widget('kbw.signature', $.ui.mouse, signatureOverrides); + +// Make some things more accessible +$.kbw.signature.options = $.kbw.signature.prototype.options; + +})(jQuery); \ No newline at end of file diff --git a/web_digital_sign/static/src/css/digital.css b/web_digital_sign/static/src/css/digital.css new file mode 100644 index 00000000..b0a44871 --- /dev/null +++ b/web_digital_sign/static/src/css/digital.css @@ -0,0 +1,10 @@ +/* Styles for signature plugin v1.1.0. */ +/* .kbw-signature { + height : "100px"; + width : "150px"; +} */ + + +.openerp .oe_form_readonly .oe_edit_only, .openerp .oe_form_readonly .oe_form_field:empty { + display: none !important; +} \ No newline at end of file diff --git a/web_digital_sign/static/src/css/jquery-ui.css b/web_digital_sign/static/src/css/jquery-ui.css new file mode 100644 index 00000000..ac8782f8 --- /dev/null +++ b/web_digital_sign/static/src/css/jquery-ui.css @@ -0,0 +1,1225 @@ +/*! jQuery UI - v1.11.2 - 2014-10-16 +* http://jqueryui.com +* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=segoe%20ui%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=ece8da&bgTextureHeader=gloss_wave&bgImgOpacityHeader=100&borderColorHeader=d4ccb0&fcHeader=433f38&iconColorHeader=847e71&bgColorContent=f5f3e5&bgTextureContent=highlight_hard&bgImgOpacityContent=100&borderColorContent=dfd9c3&fcContent=312e25&iconColorContent=808080&bgColorDefault=459e00&bgTextureDefault=highlight_hard&bgImgOpacityDefault=15&borderColorDefault=327E04&fcDefault=ffffff&iconColorDefault=eeeeee&bgColorHover=67b021&bgTextureHover=highlight_soft&bgImgOpacityHover=25&borderColorHover=327E04&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=fafaf4&bgTextureActive=highlight_hard&bgImgOpacityActive=100&borderColorActive=d4ccb0&fcActive=459e00&iconColorActive=8DC262&bgColorHighlight=fcf0ba&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=e8e1b5&fcHighlight=363636&iconColorHighlight=8DC262&bgColorError=ffedad&bgTextureError=highlight_soft&bgImgOpacityError=95&borderColorError=e3a345&fcError=cd5c0a&iconColorError=cd0a0a&bgColorOverlay=2b2922&bgTextureOverlay=inset_soft&bgImgOpacityOverlay=15&opacityOverlay=90&bgColorShadow=cccccc&bgTextureShadow=highlight_hard&bgImgOpacityShadow=95&opacityShadow=20&thicknessShadow=12px&offsetTopShadow=-12px&offsetLeftShadow=-12px&cornerRadiusShadow=10px +* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin: 2px 0 0 0; + padding: .5em .5em .5em .7em; + min-height: 0; /* support: IE7 */ + font-size: 100%; +} +.ui-accordion .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-icons .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; /* removes extra width in IE */ +} +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2.2em; +} +/* button elements seem to need a little more width */ +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} + +/* button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, +.ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon, +.ui-button-text-icon-primary .ui-icon, +.ui-button-text-icon-secondary .ui-icon, +.ui-button-text-icons .ui-icon, +.ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, +.ui-button-text-icons .ui-button-icon-primary, +.ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, +.ui-button-text-icons .ui-button-icon-secondary, +.ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} + +/* button sets */ +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} + +/* workarounds */ +/* reset extra padding in Firefox, see h5bp.com/l */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 45%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-dialog { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 20px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-draggable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + position: relative; + margin: 0; + padding: 3px 1em 3px .4em; + cursor: pointer; + min-height: 0; /* support: IE7 */ + /* support: IE10, see #8844 */ + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { + margin: -1px; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item { + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + margin: auto 0; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("data:image/gif;base64,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"); + height: 100%; + filter: alpha(opacity=25); /* support: IE8 */ + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-selectable { + -ms-touch-action: none; + touch-action: none; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-selectmenu-menu { + padding: 0; + margin: 0; + position: absolute; + top: 0; + left: 0; + display: none; +} +.ui-selectmenu-menu .ui-menu { + overflow: auto; + /* Support: IE7 */ + overflow-x: hidden; + padding-bottom: 1px; +} +.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { + font-size: 1em; + font-weight: bold; + line-height: 1.5; + padding: 2px 0.4em; + margin: 0.5em 0 0 0; + height: auto; + border: 0; +} +.ui-selectmenu-open { + display: block; +} +.ui-selectmenu-button { + display: inline-block; + overflow: hidden; + position: relative; + text-decoration: none; + cursor: pointer; +} +.ui-selectmenu-button span.ui-icon { + right: 0.5em; + left: auto; + margin-top: -8px; + position: absolute; + top: 50%; +} +.ui-selectmenu-button span.ui-selectmenu-text { + text-align: left; + padding: 0.4em 2.1em 0.4em 1em; + display: block; + line-height: 1.4; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; + -ms-touch-action: none; + touch-action: none; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* support: IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-sortable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 22px; +} +.ui-spinner-button { + width: 16px; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to override default borders */ +.ui-spinner a.ui-spinner-button { + border-top: none; + border-bottom: none; + border-right: none; +} +/* vertically center icon */ +.ui-spinner .ui-icon { + position: absolute; + margin-top: -8px; + top: 50%; + left: 0; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position: -65px -16px; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +body .ui-tooltip { + border-width: 2px; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: segoe ui,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: segoe ui,Arial,sans-serif; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #dfd9c3; + background: #f5f3e5 url("images/ui-bg_highlight-hard_100_f5f3e5_1x100.png") 50% top repeat-x; + color: #312e25; +} +.ui-widget-content a { + color: #312e25; +} +.ui-widget-header { + border: 1px solid #d4ccb0; + background: #ece8da url("images/ui-bg_gloss-wave_100_ece8da_500x100.png") 50% 50% repeat-x; + color: #433f38; + font-weight: bold; +} +.ui-widget-header a { + color: #433f38; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #327E04; + background: #459e00 url("images/ui-bg_highlight-hard_15_459e00_1x100.png") 50% 50% repeat-x; + font-weight: bold; + color: #ffffff; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #ffffff; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #327E04; + background: #67b021 url("images/ui-bg_highlight-soft_25_67b021_1x100.png") 50% 50% repeat-x; + font-weight: bold; + color: #ffffff; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited { + color: #ffffff; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #d4ccb0; + background: #fafaf4 url("images/ui-bg_highlight-hard_100_fafaf4_1x100.png") 50% 50% repeat-x; + font-weight: bold; + color: #459e00; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #459e00; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #e8e1b5; + background: #fcf0ba url("images/ui-bg_glass_55_fcf0ba_1x400.png") 50% 50% repeat-x; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #e3a345; + background: #ffedad url("images/ui-bg_highlight-soft_95_ffedad_1x100.png") 50% top repeat-x; + color: #cd5c0a; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd5c0a; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd5c0a; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("images/ui-icons_808080_256x240.png"); +} +.ui-widget-header .ui-icon { + background-image: url("images/ui-icons_847e71_256x240.png"); +} +.ui-state-default .ui-icon { + background-image: url("images/ui-icons_eeeeee_256x240.png"); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url("images/ui-icons_ffffff_256x240.png"); +} +.ui-state-active .ui-icon { + background-image: url("images/ui-icons_8DC262_256x240.png"); +} +.ui-state-highlight .ui-icon { + background-image: url("images/ui-icons_8DC262_256x240.png"); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("images/ui-icons_cd0a0a_256x240.png"); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 6px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 6px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 6px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 6px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #2b2922 url("images/ui-bg_inset-soft_15_2b2922_1x100.png") 50% bottom repeat-x; + opacity: .9; + filter: Alpha(Opacity=90); /* support: IE8 */ +} +.ui-widget-shadow { + margin: -12px 0 0 -12px; + padding: 12px; + background: #cccccc url("images/ui-bg_highlight-hard_95_cccccc_1x100.png") 50% top repeat-x; + opacity: .2; + filter: Alpha(Opacity=20); /* support: IE8 */ + border-radius: 10px; +} diff --git a/web_digital_sign/static/src/css/jquery.signature.css b/web_digital_sign/static/src/css/jquery.signature.css new file mode 100644 index 00000000..bd566550 --- /dev/null +++ b/web_digital_sign/static/src/css/jquery.signature.css @@ -0,0 +1,5 @@ +/* Styles for signature plugin v1.1.0. */ +.kbw-signature { + display: inline-block; + border: 1px solid #a0a0a0; +} diff --git a/web_digital_sign/static/src/img/icon.png b/web_digital_sign/static/src/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..53dd30d963540cd1eee217c8db5ee89277fab319 GIT binary patch literal 16349 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 literal 0 HcmV?d00001 diff --git a/web_digital_sign/static/src/js/digital_sign.js b/web_digital_sign/static/src/js/digital_sign.js new file mode 100644 index 00000000..8fc0bfb5 --- /dev/null +++ b/web_digital_sign/static/src/js/digital_sign.js @@ -0,0 +1,132 @@ +openerp.web_digital_sign = function(instance) { + var _t = instance.web._t; + var QWeb = instance.web.qweb; + var images = {} + + instance.web.form.widgets.add('signature', 'instance.web.form.FieldSignature'); + instance.web.form.FieldSignature = instance.web.form.FieldBinaryImage.extend({ + template: 'FieldSignature', + render_value: function() { + var self = this; + var url; + if (this.get('value') && !instance.web.form.is_bin_size(this.get('value'))) { + url = 'data:image/png;base64,' + this.get('value'); + }else if (this.get('value')) { + var id = JSON.stringify(this.view.datarecord.id || null); + self.digita_dataset = new instance.web.DataSetSearch(self, self.view.model, {}, []); + self.digita_dataset.read_slice(['id', self.name], {'domain': [['id', '=', id]]}).then(function(records){ + _.each(records,function(record){ + if(record[self.name]){ + images[self.name] = record[self.name] + }else{ + images[self.name] = "" + } + }) + }) + var field = this.name; + if (this.options.preview_image) + field = this.options.preview_image; + url = this.session.url('/web/binary/image', { + model: this.view.dataset.model, + id: id, + field: field, + t: (new Date().getTime()), + }); + }else { + images[self.name] = "" + url = this.placeholder; + self.set('value',images[self.name]) + } + var $img = $(QWeb.render("FieldBinaryImage-img", { widget: this, url: url })); + this.$el.find('img').remove(); + if(this.view.get("actual_mode") !== 'edit' && this.view.get("actual_mode") !== 'create'){ + this.$el.prepend($img); + }else if(this.view.get("actual_mode") == 'edit' ){ + this.$el.find('> img').remove(); + this.$el.find('> canvas').remove(); + if(! this.get('value')){ + this.$el.find('> img').remove(); + $(this.$el[0]).find(".signature").signature(); + }else if(this.get('value')){ + this.$el.prepend($img); + } + }else if( this.view.get("actual_mode") == 'create'){ + images = {} + this.$el.find('> img').remove(); + this.$el.find('> canvas').remove(); + if(! this.get('value')){ + this.$el.find('> img').remove(); + $(this.$el[0]).find(".signature").signature(); + }else if(this.get('value')){ + this.$el.prepend($img); + } + } + $(this.$el[0]).find('.clear_sign').click(function(){ + self.$el.find('> img').remove(); + images[self.name] = "" + $(self.$el[0]).find(".signature").show(); + $(self.$el[0]).find(".signature").signature('clear'); + }); + $('.save_sign').click(function(){ + var val + if($(self.$el[0]).find(".signature").hasClass( "kbw-signature" ) && ! $(self.$el[0]).find(".signature").signature('isEmpty')){ + $(self.$el[0]).find(".signature").hide(); + val = $(self.$el[0]).find(".signature > canvas")[0].toDataURL(); + images[self.name] = val.split(',')[1] + var $img = $(QWeb.render("FieldBinaryImage-extend", { widget: self, url: val })); + self.$el.find('> img').remove(); + self.$el.prepend($img); + self.set('value',val.split(',')[1]) + var id = JSON.stringify(self.view.datarecord.id || null); + var field = self.name; + url = self.session.url('/web/binary/image', { + model: self.view.dataset.model, + id: id, + field: field, + t: (new Date().getTime()), + }); + }else{ + var id = JSON.stringify(self.view.datarecord.id || null); + var field = self.name; + if (self.options.preview_image) + field = self.options.preview_image; + url = self.session.url('/web/binary/image', { + model: self.view.dataset.model, + id: id, + field: field, + t: (new Date().getTime()), + }); + var $img = $(QWeb.render("FieldBinaryImage-extend", { widget: self, url: url })); + self.$el.find('> img').remove(); + } + }); + $img.load(function() { + if (! self.options.size) + return; + $img.css("max-width", "" + self.options.size[0] + "px"); + $img.css("max-height", "" + self.options.size[1] + "px"); + $img.css("margin-left", "" + (self.options.size[0] - $img.width()) / 2 + "px"); + $img.css("margin-top", "" + (self.options.size[1] - $img.height()) / 2 + "px"); + }); + $img.on('error', function() { + $img.attr('src', self.placeholder); + instance.webclient.notification.warn(_t("Image"), _t("Could not display the selected image.")); + }); + }, + }); + instance.web.FormView.include({ + save: function(prepend_on_create) { + var self = this; + $('.save_sign').click() + var save_obj = {prepend_on_create: prepend_on_create, ret: null}; + this.save_list.push(save_obj); + return this._process_operations().then(function() { + if (save_obj.error) + return $.Deferred().reject(); + return $.when.apply($, save_obj.ret); + }).done(function() { + self.$el.removeClass('oe_form_dirty'); + }); + }, + }) +} diff --git a/web_digital_sign/static/src/xml/digital_sign.xml b/web_digital_sign/static/src/xml/digital_sign.xml new file mode 100644 index 00000000..68cf2d64 --- /dev/null +++ b/web_digital_sign/static/src/xml/digital_sign.xml @@ -0,0 +1,18 @@ + + + +
+

+ + +
+ + + + + \ No newline at end of file