Skip to content

Instantly share code, notes, and snippets.

View example.css
div input {
background-color: lightgreen;
border-radius: 5px;
padding: 0 5px;
omarstreak / isStreakInstalled.js
Last active Apr 26, 2018
Check is Streak installed
View isStreakInstalled.js
var INSTALL_CHECK = 'chrome-extension://pnnfemgpilpdaojpnkjdgfgbnnjojfik/blank.png';
function isExtensionInstalled() {
//we have different logic for Chrome vs Safari
if(BrowserDetect.browser === 'Chrome'){
// the Chrome extension makes an image "web accessible", so we have the page try to load that image.
// if it loads successfully then the Streak extension is installed. If the image does not load successfully, then the image is not installed
var img = new Image();
img.onload = function() {
View contenteditable.html
<div contenteditable="true">
hi <span contenteditable="false">&lt;contact_givenName&gt;</span>,
How are you?
omarstreak / cursorEvents.js
Created Dec 18, 2017
Kefir cursor handling
View cursorEvents.js
Kefir.fromEvents(input, 'keyup'),
Kefir.fromEvents(input, 'input'),
Kefir.fromEvents(input, 'click'),
Kefir.fromEvents(input, 'focus')
.onValue(() => /* do some stuff */)
View pasteText.js
function pasteText({replacementText, cursorContext, activeQuery}: {replacementText: string; cursorContext: CursorContext; activeQuery: string;}){
// update text node content with replaced text
const lastIndex = cursorContext.textBeforeCursor.lastIndexOf(activeQuery);
cursorContext.textNode.textContent = cursorContext.textNodeContent.substring(0, lastIndex) + replacementText + cursorContext.textAfterCursor;
const selection = document.getSelection();
if(!selection) return;
// put cursor at the end of the replaced text
const range = document.createRange();
omarstreak / positionMenu.js
Created Dec 6, 2017
Positioning the menu at the caret
View positionMenu.js
import containByScreen from 'contain-by-screen';
function positionMenuAtCaret({menuContainer, cursorContext, activeQuery}: {menuContainer: HTMLElement; cursorContext: CursorContext; activeQuery: string;}){
let textNode = cursorContext.textNode;
const menuLeftEdgeCharaterPosition = Math.max(cursorContext.cursorCharacterPosition - activeQuery.length, 0);
const range = document.createRange();
range.setStart(textNode, menuLeftEdgeCharaterPosition);
range.setEnd(textNode, menuLeftEdgeCharaterPosition);
omarstreak / getCursorContext.js
Created Dec 6, 2017
Function to get information around cursor
View getCursorContext.js
/* @flow */
/* this code heavily borrows from */
export type CursorContext = {
textNode: Node;
textNodeParent: Node;
textNodeContent: string;
textBeforeCursor: string;
textAfterCursor: string;
omarstreak / load.js
Last active Oct 24, 2017
sdk load example
View load.js
InboxSDK.load(2, 'YOUR_APP_ID_HERE', {suppressAddonTitle: 'YOUR_ADD_ON_TITLE_HERE'}).then(function(sdk){
//more code
View compose.js
document.addEventListener('DOMNodeInserted', function(e){
function addButton(composeNode){
var button = $('<div class="wG J-Z-I"><div class="J-J5-Ji J-Z-I-Kv-H"><div class="J-J5-Ji J-Z-I-J6-H"><div class="aA7 aaA aMZ"><img src="//composeIcon" /></div></div></div></div>');{
View compose.js
To inject a button into composes there's 5 main strategies an extension developer can use, each strategy has large tradeoffs
mainly around performance and ease of implementation. The result is that most extension developers opt for the
easy to implement but poor performing strategy.
Strategy 1