// Vimperator plugin: 'Walk Input' // License: BSD // Version: 1.3.0 // Maintainer: Takayama Fumihiko // anekos // ------------------------------------------------------------ // The focus walks & // // PLUGIN_INFO {{{ let INFO = xml` Takayama Fumihiko anekos BSD

The focus walks <input> & <textarea> element. If you type first, the focus moves to "<input name='search' />". Then if you type once more, the focus moves to "<input name='name' />".

xxx yyy zzz ]]> i_ ]]> <M-i> <A-i>

Move focus forward

i_ ]]> <M-S-i> <A-S-i>

Move focus backward

`; // }}} (function () { var types = [ "text", "password", "search", "datetime", "datetime-local", "date", "month", "time", "week", "number", "range", "email", "url", "tel", "color", ].map(function(type) "@type=" + JSON.stringify(type)).join(" or "); var xpath = '//input[(' + types + ' or not(@type)) and not(@disabled)] | //textarea | //*[@contenteditable="true"]'; function isVisible (elem) { while (elem && !(elem instanceof HTMLDocument)) { if (/^none$/i.test(getComputedStyle(elem, '').display)) return false; elem = elem.parentNode; } return true; } var walkinput = function (forward) { var focused = document.commandDispatcher.focusedElement; var current = null; var next = null; var prev = null; var list = []; (function (frame) { var doc = frame.document; if (doc.body.localName.toLowerCase() == 'body') { let r = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (let i = 0, l = r.snapshotLength; i < l; ++i) { let e = r.snapshotItem(i); if (!isVisible(e)) continue; let ef = {element: e, frame: frame}; list.push(ef); if (e == focused) { current = ef; } else if (current && !next) { next = ef; } else if (!current) { prev = ef; } } } for (let i = 0; i < frame.frames.length; i++) arguments.callee(frame.frames[i]); })(content); if (list.length <= 0) return; var elem = forward ? (next || list[0]) : (prev || list[list.length - 1]); if (!current || current.frame != elem.frame) elem.frame.focus(); elem.element.focus(); }; let mapForward = liberator.globalVariables.walk_input_map_forward || ' ' let mapBackward = liberator.globalVariables.walk_input_map_backward || ' ' mappings.addUserMap([modes.NORMAL, modes.INSERT], mapForward.split(/\s+/), 'Walk Input Fields (Forward)', function () walkinput(true)); mappings.addUserMap([modes.NORMAL, modes.INSERT], mapBackward.split(/\s+/), 'Walk Input Fields (Backward)', function () walkinput(false)); })();