The CreatorCon Call for Content is officially open! Get started here.

Keyboard Shortcuts

gaidem
ServiceNow Employee
ServiceNow Employee

I have been asked to have keyboard shortcut functionality in the tool.

Thanks to this site: http://www.openjs.com/scripts/events/keyboard_shortcuts/ I've been able to do this with a UI script containing the code below and Client Scripts.


Here is an example client script using this:



function onLoad() {
//Type appropriate comment here, and begin script below
shortcut.add("Ctrl+B",function() {
alert("Bold");
});

}



UI Script
Global


/**
* http://www.openjs.com/scripts/events/keyboard_shortcuts/
* Version : 2.01.B
* By Binny V A
* License : BSD
*/
shortcut = {
'all_shortcuts':{},//All the shortcuts are stored in this array
'add': function(shortcut_combination,callback,opt) {
//Provide a set of default options
var default_options = {
'type':'keydown',
'propagate':false,
'disable_in_input':false,
'target':document,
'keycode':false
}
if(!opt) opt = default_options;
else {
for(var dfo in default_options) {
if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
}
}

var ele = opt.target;
if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
var ths = this;
shortcut_combination = shortcut_combination.toLowerCase();

//The function to be called at keypress
var func = function(e) {
e = e || window.event;

if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
var element;
if(e.target) element=e.target;
else if(e.srcElement) element=e.srcElement;
if(element.nodeType==3) element=element.parentNode;

if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
}

//Find Which key is pressed
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code).toLowerCase();

if(code == 188) character=","; //If the user presses , when the type is onkeydown
if(code == 190) character="."; //If the user presses , when the type is onkeydown

var keys = shortcut_combination.split("+");
//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
var kp = 0;

//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
var shift_nums = {
"`":"~",
"1":"!",
"2":"@",
"3":"#",
"4":"$",
"5":"%",
"6":"^",
"7":"&",
"8":"*",
"9":"(",
"0":")",
"-":"_",
"=":"+",
";":":",
"'":"\"",
",":"<",
".":">",
"/":"?",
"\\":"|"
}
//Special Keys - and their codes
var special_keys = {
'esc':27,
'escape':27,
'tab':9,
'space':32,
'return':13,
'enter':13,
'backspace':8,

'scrolllock':145,
'scroll_lock':145,
'scroll':145,
'capslock':20,
'caps_lock':20,
'caps':20,
'numlock':144,
'num_lock':144,
'num':144,

'pause':19,
'break':19,

'insert':45,
'home':36,
'delete':46,
'end':35,

'pageup':33,
'page_up':33,
'pu':33,

'pagedown':34,
'page_down':34,
'pd':34,

'left':37,
'up':38,
'right':39,
'down':40,

'f1':112,
'f2':113,
'f3':114,
'f4':115,
'f5':116,
'f6':117,
'f7':118,
'f8':119,
'f9':120,
'f10':121,
'f11':122,
'f12':123
}

var modifiers = {
shift: { wanted:false, pressed:false},
ctrl : { wanted:false, pressed:false},
alt : { wanted:false, pressed:false},
meta : { wanted:false, pressed:false}//Meta is Mac specific
};

if(e.ctrlKey)modifiers.ctrl.pressed = true;
if(e.shiftKey)modifiers.shift.pressed = true;
if(e.altKey)modifiers.alt.pressed = true;
if(e.metaKey) modifiers.meta.pressed = true;

for(var i=0; k=keys<i>,i<keys.length; i++) {
//Modifiers
if(k == 'ctrl' || k == 'control') {
kp++;
modifiers.ctrl.wanted = true;

} else if(k == 'shift') {
kp++;
modifiers.shift.wanted = true;

} else if(k == 'alt') {
kp++;
modifiers.alt.wanted = true;
} else if(k == 'meta') {
kp++;
modifiers.meta.wanted = true;
} else if(k.length > 1) { //If it is a special key
if(special_keys[k] == code) kp++;

} else if(opt['keycode']) {
if(opt['keycode'] == code) kp++;

} else { //The special keys did not match
if(character == k) kp++;
else {
if(shift_nums[character] &amp;&amp; e.shiftKey) { //Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if(character == k) kp++;
}
}
}
}

if(kp == keys.length &amp;&amp;
modifiers.ctrl.pressed == modifiers.ctrl.wanted &amp;&amp;
modifiers.shift.pressed == modifiers.shift.wanted &amp;&amp;
modifiers.alt.pressed == modifiers.alt.wanted &amp;&amp;
modifiers.meta.pressed == modifiers.meta.wanted) {
callback(e);

if(!opt['propagate']) { //Stop the event
//e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = false;

//e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
}
}
this.all_shortcuts[shortcut_combination] = {
'callback':func,
'target':ele,
'event': opt['type']
};
//Attach the function with the event
if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
else ele['on'+opt['type']] = func;
},

