DO NOT TAKE THE CharaChorder APART!

The CharaChorder is not designed to be user serviceable at this time. If for some reason you need to, please contact the CharaChorder team by emailing [email protected] to get their advice before you attempt to do so. The switches are NOT designed to come off. If they come off during shipment make sure to document which one and let the team know. They will instruct you to very carefully put it back on, but it is best to let them know in case it causes issues later on.

Do not take the CharaChorder apart. Without the right training and tools, you will damage the switches in the process of removing the keycaps. If you do this, it is at your own risk.

.step file for the CharaChorder Right Shell

RightShell.STEP

.step file for CharaChorder Base Plate

CharaChorder_Baseplate.stp

.step file for CharaChorder Bridge

CharaChorder One Bridge.STEP

.stl files for Switch caps

tallCap.STL

shortCap.STL

Make your own keymap graphics

new-cc-layout.ai

How to put the CharaChorder keyboard layout on Keybr.com and Monkeytype.com

<aside> 📢 I wanted a way to show a character map while training on keybr and Monkeytype

After some research, I learned that a browser extension called TamperMonkey is a good way to tweak websites around.

Tweaking websites. Sounds scary. I know. But it's simpler than I thought it would be.

Here is a YouTube video explaining the basics of how it works: https://www.youtube.com/watch?v=8tyjJD65zws

Your mission, should you choose to accept it:

Step 1: Install the extension from tampermonkey.net

Step 2: Click on the extension and choose "Create A New Script"

Step 3: Delete everything in there, then paste the code below

Step 4: File > Save (Ctrl+S for Windows, Command ⌘-S)

Step 5: Make sure the toggle with the name of this extension is turned on

Step 6: Refresh keybr.com

If you need help, ping me on Discord! @Joe Penna (MysteryGuitarMan)#7614

Many thanks to: @lamb#9364 designed the default background image @codyw#0101 figured out the time delay issue @MaVince#7027 for updating the script to work with Monkeytype

If you can code in javascript, please read on...

</aside>

// ==UserScript==
// @name         CharaChorder static keymap
// @namespace    TamperMonkey / Greasemonkey
// @version      0.5
// @description  Changes the QWERTY keyboard flashing display to a static image of the Charachorder layout
// @author       Various CharaChorder discord users
// @match        *://monkeytype.com/*
// @match        *://www.keybr.com/*
// @icon         <https://www.keybr.com/assets/934c99d37fc250c3.png>
// @grant        none
// ==/UserScript==

(function() {
  'use strict';

  // opacity of the image (percentage out of 100)
  const imgOpacity = 70;

  // width of the image (percentage out of 100)
  const imgWidth = 100;

  // Original
  const bgOriginal = '<https://cdn.discordapp.com/attachments/866811589930647612/932298486999838761/cc-layout-faded-white.png>';
  // White Background
  const bgWhite = '<https://cdn.discordapp.com/attachments/866811589930647612/932245256416686170/cc-minimal-whitebg.png>';
  // Black Background
  const bgBlack = '<https://cdn.discordapp.com/attachments/866811589930647612/932245256232112188/cc-minimal-invert.png>';

  // selected background - update this to the bg you want to use
  const imgUrl = bgWhite;

  // concatenating all of the strings above
  const htmlInject = `<center><img src="${imgUrl}" width="${imgWidth}%" style="opacity:${imgOpacity/100};filter:alpha(opacity=${imgOpacity})";>`;

  // the div id containing
  const monkeyId = 'keymap';

  let step = 0;

  // define function to complete overwriting html
  const injectHtml = (obs, div, html) => {
    div.innerHTML = html;
    obs.disconnect();
  }

  // using a MutationObserver to detect when the site loads the QWERTY image
  const observer = new MutationObserver((mutations, obs) => {

    let keybrDiv = document.querySelector('[data-key^="Key"]').closest('div');
    if (typeof keybrDiv === 'undefined') {
        keybrDiv = document.querySelector('main div > svg').parentNode;

        if (typeof keybrDiv === 'undefined') {
            keybrDiv = document.querySelector('main > div > div:nth-child(4)');
        }
    }
    const monkeyDiv = document.getElementById(monkeyId);
    if (keybrDiv) { // keybr case
      injectHtml(obs, keybrDiv, htmlInject);
    } else if (monkeyDiv) { // monkeytype case
      const hasHidden = monkeyDiv.className.includes('hidden');
      if (step == 0 && hasHidden) {
        step = 1;
      } else if (step == 1 && !hasHidden) {
        injectHtml(obs, monkeyDiv, htmlInject);
      }
    }
  });

  observer.observe(document, {
    childList: true,
    subtree: true
  });

})();