Last active
September 26, 2016 18:38
-
-
Save omarstreak/9d2de91fdbcb758f98e6f842e4b729e1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 | |
DOMInsertionNode | |
Pros: | |
- Relatively easy to implement | |
- Responsive (no popping when making modifications to new composes) | |
Cons: | |
- MASSIVE performance degredation | |
method used by popular gmail.js library | |
*/ | |
document.addEventListener('DOMNodeInserted', function(e){ | |
if(elementMatchesCompose(e.target)){ | |
broadcastCompose(e.target); | |
} | |
}); | |
// ======================== | |
/* | |
Strategy 2 | |
Global Mutation Observer | |
Similar to DOMInsertionNode | |
Pros: | |
- Responsive | |
- Easy to implement | |
Cons: | |
- Very bad performance | |
*/ | |
var observer = new MutationObserver(function(mutations) { | |
mutations.forEach(function(mutation) { | |
if(doesMutationMatchCompose(mutation)){ | |
var compose = getComposeFromMutation(mutation); | |
broadcastCompose(compose); | |
} | |
}); | |
}); | |
observer.observe(document.body, { childList: true, subtree: true }); | |
// ======================== | |
/* | |
Strategy 3 | |
Timer | |
Pros: | |
- Relatively easy to implement | |
Cons: | |
- Can be buggy because have to keep track of what composes have been seen and not | |
- Horrible performance | |
- Not responsive. Compose will come up, and then timer will fire so you'll see "popping" | |
*/ | |
setInterval(function(){ | |
var composes = document.querySelectorAll(COMPOSE_SELECTOR); | |
for(compose in composes){ | |
if(haveNotSeenComposeBefore(compose)){ | |
broadcastCompose(compose); | |
} | |
} | |
}, 100); | |
// ======================== | |
/* | |
Strategy 4 | |
CSS Animation Detection | |
(http://developer.streak.com/2012/11/how-to-detect-dom-changes-in-css.html) | |
Pros: | |
- Responsive | |
Cons: | |
- Technique is not well known | |
- Implementation is sufficiently difficult that most extension developers don't do it | |
and easy to generate a buggy result | |
For implementation refer to above blog post | |
*/ | |
// ======================== | |
/* | |
Strategy 5 | |
Chained mutation observers | |
Pros: | |
- Responsive | |
- Little performance overhead | |
Cons: | |
- Hard to implement | |
- have to deal with a lot of cases (standalone compose, inline replies, preview pane, toggling between fullscreen compose, etc) | |
This is what the InboxSDK does, and does it very well. Implementation is too involved to | |
show in a small snippet | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment