/* Load in settings: */ // Live Code // Include libraries: /**fx.js * (c) 2006 Valerio Proietti (http://mad4milk.net). MIT-style license. * Modified to be library independent and IE 10 support by Tom Giordano * version 2.0 */ var Fx = fx = {}; Function.prototype.FxBind = function(object) { var __method = this; return function() { return __method.apply(object, arguments); } }; Fx.Extend = function(destination, source) { for (var property in source) destination[property] = source[property]; return destination; }; Fx.Camelize = function(str) { return str.replace(/-\D/gi, function(match) { return match.charAt(match.length - 1).toUpperCase(); }); }; Fx.CreateArray = function(array) { var nArray = []; for (var i = 0; i < array.length; i++) nArray.push(array[i]); return nArray; } Fx.GetElement = function() { if (arguments.length == 1) return get$(arguments[0]); var elements = []; Fx.CreateArray(arguments).each(function(el) { elements.push(get$(el)); }); return elements; function get$(el) { if (typeof(el) == "string") el = document.getElementById(el); return el; } }; Fx.Base = function() { }; Fx.Base.prototype = { setOptions: function(options) { this.options = Fx.Extend({ onStart: function() { }, onComplete: function() { }, transition: Fx.Transitions.sineInOut, duration: 500, unit: "px", wait: true, fps: 50 }, options || { }); }, step: function() { var time = new Date().getTime(); if (time < this.time + this.options.duration) { this.cTime = time - this.time; this.setNow(); } else { setTimeout(this.options.onComplete.FxBind(this, this.element), 10); this.clearTimer(); this.now = this.to; } this.increase(); }, setNow: function() { this.now = this.compute(this.from, this.to); }, compute: function(from, to) { var change = to - from; return this.options.transition(this.cTime, from, change, this.options.duration); }, clearTimer: function() { clearInterval(this.timer); this.timer = null; return this; }, _start: function(from, to) { if (!this.options.wait) this.clearTimer(); if (this.timer) return; setTimeout(this.options.onStart.FxBind(this, this.element), 10); this.from = from; this.to = to; this.time = new Date().getTime(); this.timer = setInterval(this.step.FxBind(this), Math.round(1000 / this.options.fps)); return this; }, custom: function(from, to) { return this._start(from, to); }, set: function(to) { this.now = to; this.increase(); return this; }, hide: function() { return this.set(0); }, setStyle: function(e, p, v) { if (p == "opacity") { if (v == 0 && e.style.visibility != "hidden") e.style.visibility = "hidden"; else if (e.style.visibility != "visible") e.style.visibility = "visible"; if (typeof(document.body.style.opacity) == "undefined") { if (!e.currentStyle.hasLayout) e.style.zoom = "1"; // Give it layout e.style.filter = "alpha(opacity=" + v * 100 + ")"; } e.style.opacity = v; } else e.style[p] = v + this.options.unit; } }; Fx.Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } }; Fx.Style = Fx.Class.create(); Fx.Style.prototype = Fx.Extend(new Fx.Base(), { initialize: function(el, property, options) { this.element = Fx.GetElement(el); this.setOptions(options); this.property = Fx.Camelize(property); }, increase: function() { this.setStyle(this.element, this.property, this.now); } }); Fx.Styles = Fx.Class.create(); Fx.Styles.prototype = Fx.Extend(new Fx.Base(), { initialize: function(el, options) { this.element = Fx.GetElement(el); this.setOptions(options); this.now = {}; }, setNow: function() { for (p in this.from) this.now[p] = this.compute(this.from[p], this.to[p]); }, custom: function(obj) { if (this.timer && this.options.wait) return; var from = {}; var to = {}; for (p in obj) { from[p] = obj[p][0]; to[p] = obj[p][1]; } return this._start(from, to); }, increase: function() { for (var p in this.now) this.setStyle(this.element, p, this.now[p]); } }); // Transitions (c) 2003 Robert Penner (http://www.robertpenner.com/easing/), BSD License. Fx.Transitions = { linear: function(t, b, c, d) { return c * t / d + b; }, sineInOut: function(t, b, c, d) { return -c / 2 * (Math.cos(Math.PI*t/d) - 1) + b; } }; /**mr.js * * M+R Common Functions * Copyright © 2016 * M+R * www.mrss.com * */ window.mr = { Version: 1.20160426 }; window.Mr = window.mr; mr.Browser = { isIE: document.all && !window.opera, isCSS3IE: document.all && !window.opera && /Trident/i.test(navigator.userAgent) && !/Trident\/4\./i.test(navigator.userAgent), isIE8: document.all && !window.opera && /MSIE 8\./.test(navigator.userAgent) && /Trident/i.test(navigator.userAgent), isIE7: document.all && !window.opera && /MSIE 7\./.test(navigator.userAgent) && !/Trident/i.test(navigator.userAgent), isIE6: document.all && !window.opera && /MSIE 6\./.test(navigator.userAgent) && !/Trident/i.test(navigator.userAgent), isSafari: /Safari/.test(navigator.userAgent), isMobileSafari: /AppleWebKit\/.+Mobile\//.test(navigator.userAgent), isIPhone: /(iPhone|iPod)/.test(navigator.userAgent), isIPad: /iPad/.test(navigator.userAgent), isChrome: /Chrome\//.test(navigator.userAgent), isFirefox: /Firefox/.test(navigator.userAgent), isMobile: ((/mobile/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) && screen.width <= 480) || (/android/i.test(navigator.userAgent) && screen.width == 720) || (/android/i.test(navigator.userAgent) && screen.width == 800), /* Android sometimes reports 720 or 800 instead of actual width */ isQuirksMode: !/CSS/i.test(document.compatMode), supportsTransitions: (!/Android/i.test(navigator.userAgent) && (/Safari/i.test(navigator.userAgent) && /WebKit\/\d+/i.test(navigator.userAgent) && (parseInt(navigator.userAgent.match(/WebKit\/(\d+)/i)[1]) >= 531) && !/OS\sX\s10_[45]/i.test(navigator.userAgent) && !/Windows/i.test(navigator.userAgent)) || (/Firefox\/\d+/i.test(navigator.userAgent) && parseInt(navigator.userAgent.match(/Firefox\/(\d+)/i)[1]) > 11) || (/Chrome\/\d+/i.test(navigator.userAgent) && parseInt(navigator.userAgent.match(/Chrome\/(\d+)/i)[1]) > 17)) }; mr.Test = { /* * Test for empty input. This is the only testing function that auto-trims input. */ IsEmpty: function(str) { if (str.replace(/\s*/g, "").length == 0) return true; return false; }, /* * Test for a valid email */ ValidEmail: function(str) { return (/^([\w\-\+]+)(\.[\w\-\+]+)*@([\w\-]+)(\.[\w\-]+)+$/.test(str)); }, /* * Test for a valid U.S. phone number */ ValidPhone: function(str, cellNumber) { var str = str.replace(/[\(\)\.\-\ ]/g, ""); //strip out acceptable non-numeric characters if (!/^\d{10,11}$/.test(str)) // Must contain only 10 or 11 digits return false; if (/^1\d{10}/.test(str)) // If they used a starting 1, strip it str = str.substring(1, 11); // No phone numbers starting with 0 or 1, having 11 as the second and third digits, having 555 as the first 3 digits or 555 as the 3rd through 6th digits if (/^([01]|\d11|555|\d{3}555)/.test(str)) return false; if (cellNumber && /^(8(00|88|77|66)|9(00|76)|\d{3}976)/.test(str)) // No business or toll numbers: 800, 888, 877, 866, 900, 976, or ###-976 return false; return true; }, /* * Test for a valid numeric input */ ValidNumber: function(str, floatingPoint) { if (floatingPoint) return /^[\d]+\.?[\d]+$/.test(str); return /^\d+$/.test(str); }, /* * Test for a valid credit card number */ ValidCreditCard: function(cardNumber) { cardNumber = cardNumber.replace(/[\s\-]/g, ""); // The CC number is all numbers and length of 15+ if (cardNumber == cardNumber.replace(/[^\d]/g, "") && cardNumber.length >= 15) { var total = 0; for (var i = cardNumber.length; i > 0; i--) { digit = parseInt(cardNumber) % 10; // Get right digit total += digit; i--; cardNumber = cardNumber / 10; // Will remove right most digit digit = (parseInt(cardNumber) % 10) * 2; // Double every other digit switch (digit) { case 10: digit = 1; break; case 12: digit = 3; break; case 14: digit = 5; break; case 16: digit = 7; break; case 18: digit = 9; break; } cardNumber = cardNumber / 10; // Will remove right most digit total += digit; } if (total % 10 == 0) return true; } return false; } }; mr.Get = { /* * Runs function when document is ready */ Ready: function(onReady) { if (typeof(document.addEventListener) == "function") document.addEventListener("DOMContentLoaded", onReady, false); else window.attachEvent("onload", onReady); }, /* * Get URL query parameter */ Parameter: function(param) { var regex = new RegExp("[\\?&]" + param.replace(/\[/,"\\\[").replace(/\]/,"\\\]") + "=([^&#]*)"); var result = regex.exec(window.location.href); return (result == null) ? "" : result[1]; }, /* * Get the current style of an element: * http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/ */ ElementStyle: function(oElm, strCssRule) { var strValue = ""; if (document.defaultView && document.defaultView.getComputedStyle) { strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); } else if (oElm.currentStyle) { strCssRule = strCssRule.replace(/\-(\w)/g, function(strMatch, p1) { return p1.toUpperCase(); }); strValue = oElm.currentStyle[strCssRule]; } return strValue; }, /* * Get next highest Z-index */ NextHighestZindex: function() { var highestIndex = 0; var currentIndex = 0; var elmArray = document.getElementsByTagName('*'); for (var i = 0; i < elmArray.length; i++) { currentIndex = parseFloat(mr.Get.ElementStyle(elmArray[i], "z-index")); if (!isNaN(currentIndex) && (currentIndex > highestIndex) && currentIndex < 99999999) highestIndex = currentIndex; } return (highestIndex + 1); } }; /* * Popup Dialog * Prerequisites: mr.Get * * Not quirksmode safe -- for quirksmode, use mr.Lightbox and build your own HTML dialog * Mobile support. */ mr.Dialog = function() { if (mr.Dialog.initialized) return; mr.Dialog.initialized = true; }; mr.Dialog.prototype = { Show: function(title, text, button, options) { if (options) { if (options.lightColorScheme == true) this.lightColorScheme = true; if (typeof(options.onClose) == "function") this._onClose = options.onClose; } this.bgElement = document.createElement("div"); this.bgElement.style.position = "fixed"; if (!mr.Browser.isIE || (mr.Browser.isCSS3IE && !mr.Browser.isQuirksMode)) { this.bgElement.style.backgroundColor = "rgba(0, 0, 0, 0.6)"; } else { this.bgElement.style.backgroundColor = "#000000"; // Fall back for old IE this.bgElement.style.filter = "alpha(opacity=60)"; } this.bgElement.style.top = "0px"; this.bgElement.style.left = "0px"; this.bgElement.style.bottom = "0px"; this.bgElement.style.right = "0px"; this.bgElement.style.zIndex = mr.Get.NextHighestZindex(); // Make sure it is above other elements this.msgElement = document.createElement("span"); this.msgElement.style.display = "block"; this.msgElement.style.zIndex = parseInt(this.bgElement.style.zIndex) + 1; // Make sure it is above background this.msgElement.style.position = "fixed"; this.msgElement.style.borderRadius = "10px"; this.msgElement.style.boxShadow = "0px 0px 8px #262626"; this.msgElement.style.padding = "20px"; this.msgElement.style.fontFamily = "arial, helvetica, sans-serif"; this.msgElement.style.fontSize = "16px"; this.msgElement.style.lineHeight = "19px"; this.headElement = document.createElement("span"); this.headElement.style.display = "block"; this.headElement.style.textAlign = "center"; this.headElement.style.fontSize = "18px"; this.headElement.style.fontWeight = "bold"; this.headElement.style.marginBottom = "16px"; this.headElement.innerHTML = title; this.innerElement = document.createElement("span"); this.innerElement.innerHTML = text; this.btnElement = document.createElement("span"); this.btnElement.style.display = "block"; this.btnElement.style.textAlign = "center"; this.btnElement.style.fontSize = "18px"; this.btnElement.style.fontWeight = "bold"; this.btnElement.style.cursor = "pointer"; this.btnElement.style.marginTop = "16px"; this.btnElement.innerHTML = button; var thisDialog = this; this.btnElement.onclick = function() { thisDialog.Hide(); }; this.msgElement.appendChild(this.headElement); this.msgElement.appendChild(this.innerElement); this.msgElement.appendChild(this.btnElement); // Setup light/dark color scheme if (this.lightColorScheme) { this.headElement.style.color = "#c00"; this.msgElement.style.backgroundColor = "#fff"; this.msgElement.style.color = "#000"; this.btnElement.style.color = "#c00"; } else { this.msgElement.style.border = "2px solid #fff"; this.msgElement.style.backgroundColor = "#464646"; this.msgElement.style.color = "#fff"; } document.body.appendChild(this.bgElement); document.body.appendChild(this.msgElement); if (typeof(document.body.style.opacity) == "undefined") { this.bgElement.style.filter = "alpha(opacity=1)"; this.msgElement.style.filter = "alpha(opacity=1)"; } else { this.bgElement.style.opacity = "0.01"; this.msgElement.style.opacity = "0.01"; } this.msgElement.style.marginTop = (-1 * this.msgElement.offsetHeight / 2) + "px"; this.msgElement.style.top = "50%"; this.msgElement.style.marginLeft = (-1 * this.msgElement.offsetWidth / 2) + "px"; this.msgElement.style.left = "50%"; // Always make sure it's visible on Mobile: if (mr.Browser.isMobile) { this.bgElement.scrollIntoView(); this.bgElement.style.minHeight = document.body.offsetHeight + "px"; } if (window.innerHeight < this.msgElement.offsetHeight) { this.msgElement.style.position = "absolute"; this.msgElement.style.top = "0"; this.msgElement.style.marginTop = "0"; this.msgElement.scrollIntoView(); } // Fade in, if any libraries are available if (typeof(Fx) == "object") { this.bgElement.wsFx = new Fx.Style(this.bgElement, 'opacity', {duration: 300}); this.bgElement.wsFx._start(0.01, 1.0); this.msgElement.wsFx = new Fx.Style(this.msgElement, 'opacity', {duration: 300}); this.msgElement.wsFx._start(0.01, 1.0); } else if (typeof(jQuery) == "function") { // Animate with jQuery, if loaded: jQuery(this.bgElement).fadeTo(300, 1.0); jQuery(this.msgElement).fadeTo(300, 1.0); } else { if (typeof(document.body.style.opacity) == "undefined") { this.bgElement.style.filter = "alpha(opacity=100)"; this.msgElement.style.filter = "alpha(opacity=100)"; } else { this.bgElement.style.opacity = "1"; this.msgElement.style.opacity = "1"; } } // Escape key will close dialog: if (typeof(document.onkeyup) == "function") this._previousOnKeyUp = document.onkeyup; document.onkeyup = function(e) { e = e || window.event; if (e.keyCode == 27) thisDialog.Hide(); }; }, Hide: function() { // Restore any existing onkeyup document.onkeyup = this._previousOnKeyUp; this._onClose(this); var thisDialog = this; // Fade out, if any libraries are available if (typeof(Fx) == "object") { this.bgElement.wsFx = new Fx.Style(this.bgElement, 'opacity', {duration: 300}); this.bgElement.wsFx._start(1.0, 0.01); this.msgElement.wsFx = new Fx.Style(this.msgElement, 'opacity', {duration: 300, onComplete: function() { thisDialog._hideComplete(); }}); this.msgElement.wsFx._start(1.0, 0.01); } else if (typeof(jQuery) == "function") { jQuery(this.bgElement).fadeTo(300, 0); jQuery(this.msgElement).fadeTo(300, 0, function() { thisDialog._hideComplete(); }); } else { this._hideComplete(); } }, _hideComplete: function() { document.body.removeChild(this.bgElement); document.body.removeChild(this.msgElement); }, _previousOnKeyUp: function() { }, _onClose: function() { } }; /* * Lightbox * Prerequisites: mr.Browser, mr.Get * * Works on both quirksmode and strict pages. * Mobile support. * If lightbox content is taller/wider than page, allows lightbox content to scroll. */ mr.Lightbox = function() { if (mr.Lightbox.initialized) return; mr.Lightbox.initialized = true; }; mr.Lightbox.prototype = { backgroundColor: "#000000", /* * Creates and populates a in-DOM popup lightbox, styled with user HTML * Give all your close buttons a class of mr_lightbox_close_button * onClose function will be called with reference to clicked element as first parameter, * enabling you to determine what button was clicked. */ Show: function(html, widthOfPopup, heightOfPopup, options) { this.widthOfPopup = widthOfPopup; this.heightOfPopup = heightOfPopup; if (options) { if (typeof(options.onClose) == "function") this._onClose = options.onClose; if (options.backgroundColor) this.backgroundColor = options.backgroundColor; if (options.backgroundClickCloses == true) this.backgroundClickCloses = true; if (mr.Browser.isMobile && !isNaN(options.mobileWidth) && !isNaN(options.mobileHeight)) { this.widthOfPopup = options.mobileWidth; this.heightOfPopup = options.mobileHeight; } } // Setup inner content this.contentDiv = document.createElement("div"); this.contentDiv.className = "mr_lightbox_content mr_lightbox_custom_content"; this.contentDiv.style.position = "relative"; this.contentDiv.innerHTML = html; try { this.contentDiv.style.width = this.widthOfPopup + "px"; this.contentDiv.style.height = this.heightOfPopup + "px"; } catch (e) { } this.contentDiv.style.marginLeft = "auto"; this.contentDiv.style.marginRight = "auto"; var thisLightbox = this; var contentDivSpans = this.contentDiv.getElementsByTagName("*"); for (var i = 0; i < contentDivSpans.length; i++) { if (/mr_lightbox_close_button/.test(contentDivSpans[i].className)) { contentDivSpans[i].onclick = function() { thisLightbox._onClose(this); // Call on close function provided by user thisLightbox.Hide(); return false; // Cancel the event }; } } this._build(); if (this.backgroundClickCloses) { this.backgroundDiv.onclick = function() { thisLightbox._onClose(this); // Call on close function provided by user thisLightbox.Hide(); return false; // Cancel the event }; this.popupDiv.onclick = this.backgroundDiv.onclick; // Prevent contentDiv events from bubbling: this.contentDiv.onclick = function(e) { // Stop event from bubbling: e = e || window.event; e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); }; } }, /* * Begins removal of an in-DOM popup lightbox */ Hide: function() { // Prevent hide function from being called twice (i.e. user double-clicks background) if (this.hideCalled) return; this.hideCalled = true; window.onresize = this._previousOnResize; window.onscroll = this._previousOnScroll; // We would lose reference to the lightbox during callback functions too, so store "this" in thisLightbox var thisLightbox = this; if (typeof(Fx) == "object") { // See if Moo Fx library is loaded this.backgroundDiv.wsFx = new Fx.Style(this.backgroundDiv, 'opacity', {duration: 300}); this.backgroundDiv.wsFx._start(0.5, 0.01); this.popupDiv.wsFx = new Fx.Style(this.popupDiv, 'opacity', {duration: 300, onComplete: function() { thisLightbox._hideComplete(); }}); this.popupDiv.wsFx._start(1.0, 0.01); } else if (typeof(jQuery) == "function") { // Animate with jQuery, if loaded: this.backgroundDiv.wsFx = jQuery(this.backgroundDiv).fadeTo(300, 0); this.popupDiv.wsFx = jQuery(this.popupDiv).fadeTo(300, 0, function() { thisLightbox._hideComplete(); }); } else { this._hideComplete(); } }, /* * Removes an in-DOM popup lightbox */ _hideComplete: function() { this.backgroundDiv.parentNode.removeChild(this.backgroundDiv); this.popupDiv.parentNode.removeChild(this.popupDiv); if (mr.Browser.isIE6 && this.hiddenSelects) { for (var i = 0; i < this.hiddenSelects.length; i++) this.hiddenSelects[i].style.visibility = "visible"; } if (mr.Browser.isQuirksMode && mr.Browser.isIE) { document.body.scroll = "yes"; // Re-enable scrolling in IE } var htmlTag = document.getElementsByTagName("html")[0]; htmlTag.style.overflow = "auto"; // IE10 requires us to be explicit: htmlTag.style.overflowY = "auto"; htmlTag.style.overflowX = "auto"; }, /* * Computes scrollbar widths. Based on code from: * http://www.alexandre-gomes.com/?p=115 */ _getScrollBarWidth: function() { var inner = document.createElement("div"); inner.style.width = "100%"; inner.style.height = "200px"; inner.style.margin = "0px"; inner.style.padding = "0px"; inner.style.border = "0px"; var outer = document.createElement("div"); outer.style.position = "absolute"; outer.style.top = "0px"; outer.style.left = "0px"; outer.style.visibility = "hidden"; outer.style.width = "200px"; outer.style.height = "150px"; outer.style.overflow = "hidden"; outer.style.margin = "0px"; outer.style.padding = "0px"; outer.style.border = "0px"; outer.appendChild(inner); document.body.appendChild(outer); var w1 = inner.offsetWidth; outer.style.overflow = "scroll"; var w2 = inner.offsetWidth; if (w1 == w2) w2 = outer.clientWidth; document.body.removeChild(outer); return (w1 - w2); }, /* * Sizes or resizes the lightbox to the browser window */ _sizeLightbox: function() { var marginOffset = 0; var browserViewportHeight; var browserViewportWidth; if (mr.Browser.isIE && mr.Browser.isQuirksMode) { browserViewportHeight = document.body.clientHeight; // Quirksmode IE <9 browserViewportWidth = document.body.clientWidth; // Quirksmode IE <9 } else if (mr.Browser.isIE && !mr.Browser.isCSS3IE) { browserViewportHeight = document.documentElement.clientHeight; // Strict IE <9 browserViewportWidth = document.documentElement.clientWidth; // Strict IE <9 } else { browserViewportHeight = window.innerHeight; browserViewportWidth = window.innerWidth; } // Page height will never be less than window height: var pageHeight = Math.max(browserViewportHeight, document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight); var pageWidth = Math.max(browserViewportWidth, document.body.scrollWidth, document.documentElement.scrollWidth, document.body.offsetWidth, document.documentElement.offsetWidth, document.body.clientWidth, document.documentElement.clientWidth); if (!mr.Browser.isIE || mr.Browser.isCSS3IE) { var hScroll = ((mr.Browser.isIE && !(mr.Browser.isCSS3IE && !mr.Browser.isQuirksMode)) ? document.scrollLeft : window.pageXOffset); var vScroll = ((mr.Browser.isIE && !(mr.Browser.isCSS3IE && !mr.Browser.isQuirksMode)) ? document.scrollTop : window.pageYOffset); var scrolledToTop = false; // Need to determine if popup is taller than visible portion of screen. if (this.heightOfPopup > browserViewportHeight) { // If so disable page scroll, let popup contents scroll instead this.popupDiv.style.overflowY = "auto"; this.popupDiv.style.maxHeight = browserViewportHeight + "px"; this.popupDiv.style.maxWidth = browserViewportWidth + "px"; window.scroll(0, 0); // Scroll to top scrolledToTop = true; document.getElementsByTagName("html")[0].style.overflowY = "hidden"; } else { document.getElementsByTagName("html")[0].style.overflowY = "auto"; this.popupDiv.style.overflowY = "visible"; } // Need to determine if popup is wider than visible portion of screen. if (this.widthOfPopup > browserViewportWidth) { // If so disable page scroll, let popup contents scroll instead this.popupDiv.style.overflowX = "auto"; this.popupDiv.style.maxHeight = browserViewportHeight + "px"; this.popupDiv.style.maxWidth = browserViewportWidth + "px"; window.scroll(0, 0); // Scroll to top scrolledToTop = true; document.getElementsByTagName("html")[0].style.overflowX = "hidden"; } else { document.getElementsByTagName("html")[0].style.overflowX = "auto"; this.popupDiv.style.overflowX = "visible"; } if (!scrolledToTop) window.scroll(hScroll, vScroll); // Scroll to previous position (changing scroll on HTML element causes some browsers to scroll to top) } else { // It's IE < 9, so need to determine if popup is bigger than visible portion of screen. if (this.heightOfPopup > browserViewportHeight || this.widthOfPopup > browserViewportWidth) { // If so disable page scroll, let popup contents scroll instead this.popupDiv.style.overflow = "scroll"; this.popupDiv.style.height = browserViewportHeight + "px"; this.popupDiv.style.width = browserViewportWidth + "px"; if (this.widthOfPopup > browserViewportWidth) { this.popupDiv.style.height = browserViewportHeight - (this.scrollBarWidth + parseInt(document.body.currentStyle.marginTop) + parseInt(document.body.currentStyle.marginBottom)) + "px"; window.onscroll = function() { }; } // If we weren't already scrolled to the top, move up the background div if (mr.Browser.isQuirksMode) this.backgroundDiv.style.marginTop = "0px"; window.scroll(0, 0); // Scroll to top document.getElementsByTagName("html")[0].style.overflow = "hidden"; } else { // Reset scrolling to HTML: window.onscroll = window.onresize; document.getElementsByTagName("html")[0].style.overflow = "auto"; this.popupDiv.style.overflow = "hidden"; } } // Set background div height and calculate margin offset: if (mr.Browser.isMobileSafari) { this.backgroundDiv.style.width = browserViewportWidth + "px"; this.backgroundDiv.style.height = browserViewportHeight + window.pageYOffset + "px"; // We have to factor in scroll offset on Mobile Safari since there is no CSS fixed positioning marginOffset = ((browserViewportHeight - this.heightOfPopup) / 2) + window.pageYOffset; } else if (mr.Browser.isQuirksMode && mr.Browser.isIE) { this.backgroundDiv.style.width = browserViewportHeight + "px"; // If page is scrolled down and refreshed in quirksmode IE, the page scrolls without the bg // Add in height for a possible horizontal scroll bar: this.backgroundDiv.style.height = (browserViewportHeight + document.body.scrollTop + this.scrollBarWidth) + "px"; marginOffset = ((browserViewportHeight - this.heightOfPopup) / 2) + document.body.scrollTop; } else if (!mr.Browser.isCSS3IE && mr.Browser.isIE) { // We have to factor in scroll offset on old IE since there is no CSS fixed positioning marginOffset = ((browserViewportHeight - this.heightOfPopup) / 2) + document.documentElement.scrollTop; // Include page margins on Old IE: this.backgroundDiv.style.width = pageWidth + "px"; this.backgroundDiv.style.height = pageHeight + "px"; } else { marginOffset = ((browserViewportHeight - this.heightOfPopup) / 2); } if (marginOffset < 0) marginOffset = 0; // Just in case for other browsers and needed for IE 7: if (this.backgroundDiv.offsetHeight < pageHeight || this.backgroundDiv.offsetHeight < browserViewportHeight) this.backgroundDiv.style.height = Math.max(pageHeight, browserViewportHeight) + "px"; if (this.backgroundDiv.offsetWidth < pageWidth || this.backgroundDiv.offsetWidth < browserViewportWidth) this.backgroundDiv.style.width = Math.max(pageWidth, browserViewportWidth) + "px"; // Set the size of the Popup Div, partially based on margin offset: if ((mr.Browser.isIE && !mr.Browser.isCSS3IE) || (mr.Browser.isCSS3IE && mr.Browser.isQuirksMode)) { if (mr.Browser.isQuirksMode) { // The window cannot be scrolled in legacy mode: window.scroll(0, 0); // Scroll to top this.backgroundDiv.style.marginTop = "0px"; this.popupDiv.style.width = browserViewportWidth + "px"; this.popupDiv.style.height = Math.max((browserViewportHeight - marginOffset), 0) + "px"; } else { this.popupDiv.style.height = browserViewportHeight + "px"; this.popupDiv.style.width = browserViewportWidth + "px"; this.popupDiv.style.overflow = "auto"; // We need to scroll horizontally if (this.widthOfPopup > browserViewportWidth) { // Also need to set the height here, otherwise scrollbar will be out of sight! this.popupDiv.style.height = Math.max(browserViewportHeight - marginOffset, 0) + "px"; } } } this.popupDiv.style.marginTop = marginOffset + "px"; }, /* * Builds the elements for an in-DOM popup lightbox */ _build: function() { // Create a translucent background div to go behind popup div this.backgroundDiv = document.createElement("div"); this.backgroundDiv.style.top = "0px"; this.backgroundDiv.style.right = "0px"; this.backgroundDiv.style.bottom = "0px"; this.backgroundDiv.style.left = "0px"; this.backgroundDiv.style.backgroundColor = this.backgroundColor; this.backgroundDiv.style.zIndex = mr.Get.NextHighestZindex(); // Make sure it is above other elements this.backgroundDiv.className = "mr_lightbox_background mr_lightbox_rear"; // Create the popup div this.popupDiv = document.createElement("div"); this.popupDiv.style.marginLeft = "auto"; this.popupDiv.style.marginRight = "auto"; this.popupDiv.style.textAlign = "center"; this.popupDiv.style.top = "0px"; this.popupDiv.style.right = "0px"; this.popupDiv.style.bottom = "0px"; this.popupDiv.style.left = "0px"; this.popupDiv.style.zIndex = parseInt(this.backgroundDiv.style.zIndex) + 1; // Make sure it is above background this.popupDiv.className = "mr_lightbox_background mr_lightbox_front"; if (typeof(document.body.style.opacity) == "undefined") { this.backgroundDiv.style.filter = "alpha(opacity=1)"; this.popupDiv.style.filter = "alpha(opacity=1)"; } else { this.backgroundDiv.style.opacity = "0.01"; this.popupDiv.style.opacity = "0.01"; } this.contentDiv.style.outline = "none"; this.contentDiv.style.zIndex = parseInt(this.popupDiv.style.zIndex) + 1; // And put it on top of the popup this.scrollBarWidth = this._getScrollBarWidth(); // Perform some browser-specific things, letting all IE < 9 (or 9+ quirks) and Mobile Safari see this code path: if ((mr.Browser.isIE && !mr.Browser.isCSS3IE) || (mr.Browser.isCSS3IE && mr.Browser.isQuirksMode) || mr.Browser.isMobileSafari) { this.backgroundDiv.style.position = "absolute"; this.popupDiv.style.position = "absolute"; if (mr.Browser.isMobileSafari) { this.popupDiv.style.width = "100%"; this.popupDiv.style.height = "100%"; this.popupDiv.style.minWidth = this.widthOfPopup + "px"; // For Mobile Safari only! this.popupDiv.style.minHeight = this.heightOfPopup + "px"; } if (mr.Browser.isIE6) { // Need to hide all the SELECT elements in the DOM, since IE6 has a Z-order bug: this.hiddenSelects = Array(); var selectsToHide = document.getElementsByTagName("select"); for (var i = 0; i < selectsToHide.length; i++) { if (selectsToHide[i].style.visibility.toLowerCase() != "hidden") { selectsToHide[i].style.visibility = "hidden"; this.hiddenSelects.push(selectsToHide[i]); } } } if (mr.Browser.isQuirksMode && mr.Browser.isIE) { // Instead of window.scroll(0, 0) set margin on background to (quirksmode) scroll top // Account for possibility of horizontal scrollbar disappearing and shifting contents down: this.backgroundDiv.style.marginTop = document.body.scrollTop - this.scrollBarWidth + "px"; document.body.scroll = "no"; } // Need to run this now too: this._sizeLightbox(); // we will run it again later in this function too; this is intentional } else { // Set top margin so that image displays centered, unless window is too short this.backgroundDiv.style.position = "fixed"; this.popupDiv.style.position = "fixed"; } this.popupDiv.appendChild(this.contentDiv); if (document.body.firstChild) { // If possible insert at top of document for accessibility document.body.insertBefore(this.backgroundDiv, document.body.firstChild); document.body.insertBefore(this.popupDiv, this.backgroundDiv.nextSibling); } else { document.body.appendChild(this.backgroundDiv); document.body.appendChild(this.popupDiv); } this._sizeLightbox(); // Size and position the lightbox // Setup window onresize event to handle popup position and background size on browser size change: if (typeof(window.onresize) == "function") this._previousOnResize = window.onresize; if (typeof(window.onscroll) == "function") this._previousOnScroll = window.onscroll; var thisLightbox = this; window.onresize = function() { thisLightbox._previousOnResize(); thisLightbox._sizeLightbox(); }; // If content is taller than page, don't setup scroll to do resize: if (mr.Browser.isIE && (document.body.clientHeight > this.heightOfPopup) && !(mr.Browser.isCSS3IE && !mr.Browser.isQuirksMode)) window.onscroll = window.onresize; // This way scroll wheel is focused correctly for IE, but still a good idea other browsers: // IE jumps the page lower/higher if we set focus to an element not completely on the screen: this.contentDiv.focus(); if (typeof(Fx) == "object") { // See if Fx library is loaded: this.backgroundDiv.wsFx = new Fx.Style(this.backgroundDiv, 'opacity', {duration: 750}); this.backgroundDiv.wsFx._start(0.01, 0.5); this.popupDiv.wsFx = new Fx.Style(this.popupDiv, 'opacity', {duration: 500}); this.popupDiv.wsFx._start(0.01, 1.0); } else if (typeof(jQuery) == "function") { // Animate with jQuery, if loaded: this.backgroundDiv.wsFx = jQuery(this.backgroundDiv).fadeTo(750, 0.5); this.popupDiv.wsFx = jQuery(this.popupDiv).fadeTo(500, 1.0); } else { if (typeof(document.body.style.opacity) == "undefined") { this.backgroundDiv.style.filter = "alpha(opacity=50)"; this.popupDiv.style.filter = "alpha(opacity=100)"; } else { this.backgroundDiv.style.opacity = "0.5"; this.popupDiv.style.opacity = "1"; } } }, /* Used for storing existing onresize functions */ _previousOnResize: function() { }, /* Used for storing existing onscroll functions */ _previousOnScroll: function() { }, _onClose: function() { } }; /* * Cookie handling: */ mr.Cookie = {}; mr.Cookie = { Get: function(cookieName) { if (document.cookie.length > 0) { var cookieStart = document.cookie.indexOf(cookieName + "="); if (cookieStart != -1) { cookieStart += cookieName.length + 1; var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) cookieEnd = document.cookie.length; return unescape(document.cookie.substring(cookieStart, cookieEnd)); } } return ""; }, Set: function(name, value, time, format) { var expireDate = new Date(); format = format.toLowerCase(); if (format == "m") expireDate.setMinutes(expireDate.getMinutes() + parseInt(time)); else if (format == "h") expireDate.setHours(expireDate.getHours() + parseInt(time)); else expireDate.setDate(expireDate.getDate() + parseInt(time)); document.cookie = name + "=" + value + ";expires=" + expireDate.toUTCString() + ";path=/"; } }; /* EOF */ // Include CSS: var css = '/* Fix ForumOne\'s header: */\nheader.banner {\n\ttop: 0;\n}\n/* Banner */\n.dropdown-banner {\n\twidth: 100%;\n\tdisplay: none;\n\tbackground: #ffc702;\n\tpadding-bottom: 20px;\n}\n.dropdown-banner, .dropdown-banner * {\n\t-webkit-text-size-adjust: none;\n\t-moz-text-size-adjust: none;\n\t-ms-text-size-adjust: none;\n\ttext-size-adjust: none;\n}\n.dropdown-banner .banner-inner {\n\tmax-width: 1150px;\n\tmargin: 0 auto;\n\tdisplay: block;\n}\n.dropdown-banner .banner-left {\n\twidth: 68%;\n\tmax-width: 850px;\n\tfloat: left;\n\tpadding-top: 20px;\n\toverflow: hidden;\n}\n.dropdown-banner .banner-left > p {\n\tmargin: 0;\n\tfont-size: 15px;\n\tline-height: 18px;\n\tpadding-right: 10px;\n\tmax-height: 1000000px; /* Android Chrome fix: http://stackoverflow.com/questions/11694767/ */\n}\n.dropdown-banner .banner-left-image > img {\n\tfloat: left;\n\tmargin-right: 16px;\n\tmax-width: 140px;\n\theight: auto;\n}\n.dropdown-banner .banner-left-image > p {\n\tmargin-left: 156px;\n\twidth: 624px;\n}\n.dropdown-banner .banner-right {\n\twidth: 274px;\n\tfloat: right;\n\tpadding-top: 15px;\n}\n.dropdown-banner .banner-right-inner {\n\tposition: relative;\n}\n.dropdown-banner .close-banner {\n\ttop: 10px;\n\tright: 10px;\n\tcursor: pointer;\n\tposition: absolute;\n}\n.dropdown-banner .btn-support {\n\tcursor: pointer;\n\tmargin: 12px 2px;\n}\n.dropdown-banner .banner-dollar-sign {\n\ttop: 37px; \n\tcolor: #797878;\n\tfont-size: 26px;\n\tmargin-left: 5px;\n\tposition: absolute; \n\tfont-family: arial,helvetica,sans-serif;\n}\n.dropdown-banner #header-donate-amount {\n\twidth: 60px;\n\theight: 40px;\n\tmargin: 12px 4px 0px 0;\n\tpadding-left: 8px;\n\tfloat: left;\n\tborder: 1px solid #b3b5b0;\n}\n@media screen and (max-width: 1180px) {\n\t.dropdown-banner .banner-left > p {\n\t\tpadding-left: 10px;\n\t}\n}\n@media screen and (max-width: 899px) {\n\t.dropdown-banner {\n\t\tdisplay: none !important;\n\t}\n}\n/* Lightbox */\n.lightbox > .lightbox__background {\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n position: fixed;\n opacity: .7;\n width: 100%;\n z-index: 10000;\n background: #333;\n}\n.lightbox > .lightbox__content {\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n position: fixed;\n width: 100%;\n z-index: 10001;\n}\n.lightbox > .lightbox__content > .lightbox__desktop {\n display: block;\n position: relative;\n margin: 30px auto 10px;\n}\n.lightbox > .lightbox__content > .lightbox__mobile {\n display: none;\n margin: 30px auto 0 auto;\n position: relative;\n}\n.lightbox__content {\n\tmax-width: 630px;\n\tmargin: auto;\n}\n.lightbox__desktop, .lightbox__mobile {\n\tbackground-color: #fff;\n\tpadding-bottom: 24px;\n}\n.lightbox__close {\n\twidth: 30px;\n\theight: 30px;\n\tbackground-image: url(http://files.rightwingwatch.org/uploads/rww-lb-close-x.png);\n\tbackground-repeat: no-repeat;\n\tposition: absolute;\n\tright: 22px;\n\ttop: 24px;\n\tcursor: pointer;\n}\n.mrlb__image {\n\tdisplay: block;\n\twidth: 100%;\n\theight: auto;\n\tborder: 0;\n}\n.mrlb__header {\n\tfont-family: \"Oswald\", arial, sans-serif;\n\tfont-size: 2.8em;\n\ttext-align: center;\n\tline-height: 140%;\n\tcolor: #ae272b;\n\tpadding-top: 20px;\n\tpadding-left: 50px;\n\tpadding-right: 50px;\n}\n.mrlb__subheader, .mrlb__thanks {\n\tfont-family: \"Rokkitt\", courier, serif;\n\tfont-size: 2em;\n\ttext-align: center;\n\tline-height: 1.1em;\n\tcolor: #252525;\n\tmax-width: 580px;\n\tpadding: 0 20px 6px 20px;\n\tmargin: auto;\n}\n.mrlb__thanks {\n\tpadding-top: 24px;\n\tpadding-bottom: 24px;\n}\n.mrlb__form {\n\ttext-align: center;\n}\n.mrlb__form > .mrlb__email {\n\tdisplay: block;\n\twidth: 90%;\n\tmax-width: 440px;\n\tpadding: 10px 12px;\n\tfont-size: 16px;\n\tmargin: auto;\n\tborder: 1px solid #b5b7b6;\n}\n.mrlb__form > .mrlb__sign {\n\tbackground-color: #252525;\n\tborder-bottom: 5px solid #ed1c24;\n\tdisplay: inline-block;\n\tmax-width: 79%;\n\tpadding: 14px 16px 12px 16px;\n\tmargin: 24px auto 24px auto;\n\tcolor: #fff;\n\ttext-transform: uppercase;\n\ttext-align: center;\n\tfont-weight: bold;\n\tcursor: pointer;\n}\n.mrlb__logo {\n\twidth: 114px;\n\theight: 53px;\n\tbackground-image: url(http://www.pfaw.org/wp-content/themes/pfaw/images/bg/PFAW_logo.svg);\n\tbackground-size: contain;\n\tbackground-repeat: no-repeat;\n\tmargin: auto;\n}\n\n/* Donation specific: */\n.mrlb__donation .mrlb__subheader {\n\tpadding-top: 20px;\n}\n\n/* Mobile: */\n@media screen and (max-width: 899px) {\n\t.mrlb__header {\n\t\tfont-size: 5.8vw;\n\t}\n\t.mrlb__subheader, .mrlb__thanks {\n\t\tfont-size: 4.1vw;\n\t}\n}\n@media screen and (max-width: 480px) {\n\t.mrlb__header {\n\t\tfont-size: 28px;\n\t\tpadding-left: 50px;\n\t\tpadding-right: 50px;\n\t}\n\t.mrlb__firstline {\n\t\tfont-size: 28px;\n\t}\n\t.mrlb__subheader, .mrlb__thanks {\n\t\tmargin: 6px 0 6px 0;\n\t\tfont-size: 20px;\n\t}\n}\n\n'; var style = document.createElement("style"); style.type = "text/css"; if (style.styleSheet) style.styleSheet.cssText = css; else style.appendChild(document.createTextNode(css)); document.getElementsByTagName("head")[0].appendChild(style); /* * Handles signup validation, tracking, and thank you display */ function setupSignupErrorChecking(signupForm, googleAnalyticsCategory, googleAnalyticsAction, googleAnalyticsLabel, thankYouHTML) { // For email signup: if (signupForm) { // On survey submission, validate: signupForm.submit(function() { var signupEmail = signupForm.find('[name="cons_email"]'); if (!mr.Test.ValidEmail(signupEmail.val())) { signupEmail.attr("disabled", "disabled"); window.validEmailDialog = new mr.Dialog(); window.validEmailDialog.Show("Error", "Please correct your email address.", "OK", { lightColorScheme: true, onClose: function() { signupEmail.removeAttr("disabled"); } }); return false; } // Track in GA: if (window._gaq) _gaq.push(['_trackEvent', googleAnalyticsCategory, googleAnalyticsAction, googleAnalyticsLabel]); // Show thanks: signupForm.css("display", "none"); signupForm.after(thankYouHTML); return true; }); } } // Page ready actions: $(document).ready(function() { // Create iframe for cross domain submissions: $("body").append(''); // For sidebar email signup: setupSignupErrorChecking($("#sb-signup"), 'Email Sign-up', 'Email Sign-up', 'Right Sidebar Best of the Blog email form', '
Thank you!
'); // For header email signup: setupSignupErrorChecking($("#header-signup"), 'Email Sign-up', 'Email Sign-up', 'Header email form', '
Thank you!
'); // For footer email signup: setupSignupErrorChecking($("#footer-signup"), 'Email Sign-up', 'Email Sign-up', 'Footer email form', ''); }); // The dropdown banner reusable: var mrDropDownBannerHTML = '\n\n\t
\n\t\t
\n\t\t\t\n\t\t\t

\n\t\t\t\tTo our readers: A Donald Trump presidency threatens to empower dangerous elements of the Radical Right that have, until recently, been relegated to the fringes of America. Never has the work of Right Wing Watch, a project of the People For the American Way dedicated to exposing the Far-Right"s extreme and intolerant agenda, been more important. As a non-profit, our main source of support is readers like you. If you use Right Wing Watch, please consider making a contribution to support our work at this critical time.\n\t\t\t

\n\t\t
\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t
\n\t\t
\n\t
\n\t\n'; /**================================================================== * Banner Cookie * * Parses cookie into opens and reset values w/ type checking. * Instantiate this with the raw cookie value, and use the * getters/setters. Finally, use the save method to set it. *=================================================================*/ window.BannerCookie = function(value){ if (value === undefined){ // Start with some defaults var today = new Date(); today.setMonth(today.getMonth() + 3) this.setOpens(1); this.setReset(today); return this; } this.__value = value; this.__parse(); }; /** * Split the cookie on '/' and validate has 2 parts: * {{opens}}/{{resets}} */ BannerCookie.prototype.__parse = function(){ vals = this.__value.split('/'); if (vals.length !== 2) { throw 'cookie must have two parts, an open count and a reset count'; } this.setOpens(vals[0]); this.setReset(vals[1]); }; /** * Save the cookie to the browser (cookie expires 3 months -- 90 days) */ BannerCookie.prototype.save = function(identifier){ if (typeof(identifier) !== 'string'){ throw 'identifier must be a string'; } var value = this.getOpens().toString() + '/' + this.getReset().toISOString() mr.Cookie.Set(identifier, value, 90, 'd'); return true; }; /** * Opens setter */ BannerCookie.prototype.setOpens = function(opens){ if (isNaN(+opens)){ throw 'opens must be an integer or be able to be cast to an integer'; } this.__opens = +opens; return this.getOpens(); }; /** * Opens getter */ BannerCookie.prototype.getOpens = function(){ return this.__opens; } /** * Reset setter */ BannerCookie.prototype.setReset = function(reset){ if (isNaN(Date.parse(reset))){ throw 'reset must be an instance of Date or be able to be parsed as a Date'; } this.__reset = new Date(reset); return this.getReset(); }; /** * Reset getter */ BannerCookie.prototype.getReset = function(){ return this.__reset; } /**================================================================== * Banner *=================================================================*/ window.Banner = function(controls){ if (typeof(controls) !== 'string'){ throw 'controls must be a string'; } this.__controls = controls; this.log('Constructing instance of Banner'); this.log(this.controls()); this.log('Checking Banner limit'); if (!this.limit()){ this.show(); } }; /** * Conditionally Log debug messages */ Banner.prototype.log = function(msg){ if (this.controls().debug){ console.log(msg); } }; /** * Get controls */ Banner.prototype.controls = function(){ return window[this.__controls]; }; /** * Whether to force the banner to show * Returns a boolean */ Banner.prototype.force = function(){ return mr.Get.Parameter('bannertest') === 't'; }; /** * Get the browser cookie or a default * Returns a instance of BannerCookie */ Banner.prototype.cookie = function(){ if (this.__cookie instanceof BannerCookie) { return this.__cookie; } var rawCookie = mr.Cookie.Get(this.controls().identifier), today = new Date(); // Get parsed cookie OR a default try { this.__cookie = new BannerCookie(rawCookie); if (today > this.__cookie.getReset()){ // Reset to 1 and 3 months from now if today is // past the cookie's reset date this.__cookie = new BannerCookie(); } } catch(e) { // Error getting cookie, set default this.__cookie = new BannerCookie(); } return this.__cookie; }; /** * Limit the number of times a visitor sees the banner * to 3 times in a 3 month period. * Returns a boolean */ Banner.prototype.limit = function(){ var cookie = this.cookie(), limit, opens; // Whether to limit the banner (either based on opens or close button) try { limit = cookie.getOpens() > 5 || window.sessionStorage.getItem(this.controls().identifier) === 'false'; } catch (e) { } this.log('Banner limited: ' + limit); // If limited, increment opens and update cookie in browser if (!limit){ this.log('Incrementing & saving banner cookie'); cookie.setOpens(cookie.getOpens() + 1); cookie.save(this.controls().identifier); } return limit; }; /** * Show the banner */ Banner.prototype.show = function(){ this.log('Showing banner'); var self = this; // Move donate box and show banner //$('#header #header-donate-amount-overlay, #header #header-donate-amount, #header .btn-support-style').remove(); // We add it to the DOM _twice_! Once to the body as a non-position-fixed element where it won't be seen, and again in the fixed header // (this is necessary to push the content down, as the banner is not always the same height at different display sizes) $('body').prepend(this.controls().html); $('header.banner').prepend(this.controls().html); $('.dropdown-banner').show(); this.log('Banner should be visible'); $.event.trigger({ type: "mrDropDownBannerShown" }); // Bind listeners to donate button and close button var go = function(){ // Navigate to donation form with amount input by visitor window.location.replace('https://secure.pfaw.org/site/SPageNavigator/ms_donation_' + encodeURIComponent(self.controls().form) + '.html?amount=' + encodeURIComponent($('#header-donate-amount').val()) + '&s_src=' + encodeURIComponent(self.controls().source) ); }; $('.btn-support').click(go); $('#header-donate-amount').keypress(function(e){ if (e.keyCode === 13){ go(); } }); this.log('Listeners bound to support button and enter key on input'); var close = function(){ $('.dropdown-banner').hide(); $.event.trigger({ type: "mrDropDownBannerClosed" }); window.sessionStorage.setItem(self.controls().identifier, false) }; $('.close-banner').click(close); this.log('Listeners bound to close button'); }; /** * Patch Date's toISOString for IE8 */ if (!Date.prototype.toISOString) { if (!Date.prototype.toJSON) { Date.prototype.toJSON = function (key) { function f(n) { return n < 10 ? '0' + n : n; } return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; } Date.prototype.toISOString = Date.prototype.toJSON; } // Now setup the dropdown: window.mrbanControls = { form: 13261, debug: false, threashold: 5, daysBetweenShowing: 365, source: 'rww_banner_june2016', identifier: 'rww-banner_08-06', html: '' }; $(document).ready(function() { // Create the dropdown banner: window.mrban = new Banner('mrbanControls'); }); // And the lightbox reusable: /** * RWW Reusable Lightbox - v8.1 - 11-03-2016 */ window.mrlbControls = { surveyID: 11143, sourceCode: "rww_lightbox", hiddenInterests: { name: "3092_11143_2_13919", values: [1021, 1103, 1101, 1102] }, cookieName: "rww_popup_201606", daysBetweenShowing: 7, daysBetweenShowingIfTheyProvideEmail: 365, thankYouText: "Thank you!", html: { desktop: '\n
\n\tWE\'RE FACING THE BATTLE OF OUR LIVES\n
\n
\n\tHelp Us Defend America From the Trump Agenda\n
\n
\n\t\n\t
Let us know you stand against hate
\n
\n
\n\n', mobile: '\n
\n\tWE\'RE FACING THE BATTLE OF OUR LIVES\n
\n
\n\tHelp Us Defend America From the Trump Agenda\n
\n
\n\t\n\t
Let us know you stand against hate
\n
\n
\n\n' } }; window.mrlbDonateControls = { donationPageURL: 'https://secure.pfaw.org/site/SPageNavigator/ms_donation_12700.html?autologin=true&utm_medium=lightbox&utm_source=fr&utm_campaign=RWWlightbox&s_opt_v=5773880302&s_opt=t', cookieName: "dec2015", daysBetweenShowing: 334, html: { desktop: '\n
\n\t
\n\t\tDONATE TODAY TO HELP STOP A TRUMP PRESIDENCY\n\t
\n\t
\n\t\tThe Supreme Court is Too Important to Risk a Trump Nominee.\n\t
\n\t
\n\t\t
Donate
\n\t
\n\t
\n
\n', mobile: '\n
\n\t
\n\t\tDONATE TODAY TO HELP STOP A TRUMP PRESIDENCY\n\t
\n\t
\n\t\tThe Supreme Court is Too Important to Risk a Trump Nominee.\n\t
\n\t
\n\t\t
Donate
\n\t
\n\t
\n
\n' } }; // Parse schedule from schedule string: window.mrlbLightboxScheduleStr = '\n\tadvocacy:\n\t\tstart showing: \"January 1, 2016\"\n\t\tstop showing: \"January 1, 2020\"\n\tdonation:\n\t\tstart showing: \"January 1, 2020\"\n\t\tstop showing: \"January 1, 2021\"\n'; function mrlbParseIntoSchedule(scheduleStr, scheduleLightboxObj, startStop, regex, defaultDate) { var parseArray = scheduleStr.match(regex); if (parseArray.length > 1) scheduleLightboxObj[startStop] = new Date(Date.parse(parseArray[1])); else scheduleLightboxObj[startStop] = new Date(Date.parse(defaultDate)); } window.mrlbLightboxSchedule = { advocacy: { }, donation: { } }; mrlbParseIntoSchedule(window.mrlbLightboxScheduleStr, window.mrlbLightboxSchedule.advocacy, "start", /advocacy[^\:]*\:[\s\S]*?start[^\:]*\:[^\"]*[\"]([^\"]*)/im, "January 1, 2000"); // "find advocacy: then start: then quotated string mrlbParseIntoSchedule(window.mrlbLightboxScheduleStr, window.mrlbLightboxSchedule.advocacy, "stop", /advocacy[^\:]*\:[\s\S]*?stop[^\:]*\:[^\"]*[\"]([^\"]*)/im, "January 1, 2050"); // "find advocacy: then stop: then quotated string mrlbParseIntoSchedule(window.mrlbLightboxScheduleStr, window.mrlbLightboxSchedule.donation, "start", /donation[^\:]*\:[\s\S]*?start[^\:]*\:[^\"]*[\"]([^\"]*)/im, "January 1, 2000"); // "find donation: then start: then quotated string mrlbParseIntoSchedule(window.mrlbLightboxScheduleStr, window.mrlbLightboxSchedule.donation, "stop", /donation[^\:]*\:[\s\S]*?stop[^\:]*\:[^\"]*[\"]([^\"]*)/im, "January 1, 2050"); // "find donation: then stop: then quotated string jQuery(document).ready(function(){ /** * Tiny Pub/Sub * See: https://gist.github.com/cowboy/661855/c119783954e1b10551c4afef53b2c04fefcb7465 */ var evts = jQuery({}); jQuery.subscribe = function() { evts.bind.apply( evts, arguments ); }; jQuery.unsubscribe = function() { evts.unbind.apply( evts, arguments ); }; jQuery.publish = function() { evts.trigger.apply( evts, arguments ); }; /** * Subscribe to show event to setup form functionality and push analytics events */ jQuery.subscribe('lightbox.show', function(evt, lightbox){ // Set cookie so it shows at daysBetweenShowing interval: mr.Cookie.Set(lightbox.Controls().cookieName || 'lightboxcookie', 'true', lightbox.Controls().daysBetweenShowing || 7, 'd'); // Track view in Optimizely: window.optimizely = window.optimizely || []; window.optimizely.push(["trackEvent", "lightbox_displayed"]); // And in GA: try { ga('send', 'event', 'Lightbox', 'Lightbox Displayed', {'nonInteraction': 1}); } catch (e) { /* Missing GA, ignoring */ } // Code for placeholder: jQuery('.lightbox__content').find('[placeholder]').focus(function(){ var input = jQuery(this); if (input.val() == input.attr('placeholder')) { input.val(''); input.removeClass('placeholder'); } }).blur(function(){ var input = jQuery(this); if (input.val() === '' || input.val() == input.attr('placeholder')) { input.addClass('placeholder'); input.val(input.attr('placeholder')); } }).blur(); // Bind close event jQuery('.lightbox__desktop > .lightbox__close, .lightbox__mobile > .lightbox__close').click(lightbox.Close()); // Bind sign event jQuery('.mrlb__sign').click(function(e){ if (typeof(lightbox.Controls().sign) === 'function'){ return lightbox.Controls().sign(e, lightbox); } return lightbox.Close()(e); }); // Bind to input keydown looking for enter key jQuery('.lightbox__content').find('input').keydown(function(e){ var k = e || window.event; if (k.keyCode == 13){ // Add a slight delay for Firefox autocomplete window.setTimeout(function(){ if (typeof(lightbox.Controls().sign) === 'function'){ return lightbox.Controls().sign(e, lightbox); } return lightbox.Close()(e); }, 100); return false; } }); }); /** * Subscribe to close event and send close events if box closed by the X */ jQuery.subscribe('lightbox.close', function(evt){ //if ($(evt.currentTarget).hasClass('.lightbox__close')){ // Track in Optimizely that they closed it: window.optimizely = window.optimizely || []; window.optimizely.push(["trackEvent", "lightbox_closed"]); // And in GA: try { ga('send', 'event', 'Lightbox', 'Lightbox Closed', {'nonInteraction': 1}); } catch (e) { /* Missing GA, ignoring */ } //} }); var MRLightbox; /** * Lightbox Constructor */ MRLightbox = function(target, controlsVar) { var self = this, s = new String(); // Get Controls this._controlsVar = controlsVar || 'mrlbControls'; this.Controls().container = target || 'mrLightbox_19h459s'; this.Controls().shown = false; this._debugMsg('Instantiating MRLightbox, already set controls variable (' + controlsVar + ')'); // Wait 2 sec, because sometimes optimizely is slow. If after 2 seconds, still don't have optimizely* loaded, then proceed anyways. // This is just the optimizely js lib. Its not affected by whether there is a test or not, but it does give tests a chance to override the lightbox. var tend = new Date(); tend.setSeconds(tend.getSeconds() + 2); var show = function(){ self._debugMsg('Waiting for Optimizely to load'); var now = new Date(), override = typeof(window.mrlbOverride) === 'boolean' && window.mrlbOverride; self._debugMsg('Optimizely has loaded and mrlbOverride is falsy: ' + ((window.optimizely || false) && !override)); self._debugMsg('Timed-out and mrlbOverride is falsey: ' + (!override && now > tend)); if (((window.optimizely || false) && !override) || (!override && now > tend)) { self._debugMsg('Optimizely loaded'); try { self._debugMsg('Trying to call MRLightbox.Show()'); self.Show(); } catch(e) { self._debugMsg(e); return; } } else if (!override) { window.setTimeout(show, 100); } else { self._debugMsg('MRLightbox overriden, not showing.'); } }; window.setTimeout(show, 100); }; /** * Gets the Controls Object * * Always get Controls values through this function, because we want outside * scripts (ie. Optimizely et al) to be able to update these values. */ MRLightbox.prototype.Controls = function() { return window[this._controlsVar] || {}; }; /** * Show the Lightbox * * Run some logic around building the html before adding it to the DOM and * binding listeners for closing the lightbox. */ MRLightbox.prototype.Show = function() { this._debugMsg('Showing MRLightbox'); var self = this, body = document.getElementsByTagName('body')[0]; html = ''; // Defer to control's show fn, allowing to override lightbox try { this._debugMsg('Trying to call user-defined show function'); var show = this.Controls().show || function(){return false;}; this._debugMsg('Success calling user-defined show function'); if (!show()) { throw 'suppressed by user-defined show function; do not show function'; } } catch (e) { self._debugMsg(e); throw 'error calling user-defined show function; do not show lightbox'; } this._debugMsg('Allowed to proceed showing lightbox'); // Build the Lightbox HTML try { this._debugMsg('Trying to generate html'); if (!this.Controls().html) { this.Controls().html = {}; } html = this._wrap(this.Controls().html.desktop || "", this.Controls().html.mobile || ""); } catch (e) { self._debugMsg(e); if (this.Controls().shown) { // Hide if already shown document.getElementById(this.Controls().container).style.display = 'none'; } throw 'build html is in error; do not show lightbox' } this._debugMsg('Success generating html'); // Show or Update HTML if (!this.Controls().shown) { this._debugMsg('Lightbox not yet shown, create target container w/ lightbox html'); // Add container to DOM w/ lightbox HTML var container = document.createElement('div'); container.id = this.Controls().container; container.innerHTML = html; body.appendChild(container); if (typeof($.publish) === 'function'){ $.publish('lightbox.show', this); } } else { this._debugMsg('Lightbox already shown, updating target container w/ new html'); // Replace container with new HTML container = document.getElementById(this.Controls().container); container.innerHTML = html; container.style.display = 'block'; if (typeof(jQuery.publish) === 'function'){ jQuery.publish('lightbox.update', this); } } this.Controls().shown = true; this._debugMsg('Done showing Lightbox'); return this; // to allow chaining }; /** * Close the Lightbox */ MRLightbox.prototype.Close = function() { var self = this; self._debugMsg('Returning MRLightbox close callback'); return function(evt){ self._debugMsg('Closing Lightbox, trying to call user-defined close function'); if (typeof(self.Controls().close) === 'function') { self.Controls().close(evt); } document.getElementById(self.Controls().container).style.display = 'none'; if (typeof($.publish) === 'function'){ self._debugMsg('Publishing "lightbox.close" event on jQuery Tiny Pub/Sub'); $.publish('lightbox.close', evt); } self._debugMsg('Done closing MRLightbox'); }; }; /** * Helper: Return the complete lightbox html (from the desktop and mobile html) */ MRLightbox.prototype._wrap = function(desktop, mobile) { return ''; }; /** * Helper: Conditionally Log Debugging Messages to Console */ MRLightbox.prototype._debugMsg = function(e) { if (this.Controls().debug) { console.log(e); } }; // We return and don't show if we're coming from particular URL if (mr.Get.Parameter("utm_medium") == "email") { window.mrlbOverride = true; } if (mr.Browser.isMobile) { window.mrlbControls.sourceCode = 'rww_lightbox_mobile'; // And code to fix up the scroll position on mobile var scrollCount = 0; function scrollToLightbox() { scrollCount++; if (scrollCount < 10) { if (window.mrlbControls.shown === true) window.scrollTo(0, 0); //$(".lightbox__mobile").css("margin-left", ((screen.width - 300 /* 300 is our lightbox width */) / 2) + "px"); window.setTimeout(scrollToLightbox, 500); } } $(document).ready(function() { scrollToLightbox(); }); } if ((new Date()).getTime() > window.mrlbLightboxSchedule.donation.start.getTime() && (new Date()).getTime() < window.mrlbLightboxSchedule.donation.stop.getTime()) { // Show the donation lightbox window.mrlbControls = window.mrlbDonateControls; jQuery.extend( window.mrlbControls, { debug: mr.Get.Parameter('debug') === 'true' || false, show: function(){ var today = new Date(); return (!mr.Cookie.Get(window.mrlbControls.cookieName) || mr.Get.Parameter("lightboxtest")); }, sign: function(evt, lightbox){ // Track in Optimizely that they clicked donate: window.optimizely = window.optimizely || []; window.optimizely.push(["trackEvent", "donate_click_lightbox"]); // And in GA: try { ga('send', 'event', 'Donate Click', 'Donate Click Lightbox', {'nonInteraction': 1}); } catch (e) { /* Missing GA, ignoring */ } mr.Cookie.Set(lightbox.Controls().cookieName, "true", lightbox.Controls().daysBetweenShowing, "d"); window.location.replace(window.mrlbControls.donationPageURL); return false; } }); window.mrlb = new MRLightbox(); window.MRLightbox = MRLightbox; } else if ((new Date()).getTime() > window.mrlbLightboxSchedule.advocacy.start.getTime() && (new Date()).getTime() < window.mrlbLightboxSchedule.advocacy.stop.getTime()) { // Show the advocacy lightbox: /** * Add in show and sign functions if they don't already exist */ jQuery.extend( window.mrlbControls, { debug: mr.Get.Parameter('debug') === 'true' || false, show: function(){ var today = new Date(); return (!mr.Cookie.Get(window.mrlbControls.cookieName) || mr.Get.Parameter("lightboxtest")); }, sign: function(evt, lightbox){ // Validate email address: var emailfield = jQuery(evt.currentTarget).parent().find('.mrlb__email[placeholder]'), errorStr = ""; emailfield.each(function(){ if (emailfield.val() == emailfield.attr('placeholder')){ errorStr += "
- " + emailfield.attr('placeholder').replace("*", ""); } else if (emailfield.attr("name").toLowerCase() == "email" && !mr.Test.ValidEmail(emailfield.val())) { errorStr += "
- " + emailfield.attr('placeholder').replace("*", ""); } }); if (errorStr !== "") { (new mr.Dialog()).Show("Error", "Please correct your email address.", "OK", { lightColorScheme: true, onClose: function() { } }); return false; } // Create html for hidden interests var hiddenInterestsHtml = ""; for (var i = 0; i < lightbox.Controls().hiddenInterests.values.length; i++) { hiddenInterestsHtml += ''; } // Post via form and hidden iframe for cross-domain support: $(document.body).append('
' + '' + // Email Address '' + // ? '' + // Remember Me, Stay Logged In '' + // Opt-in to Remembered Login '' + // Spam control field '' + // Submit Action '' + // Survey ID '' + // Source Code hiddenInterestsHtml + '
'); $("#mrlb__form").submit(); // Track in Optimizely that they submitted it: window.optimizely = window.optimizely || []; window.optimizely.push(["trackEvent", "email_signup"]); window.optimizely.push(["trackEvent", "email_signup_lightbox"]); // And in GA: try { ga('send', 'event', 'Email Sign-up', 'Email Sign-up Lightbox', {'nonInteraction': 1}); } catch (e) { /* Missing GA, ignoring */ } // Show Thanks Text $('.lightbox__content').find('.mrlb__form').html("
" + window.mrlbControls.thankYouText + "
"); mr.Cookie.Set(lightbox.Controls().cookieName, "true", lightbox.Controls().daysBetweenShowingIfTheyProvideEmail, "d"); window.setTimeout(lightbox.Close(), 2000); return false; } }); window.mrlb = new MRLightbox(); window.MRLightbox = MRLightbox; } }); // For outermost conditional -- don't remove: