Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- multiple command key shortcuts 19Jan2019
- Function:
- command + s to save the post.
- command + control + command + h Toggles between showing the underlying html and back to normal.
- Note: Apple filters the html.
- future commands
- select picture
- quote
- strikeout
- Intercepts command + s. "Clicks" on save/edit button. Prevent command+s bubbling.
- interesting
- https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
- https://discussions.apple.com/thread/250079673?page=1
- from Greasemonkey hacks: tips & Tools for Remixing the web with Firefox
- by Julien Couvreur
- Code from book with his gracious permission
- Javascript: The Definitive Guide 6th Edition
- Avoids use of jquery. jquery is not working for me at this time.
- https://stackoverflow.com/questions/2878983/capture-key-press-without-placing-an-input-element-on-the-page
- window.addEventListener('keydown', function (e) {
- if (e.ctrlKey && e.keyCode == 90) {
- // Ctrl + z pressed
- }
- });
- What html characters do we need to escape?
- < (<)
- > (>)
- & (&)
- " double-quote (")
- ' single quote (')
- https://www.w3.org/International/questions/qa-escapes#use
- Support for full regular expressions in include and exclude rules is also available.
- If the rule both starts and ends with a forward-slash (/) character,
- the contents inside those slashes are interpreted as a regular expression.
- two types of url's we need to handle:
- https://discussions.apple.com/thread/250075737
- https://discussions.apple.com/create/question?communityId=2206020
- https://discussions.apple.com/create/userTip?communityId=2206020
- https://discussions.apple.com/docs/DOC-250000368
- */
- /* eslint */
- /* https://eslint.org/docs/rules/no-multi-spaces */
- /* Most of these rule adjustment don't work in */
- /* this browser :-(. */
- /* eslint "ignoreEOLComments": "off", "ignoreComments": "off" */
- // /*eslint no-caller: "error"*/
- // /* eslint no-multi-spaces: ["error", { ignoreEOLComments: true }] */
- // ==UserScript==
- // @name multiple command key shortcuts 19Jan2019
- // @namespace bubo-bubo/gmscripts
- // @description Implement save and html edit shortcut.
- // @include /https://discussions\.apple\.com/+thread/+.*/
- // @include /https://discussions\.apple\.com/create/question.*/
- // @include /https://discussions\.apple\.com/create/userTip.*/
- // @include /https://discussions\.apple\.com/docs/.*/
- // @version 19Jan2019
- // @grant none
- // ==/UserScript==
- var debug = 2; // 0 -- no debug
- // 1 -- normal debug
- // 2 -- intense debug
- // Keeps tracks of what stage we are in our HTML edit.
- // 0 is not editing
- // 1 is editing. Thereby displaying actually html.
- var trackHTMLEdit = false;
- // Is event listner load deployed?
- var deployListnerLoad = false;
- let aDate = new Date();
- console.log ("====> starting command key shortcuts. " + aDate);
- // Setup once page is loaded.
- // This program monitors incoming keypress. When a known key is observed, this program takes the
- // assigned action.
- /* Most likely will be interactive.
- The script will run after the main page is loaded, but before other resources
- (images, style sheets, etc.) have loaded.
- https://wiki.greasespot.net/Metadata_Block#.40run-at */
- if (debug) console.log("document.readyState is " + document.readyState);
- // ready to roll? More stuff for later?
- if (document.readyState=="complete") {
- console.log("rolling along")
- // rolling along
- pageLoadComplete()
- }
- else {
- if (debug>=2) console.log('adding listeners')
- // wait out page loading.
- window.addEventListener("load",
- pageLoadComplete,
- true);
- deployListnerLoad = true;
- }
- // register event listeners
- // nothing like starting at the end ;-)
- window.addEventListener('unload',
- function(e)
- {
- if (debug) console.log('unloading.');
- // may not be needed. Wonder if that is bad?
- if (deployListnerLoad) {
- window.removeEventListener("load",
- pageLoadComplete,
- true);
- deployListnerLoad = false;
- }
- window.removeEventListener("keypress",
- processKey,
- false);
- if (debug) console.log('removing e.type is '+ e.type + " arg is " + arguments.callee);
- // remove anonymous unload. [ Thus unload ]
- window.removeEventListener(e.type,
- arguments.callee,
- true);
- },
- true);
- // last set value is returned as return code.
- var done;
- done = 0;
- // -----------------------------------------------------------------------------
- function pageLoadComplete() {
- if (debug>=2) console.log("All page resources finished loading!")
- // find how many reply buttons there are. Not used for nothing.
- var theNodes = document.querySelectorAll(
- "button.button.button-black:not(.hidden):not(.button-checked)")
- if (debug>=2) spew ("theNodes",theNodes)
- if (debug)console.log("let's get started.")
- /* Let's get started. */
- processPage()
- } // end function pageLoadComplete
- /* --------------------------------------------------------------------- */
- /* main line code */
- function processPage() {
- if (debug) console.log ("--> processPage. ");
- /* Who knows, we might have to wait a bit */
- /* <div class="editor-section"> */
- //var theNode = document.querySelector("div.editor-section")
- var theNode = document.querySelector("div#main-content")
- console.log("theNode is ",theNode)
- theNode.addEventListener("keypress",
- processKey,
- false);
- if (debug) console.log ("done with processPage ");
- } // end of processPage
- // -----------------------------------------
- function processKey(event) {
- if (debug) console.log("in processKey with event input event",event)
- if (debug>=2) {
- console.log(" event.altKey is " + event.altKey)
- console.log(" event.ctrlKey is " + event.ctrlKey)
- console.log(" event.metaKey is " + event.metaKey)
- console.log(" event.shiftKey is " + event.shiftKey)
- if ( event.charCode === 115){
- console.log (" s ")
- }
- if (event.metaKey){
- console.log (" event.metaKey ")
- }
- } // end if debug
- // Check modifier keys
- if (event.altKey) {
- // skip
- if (debug>=2) console.log (" skipping altKey! no actions assigned.")
- }
- else if (event.shiftKey) {
- // skip
- if (debug>=2) console.log (" skipping shiftKey! no actions assigned.")
- }
- // meta key is required for save, html edit, quote and select picture
- else if (event.metaKey) {
- if (debug>=2) console.log (" metaKey found!")
- // control key is required for html edit, quote and select picture
- if (event.ctrlKey) {
- if (debug>=2) console.log (" ctrlKey found!")
- // could be command + control + h for html edit
- if (event.charCode === 104) {
- if (debug>=2) console.log (" command + control + h!")
- htmlEdit(event)
- }
- // could be command + control + p for pick picture
- else if (event.charCode === 112) {
- if (debug>=2) console.log (" command + control + p!")
- }
- } // end of ctrlKey
- else {
- if (debug>=2) console.log (" processing metaKey!")
- // could be command + s for save post
- if (event.charCode === 115 ){
- if (debug>=2) console.log (" found command + s!")
- // <div class="editor-section hidden">
- // ... clipped ...
- // <button class="button" data-action="submit-post">Post</button>
- // same for repy and edit.
- // div.editor-section
- // let saveButton = document.querySelector('button.button[data-action="submit-post"]')
- // noticed after reply, reminants are left hidden :-(. So, avoid hidden.
- let saveButton = document.querySelector(
- 'div.editor-section:not(.hidden) button.button[data-action="submit-post"]')
- if (debug>=2) console.log ("saveButton is ",saveButton)
- if (saveButton) {
- clickAnchorTag(saveButton)
- // we will take control of command+s, so don't pass up to other event handlers.
- event.preventDefault()
- }
- else {
- if (debug) console.log("We have no reply to save; bubble up.")
- }
- } // 115 or s
- } // end of else not control key
- } // metaKey
- //GetDescriptionFor(e," ")
- if (debug>=1) console.log(" done with processKey")
- } // end of processKey
- /* --------------------------------------------------------------------- */
- function htmlEdit(event)
- {
- /*
- This html is for the reply and edit reply. There is a slightly different format for
- a new post and a user tip.
- <div class="editor-section">
- <div id="editor-placeholder" ... >
- <div class="editor ql-container" ... >
- <div class="ql-editor"
- data-gramm="false"
- data-placeholder="Tell us what’s on your mind."
- contenteditable="true">
- */
- // find the editor section.
- // Reply and Edit Reply catch first selector.
- // Create new post and new user tip catch on second selector.
- let saveTextNode = document.querySelector(
- 'div.editor-section:not(.hidden) div#editor-placeholder div.ql-editor, section.create-post div.editor.ql-container div.ql-editor')
- if (debug>=2) console.log("saveTextNode is ",saveTextNode)
- // is the user really doing an edit?
- if (saveTextNode) {
- // should we begin the HTML edit?
- if (trackHTMLEdit===false) {
- // request to edit.
- let savedInnerHTML = saveTextNode.innerHTML
- if (debug>=2) console.log("savedInnerHTML is ",savedInnerHTML)
- // Convert display to HTML
- // amazing.
- // https://stackoverflow.com/questions/6234773/can-i-escape-html-special-chars-in-javascript
- saveTextNode.innerText = savedInnerHTML
- // toggle
- trackHTMLEdit = true
- // we will take control of control + command + h, so don't pass up
- // to other event handlers.
- event.preventDefault()
- }
- else {
- // end HTML edit. Convert to regular text.
- if (debug>=2) console.log("displaying html. Convert back. ")
- // already doing HTML edit.
- let displayedText=saveTextNode.innerText
- if (debug>=2) console.log("displayedText is ",displayedText)
- saveTextNode.innerHTML = displayedText
- // toggle
- trackHTMLEdit = false
- // we will take control of control + command + h, so don't pass up
- // to other event handlers.
- event.preventDefault()
- }
- } // end doing an edit found "right" node
- else {
- if (debug) console.log("reply edit note not found.")
- }
- } // end of function htmlEdit
- /* --------------------------------------------------------------------- */
- function GetDescriptionFor(e,inDent)
- {
- console.log (inDent + "in GetDescriptionFor")
- console.log (inDent + "e.keyCode is " + e.keyCode )
- console.log (inDent + "e.keyCode in hex is " +toHexString(e.keyCode,inDent+" ") )
- var result, code;
- if ((e.charCode) && (e.keyCode==0))
- {
- result = "charCode: " + e.charCode;
- code = e.charCode;
- } else {
- result = "keyCode: " + e.keyCode;
- code = e.keyCode;
- }
- if (code == 8) result += " BKSP"
- else if (code == 9) result += " TAB"
- else if (code == 46) result += " DEL"
- else if ((code >= 41) && (code <=126)) result += " '" + String.fromCharCode(code) + "'";
- if (e.altKey) result += " alt";
- if (e.ctrlKey) result += " ctrl";
- if (e.metaKey) result += " meta";
- if (e.shiftKey) result += " shift";
- console.log (inDent + "result is " + result)
- return result;
- } // end of GetDescriptionFor
- /* --------------------------------------------------------------------- */
- /* print out objects:
- https://stackoverflow.com/questions/957537/how-can-i-display-a-javascript-object
- https://code-maven.com/logging-javascript-objects
- */
- function spew (objName,inputObj) {
- if (debug>=1) console.log ("starting spew")
- if (debug>=2) {
- console.log (objName + " is: ", inputObj)
- console.log ("inputObj.length is " + inputObj.length)
- console.log ("typeof inputObj is " + typeof inputObj)
- //this will show object gandalf IN ALL BROWSERS!
- console.log(JSON.stringify(inputObj));
- //this will show object gandalf IN ALL BROWSERS! with beautiful indent
- console.log(JSON.stringify(inputObj, null, 4));
- console.log("keys",Object.keys(inputObj));
- console.log("lenght is " + Object.keys(inputObj).length)
- console.log(Object.values(inputObj));
- //There is also this new option if you're using ECMAScript 2016 or newer:
- try {
- Object.keys(inputObj).forEach(e => console.log(`key=${e} value=${inputObj[e]}`));
- }
- catch (err) {
- console.log (" You must need ECMAScript 2016 or newer \""+ err.message + "\"" )
- } // end catch
- } // end of if debug printing code
- if (debug>=1) console.log ("ending spew")
- } // end of function spew
- // -----------------------------------------
- // https://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript
- function toHexString(value,inDent) {
- let hexString = value.toString(16);
- if (debug>=2) console.log (inDent + "hexString is " + hexString)
- if (hexString.length % 2) {
- hexString = '0' + hexString;
- }
- return hexString;
- } // end of toHexString
- /* --------------------------------------------------------------------- */
- /* based on:
- https://stackoverflow.com/questions/902713/how-do-i-programmatically-click-a-link-with-javascript
- */
- function clickAnchorTag(inputObj) {
- if (debug>=1) console.log("in clickAnchorTag.\n inputObj is",inputObj)
- var event = document.createEvent('MouseEvent');
- if (debug>=2) console.log ("proceeding to set new event")
- event = new CustomEvent('click');
- if (debug>=2) console.log ("clicking...")
- inputObj.dispatchEvent(event);
- } // end of clickAnchorTag
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement