|  | 
| 19 | 19 |     const SPINNING_ANIMATION = browser.extension.getURL("Spinning.json"); | 
| 20 | 20 |     const START_ANIMATION = browser.extension.getURL("Start.json"); | 
| 21 | 21 | 
 | 
| 22 |  | -    // This is a list of anchors on pages we are running stm on.  | 
| 23 |  | -    // In current order they are: google, ddg home, ddg search page, yahoo home, yahoo search page | 
| 24 |  | -    const ACCEPTABLE_ANCHORS = [ | 
| 25 |  | -        "sfdiv", | 
| 26 |  | -        "search_form_homepage", | 
| 27 |  | -        "seach_form", | 
| 28 |  | -        "uh-search-form", | 
| 29 |  | -        "sf" | 
| 30 |  | -    ]; | 
|  | 22 | + | 
|  | 23 | +    const getSTMAnchors = documentDomain => { | 
|  | 24 | +        switch (documentDomain) { | 
|  | 25 | +            case "www.google.com": | 
|  | 26 | +            case "www.google.ca": | 
|  | 27 | +            case "www.google.co.uk": | 
|  | 28 | +                return { | 
|  | 29 | +                    input: "lst-ib", | 
|  | 30 | +                    anchor: "sfdiv" | 
|  | 31 | +                } | 
|  | 32 | +            case "duckduckgo.com": | 
|  | 33 | +                if (document.body.classList.contains("body--serp")) { | 
|  | 34 | +                    return { | 
|  | 35 | +                        input: "search_form_input", | 
|  | 36 | +                        anchor: "search_form" | 
|  | 37 | +                    }; | 
|  | 38 | +                } | 
|  | 39 | +                return { | 
|  | 40 | +                    input: "search_form_input_homepage", | 
|  | 41 | +                    anchor: "search_form_homepage" | 
|  | 42 | +                }; | 
|  | 43 | +            case "ca.yahoo.com": | 
|  | 44 | +            case "uk.yahoo.com": | 
|  | 45 | +            case "www.yahoo.com": | 
|  | 46 | +                return { | 
|  | 47 | +                    input: "uh-search-box", | 
|  | 48 | +                    anchor: "uh-search-form" | 
|  | 49 | +                }; | 
|  | 50 | +            default: | 
|  | 51 | +                return null; | 
|  | 52 | +        } | 
|  | 53 | +    } | 
|  | 54 | + | 
| 31 | 55 | 
 | 
| 32 | 56 |     // Encapsulation of the popup we use to provide our UI. | 
| 33 | 57 |     const POPUP_WRAPPER_MARKUP = `<div id="stm-popup"> | 
| 34 |  | -        <div id="stm-header"><div role="button" tabindex="1" id="stm-close"></div></div> | 
| 35 |  | -        <div id="stm-inject"></div> | 
| 36 |  | -    </div>`; | 
|  | 58 | +            <div id="stm-header"><div role="button" tabindex="1" id="stm-close"></div></div> | 
|  | 59 | +            <div id="stm-inject"></div> | 
|  | 60 | +            <a href="https://qsurvey.mozilla.com/s3/voice-fill" id="stm-feedback" role="button" tabindex="2">Feedback</a> | 
|  | 61 | +        </div>`; | 
| 37 | 62 | 
 | 
| 38 | 63 |     // When submitting, this markup is passed in | 
| 39 |  | -    const SUBMISSION_MARKUP = ` | 
| 40 |  | -        <div id="stm-levels-wrapper"> | 
|  | 64 | +    const SUBMISSION_MARKUP = `<div id="stm-levels-wrapper"> | 
| 41 | 65 |             <canvas hidden id="stm-levels" width=720 height=310></canvas> | 
| 42 | 66 |         </div> | 
| 43 | 67 |         <div id="stm-animation-wrapper"> | 
|  | 
| 49 | 73 | 
 | 
| 50 | 74 |     // When Selecting, this markup is passed in | 
| 51 | 75 |     const SELECTION_MARKUP = `<form id="stm-selection-wrapper"> | 
| 52 |  | -        <div id="stm-list-wrapper"> | 
| 53 |  | -            <input id="stm-input" type="text" /> | 
| 54 |  | -            <div id="stm-list"></div> | 
| 55 |  | -        </div> | 
| 56 |  | -        <button id="stm-reset-button" title="reset"></button> | 
| 57 |  | -        <input id="stm-submit-button" type="submit" title="sumbit" value=""/> | 
| 58 |  | -    </form>` | 
|  | 76 | +            <div id="stm-list-wrapper"> | 
|  | 77 | +                <input id="stm-input" type="text" /> | 
|  | 78 | +                <div id="stm-list"></div> | 
|  | 79 | +            </div> | 
|  | 80 | +            <button id="stm-reset-button" title="reset" type="button"></button> | 
|  | 81 | +            <input id="stm-submit-button" type="submit" title="sumbit" value=""/> | 
|  | 82 | +        </form>`; | 
| 59 | 83 | 
 | 