//Remove the shortcut - just specify the shortcut and I will remove the binding
'remove':function(shortcut_combination) {
shortcut_combination = shortcut_combination.toLowerCase();
var binding = this.all_shortcuts[shortcut_combination];
delete(this.all_shortcuts[shortcut_combination])
if(!binding) return;
var type = binding['event'];
var ele = binding['target'];
var callback = binding['callback'];

if(ele.detachEvent) ele.detachEvent('on'+type, callback);
else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
else ele['on'+type] = false;
}
}

Supported keys are:
All alpha/numeric keys - abc...xyz,01..89
Special Characters - Every special character on a standard keyboard can be accessed.
Special Keys...
Tab
Space
Return
Enter
Backspace
Scroll_lock
Caps_lock
Num_lock
Pause
Insert
Home
Delete
End
Page_up
Page_down
Left
Up
Right
Down
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12

11 REPLIES 11

gaidem
ServiceNow Employee
ServiceNow Employee

Here's what I've implemented so far:




function onLoad() {
//Type appropriate comment here, and begin script below
if(!g_form.isNewRecord()){
var is_processing_p_key = false;
shortcut.add('p', function() {
is_processing_p_key = true;
setTimeout(function() { is_processing_p_key = false; }, 500);
}, {disable_in_input: true});
//assign to me
shortcut.add("M",function() {
assign_to_me();
},{disable_in_input: true});
//resolve
shortcut.add("Shift+R",function() {
resolve_ticket();
},{disable_in_input: true});
//pending client
shortcut.add("C",function() {
if (is_processing_p_key==false)
client.toggle();
pend_client();
},{disable_in_input: true});

//pending vendor
shortcut.add("3",function() {
if (is_processing_p_key==false)
client.toggle();
pend_vendor();
},{disable_in_input: true});


function assign_to_me(){
var usrGrp = new GlideRecord('sys_user');
usrGrp.addQuery('sys_id',g_user.userID);
usrGrp.query();
if(usrGrp.next()){
g_form.setValue('assigned_to',g_user.userID);
g_form.setValue('assignment_group',usrGrp.u_primary_group);
}}

function resolve_ticket(){
g_form.setValue('incident_state','6');
}

function pend_client(){
g_form.setValue('incident_state','8');
g_form.setValue('u_hold_code','Pending Client');
}

function pend_vendor(){
g_form.setValue('incident_state','8');
g_form.setValue('u_hold_code','Pending Vendor');
}
}}


Torbjorn Skantz
Tera Contributor

Great solution!

I had som e issues with the script for N+I as it would sometimes open up in the navigator frame. If you changed the window.location to parent.gsft_main.location.href the new record will always open up in the main frame.

My altered UI script that lets a user open a new ticket by pressing Ctrl+Q:

shortcut.add('Ctrl+q', function() {
//Use parent location to avoid new url being loaded in the menu
parent.gsft_main.location.href = "/ticket.do?sys_id=-1&sysparm_query=active=true&sysparm_stack=ticket_list.do?sysparm_query=active=true";
});


tomas_larsson
Kilo Explorer

Has anyone tried this on the Berlin release? I am not able to get it working....

Thanks,
Tomas


Thummala_Murthy
Kilo Contributor

Hi ,
Can you please help to write a script onchange of disallowing special chars and allow only Alpha Numeric .

Thnx
Murthy


Client side number validation

That post contains client side code for testing numeric but you can easily modify it to test for alphanumeric.