Skip to content
This repository was archived by the owner on Dec 30, 2024. It is now read-only.
WombatFromHell edited this page Sep 22, 2019 · 9 revisions

Writing new scripts

Create a new javascript file in the scripts directory and add to the manifest.json under "content_scripts": [...]. The script below assumes a common use-case that this is a script with an option and a sub-option (in Options panel).

const ExampleScript = {
    install(postElement, root_id, is_root_post) {
        // ...do things with the processPostEvent arguments here...
        getEnabledSuboption("example_suboption").then(response => {
            if (response) {
                // do things if the suboption is enabled...
            }
        });
    }
};

// load only if the Option 'example_script_option' is enabled...
addDeferredHandler(getEnabled("example_script_option"), (response) => {
    if (response) processPostEvent.addHandler(ExampleScript.install);
});

To write a script that only runs once when the page loads remove the parameters in the install function and replace the addDeferredHandler call with: fullPostsCompletedEvent.addHandler(ExampleScript.install);

Extension Storage (Options and Sub-Options)

Chrome Shack currently uses the WebExtensions storage facility which allows for pushing/retrieving javascript primitives into sandboxed browser storage. There are methods in settings.js that provide shortcuts for managing these settings primitives, for example:

getEnabled - takes an optional key argument. Looks up key values in the enabled_scripts array and returns the key name if found. This function is asynchronous and so it returns a resolved Promise once the call completes.

setEnabled - takes a required key argument. Pushes a key into the enabled_scripts array (avoiding exact duplicates). This function is asynchronous and so it returns a resolved Promise once the call completes.

removeEnabled - takes a required key argument. Removes a key from the enabled_scripts array if found. This function is asynchronous and so it returns a resolved Promise once the call completes.

getEnabledSuboption - takes an optional key argument. Looks up key values in the enabled_scripts array and returns the key name if found. This function is asynchronous and so it returns a resolved Promise once the call completes.

setEnabledSuboption - takes a required key argument. Pushes a key into the enabled_scripts array (avoiding exact duplicates). This function is asynchronous and so it returns a resolved Promise once the call completes.

removeEnabledSuboption - takes a required key argument. Removes a key from the enabled_scripts array if found. This function is asynchronous and so it returns a resolved Promise once the call completes.

getSetting - takes an optional key argument. Looks up key values in the root of the storage facility and returns the result. This function is asynchronous and so it returns a resolved Promise once the call completes.

setSetting - takes required key and value arguments. Sets a key with the value provided, in the root of the storage facility, overwriting any other exactly named key, and resolves when the call completes. This function is asynchronous and so it returns a Promise.

removeSetting - takes a required key argument. Removes a key from the root of the storage facility and resolves when the call completes. This function is asynchronous and so it returns a Promise.

Defining an Option or Sub-Option in the Options panel

You can define an Option or Sub-Option inside options.html. An Option is defined like so:

<h2>
    <input type="checkbox" class="script_check" id="new_option" />
    <label for="new_option">Example Option</label>
</h2>
<p class="info">Description for Example Option goes here.</p>

A Sub-Option can be defined like so (extending the above Option example):

<div id="new_option_settings">
    <div class="suboption indent">
        <input type="checkbox" class="suboption" id="new_suboption" />
        <label for="new_suboption">Description for Example Sub-Option goes here.</label>
    </div>
</div>

You would then retrieve whether or not the Option is enabled with:

getEnabled("new_option").then(async (response) => {
    // response is truthy if the option is found/enabled or falsey otherwise
    let suboptionEnabled = await getEnabledSuboption("new_suboption");
    // subOptionEnabled is truthy if the option is found/enabled or falsey otherwise
});

Events

The currently exposed list of events and their arguments when raised are as follows (live DOM refs are used when possible):

processPostEvent - passes three arguments: postElement, root_id, and is_root_post. This event is raised once for each post that is displayed.

processPostBoxEvent - passes one argument: inlineReplyElement. This event is raised each time the post box is opened.

fullPostsCompletedEvent - passes no arguments, so make sure to target DOM elements with document.querySelector or other similar methods. This is raised each time the full Chatty page or a Chatty thread link is opened.

processRefreshIntentEvent - passes three arguments: lastPostId, lastRootId, is_root, and from_reply. This event is raised when a refresh button is clicked on a root thread or post.

processEmptyTagsLoadedEvent - passes three arguments: postElement, rootElement, postHasTags, and rootHasTags. This event is raised when a post is opened that contains empty nuLOL tag data.

processTagDataLoadedEvent - passes three arguments: postElement, rootElement, postHasTags, and rootHasTags. This event is raised when a post is opened that contains updated nuLOL tag data.

processReplyEvent - passes one argument: parentId. This event is raised when a reply has been submitted (NOTE: as of right now, nuLOL tag data is not updated automatically upon submitting a reply; Chrome Shack uses a workaround instead, see processTagDataLoadedEvent above).

Notes

If your javascript events aren't getting called, it may be because the shack is importing the nodes you are modifying which strips the javascript from them. This is why there is an event that fires when the post box is displayed: the post box that exists when the page is first loaded is copied into the page when the reply button is clicked.

Clone this wiki locally