diff --git a/src/persist/zcl_abapgit_persistence_user.clas.abap b/src/persist/zcl_abapgit_persistence_user.clas.abap
index 25d63948d..14641972b 100644
--- a/src/persist/zcl_abapgit_persistence_user.clas.abap
+++ b/src/persist/zcl_abapgit_persistence_user.clas.abap
@@ -151,7 +151,6 @@ CLASS zcl_abapgit_persistence_user DEFINITION
RAISING
zcx_abapgit_exception.
PRIVATE SECTION.
-
TYPES:
BEGIN OF ty_repo_config,
url TYPE zif_abapgit_persistence=>ty_repo-url,
@@ -337,6 +336,17 @@ CLASS zcl_abapgit_persistence_user IMPLEMENTATION.
ENDMETHOD.
+ METHOD get_settings.
+
+ DATA: ls_user TYPE ty_user.
+
+ ls_user = read( ).
+
+ rs_user_settings = ls_user-settings.
+
+ ENDMETHOD.
+
+
METHOD is_favorite_repo.
DATA: lt_favorites TYPE tt_favorites.
@@ -463,6 +473,17 @@ CLASS zcl_abapgit_persistence_user IMPLEMENTATION.
ENDMETHOD.
+ METHOD set_settings.
+
+ DATA: ls_user TYPE ty_user.
+
+ ls_user = read( ).
+ ls_user-settings = is_user_settings.
+ update( ls_user ).
+
+ ENDMETHOD.
+
+
METHOD toggle_changes_only.
DATA ls_user TYPE ty_user.
@@ -568,25 +589,4 @@ CLASS zcl_abapgit_persistence_user IMPLEMENTATION.
COMMIT WORK AND WAIT.
ENDMETHOD. "update_repo_config
-
- METHOD get_settings.
-
- DATA: ls_user TYPE ty_user.
-
- ls_user = read( ).
-
- rs_user_settings = ls_user-settings.
-
- ENDMETHOD.
-
- METHOD set_settings.
-
- DATA: ls_user TYPE ty_user.
-
- ls_user = read( ).
- ls_user-settings = is_user_settings.
- update( ls_user ).
-
- ENDMETHOD.
-
ENDCLASS.
diff --git a/src/ui/zcl_abapgit_gui.clas.abap b/src/ui/zcl_abapgit_gui.clas.abap
index 509733a93..813025bfb 100644
--- a/src/ui/zcl_abapgit_gui.clas.abap
+++ b/src/ui/zcl_abapgit_gui.clas.abap
@@ -1,7 +1,7 @@
-class ZCL_ABAPGIT_GUI definition
- public
- final
- create private .
+CLASS zcl_abapgit_gui DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PRIVATE .
PUBLIC SECTION.
@@ -20,6 +20,8 @@ class ZCL_ABAPGIT_GUI definition
METHODS on_event FOR EVENT sapevent OF cl_gui_html_viewer
IMPORTING action frame getdata postdata query_table. "#EC NEEDED
+ METHODS focus.
+
PRIVATE SECTION.
CLASS-DATA: go_gui TYPE REF TO zcl_abapgit_gui.
@@ -192,6 +194,13 @@ CLASS ZCL_ABAPGIT_GUI IMPLEMENTATION.
ENDMETHOD. "constructor
+ METHOD focus.
+
+ cl_gui_control=>set_focus( mo_html_viewer ).
+
+ ENDMETHOD.
+
+
METHOD get_current_page_name.
IF mi_cur_page IS BOUND.
rv_page_name =
diff --git a/src/ui/zcl_abapgit_gui_page.clas.abap b/src/ui/zcl_abapgit_gui_page.clas.abap
index d7a576658..c0387331f 100644
--- a/src/ui/zcl_abapgit_gui_page.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page.clas.abap
@@ -29,7 +29,6 @@ CLASS zcl_abapgit_gui_page DEFINITION PUBLIC ABSTRACT CREATE PUBLIC.
METHODS title
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
-
METHODS footer
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
@@ -98,7 +97,25 @@ CLASS ZCL_ABAPGIT_GUI_PAGE IMPLEMENTATION.
METHOD scripts.
- ASSERT 1 = 1. " Dummy
+
+ DATA: lo_settings TYPE REF TO zcl_abapgit_settings,
+ lv_link_hint_key TYPE char01,
+ lv_background_color TYPE string.
+
+ CREATE OBJECT ro_html.
+
+ lo_settings = zcl_abapgit_persist_settings=>get_instance( )->read( ).
+
+ lv_link_hint_key = lo_settings->get_link_hint_key( ).
+ lv_background_color = lo_settings->get_link_hint_background_color( ).
+
+ IF lo_settings->get_link_hints( ) = abap_true
+ AND lv_link_hint_key IS NOT INITIAL.
+ ro_html->add( |setLinkHints("{ lv_link_hint_key }","{ lv_background_color }");| ).
+ ro_html->add( |setInitialFocusWithQuerySelector('a span', true);| ).
+ ro_html->add( |enableArrowListNavigation();| ).
+ ENDIF.
+
ENDMETHOD. "scripts
@@ -111,6 +128,7 @@ CLASS ZCL_ABAPGIT_GUI_PAGE IMPLEMENTATION.
ro_html->add( |
{
zcl_abapgit_html=>a( iv_txt = ' '
+ iv_id = 'abapGitLogo'
iv_act = zif_abapgit_definitions=>gc_action-abapgit_home )
} | | ). "#EC NOTEXT
diff --git a/src/ui/zcl_abapgit_gui_page_commit.clas.abap b/src/ui/zcl_abapgit_gui_page_commit.clas.abap
index 18cb255aa..9ea392fbd 100644
--- a/src/ui/zcl_abapgit_gui_page_commit.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_commit.clas.abap
@@ -319,7 +319,8 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_COMMIT IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
+ ro_html = super->scripts( ).
+
ro_html->add( 'setInitialFocus("comment");' ).
ENDMETHOD.
diff --git a/src/ui/zcl_abapgit_gui_page_debuginfo.clas.abap b/src/ui/zcl_abapgit_gui_page_debuginfo.clas.abap
index 57e8c00c6..bb049a96f 100644
--- a/src/ui/zcl_abapgit_gui_page_debuginfo.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_debuginfo.clas.abap
@@ -94,7 +94,7 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_DEBUGINFO IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
+ ro_html = super->scripts( ).
ro_html->add( 'debugOutput("Browser: " + navigator.userAgent + ' &&
'"
Frontend time: " + new Date(), "debug_info");' ).
diff --git a/src/ui/zcl_abapgit_gui_page_diff.clas.abap b/src/ui/zcl_abapgit_gui_page_diff.clas.abap
index 0a33bcf48..5c2e0c861 100644
--- a/src/ui/zcl_abapgit_gui_page_diff.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_diff.clas.abap
@@ -633,7 +633,7 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_DIFF IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
+ ro_html = super->scripts( ).
ro_html->add( 'var gHelper = new DiffHelper({' ).
ro_html->add( | seed: "{ mv_seed }",| ).
diff --git a/src/ui/zcl_abapgit_gui_page_main.clas.abap b/src/ui/zcl_abapgit_gui_page_main.clas.abap
index 842442b10..3fb5db337 100644
--- a/src/ui/zcl_abapgit_gui_page_main.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_main.clas.abap
@@ -10,7 +10,8 @@ CLASS zcl_abapgit_gui_page_main DEFINITION
zif_abapgit_gui_page~on_event REDEFINITION.
PROTECTED SECTION.
- METHODS render_content REDEFINITION.
+ METHODS:
+ render_content REDEFINITION.
PRIVATE SECTION.
CONSTANTS: BEGIN OF c_actions,
@@ -351,4 +352,5 @@ CLASS zcl_abapgit_gui_page_main IMPLEMENTATION.
ENDCASE.
ENDMETHOD. "on_event
+
ENDCLASS.
diff --git a/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap b/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap
index d1586b42f..c00d7a0b3 100644
--- a/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap
@@ -579,7 +579,8 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
+ ro_html = super->scripts( ).
+
ro_html->add( 'setInitialFocus("filter");' ).
ENDMETHOD.
diff --git a/src/ui/zcl_abapgit_gui_page_settings.clas.abap b/src/ui/zcl_abapgit_gui_page_settings.clas.abap
index 8392c2b35..f302d520e 100644
--- a/src/ui/zcl_abapgit_gui_page_settings.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_settings.clas.abap
@@ -57,6 +57,12 @@ CLASS zcl_abapgit_gui_page_settings DEFINITION
METHODS render_start_up
RETURNING
VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
+ METHODS render_link_hints
+ RETURNING
+ VALUE(ro_html) TYPE REF TO zcl_abapgit_html
+ RAISING
+ zcx_abapgit_exception.
+
ENDCLASS.
@@ -127,6 +133,23 @@ CLASS zcl_abapgit_gui_page_settings IMPLEMENTATION.
mo_settings->set_adt_jump_enanbled( abap_false ).
ENDIF.
+ READ TABLE it_post_fields ASSIGNING WITH KEY name = 'link_hints'.
+ IF sy-subrc = 0.
+ mo_settings->set_link_hints( abap_true ).
+ ELSE.
+ mo_settings->set_link_hints( abap_false ).
+ ENDIF.
+
+ READ TABLE it_post_fields ASSIGNING WITH KEY name = 'link_hint_key'.
+ IF sy-subrc = 0.
+ mo_settings->set_link_hint_key( |{ -value }| ).
+ ENDIF.
+
+ READ TABLE it_post_fields ASSIGNING WITH KEY name = 'link_hint_background_color'.
+ IF sy-subrc = 0.
+ mo_settings->set_link_hint_background_color( |{ -value }| ).
+ ENDIF.
+
READ TABLE it_post_fields ASSIGNING WITH KEY name = 'comment_length'.
IF sy-subrc = 0.
lv_i_param_value = -value.
@@ -243,6 +266,8 @@ CLASS zcl_abapgit_gui_page_settings IMPLEMENTATION.
ro_html->add( render_max_lines( ) ).
ro_html->add( |
| ).
ro_html->add( render_adt_jump_enabled( ) ).
+ ro_html->add( |
| ).
+ ro_html->add( render_link_hints( ) ).
ro_html->add( render_section_end( ) ).
ro_html->add( render_form_end( ) ).
@@ -403,4 +428,37 @@ CLASS zcl_abapgit_gui_page_settings IMPLEMENTATION.
ro_html->add( |
| ).
ENDMETHOD.
+
+ METHOD render_link_hints.
+
+ DATA: lv_checked TYPE string,
+ lv_link_hint_key TYPE char01,
+ lv_link_background_color TYPE string.
+
+ IF mo_settings->get_link_hints( ) = abap_true.
+ lv_checked = 'checked'.
+ ENDIF.
+
+ lv_link_hint_key = mo_settings->get_link_hint_key( ).
+ lv_link_background_color = mo_settings->get_link_hint_background_color( ).
+
+ CREATE OBJECT ro_html.
+ ro_html->add( |Vimium like link hints
| ).
+ ro_html->add( ` Enable Vimium like link hints` ).
+ ro_html->add( |
| ).
+ ro_html->add( |
| ).
+ ro_html->add( | Single key to activate links| ).
+ ro_html->add( |
| ).
+ ro_html->add( |
| ).
+ ro_html->add( | Background Color| ).
+
+ ro_html->add( |
| ).
+ ro_html->add( |
| ).
+
+ ENDMETHOD.
+
ENDCLASS.
diff --git a/src/ui/zcl_abapgit_gui_page_stage.clas.abap b/src/ui/zcl_abapgit_gui_page_stage.clas.abap
index 6e822e0b3..c5b298563 100644
--- a/src/ui/zcl_abapgit_gui_page_stage.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_stage.clas.abap
@@ -317,7 +317,7 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
+ ro_html = super->scripts( ).
ro_html->add( 'var gStageParams = {' ).
ro_html->add( | seed: "{ mv_seed }",| ). " Unique page id
diff --git a/src/ui/zcl_abapgit_gui_page_tag.clas.abap b/src/ui/zcl_abapgit_gui_page_tag.clas.abap
index b2fa0ee19..2f8980427 100644
--- a/src/ui/zcl_abapgit_gui_page_tag.clas.abap
+++ b/src/ui/zcl_abapgit_gui_page_tag.clas.abap
@@ -248,8 +248,9 @@ CLASS zcl_abapgit_gui_page_tag IMPLEMENTATION.
METHOD scripts.
- CREATE OBJECT ro_html.
- ro_html->add( 'setInitialFocus("tag_name");' ).
+ ro_html = super->scripts( ).
+
+ ro_html->add( 'setInitialFocus("name");' ).
ENDMETHOD. "scripts
diff --git a/src/ui/zcl_abapgit_html.clas.abap b/src/ui/zcl_abapgit_html.clas.abap
index 8d5fb298c..086e5bd47 100644
--- a/src/ui/zcl_abapgit_html.clas.abap
+++ b/src/ui/zcl_abapgit_html.clas.abap
@@ -1,6 +1,6 @@
CLASS zcl_abapgit_html DEFINITION
PUBLIC
- CREATE PUBLIC .
+ CREATE PUBLIC.
PUBLIC SECTION.
@@ -26,7 +26,7 @@ CLASS zcl_abapgit_html DEFINITION
!iv_opt TYPE clike OPTIONAL
!iv_class TYPE string OPTIONAL
!iv_id TYPE string OPTIONAL
- !iv_style TYPE string OPTIONAL .
+ !iv_style TYPE string OPTIONAL.
METHODS add_icon
IMPORTING
!iv_name TYPE string
@@ -99,7 +99,8 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
lv_href TYPE string,
lv_click TYPE string,
lv_id TYPE string,
- lv_style TYPE string.
+ lv_style TYPE string,
+ lv_span TYPE string.
lv_class = iv_class.
@@ -140,7 +141,9 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
lv_style = | style="{ iv_style }"|.
ENDIF.
- rv_str = |{ iv_txt }|.
+ lv_span = ||.
+
+ rv_str = |{ iv_txt }{ lv_span }|.
ENDMETHOD. "a
diff --git a/src/zabapgit_css_common.w3mi.data.css b/src/zabapgit_css_common.w3mi.data.css
index 8eff85e72..63fb09878 100644
--- a/src/zabapgit_css_common.w3mi.data.css
+++ b/src/zabapgit_css_common.w3mi.data.css
@@ -20,6 +20,10 @@ a:hover, a:active {
text-decoration: underline;
}
+#abapGitLogo {
+ outline: none;
+}
+
img { border: 0px; vertical-align: middle; }
table { border-collapse: collapse; }
pre { display: inline; }
@@ -661,6 +665,7 @@ div.tutorial h2 {
.nav-container.float-right ul ul { left: auto; right: 0; }
.nav-container ul li.current-menu-item { font-weight: 700; }
+.nav-container ul li.block ul { display: block; }
.nav-container ul li:hover > ul { display: block; }
.nav-container ul ul li:hover { background-color: #f6f6f6; }
@@ -824,3 +829,39 @@ div.news .update {
border: #e8ba30 1px solid;
background-color: #f5c538;
}
+
+/* Tooltip text */
+.tooltiptext {
+ line-height: 15px;
+ width: 60px;
+ color: #000;
+ text-align: center;
+ padding: 5px 0;
+ border-radius: 6px;
+
+ /* Position the tooltip text */
+ position: absolute;
+ z-index: 1;
+ margin-left: -60px;
+ margin-top: -30px;
+
+ /* Fade in tooltip */
+ opacity: 1;
+ transition: opacity 0.3s;
+}
+
+.hidden {
+ visibility: hidden;
+}
+
+/* Tooltip arrow */
+.tooltiptext::after {
+ content: "";
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: #555 transparent transparent transparent;
+}
diff --git a/src/zabapgit_css_common.w3mi.xml b/src/zabapgit_css_common.w3mi.xml
index dbdbed67e..cbea95037 100644
--- a/src/zabapgit_css_common.w3mi.xml
+++ b/src/zabapgit_css_common.w3mi.xml
@@ -15,7 +15,7 @@
MI
ZABAPGIT_CSS_COMMON
filename
- ~wwwtmp.css
+ common.css
MI
diff --git a/src/zabapgit_forms.prog.abap b/src/zabapgit_forms.prog.abap
index 4980e7b62..d60b4d6e3 100644
--- a/src/zabapgit_forms.prog.abap
+++ b/src/zabapgit_forms.prog.abap
@@ -109,7 +109,9 @@ FORM package_popup TABLES tt_fields TYPE zif_abapgit_definitions=>ty_sval_tt
ENDFORM. "package_popup
FORM output.
- DATA: lt_ucomm TYPE TABLE OF sy-ucomm.
+ DATA: lt_ucomm TYPE TABLE OF sy-ucomm,
+ lx_error TYPE REF TO zcx_abapgit_exception.
+
PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.
APPEND 'CRET' TO lt_ucomm. "Button Execute
@@ -119,6 +121,12 @@ FORM output.
p_status = sy-pfkey
TABLES
p_exclude = lt_ucomm.
+
+ TRY.
+ zcl_abapgit_gui=>get_instance( )->focus( ).
+ CATCH zcx_abapgit_exception INTO lx_error.
+ message lx_error type 'S' DISPLAY LIKE 'E'.
+ ENDTRY.
ENDFORM.
FORM exit RAISING zcx_abapgit_exception.
diff --git a/src/zabapgit_js_common.w3mi.data.js b/src/zabapgit_js_common.w3mi.data.js
index 5a8a73f5f..5939ad20c 100644
--- a/src/zabapgit_js_common.w3mi.data.js
+++ b/src/zabapgit_js_common.w3mi.data.js
@@ -66,6 +66,20 @@ function setInitialFocus(id) {
document.getElementById(id).focus();
}
+// Set focus to a element with query selector
+function setInitialFocusWithQuerySelector(sSelector, bFocusParent) {
+ var oSelected = document.querySelector(sSelector);
+
+ if (oSelected) {
+ if (bFocusParent) {
+ oSelected.parentElement.focus();
+ } else {
+ oSelected.focus();
+ }
+ }
+
+}
+
// Submit an existing form
function submitFormById(id) {
document.getElementById(id).submit();
@@ -537,6 +551,273 @@ DiffHelper.prototype.highlightButton = function(state) {
// News announcement
function displayNews() {
- var div = document.getElementById("news");
- div.style.display = (div.style.display)?'':'none';
+ var div = document.getElementById("news");
+ div.style.display = (div.style.display) ? '' : 'none';
}
+
+function KeyNavigation() {
+
+}
+
+KeyNavigation.prototype.onkeydown = function(oEvent) {
+
+ if (oEvent.defaultPrevented) {
+ return;
+ }
+
+ // navigate with arrows through list items and support pressing links with enter and space
+ if (oEvent.key === "ENTER" || oEvent.key === "") {
+ this.onEnterOrSpace(oEvent);
+ } else if (/Down$/.test(oEvent.key)) {
+ this.onArrowDown(oEvent);
+ } else if (/Up$/.test(oEvent.key)) {
+ this.onArrowUp(oEvent);
+ }
+
+};
+
+KeyNavigation.prototype.getLiSelected = function() {
+ return document.querySelector('li .selected');
+};
+
+KeyNavigation.prototype.getActiveElement = function () {
+ return document.activeElement;
+};
+
+KeyNavigation.prototype.getActiveElementParent = function () {
+ return this.getActiveElement().parentElement;
+};
+
+KeyNavigation.prototype.onEnterOrSpace = function (oEvent) {
+
+ // Enter or space clicks the selected link
+
+ var liSelected = this.getLiSelected();
+
+ if (liSelected) {
+ liSelected.firstElementChild.click();
+ }
+
+};
+
+
+KeyNavigation.prototype.onArrowDown = function (oEvent) {
+
+ var
+ liNext,
+ liSelected = this.getLiSelected(),
+ oActiveElementParent = this.getActiveElementParent();
+
+ if (liSelected) {
+
+ // we deselect the current li and select the next sibling
+ liNext = oActiveElementParent.nextElementSibling;
+ if (liNext) {
+ liSelected.classList.toggle('selected');
+ liNext.firstElementChild.focus();
+ oActiveElementParent.classList.toggle('selected');
+ oEvent.preventDefault();
+ }
+
+ } else {
+
+ // we don't have any li selected, we have lookup where to start...
+ // the right element should have been activated in fnTooltipActivate
+ liNext = this.getActiveElement().nextElementSibling;
+ if (liNext) {
+ liNext.classList.toggle('selected');
+ liNext.firstElementChild.firstElementChild.focus();
+ oEvent.preventDefault();
+ }
+
+ }
+
+};
+
+
+KeyNavigation.prototype.onArrowUp = function (oEvent) {
+
+ var
+ liSelected = this.getLiSelected(),
+ liPrevious = this.getActiveElementParent().previousElementSibling;
+
+ if (liSelected && liPrevious) {
+
+ liSelected.classList.toggle('selected');
+ liPrevious.firstElementChild.focus();
+ this.getActiveElementParent().classList.toggle('selected');
+ oEvent.preventDefault();
+
+ }
+
+};
+
+// this functions enables the navigation with arrows through list items (li)
+// e.g. in dropdown menus
+function enableArrowListNavigation() {
+
+ var oKeyNavigation = new KeyNavigation();
+
+ document.addEventListener('keydown', oKeyNavigation.onkeydown.bind(oKeyNavigation));
+
+};
+
+function LinkHints(sLinkHintKey, sColor){
+ this.sLinkHintKey = sLinkHintKey;
+ this.sColor = sColor;
+ this.oTooltipMap = {};
+ this.bTooltipsOn = false;
+ this.sPending = "";
+ this.aTooltipElements = document.querySelectorAll('a span');
+}
+
+LinkHints.prototype.fnRenderTooltip = function (oTooltip, iTooltipCounter) {
+ if (this.bTooltipsOn) {
+ oTooltip.classList.remove('hidden');
+ } else {
+ oTooltip.classList.add('hidden');
+ }
+ oTooltip.innerHTML = iTooltipCounter;
+ oTooltip.style.backgroundColor = this.sColor;
+ this.oTooltipMap[iTooltipCounter] = oTooltip;
+};
+
+LinkHints.prototype.getTooltipStartValue = function(iToolTipCount){
+
+ // if whe have 333 tooltips we start from 100
+ return Math.pow(10,iToolTipCount.toString().length - 1);
+
+};
+
+LinkHints.prototype.fnRenderTooltips = function () {
+
+ // all possible links which should be accessed via tooltip have
+ // sub span which is hidden by default. If we like to show the
+ // tooltip we have to toggle the css class 'hidden'.
+ //
+ // We use numeric values for the tooltip label. Maybe we can
+ // support also alphanumeric chars in the future. Then we have to
+ // calculate permutations and that's work. So for the sake of simplicity
+ // we stick to numeric values and just increment them.
+
+ var
+ iTooltipCounter = this.getTooltipStartValue(this.aTooltipElements.length),
+ that = this;
+
+ [].forEach.call(this.aTooltipElements, function(oTooltip){
+ iTooltipCounter += 1;
+ this.fnRenderTooltip(oTooltip, iTooltipCounter)
+ }.bind(that));
+
+};
+
+LinkHints.prototype.fnToggleAllTooltips = function () {
+
+ this.sPending = "";
+ this.bTooltipsOn = !this.bTooltipsOn;
+ this.fnRenderTooltips();
+
+};
+
+LinkHints.prototype.fnRemoveAllTooltips = function () {
+
+ this.sPending = "";
+ this.bTooltipsOn = false;
+
+ [].forEach.call(this.aTooltipElements, function (oTooltip) {
+ oTooltip.classList.add('hidden');
+ });
+
+};
+
+LinkHints.prototype.fnFilterTooltips = function (sPending) {
+
+ var that = this;
+
+ Object
+ .keys(this.oTooltipMap)
+ .forEach(function (sKey) {
+
+ // we try to partially match, but only from the beginning!
+ var regex = new RegExp("^" + this.sPending);
+ var oTooltip = this.oTooltipMap[sKey];
+
+ if (regex.test(sKey)) {
+ // we have a partial match, grey out the matched part
+ oTooltip.innerHTML = sKey.replace(regex, "" + this.sPending + '
');
+ } else {
+ // and hide the not matched tooltips
+ oTooltip.classList.add('hidden');
+ }
+
+ }.bind(that));
+
+};
+
+LinkHints.prototype.fnActivateDropDownMenu = function (oTooltip) {
+ // to enable link hint navigation for drop down menu, we must expand
+ // like if they were hovered
+ oTooltip.parentElement.parentElement.classList.toggle("block");
+};
+
+
+LinkHints.prototype.fnTooltipActivate = function (oTooltip) {
+
+ // a tooltips was successfully specified, so we try to trigger the link
+ // and remove all tooltips
+ this.fnRemoveAllTooltips();
+ oTooltip.parentElement.click();
+
+ // in case it is a dropdownmenu we have to expand and focus it
+ this.fnActivateDropDownMenu(oTooltip);
+ oTooltip.parentElement.focus();
+
+}
+
+LinkHints.prototype.onkeypress = function(oEvent){
+
+ if (oEvent.defaultPrevented) {
+ return;
+ }
+
+ var activeElementType = ((document.activeElement && document.activeElement.nodeName) || "");
+
+ // link hints are disabled for input and textareas for obvious reasons.
+ // Maybe we must add other types here in the future
+ if (oEvent.key === this.sLinkHintKey && activeElementType !== "INPUT" && activeElementType !== "TEXTAREA") {
+
+ this.fnToggleAllTooltips();
+
+ } else if (this.bTooltipsOn === true) {
+
+ // the user tries to reach a tooltip
+ this.sPending += oEvent.key;
+ var oTooltip = this.oTooltipMap[this.sPending];
+
+ if (oTooltip) {
+ // we are there, we have a fully specified tooltip. Let's activate it
+ this.fnTooltipActivate(oTooltip);
+ } else {
+ // we are not there yet, but let's filter the link so that only
+ // the partially matched are shown
+ this.fnFilterTooltips(this.sPending);
+ }
+
+ }
+
+}
+
+// Vimium like link hints
+function setLinkHints(sLinkHintKey, sColor) {
+
+ if (!sLinkHintKey || !sColor) {
+ return;
+ }
+
+ var oLinkHint = new LinkHints(sLinkHintKey, sColor);
+
+ document.addEventListener("keypress", oLinkHint.onkeypress.bind(oLinkHint));
+
+}
+
+
diff --git a/src/zcl_abapgit_settings.clas.abap b/src/zcl_abapgit_settings.clas.abap
index 15284e9f7..60fa6aaa6 100644
--- a/src/zcl_abapgit_settings.clas.abap
+++ b/src/zcl_abapgit_settings.clas.abap
@@ -82,7 +82,29 @@ CLASS zcl_abapgit_settings DEFINITION PUBLIC CREATE PUBLIC.
VALUE(rv_show_default_repo) TYPE abap_bool,
set_show_default_repo
IMPORTING
- iv_show_default_repo TYPE abap_bool.
+ iv_show_default_repo TYPE abap_bool,
+ set_link_hints
+ IMPORTING
+ iv_link_hints TYPE abap_bool,
+ get_link_hints
+ RETURNING
+ VALUE(rv_link_hints) TYPE abap_bool
+ RAISING
+ zcx_abapgit_exception,
+ set_link_hint_key
+ IMPORTING
+ iv_link_hint_key TYPE char01,
+ get_link_hint_key
+ RETURNING
+ VALUE(rv_link_hint_key) TYPE char01
+ RAISING
+ zcx_abapgit_exception,
+ get_link_hint_background_color
+ RETURNING
+ VALUE(rv_background_color) TYPE string,
+ set_link_hint_background_color
+ IMPORTING
+ iv_background_color TYPE string.
PRIVATE SECTION.
TYPES: BEGIN OF ty_s_settings,
@@ -124,6 +146,16 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
ENDMETHOD.
+ METHOD get_link_hints.
+ rv_link_hints = ms_user_settings-link_hints.
+ ENDMETHOD.
+
+
+ METHOD get_link_hint_key.
+ rv_link_hint_key = ms_user_settings-link_hint_key.
+ ENDMETHOD.
+
+
METHOD get_max_lines.
rv_lines = ms_user_settings-max_lines.
ENDMETHOD.
@@ -164,6 +196,15 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
ENDMETHOD.
+ METHOD get_show_default_repo.
+ rv_show_default_repo = ms_user_settings-show_default_repo.
+ ENDMETHOD.
+
+
+ METHOD get_user_settings.
+ rs_settings = ms_user_settings.
+ ENDMETHOD.
+
METHOD set_adt_jump_enanbled.
ms_user_settings-adt_jump_enabled = iv_adt_jump_enabled.
@@ -192,6 +233,8 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
set_show_default_repo( abap_false ).
set_commitmsg_comment_length( c_commitmsg_comment_length_dft ).
set_commitmsg_body_size( c_commitmsg_body_size_dft ).
+ set_link_hint_key( |f| ).
+ set_link_hint_background_color( |yellow| ).
ENDMETHOD.
@@ -201,6 +244,16 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
ENDMETHOD.
+ METHOD set_link_hints.
+ ms_user_settings-link_hints = iv_link_hints.
+ ENDMETHOD.
+
+
+ METHOD set_link_hint_key.
+ ms_user_settings-link_hint_key = iv_link_hint_key.
+ ENDMETHOD.
+
+
METHOD set_max_lines.
ms_user_settings-max_lines = iv_lines.
ENDMETHOD.
@@ -226,6 +279,11 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
ENDMETHOD.
+ METHOD set_show_default_repo.
+ ms_user_settings-show_default_repo = iv_show_default_repo.
+ ENDMETHOD.
+
+
METHOD set_user_settings.
ms_user_settings = is_user_settings.
ENDMETHOD.
@@ -248,18 +306,13 @@ CLASS zcl_abapgit_settings IMPLEMENTATION.
ENDMETHOD.
- METHOD get_user_settings.
- rs_settings = ms_user_settings.
+ METHOD get_link_hint_background_color.
+ rv_background_color = ms_user_settings-link_hint_background_color.
ENDMETHOD.
- METHOD get_show_default_repo.
- rv_show_default_repo = ms_user_settings-show_default_repo.
- ENDMETHOD.
-
-
- METHOD set_show_default_repo.
- ms_user_settings-show_default_repo = iv_show_default_repo.
+ METHOD set_link_hint_background_color.
+ ms_user_settings-link_hint_background_color = iv_background_color.
ENDMETHOD.
ENDCLASS.
diff --git a/src/zif_abapgit_definitions.intf.abap b/src/zif_abapgit_definitions.intf.abap
index 961ca6cea..6c4fefd33 100644
--- a/src/zif_abapgit_definitions.intf.abap
+++ b/src/zif_abapgit_definitions.intf.abap
@@ -324,9 +324,12 @@ INTERFACE zif_abapgit_definitions PUBLIC.
TYPES tt_repo_items TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY.
TYPES: BEGIN OF ty_s_user_settings,
- max_lines TYPE i,
- adt_jump_enabled TYPE abap_bool,
- show_default_repo TYPE abap_bool,
+ max_lines TYPE i,
+ adt_jump_enabled TYPE abap_bool,
+ show_default_repo TYPE abap_bool,
+ link_hints TYPE abap_bool,
+ link_hint_key TYPE char01,
+ link_hint_background_color TYPE string,
END OF ty_s_user_settings.
CONSTANTS: