CINXE.COM
Create Account - Try Disqus for Free | Disqus
<!DOCTYPE html> <html lang="en-us"> <head> <link rel="shortcut icon" href="//a.disquscdn.com/1730296160/img/favicon16-32.ico" type="image/vnd.microsoft.icon"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="Content-Language" content="en-us"> <meta name="keywords" content="Disqus, disqus.com, comments, blog, blogs, discussion"> <meta name="google" value="notranslate" /> <title> Create Account - Try Disqus for Free | Disqus </title> <meta name="description" content="Engage, grow, and monetize your audiences. Try Disqus today for free."> <script type="text/javascript" charset="utf-8"> document.domain = 'disqus.com'; if (window.context === undefined) { var context = {}; } context.disqusUrl = 'https://disqus.com'; context.revealUrl = 'http://hubspot.disqus.biz/reveal-by-disqus-organic'; context.disqusDomain = 'disqus.com'; context.mediaUrl = '//a.disquscdn.com/1730296160/'; context.uploadsUrl = '//a.disquscdn.com/uploads'; context.sslUploadsUrl = '//a.disquscdn.com/uploads'; context.loginUrl = 'https://disqus.com/profile/login/'; context.signupUrl = 'https://disqus.com/profile/signup/'; context.apiUrl = '//disqus.com/api/3.0/'; context.apiPublicKey = 'Y1S1wGIzdc63qnZ5rhHfjqEABGA4ZTDncauWFFWWTUBqkmLjdxloTb7ilhGnZ7z1'; context.forum = null; context.adminUrl = 'https://disqus.com'; context.urlMap = { 'signup': 'http://disqus.com/admin/signup/', 'dashboard': 'http://disqus.com/dashboard/', 'admin': 'https://disqus.com/admin/', 'logout': '//disqus.com/logout/', 'home': 'https://disqus.com', 'home_settings_profile': 'https://disqus.com/home/settings/profile/', 'for_websites': 'http://disqus.com/websites/', 'for_publishers': 'http://hubspot.disqus.biz/reveal-by-disqus-organic', 'login': 'https://disqus.com/profile/login/' }; context.navMap = { 'signup': '', 'dashboard': '', 'admin': '', 'addons': '' }; </script> <script src="//a.disquscdn.com/1730296160/js/src/auth_context.js" type="text/javascript" charset="utf-8"></script> <link rel="stylesheet" href="//a.disquscdn.com/1730296160/build/css/f7234396687f.css" type="text/css" /> <script type="text/javascript" src="//a.disquscdn.com/1730296160/build/js/abadd50d331d.js"></script> <script> // // shared/foundation.js // // This file contains the absolute minimum code necessary in order // to create a new application in the DISQUS namespace. // // You should load this file *before* anything that modifies the DISQUS global. // /*jshint browser:true, undef:true, strict:true, expr:true, white:true */ /*global DISQUS:true */ var DISQUS = (function (window, undefined) { "use strict"; var DISQUS = window.DISQUS || {}; // Exception thrown from DISQUS.assert method on failure DISQUS.AssertionError = function (message) { this.message = message; }; DISQUS.AssertionError.prototype.toString = function () { return 'Assertion Error: ' + (this.message || '[no message]'); }; // Raises a DISQUS.AssertionError if value is falsy DISQUS.assert = function (value, message, soft) { if (value) return; if (soft) window.console && window.console.log("DISQUS assertion failed: " + message); else throw new DISQUS.AssertionError(message); }; // Functions to clean attached modules (used by define and cleanup) var cleanFuncs = []; // Attaches a new public interface (module) to the DISQUS namespace. // For example, if DISQUS object is { 'a': { 'b': {} } }: // // DISQUS.define('a.b.c', function () { return { 'd': 'hello' }; }); will transform it into // -> { 'a': { 'b': { 'c': { 'd' : hello' }}}} // // and DISQUS.define('a', function () { return { 'x': 'world' }; }); will transform it into // -> { 'a': { 'b': {}}, 'x': 'world' } // // Attach modules to DISQUS using only this function. DISQUS.define = function (name, fn) { /*jshint loopfunc:true */ if (typeof name === 'function') { fn = name; name = ''; } var parts = name.split('.'); var part = parts.shift(); var cur = DISQUS; var exports = (fn || function () { return {}; }).call({ overwrites: function (obj) { obj.__overwrites__ = true; return obj; } }, window); while (part) { cur = (cur[part] ? cur[part] : cur[part] = {}); part = parts.shift(); } for (var key in exports) { if (!exports.hasOwnProperty(key)) continue; /*jshint eqnull:true */ if (!exports.__overwrites__ && cur[key] !== null) { DISQUS.assert(!cur.hasOwnProperty(key), 'Unsafe attempt to redefine existing module: ' + key, true /* soft assertion */); } cur[key] = exports[key]; cleanFuncs.push(function (cur, key) { return function () { delete cur[key]; }; }(cur, key)); } return cur; }; // Alias for DISQUS.define for the sake of semantics. // You should use it when you need to get a reference to another // DISQUS module before that module is defined: // // var collections = DISQUS.use('lounge.collections'); // // DISQUS.use is a single argument function because we don't // want to encourage people to use it instead of DISQUS.define. DISQUS.use = function (name) { return DISQUS.define(name); }; DISQUS.cleanup = function () { for (var i = 0; i < cleanFuncs.length; i++) { cleanFuncs[i](); } }; return DISQUS; })(window); /*jshint expr:true, undef:true, strict:true, white:true, browser:true */ /*global DISQUS:false*/ // // shared/corefuncs.js // DISQUS.define(function (window, undefined) { "use strict"; var DISQUS = window.DISQUS; var document = window.document; var head = document.getElementsByTagName('head')[0] || document.body; var jobs = { running: false, timer: null, queue: [] }; var uid = 0; // Taken from _.uniqueId DISQUS.getUid = function (prefix) { var id = ++uid + ''; return prefix ? prefix + id : id; }; /* Defers func() execution until cond() is true */ DISQUS.defer = function (cond, func) { function beat() { /*jshint boss:true */ var queue = jobs.queue; if (queue.length === 0) { jobs.running = false; clearInterval(jobs.timer); } for (var i = 0, pair; pair = queue[i]; i++) { if (pair[0]()) { queue.splice(i--, 1); pair[1](); } } } jobs.queue.push([cond, func]); beat(); if (!jobs.running) { jobs.running = true; jobs.timer = setInterval(beat, 100); } }; DISQUS.isOwn = function (obj, key) { // The object.hasOwnProperty method fails when the // property under consideration is named 'hasOwnProperty'. return Object.prototype.hasOwnProperty.call(obj, key); }; DISQUS.isString = function (str) { return Object.prototype.toString.call(str) === "[object String]"; }; /* * Iterates over an object or a collection and calls a callback * function with each item as a parameter. */ DISQUS.each = function (collection, callback) { var length = collection.length, forEach = Array.prototype.forEach; if (!isNaN(length)) { // Treat collection as an array if (forEach) { forEach.call(collection, callback); } else { for (var i = 0; i < length; i++) { callback(collection[i], i, collection); } } } else { // Treat collection as an object for (var key in collection) { if (DISQUS.isOwn(collection, key)) { callback(collection[key], key, collection); } } } }; // Borrowed from underscore DISQUS.extend = function (obj) { DISQUS.each(Array.prototype.slice.call(arguments, 1), function (source) { for (var prop in source) { obj[prop] = source[prop]; } }); return obj; }; DISQUS.serializeArgs = function (params) { var pcs = []; DISQUS.each(params, function (val, key) { if (val !== undefined) { pcs.push(key + (val !== null ? '=' + encodeURIComponent(val) : '')); } }); return pcs.join('&'); }; DISQUS.serialize = function (url, params, nocache) { if (params) { url += (~url.indexOf('?') ? (url.charAt(url.length - 1) == '&' ? '': '&') : '?'); url += DISQUS.serializeArgs(params); } if (nocache) { var ncp = {}; ncp[(new Date()).getTime()] = null; return DISQUS.serialize(url, ncp); } var len = url.length; return (url.charAt(len - 1) == "&" ? url.slice(0, len - 1) : url); }; var TIMEOUT_DURATION = 2e4; // 20 seconds var addEvent, removeEvent; // select the correct event listener function. all of our supported // browsers will use one of these if ('addEventListener' in window) { addEvent = function (node, event, handler) { node.addEventListener(event, handler, false); }; removeEvent = function (node, event, handler) { node.removeEventListener(event, handler, false); }; } else { addEvent = function (node, event, handler) { node.attachEvent('on' + event, handler); }; removeEvent = function (node, event, handler) { node.detachEvent('on' + event, handler); }; } DISQUS.require = function (url, params, nocache, success, failure) { var script = document.createElement('script'); var evName = script.addEventListener ? 'load' : 'readystatechange'; var timeout = null; script.src = DISQUS.serialize(url, params, nocache); script.async = true; script.charset = 'UTF-8'; function handler(ev) { ev = ev || window.event; if (!ev.target) { ev.target = ev.srcElement; } if (ev.type != 'load' && !/^(complete|loaded)$/.test(ev.target.readyState)) { return; // Not ready yet } if (success) { success(); } if (timeout) { clearTimeout(timeout); } removeEvent(ev.target, evName, handler); } if (success || failure) { addEvent(script, evName, handler); } if (failure) { timeout = setTimeout(function () { failure(); }, TIMEOUT_DURATION); } head.appendChild(script); return DISQUS; }; DISQUS.requireStylesheet = function (url, params, nocache) { var link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = DISQUS.serialize(url, params, nocache); head.appendChild(link); return DISQUS; }; DISQUS.requireSet = function (urls, nocache, callback) { var remaining = urls.length; DISQUS.each(urls, function (url) { DISQUS.require(url, {}, nocache, function () { if (--remaining === 0) { callback(); } }); }); }; DISQUS.injectCss = function (css) { var style = document.createElement('style'); style.setAttribute('type', 'text/css'); // Make inline CSS more readable by splitting each rule onto a separate line css = css.replace(/\}/g, "}\n"); if (window.location.href.match(/^https/)) css = css.replace(/http:\/\//g, 'https://'); if (style.styleSheet) { // Internet Explorer only style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); }; DISQUS.isString = function (val) { return Object.prototype.toString.call(val) === '[object String]'; }; }); /*jshint boss:true*/ /*global DISQUS */ DISQUS.define('Events', function (window, undefined) { "use strict"; // Returns a function that will be executed at most one time, no matter how // often you call it. Useful for lazy initialization. var once = function (func) { var ran = false, memo; return function () { if (ran) return memo; ran = true; memo = func.apply(this, arguments); func = null; return memo; }; }; var has = DISQUS.isOwn; var keys = Object.keys || function (obj) { if (obj !== Object(obj)) throw new TypeError('Invalid object'); var keys = []; for (var key in obj) if (has(obj, key)) keys[keys.length] = key; return keys; }; var slice = [].slice; // Backbone.Events // --------------- // A module that can be mixed in to *any object* in order to provide it with // custom events. You may bind with `on` or remove with `off` callback // functions to an event; `trigger`-ing an event fires all callbacks in // succession. // // var object = {}; // _.extend(object, Backbone.Events); // object.on('expand', function(){ alert('expanded'); }); // object.trigger('expand'); // var Events = { // Bind an event to a `callback` function. Passing `"all"` will bind // the callback to all events fired. on: function (name, callback, context) { if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; this._events = this._events || {}; var events = this._events[name] || (this._events[name] = []); events.push({callback: callback, context: context, ctx: context || this}); return this; }, // Bind an event to only be triggered a single time. After the first time // the callback is invoked, it will be removed. once: function (name, callback, context) { if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; var self = this; var onced = once(function () { self.off(name, onced); callback.apply(this, arguments); }); onced._callback = callback; return this.on(name, onced, context); }, // Remove one or many callbacks. If `context` is null, removes all // callbacks with that function. If `callback` is null, removes all // callbacks for the event. If `name` is null, removes all bound // callbacks for all events. off: function (name, callback, context) { var retain, ev, events, names, i, l, j, k; if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; if (!name && !callback && !context) { this._events = {}; return this; } names = name ? [name] : keys(this._events); for (i = 0, l = names.length; i < l; i++) { name = names[i]; if (events = this._events[name]) { this._events[name] = retain = []; if (callback || context) { for (j = 0, k = events.length; j < k; j++) { ev = events[j]; if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || (context && context !== ev.context)) { retain.push(ev); } } } if (!retain.length) delete this._events[name]; } } return this; }, // Trigger one or many events, firing all bound callbacks. Callbacks are // passed the same arguments as `trigger` is, apart from the event name // (unless you're listening on `"all"`, which will cause your callback to // receive the true name of the event as the first argument). trigger: function (name) { if (!this._events) return this; var args = slice.call(arguments, 1); if (!eventsApi(this, 'trigger', name, args)) return this; var events = this._events[name]; var allEvents = this._events.all; if (events) triggerEvents(events, args); if (allEvents) triggerEvents(allEvents, arguments); return this; }, // Tell this object to stop listening to either specific events ... or // to every object it's currently listening to. stopListening: function (obj, name, callback) { var listeners = this._listeners; if (!listeners) return this; var deleteListener = !name && !callback; if (typeof name === 'object') callback = this; if (obj) (listeners = {})[obj._listenerId] = obj; for (var id in listeners) { listeners[id].off(name, callback, this); if (deleteListener) delete this._listeners[id]; } return this; } }; // Regular expression used to split event strings. var eventSplitter = /\s+/; // Implement fancy features of the Events API such as multiple event // names `"change blur"` and jQuery-style event maps `{change: action}` // in terms of the existing API. var eventsApi = function (obj, action, name, rest) { if (!name) return true; // Handle event maps. if (typeof name === 'object') { for (var key in name) { obj[action].apply(obj, [key, name[key]].concat(rest)); } return false; } // Handle space separated event names. if (eventSplitter.test(name)) { var names = name.split(eventSplitter); for (var i = 0, l = names.length; i < l; i++) { obj[action].apply(obj, [names[i]].concat(rest)); } return false; } return true; }; // A difficult-to-believe, but optimized internal dispatch function for // triggering events. Tries to keep the usual cases speedy (most internal // Backbone events have 3 arguments). var triggerEvents = function (events, args) { var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; switch (args.length) { case 0: while (++i < l) { (ev = events[i]).callback.call(ev.ctx); } return; case 1: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1); } return; case 2: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1, a2); } return; case 3: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); } return; default: while (++i < l) { (ev = events[i]).callback.apply(ev.ctx, args); } } }; var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; // Inversion-of-control versions of `on` and `once`. Tell *this* object to // listen to an event in another object ... keeping track of what it's // listening to. DISQUS.each(listenMethods, function (implementation, method) { Events[method] = function (obj, name, callback) { var listeners = this._listeners || (this._listeners = {}); var id = obj._listenerId || (obj._listenerId = DISQUS.getUid('l')); listeners[id] = obj; if (typeof name === 'object') callback = this; obj[implementation](name, callback, this); return this; }; }); // Aliases for backwards compatibility. Events.bind = Events.on; Events.unbind = Events.off; return Events; }); // used for /follow/ /login/ /signup/ social oauth dialogs // faking the bus DISQUS.use('Bus'); _.extend(DISQUS.Bus, DISQUS.Events); </script> <script src="//a.disquscdn.com/1730296160/js/src/global.js" charset="utf-8"></script> <script type="text/javascript"> if (window.AB_TESTS === undefined) { var AB_TESTS = {}; } </script> <script type="text/javascript" charset="utf-8"> // Global tests $(document).ready(function() { $('a[rel*=facebox]').facebox(); }); </script> <script type="text/x-underscore-template" data-template-name="global-nav"> <% var has_custom_avatar = data.avatar_url && data.avatar_url.indexOf('noavatar') < 0; %> <% var has_custom_username = data.username && data.username.indexOf('disqus_') < 0; %> <% if (data.username) { %> <% if (data.has_forums) { %> <li class="admin<% if (has_custom_avatar || !has_custom_username) { %> avatar-menu-admin<% } %>" data-analytics="header admin"><a href="<%= data.urlMap.admin %>"><strong>Admin</strong></a></li> <% } %> <li class="user-dropdown dropdown-toggle<% if (has_custom_avatar || !has_custom_username) { %> avatar-menu<% } else { %> username-menu<% } %>" data-analytics="header username dropdown" data-floater-marker="<% if (has_custom_avatar || !has_custom_username) { %>square<% } %>"> <a href="<%= data.urlMap.home %>/<%= data.username %>/"> <% if (has_custom_avatar) { %> <img src="<%= data.avatar_url %>" class="avatar"> <% } else if (has_custom_username) { %> <%= data.username %> <% } else { %> <img src="<%= data.avatar_url %>" class="avatar"> <% } %> <span class="caret"></span> </a> <ul class="clearfix dropdown"> <li data-analytics="header view profile"><a href="<%= data.urlMap.home %>/<%= data.username %>/">View Profile</a></li> <li class="js-edit-profile" data-analytics="header edit profile"><a href="<%= data.urlMap.home_settings_profile %>">Edit Profile</a></li> <li class="logout" data-analytics="header logout"><a href="<%= data.urlMap.logout %>">Logout</a></li> </ul> </li> <% } else { %> <li class="link-login" data-analytics="header login"><a href="<%= data.urlMap.login %>?next=<%= encodeURIComponent(document.location.href) %>">Log in</a></li> <% } %> </script> <!--[if lte IE 7]> <script src="//a.disquscdn.com/1730296160/js/src/border_box_model.js"></script> <![endif]--> <!--[if lte IE 8]> <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.5.3/modernizr.min.js"></script> <script src="//a.disquscdn.com/1730296160/js/src/selectivizr.js"></script> <![endif]--> <meta name="viewport" content="width=device-width, user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <script type="text/javascript" charset="utf-8"> // Global tests $(document).ready(function() { $('a[rel*=facebox]').facebox(); }); </script> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-MRHN8JCT');</script> <!-- End Google Tag Manager --> </head> <body class="" id="js-content"> <div class="text-center signin-header"> <a href="/" class="logo" data-analytics="site logo" style="margin-top: 90px;"> <img src="//a.disquscdn.com/1730296160/img/disqus-logo-blue-transparent.png" width="174" height="32" alt="Disqus" title="Disqus - Discover your community"/> </a> </div> <section class="container--narrow signup"> <form id="login-form" action="" method="post" accept-charset="utf-8"> <input type='hidden' name='csrfmiddlewaretoken' value='XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG' /> <p class="text-subheading text-center">Sign up for Disqus with your social media account or email address</p> <div class="social-login__outer-wrapper"> <div class="social-login__wrapper"> <button id="google-signup" title="google" type="button" class="social-button -google"> <span class="auth-container"> <img src="//a.disquscdn.com/1730296160/img/icons/google_2023.svg" alt="Google"> Google </span> </button> <button id="facebook-signup" title="facebook" type="button" class="social-button -facebook"> <span class="auth-container"> <img src="//a.disquscdn.com/1730296160/img/icons/facebook_2023.svg" alt="Facebook"> Facebook </span> </button> <button id="x-signup" title="twitter" type="button" class="social-button -twitter"> <span class="auth-container"> <img src="//a.disquscdn.com/1730296160/img/icons/twitter.svg" alt="X (Twitter)"> X (Twitter) </span> </button> <button id="microsoft-signup" title="microsoft" type="button" class="social-button -microsoft"> <span class="auth-container"> <img src="//a.disquscdn.com/1730296160/img/icons/microsoft.svg" alt="Microsoft"> Microsoft </span> </button> <button id="apple-signup" title="apple" type="button" class="social-button -apple"> <span class="auth-container"> <img src="//a.disquscdn.com/1730296160/img/icons/apple.svg" alt="Apple"> Apple </span> </button> </div> </div> <div class="separator-container"> <div class="line"></div> or <div class="line"></div> </div> <fieldset class="input-group"> Name* <input id="display-name-input" type="text" name="display_name" class="form-text" value="" placeholder="e.g. John Doe" required aria-label="Name" > </fieldset> <fieldset class="input-group"> Email* <input id="email-input" type="email" name="email" class="form-text" value="" placeholder="Email" required aria-label="e.g. johndoe@email.com" > </fieldset> <fieldset class="input-group"> Password* <input id="password-input" type="password" name="password" class="form-text" placeholder="Enter your password" required aria-label="Password" > </fieldset> <script src='https://www.google.com/recaptcha/api.js'></script> <script type="text/javascript"> var DjangoRecaptchaOptions = { "lang": "en" }; if (typeof RecaptchaOptions !== 'object') { RecaptchaOptions = DjangoRecaptchaOptions; } else { for (key in DjangoRecaptchaOptions) { RecaptchaOptions[key] = DjangoRecaptchaOptions[key]; } } </script> <div class="g-recaptcha" data-sitekey="6LfHFZceAAAAAIuuLSZamKv3WEAGGTgqB_E7G7f3"></div> <noscript> <div style="width: 302px; height: 352px;"> <div style="width: 302px; height: 352px; position: relative;"> <div style="width: 302px; height: 352px; position: absolute;"> <iframe src="https://www.google.com/recaptcha/api/fallback?k=6LfHFZceAAAAAIuuLSZamKv3WEAGGTgqB_E7G7f3" frameborder="0" scrolling="no" style="width: 302px; height:352px; border-style: none;"> </iframe> </div> <div style="width: 250px; height: 80px; position: absolute; border-style: none; bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;"> <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="recaptcha_challenge_field" style="width: 250px; height: 80px; border: 1px solid #c1c1c1; margin: 0px; padding: 0px; resize: none;" value=""> </textarea> <input type='hidden' name='recaptcha_response_field' value='manual_challenge' /> </div> </div> </div> </noscript> <section class="tos__container"> <div class="privacy-info"> By clicking submit, I authorize Disqus, Inc. and its affiliated companies to: <ul> <li>Use, sell, and share my information to enable me to use its comment services and for marketing purposes, including cross-context behavioral advertising, as described in our <a href="https://help.disqus.com/en/articles/1717102-terms-of-service" target="_blank" rel="noopener noreferrer">Terms of Service</a> and <a href="https://disqus.com/privacy-policy/" target="_blank" rel="noopener noreferrer">Privacy Policy</a></li> <li>Supplement the information that I provide with additional information lawfully obtained from other sources, like demographic data from public sources, interests inferred from web page views, or other data relevant to what might interest me, like past purchase or location data</li> <li>Contact me or enable others to contact me by email with offers for goods and services (from any category) at the email address provided</li> <li>Process any sensitive personal information that I submit in a comment for the purpose of displaying the comment</li> <li>Retain my information while I am engaging with marketing messages that I receive and for a reasonable amount of time thereafter. I understand I can opt out at any time through an email that I receive. Companies that we share data with are listed <a href="https://help.disqus.com/en/articles/1944034-cookies-and-data-recipients" target="_blank" rel="noopener noreferrer">here</a></li> </ul> </div> <input type="hidden" name="tos" value="True"> <input type="hidden" name="privacy-policy" value="True"> </section> <div class="button-container spacing-bottom"> <button id="signup-button" class="button submit" data-analytics="sign-in">Sign up<span class="spinner"></span></button> </div> <div class="redirect signup"> Already have an account? <a id="login-link" href="https://disqus.com/profile/login/?next=https%3A//disqus.com/api/console/">Log In</a> </div> </form> </section> <div class="text-center footer"> <div class="footer-group"> <span class="footer-item copyright">© 2024 Disqus</span> <a class="footer-item footer-link" href="https://about.disqus.com/contact" target="_blank" rel="noopener noreferrer">Contact Us</a> </div> <div class="footer-group"> <a class="footer-item footer-link" href="https://help.disqus.com/customer/portal/articles/466260-terms-of-service" target="_blank" rel="noopener noreferrer">Terms & Conditions</a> <a class="footer-item footer-link" href="https://disqus.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a> </div> </div> <script> (function (){ // adds a classname for css to target the current page without passing in special things from the server or wherever // replacing all characters not allowable in classnames var newLocation = encodeURIComponent(window.location.pathname).replace(/[\.!~*'\(\)]/g, '_'); // cleaning up remaining url-encoded symbols for clarity sake newLocation = newLocation.replace(/%2F/g, '-').replace(/^-/, '').replace(/-$/, ''); if (newLocation === '') { newLocation = 'homepage'; } $('body').addClass('' + newLocation); }()); $(function ($) { // adds 'page-active' class to links matching the page url $('a[href="' + window.location.pathname + '"]').addClass('page-active'); }); $(document).delegate('[data-toggle-selector]', 'click', function (e) { var $this = $(this); $($this.attr('data-toggle-selector')).toggle(); e.preventDefault(); }); </script> <script src="https://c.disquscdn.com/next/current/embed/jester.js"></script> <script> var jesterObj = { product: 'dotcom', zone: 'register', }; window.DISQUS.jester.pv(jesterObj); </script> <script> DISQUS.define('web.urls', function () { return { twitter: 'https://disqus.com/_ax/twitter/begin/?ctkn=XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG', google: 'https://disqus.com/_ax/google/begin/?ctkn=XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG', facebook: 'https://disqus.com/_ax/facebook/begin/?ctkn=XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG', microsoft: 'https://disqus.com/_ax/microsoft/begin/?ctkn=XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG', apple: 'https://disqus.com/_ax/apple/begin/?ctkn=XPySQ7Sw7LSSFkBe2sPmEKKZgjDaJCCG', dashboard: 'http://disqus.com/dashboard/' } }); $(document).ready(function () { var updateEnabled = function () { var $submit = $(".button.submit"); var isPrivate = false; if (!isPrivate || ($("input[name=tos]").is(":checked") && $("input[name=privacy-policy]").is(":checked"))) $submit.removeAttr('disabled'); else $submit.attr('disabled', 'disabled'); }; $("input[type=checkbox]").change(updateEnabled); updateEnabled(); $("form").submit(function () { $(this).find('.button.submit') .attr('disabled', 'disabled') .addClass('submitted'); $(this).find('#password-input') .attr('readonly', 'readonly'); $(this).find('#email-input') .attr('readonly', 'readonly'); $(this).find('#display-name-input') .attr('readonly', 'readonly'); }); }); </script> <script type="text/javascript" src="//a.disquscdn.com/1730296160/js/src/social_login.js"></script> <script> (function () { // https://gist.github.com/3108177 var supportsGCS = "defaultView" in window.document && "getComputedStyle" in window.document.defaultView; function getStyle(element, property) { // `element.ownerDocument` returns the used style values relative to the // element's parent document (which may be another frame). `defaultView` // is required for Safari 2 support and when retrieving framed styles in // Firefox 3.6 (https://github.com/jquery/jquery/pull/524#issuecomment-2241183). var style = supportsGCS ? element.ownerDocument.defaultView.getComputedStyle(element, null) : element.currentStyle; return (style || element.style)[property]; } function getWindowPadding() { // Based in part on // http://stackoverflow.com/questions/1275849/get-height-of-enter-browser-window-in-ie8 if (window.outerHeight !== undefined) { return { x: window.outerWidth - window.innerWidth, y: window.outerHeight - window.innerHeight } } var docElem = document.documentElement; // Old browser (IE8 and below). Need to resize window, observe change in // clientWidth/Height in order to determine padding. var oldX = docElem.clientWidth; var oldY = docElem.clientHeight; // clientWidth/Height *will* be smaller than the current window size. But // not by much. I figure this is the least jarring size to pick. window.resizeTo(oldX, oldY); var padding = { x: oldX - docElem.clientWidth, y: oldY - docElem.clientHeight }; // Restore window to original dimensions window.resizeTo(oldX + padding.x, oldY + padding.y); return padding; } function getScrollbarWidth() { // credits: http://davidwalsh.name/detect-scrollbar-width // Create the measurement node var scrollDiv = document.createElement("div"); scrollDiv.className = "scrollbar-measure"; document.body.appendChild(scrollDiv); // Get the scrollbar width var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; // Delete the DIV document.body.removeChild(scrollDiv); return scrollbarWidth; } if (window.resizeTo) { window.onload = function () { // Should only calculate document dimensions after page has fully loaded. // I've also observed some funky results without using setTimeout to wrap // the callback. Other applications seem to resize on a delay, so I suspect // this is necessary. setTimeout(function () { var content = document.getElementById('js-content'), buffer = 20, width = content.offsetWidth, height = content.offsetHeight, padding = getWindowPadding(), scrollWidth = getScrollbarWidth(), viewportHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight, viewportWidth = window.innerWidth || ((document.documentElement.clientWidth || document.body.clientWidth) + scrollWidth), browser = window.outerHeight || viewportHeight, availableHeight = window.screen.availHeight, availableWidth = window.screen.availWidth; var urlParams = {}; window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { urlParams[key] = value; }); // resize only when content is cropped if(!(['true', '1'].includes(urlParams.prevent_resize)) && (viewportHeight < height + buffer || viewportWidth < width)) { if(!window.screenLeft) { window.screenLeft = window.screenX; window.screenTop = window.screenY; } window.resizeTo( Math.min(availableWidth - window.screenLeft, Math.max(width, viewportWidth)), Math.min(availableHeight - window.screenTop, height + (browser - viewportHeight) + buffer) ); } }, 250); } } }()); </script> <!-- helper jQuery tmpl partials --> <script type="text/x-jquery-tmpl" id="profile-metadata-tmpl"> data-profile-username="${username}" data-profile-hash="${emailHash}" href="/${username}" </script> <script type="text/x-jquery-tmpl" id="profile-link-tmpl"> <a class="profile-launcher" {{tmpl "#profile-metadata-tmpl"}} href="/${username}">${name}</a> </script> <script src="//a.disquscdn.com/1730296160/js/src/templates.js"></script> <script src="//a.disquscdn.com/1730296160/js/src/modals.js"></script> <script> DISQUS.ui.config({ disqusUrl: 'https://disqus.com', mediaUrl: '//a.disquscdn.com/1730296160/' }); </script> </body> </html>