Re: modals.js

From disqus.com, 1 Month ago, written in JavaScript, viewed 3 times. This paste is a reply to Re: social_login.js from disqus.com - view diff
URL https://pastebin.freepbx.org/view/27338af5 Embed
Download Paste or View Raw
  1. var DISQUS = DISQUS || {};
  2.  
  3. (function () {
  4.     "use strict";
  5.  
  6.     var templates = {},
  7.         config = {
  8.             // Defaults can be overridden via DISQUS.ui.init
  9.             disqusUrl: '//disqus.com',
  10.             mediaUrl: '//a.disquscdn.com/current'
  11.         };
  12.  
  13.     templates.modal = function (context) {
  14.         return '<div class="dsq-popup-container">' +
  15.             '  <table>' +
  16.             '    <tbody>' +
  17.             '      <tr>' +
  18.             '        <td class="dsq-popup-tl"></td>' +
  19.             '        <td class="dsq-popup-b"></td>' +
  20.             '        <td class="dsq-popup-tr"></td>' +
  21.             '      </tr>' +
  22.             '      <tr>' +
  23.             '        <td class="dsq-popup-b"></td>' +
  24.             '        <td class="dsq-popup-body">' +
  25.             '          <div class="dsq-popup-wrapper">' +
  26.             '              <div class="dsq-popup-title">' +
  27.             '                  <button type="button" class="dsq-popup-close dsq-button-small" style="float:right; color: #fff">Close</button>' +
  28.             '                  <h3>' + context.popupHeader + '</h3>' +
  29.             '              </div>' +
  30.             '              <div class="dsq-popup-content">' + context.popupBody + '</div>' +
  31.                 ((context.footer &&
  32.                 '              <div class="powered-by">' +
  33.                 '                <a href="//disqus.com">' +
  34.                 '                  <img src="//a.disquscdn.com/current/images/embed/disqus-logo-noborder.png" alt="Disqus Comments" style="margin-bottom:-5px;"/>' +
  35.                 '                </a>' +
  36.                 '              </div>'
  37.                 ) || '') +
  38.             '          </div>' +
  39.             '        </td>' +
  40.             '        <td class="dsq-popup-b"></td>' +
  41.             '      </tr>' +
  42.             '      <tr>' +
  43.             '        <td class="dsq-popup-bl"></td>' +
  44.             '        <td class="dsq-popup-b"></td>' +
  45.             '        <td class="dsq-popup-br"></td>' +
  46.             '      </tr>' +
  47.             '    </tbody>' +
  48.             '  </table>' +
  49.             '</div>';
  50.     };
  51.  
  52.     DISQUS.ui = DISQUS.ui || {};
  53.  
  54.     /*
  55.      * Helper function returns true if the element at 'id' is or is
  56.      * contained by the element targetted by the given click event (ev)
  57.      */
  58.     function isClicked(ev, id) {
  59.         var target = ev.target || ev.srcElement;
  60.  
  61.         return $(target).closest('#' + id).length !== 0;
  62.     }
  63.  
  64.     // Keep references to instantiated modals, so we can track and
  65.     // close them later
  66.  
  67.     var _instances = {};
  68.     var _guid = 0;
  69.  
  70.     /**
  71.      * Generic DISQUS-themed modal
  72.      */
  73.  
  74.     var Modal = function () {
  75.         this.guid = ++_guid;
  76.         _instances[this.guid] = this;
  77.     };
  78.  
  79.     // Class methods
  80.     $.extend(Modal, {
  81.         // Closes all instances of any modals inheriting from this class
  82.         closeAll: function() {
  83.             $.each(_instances, function(index, modal) {
  84.                 modal.close();
  85.             });
  86.         },
  87.         // Returns the last instantiated modal that inherited this class
  88.         last: function() { return _instances[_guid]; }
  89.     });
  90.  
  91.     Modal.prototype = {
  92.         init: function() {
  93.             var self = this;
  94.  
  95.             var container = self.container;
  96.             container.className = 'dsq-popup dsq-popup-message' +
  97.                 ' ' + (self.extra || '');
  98.  
  99.  
  100.             self._onContentReady();
  101.  
  102.             var close = $(container).find('.dsq-popup-close');
  103.             if (close && close.length) {
  104.                 close.bind('mouseup', function() {
  105.                     self.close();
  106.                 });
  107.             }
  108.  
  109.             self.mouseUpListener = function (ev) {
  110.                 if (!isClicked(ev, self.container.id))
  111.                     self.close();
  112.             };
  113.  
  114.             self.keyUpListener = function (ev) {
  115.                 if (ev.keyCode == 27) // Escape
  116.                     self.close();
  117.             };
  118.  
  119.             $(document).bind('mouseup', self.mouseUpListener);
  120.             $(document).bind('keyup', self.keyUpListener);
  121.  
  122.             // track views of settings page
  123.             new Image().src = 'https://referrer.disqus.com/juggler/stat.gif?event=home.route.settings_old.open';
  124.         },
  125.  
  126.         _onContentReady: function() {
  127.             var self = this;
  128.             var container = self.container;
  129.             $('body').append(container);
  130.             container.style.display = 'block';
  131.             self.reposition();
  132.  
  133.             if (self.onReady) {
  134.                 self.onReady();
  135.             }
  136.         },
  137.  
  138.         open: function (params) {
  139.             Modal.closeAll();
  140.  
  141.             var self = this;
  142.             $.extend(self, params || {});
  143.  
  144.             var title = self.title || '';
  145.             var body = self.body || '';
  146.  
  147.             self.container = document.createElement('div');
  148.             var container = self.container;
  149.  
  150.             container.id = 'dsq-popup-message';
  151.  
  152.             // Throwaway outer div to get template contents as string
  153.             container.innerHTML = $('<div>').append(templates.modal({
  154.                 popupHeader: title,
  155.                 popupBody: body,
  156.                 footer: typeof params.footer !== 'undefined' ? params.footer : true
  157.             })).html();
  158.  
  159.             self.init();
  160.  
  161.             return container;
  162.         }, // open
  163.  
  164.         close: function (force) {
  165.             var self = this;
  166.  
  167.             var container = self.container;
  168.             if (!container) {
  169.                 return;
  170.             }
  171.  
  172.             // Clean up events
  173.             if (self.mouseUpListener) {
  174.                 $(document).unbind('mouseup', self.mouseUpListener);
  175.                 self.mouseUpListener = null;
  176.             }
  177.  
  178.             if (self.keyUpListener) {
  179.                 $(document).unbind('keyup', self.keyUpListener);
  180.                 self.keyUpListener = null;
  181.             }
  182.  
  183.             var overlay = $('#dsq-overlay');
  184.             if (overlay) {
  185.                 overlay.remove();
  186.             }
  187.  
  188.             try {
  189.                 $(container).remove();
  190.             } catch (exc) {
  191.                 // HACK: IE throws a RuntimeError when using deleteNode()
  192.                 // with a node containing <table> in the html.
  193.                 //
  194.                 // Also, IE8 fucks up iframes when a focuses element with an
  195.                 // iframe inside tries to delete itself.
  196.                 var iframes = container.getElementsByTagName("IFRAME");
  197.                 for (var i = 0; i < iframes.length; i++) {
  198.                     iframes[i].parentNode.removeChild(iframes[i]);
  199.                 }
  200.                 container.parentNode.removeChild(container);
  201.             }
  202.             self.container = null;
  203.  
  204.             if (self.onClose) {
  205.                 self.onClose();
  206.             }
  207.  
  208.             // Cleanup
  209.             _instances[this.guid] = null;
  210.             delete _instances[this.guid];
  211.  
  212.         }, // close
  213.  
  214.         reposition: function() {
  215.             var self = this;
  216.  
  217.             var container = self.container;
  218.             if (!container) {
  219.                 return false;
  220.             }
  221.  
  222.             var windowSize = this.getSize();
  223.             var x = (windowSize[0] - container.offsetWidth) / 2;
  224.             var y = (windowSize[1] - container.offsetHeight) / 2;
  225.  
  226.             container.style.left = x + 'px';
  227.             container.style.top = y + 'px';
  228.             return true;
  229.         },
  230.  
  231.         getSize: function () { // Not covered by tests
  232.             if (typeof window.innerWidth == 'number')
  233.                 return [ window.innerWidth, window.innerHeight ]; // Non-IE
  234.             else if (document.documentElement)
  235.                 return [
  236.                     document.documentElement.clientWidth  || document.body.clientWidth,
  237.                     document.documentElement.clientHeight || document.body.clientHeight
  238.                 ];
  239.             else
  240.                 return [-1, -1];
  241.         }
  242.     };
  243.  
  244.     /**
  245.      * Used by LoginBox to associate a tab with a content node
  246.      *
  247.      * @param {api.LoginBox} a reference to the login box that owns this tab
  248.      * @param {String} id to the tab container DOM elem
  249.      * @param {ContentBase} an instance of a login content object
  250.      */
  251.      var LoginBoxTab = function(parent, tabId, content) {
  252.         var self = this;
  253.         self.parent = parent;
  254.         self.tabNode = $('#' + tabId);
  255.         self.content = content;
  256.  
  257.         var anchor = self.tabNode.find('a')[0];
  258.  
  259.         $(anchor).bind('click', function (ev) {
  260.             self.enable();
  261.  
  262.             ev.preventDefault();
  263.             return false;
  264.         });
  265.     };
  266.  
  267.     LoginBoxTab.prototype = {
  268.         enable: function() {
  269.             if (this.parent.enabledTab) {
  270.                 this.parent.enabledTab.disable();
  271.             }
  272.  
  273.             $(this.tabNode).addClass('dsq-active');
  274.             this.content.show();
  275.  
  276.             this.parent.enabledTab = this;
  277.         },
  278.         disable: function() {
  279.             $(this.tabNode).removeClass('dsq-active');
  280.             this.content.hide();
  281.         }
  282.     };
  283.  
  284.     /*
  285.      * Base class to encapsulate a re-usable login content element.
  286.      * Do not instantiate; create subclasses for concrete login elements
  287.      * (i.e. Guest login, Disqus login, Facebook login).
  288.      *
  289.      * @param containerId {String} the content container DOM id
  290.      * @param opts {Hash} a hash of user-defineable options
  291.      *   noAutoFocus - if false, doesn't focus on the first input when revealed
  292.      *
  293.      */
  294.     var ContentBase = function(containerId, opts) {
  295.         this.opts = opts || {};
  296.         this.container = $('#' + containerId)[0];
  297.     };
  298.  
  299.     ContentBase.prototype = {
  300.         show: function() {
  301.             $(this.container).attr('style', 'display: block !important');
  302.  
  303.             // Focus on first element (if it exists; won't always)
  304.             var inputs = $(this.container).find('input');
  305.             if (inputs.length && !this.opts.noAutoFocus) {
  306.                 inputs[0].focus();
  307.             }
  308.         },
  309.  
  310.         hide: function() {
  311.             $(this.container).attr('style', 'display: none !important');
  312.         }
  313.     };
  314.  
  315.     /**
  316.      * Generic iframe wrapping Content class
  317.      *
  318.      * @param containerId {String} id of the target DOM container
  319.      * @param iframeUrl (String)
  320.      */
  321.     var iFrameContent = function(containerId, iframeUrl) {
  322.         ContentBase.call(this, containerId);
  323.  
  324.         // Browsers often aggressively cache iframes, so we'll use
  325.         // a cache-busting timestamp to make sure we load new copies
  326.         // (this is especially important for iframe content that uses
  327.         //  csrf tokens)
  328.         this.url = iframeUrl; // TODO cache bust
  329.         this.iframe = null;
  330.     };
  331.  
  332.     $.extend(iFrameContent.prototype, ContentBase.prototype, {
  333.         show: function() {
  334.             var self = this;
  335.             if (!this.iframe) {
  336.                 this.iframe = $('<iframe>').attr({
  337.                     src: this.url,
  338.                     style:"display:none !important;",
  339.                     frameBorder: '0',
  340.                     frameSpacing: '0',
  341.                     height: '100%',
  342.                     width: '100%'
  343.                 });
  344.  
  345.                 this.iframe.bind('load', function() {
  346.                     self.spinner.attr('style', 'display: none !important');
  347.                     self.iframe.attr('style', 'display: block !important');
  348.                 });
  349.  
  350.                 this.spinner = $('<img>').attr('src', config.mediaUrl + '/images/dsq-loader.gif');
  351.  
  352.                 $(this.container)
  353.                     .append(this.spinner)
  354.                     .append(this.iframe);
  355.             }
  356.  
  357.             ContentBase.prototype.show.call(this);
  358.         }
  359.     });
  360.  
  361.     $.extend(DISQUS.ui, {
  362.         Modal: Modal,
  363.  
  364.         config: function (_config) {
  365.             $.extend(config, _config)
  366.         }
  367.     })
  368.  
  369.     // Load associated stylesheet for modals
  370.     $('<link>')
  371.         .attr('href', config.mediaUrl + '/css/modals.css')
  372.         .attr('type', 'text/css')
  373.         .attr('rel', 'stylesheet')
  374.         .appendTo('head');
  375. })();
  376. var DISQUS = DISQUS || {};
  377.  
  378. (function () {
  379.     "use strict";
  380.  
  381.     var templates = {},
  382.         config = {
  383.             // Defaults can be overridden via DISQUS.ui.init
  384.             disqusUrl: '//disqus.com',
  385.             mediaUrl: '//a.disquscdn.com/current'
  386.         };
  387.  
  388.     templates.modal = function (context) {
  389.         return '<div class="dsq-popup-container">' +
  390.             '  <table>' +
  391.             '    <tbody>' +
  392.             '      <tr>' +
  393.             '        <td class="dsq-popup-tl"></td>' +
  394.             '        <td class="dsq-popup-b"></td>' +
  395.             '        <td class="dsq-popup-tr"></td>' +
  396.             '      </tr>' +
  397.             '      <tr>' +
  398.             '        <td class="dsq-popup-b"></td>' +
  399.             '        <td class="dsq-popup-body">' +
  400.             '          <div class="dsq-popup-wrapper">' +
  401.             '              <div class="dsq-popup-title">' +
  402.             '                  <button type="button" class="dsq-popup-close dsq-button-small" style="float:right; color: #fff">Close</button>' +
  403.             '                  <h3>' + context.popupHeader + '</h3>' +
  404.             '              </div>' +
  405.             '              <div class="dsq-popup-content">' + context.popupBody + '</div>' +
  406.                 ((context.footer &&
  407.                 '              <div class="powered-by">' +
  408.                 '                <a href="//disqus.com">' +
  409.                 '                  <img src="//a.disquscdn.com/current/images/embed/disqus-logo-noborder.png" alt="Disqus Comments" style="margin-bottom:-5px;"/>' +
  410.                 '                </a>' +
  411.                 '              </div>'
  412.                 ) || '') +
  413.             '          </div>' +
  414.             '        </td>' +
  415.             '        <td class="dsq-popup-b"></td>' +
  416.             '      </tr>' +
  417.             '      <tr>' +
  418.             '        <td class="dsq-popup-bl"></td>' +
  419.             '        <td class="dsq-popup-b"></td>' +
  420.             '        <td class="dsq-popup-br"></td>' +
  421.             '      </tr>' +
  422.             '    </tbody>' +
  423.             '  </table>' +
  424.             '</div>';
  425.     };
  426.  
  427.     DISQUS.ui = DISQUS.ui || {};
  428.  
  429.     /*
  430.      * Helper function returns true if the element at 'id' is or is
  431.      * contained by the element targetted by the given click event (ev)
  432.      */
  433.     function isClicked(ev, id) {
  434.         var target = ev.target || ev.srcElement;
  435.  
  436.         return $(target).closest('#' + id).length !== 0;
  437.     }
  438.  
  439.     // Keep references to instantiated modals, so we can track and
  440.     // close them later
  441.  
  442.     var _instances = {};
  443.     var _guid = 0;
  444.  
  445.     /**
  446.      * Generic DISQUS-themed modal
  447.      */
  448.  
  449.     var Modal = function () {
  450.         this.guid = ++_guid;
  451.         _instances[this.guid] = this;
  452.     };
  453.  
  454.     // Class methods
  455.     $.extend(Modal, {
  456.         // Closes all instances of any modals inheriting from this class
  457.         closeAll: function() {
  458.             $.each(_instances, function(index, modal) {
  459.                 modal.close();
  460.             });
  461.         },
  462.         // Returns the last instantiated modal that inherited this class
  463.         last: function() { return _instances[_guid]; }
  464.     });
  465.  
  466.     Modal.prototype = {
  467.         init: function() {
  468.             var self = this;
  469.  
  470.             var container = self.container;
  471.             container.className = 'dsq-popup dsq-popup-message' +
  472.                 ' ' + (self.extra || '');
  473.  
  474.  
  475.             self._onContentReady();
  476.  
  477.             var close = $(container).find('.dsq-popup-close');
  478.             if (close && close.length) {
  479.                 close.bind('mouseup', function() {
  480.                     self.close();
  481.                 });
  482.             }
  483.  
  484.             self.mouseUpListener = function (ev) {
  485.                 if (!isClicked(ev, self.container.id))
  486.                     self.close();
  487.             };
  488.  
  489.             self.keyUpListener = function (ev) {
  490.                 if (ev.keyCode == 27) // Escape
  491.                     self.close();
  492.             };
  493.  
  494.             $(document).bind('mouseup', self.mouseUpListener);
  495.             $(document).bind('keyup', self.keyUpListener);
  496.  
  497.             // track views of settings page
  498.             new Image().src = 'https://referrer.disqus.com/juggler/stat.gif?event=home.route.settings_old.open';
  499.         },
  500.  
  501.         _onContentReady: function() {
  502.             var self = this;
  503.             var container = self.container;
  504.             $('body').append(container);
  505.             container.style.display = 'block';
  506.             self.reposition();
  507.  
  508.             if (self.onReady) {
  509.                 self.onReady();
  510.             }
  511.         },
  512.  
  513.         open: function (params) {
  514.             Modal.closeAll();
  515.  
  516.             var self = this;
  517.             $.extend(self, params || {});
  518.  
  519.             var title = self.title || '';
  520.             var body = self.body || '';
  521.  
  522.             self.container = document.createElement('div');
  523.             var container = self.container;
  524.  
  525.             container.id = 'dsq-popup-message';
  526.  
  527.             // Throwaway outer div to get template contents as string
  528.             container.innerHTML = $('<div>').append(templates.modal({
  529.                 popupHeader: title,
  530.                 popupBody: body,
  531.                 footer: typeof params.footer !== 'undefined' ? params.footer : true
  532.             })).html();
  533.  
  534.             self.init();
  535.  
  536.             return container;
  537.         }, // open
  538.  
  539.         close: function (force) {
  540.             var self = this;
  541.  
  542.             var container = self.container;
  543.             if (!container) {
  544.                 return;
  545.             }
  546.  
  547.             // Clean up events
  548.             if (self.mouseUpListener) {
  549.                 $(document).unbind('mouseup', self.mouseUpListener);
  550.                 self.mouseUpListener = null;
  551.             }
  552.  
  553.             if (self.keyUpListener) {
  554.                 $(document).unbind('keyup', self.keyUpListener);
  555.                 self.keyUpListener = null;
  556.             }
  557.  
  558.             var overlay = $('#dsq-overlay');
  559.             if (overlay) {
  560.                 overlay.remove();
  561.             }
  562.  
  563.             try {
  564.                 $(container).remove();
  565.             } catch (exc) {
  566.                 // HACK: IE throws a RuntimeError when using deleteNode()
  567.                 // with a node containing <table> in the html.
  568.                 //
  569.                 // Also, IE8 fucks up iframes when a focuses element with an
  570.                 // iframe inside tries to delete itself.
  571.                 var iframes = container.getElementsByTagName("IFRAME");
  572.                 for (var i = 0; i < iframes.length; i++) {
  573.                     iframes[i].parentNode.removeChild(iframes[i]);
  574.                 }
  575.                 container.parentNode.removeChild(container);
  576.             }
  577.             self.container = null;
  578.  
  579.             if (self.onClose) {
  580.                 self.onClose();
  581.             }
  582.  
  583.             // Cleanup
  584.             _instances[this.guid] = null;
  585.             delete _instances[this.guid];
  586.  
  587.         }, // close
  588.  
  589.         reposition: function() {
  590.             var self = this;
  591.  
  592.             var container = self.container;
  593.             if (!container) {
  594.                 return false;
  595.             }
  596.  
  597.             var windowSize = this.getSize();
  598.             var x = (windowSize[0] - container.offsetWidth) / 2;
  599.             var y = (windowSize[1] - container.offsetHeight) / 2;
  600.  
  601.             container.style.left = x + 'px';
  602.             container.style.top = y + 'px';
  603.             return true;
  604.         },
  605.  
  606.         getSize: function () { // Not covered by tests
  607.             if (typeof window.innerWidth == 'number')
  608.                 return [ window.innerWidth, window.innerHeight ]; // Non-IE
  609.             else if (document.documentElement)
  610.                 return [
  611.                     document.documentElement.clientWidth  || document.body.clientWidth,
  612.                     document.documentElement.clientHeight || document.body.clientHeight
  613.                 ];
  614.             else
  615.                 return [-1, -1];
  616.         }
  617.     };
  618.  
  619.     /**
  620.      * Used by LoginBox to associate a tab with a content node
  621.      *
  622.      * @param {api.LoginBox} a reference to the login box that owns this tab
  623.      * @param {String} id to the tab container DOM elem
  624.      * @param {ContentBase} an instance of a login content object
  625.      */
  626.      var LoginBoxTab = function(parent, tabId, content) {
  627.         var self = this;
  628.         self.parent = parent;
  629.         self.tabNode = $('#' + tabId);
  630.         self.content = content;
  631.  
  632.         var anchor = self.tabNode.find('a')[0];
  633.  
  634.         $(anchor).bind('click', function (ev) {
  635.             self.enable();
  636.  
  637.             ev.preventDefault();
  638.             return false;
  639.         });
  640.     };
  641.  
  642.     LoginBoxTab.prototype = {
  643.         enable: function() {
  644.             if (this.parent.enabledTab) {
  645.                 this.parent.enabledTab.disable();
  646.             }
  647.  
  648.             $(this.tabNode).addClass('dsq-active');
  649.             this.content.show();
  650.  
  651.             this.parent.enabledTab = this;
  652.         },
  653.         disable: function() {
  654.             $(this.tabNode).removeClass('dsq-active');
  655.             this.content.hide();
  656.         }
  657.     };
  658.  
  659.     /*
  660.      * Base class to encapsulate a re-usable login content element.
  661.      * Do not instantiate; create subclasses for concrete login elements
  662.      * (i.e. Guest login, Disqus login, Facebook login).
  663.      *
  664.      * @param containerId {String} the content container DOM id
  665.      * @param opts {Hash} a hash of user-defineable options
  666.      *   noAutoFocus - if false, doesn't focus on the first input when revealed
  667.      *
  668.      */
  669.     var ContentBase = function(containerId, opts) {
  670.         this.opts = opts || {};
  671.         this.container = $('#' + containerId)[0];
  672.     };
  673.  
  674.     ContentBase.prototype = {
  675.         show: function() {
  676.             $(this.container).attr('style', 'display: block !important');
  677.  
  678.             // Focus on first element (if it exists; won't always)
  679.             var inputs = $(this.container).find('input');
  680.             if (inputs.length && !this.opts.noAutoFocus) {
  681.                 inputs[0].focus();
  682.             }
  683.         },
  684.  
  685.         hide: function() {
  686.             $(this.container).attr('style', 'display: none !important');
  687.         }
  688.     };
  689.  
  690.     /**
  691.      * Generic iframe wrapping Content class
  692.      *
  693.      * @param containerId {String} id of the target DOM container
  694.      * @param iframeUrl (String)
  695.      */
  696.     var iFrameContent = function(containerId, iframeUrl) {
  697.         ContentBase.call(this, containerId);
  698.  
  699.         // Browsers often aggressively cache iframes, so we'll use
  700.         // a cache-busting timestamp to make sure we load new copies
  701.         // (this is especially important for iframe content that uses
  702.         //  csrf tokens)
  703.         this.url = iframeUrl; // TODO cache bust
  704.         this.iframe = null;
  705.     };
  706.  
  707.     $.extend(iFrameContent.prototype, ContentBase.prototype, {
  708.         show: function() {
  709.             var self = this;
  710.             if (!this.iframe) {
  711.                 this.iframe = $('<iframe>').attr({
  712.                     src: this.url,
  713.                     style:"display:none !important;",
  714.                     frameBorder: '0',
  715.                     frameSpacing: '0',
  716.                     height: '100%',
  717.                     width: '100%'
  718.                 });
  719.  
  720.                 this.iframe.bind('load', function() {
  721.                     self.spinner.attr('style', 'display: none !important');
  722.                     self.iframe.attr('style', 'display: block !important');
  723.                 });
  724.  
  725.                 this.spinner = $('<img>').attr('src', config.mediaUrl + '/images/dsq-loader.gif');
  726.  
  727.                 $(this.container)
  728.                     .append(this.spinner)
  729.                     .append(this.iframe);
  730.             }
  731.  
  732.             ContentBase.prototype.show.call(this);
  733.         }
  734.     });
  735.  
  736.     $.extend(DISQUS.ui, {
  737.         Modal: Modal,
  738.  
  739.         config: function (_config) {
  740.             $.extend(config, _config)
  741.         }
  742.     })
  743.  
  744.     // Load associated stylesheet for modals
  745.     $('<link>')
  746.         .attr('href', config.mediaUrl + '/css/modals.css')
  747.         .attr('type', 'text/css')
  748.         .attr('rel', 'stylesheet')
  749.         .appendTo('head');
  750. })();
  751. // var DISQUS = DISQUS || {};
  752.  
  753. (function () {
  754.     "use strict";
  755.  
  756.     var templates = {},
  757.         config = {
  758.             // Defaults can be overridden via DISQUS.ui.init
  759.             disqusUrl: '//disqus.com',
  760.             mediaUrl: '//a.disquscdn.com/current'
  761.         };
  762.  
  763.     templates.modal = function (context) {
  764.         return '<div class="dsq-popup-container">' +
  765.             '  <table>' +
  766.             '    <tbody>' +
  767.             '      <tr>' +
  768.             '        <td class="dsq-popup-tl"></td>' +
  769.             '        <td class="dsq-popup-b"></td>' +
  770.             '        <td class="dsq-popup-tr"></td>' +
  771.             '      </tr>' +
  772.             '      <tr>' +
  773.             '        <td class="dsq-popup-b"></td>' +
  774.             '        <td class="dsq-popup-body">' +
  775.             '          <div class="dsq-popup-wrapper">' +
  776.             '              <div class="dsq-popup-title">' +
  777.             '                  <button type="button" class="dsq-popup-close dsq-button-small" style="float:right; color: #fff">Close</button>' +
  778.             '                  <h3>' + context.popupHeader + '</h3>' +
  779.             '              </div>' +
  780.             '              <div class="dsq-popup-content">' + context.popupBody + '</div>' +
  781.                 ((context.footer &&
  782.                 '              <div class="powered-by">' +
  783.                 '                <a href="//disqus.com">' +
  784.                 '                  <img src="//a.disquscdn.com/current/images/embed/disqus-logo-noborder.png" alt="Disqus Comments" style="margin-bottom:-5px;"/>' +
  785.                 '                </a>' +
  786.                 '              </div>'
  787.                 ) || '') +
  788.             '          </div>' +
  789.             '        </td>' +
  790.             '        <td class="dsq-popup-b"></td>' +
  791.             '      </tr>' +
  792.             '      <tr>' +
  793.             '        <td class="dsq-popup-bl"></td>' +
  794.             '        <td class="dsq-popup-b"></td>' +
  795.             '        <td class="dsq-popup-br"></td>' +
  796.             '      </tr>' +
  797.             '    </tbody>' +
  798.             '  </table>' +
  799.             '</div>';
  800.     };
  801.  
  802.     DISQUS.ui = DISQUS.ui || {};
  803.  
  804.     /*
  805.      * Helper function returns true if the element at 'id' is or is
  806.      * contained by the element targetted by the given click event (ev)
  807.      */
  808.     function isClicked(ev, id) {
  809.         var target = ev.target || ev.srcElement;
  810.  
  811.         return $(target).closest('#' + id).length !== 0;
  812.     }
  813.  
  814.     // Keep references to instantiated modals, so we can track and
  815.     // close them later
  816.  
  817.     var _instances = {};
  818.     var _guid = 0;
  819.  
  820.     /**
  821.      * Generic DISQUS-themed modal
  822.      */
  823.  
  824.     var Modal = function () {
  825.         this.guid = ++_guid;
  826.         _instances[this.guid] = this;
  827.     };
  828.  
  829.     // Class methods
  830.     $.extend(Modal, {
  831.         // Closes all instances of any modals inheriting from this class
  832.         closeAll: function() {
  833.             $.each(_instances, function(index, modal) {
  834.                 modal.close();
  835.             });
  836.         },
  837.         // Returns the last instantiated modal that inherited this class
  838.         last: function() { return _instances[_guid]; }
  839.     });
  840.  
  841.     Modal.prototype = {
  842.         init: function() {
  843.             var self = this;
  844.  
  845.             var container = self.container;
  846.             container.className = 'dsq-popup dsq-popup-message' +
  847.                 ' ' + (self.extra || '');
  848.  
  849.  
  850.             self._onContentReady();
  851.  
  852.             var close = $(container).find('.dsq-popup-close');
  853.             if (close && close.length) {
  854.                 close.bind('mouseup', function() {
  855.                     self.close();
  856.                 });
  857.             }
  858.  
  859.             self.mouseUpListener = function (ev) {
  860.                 if (!isClicked(ev, self.container.id))
  861.                     self.close();
  862.             };
  863.  
  864.             self.keyUpListener = function (ev) {
  865.                 if (ev.keyCode == 27) // Escape
  866.                     self.close();
  867.             };
  868.  
  869.             $(document).bind('mouseup', self.mouseUpListener);
  870.             $(document).bind('keyup', self.keyUpListener);
  871.  
  872.             // track views of settings page
  873.             new Image().src = 'https://referrer.disqus.com/juggler/stat.gif?event=home.route.settings_old.open';
  874.         },
  875.  
  876.         _onContentReady: function() {
  877.             var self = this;
  878.             var container = self.container;
  879.             $('body').append(container);
  880.             container.style.display = 'block';
  881.             self.reposition();
  882.  
  883.             if (self.onReady) {
  884.                 self.onReady();
  885.             }
  886.         },
  887.  
  888.         open: function (params) {
  889.             Modal.closeAll();
  890.  
  891.             var self = this;
  892.             $.extend(self, params || {});
  893.  
  894.             var title = self.title || '';
  895.             var body = self.body || '';
  896.  
  897.             self.container = document.createElement('div');
  898.             var container = self.container;
  899.  
  900.             container.id = 'dsq-popup-message';
  901.  
  902.             // Throwaway outer div to get template contents as string
  903.             container.innerHTML = $('<div>').append(templates.modal({
  904.                 popupHeader: title,
  905.                 popupBody: body,
  906.                 footer: typeof params.footer !== 'undefined' ? params.footer : true
  907.             })).html();
  908.  
  909.             self.init();
  910.  
  911.             return container;
  912.         }, // open
  913.  
  914.         close: function (force) {
  915.             var self = this;
  916.  
  917.             var container = self.container;
  918.             if (!container) {
  919.                 return;
  920.             }
  921.  
  922.             // Clean up events
  923.             if (self.mouseUpListener) {
  924.                 $(document).unbind('mouseup', self.mouseUpListener);
  925.                 self.mouseUpListener = null;
  926.             }
  927.  
  928.             if (self.keyUpListener) {
  929.                 $(document).unbind('keyup', self.keyUpListener);
  930.                 self.keyUpListener = null;
  931.             }
  932.  
  933.             var overlay = $('#dsq-overlay');
  934.             if (overlay) {
  935.                 overlay.remove();
  936.             }
  937.  
  938.             try {
  939.                 $(container).remove();
  940.             } catch (exc) {
  941.                 // HACK: IE throws a RuntimeError when using deleteNode()
  942.                 // with a node containing <table> in the html.
  943.                 //
  944.                 // Also, IE8 fucks up iframes when a focuses element with an
  945.                 // iframe inside tries to delete itself.
  946.                 var iframes = container.getElementsByTagName("IFRAME");
  947.                 for (var i = 0; i < iframes.length; i++) {
  948.                     iframes[i].parentNode.removeChild(iframes[i]);
  949.                 }
  950.                 container.parentNode.removeChild(container);
  951.             }
  952.             self.container = null;
  953.  
  954.             if (self.onClose) {
  955.                 self.onClose();
  956.             }
  957.  
  958.             // Cleanup
  959.             _instances[this.guid] = null;
  960.             delete _instances[this.guid];
  961.  
  962.         }, // close
  963.  
  964.         reposition: function() {
  965.             var self = this;
  966.  
  967.             var container = self.container;
  968.             if (!container) {
  969.                 return false;
  970.             }
  971.  
  972.             var windowSize = this.getSize();
  973.             var x = (windowSize[0] - container.offsetWidth) / 2;
  974.             var y = (windowSize[1] - container.offsetHeight) / 2;
  975.  
  976.             container.style.left = x + 'px';
  977.             container.style.top = y + 'px';
  978.             return true;
  979.         },
  980.  
  981.         getSize: function () { // Not covered by tests
  982.             if (typeof window.innerWidth == 'number')
  983.                 return [ window.innerWidth, window.innerHeight ]; // Non-IE
  984.             else if (document.documentElement)
  985.                 return [
  986.                     document.documentElement.clientWidth  || document.body.clientWidth,
  987.                     document.documentElement.clientHeight || document.body.clientHeight
  988.                 ];
  989.             else
  990.                 return [-1, -1];
  991.         }
  992.     };
  993.  
  994.     /**
  995.      * Used by LoginBox to associate a tab with a content node
  996.      *
  997.      * @param {api.LoginBox} a reference to the login box that owns this tab
  998.      * @param {String} id to the tab container DOM elem
  999.      * @param {ContentBase} an instance of a login content object
  1000.      */
  1001.      var LoginBoxTab = function(parent, tabId, content) {
  1002.         var self = this;
  1003.         self.parent = parent;
  1004.         self.tabNode = $('#' + tabId);
  1005.         self.content = content;
  1006.  
  1007.         var anchor = self.tabNode.find('a')[0];
  1008.  
  1009.         $(anchor).bind('click', function (ev) {
  1010.             self.enable();
  1011.  
  1012.             ev.preventDefault();
  1013.             return false;
  1014.         });
  1015.     };
  1016.  
  1017.     LoginBoxTab.prototype = {
  1018.         enable: function() {
  1019.             if (this.parent.enabledTab) {
  1020.                 this.parent.enabledTab.disable();
  1021.             }
  1022.  
  1023.             $(this.tabNode).addClass('dsq-active');
  1024.             this.content.show();
  1025.  
  1026.             this.parent.enabledTab = this;
  1027.         },
  1028.         disable: function() {
  1029.             $(this.tabNode).removeClass('dsq-active');
  1030.             this.content.hide();
  1031.         }
  1032.     };
  1033.  
  1034.     /*
  1035.      * Base class to encapsulate a re-usable login content element.
  1036.      * Do not instantiate; create subclasses for concrete login elements
  1037.      * (i.e. Guest login, Disqus login, Facebook login).
  1038.      *
  1039.      * @param containerId {String} the content container DOM id
  1040.      * @param opts {Hash} a hash of user-defineable options
  1041.      *   noAutoFocus - if false, doesn't focus on the first input when revealed
  1042.      *
  1043.      */
  1044.     var ContentBase = function(containerId, opts) {
  1045.         this.opts = opts || {};
  1046.         this.container = $('#' + containerId)[0];
  1047.     };
  1048.  
  1049.     ContentBase.prototype = {
  1050.         show: function() {
  1051.             $(this.container).attr('style', 'display: block !important');
  1052.  
  1053.             // Focus on first element (if it exists; won't always)
  1054.             var inputs = $(this.container).find('input');
  1055.             if (inputs.length && !this.opts.noAutoFocus) {
  1056.                 inputs[0].focus();
  1057.             }
  1058.         },
  1059.  
  1060.         hide: function() {
  1061.             $(this.container).attr('style', 'display: none !important');
  1062.         }
  1063.     };
  1064.  
  1065.     /**
  1066.      * Generic iframe wrapping Content class
  1067.      *
  1068.      * @param containerId {String} id of the target DOM container
  1069.      * @param iframeUrl (String)
  1070.      */
  1071.     var iFrameContent = function(containerId, iframeUrl) {
  1072.         ContentBase.call(this, containerId);
  1073.  
  1074.         // Browsers often aggressively cache iframes, so we'll use
  1075.         // a cache-busting timestamp to make sure we load new copies
  1076.         // (this is especially important for iframe content that uses
  1077.         //  csrf tokens)
  1078.         this.url = iframeUrl; // TODO cache bust
  1079.         this.iframe = null;
  1080.     };
  1081.  
  1082.     $.extend(iFrameContent.prototype, ContentBase.prototype, {
  1083.         show: function() {
  1084.             var self = this;
  1085.             if (!this.iframe) {
  1086.                 this.iframe = $('<iframe>').attr({
  1087.                     src: this.url,
  1088.                     style:"display:none !important;",
  1089.                     frameBorder: '0',
  1090.                     frameSpacing: '0',
  1091.                     height: '100%',
  1092.                     width: '100%'
  1093.                 });
  1094.  
  1095.                 this.iframe.bind('load', function() {
  1096.                     self.spinner.attr('style', 'display: none !important');
  1097.                     self.iframe.attr('style', 'display: block !important');
  1098.                 });
  1099.  
  1100.                 this.spinner = $('<img>').attr('src', config.mediaUrl + '/images/dsq-loader.gif');
  1101.  
  1102.                 $(this.container)
  1103.                     .append(this.spinner)
  1104.                     .append(this.iframe);
  1105.             }
  1106.  
  1107.             ContentBase.prototype.show.call(this);
  1108.         }
  1109.     });
  1110.  
  1111.     $.extend(DISQUS.ui, {
  1112.         Modal: Modal,
  1113.  
  1114.         config: function (_config) {
  1115.             $.extend(config, _config)
  1116.         }
  1117.     })
  1118.  
  1119.     // Load associated stylesheet for modals
  1120.     $('<link>')
  1121.         .attr('href', config.mediaUrl + '/css/modals.css')
  1122.         .attr('type', 'text/css')
  1123.         .attr('rel', 'stylesheet')
  1124.         .appendTo('head');
  1125. })();
  1126. // https://a.disquscdn.com/js/src/modals.js

Replies to Re: modals.js rss

Title Name Language When
Re:templates.js disqus.com javascript 1 Month ago.

Reply to "Re: modals.js"

Here you can reply to the paste above