text-aid-too
Version:
Edit web inputs (including on GMail) with your favourite native text editor; and (experimentally) use markdown.
108 lines (88 loc) • 3.13 kB
text/coffeescript
frame = 1 + Math.floor 999999999 * Math.random()
isTriggerEvent = do ->
properties = [ "altKey", "ctrlKey", "shiftKey", "keyCode" ]
(key, event) ->
for property in properties
return false unless event[property] == key[property]
true
contentCache = {}
getElementContent = (element, id) ->
if contentCache[id]?
contentCache[id]
else if element.isContentEditable
element.innerHTML
else
element.value
setElementContent = (element, request) ->
contentCache[request.id] = request.originalText if request.originalText?
if element.isContentEditable
element.innerHTML = request.text
else
element.value = request.text
clearElementContent = (event) ->
if element = getElement()
id = Common.identity.getId element
delete contentCache[id] if id? and contentCache[id]?
true
editElement = (element) ->
id = Common.identity.getId element
chrome.runtime.sendMessage
name: "edit"
text: getElementContent element, id
isContentEditable: element.isContentEditable
id: id
frame: frame
chrome.runtime.onMessage.addListener (request, sender) ->
if request.frame == frame and element = Common.identity.getObj request.id
setElementContent element, request
false
getElement = do ->
nonEditableInputs = [ "radio", "checkbox" ]
editableNodeNames = [ "textarea" ]
(element = document.activeElement) ->
nodeName = element.nodeName?.toLowerCase()
return element if false or
element.isContentEditable or
(nodeName? and nodeName == "input" and element.type not in nonEditableInputs) or
(nodeName? and nodeName in editableNodeNames)
null
installListener = (element, event, callback) ->
element.addEventListener event, callback, true
chrome.storage.sync.get "key", (items) ->
unless chrome.runtime.lastError
key = items.key
installListener window, "keydown", (event) ->
maintainIcon()
if isTriggerEvent(key, event) and element = getElement()
Common.log "keyboard hit, element:", element
event.preventDefault()
event.stopImmediatePropagation()
editElement element
return false
true
chrome.storage.onChanged.addListener (changes, area) =>
if area == "sync" and changes.key?.newValue?
key = changes.key.newValue
maintainIcon = do ->
showing = false
->
changed = false
if not showing and getElement()
showing = true
changed = true
else if showing and not getElement()
showing = false
changed = true
if changed
chrome.runtime.sendMessage name: "icon", showing: showing
Common.log "icon:", showing
true
for event in [ "focus", "blur" ]
installListener window, event, maintainIcon
installListener window, "keypress", clearElementContent