From b5f488dfea88f1710abdc24ed84dc0d5a4045d8b Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Wed, 22 Aug 2012 14:48:39 -0400 Subject: [PATCH] hints are finally showing up on the pages. currently they are displayed for all the links on the page: document.links. This is to be replaced with proper subset of elements --- packages/hints.coffee | 57 ++++++++++++++++------- packages/marker.coffee | 72 ++++++++++++++++++++--------- resources/vimff.css | 101 +++++++++++++++++++++-------------------- 3 files changed, 145 insertions(+), 85 deletions(-) diff --git a/packages/hints.coffee b/packages/hints.coffee index bd09235..7af5c12 100644 --- a/packages/hints.coffee +++ b/packages/hints.coffee @@ -5,14 +5,33 @@ CONTAINER_ID = 'vimffHintMarkerContainer' HTMLDocument = Ci.nsIDOMHTMLDocument { Marker, getElementRect } = require 'marker' -createOrGetHintsContainer = (document) -> - if container = document.getElementById CONTAINER_ID - return container - else - container = document.createElement 'div' - container.id = CONTAINER_ID - document.body.appendChild container - return container +indexToHint = (i, chars) -> + return '' if i < 0 + + n = chars.length + l = Math.floor(i / n); k = i % n; + + return indexToHint(l - 1, chars) + chars[k] + +hintToIndex = (hint, chars) -> + return -1 if hint.length < 1 + + n = chars.length; m = hint.length + + i = chars.indexOf(hint[m - 1]) + if hint.length > 1 + base = hintToIndex(hint.slice(0, m - 1), chars) + i += (base + 1) * n + + return i + +getHintsContainer = (document) -> + document.getElementById CONTAINER_ID + +createHintsContainer = (document) -> + container = document.createElement 'div' + container.id = CONTAINER_ID + return container hasHints = (document) -> document.getUserData 'vimff.has_hints' @@ -22,27 +41,33 @@ addHints = (document, cb) -> removeHints document if document instanceof HTMLDocument - container = createOrGetHintsContainer document + container = createHintsContainer document + + start = new Date().getTime() - markers = [] + markers = {}; i = 0; for link in document.links if rect = getElementRect link - marker = new Marker(link, 'aa', container) - marker.show() - marker.setPosition rect.left, rect.top - markers.push marker + hint = indexToHint(i++, HINTCHARS) + marker = new Marker(link, container) + marker.setPosition rect + marker.setHint hint + markers[hint] = marker + + console.log new Date().getTime() - start, 'aaaaa' document.setUserData 'vimff.has_hints', true, null document.setUserData 'vimff.markers', markers, null + document.body.appendChild container + removeHints = (document) -> console.log hasHints document if hasHints document document.setUserData 'vimff.has_hints', undefined, null document.setUserData 'vimff.markers', undefined, null - container = createOrGetHintsContainer document - document.body.removeChild container + document.body.removeChild container if container = getHintsContainer document exports.addHints = addHints exports.removeHints = removeHints diff --git a/packages/marker.coffee b/packages/marker.coffee index 5ee5712..e82c134 100644 --- a/packages/marker.coffee +++ b/packages/marker.coffee @@ -1,43 +1,73 @@ class Marker - constructor: (@element, @chars, @container) -> + constructor: (@element, @container) -> document = @element.ownerDocument window = document.defaultView @markerElement = document.createElement 'div' @markerElement.className = 'vimffReset vimffHintMarker' - for char in @chars + + @container.appendChild @markerElement + + show: -> @markerElement.style.display = 'none' + hide: -> delete @markerElement.style.display + + setPosition: (rect) -> + @markerElement.style.left = rect.left + 'px' + @markerElement.style.top = rect.top + 'px' + + setHint: (@hint) -> + document = @element.ownerDocument + + while @markerElement.hasChildNodes() + @markerElement.removeChild @markedElement.firstChild + + for char in @hint span = document.createElement 'span' span.className = 'vimffReset' - span.textContent = char + span.textContent = char.toUpperCase() @markerElement.appendChild span - show: -> @container.appendChild @markerElement - hide: -> @container.removeChild @markerElement - - setPosition: (left, top) -> - @markerElement.style.left = left + 'px' - @markerElement.style.top = top + 'px' +# The login in this method is copied from Vimium for Chrome getElementRect = (element) -> document = element.ownerDocument window = document.defaultView docElem = document.documentElement body = document.body - rect = element.getBoundingClientRect() + clientTop = docElem.clientTop || body.clientTop || 0; + clientLeft = docElem.clientLeft || body.clientLeft || 0; + scrollTop = window.pageYOffset || docElem.scrollTop; + scrollLeft = window.pageXOffset || docElem.scrollLeft; + + rects = [rect for rect in element.getClientRects()] + rects.push element.getBoundingClientRect() + + for rect in rects + if rect.width > 2 and rect.height > 2 and \ + rect.top > -2 and rect.left > -2 and \ + rect.top < window.innerHeight - 2 and \ + rect.left < window.innerWidth - 2 + + return { + top: rect.top + scrollTop - clientTop; + left: rect.left + scrollLeft - clientLeft; + width: rect.width + height: rect.height + } + + # If the element has 0 dimentions then check what's inside. + # Floated or absolutely positioned elements are of particular interest + for rect in rects + if rect.width == 0 or rect.height == 0 + for childElement in element.children + computedStyle = window.getComputedStyle childElement, null + if computedStyle.getPropertyValue 'float' != 'none' or \ + computedStyle.getPropertyValue 'position' == 'absolute' - if rect.width > 0 and rect.height > 0 - clientTop = docElem.clientTop || body.clientTop || 0; - clientLeft = docElem.clientLeft || body.clientLeft || 0; - scrollTop = window.pageYOffset || docElem.scrollTop; - scrollLeft = window.pageXOffset || docElem.scrollLeft; + return childRect if childRect = getElementRect childElement - return { - top: rect.top + scrollTop - clientTop; - left: rect.left + scrollLeft - clientLeft; - width: rect.width - height: rect.height - } + return undefined exports.Marker = Marker exports.getElementRect = getElementRect diff --git a/resources/vimff.css b/resources/vimff.css index 92329f8..a0528a7 100644 --- a/resources/vimff.css +++ b/resources/vimff.css @@ -10,59 +10,64 @@ a:hover.vimffReset, td.vimffReset, tr.vimffReset { - background: none; - border: none; - bottom: auto; - box-shadow: none; - color: black; - cursor: auto; - display: inline; - float: none; - font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif; - font-size: inherit; - font-style: normal; - font-variant: normal; - font-weight: normal; - height: auto; - left: auto; - letter-spacing: 0; - line-height: 100%; - margin: 0; - max-height: none; - max-width: none; - min-height: 0; - min-width: 0; - opacity: 1; - padding: 0; - position: static; - right: auto; - text-align: left; - text-decoration: none; - text-indent: 0; - text-shadow: none; - text-transform: none; - top: auto; - vertical-align: baseline; - white-space: normal; - width: auto; - z-index: 99999999; + background: none; + border: none; + bottom: auto; + box-shadow: none; + color: black; + cursor: auto; + display: inline; + float: none; + font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif; + font-size: inherit; + font-style: normal; + font-variant: normal; + font-weight: normal; + height: auto; + left: auto; + letter-spacing: 0; + line-height: 100%; + margin: 0; + max-height: none; + max-width: none; + min-height: 0; + min-width: 0; + opacity: 1; + padding: 0; + position: static; + right: auto; + text-align: left; + text-decoration: none; + text-indent: 0; + text-shadow: none; + text-transform: none; + top: auto; + vertical-align: baseline; + white-space: normal; + width: auto; + z-index: 99999999; } div.vimffHintMarker { - position: absolute; - display: block; - top: -1px; - left: -1px; - white-space: nowrap; - overflow: hidden; - font-size: 11px; - padding: 1px 3px 0px 3px; - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785), color-stop(100%,#FFC542)); - border: solid 1px #C38A22; - border-radius: 3px; - box-shadow: 0px 3px 7px 0px rgba(0, 0, 0, 0.3); + position: absolute; + display: block; + top: -1px; + left: -1px; + white-space: nowrap; + overflow: hidden; + font-size: 11px; + padding: 1px 3px 0px 3px; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785),color-stop(100%,#FFC542)); + border: solid 1px #C38A22; + border-radius: 3px; + box-shadow: 0px 3px 7px 0px rgba(0, 0, 0, 0.3); + background-color: yellow; +} + +div > .vimiumHintMarker > .matchingCharacter { } + div.vimffHintMarker span { color: #302505; font-family: Helvetica, Arial, sans-serif; -- 2.39.3