| 60 | 84 |     const SpeakToMePopup = { | 
| 61 | 85 |         // closeClicked used to skip out of media recording handling | 
|  | 
| 142 | 166 |                     html += "</ul>"; | 
| 143 | 167 |                     list.innerHTML = html; | 
| 144 | 168 |                 } | 
| 145 |  | -                 | 
|  | 169 | + | 
| 146 | 170 |                 input.value = firstChoice.text; | 
| 147 | 171 |                 input.size = input.value.length; | 
| 148 | 172 | 
 | 
| 149 | 173 |                 if (list) { | 
| 150 | 174 |                     list.style.width = `${input.offsetWidth}px`; | 
| 151 | 175 |                 } | 
| 152 |  | -                 | 
|  | 176 | + | 
| 153 | 177 |                 input.focus(); | 
| 154 | 178 | 
 | 
| 155 | 179 |                 form.addEventListener("submit", function _submit_form(e) { | 
|  | 180 | +                    console.log('!!!!!!!!'); | 
| 156 | 181 |                     e.preventDefault(); | 
|  | 182 | +                    e.stopPropagation(); | 
| 157 | 183 |                     form.removeEventListener("submit", _submit_form); | 
| 158 | 184 |                     resolve(input.value); | 
| 159 | 185 |                 }); | 
| 160 | 186 | 
 | 
| 161 | 187 |                 list.addEventListener("click", function _choose_item(e) { | 
|  | 188 | +                    e.preventDefault(); | 
| 162 | 189 |                     list.removeEventListener("click", _choose_item); | 
| 163 | 190 |                     if (e.target instanceof HTMLLIElement) { | 
| 164 | 191 |                         resolve(e.target.textContent); | 
| 165 | 192 |                     } | 
| 166 | 193 |                 }); | 
| 167 | 194 | 
 | 
|  | 195 | +                list.addEventListener("keypress", function _choose_item(e) { | 
|  | 196 | +                    e.preventDefault(); | 
|  | 197 | +                    const key = e.which || e.keyCode; | 
|  | 198 | +                    if (key === 13) { | 
|  | 199 | +                        list.removeEventListener("click", _choose_item); | 
|  | 200 | +                        if (e.target instanceof HTMLLIElement) { | 
|  | 201 | +                            resolve(e.target.textContent); | 
|  | 202 | +                        } | 
|  | 203 | +                    } | 
|  | 204 | +                }); | 
|  | 205 | + | 
| 168 | 206 |                 reset.addEventListener("click", function _reset_click(e) { | 
|  | 207 | +                    console.log('reject'); | 
|  | 208 | +                    e.preventDefault(); | 
| 169 | 209 |                     close.removeEventListener("click", _reset_click); | 
| 170 | 210 |                     reject(e.target.id); | 
| 171 | 211 |                 }); | 
| 172 | 212 | 
 | 
| 173 | 213 |                 close.addEventListener("click", function _close_click(e) { | 
|  | 214 | +                    e.preventDefault(); | 
| 174 | 215 |                     close.removeEventListener("click", _close_click); | 
| 175 | 216 |                     reject(e.target.id); | 
| 176 | 217 |                 }); | 
|  | 
| 184 | 225 |     class SpeakToMeIcon { | 
| 185 | 226 |         constructor() { | 
| 186 | 227 |             console.log(`SpeakToMeIcon constructor ${this}`); | 
|  | 228 | +            const register = getSTMAnchors(document.domain); | 
| 187 | 229 |             this.icon = document.createElement("button"); | 
| 188 | 230 |             this.icon.classList.add("stm-icon"); | 
| 189 | 231 |             this.icon.classList.add("stm-hidden"); | 
| 190 | 232 |             this.hasAnchor = false; | 
| 191 |  | -            document.body.appendChild(this.icon); | 
|  | 233 | +            this.input = document.getElementById(register.input); | 
|  | 234 | +            this.anchor = document.getElementById(register.anchor); | 
| 192 | 235 | 
 | 
| 193 |  | -            this.icon.addEventListener("click", on_stm_icon_click); | 
| 194 |  | - | 
| 195 |  | -            const self = this; | 
| 196 |  | - | 
| 197 |  | -            // Note: remove the event so and toggle has anchor to ensure the anchor doesn't move around | 
| 198 |  | -            document.body.addEventListener("focusin", function _set_anchor(event) { | 
| 199 |  | -                if (event.target.id === "stm-input") { | 
| 200 |  | -                    return; | 
| 201 |  | -                } | 
| 202 |  | -                self.anchor_to(event.target); | 
| 203 |  | -                self.hasAnchor = true; | 
| 204 |  | -            }); | 
| 205 |  | - | 
| 206 |  | -            // Check if an element is already focused in the document. | 
| 207 |  | -            if (document.hasFocus() && document.activeElement && !this.hasAnchor) { | 
| 208 |  | -                self.anchor_to(document.activeElement); | 
| 209 |  | -            } | 
| 210 |  | -        } | 
| 211 |  | - | 
| 212 |  | -        // util finding the right parent element for any given acceptable page | 
| 213 |  | -        // to add additional pages, review ACCEPTABLE_ANCHORS const above, and add appropriate pages to the manifest | 
| 214 |  | -        // TODO: this whole thing feels like a hack! | 
| 215 |  | -        find_ancestor(root_el) { | 
| 216 |  | -            let el = root_el; | 
| 217 |  | - | 
| 218 |  | - | 
| 219 |  | -            const currentNotAcceptable = (item, index, array) => { | 
| 220 |  | -                return item !== el.id; | 
| 221 |  | -            } | 
| 222 |  | - | 
| 223 |  | -            //traverse up the Dom Tree until it finds the right acceptable anchor | 
| 224 |  | -            // Dead end when we hit the body | 
| 225 |  | -            while (ACCEPTABLE_ANCHORS.every(currentNotAcceptable) && el !== document.body) { | 
| 226 |  | -                el = el.parentElement; | 
| 227 |  | -            } | 
| 228 |  | - | 
| 229 |  | -            return el; | 
| 230 |  | -        } | 
| 231 |  | - | 
| 232 |  | -        // this anchors the speak to me button to the closest acceptable DOM element (ui_anchor) and then unhides the button | 
| 233 |  | -        anchor_to(target) { | 
| 234 |  | -            console.log(`SpeakToMeIcon anchor_to ${target}`); | 
| 235 |  | - | 
| 236 |  | - | 
| 237 |  | -            if ( | 
| 238 |  | -                !( | 
| 239 |  | -                    target instanceof HTMLInputElement && | 
| 240 |  | -                    ["text", "email", "search"].indexOf(target.type) >= 0 | 
| 241 |  | -                ) | 
| 242 |  | -            ) { | 
| 243 |  | -                return; | 
|  | 236 | +            if (this.input.ownerDocument !== document) { | 
|  | 237 | +                return null; | 
| 244 | 238 |             } | 
| 245 | 239 | 
 | 
| 246 |  | -            const ui_anchor = this.find_ancestor(target); | 
| 247 |  | -            this._input_field = target; | 
| 248 |  | -            ui_anchor.style.position = "relative"; | 
| 249 |  | -            ui_anchor.append(this.icon); | 
|  | 240 | +            document.body.appendChild(this.icon); | 
|  | 241 | +            this.icon.addEventListener("click", on_stm_icon_click); | 
|  | 242 | +            this.input.focus(); | 
|  | 243 | +            this.anchor.style.position = "relative"; | 
|  | 244 | +            this.anchor.style.overflow = "visible"; | 
|  | 245 | +            this.anchor.append(this.icon); | 
| 250 | 246 |             this.icon.classList.remove("stm-hidden"); | 
| 251 | 247 |         } | 
| 252 | 248 | 
 | 
|  | 249 | + | 
| 253 | 250 |         set_input(text) { | 
| 254 | 251 |             console.log(`SpeakToMeIcon set_input ${text}`); | 
| 255 |  | -            this._input_field.value = text; | 
| 256 |  | -            this._input_field.focus(); | 
| 257 |  | -            this._input_field.form.submit(); | 
|  | 252 | +            this.input.value = text; | 
|  | 253 | +            this.input.focus(); | 
|  | 254 | +            this.input.form.submit(); | 
| 258 | 255 |         } | 
| 259 | 256 |     } | 
| 260 | 257 | 
 | 
|  | 
| 537 | 534 |     }; | 
| 538 | 535 | 
 | 
| 539 | 536 |     const stm_icon = new SpeakToMeIcon(); | 
| 540 |  | - | 
| 541 | 537 |     SpeakToMePopup.init(); | 
| 542 | 538 | 
 | 
| 543 | 539 | 
 | 
|  | 
0 commit comments