NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Listener Tools // @license MPL-2.0 // @namespace https://github.com/AmicableBruda/7cups // @supportURL https://github.com/AmicableBruda/7cups/issues // @updateUrl https://github.com/AmicableBruda/7cups/raw/master/Listener%20Tools%20Update.user.js // @downloadURL https://github.com/AmicableBruda/7cups/raw/master/Listener%20Tools.user.js // @version 0.5 // @description Listener improvements for the 7cups.com chat interface. // @author AmicableBruda // @match https://www.7cups.com/*/connect/conversation* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // ==/UserScript== /* DISCLAIMER I'm not affiliated with 7 Cups in any official capacity and 7 Cups has NOT approved me or this code for use on their website. This code is licensed under the MPL 2.0 open source license. */ var resourceLinks = [ "http://suicide.org/", "https://www.7cups.com/12-step-working-guide/", "https://www.7cups.com/7cups-for-the-searching-soul/", "https://www.7cups.com/adhd/", "https://www.7cups.com/act-therapy-techniques/", "https://www.7cups.com/alcohol-drug-abuse/", "https://www.7cups.com/anxiety-help/", "https://www.7cups.com/managing-bipolar/", "https://www.7cups.com/boundaries/", "https://www.7cups.com/breakup-advice/", "https://www.7cups.com/bullying/", "https://www.7cups.com/chronic-pain/", "https://www.7cups.com/how-to-adjust-to-college-life/", "https://www.7cups.com/schizophrenia-listeners/", "https://www.7cups.com/depression-help-online/", "https://www.7cups.com/diabetes-cbt/", "https://www.7cups.com/eating-disorder-help/", "https://www.7cups.com/how-to-get-motivated-to-exercise/", "https://www.7cups.com/family-stress/", "https://www.7cups.com/managing-finances/", "https://www.7cups.com/forgiveness/", "https://www.7cups.com/getting-unstuck/", "https://www.7cups.com/grief/", "https://www.7cups.com/how-to-deal-with-loneliness/", "https://www.7cups.com/help-managing-emotions/", "https://www.7cups.com/ocd/", "https://www.7cups.com/panic-attacks-help-online/", "https://www.7cups.com/online-parenting-course/", "https://www.7cups.com/ypoc-guide/", "https://www.7cups.com/perinatal-support-listeners/", "https://www.7cups.com/psychological-first-aid/", "https://www.7cups.com/self-harm/", "https://www.7cups.com/sleeping-well/", "https://www.7cups.com/social-anxiety/", "https://www.7cups.com/startup-support/", "https://www.7cups.com/domestic-assault-survivor/", "https://www.7cups.com/how-to-overcome-test-taking-anxiety/", "https://www.7cups.com/traumatic-experience-help/", "https://www.7cups.com/weight-management/", "https://www.7cups.com/work-related-stress/" ]; GM_addStyle(` .lt-social-dropbtn, .lt-resource-dropbtn { width: 25px; border-radius:8px; background: white; border: 1px outset #0275d8; font-weight: bold; font-size: 12px; color: #0275d8; margin-top: 0px } .lt-resource-dropbtn {} .lt-resource-dropdown { top: 23px; } .lt-social-dropdown, .lt-resource-dropdown { z-index:1; margin-left: 4px; margin-top: 2px; } .lt-social-dropdown-content, .lt-resource-dropdown-content { min-width: 320px; max-height: 400px; border: 1px solid #1e90fe; border-radius: 10px; background: white; padding: 10px; z-index: 2; overflow-x: hidden; overflow-y: auto; left: 0px; bottom: 0px; } #lt-social-input { width:225px; margin-bottom: 5px; } #lt-resource-input { width:240px; margin-bottom: 5px; } `); // load stored socials or defaults function loadSocials() { let socials = GM_getValue("lt-social"); if (socials === undefined) { socials = []; socials.push("Hello! How are you?"); socials.push("Hello! How is everyone?"); socials.push("Welcome to 7 Cups! How are you?"); let json = JSON.stringify(socials); if (json) { GM_setValue("lt-social", json); } else { console.log("Error creating social JSON."); } } else { socials = JSON.parse(socials); } return socials; } // load stored resources or defaults function loadResources() { let resources = GM_getValue("lt-resource"); if (resources === undefined) { resources = []; resources = resourceLinks; let json = JSON.stringify(resources); if (json) { GM_setValue("lt-resource", json); } else { console.log("Error creating resources JSON"); } } else { resources = JSON.parse(resources); } return resources; } /* ClickList object constructor A list of elements that insert their string content into the chat input box when clicked. itemClass - specifice the css class used for the items. items - array of strings titleCreator - a function that takes one argument 'string' and is called on each item to create the link text displayed in the html list. 'string' contains the item's full string. */ function ClickList(itemClass, items, titleCreator) { let ob = this; let clickFunc = function() { document.querySelector("#chatForm textarea#Comment").value = this.getAttribute("string"); }; ob.itemClass = itemClass; ob.newItem = function (string) { let a = document.createElement("a"); a.setAttribute("href", "#"); a.setAttribute("class", ob.itemClass); a.setAttribute("string", string); a.setAttribute("title", string); a.innerHTML = ob.createTitle(string); //todo: add string replace for web urls a.addEventListener("click", clickFunc); return a; }; ob.createTitle = titleCreator; ob.append = function (string) { let item = ob.newItem(string); ob.element.appendChild(item); ob.element.appendChild(document.createElement("br")); }; ob.prepend = function (string) { let item = ob.newItem(string); ob.element.insertBefore(document.createElement("br"), ob.element.childNodes[0]); ob.element.insertBefore(item, ob.element.childNodes[0]); }; ob.element = document.createElement("div"); for (let i = 0; i < items.length; i++) { ob.append(items[i]); } } /* SaveForm object constructor An input form used to add new strings to an existing clickList and stored string array. id - CSS id used in form html elements (example-form, example-input, example-button) placeholder - Text to display as placeholder in html input box. clickList - The clickList that this form saves to. */ function SaveForm(id, placeholder, clickList) { let ob = this; ob.id = id; ob.list = clickList; ob.save = function () { let text = ob.input.value; ob.list.prepend(text); let json = GM_getValue(ob.id), storedList = JSON.parse(json); let newList = []; newList.push(text); storedList.forEach(function(elem) { newList.push(elem); }); GM_setValue(ob.id, JSON.stringify(newList)); ob.input.value = ""; }; ob.element = document.createElement("form"); ob.input = document.createElement("input"); ob.button = document.createElement("button"); ob.element.setAttribute("id", `${id}-form`); ob.input.setAttribute("id", `${id}-input`); ob.input.setAttribute("placeholder", placeholder); ob.button.setAttribute("id", `${id}-button`); ob.button.setAttribute("onclick", "return false;"); ob.button.innerHTML = "+"; ob.button.addEventListener("click", ob.save); ob.element.appendChild(ob.input); ob.element.appendChild(ob.button); } /* HoverMenu object constructor A hover menu that displays its content on mouseover. id - CSS id used for the menu and to customize the CSS class of child elements (example-dropbt, example-dropdown, example-dropdown-content). title - Text used for elements menu button. */ function HoverMenu(id, title) { let ob = this; ob.id = id; ob.title = title; ob.button = document.createElement("button"); ob.button.setAttribute("class", `${id}-dropbtn`); ob.button.style.position = "absolute"; ob.button.innerHTML = this.title; ob.content = document.createElement("div"); ob.content.setAttribute("class", `${id}-dropdown-content`); ob.content.style.position = "absolute"; ob.content.style.display = "none"; ob.element = document.createElement("div"); ob.element.setAttribute("class", `${id}-dropdown`); ob.element.style.position = "absolute"; ob.element.style.display = "inline-block"; ob.element.appendChild(this.button); ob.element.appendChild(this.content); ob.element.addEventListener("mouseover", function() { ob.content.style.display = "block"; }); ob.element.addEventListener("mouseout", function() { ob.content.style.display = "none"; }); } var socials = loadSocials(); var resources = loadResources(); (function() { 'use strict'; var sTitleFunc = function (string) { return string.substring(0, 43); }; var socialList = new ClickList("click-item", socials, sTitleFunc); var socialMenu = new HoverMenu("lt-social", "S"), socialSave = new SaveForm("lt-social", "Add new social comment here", socialList); GM_registerMenuCommand("Reset Socials", function() { // register option in Tampermonkey menu for deleting stored socials if (confirm("Reset Socials to default?")) { GM_deleteValue("lt-social"); socials = loadSocials(); socialList = new ClickList("click-item", socials, sTitleFunc); let newSave = new SaveForm("lt-social", "Add new social comment here", socialList); socialMenu.content.innerHTML = ""; socialMenu.content.appendChild(newSave.element); socialMenu.content.appendChild(socialList.element); } }, "S"); var rTitleFunc = function (string) { return string.replace(/^https:\/\/www.7cups.com\//, "").replace(/\/$/, "").substring(0, 43); }; var resourceList = new ClickList("click-item", resources, rTitleFunc); var resourceMenu = new HoverMenu("lt-resource", "R"), resourceSave = new SaveForm("lt-resource", "Add new resource link here", resourceList); GM_registerMenuCommand("Reset Resources", function() { // register option in Tampermonkey menu for deleting stored Resources if (confirm("Reset Resources to default?")) { GM_deleteValue("lt-resource"); resources = loadResources(); let resourceList = new ClickList("click-item", resources, rTitleFunc); let newSave = new SaveForm("lt-resource", "Add new resource link here", resourceList); resourceMenu.content.innerHTML = ""; resourceMenu.content.appendChild(newSave.element); resourceMenu.content.appendChild(resourceList.element); } }, "R"); var chatForm = document.getElementById("chatForm"), parent = chatForm.parentNode; socialMenu.content.appendChild(socialSave.element); socialMenu.content.appendChild(socialList.element); parent.insertBefore(socialMenu.element, chatForm); resourceMenu.content.appendChild(resourceSave.element); resourceMenu.content.appendChild(resourceList.element); parent.insertBefore(resourceMenu.element, chatForm); })();