Skip to content

Instantly share code, notes, and snippets.

@hinke
Created August 2, 2012 09:20
Show Gist options
  • Save hinke/3235736 to your computer and use it in GitHub Desktop.
Save hinke/3235736 to your computer and use it in GitHub Desktop.
Readmill send script
aavunction(window) {
var WIDGET_BASE_DOMAIN = 'https://widgets.readmill.com',
PLATFORM_BASE_DOMAIN = 'https://platform.readmill.com',
hasAutoTriggerProcessMarkersFired = false, doc = window.document;
/*
* Select most suitable method for getting all elements by tag name
* to support browsers that does not have getElementsByClassName
*/
function getElementsByClassName(clsName) {
// Preferably use the native version
if(doc.getElementsByClassName) {
return doc.getElementsByClassName(clsName);
}
// Construct a manual getElementsByClassName (for IE < 9)
return (function() {
var elements = doc.getElementsByTagName('*'),
result = [],
clsRegex = new RegExp('(\\s|^)' + clsName + '(\\s|$)');
for (i = elements.length; i--;) {
var el = elements[i], elementClass = el.className || el.getAttribute('class') || '';
if (elementClass.match(clsRegex)) {
result.push(el);
}
}
return result;
})();
}
/*
* Helper function that takes an attribute from the given element
* and converts it into a parameter string (with a default value)
* and pushes it to a given array.
*/
function pushAttributeToParams(element, attrName, params, paramName) {
var attrValue;
if(attrValue = element.getAttribute(attrName)) {
params.push(paramName + '=' + encodeURIComponent(attrValue));
}
}
// Helper to apply styling according to display class
function styleIFrame(iframe, displayClass) {
var style = 'margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; position: static; left: 0px; top: 0px;',
placeHolderUrl;
switch(displayClass) {
case 'large':
style += 'width: 170px !important; height: 40px !important;';
placeHolderUrl = PLATFORM_BASE_DOMAIN + '/assets/platform/btn_ph_str_large.png';
break;
case 'small':
style += 'width: 72px !important; height: 26px !important; ';
placeHolderUrl = PLATFORM_BASE_DOMAIN + '/assets/platform/btn_ph_str_small.png';
break;
}
iframe.style.cssText = "background: transparent url(" + placeHolderUrl + ") !important; " + style;
// Move into a function for better minimization
function _applyAttribute(attrName, value) {
iframe.setAttribute(attrName, value);
}
// NOTE Be careful about capitalization here. Internet explorer
// does not care about attributes unless they are camel cased
_applyAttribute('allowTransparency', 'true'); // Let transparency shine through
_applyAttribute('frameBorder', '0'); // Hide ugly iframe border
_applyAttribute('tabIndex', '0'); // Disable tabbing to the iframe
_applyAttribute('scrolling', 'no'); // Disable scrolling overflowing content
if(iframe.className) {
iframe.className = 'send-to-readmill ' + displayClass;
} else {
iframe.setAttribute('class', 'send-to-readmill ' + displayClass);
}
}
/*
* Goes through all div's that has the class 'send-to-readmill' on them and replaces
* them with an iframe containing the Send to Readmill button.
*/
function processMarkers() {
// Collect all send to readmill (str) elements that should be replaced
var strElements = getElementsByClassName('send-to-readmill');
// Insert an iframe for each marked div
for(var i = strElements.length; i--;) {
var element = strElements[i], parentNode = element.parentNode, params = [], src, iframe, displayClass;
// Only care about div.send-to-readmill
if(element.tagName.toLowerCase() !== 'div') { continue; }
// Base source of the iframe
src = WIDGET_BASE_DOMAIN + '/send';
// Convert data attributes to source parameters
pushAttributeToParams(element, 'data-download-url', params, 'download_url');
pushAttributeToParams(element, 'data-buy-url', params, 'buy_url');
// Display data attribute is a bit special since we have restriction
// on its value (large or small) as well as a default value (large)
displayClass = (element.getAttribute('data-display') || '').toLowerCase();
if((displayClass != 'large') && (displayClass != 'small')) {
displayClass = 'large'; // Fall back to default unless display is allowed value
}
params.push('display=' + displayClass);
// Append the origin domain to enable showing a customized sign in screen
params.push('origin_domain=' + encodeURIComponent(doc.domain));
// Concatenate the final souce for the iframe
src += '?' + params.join('&');
// Insert the actual iframe
iframe = doc.createElement('iframe');
styleIFrame(iframe, displayClass);
iframe.src = src;
parentNode.insertBefore(iframe, element);
parentNode.removeChild(element);
}
}
/*
* Trigger processing of markers (div.send-to-readmill) automatically whenever
* the DOM is ready
*/
function autoTriggerProcessMarkers() {
if(!hasAutoTriggerProcessMarkersFired) {
hasAutoTriggerProcessMarkersFired = true;
processMarkers();
}
}
/*
* Attach a callback to the DOM ready event with as broad browser support
* as possible.
*/
if(doc.addEventListener ) {
// Webkit, Opera, Firefox
doc.addEventListener("DOMContentLoaded", autoTriggerProcessMarkers, false);
window.addEventListener("load", autoTriggerProcessMarkers, false);
} else if (doc.attachEvent) {
// Internet explorer < 9
doc.attachEvent("onreadystatechange", function(){
if(doc.readyState === "complete") {
autoTriggerProcessMarkers();
}
});
doc.attachEvent('onload', autoTriggerProcessMarkers);
} else {
doc.onload = autoTriggerProcessMarkers;
}
// Handle the case where the script is inserted after the DOM loaded event
// has already happened
if(doc.readyState === 'complete') {
setTimeout(function() { autoTriggerProcessMarkers(); }, 1);
}
// Expose the processing method to allow dynamic processing of
// elements that are added later (via ajax for example)
window.Readmill = window.Readmill || {};
window.Readmill.SendToReadmill = {
build: processMarkers
};
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment