Skip to content

Instantly share code, notes, and snippets.

@omarstreak
omarstreak / example.css
Created June 4, 2018 23:13
Input button pill
div input {
background-color: lightgreen;
border-radius: 5px;
padding: 0 5px;
}
@omarstreak
omarstreak / isStreakInstalled.js
Last active April 26, 2018 22:55
Check is Streak installed
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() {
clearInterval(installTimerId);
<div contenteditable="true">
<div>
hi <span contenteditable="false">&lt;contact_givenName&gt;</span>,
</div>
<div>
How are you?
</div>
</div>
@omarstreak
omarstreak / cursorEvents.js
Created December 18, 2017 18:52
Kefir cursor handling
Kefir.merge([
Kefir.fromEvents(input, 'keyup'),
Kefir.fromEvents(input, 'input'),
Kefir.fromEvents(input, 'click'),
Kefir.fromEvents(input, 'focus')
])
.takeUntilBy(elementDestroyedObservable)
.debounce(100)
.onValue(() => /* do some stuff */)
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
omarstreak / positionMenu.js
Created December 6, 2017 23:10
Positioning the menu at the caret
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);
range.collapse(true);
@omarstreak
omarstreak / getCursorContext.js
Created December 6, 2017 22:53
Function to get information around cursor
/* @flow */
/* this code heavily borrows from https://github.com/zurb/tribute */
export type CursorContext = {
textNode: Node;
textNodeParent: Node;
textNodeContent: string;
textBeforeCursor: string;
textAfterCursor: string;
@omarstreak
omarstreak / load.js
Last active October 24, 2017 19:38
sdk load example
InboxSDK.load(2, 'YOUR_APP_ID_HERE', {suppressAddonTitle: 'YOUR_ADD_ON_TITLE_HERE'}).then(function(sdk){
//more code
});
document.addEventListener('DOMNodeInserted', function(e){
if(e.target.classList.contains('An')){
addButton(e.target);
}
});
$('.An').forEach(addButton);
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>');
button.click(function(e){
/*
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