Anonymous Login
2016-09-28 10:27 CEST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
04652User patchesSurvey designpublic2010-12-14 13:02
Reporteruser9586 
Assigned Toc_schmitz 
PrioritynormalSeverityminor 
StatusclosedResolutionfixed 
Product Version1.90 
Target VersionFixed in Version1.91 
Summary04652: Keyboard-less operation through JS keypad
DescriptionAs described before in http://sourceforge.net/mailarchive/message.php?msg_name=20100908124843.af9a493a.yuri.delia%40eurac.edu , we're using limesurvey on tablet-pcs in a setting similar to paper questionnaires.

These tablet PCs don't have a keyboard or numeric keypad. We designed our questionnaires so that there's mostly no need to enter text or numbers (we used sliders, options, etc).

There are still rare cases where entering an arbitrary number or a very short text is desiderable though, and should be possible without having a keyboard.

This patch adds a new per-survey setting called 'Keyboard-less operation', which adds a virtual keypad, or virtual keyboard to 'Numerical/Multiple numerical/Short text/Multiple short text' question types (we don't use short text ourselves, but it was easy enough to implement to include it anyway). By differentiating the keypad, based on the question type, the UI is superior than using a system-wide virtual keypad.

The patch itself uses a jquery plugin called 'Keypad', by Keith Wood (http://keith-wood.name/keypad.html), which is dual-licensed MIT/GPL and supports multiple language translations and layouts.
Additional InformationNotably, the 'token' can also be entered with a virtual keyboard.
TagsNo tags attached.
Complete LimeSurvey version number (& build)9114
Attached Files
  • diff file icon svn-patch-2.diff (46,430 bytes) 2010-11-29 11:54 -
    Index: scripts/jquery/jquery.keypad.min.js
    ===================================================================
    --- scripts/jquery/jquery.keypad.min.js	(revision 0)
    +++ scripts/jquery/jquery.keypad.min.js	(revision 0)
    @@ -0,0 +1,7 @@
    +/* http://keith-wood.name/keypad.html
    +   Keypad field entry extension for jQuery v1.3.0.
    +   Written by Keith Wood (kbwood{at}iinet.com.au) August 2008.
    +   Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
    +   MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
    +   Please attribute the author if you use it. */
    +(function($){var t='keypad';function Keypad(){this.BS='\x08';this.DEL='\x7F';this.EN='\x0D';this._curInst=null;this._disabledFields=[];this._keypadShowing=false;this.regional=[];this.regional['']={buttonText:'...',buttonStatus:'Open the keypad',closeText:'Close',closeStatus:'Close the keypad',clearText:'Clear',clearStatus:'Erase all the text',backText:'Back',backStatus:'Erase the previous character',enterText:'Enter',enterStatus:'Carriage return',shiftText:'Shift',shiftStatus:'Toggle upper/lower case characters',alphabeticLayout:this.qwertyAlphabetic,fullLayout:this.qwertyLayout,isAlphabetic:this.isAlphabetic,isNumeric:this.isNumeric,isRTL:false};this._defaults={showOn:'focus',buttonImage:'',buttonImageOnly:false,showAnim:'show',showOptions:{},duration:'normal',appendText:'',useThemeRoller:false,keypadClass:'',prompt:'',layout:['123'+this.CLOSE,'456'+this.CLEAR,'789'+this.BACK,this.SPACE+'0'],separator:'',target:null,keypadOnly:true,randomiseAlphabetic:false,randomiseNumeric:false,randomiseOther:false,randomiseAll:false,beforeShow:null,onKeypress:null,onClose:null};$.extend(this._defaults,this.regional['']);this.mainDiv=$('<div class="'+this._mainDivClass+'" style="display: none;"></div>')}var u='\x00';var v='\x01';var w='\x02';var x='\x03';var y='\x04';var z='\x05';var A='\x06';var B='\x07';$.extend(Keypad.prototype,{CLOSE:u,CLEAR:v,BACK:w,SHIFT:x,SPACE_BAR:y,SPACE:z,HALF_SPACE:A,ENTER:B,qwertyAlphabetic:['qwertyuiop','asdfghjkl','zxcvbnm'],qwertyLayout:['!@#$%^&*()_='+A+z+u,A+'`~[]{}<>\\|/'+z+'789','qwertyuiop\'"'+A+'456',A+'asdfghjkl;:'+z+'123',z+'zxcvbnm,.?'+z+A+'-0+',z+x+y+B+A+w+v],markerClassName:'hasKeypad',_mainDivClass:'keypad-popup',_inlineClass:'keypad-inline',_appendClass:'keypad-append',_triggerClass:'keypad-trigger',_disableClass:'keypad-disabled',_inlineEntryClass:'keypad-keyentry',_coverClass:'keypad-cover',setDefaults:function(a){extendRemove(this._defaults,a||{});return this},_attachKeypad:function(a,b){var c=(a.nodeName.toLowerCase()!='input'&&a.nodeName.toLowerCase()!='textarea');var d={_inline:c,_mainDiv:(c?$('<div class="'+this._inlineClass+'"></div>'):$.keypad.mainDiv),ucase:false};d.settings=$.extend({},b||{});this._setInput(a,d);this._connectKeypad(a,d);if(c){$(a).append(d._mainDiv).bind('click.keypad',function(){d._input.focus()});this._updateKeypad(d)}else if($(a).is(':disabled')){this._disableKeypad(a)}},_setInput:function(a,b){b._input=$(!b._inline?a:this._get(b,'target')||'<input type="text" class="'+this._inlineEntryClass+'" disabled="disabled"/>');if(b._inline){a=$(a);a.find('input').remove();if(!this._get(b,'target')){a.append(b._input)}}},_connectKeypad:function(d,e){var f=$(d);if(f.hasClass(this.markerClassName)){return}var g=this._get(e,'appendText');var h=this._get(e,'isRTL');if(g){f[h?'before':'after']('<span class="'+this._appendClass+'">'+g+'</span>')}if(!e._inline){var i=this._get(e,'showOn');if(i=='focus'||i=='both'){f.focus(this._showKeypad).keydown(this._doKeyDown)}if(i=='button'||i=='both'){var j=this._get(e,'buttonText');var k=this._get(e,'buttonStatus');var l=this._get(e,'buttonImage');var m=$(this._get(e,'buttonImageOnly')?$('<img src="'+l+'" alt="'+k+'" title="'+k+'"/>'):$('<button type="button" title="'+k+'"></button>').html(l==''?j:$('<img src="'+l+'" alt="'+k+'" title="'+k+'"/>')));f[h?'before':'after'](m);m.addClass(this._triggerClass).click(function(){if($.keypad._keypadShowing&&$.keypad._lastField==d){$.keypad._hideKeypad()}else{$.keypad._showKeypad(d)}return false})}}e.saveReadonly=f.attr('readonly');f.addClass(this.markerClassName).attr('readonly',(this._get(e,'keypadOnly')?'readonly':'')).bind('setData.keypad',function(a,b,c){e.settings[b]=c}).bind('getData.keypad',function(a,b){return this._get(e,b)});$.data(d,t,e)},_destroyKeypad:function(a){var b=$(a);if(!b.hasClass(this.markerClassName)){return}var c=$.data(a,t);if(this._curInst==c){this._hideKeypad()}b.siblings('.'+this._appendClass).remove().end().siblings('.'+this._triggerClass).remove().end().prev('.'+this._inlineEntryClass).remove();b.empty().unbind('focus',this._showKeypad).removeClass(this.markerClassName).attr('readonly',c.saveReadonly);$.removeData(c._input[0],t);$.removeData(a,t)},_enableKeypad:function(b){var c=$(b);if(!c.hasClass(this.markerClassName)){return}var d=b.nodeName.toLowerCase();if(d=='input'||d=='textarea'){b.disabled=false;c.siblings('button.'+this._triggerClass).each(function(){this.disabled=false}).end().siblings('img.'+this._triggerClass).css({opacity:'1.0',cursor:''})}else if(d=='div'||d=='span'){c.children('.'+this._disableClass).remove();var e=$.data(b,t);e._mainDiv.find('button').attr('disabled','')}this._disabledFields=$.map(this._disabledFields,function(a){return(a==b?null:a)})},_disableKeypad:function(b){var c=$(b);if(!c.hasClass(this.markerClassName)){return}var d=b.nodeName.toLowerCase();if(d=='input'||d=='textarea'){b.disabled=true;c.siblings('button.'+this._triggerClass).each(function(){this.disabled=true}).end().siblings('img.'+this._triggerClass).css({opacity:'0.5',cursor:'default'})}else if(d=='div'||d=='span'){var e=c.children('.'+this._inlineClass);var f=e.offset();var g={left:0,top:0};e.parents().each(function(){if($(this).css('position')=='relative'){g=$(this).offset();return false}});c.prepend('<div class="'+this._disableClass+'" style="width: '+e.outerWidth()+'px; height: '+e.outerHeight()+'px; left: '+(f.left-g.left)+'px; top: '+(f.top-g.top)+'px;"></div>');var h=$.data(b,t);h._mainDiv.find('button').attr('disabled','disabled')}this._disabledFields=$.map(this._disabledFields,function(a){return(a==b?null:a)});this._disabledFields[this._disabledFields.length]=b},_isDisabledKeypad:function(a){return(a&&$.inArray(a,this._disabledFields)>-1)},_changeKeypad:function(a,b,c){var d=b||{};if(typeof b=='string'){d={};d[b]=c}var e=$.data(a,t);if(e){if(this._curInst==e){this._hideKeypad()}extendRemove(e.settings,d);this._setInput($(a),e);this._updateKeypad(e)}},_showKeypad:function(b){b=b.target||b;if($.keypad._isDisabledKeypad(b)||$.keypad._lastField==b){return}var c=$.data(b,t);$.keypad._hideKeypad(null,'');$.keypad._lastField=b;$.keypad._pos=$.keypad._findPos(b);$.keypad._pos[1]+=b.offsetHeight;var d=false;$(b).parents().each(function(){d|=$(this).css('position')=='fixed';return!d});if(d&&$.browser.opera){$.keypad._pos[0]-=document.documentElement.scrollLeft;$.keypad._pos[1]-=document.documentElement.scrollTop}var e={left:$.keypad._pos[0],top:$.keypad._pos[1]};$.keypad._pos=null;c._mainDiv.css({position:'absolute',display:'block',top:'-1000px',width:($.browser.opera?'1000px':'auto')});$.keypad._updateKeypad(c);e=$.keypad._checkOffset(c,e,d);c._mainDiv.css({position:(d?'fixed':'absolute'),display:'none',left:e.left+'px',top:e.top+'px'});var f=$.keypad._get(c,'showAnim');var g=$.keypad._get(c,'duration');g=(g=='normal'&&$.ui&&$.ui.version>='1.8'?'_default':g);var h=function(){$.keypad._keypadShowing=true;var a=$.keypad._getBorders(c._mainDiv);c._mainDiv.find('iframe.'+$.keypad._coverClass).css({left:-a[0],top:-a[1],width:c._mainDiv.outerWidth(),height:c._mainDiv.outerHeight()})};if($.effects&&$.effects[f]){c._mainDiv.show(f,$.keypad._get(c,'showOptions'),g,h)}else{c._mainDiv[f||'show']((f?g:''),h)}if(!f){h()}if(c._input[0].type!='hidden'){c._input[0].focus()}$.keypad._curInst=c},_updateKeypad:function(a){var b=this._getBorders(a._mainDiv);a._mainDiv.empty().append(this._generateHTML(a)).find('iframe.'+this._coverClass).css({left:-b[0],top:-b[1],width:a._mainDiv.outerWidth(),height:a._mainDiv.outerHeight()});a._mainDiv.removeClass().addClass(this._get(a,'keypadClass')+(this._get(a,'useThemeRoller')?' ui-widget ui-widget-content':'')+(this._get(a,'isRTL')?' keypad-rtl':'')+' '+(a._inline?this._inlineClass:this._mainDivClass));var c=this._get(a,'beforeShow');if(c){c.apply((a._input?a._input[0]:null),[a._mainDiv,a])}},_getBorders:function(c){var d=function(a){var b=($.browser.msie?1:0);return{thin:1+b,medium:3+b,thick:5+b}[a]||a};return[parseFloat(d(c.css('border-left-width'))),parseFloat(d(c.css('border-top-width')))]},_checkOffset:function(a,b,c){var d=a._input?this._findPos(a._input[0]):null;var e=window.innerWidth||document.documentElement.clientWidth;var f=window.innerHeight||document.documentElement.clientHeight;var g=document.documentElement.scrollLeft||document.body.scrollLeft;var h=document.documentElement.scrollTop||document.body.scrollTop;if(($.browser.msie&&parseInt($.browser.version,10)<7)||$.browser.opera){var i=0;a._mainDiv.find(':not(div,iframe)').each(function(){i=Math.max(i,this.offsetLeft+$(this).outerWidth()+parseInt($(this).css('margin-right'),10))});a._mainDiv.css('width',i)}if(this._get(a,'isRTL')||(b.left+a._mainDiv.outerWidth()-g)>e){b.left=Math.max((c?0:g),d[0]+(a._input?a._input.outerWidth():0)-(c?g:0)-a._mainDiv.outerWidth()-(c&&$.browser.opera?document.documentElement.scrollLeft:0))}else{b.left-=(c?g:0)}if((b.top+a._mainDiv.outerHeight()-h)>f){b.top=Math.max((c?0:h),d[1]-(c?h:0)-a._mainDiv.outerHeight()-(c&&$.browser.opera?document.documentElement.scrollTop:0))}else{b.top-=(c?h:0)}return b},_findPos:function(a){while(a&&(a.type=='hidden'||a.nodeType!=1)){a=a.nextSibling}var b=$(a).offset();return[b.left,b.top]},_hideKeypad:function(a,b){var c=this._curInst;if(!c||(a&&c!=$.data(a,t))){return}if(this._keypadShowing){b=(b!=null?b:this._get(c,'duration'));b=(b=='normal'&&$.ui&&$.ui.version>='1.8'?'_default':b);var d=this._get(c,'showAnim');if($.effects&&$.effects[d]){c._mainDiv.hide(d,this._get(c,'showOptions'),b)}else{c._mainDiv[(d=='slideDown'?'slideUp':(d=='fadeIn'?'fadeOut':'hide'))](d?b:'')}}var e=this._get(c,'onClose');if(e){e.apply((c._input?c._input[0]:null),[c._input.val(),c])}if(this._keypadShowing){this._keypadShowing=false;this._lastField=null}if(c._inline){c._input.val('')}this._curInst=null},_doKeyDown:function(e){if(e.keyCode==9){$.keypad.mainDiv.stop(true,true);$.keypad._hideKeypad()}},_checkExternalClick:function(a){if(!$.keypad._curInst){return}var b=$(a.target);if(!b.parents().andSelf().is('.'+$.keypad._mainDivClass)&&!b.hasClass($.keypad.markerClassName)&&!b.parents().andSelf().hasClass($.keypad._triggerClass)&&$.keypad._keypadShowing){$.keypad._hideKeypad()}},_shiftKeypad:function(a){a.ucase=!a.ucase;this._updateKeypad(a);a._input.focus()},_clearValue:function(a){this._setValue(a,'',0);this._notifyKeypress(a,$.keypad.DEL)},_backValue:function(a){var b=a._input[0];var c=a._input.val();var d=[c.length,c.length];if(b.setSelectionRange){d=(a._input.attr('readonly')||a._input.attr('disabled')?d:[b.selectionStart,b.selectionEnd])}else if(b.createTextRange){d=(a._input.attr('readonly')||a._input.attr('disabled')?d:this._getIERange(b))}this._setValue(a,(c.length==0?'':c.substr(0,d[0]-1)+c.substr(d[1])),d[0]-1);this._notifyKeypress(a,$.keypad.BS)},_selectValue:function(a,b){this.insertValue(a._input[0],b);this._setValue(a,a._input.val());this._notifyKeypress(a,b)},insertValue:function(a,b){a=(a.jquery?a:$(a));var c=a[0];var d=a.val();var e=[d.length,d.length];if(c.setSelectionRange){e=(a.attr('readonly')||a.attr('disabled')?e:[c.selectionStart,c.selectionEnd])}else if(c.createTextRange){e=(a.attr('readonly')||a.attr('disabled')?e:this._getIERange(c))}a.val(d.substr(0,e[0])+b+d.substr(e[1]));pos=e[0]+b.length;if(a.css('display')!='none'){a.focus()}if(c.setSelectionRange){if(a.css('display')!='none'){c.setSelectionRange(pos,pos)}}else if(c.createTextRange){var e=c.createTextRange();e.move('character',pos);e.select()}},_getIERange:function(e){e.focus();var f=document.selection.createRange().duplicate();var g=this._getIETextRange(e);g.setEndPoint('EndToStart',f);var h=function(a){var b=a.text;var c=b;var d=false;while(true){if(a.compareEndPoints('StartToEnd',a)==0){break}else{a.moveEnd('character',-1);if(a.text==b){c+='\r\n'}else{break}}}return c};var i=h(g);var j=h(f);return[i.length,i.length+j.length]},_getIETextRange:function(a){var b=(a.nodeName.toLowerCase()=='input');var c=(b?a.createTextRange():document.body.createTextRange());if(!b){c.moveToElementText(a)}return c},_setValue:function(a,b){var c=a._input.attr('maxlength');if(c>-1){b=b.substr(0,c)}a._input.val(b);if(!this._get(a,'onKeypress')){a._input.trigger('change')}},_notifyKeypress:function(a,b){var c=this._get(a,'onKeypress');if(c){c.apply((a._input?a._input[0]:null),[b,a._input.val(),a])}},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_generateHTML:function(a){var b=this._get(a,'useThemeRoller');var c=this._get(a,'isRTL');var d=this._get(a,'prompt');var e=this._get(a,'separator');var f=(!d?'':'<div class="keypad-prompt'+(b?' ui-widget-header ui-corner-all':'')+'">'+d+'</div>');var g=this._randomiseLayout(a);for(var i=0;i<g.length;i++){f+='<div class="keypad-row">';var h=g[i].split(e);for(var j=0;j<h.length;j++){if(a.ucase){h[j]=h[j].toUpperCase()}f+=(h[j]==this.SPACE?'<div class="keypad-space"></div>':(h[j]==this.HALF_SPACE?'<div class="keypad-half-space"></div>':'<button type="button" class="keypad-key'+(b?' ui-state-default':'')+(h[j]==this.CLEAR?' keypad-clear'+(b?' ui-state-highlight':''):(h[j]==this.BACK?' keypad-back'+(b?' ui-state-highlight':''):(h[j]==this.CLOSE?' keypad-close'+(b?' ui-state-highlight':''):(h[j]==this.SHIFT?' keypad-shift'+(b?' ui-state-highlight':''):(h[j]==this.ENTER?' keypad-enter'+(b?' ui-state-highlight':''):(h[j]==this.SPACE_BAR?' keypad-spacebar':''))))))+'" '+'title="'+(h[j]==this.CLEAR?this._get(a,'clearStatus'):(h[j]==this.BACK?this._get(a,'backStatus'):(h[j]==this.ENTER?this._get(a,'enterStatus'):(h[j]==this.CLOSE?this._get(a,'closeStatus'):(h[j]==this.SHIFT?this._get(a,'shiftStatus'):'')))))+'">'+(h[j]==this.CLEAR?this._get(a,'clearText'):(h[j]==this.BACK?this._get(a,'backText'):(h[j]==this.CLOSE?this._get(a,'closeText'):(h[j]==this.SHIFT?this._get(a,'shiftText'):(h[j]==this.ENTER?this._get(a,'enterText'):(h[j]==this.SPACE_BAR?'&nbsp;':(h[j]==' '?'&nbsp;':h[j])))))))+'</button>'))}f+='</div>'}f+='<div style="clear: both;"></div>'+(!a._inline&&$.browser.msie&&parseInt($.browser.version,10)<7?'<iframe src="javascript:false;" class="'+$.keypad._coverClass+'"></iframe>':'');f=$(f);var k=a;var l='keypad-key-down'+(b?' ui-state-active':'');f.find('button').mousedown(function(){$(this).addClass(l)}).mouseup(function(){$(this).removeClass(l)}).mouseout(function(){$(this).removeClass(l)}).filter('.keypad-clear').click(function(){$.keypad._clearValue(k)}).end().filter('.keypad-back').click(function(){$.keypad._backValue(k)}).end().filter('.keypad-close').click(function(){$.keypad._curInst=(k._inline?k:$.keypad._curInst);$.keypad._hideKeypad()}).end().filter('.keypad-shift').click(function(){$.keypad._shiftKeypad(k)}).end().filter('.keypad-enter').click(function(){$.keypad._selectValue(k,$.keypad.EN)}).end().not('.keypad-clear').not('.keypad-back').not('.keypad-close').not('.keypad-shift').not('.keypad-enter').click(function(){$.keypad._selectValue(k,$(this).text())});return f},_randomiseLayout:function(b){var c=this._get(b,'randomiseNumeric');var d=this._get(b,'randomiseAlphabetic');var e=this._get(b,'randomiseOther');var f=this._get(b,'randomiseAll');var g=this._get(b,'layout');if(!c&&!d&&!e&&!f){return g}var h=this._get(b,'isNumeric');var k=this._get(b,'isAlphabetic');var l=this._get(b,'separator');var m=[];var p=[];var q=[];var r=[];for(var i=0;i<g.length;i++){r[i]='';var s=g[i].split(l);for(var j=0;j<s.length;j++){if(this._isControl(s[j])){continue}if(f){q.push(s[j])}else if(h(s[j])){m.push(s[j])}else if(k(s[j])){p.push(s[j])}else{q.push(s[j])}}}if(c){this._shuffle(m)}if(d){this._shuffle(p)}if(e||f){this._shuffle(q)}var n=0;var a=0;var o=0;for(var i=0;i<g.length;i++){var s=g[i].split(l);for(var j=0;j<s.length;j++){r[i]+=(this._isControl(s[j])?s[j]:(f?q[o++]:(h(s[j])?m[n++]:(k(s[j])?p[a++]:q[o++]))))+l}}return r},_isControl:function(a){return a<' '},isAlphabetic:function(a){return(a>='A'&&a<='Z')||(a>='a'&&a<='z')},isNumeric:function(a){return(a>='0'&&a<='9')},_shuffle:function(a){for(var i=a.length-1;i>0;i--){var j=Math.floor(Math.random()*a.length);var b=a[i];a[i]=a[j];a[j]=b}}});function extendRemove(a,b){$.extend(a,b);for(var c in b){if(b[c]==null||b[c]==undefined){a[c]=b[c]}}return a};$.fn.keypad=function(a){var b=Array.prototype.slice.call(arguments,1);if(a=='isDisabled'){return $.keypad['_'+a+'Keypad'].apply($.keypad,[this[0]].concat(b))}return this.each(function(){typeof a=='string'?$.keypad['_'+a+'Keypad'].apply($.keypad,[this].concat(b)):$.keypad._attachKeypad(this,a)})};$.keypad=new Keypad();$(function(){$(document.body).append($.keypad.mainDiv).mousedown($.keypad._checkExternalClick)})})(jQuery);
    \ No newline at end of file
    Index: scripts/jquery/css/jquery.keypad.alt.css
    ===================================================================
    --- scripts/jquery/css/jquery.keypad.alt.css	(revision 0)
    +++ scripts/jquery/css/jquery.keypad.alt.css	(revision 0)
    @@ -0,0 +1,102 @@
    +/* Alternate style sheet for jQuery Keypad v1.3.0 */
    +button.keypad-trigger {
    +	width: 25px;
    +	padding: 0px;
    +}
    +img.keypad-trigger {
    +	margin: 2px;
    +	vertical-align: middle;
    +}
    +.keypad-popup {
    +	display: none;
    +	z-index: 10;
    +	margin: 0;
    +	padding: 0;
    +	background-color: #fff;
    +	color: #000;
    +	border: 1px solid #888;
    +	border-radius: 4px;
    +	-moz-border-radius: 4px;
    +	-webkit-border-radius: 4px;
    +	font-family: Arial,Helvetica,sans-serif;
    +	font-size: 14px;
    +}
    +.keypad-keyentry {
    +	display: none;
    +}
    +.keypad-inline {
    +	background-color: #f4f4f4;
    +	border: 1px solid #888;
    +	border-radius: 4px;
    +	-moz-border-radius: 4px;
    +	-webkit-border-radius: 4px;
    +}
    +.keypad-disabled {
    +	position: absolute;
    +	z-index: 100;
    +	background-color: white;
    +	opacity: 0.25;
    +	filter: alpha(opacity=25);
    +}
    +.keypad-rtl {
    +	direction: rtl;
    +}
    +.keypad-prompt {
    +	clear: both;
    +	text-align: center;
    +}
    +.keypad-prompt.ui-widget-header {
    +	margin: 2px;
    +}
    +.keypad-row {
    +	clear: both;
    +	float: left;
    +	width: 100%;
    +}
    +.keypad-space {
    +	float: left;
    +	margin: 2px;
    +	width: 24px;
    +}
    +* html .keypad-space { /* IE6 */
    +	margin: 0px;
    +	width: 28px;
    +}
    +.keypad-half-space {
    +	float: left;
    +	margin: 1px;
    +	width: 12px;
    +}
    +* html .keypad-half-space { /* IE6 */
    +	margin: 0px;
    +	width: 14px;
    +}
    +.keypad-key {
    +	float: left;
    +	margin: 2px;
    +	padding: 0px;
    +	width: 24px;
    +	text-align: center;
    +	cursor: pointer;
    +}
    +.keypad-spacebar {
    +	width: 164px;
    +}
    +.keypad-enter {
    +	width: 52px;
    +}
    +.keypad-clear, .keypad-back, .keypad-close, .keypad-shift {
    +	width: 108px;
    +	font-weight: bold;
    +}
    +.keypad-cover {
    +	display: none;
    +	display/**/: block;
    +	position: absolute;
    +	z-index: -1;
    +	filter: mask();
    +	top: -4px;
    +	left: -4px;
    +	width: 125px;
    +	height: 200px;
    +}
    Index: scripts/jquery/css/jquery.keypad.css
    ===================================================================
    --- scripts/jquery/css/jquery.keypad.css	(revision 0)
    +++ scripts/jquery/css/jquery.keypad.css	(revision 0)
    @@ -0,0 +1,124 @@
    +/* Main style sheet for jQuery Keypad v1.3.0 */
    +button.keypad-trigger {
    +	width: 25px;
    +	padding: 0px;
    +}
    +img.keypad-trigger {
    +	margin: 2px;
    +	vertical-align: middle;
    +}
    +.keypad-popup {
    +	display: none;
    +	z-index: 10;
    +	margin: 0;
    +	padding: 0;
    +	background-color: #fff;
    +	color: #000;
    +	border: 1px solid #888;
    +	border-radius: 4px;
    +	-moz-border-radius: 4px;
    +	-webkit-border-radius: 4px;
    +	font-family: Arial,Helvetica,sans-serif;
    +	font-size: 14px;
    +}
    +.keypad-keyentry {
    +	display: none;
    +}
    +.keypad-inline {
    +	background-color: #f4f4f4;
    +	border: 1px solid #888;
    +	border-radius: 4px;
    +	-moz-border-radius: 4px;
    +	-webkit-border-radius: 4px;
    +}
    +.keypad-disabled {
    +	position: absolute;
    +	z-index: 100;
    +	background-color: white;
    +	opacity: 0.5;
    +	filter: alpha(opacity=50);
    +}
    +.keypad-rtl {
    +	direction: rtl;
    +}
    +.keypad-prompt {
    +	clear: both;
    +	text-align: center;
    +}
    +.keypad-prompt.ui-widget-header {
    +	margin: 2px;
    +}
    +.keypad-row {
    +	clear: both;
    +	float: left;
    +	width: 100%;
    +}
    +.keypad-space {
    +	float: left;
    +	margin: 2px;
    +	width: 24px;
    +}
    +* html .keypad-space { /* IE6 */
    +	margin: 0px;
    +	width: 28px;
    +}
    +.keypad-half-space {
    +	float: left;
    +	margin: 1px;
    +	width: 12px;
    +}
    +* html .keypad-half-space { /* IE6 */
    +	margin: 0px;
    +	width: 14px;
    +}
    +.keypad-key {
    +	float: left;
    +	margin: 2px;
    +	padding: 0px;
    +	width: 24px;
    +	background-color: #f4f4f4;
    +	border-radius: 4px;
    +	-moz-border-radius: 4px;
    +	-webkit-border-radius: 4px;
    +	text-align: center;
    +	cursor: pointer;
    +}
    +.keypad-key[disabled] {
    +	border: 2px outset;
    +}
    +.keypad-key-down {
    +}
    +.keypad-spacebar {
    +	width: 164px;
    +}
    +.keypad-enter {
    +	width: 52px;
    +}
    +.keypad-clear, .keypad-back, .keypad-close, .keypad-shift {
    +	width: 52px;
    +	color: #fff;
    +	font-weight: bold;
    +}
    +.keypad-clear {
    +	background-color: #a00;
    +}
    +.keypad-back {
    +	background-color: #00a;
    +}
    +.keypad-close {
    +	background-color: #0a0;
    +}
    +.keypad-shift {
    +	background-color: #0aa;
    +}
    +.keypad-cover {
    +	display: none;
    +	display/**/: block;
    +	position: absolute;
    +	z-index: -1;
    +	filter: mask();
    +	top: -4px;
    +	left: -4px;
    +	width: 125px;
    +	height: 200px;
    +}
    Index: scripts/jquery/locale/ui.keypad-pt-BR.js
    ===================================================================
    --- scripts/jquery/locale/ui.keypad-pt-BR.js	(revision 0)
    +++ scripts/jquery/locale/ui.keypad-pt-BR.js	(revision 0)
    @@ -0,0 +1,18 @@
    +/* http://keith-wood.name/keypad.html
    +   brazilian portuguese initialisation for the jQuery keypad extension
    +   Written by Israel Rodriguez (yzraeu{at}gmail.com) July 2009. */
    +(function($) { // hide the namespace
    +    $.keypad.regional['pt-BR'] = {
    +        buttonText: '...', buttonStatus: 'Abrir o teclado',
    +        closeText: 'Fechar', closeStatus: 'Fechar o teclado',
    +        clearText: 'Limpar', clearStatus: 'Limpar todo o texto',
    +        backText: 'Apagar', backStatus: 'Apagar o caractere anterior',
    +        shiftText: 'Shift', shiftStatus: 'Ativar maiúsculas/minusculas',
    +        alphabeticLayout: $.keypad.qwertyAlphabetic,
    +        fullLayout: $.keypad.qwertyLayout,
    +        isAlphabetic: $.keypad.isAlphabetic,
    +        isNumeric: $.keypad.isNumeric,
    +        isRTL: false
    +    };
    +    $.keypad.setDefaults($.keypad.regional['pt-BR']);
    +})(jQuery);
    Index: scripts/jquery/locale/ui.keypad-de.js
    ===================================================================
    --- scripts/jquery/locale/ui.keypad-de.js	(revision 0)
    +++ scripts/jquery/locale/ui.keypad-de.js	(revision 0)
    @@ -0,0 +1,32 @@
    +/* http://keith-wood.name/keypad.html
    +   German localisation for the jQuery keypad extension
    +   Written by Uwe Jakobs(u.jakobs{at}imageco.de) September 2009. */
    +(function($) { // hide the namespace
    +
    +$.keypad.qwertzAlphabetic = ['qwertzuiopüß', 'asdfghjklöä', 'yxcvbnm'];
    +$.keypad.qwertzLayout = 
    +	['!"§$%&/()=?`' + $.keypad.BACK + $.keypad.HALF_SPACE + '$£€/',
    +	'<>°^@{[]}\\~´;:' + $.keypad.HALF_SPACE + '789*',
    +	$.keypad.qwertzAlphabetic[0] + '+*' +
    +	$.keypad.HALF_SPACE + '456-',
    +	$.keypad.HALF_SPACE + $.keypad.qwertzAlphabetic[1] +
    +	'#\'' + $.keypad.SPACE + '123+',
    +	'|' + $.keypad.qwertzAlphabetic[2] + 'µ,.-_' +
    +	$.keypad.SPACE + $.keypad.HALF_SPACE +'.0,=', 
    +	$.keypad.SHIFT + $.keypad.SPACE + $.keypad.SPACE_BAR +
    +	$.keypad.SPACE + $.keypad.SPACE + $.keypad.SPACE + $.keypad.CLEAR +
    +	$.keypad.SPACE + $.keypad.SPACE + $.keypad.HALF_SPACE + $.keypad.CLOSE];
    +$.keypad.regional['de'] = {
    +	buttonText: '...', buttonStatus: 'Öffnen',
    +	closeText: 'schließen', closeStatus: 'schließen',
    +	clearText: 'löschen', clearStatus: 'Gesamten Inhalt löschen',
    +	backText: 'zurück', backStatus: 'Letzte Eingabe löschen',
    +	shiftText: 'umschalten', shiftStatus: 'Zwischen Groß- und Kleinschreibung wechseln',
    +	alphabeticLayout: $.keypad.qwertzAlphabetic,
    +	fullLayout: $.keypad.qwertzLayout,
    +	isAlphabetic: $.keypad.isAlphabetic,
    +	isNumeric: $.keypad.isNumeric,
    +	isRTL: false};
    +$.keypad.setDefaults($.keypad.regional['de']);
    +
    +})(jQuery);
    Index: scripts/jquery/locale/ui.keypad-nl.js
    ===================================================================
    --- scripts/jquery/locale/ui.keypad-nl.js	(revision 0)
    +++ scripts/jquery/locale/ui.keypad-nl.js	(revision 0)
    @@ -0,0 +1,17 @@
    +/* http://keith-wood.name/keypad.html
    +   dutch initialisation for the jQuery keypad extension
    +   Written by Michiel Mussies (mail{at}webcrafts.nl) November 2009. */
    +(function($) { // hide the namespace
    +    $.keypad.regional['nl'] = {
    +        buttonText: '...', buttonStatus: 'Open',
    +        closeText: 'Sluit', closeStatus: 'Sluit',
    +        clearText: 'Wissen', clearStatus: 'Wis alle tekens',
    +        backText: 'Terug', backStatus: 'Wis laatste teken',
    +        shiftText: 'Shift', shiftStatus: 'Activeer hoofd-/kleine letters',
    +        alphabeticLayout: $.keypad.qwertyAlphabetic,
    +        fullLayout: $.keypad.qwertyLayout,
    +        isAlphabetic: $.keypad.isAlphabetic,
    +        isNumeric: $.keypad.isNumeric,
    +        isRTL: false};
    +    $.keypad.setDefaults($.keypad.regional['nl']);
    +})(jQuery);
    Index: scripts/jquery/locale/ui.keypad-es.js
    ===================================================================
    --- scripts/jquery/locale/ui.keypad-es.js	(revision 0)
    +++ scripts/jquery/locale/ui.keypad-es.js	(revision 0)
    @@ -0,0 +1,17 @@
    +/* http://keith-wood.name/keypad.html
    +   Spanish initialisation for the jQuery keypad extension
    +   Written by Cristhian Benitez (cbenitez@gmail.com). */
    +(function($) { // hide the namespace
    +$.keypad.regional['es'] = {
    +	buttonText: '...', buttonStatus: 'Abrir el teclado',
    +	closeText: 'Cerrar', closeStatus: 'Cerrar el teclado',
    +	clearText: 'Limpiar', clearStatus: 'Eliminar todo el texto',
    +	backText: 'Volver', backStatus: 'Borrar el caracter anterior',
    +	shiftText: 'Shift', shiftStatus: 'Cambiar mayusculas/minusculas',
    +	alphabeticLayout: $.keypad.qwertyAlphabetic,
    +	fullLayout: $.keypad.qwertyLayout,
    +	isAlphabetic: $.keypad.isAlphabetic,
    +	isNumeric: $.keypad.isNumeric,
    +	isRTL: false};
    +$.keypad.setDefaults($.keypad.regional['es']);
    +})(jQuery);
    Index: scripts/jquery/locale/ui.keypad-fr.js
    ===================================================================
    --- scripts/jquery/locale/ui.keypad-fr.js	(revision 0)
    +++ scripts/jquery/locale/ui.keypad-fr.js	(revision 0)
    @@ -0,0 +1,33 @@
    +/* http://keith-wood.name/keypad.html
    +   French initialisation for the jQuery keypad extension
    +   Written by Keith Wood (kbwood{at}iinet.com.au) August 2008. */
    +(function($) { // hide the namespace
    +
    +$.keypad.azertyAlphabetic = ['àâçéèêîôùû', 'azertyuiop', 'qsdfghjklm', 'wxcvbn'];
    +$.keypad.azertyLayout = ['&~#{([_@])}' + $.keypad.HALF_SPACE + '£$€',
    +	'<>|`°^!?\'"\\' + $.keypad.HALF_SPACE + '/*=',
    +	$.keypad.HALF_SPACE + $.keypad.azertyAlphabetic[0] + $.keypad.SPACE + '789',
    +	$.keypad.azertyAlphabetic[1] + '%' + $.keypad.HALF_SPACE + '456',
    +	$.keypad.HALF_SPACE + $.keypad.azertyAlphabetic[2] + $.keypad.SPACE + '123',
    +	'§' + $.keypad.azertyAlphabetic[3] + ',.;:' + $.keypad.HALF_SPACE + '-0+',
    +	$.keypad.SHIFT + $.keypad.SPACE_BAR + $.keypad.HALF_SPACE +
    +	$.keypad.BACK + $.keypad.CLEAR + $.keypad.CLOSE];
    +$.keypad.regional['fr'] = {
    +	buttonText: '...', buttonStatus: 'Ouvrir',
    +	closeText: 'Fermer', closeStatus: 'Fermer le pavé numérique',
    +	clearText: 'Effacer', clearStatus: 'Effacer la valeur',
    +	backText: 'Défaire', backStatus: 'Effacer la dernière touche',
    +	shiftText: 'Maj', shiftStatus: '',
    +	alphabeticLayout: $.keypad.azertyAlphabetic,
    +	fullLayout: $.keypad.azertyLayout,
    +	isAlphabetic: isAlphabetic,
    +	isNumeric: $.keypad.isNumeric,
    +	isRTL: false};
    +$.keypad.setDefaults($.keypad.regional['fr']);
    +
    +function isAlphabetic(ch) {
    +	return ($.keypad.isAlphabetic(ch) ||
    +		'áàäãâçéèëêíìïîóòöõôúùüû'.indexOf(ch) > -1);
    +}
    +
    +})(jQuery);
    Index: scripts/survey_runtime.js
    ===================================================================
    --- scripts/survey_runtime.js	(revision 9552)
    +++ scripts/survey_runtime.js	(working copy)
    @@ -12,6 +12,25 @@
         $(".question").find("select").each(function () {
             hookEvent($(this).attr('id'),'mousewheel',noScroll);
         });
    +        var kp = $("input.num-keypad");
    +        if(kp.length) kp.keypad({showAnim: 'fadeIn', keypadOnly: false});
    +        kp = $("input.text-keypad");
    +        if(kp.length)
    +        {
    +                var spacer = $.keypad.HALF_SPACE;
    +                for(var i = 0; i != 8; ++i) spacer += $.keypad.SPACE;
    +		kp.keypad({
    +			showAnim: 'fadeIn',
    +			keypadOnly: false,
    +			layout: [
    +                                spacer + $.keypad.CLEAR + $.keypad.CLOSE, $.keypad.SPACE,
    +			        '!@#$%^&*()_=' + $.keypad.HALF_SPACE + $.keypad.BACK,
    +			        $.keypad.HALF_SPACE + '`~[]{}<>\\|/' + $.keypad.SPACE + $.keypad.SPACE + '789',
    +			        'qwertyuiop\'"' + $.keypad.HALF_SPACE + $.keypad.SPACE + '456',
    +			        $.keypad.HALF_SPACE + 'asdfghjkl;:' + $.keypad.SPACE + $.keypad.SPACE + '123',
    +			        $.keypad.SPACE + 'zxcvbnm,.?' + $.keypad.SPACE + $.keypad.SPACE + $.keypad.HALF_SPACE + '-0+',
    +			        $.keypad.SHIFT + $.keypad.SPACE_BAR + $.keypad.ENTER]});
    +        }
     });
     
     Array.prototype.push = function()
    Index: images/keypad.png
    ===================================================================
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: images/keypad.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Index: common_functions.php
    ===================================================================
    --- common_functions.php	(revision 9552)
    +++ common_functions.php	(working copy)
    @@ -7956,4 +7956,19 @@
         return $bAnsw;
     }
     
    +/**
    + * Include Keypad headers
    + */
    +function vIncludeKeypad()
    +{
    +    global $js_header_includes, $css_header_includes, $clang;
    +
    +    $js_header_includes[] = '/scripts/jquery/jquery.keypad.min.js';
    +    if ($clang->langcode !== 'en')
    +    {
    +        $js_header_includes[] = '/scripts/jquery/locale/ui.keypad-'.$clang->langcode.'.js';
    +    }
    +    $css_header_includes[] = '/scripts/jquery/css/jquery.keypad.alt.css';
    +}
    +
     // Closing PHP tag intentionally left out - yes, it is okay
    Index: qanda.php
    ===================================================================
    --- qanda.php	(revision 9552)
    +++ qanda.php	(working copy)
    @@ -3926,7 +3926,7 @@
     // ---------------------------------------------------------------
     function do_multipleshorttext($ia)
     {
    -    global $dbprefix, $clang;
    +    global $dbprefix, $clang, $thissurvey;
     
         if ($ia[8] == 'Y')
         {
    @@ -3980,6 +3980,16 @@
             $suffix = '';
         }
     
    +    if ($thissurvey['nokeyboard']=='Y')
    +    {
    +        vIncludeKeypad();
    +        $kpclass = "text-keypad";
    +    }
    +    else
    +    {
    +        $kpclass = "";
    +    }
    +
         if ($qidattributes['random_order']==1) {
             $ansquery = "SELECT * FROM {$dbprefix}questions WHERE parent_qid=$ia[0]  AND language='".$_SESSION['s_lang']."' ORDER BY ".db_random();
         }
    @@ -4039,7 +4049,7 @@
                     $answer_main .= "\t<li>\n"
                     . "<label for=\"answer$myfname\">{$ansrow['question']}</label>\n"
                     . "\t<span>\n".$prefix."\n".'
    -				<textarea class="textarea" name="'.$myfname.'" id="answer'.$myfname.'" 
    +				<textarea class="textarea '.$kpclass.'" name="'.$myfname.'" id="answer'.$myfname.'" 
     				rows="'.$drows.'" cols="'.$tiwidth.'" onkeyup="textLimit(\'answer'.$ia[1].'\', '.$maxsize.'); '.$checkconditionFunction.'(this.value, this.name, this.type);" '.$numbersonly.'>';
     
                     if($label_width < strlen(trim(strip_tags($ansrow['question']))))
    @@ -4068,7 +4078,7 @@
                     if ($ansrow['question'] == "") {$ansrow['question'] = "&nbsp;";}
                     $answer_main .= "\t<li>\n"
                     . "<label for=\"answer$myfname\">{$ansrow['question']}</label>\n"
    -                . "\t<span>\n".$prefix."\n".'<input class="text" type="text" size="'.$tiwidth.'" name="'.$myfname.'" id="answer'.$myfname.'" value="';
    +                . "\t<span>\n".$prefix."\n".'<input class="text '.$kpclass.'" type="text" size="'.$tiwidth.'" name="'.$myfname.'" id="answer'.$myfname.'" value="';
     
                     if($label_width < strlen(trim(strip_tags($ansrow['question']))))
                     {
    @@ -4102,7 +4112,7 @@
     // ---------------------------------------------------------------
     function do_multiplenumeric($ia)
     {
    -    global $dbprefix, $clang, $js_header_includes, $css_header_includes;
    +    global $dbprefix, $clang, $js_header_includes, $css_header_includes, $thissurvey;
     
         if ($ia[8] == 'Y')
         {
    @@ -4190,6 +4200,16 @@
             $suffix = '';
         }
     
    +    if ($thissurvey['nokeyboard']=='Y')
    +    {
    +        vIncludeKeypad();
    +        $kpclass = "num-keypad";
    +    }
    +    else
    +    {
    +        $kpclass = "";
    +    }
    +
         if(!empty($numbersonlyonblur))
         {
             $numbersonly .= ' onblur="'.implode(';', $numbersonlyonblur).'"';
    @@ -4356,7 +4376,7 @@
     
                 if ($slider_layout === false)
                 {
    -                $answer_main .= "<span class=\"input\">\n\t".$prefix."\n\t<input class=\"text\" type=\"text\" size=\"".$tiwidth.'" name="'.$myfname.'" id="answer'.$myfname.'" value="';
    +                $answer_main .= "<span class=\"input\">\n\t".$prefix."\n\t<input class=\"text $kpclass\" type=\"text\" size=\"".$tiwidth.'" name="'.$myfname.'" id="answer'.$myfname.'" value="';
                     if (isset($_SESSION[$myfname]))
                     {
                         $answer_main .= $_SESSION[$myfname];
    @@ -4587,7 +4607,7 @@
     // ---------------------------------------------------------------
     function do_numerical($ia)
     {
    -    global $clang;
    +    global $clang, $thissurvey;
     
         if ($ia[8] == 'Y')
         {
    @@ -4642,8 +4662,18 @@
             $acomma=".,";
         }
     
    +    if ($thissurvey['nokeyboard']=='Y')
    +    {
    +        vIncludeKeypad();
    +        $kpclass = "num-keypad";
    +    }
    +    else
    +    {
    +        $kpclass = "";
    +    }
    +
         // --> START NEW FEATURE - SAVE
    -    $answer = "<p class=\"question\">\n\t$prefix\n\t<input class=\"text\" type=\"text\" size=\"$tiwidth\" name=\"$ia[1]\" "
    +    $answer = "<p class=\"question\">\n\t$prefix\n\t<input class=\"text $kpclass\" type=\"text\" size=\"$tiwidth\" name=\"$ia[1]\" "
         . "id=\"answer{$ia[1]}\" value=\"{$_SESSION[$ia[1]]}\" alt=\"".$clang->gT('Answer')."\" onkeypress=\"return goodchars(event,'-0123456789{$acomma}')\" onchange='$checkconditionFunction(this.value, this.name, this.type)'"
         . "maxlength=\"{$maxsize}\" />\n\t{$suffix}\n</p>\n";
         if ($qidattributes['hide_tip']==0)
    @@ -4664,7 +4694,7 @@
     // ---------------------------------------------------------------
     function do_shortfreetext($ia)
     {
    -    global $clang, $js_header_includes;
    +    global $clang, $js_header_includes, $thissurvey;
     
         if ($ia[8] == 'Y')
         {
    @@ -4715,6 +4745,15 @@
         {
             $suffix = '';
         }
    +    if ($thissurvey['nokeyboard']=='Y')
    +    {
    +        vIncludeKeypad();
    +        $kpclass = "text-keypad";
    +    }
    +    else
    +    {
    +        $kpclass = "";
    +    }
         if (trim($qidattributes['display_rows'])!='')
         {
             //question attribute "display_rows" is set -> we need a textarea to be able to show several rows
    @@ -4747,7 +4786,7 @@
             //NEW: textarea instead of input=text field
     
             // --> START NEW FEATURE - SAVE
    -        $answer .= '<textarea class="textarea" name="'.$ia[1].'" id="answer'.$ia[1].'" '
    +        $answer .= '<textarea class="textarea '.$kpclass.'" name="'.$ia[1].'" id="answer'.$ia[1].'" '
             .'rows="'.$drows.'" cols="'.$tiwidth.'" onkeyup="textLimit(\'answer'.$ia[1].'\', '.$maxsize.'); '.$checkconditionFunction.'(this.value, this.name, this.type);" '.$numbersonly.'>';
             // --> END NEW FEATURE - SAVE
     
    @@ -4758,7 +4797,7 @@
         else
         {
             //no question attribute set, use common input text field
    -        $answer = "<p class=\"question\">\n\t$prefix\n\t<input class=\"text\" type=\"text\" size=\"$tiwidth\" name=\"$ia[1]\" id=\"answer$ia[1]\" value=\""
    +        $answer = "<p class=\"question\">\n\t$prefix\n\t<input class=\"text $kpclass\" type=\"text\" size=\"$tiwidth\" name=\"$ia[1]\" id=\"answer$ia[1]\" value=\""
             .htmlspecialchars($_SESSION[$ia[1]],ENT_QUOTES,'UTF-8')
             ."\" maxlength=\"$maxsize\" onkeyup=\"$checkconditionFunction(this.value, this.name, this.type)\" $numbersonly />\n\t$suffix\n</p>\n";
         }
    Index: admin/database.php
    ===================================================================
    --- admin/database.php	(revision 9552)
    +++ admin/database.php	(working copy)
    @@ -1075,6 +1075,7 @@
                                 'showwelcome'=>$_POST['showwelcome'],
                                 'allowprev'=>$_POST['allowprev'],
                                 'allowjumps'=>$_POST['allowjumps'],
    +                            'nokeyboard'=>$_POST['nokeyboard'],
                                 'showprogress'=>$_POST['showprogress'],
                                 'listpublic'=>$_POST['public'],
                                 'htmlemail'=>$_POST['htmlemail'],
    @@ -1366,6 +1367,7 @@
                                 'showwelcome'=>$_POST['showwelcome'],
                                 'allowprev'=>$_POST['allowprev'],
                                 'allowjumps'=>$_POST['allowjumps'],
    +                            'nokeyboard'=>$_POST['nokeyboard'],
                                 'showprogress'=>$_POST['showprogress'],
                                 'printanswers'=>$_POST['printanswers'],
             //                            'usetokens'=>$_POST['usetokens'],
    Index: admin/install/create-mysql.sql
    ===================================================================
    --- admin/install/create-mysql.sql	(revision 9552)
    +++ admin/install/create-mysql.sql	(working copy)
    @@ -280,6 +280,7 @@
       `showprogress` char(1) default 'Y',
       `allowjumps` char(1) default 'N',
       `navigationdelay` tinyint(2) default '0',
    +  `nokeyboard` char(1) default 'N',
        PRIMARY KEY(`sid`)
     ) ENGINE=$databasetabletype CHARACTER SET utf8 COLLATE utf8_unicode_ci;
     
    Index: admin/install/create-mssqlnative.sql
    ===================================================================
    --- admin/install/create-mssqlnative.sql	(revision 9552)
    +++ admin/install/create-mssqlnative.sql	(working copy)
    @@ -300,6 +300,7 @@
       [showprogress] char(1) default 'N',
       [allowjumps] char(1) default 'N',
       [navigationdelay] tinyint default '0',
    +  [nokeyboard] char(1) default 'N',
       
       PRIMARY KEY  ([sid])
     ) 
    Index: admin/install/create-postgres.sql
    ===================================================================
    --- admin/install/create-postgres.sql	(revision 9552)
    +++ admin/install/create-postgres.sql	(working copy)
    @@ -304,7 +304,8 @@
     	tokenlength smallint DEFAULT '15',
         showprogress character(1) DEFAULT 'N'::bpchar,
         allowjumps character(1) DEFAULT 'N'::bpchar,
    -    navigationdelay smallint DEFAULT '0'
    +    navigationdelay smallint DEFAULT '0',
    +    nokeyboard character(1) DEFAULT 'N'::bpchar
     );
     
     ALTER TABLE ONLY prefix_surveys ADD CONSTRAINT prefix_surveys_pkey PRIMARY KEY (sid);
    Index: admin/install/create-mssql.sql
    ===================================================================
    --- admin/install/create-mssql.sql	(revision 9552)
    +++ admin/install/create-mssql.sql	(working copy)
    @@ -291,6 +291,7 @@
       [showprogress] char(1) default 'N',
       [allowjumps] char(1) default 'N',
       [navigationdelay] tinyint default '0',
    +  [nokeyboard] char(1) default 'N',
       
       PRIMARY KEY  ([sid])
     ) 
    Index: admin/editsurveysettings.php
    ===================================================================
    --- admin/editsurveysettings.php	(revision 9552)
    +++ admin/editsurveysettings.php	(working copy)
    @@ -332,6 +332,17 @@
             $editsurvey .= ">".$clang->gT("No")."</option>\n"
                     . "</select></li>\n";
     
    +        //No Keyboard
    +        $editsurvey .= "<li><label for='nokeyboard'>".$clang->gT("Keyboard-less operation")."</label>\n"
    +                . "<select id='nokeyboard' name='nokeyboard'>\n"
    +                . "<option value='Y'";
    +        if (!isset($esrow['nokeyboard']) || !$esrow['nokeyboard'] || $esrow['nokeyboard'] == "Y") {$editsurvey .= " selected='selected'";}
    +        $editsurvey .= ">".$clang->gT("Yes")."</option>\n"
    +                . "<option value='N'";
    +        if (isset($esrow['nokeyboard']) && $esrow['nokeyboard'] == "N") {$editsurvey .= " selected='selected'";}
    +        $editsurvey .= ">".$clang->gT("No")."</option>\n"
    +                . "</select></li>\n";
    +
     	//Show Progress
     	$editsurvey .= "<li><label for='showprogress'>".$clang->gT("Show progress bar")."</label>\n"
                     . "<select id='showprogress' name='showprogress'>\n"
    Index: admin/update/upgrade-mysql.php
    ===================================================================
    --- admin/update/upgrade-mysql.php	(revision 9552)
    +++ admin/update/upgrade-mysql.php	(working copy)
    @@ -407,6 +407,7 @@
             modify_database("", "ALTER TABLE `prefix_surveys` ADD `showprogress` char(1) default 'Y'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE `prefix_surveys` ADD `allowjumps` char(1) default 'N'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE `prefix_surveys` ADD `navigationdelay` tinyint(2) default '0'"); echo $modifyoutput; flush();
    +        modify_database("", "ALTER TABLE `prefix_surveys` ADD `nokeyboard` char(1) default 'N'"); echo $modifyoutput; flush();
             modify_database("", "CREATE TABLE `prefix_survey_permissions` (
                                     `sid` int(10) unsigned NOT NULL,
                                     `uid` int(10) unsigned NOT NULL,
    Index: admin/update/upgrade-mssqlnative.php
    ===================================================================
    --- admin/update/upgrade-mssqlnative.php	(revision 9552)
    +++ admin/update/upgrade-mssqlnative.php	(working copy)
    @@ -422,6 +422,7 @@
             modify_database("", "ALTER TABLE [prefix_surveys] ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE [prefix_surveys] ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE [prefix_surveys] ADD navigationdelay tinyint NOT NULL default '0'"); echo $modifyoutput; flush();
    +        modify_database("", "ALTER TABLE [prefix_surveys] ADD nokeyboard CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
             modify_database("", "CREATE TABLE [prefix_survey_permissions] (
                                 [sid] INT NOT NULL,         
                                 [uid] INT NOT NULL,         
    Index: admin/update/upgrade-postgres.php
    ===================================================================
    --- admin/update/upgrade-postgres.php	(revision 9552)
    +++ admin/update/upgrade-postgres.php	(working copy)
    @@ -249,6 +249,7 @@
             modify_database("", "ALTER TABLE prefix_surveys ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE prefix_surveys ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE prefix_surveys ADD navigationdelay smallint NOT NULL default '0'"); echo $modifyoutput; flush();
    +        modify_database("", "ALTER TABLE prefix_surveys ADD nokeyboard char(1) default 'N'"); echo $modifyoutput; flush();
             modify_database("", "CREATE TABLE prefix_survey_permissions (
                                 sid integer DEFAULT 0 NOT NULL,
                                 uid integer DEFAULT 0 NOT NULL,
    Index: admin/update/upgrade-mssql.php
    ===================================================================
    --- admin/update/upgrade-mssql.php	(revision 9552)
    +++ admin/update/upgrade-mssql.php	(working copy)
    @@ -425,6 +425,7 @@
             modify_database("", "ALTER TABLE [prefix_surveys] ADD showprogress CHAR(1) NULL default 'Y'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE [prefix_surveys] ADD allowjumps CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
             modify_database("", "ALTER TABLE [prefix_surveys] ADD navigationdelay tinyint default '0'"); echo $modifyoutput; flush();
    +        modify_database("", "ALTER TABLE [prefix_surveys] ADD nokeyboard CHAR(1) NULL default 'N'"); echo $modifyoutput; flush();
             modify_database("", "CREATE TABLE [prefix_survey_permissions] (
                                 [sid] INT NOT NULL,         
                                 [uid] INT NOT NULL,         
    Index: index.php
    ===================================================================
    --- index.php	(revision 9552)
    +++ index.php	(working copy)
    @@ -2298,6 +2298,16 @@
         // TOKEN REQUIRED BUT NO TOKEN PROVIDED
         if ($tokensexist == 1 && !returnglobal('token'))
         {
    +        if ($thissurvey['nokeyboard']=='Y')
    +        {
    +            vIncludeKeypad();
    +            $kpclass = "text-keypad";
    +        }
    +        else
    +        {
    +            $kpclass = "";
    +        }
    +
             // DISPLAY REGISTER-PAGE if needed
             // DISPLAY CAPTCHA if needed
             sendcacheheaders();
    @@ -2319,7 +2329,7 @@
     	        <form id='tokenform' method='get' action='{$publicurl}/index.php'>
                     <ul>
                     <li>
    -            <label for='token'>".$clang->gT("Token")."</label><input class='text' id='token' type='text' name='token' />";
    +            <label for='token'>".$clang->gT("Token")."</label><input class='text $kpclass' id='token' type='text' name='token' />";
                 
                 echo "<input type='hidden' name='sid' value='".$surveyid."' id='sid' />
     				<input type='hidden' name='lang' value='".$templang."' id='lang' />";
    
    diff file icon svn-patch-2.diff (46,430 bytes) 2010-11-29 11:54 +

-Relationships
+Relationships

-Notes

~13089

c_schmitz (administrator)

Can you please provide the patch as a subversion patch (svn diff) against our 1.91 development version at the subversion branch at :
https://limesurvey.svn.sourceforge.net/svnroot/limesurvey/source/limesurvey_dev

Thank you!

~13450

DenisChenu (developer)

Maybe it's a good idea to add this in a template version ?

I think it can be add in default-kbless template. some js/css file and template.js modification.

~13451

c_schmitz (administrator)

rather not. I want don't want to maintain another template. Also having this feature configurable from the UI is superior than having it in the template.

~13661

user9586

Patch updated.

~13662

user9586

Sorry for the double-post, the last patch was missing new files.

~13670

c_schmitz (administrator)

Great patch - thank you very much!

~13672

user9586

svn is missing the new files contained in the patch in the scripts directory.

~13673

c_schmitz (administrator)

Last edited: 2010-11-30 16:06

View 2 revisions

I committed everything I got. Can you add another patch file with the missing files? Which files you think are missing?

~13674

user9586

It's in the patch already (see the first file: scripts/jquery/jquery.keypad.min.js). Maybe you forgot to add them before the commit?

~13675

c_schmitz (administrator)

Yes, and I added them to SVN for sure. Update your local subversion again.

~13676

user9586

You were right. I don't know why, but 'svn up' and 'svn status' both reported that the repository was updated, but those files were still missing.

I removed 'scripts' and forced an updated to get the files...

Anyway, sorry for the noise.

~13677

c_schmitz (administrator)

np ;)
+Notes

-Issue History
Date Modified Username Field Change
2010-10-05 20:02 user9586 New Issue
2010-10-05 20:02 user9586 File Added: patch.diff
2010-10-11 23:55 c_schmitz Status new => feedback
2010-10-11 23:55 c_schmitz Note Added: 13089
2010-11-07 16:11 DenisChenu Note Added: 13450
2010-11-07 20:00 c_schmitz Note Added: 13451
2010-11-07 20:05 c_schmitz Assigned To => c_schmitz
2010-11-07 20:05 c_schmitz Status feedback => assigned
2010-11-29 11:52 user9586 File Added: svn-patch.diff
2010-11-29 11:52 user9586 Note Added: 13661
2010-11-29 11:54 user9586 File Added: svn-patch-2.diff
2010-11-29 11:55 user9586 Note Added: 13662
2010-11-30 15:06 c_schmitz File Deleted: patch.diff
2010-11-30 15:06 c_schmitz File Deleted: svn-patch.diff
2010-11-30 15:24 c_schmitz Note Added: 13670
2010-11-30 15:24 c_schmitz Status assigned => resolved
2010-11-30 15:24 c_schmitz Fixed in Version => 1.91
2010-11-30 15:24 c_schmitz Resolution open => fixed
2010-11-30 16:00 user9586 Note Added: 13672
2010-11-30 16:00 user9586 Status resolved => feedback
2010-11-30 16:00 user9586 Resolution fixed => reopened
2010-11-30 16:05 c_schmitz Note Added: 13673
2010-11-30 16:06 c_schmitz Note Edited: 13673 View Revisions
2010-11-30 16:08 user9586 Note Added: 13674
2010-11-30 16:08 user9586 Status feedback => assigned
2010-11-30 16:28 c_schmitz Note Added: 13675
2010-11-30 16:40 user9586 Note Added: 13676
2010-11-30 18:06 c_schmitz Note Added: 13677
2010-11-30 18:06 c_schmitz Status assigned => resolved
2010-11-30 18:06 c_schmitz Resolution reopened => fixed
2010-12-14 13:02 c_schmitz Status resolved => closed
+Issue History