Menu hotkeys system implementation.
authorJanusz Dobrowolski <janusz@frontaccounting.eu>
Mon, 6 Oct 2008 17:02:45 +0000 (17:02 +0000)
committerJanusz Dobrowolski <janusz@frontaccounting.eu>
Mon, 6 Oct 2008 17:02:45 +0000 (17:02 +0000)
15 files changed:
includes/page/header.inc
includes/ui/ui_controls.inc
includes/ui/ui_input.inc
js/JsHttpRequest.js
js/inserts.js
js/utils.js
reporting/includes/reports_classes.inc
sales/manage/customers.php
sales/sales_order_entry.php
themes/aqua/default.css
themes/aqua/renderer.php
themes/cool/default.css
themes/cool/renderer.php
themes/default/default.css
themes/default/renderer.php

index 97529207827b49f15a4b97c41126d9dec924d57b..2ab707cc55e9d14419c6dcfd6d4312e8d56db0ed 100644 (file)
@@ -17,7 +17,7 @@ function help_url($title, $app)
        }
        elseif ($title==_("Main Menu"))
        {
-               $help_page_url = $applications[$app];
+               $help_page_url = access_string($applications[$app], true);
        }
        else
        {
index 1883ba2aeafc12ebdff7334f7161f8ddb0aa1ac8..2693b07943db5c0caa04a5479ee328f995800f8d 100644 (file)
@@ -59,6 +59,27 @@ function meta_forward($forward_to, $params="")
 }
 
 //-----------------------------------------------------------------------------------
+// Find and replace hotkey marker.
+// if $clean == true marker is removed and clean label is returned 
+// (for use in wiki help system), otherwise result is array of label 
+// with underlined hotkey letter and access property string.
+//
+function access_string($label, $clean=false)
+{
+       $access = '';
+       $slices = array();
+
+       if (preg_match('/(.*)&([a-zA-Z0-9])(.*)/', $label, $slices))    
+       {
+               $label = $clean ? $slices[1].$slices[2].$slices[3] :
+                       $slices[1].'<u>'.$slices[2].'</u>'.$slices[3];
+               $access = " accesskey='".strtoupper($slices[2])."'";
+       }
+       
+       $label = str_replace( '&&', '&', $label);
+
+       return $clean ? $label : array($label, $access);
+}
 
 function hyperlink_back($center=true)
 {
@@ -73,9 +94,10 @@ function hyperlink_back($center=true)
 
 function hyperlink_no_params($target, $label, $center=true)
 {
+       $pars = access_string($label);
        if ($center)
                echo "<br><center>";
-       echo "<a href='$target?=" . SID . "'>$label</a>\n";
+       echo "<a href='$target?=" . SID . "'$pars[1]>$pars[0]</a>\n";
        if ($center)
                echo "</center>";
 }
@@ -91,9 +113,10 @@ function hyperlink_no_params_td($target, $label)
 
 function hyperlink_params($target, $label, $params, $center=true)
 {
+       $pars = access_string($label);
        if ($center)
                echo "<br><center>";
-       echo "<a href='$target?$params'>$label</a>\n";
+       echo "<a href='$target?$params'$pars[1]>$pars[0]</a>\n";
        if ($center)
                echo "</center>";
 }
@@ -109,9 +132,10 @@ function hyperlink_params_td($target, $label, $params)
 
 function hyperlink_params_separate($target, $label, $params, $center=false)
 {
+       $pars = access_string($label);
        if ($center)
                echo "<br><center>";
-       echo "<a target='_blank' href='$target?$params" . SID . "'>$label</a>\n";
+       echo "<a target='_blank' href='$target?$params" . SID . "'$pars[1]>$pars[0]</a>\n";
        if ($center)
                echo "</center>";
 }
index 3c2151bc34a531eded03040b72e95b7576123300..3817bc9f2606f817b1d12513d6af34b208f803cd 100644 (file)
@@ -94,50 +94,45 @@ function hidden($name, $value=null, $echo=true)
                return $ret;
 }
 
