4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
13 * @class Roo.form.Signature
14 * @extends Roo.form.Field
18 * @param {Object} config Configuration options
21 Roo.form.Signature = function(config){
22 Roo.form.Signature.superclass.constructor.call(this, config);
24 this.addEvents({// not in used??
27 * Fires when the 'confirm' icon is pressed (add a listener to enable add button)
28 * @param {Roo.form.Signature} combo This combo box
33 * Fires when the 'edit' icon is pressed (add a listener to enable add button)
34 * @param {Roo.form.ComboBox} combo This combo box
35 * @param {Roo.data.Record|false} record The data record returned from the underlying store (or false on nothing selected)
41 Roo.extend(Roo.form.Signature, Roo.form.Field, {
43 * @cfg {Object} labels Label to use when rendering a form.
55 * @cfg {Number} width The signature panel width (defaults to 300)
59 * @cfg {Number} height The signature panel height (defaults to 100)
63 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to false)
68 // {Object} signPanel The signature SVG panel element (defaults to {})
70 // {Boolean} isMouseDown False to validate that the mouse down event (defaults to false)
72 // {Boolean} isConfirmed validate the signature is confirmed or not for submitting form (defaults to false)
74 // {String} signatureTmp SVG mapping string (defaults to empty string)
78 defaultAutoCreate : { // modified by initCompnoent..
84 onRender : function(ct, position){
86 Roo.form.Signature.superclass.onRender.call(this, ct, position);
88 this.wrap = this.el.wrap({
89 cls:'x-form-signature-wrap', style : 'width: ' + this.width + 'px', cn:{cls:'x-form-signature'}
92 this.createToolbar(this);
93 this.signPanel = this.wrap.createChild({
95 style: 'width: ' + this.width + 'px; height: ' + this.height + 'px; border: 0;'
99 this.svgID = Roo.id();
100 this.svgEl = this.signPanel.createChild({
101 xmlns : 'http://www.w3.org/2000/svg',
105 viewBox: '0 0 '+this.width+' '+this.height,
109 id: this.svgID + "-svg-r",
117 y1: (this.height*0.8), // start set the line in 80% of height
118 x2: this.width, // end
119 y2: (this.height*0.8), // end set the line in 80% of height
122 'stroke-dasharray': "3",
123 'shape-rendering': "crispEdges",
124 'pointer-events': "none"
128 id: this.svgID + "-svg-p",
132 'pointer-events': 'none'
137 this.svgBox = this.svgEl.dom.getScreenCTM();
139 createSVG : function(){
140 var svg = this.signPanel;
141 var r = svg.select('#'+ this.svgID + '-svg-r', true).first().dom;
144 r.addEventListener('mousedown', function(e) { return t.down(e); }, false);
145 r.addEventListener('mousemove', function(e) { return t.move(e); }, false);
146 r.addEventListener('mouseup', function(e) { return t.up(e); }, false);
147 r.addEventListener('mouseout', function(e) { return t.up(e); }, false);
148 r.addEventListener('touchstart', function(e) { return t.down(e); }, false);
149 r.addEventListener('touchmove', function(e) { return t.move(e); }, false);
150 r.addEventListener('touchend', function(e) { return t.up(e); }, false);
153 isTouchEvent : function(e){
154 return e.type.match(/^touch/);
156 getCoords : function (e) {
157 var pt = this.svgEl.dom.createSVGPoint();
160 if (this.isTouchEvent(e)) {
161 pt.x = e.targetTouches[0].clientX
162 pt.y = e.targetTouches[0].clientY;
164 var a = this.svgEl.dom.getScreenCTM();
166 var mx = pt.matrixTransform(b);
167 return mx.x + ',' + mx.y;
169 //mouse event headler
170 down : function (e) {
171 this.signatureTmp += 'M' + this.getCoords(e) + ' ';
172 this.signPanel.select('#'+ this.svgID + '-svg-p', true).first().attr('d', this.signatureTmp);
174 this.isMouseDown = true;
178 move : function (e) {
179 if (this.isMouseDown) {
180 this.signatureTmp += 'L' + this.getCoords(e) + ' ';
181 this.signPanel.select('#'+ this.svgID + '-svg-p', true).first().attr( 'd', this.signatureTmp);
187 this.isMouseDown = false;
188 var sp = this.signatureTmp.split(' ');
191 if(!sp[sp.length-2].match(/^L/)){
195 this.signatureTmp = sp.join(" ");
198 if(this.getValue() != this.signatureTmp){
199 this.signPanel.select('#'+ this.svgID + '-svg-r', true).first().attr('fill', '#ffa');
200 this.isConfirmed = false;
206 * Protected method that will not generally be called directly. It
207 * is called when the editor creates its toolbar. Override this method if you need to
208 * add custom toolbar buttons.
209 * @param {HtmlEditor} editor
211 createToolbar : function(editor){
212 function btn(id, toggle, handler){
213 var xid = fid + '-'+ id ;
217 cls : 'x-btn-icon x-edit-'+id,
218 enableToggle:toggle !== false,
219 scope: editor, // was editor...
220 handler:handler||editor.relayBtnCmd,
221 clickEvent:'mousedown',
222 tooltip: etb.buttonTips[id] || undefined, ///tips ???
228 var tb = new Roo.Toolbar(editor.wrap.dom.firstChild);
232 cls : ' x-signature-btn x-signature-'+id,
233 scope: editor, // was editor...
235 clickEvent:'mousedown',
236 text: this.labels.clear
243 cls : ' x-signature-btn x-signature-'+id,
244 scope: editor, // was editor...
245 handler: this.setConfirmed,
246 clickEvent:'mousedown',
247 text: this.labels.confirm
254 * when user is clicked confirm then show this image.....
256 * @return {String} Image Data URI
258 getImageDataURI : function(){
259 var svg = this.svgEl.dom.outerHTML;
260 var src = 'data:image/svg+xml;base64,'+window.btoa(svg);
265 * @return {Boolean} this.isConfirmed
267 getConfirmed : function(){
268 return this.isConfirmed;
272 * @return {Number} this.width
274 getWidth : function(){
279 * @return {Number} this.height
281 getHeight : function(){
285 getSignature : function(){
286 return this.signatureTmp;
290 this.signatureTmp = '';
291 this.signPanel.select('#'+ this.svgID + '-svg-r', true).first().attr('fill', '#ffa');
292 this.signPanel.select('#'+ this.svgID + '-svg-p', true).first().attr( 'd', '');
293 this.isConfirmed = false;
294 Roo.form.Signature.superclass.reset.call(this);
296 setSignature : function(s){
297 this.signatureTmp = s;
298 this.signPanel.select('#'+ this.svgID + '-svg-r', true).first().attr('fill', '#ffa');
299 this.signPanel.select('#'+ this.svgID + '-svg-p', true).first().attr( 'd', s);
301 this.isConfirmed = false;
302 Roo.form.Signature.superclass.reset.call(this);
305 // Roo.log(this.signPanel.dom.contentWindow.up())
308 setConfirmed : function(){
309 if(!this.getSignature()){
312 this.signPanel.select('#'+ this.svgID + '-svg-r', true).first().attr('fill', '#cfc');
313 this.setValue(this.getSignature());
314 this.isConfirmed = true;
317 // Roo.log(Roo.get(this.signPanel.dom.contentWindow.r).attr('fill', '#cfc'));
320 confirmHandler : function(){
321 Roo.log('in confirm clicked');
322 if(!this.getConfirmed()){
323 return false; // stops
325 Roo.log('in confirm clicked');
328 // this.items.each(function(f){
329 // if(!f.isValid(true)){
334 // for(var i = 0, len = this.buttons.length; i < len; i++){
335 // var btn = this.buttons[i];
336 // if(btn.formBind === true && btn.disabled === valid){
337 // btn.setDisabled(!valid);
340 this.fireEvent('confirm', this);
343 // Subclasses should provide the validation implementation by overriding this
344 validateValue : function(value){
349 if(this.isConfirmed){