Paste Search Dynamic
Recent pastes
modals.js
  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. })();
Parsed in 0.072 seconds