-//---------------------------------------------------------------------------------
-//     Submit button.
-//     $async parameter can have 3 values:
-//             null - fallback button not visible in js enabled mode
-//             false - normal submit via form action
-//             true  - when js is on submition via ajax call
-//             'process' - ditto with processing indicator in msgbox
-//
-function submit($name, $value, $echo=true, $title=false, $async=false)
+function submit($name, $value, $echo=true, $title=false, $async=false, $icon=false)
 {
-
+       global $path_to_root;
+       
        default_focus($name);
-       $submit_str = "<input type=\"submit\" class=\""
+       $submit_str = "<button class=\""
            .($async ? 'ajaxsubmit' : 'inputsubmit')
                ."\""
                .($async === null ? (in_ajax() ? " style='display:none;'" : ' aspect="fallback"' ): 
                        ($async === 'process' ? 'aspect="process"' : '') )
-           ." name=\"$name\"  id=\"$name\" value=\"$value\""
+           ." name=\"$name\"  id=\"$name\" " //value=\"$value\""
            .($title ? " title='$title'" : '')
-           .">\n";
+           ."><span>$value</span>"
+               .($icon ? "<img src='$path_to_root/themes/default/images/$icon'>" : '')
+               ."</button>\n";
        if ($echo)
                echo $submit_str;
        else
                return $submit_str;
 }
 
-function submit_center($name, $value, $echo=true, $title=false, $async=false)
+function submit_center($name, $value, $echo=true, $title=false, $async=false, $icon=false)
 {
        echo "<center>";
-       submit($name, $value, $echo, $title, $async);
+       submit($name, $value, $echo, $title, $async, $icon);
        echo "</center>";
 }
 
-function submit_center_first($name, $value, $title=false, $async=false)
+function submit_center_first($name, $value, $title=false, $async=false, $icon=false)
 {
        echo "<center>";
-       submit($name, $value, true, $title, $async);
+       submit($name, $value, true, $title, $async, $icon);
        echo "&nbsp;";
 }
 
-function submit_center_last($name, $value, $title=false, $async=false)
+function submit_center_last($name, $value, $title=false, $async=false, $icon=false)
 {
        echo "&nbsp;";
-       submit($name, $value, true, $title, $async);
+       submit($name, $value, true, $title, $async, $icon);
        echo "</center>";
 }
 
