static struct {
     JSObjectRef    obj;       /* the js object */
-    guint          num;       /* olds the numeric filter for hints typed by the user */
     char           mode;      /* mode identifying char - that last char of the hint prompt */
     int            promptlen; /* lenfth of the hint prompt chars 2 or 3 */
     gboolean       gmode;     /* indicate if the hints g mode is used */
 
 extern VbCore vb;
 
-static void call_hints_function(const char *func, int count, JSValueRef params[]);
+static gboolean call_hints_function(const char *func, int count, JSValueRef params[]);
 
 
 void hints_init(WebKitWebFrame *frame)
         hints.obj = NULL;
     }
     if (!hints.obj) {
-        hints.obj = js_create_object(frame, HINTS_JS);
         hints.ctx = webkit_web_frame_get_global_context(frame);
+        hints.obj = js_create_object(frame, HINTS_JS);
     }
 }
 
 VbResult hints_keypress(int key)
 {
+    JSValueRef arguments[1];
+
     /* if we are not already in hint mode we expect to get a ; to start
      * hinting */
     if (!(vb.mode->flags & FLAG_HINTING) && key != ';') {
         hints_fire();
 
         return RESULT_COMPLETE;
-    }
-
-    /* if there is an active filter by hint num backspace will remove the
-     * number filter first */
-    if (hints.num && key == CTRL('H')) {
-        hints.num /= 10;
-        hints_update(hints.num);
-
-        return RESULT_COMPLETE;
-    }
-    if (isdigit(key)) {
-        int num = key - '0';
-        if ((num >= 1 && num <= 9) || (num == 0 && hints.num)) {
-            /* allow a zero as non-first number */
-            hints.num = (hints.num ? hints.num * 10 : 0) + num;
-            hints_update(hints.num);
-
+    } else if (key == CTRL('H')) {
+        arguments[0] = JSValueMakeNull(hints.ctx);
+        if (call_hints_function("update", 1, arguments)) {
             return RESULT_COMPLETE;
         }
-    }
-    if (key == KEY_TAB) {
+    } else if (isdigit(key)) {
+        arguments[0] = JSValueMakeNumber(hints.ctx, key - '0');
+        if (call_hints_function("update", 1, arguments)) {
+            return RESULT_COMPLETE;
+        }
+    } else if (key == KEY_TAB) {
         hints_focus_next(false);
 
         return RESULT_COMPLETE;
-    }
-    if (key == KEY_SHIFT_TAB) {
+    } else if (key == KEY_SHIFT_TAB) {
         hints_focus_next(true);
 
         return RESULT_COMPLETE;
 
 void hints_create(const char *input)
 {
+    /* don't start hinting if the hinting object isn't created - for example
+     * if hinting is started before the first data of page are recieved */
+    if (!hints.obj) {
+        return;
+    }
+
     /* check if the input contains a valid hinting prompt */
     if (!hints_parse_prompt(input, &hints.mode, &hints.gmode)) {
         /* if input is not valid, clear possible previous hint mode */
     if (!(vb.mode->flags & FLAG_HINTING)) {
         vb.mode->flags |= FLAG_HINTING;
 
-        /* unset number filter - this is required to remove the last char from
-         * inputbox on backspace also if there was used a number filter prior */
-        hints.num       = 0;
         hints.promptlen = hints.gmode ? 3 : 2;
 
         JSValueRef arguments[] = {
             js_string_to_ref(hints.ctx, (char[]){hints.mode, '\0'}),
+            JSValueMakeBoolean(hints.ctx, hints.gmode),
             JSValueMakeNumber(hints.ctx, MAXIMUM_HINTS)
         };
-        call_hints_function("init", 2, arguments);
+        call_hints_function("init", 3, arguments);
 
         /* if hinting is started there won't be any aditional filter given and
          * we can go out of this function */
     call_hints_function("filter", 1, arguments);
 }
 
-void hints_update(int num)
-{
-    JSValueRef arguments[] = {
-        JSValueMakeNumber(hints.ctx, num)
-    };
-    call_hints_function("update", 1, arguments);
-}
-
 void hints_focus_next(const gboolean back)
 {
     JSValueRef arguments[] = {
     return res;
 }
 
-static void call_hints_function(const char *func, int count, JSValueRef params[])
+static gboolean call_hints_function(const char *func, int count, JSValueRef params[])
 {
     char *value = js_object_call_function(hints.ctx, hints.obj, func, count, params);
 
+    if (!value) {
+        return false;
+    }
+
+    if (!strncmp(value, "ERROR:", 6)) {
+        g_free(value);
+        return false;
+    }
+
     if (!strncmp(value, "OVER:", 5)) {
         g_signal_emit_by_name(
             vb.gui.webview, "hovering-over-link", NULL, *(value + 5) == '\0' ? NULL : (value + 5)
         );
     } else if (!strncmp(value, "DONE:", 5)) {
-        if (hints.gmode) {
-            /* if g mode is used reset number filter and keep in hint mode */
-            hints.num = 0;
-            hints_update(hints.num);
-        } else {
+        if (!hints.gmode) {
             mode_enter('n');
         }
     } else if (!strncmp(value, "INSERT:", 7)) {
             input_open_editor();
         }
     } else if (!strncmp(value, "DATA:", 5)) {
-        if (hints.gmode) {
-            /* if g mode is used reset number filter and keep in hint mode */
-            hints.num = 0;
-            hints_update(hints.num);
-        } else {
-            /* switch first to normal mode - else we would clear the inputbox
-             * on switching mode also if we want to show yanked data */
+        /* switch first to normal mode - else we would clear the inputbox
+         * on switching mode also if we want to show yanked data */
+        if (!hints.gmode) {
             mode_enter('n');
         }
 
         }
     }
     g_free(value);
+
+    return true;
 }
 
         helper(window);
     }
 
-    function show() {
+    function show(fireLast) {
         var i, hint, newIdx,
             num     = 1,
             matcher = getMatcher(filterText);
                 num++;
             }
         }
-
-        if (validHints.length <= 1) {
+        if (fireLast && validHints.length <= 1) {
             focusHint(0);
-
             return fire();
         }
 
 
     function fire() {
         if (!activeHint) {
-            return "DONE:";
+            return "ERROR:";
         }
 
         var e    = activeHint.e,
             tag  = e.nodeName.toLowerCase(),
-            type = e.type || "";
+            type = e.type || "",
+            res  = "";
 
         if (tag === "input" || tag === "textarea" || tag === "select") {
             if (type === "radio" || type === "checkbox") {
                 e.focus();
                 click(e);
-                return "DONE:";
-            }
-            if (type === "submit" || type === "reset" || type  === "button" || type === "image") {
+                res = "DONE:";
+            } else if (type === "submit" || type === "reset" || type  === "button" || type === "image") {
                 click(e);
-                return "DONE:";
+                res = "DONE:";
+            } else {
+                e.focus();
+                res = "INSERT:";
             }
+        } else if (tag === "iframe" || tag === "frame") {
             e.focus();
-            return "INSERT:";
+            res = "DONE:";
         }
-        if (tag === "iframe" || tag === "frame") {
-            e.focus();
-            return "DONE:";
+
+        if (config.continue) {
+            /* reset the filter number */
+            filterNum = 0;
+            show(false);
+        } else {
+            clear();
         }
 
-        return config.action(e);
+        return res || config.action(e);
     }
 
     /* internal used methods */
 
     /* the api */
     return {
-        init: function init(mode, maxHints) {
+        init: function init(mode, keepOpen, maxHints) {
             var prop,
                 /* holds the xpaths for the different modes */
                 xpathmap = {
                     eiIOpPsTy: function(e) {return "DATA:" + getSrc(e);}
                 };
 
-            config = {maxHints: maxHints};
+            config = {
+                maxHints: maxHints,
+                continue: keepOpen
+            };
             for (prop in xpathmap) {
                 if (prop.indexOf(mode) >= 0) {
                     config["xpath"] = xpathmap[prop];
             }
 
             create();
-            return show();
+            return show(true);
         },
         filter: function filter(text) {
             /* remove previously set number filters to make the filter */
             /* easier to understand for the users */
             filterNum  = 0;
             filterText = text || "";
-            return show();
+            return show(true);
         },
         update: function update(n) {
-            filterNum = n;
-            return show();
+            /* delete last filter number digit */
+            if (null === n && filterNum) {
+                filterNum = Math.floor(filterNum / 10);
+                return show(false);
+            }
+            if ((n >= 1 && n <= 9) || (n === 0 && filterNum)) {
+                /* allow a zero as non-first number */
+                filterNum = (filterNum ? filterNum * 10 : 0) + n;
+                return show(true);
+            }
+            return "ERROR:";
         },
         clear:      clear,
         fire:       fire,