(function (document, $) { "use strict"; const MARKET_META_DATA_SELECTOR = 'meta[name="marketLayerOverride"]:not([data-marketlayer-submarket])'; const SUB_MARKET_META_DATA_SELECTOR = 'meta[name="marketLayerOverride"][data-marketlayer-submarket]'; const MARKET_SELECTOR_SELECTOR = '[data-mount="market-selector"] select'; const POSITION_OPTION_APPEND = 'append'; const POSITION_OPTION_PREPEND = 'prepend'; const POSITION_OPTION_REPLACE = 'replace'; const POSITION_OPTION_INNER_TEXT = 'innerText'; const NOT_META_DATA_SPECIFIER = ':not([meta])'; const OVERRIDE_OBJECT_ATTRIBUTES = [ "data-marketlayer-submarket", "data-marketlayer-content", "data-marketlayer-selector", "data-marketlayer-position" ]; let $marketSelector = $(MARKET_SELECTOR_SELECTOR); let $marketMetaDataElements = $(MARKET_META_DATA_SELECTOR); let $subMarketMetaDataElements = $(SUB_MARKET_META_DATA_SELECTOR); let previousOverrides = []; /** * Refines overrides to only page and sub market specific overrides. * @param subMarket - current market selector sub market code. */ const refineOverrides = (subMarket) => { let overrideObjects = []; //Create all sub-market overrides. $subMarketMetaDataElements.each(function() { let curOverrideSubMarket = $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[0]); //Sub market is the selected market or no sub market is required. if(curOverrideSubMarket == subMarket) { var newObject = { content: $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[1]), selector: $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[2]) + NOT_META_DATA_SPECIFIER, position: $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[3]) }; overrideObjects.push(newObject); console.log(newObject); } }); //Create market overrides that are not covered by sub-market overrides. $marketMetaDataElements.each(function() { let curContent = $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[1]); let curSelector = $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[2]) + NOT_META_DATA_SPECIFIER; let curPosition = $(this).attr(OVERRIDE_OBJECT_ATTRIBUTES[3]); let isContained = false; for(let i = 0; i < overrideObjects.length; i++) { if(curSelector == overrideObjects[i].selector && curPosition == overrideObjects[i].position) { isContained = true; break; } } if(!isContained) { var newObject = { content: curContent, selector: curSelector, position: curPosition }; overrideObjects.push(newObject); } }); console.log(overrideObjects); return overrideObjects; } /** * Appends content to specified selector element and adds to previous override list. * @param override - object containing selector, content, and position. */ const appendContent = (override) => { $(override.selector).after(override.content); previousOverrides.push({ 'element': $(override.selector).next(), 'action': 'remove', 'content': '' }); } /** * Prepends content to specified selector element and adds to previous override list. * @param override - object containing selector, content, and position. */ const prependContent = (override) => { $(override.selector).before(override.content); previousOverrides.push({ 'element': $(override.selector).prev(), 'action': 'remove', 'content': '' }); } /** * Replaces content with specified selector element and adds to previous override list. * @param override - object containing selector, content, and position. */ const replaceWithContent = (override) => { let prevElement = $(override.selector); let newElement = $(override.content); prevElement.replaceWith(newElement); previousOverrides.push({ 'element': newElement, 'action': 'replace', 'content': prevElement }); } /** * Replaces text with specified selector element and adds to previous override list. * @param override - object containing selector, content, and position. */ const replaceInnerTextWithContent = (override) => { let prevText = $(override.selector).text(); $(override.selector).text(override.content); previousOverrides.push({ 'element': $(override.selector), 'action': 'replace-text', 'content': prevText }); } /** * Applies refined overrides using jqery. * @param overrideObjects - override objects with position, content, and selector. */ const applyOverrides = (overrideObjects) => { overrideObjects.forEach((override) => { if(override.position === POSITION_OPTION_APPEND) { appendContent(override); } else if (override.position === POSITION_OPTION_PREPEND) { prependContent(override); } else if (override.position === POSITION_OPTION_REPLACE) { replaceWithContent(override); } else if (override.position === POSITION_OPTION_INNER_TEXT) { replaceInnerTextWithContent(override); } }); } /** * Reverts all previous overrides before new market overrides are applied. */ const revertOverrides = () => { previousOverrides.forEach((override) => { if(override.action == 'remove') { override.element.remove(); } else if(override.action == 'replace') { override.element.replaceWith(override.content); } else if(override.action == 'replace-text') { override.element.text(override.content); } }); previousOverrides = []; } //Market Selector is used on the page. if($marketSelector.length) { let subMarket = $marketSelector.find(":selected").val(); //Refine override metadata and apply overrides. let overrideObjects = refineOverrides(subMarket); applyOverrides(overrideObjects); //When market selector is updated. $marketSelector.change(() => { let subMarket = $marketSelector.find(":selected").val(); //Revert previous overrides. revertOverrides(); //Refine override metadata. let overrideObjects = refineOverrides(subMarket); //Apply overrides. applyOverrides(overrideObjects); }); } else { //Refine override metadata and apply overrides. let overrideObjects = refineOverrides(null); applyOverrides(overrideObjects); } })(document, $);