index d89ff4b2ce756a056af255d7826ba9ce903df857..654362dc2aeaf863115ebe4626f4cd1b6c268297 100644 (file)
@@ -255,7 +255,7 @@ function JsHttpRequest() {
                     if (tn == 'FORM') {
                         // FORM itself is passed.
                         formAdded = true;
-                    } else if (tn == 'INPUT' || tn == 'TEXTAREA' || tn == 'SELECT') {
+                    } else if (tn == 'INPUT' || tn == 'TEXTAREA' || tn == 'SELECT' || tn == 'BUTTON') {
                         // This is a single form elemenent.
                     } else {
                         return this._error('inv_form_el', (v.name||''), v.tagName);
index 0eb4369f2224f8308070435beee347731544a89c..01fad9985f28912f80f2d77cf151c309c1f3583f 100644 (file)
@@ -1,4 +1,8 @@
 var _focus;
+var _hotkeys = {
+       'alt': false,   // whether is the Alt key pressed
+       'focus': -1     // currently selected indeks of document.links
+};
 
 function debug(msg) {
     box = document.getElementById('msgbox')
@@ -142,7 +146,7 @@ function _set_combo_select(e) {
                                // F4: call related database editor - not available in non-js fallback mode
                                JsHttpRequest.request('_'+this.name+'_editor', this.form);
                                return false; // prevent default binding
-                               // TODO: preventDefault, stopPropagation when needed
+                               // TODO: stopPropagation when needed
                        }
                }
 }              
@@ -151,6 +155,20 @@ function _set_combo_select(e) {
  Behaviour definitions
 */
 var inserts = {
+       'form': function(e) {
+               e.onkeydown = function(ev) { 
+                       ev = ev||window.event;
+                       key = ev.keyCode||ev.which;
+                       if((ev.ctrlKey && key == 13) || key == 27) {
+                               ev.cancelBubble = true;
+                       if(ev.stopPropagation) ev.stopPropagation();
+// here ctrl-enter/escape support
+                               ev.returnValue = false;
+                               return false;
+                       } 
+                       return true;
+               }
+       },
        'input': function(e) {
                if(e.onfocus==undefined) {
                        e.onfocus = function() {
@@ -185,7 +203,7 @@ var inserts = {
            // this shows divs for js enabled browsers only
            e.style.display = 'block';
        },
-       'input.ajaxsubmit,input.editbutton,input.navibutton': 
+       'input.ajaxsubmit','button.ajaxsubmit,button.editbutton,button.navibutton': 
        function(e) {
            e.onclick = function() {
                        if (this.getAttribute('aspect') == 'process')
@@ -266,7 +284,68 @@ var inserts = {
        }
 */
 };
+function stopEv(ev) {
+                       ev.returnValue = false;
+                       ev.cancelBubble = true;
+                       if(ev.preventDefault) ev.preventDefault();
+                       return false;
+}
+/*
+       Modified accesskey system. While Alt key is pressed letter keys moves 
+       focus to next marked link. Alt key release activates focused link.
+*/
+function setHotKeys() {
+       document.onkeydown = function(ev) {
+               ev = ev||window.event;
+               key = ev.keyCode||ev.which;
+               if (key == 18) {        // start selection
+                       _hotkeys.alt = true;
+                       _hotkeys.focus = -1;
+                       return stopEv(ev);
+               } else
+               if (key == 27) { // cancel selection
+                       _hotkeys.alt = false;
+                       _hotkeys.focus = -1;
+                       return stopEv(ev);
+               } 
+               else if (_hotkeys.alt && ((key>47 && key<58) || (key>64 && key<91))) {
+                       var n = _hotkeys.focus;
+                       var l = document.links;
+                       var cnt = l.length;
+                       key = String.fromCharCode(key);
+                       for (var i=0; i<cnt; i++) { 
+                               n = (n+1)%cnt;
+                               // check also if the link is visible
+                               if (l[n].accessKey==key && l[n].scrollWidth) {
+                                       _hotkeys.focus = n;
+           // The timeout is needed to prevent unpredictable behaviour on IE.
+                                       var tmp = function() {document.links[_hotkeys.focus].focus();};
+                                       setTimeout(tmp, 0);
+                                       break;
+                               }
+                       }
+                       return stopEv(ev);
+               }
+               return true;
+       };
+       document.onkeyup = function(ev) {
+               if (_hotkeys.alt==true) {
+                       ev = ev||window.event;
+                       key = ev.keyCode||ev.which;
+
+                       if (key == 18) {
+                               _hotkeys.alt = false;
+                               if (_hotkeys.focus>=0) {
+                                       window.location = document.links[_hotkeys.focus].href;
+                               }
+                       } 
+                       return stopEv(ev);
+               }
+               return true;
+       }
+}
 
 Behaviour.register(inserts);
 
 Behaviour.addLoadEvent(setFocus);
+Behaviour.addLoadEvent(setHotKeys);
index 761917a2d0f9e17cd5a6a143f74ec2c523c07225..b2fc71c4b5bb83f1acb0c065d57b3684228eb638 100644 (file)
@@ -183,7 +183,11 @@ function goBack() {
 }
 
 function setFocus(name, byId) {
-
+  if(document.location.pathname.indexOf('index.php') != -1) {
+       // this is application menu page - set focus on first link
+       // var el = document.getElementById('msgbox');
+       // TODO find first link after msgbox and set focus
+  }
   if(!name) {
        if (_focus)     
                name = _focus;  // last focus set in onfocus handlers
index 0dabe11ca676661ab3d027d91873501709b355d9..e180ed3b5fde15a8cb85e2bc51f0e0ffdd1d4c27 100644 (file)
@@ -31,11 +31,12 @@ class BoxReports
                foreach($this->ar_classes as $key=>$value)
                {
                        $style = $class_counter==0 ? '' : $style = "style='display:none'";
-                       $st_classes .= "<a href='javascript:showClass($class_counter)'>$key</a> <br>";
+                       $acc = access_string($key);
+                       $st_classes .= "<a href='javascript:showClass($class_counter)'$acc[1]>$acc[0]</a> <br>";
                        $st_reports .= "<table id='TAB_" . $class_counter++ ."' $style cellpadding=0 cellspacing=0 border=0 width='100%'><tr><td><b>" . _("Reports For Class: ") . "&nbsp;$key</b></td></tr>";
                        foreach($value as $report)
-                       {
-                               $st_reports .= "<tr><td><a href='javascript:showReport($rep_counter)'>" . $report->name . "</a></td></tr>";
+                       {       $acc = access_string($report->name);
+                               $st_reports .= "<tr><td><a href='javascript:showReport($rep_counter)'$acc[1]>$acc[0]</a></td></tr>";
                                $st_params .= "<table border=0 id='REP_" . $rep_counter++ . "' style='display:none'>";
                                $st_params .= "<tr><td>" . $report->getDisplay() . "</td></tr></table>";
                        }
index 2605cae41a2adeceb23c0c103a323f81d2de366a..944d63e0f1b9968f9a7ffa24ce87b3574f419822 100644 (file)
@@ -274,7 +274,9 @@ credit_status_list_row(_("Credit Status:"), 'credit_status', $_POST['credit_stat
 if (!$new_customer)  {
        start_row();
        echo '<td>'._('Customer branches').':</td>';
-       hyperlink_params_td($path_to_root . "/sales/manage/customer_branches.php",'<b>'. (count($_SESSION['Context']) ?  _("Select or Add") : _("Add or Edit")).'</b>', "debtor_no=".$_POST['customer_id']);
+       hyperlink_params_td($path_to_root . "/sales/manage/customer_branches.php",
+               '<b>'. (count($_SESSION['Context']) ?  _("Select or &Add") : _("&Add or Edit ")).'</b>', 
+               "debtor_no=".$_POST['customer_id']);
        end_row();
 }
 end_table();
index 9891d0c5d3d11788877bd3436e5cee5a1f51a4ec..70ca31a4ca672e89ec55eb8554a1bfd38b07e4f2 100644 (file)
@@ -487,14 +487,15 @@ if ($customer_error == "") {
        if ($_SESSION['Items']->trans_no == 0) {
 
                submit_center_first('ProcessOrder', $porder,
-                   _('Check entered data and save document'), true);
+                   _('Check entered data and save document'), true, 'confirm.png');
        } else {
                submit_center_first('ProcessOrder', $corder,
-                   _('Validate changes and update document'), true);
+                   _('Validate changes and update document'), true, 'confirm.png');
        }
 
        submit_center_last('CancelOrder', $cancelorder,
-          _('Cancels document entry or removes sales order when editing an old document'));
+          _('Cancels document entry or removes sales order when editing an old document'),
+          true, 'escape.png');
 } else {
        display_error($customer_error);
 }
index e7323a8a6a87bf0da35722a310b003c0a18f58ea..d0d87e99a7e5ccbf2a321d39f3f0081140a0cdc7 100644 (file)
@@ -71,6 +71,17 @@ a:hover {
        text-decoration: underline;
 }
 
+button {
+       font-size: 11px;
+       border: 1px #0066cc solid;
+       padding: 1px 0px;
+}
+
+button img, span {
+       padding: 0px 2px ;
+       vertical-align: middle;
+}
+
 .login {
        background-color: #ffffff;
        border: none;
index ad4cd21e3cc0e43b5886d1173d22cff74c2b176c..8e42fca75a665fa87106721d5bbf1205aa498168 100644 (file)
                                echo "<div class=tabs>";
                                foreach($applications as $app => $name)
                                {
+                                       $acc = access_string($name);
                                        echo "<a ".($sel_app == $app ? "class='selected' " : "").
                                        "href='$local_path_to_root/index.php?application=".$app.
-                                               SID ."'>" .$name . "</a>";
+                                               SID ."'$acc[1]>" .$acc[0] . "</a>";
                                }
                                echo "</div>";
 
 
                                foreach ($module->lappfunctions as $appfunction)
                                {
-                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                               echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                       {
+                                               $lnk = access_string($appfunction->label);
+                                               echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                       }
                                }
                                echo "</td>";
                                if (sizeof($module->rappfunctions) > 0)
                                        echo "<td width='50%' class='menu_group_items'>";
                                        foreach ($module->rappfunctions as $appfunction)
                                        {
-                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                                       echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                               {
+                                                       $lnk = access_string($appfunction->label);
+                                                       echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                               }
                                        }
                                        echo "</td>";
                                }
index fc84e8b9ac0d78f1577b2ce519e585d05e185305..85f8342dfb5e238d1c5bed3d4a6dc591004a394f 100644 (file)
@@ -71,6 +71,16 @@ a:hover {
        text-decoration: underline;
 }
 
+button {
+       font-size: 11px;
+       border: 1px #0066cc solid;
+       padding: 1px 0px;
+}
+
+button img, span {
+       padding: 0px 2px ;
+       vertical-align: middle;
+}
 
 .login {
        background-color: #ffffff;
index ad4cd21e3cc0e43b5886d1173d22cff74c2b176c..8e42fca75a665fa87106721d5bbf1205aa498168 100644 (file)
                                echo "<div class=tabs>";
                                foreach($applications as $app => $name)
                                {
+                                       $acc = access_string($name);
                                        echo "<a ".($sel_app == $app ? "class='selected' " : "").
                                        "href='$local_path_to_root/index.php?application=".$app.
-                                               SID ."'>" .$name . "</a>";
+                                               SID ."'$acc[1]>" .$acc[0] . "</a>";
                                }
                                echo "</div>";
 
 
                                foreach ($module->lappfunctions as $appfunction)
                                {
-                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                               echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                       {
+                                               $lnk = access_string($appfunction->label);
+                                               echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                       }
                                }
                                echo "</td>";
                                if (sizeof($module->rappfunctions) > 0)
                                        echo "<td width='50%' class='menu_group_items'>";
                                        foreach ($module->rappfunctions as $appfunction)
                                        {
-                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                                       echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                               {
+                                                       $lnk = access_string($appfunction->label);
+                                                       echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                               }
                                        }
                                        echo "</td>";
                                }
index a32fa4e9e6552bfeca531bd9c34f180e463cd3fa..ef361e15f046a13dde1c8901e8bbbef26cfe3d02 100644 (file)
@@ -71,6 +71,17 @@ a:hover {
        text-decoration: underline;
 }
 
+button {
+       font-size: 11px;
+       border: 1px #0066cc solid;
+       padding: 1px 0px;
+}
+
+button img, span {
+       padding: 0px 2px ;
+       vertical-align: middle;
+}
+
 .login {
        background-color: #ffffff;
        border: none;
index 51cbc8e441bfe26bc1eb9c720ebd1006135358ae..00bff4ea9adaea80f6a359028a6b23d74030338d 100644 (file)
                                echo "<div class=tabs>";
                                foreach($applications as $app => $name)
                                {
+                                       $acc = access_string($name);
                                        echo "<a ".($sel_app == $app ? "class='selected' " : "").
                                        "href='$local_path_to_root/index.php?application=".$app.
-                                               SID ."'>" .$name . "</a>";
+                                               SID ."'$acc[1]>" .$acc[0] . "</a>";
                                }
                                echo "</div>";
                                echo "</td></tr></table>";
 
                                foreach ($module->lappfunctions as $appfunction)
                                {
-                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                               echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                       if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                       {
+                                               $lnk = access_string($appfunction->label);
+                                               echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                       }
                                }
                                echo "</td>";
                                if (sizeof($module->rappfunctions) > 0)
                                        echo "<td width='50%' class='menu_group_items'>";
                                        foreach ($module->rappfunctions as $appfunction)
                                        {
-                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access))
-                                                       echo "<a href='$appfunction->link'> " . $appfunction->label . "</a><br>";
+                                               if ($_SESSION["wa_current_user"]->can_access_page($appfunction->access)) 
+                                               {
+                                                       $lnk = access_string($appfunction->label);
+                                                       echo "<a href='$appfunction->link'$lnk[1]>$lnk[0]</a><br>";
+                                               }
                                        }
                                        echo "</td>";
                                }