/** * Embed Tumblr Posts * * @author Tateya GUMI * @version 0.2.0 * @license MIT License */ (function(global, Module, undefined) { 'use strict'; var namespace = 'jp.or.tateya.embed-tumblr-posts'; var window = global.window; var module = new Module(namespace, global); /** * @const * @type {string} * @since 0.1.0 */ var XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; var EmbedTumblrPosts = module.find('EmbedTumblrPosts') || (function() { /** * @constructor * @param {Element} targetElement * @param {Object} settings * @since 0.1.0 */ var EmbedTumblrPosts = function EmbedTumblrPosts(targetElement, settings) { settings = settings || {}; this.settings = util.objectMerge(EmbedTumblrPosts.DEFAULT_SETTINGS, settings); this.targetElement = targetElement; if (!(targetElement instanceof Element)) { throw new TypeError('This class is required argument targetElement.'); } this.contextNode = targetElement.ownerDocument; }; EmbedTumblrPosts.prototype.constructor = EmbedTumblrPosts; /** * @const * @type {Object.<string,number>} * @since 0.1.0 */ EmbedTumblrPosts.DEFAULT_SETTINGS = { api_key: null, 'base-hostname': 'example.com', limit: 10, offset: 0 }; (function(proto) { /** * @param {Event} event * @since 0.1.0 */ proto.run = function run(event) { }; })(EmbedTumblrPosts.prototype); module.install('EmbedTumblrPosts', EmbedTumblrPosts); return EmbedTumblrPosts; })(); var preparation = module.find('preparation') || (function() { /** * @param {Document} document * @since 0.1.0 */ var preparation = function(document) { var currentScriptElement = preparation.getCurrentScriptElement(document); var settings = util.objectMerge.apply(util, [ preparation.parseEmbedSettingsText(currentScriptElement), preparation.parseQueryString(currentScriptElement) ]); preparation.listener = preparation.createListener(currentScriptElement, settings); preparation.addListener(); }; /** * @param {Event} event * @since 0.1.0 */ preparation.listener = function listener(event) { return undefined; }; /** * @private * @since 0.1.0 */ preparation.addListener = function addListener() { var listener = preparation.listener; window.addEventListener('DOMContentLoaded', listener); }; /** * @private * @param {HTMLElement} targetElement * @param {Object} settings * @return {Function} listener * @since 0.1.0 */ preparation.createListener = function createListener(targetElement, settings) { var etp = new EmbedTumblrPosts(targetElement, settings); return function listener(event) { etp.run(event); }; }; /** * @private * @param {Document} document * @return {HTMLScriptElement} currentScriptElement * @since 0.1.0 */ preparation.getCurrentScriptElement = function getCurrentScriptElement(document) { var scriptElements = document.getElementsByTagNameNS(XHTML_NAMESPACE, 'script'); var currentScriptElement = scriptElements[scriptElements.length-1]; return currentScriptElement; }; /** * @private * @param {HTMLScriptElement} scriptElement * @return {Object} query * @since 0.1.0 */ preparation.parseQueryString = function parseQueryString(scriptElement) { var scriptUri = scriptElement.getAttribute('src'); var queryString = (util.parseUri(scriptUri).search || '?').slice(1); var query = util.parseQueryString(queryString); return query; }; /** * @private * @param {HTMLScriptElement} scriptElement * @return {Object} settings * @since 0.1.0 */ preparation.parseEmbedSettingsText = function parseEmbedSettingsText(scriptElement) { var embedSettingsText = util.extractContentsFromCdataSection(scriptElement.textContent); embedSettingsText = embedSettingsText || '{}'; var settings = JSON.parse(embedSettingsText); return settings; }; module.install('preparation', preparation); return preparation; })(); var util = module.find('util') || (function() { /** * Utilty methods * @type {Object.<Function>} * @since 0.1.0 */ var util = {}; /** * @param {...*} var_args * @return {Object} * @since 0.1.0 */ util.objectMerge = function objectMerge(var_args) { var objects = arguments; var newObject = {}; for (var i=0, len=objects.length, object, objectKey; i<len; i++) { for (objectKey in object = objects[i]) { newObject[objectKey] = object[objectKey]; } } return newObject; }; /** * @param {string} uri * @return {Object} parsedUri * @since 0.1.0 */ util.parseUri = function parseUri(uri) { var parsedUri = document.createElementNS(XHTML_NAMESPACE, 'a'); parsedUri.setAttribute('href', uri); return parsedUri; }; /** * @param {string} queryString * @return {Object} query; * @since 0.1.0 */ util.parseQueryString = function parseQueryString(queryString) { var query = {}; var splitQueryString = queryString.split(/[;&]/); for (var i=0, len=splitQueryString.length, keyAndValue; i<len; i++) { keyAndValue = splitQueryString[i].split('='); query[keyAndValue[0]] = keyAndValue[1] || true; } return query; }; /** * @param {string} cdataSection * @return {string} content * @since 0.1.0 */ util.extractContentsFromCdataSection = function extractContentsFromCdataSection(cdataSection) { var contents = cdataSection; contents = contents.replace(/^<!\[CDATA\[/, ''); contents = contents.replace(/\]\]>$/, ''); return contents; }; /** * @param {string} text * @return {string} extractedHtmlTagsText * @since 0.1.0 */ util.extractHtmlTags = function extractHtmlTags(text) { var extractedHtmlTagsText = text; extractedHtmlTagsText = extractedHtmlTagsText.replace(/<.+?>/g, ''); return extractedHtmlTagsText; }; /** * @param {string} text * @return {string} escapedText * @since 0.1.0 */ util.escapeHtmlTags = function escapeHtmlTags(text) { var escapedText = text; escapedText = escapedText.replace(/&/g, '&'); escapedText = escapedText.replace(/</g, '<'); escapedText = escapedText.replace(/>/g, '>'); return escapedText; }; module.install('util', util); return util; })(); /** * @private * @param {Document} document * @since 0.1.0 */ function supportInternetExplorer(document) { if (typeof(global.Window.prototype.addEventListener) !== 'function') { global.Window.prototype.addEventListener = function addEventListener(type, listener, useCapture) { var target = this; listener = function(event) { if (event.type === 'onreadystatechange' && this.readyState !== 'complate') { return; } listener.call(target, event); }; if (type !== 'DOMContentLoaded') { document.attachEvent('onreadystatechange', listener); } else { this.attachEvent('on' + type, listener); } }; } if (typeof(document.createElementNS) !== 'function') { document.createElementNS = function createElementNS(namespace, tagName) { return this.createElement(tagName); }; } if (typeof(document.getElementsByTagNameNS) !== 'function') { document.getElementsByTagNameNS = function getElementsByTagNameNS(namespace, tagName) { return this.getElementsByTagName(tagName); }; } if (typeof(document.createElementNS(XHTML_NAMESPACE, 'div').textContent) !== 'string' && typeof(Object.defineProperty) === 'function') { Object.defineProperty(Element.prototype, 'textContent', { get: function getter() { return this.extractHtmlTags(this.innerHTML); }, set: function setter(text) { return this.innerHTML = util.escapeHtmlTags(text); }, configurable: true, enumerable: false }); } }; if (window === global) { if (typeof(window.navigator) !== 'undefined' && /MSIE/.test(window.navigator.userAgent)) { supportInternetExplorer(window.document); } preparation(window.document); } })(this, (function() { 'use strict'; /** * @constructor * @param {string} namespace * @since 0.2.0 */ var Module = function Module(namespace, path) { path = path || {}; var properties = namespace.split('.'); for (var i=0, len=properties.length, property; i<len; i++) { property = properties[i]; path = path[property] = path[property] || {}; } this.path = path; }; /** * @param {string} name * @return {Object} object * @since 0.2.0 */ Module.prototype.find = function find(name) { var object = this.path[name]; return (typeof(object) !== 'undefined') ? object : null; }; /** * @param {string} name * @param {Object} object * @return {Object} object * @since 0.2.0 */ Module.prototype.install = function install(name, object) { this.path[name] = object; return object; }; return Module; })(), void 0);