diff options
Diffstat (limited to 'static/js/iDisqus.js')
-rw-r--r-- | static/js/iDisqus.js | 1769 |
1 files changed, 178 insertions, 1591 deletions
diff --git a/static/js/iDisqus.js b/static/js/iDisqus.js index ee325e2..19f658c 100644 --- a/static/js/iDisqus.js +++ b/static/js/iDisqus.js @@ -1,1591 +1,178 @@ -/*! - * v 0.2.11 - * - * https://github.com/fooleap/disqus-php-api - * - * Copyright 2017-2018 fooleap - * Released under the MIT license - */ -(function (global) { - 'use strict'; - - var d = document, - l = localStorage, - scripts = d.scripts, - lasturl = scripts[scripts.length - 1].src, - filepath = lasturl.substring(0, lasturl.lastIndexOf('/')), - isEdge = navigator.userAgent.indexOf("Edge") > -1, - isIE = !!window.ActiveXObject || "ActiveXObject" in window; - - function getLocation(href) { - var link = d.createElement('a'); - link.href = href; - return link; - } - - function getAjax(url, success, error) { - var xhr = new XMLHttpRequest(); - xhr.open ('GET', encodeURI(url)); - xhr.onreadystatechange = function() { - if (xhr.readyState == 4 && xhr.status == 200) { - success(xhr.responseText); - } - } - xhr.onerror = error; - xhr.withCredentials = true; - xhr.send(); - return xhr; - } - - function postAjax(url, data, success, error) { - var params = typeof data == 'string' ? data : Object.keys(data).map( - function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) } - ).join('&'); - - var xhr = new XMLHttpRequest(); - xhr.open('POST', url); - xhr.onreadystatechange = function() { - if (xhr.readyState == 4 && xhr.status == 200) { - success(xhr.responseText); - } - }; - xhr.onerror = error; - xhr.withCredentials = true; - xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - xhr.send(params); - return xhr; - } - - // matches & closest polyfill https://github.com/jonathantneal/closest - (function (ElementProto) { - if (typeof ElementProto.matches !== 'function') { - ElementProto.matches = ElementProto.msMatchesSelector || ElementProto.mozMatchesSelector || ElementProto.webkitMatchesSelector || function matches(selector) { - var element = this; - var elements = (element.document || element.ownerDocument).querySelectorAll(selector); - var index = 0; - - while (elements[index] && elements[index] !== element) { - ++index; - } - - return Boolean(elements[index]); - }; - } - - if (typeof ElementProto.closest !== 'function') { - ElementProto.closest = function closest(selector) { - var element = this; - - while (element && element.nodeType === 1) { - if (element.matches(selector)) { - return element; - } - - element = element.parentNode; - } - - return null; - }; - } - })(window.Element.prototype); - - // 访客信息 - var User = function () { - this.dom = arguments[0]; - this.opts = arguments[1]; - this.init(); - this.autologin(); - } - - User.prototype = { - // 初始化访客信息 - init: function(){ - var _ = this; - // 读取访客信息 - _.name = l.getItem('name'); - _.email = l.getItem('email'); - _.url = l.getItem('url'); - _.avatar = l.getItem('avatar'); - _.type = l.getItem('type'); - _.logged_in = l.getItem('logged_in'); - - var boxarr = _.dom.getElementsByClassName('comment-box'); - if( _.logged_in == 'true' ) { - [].forEach.call(boxarr,function(item){ - if(_.type == '1'){ - item.querySelector('.comment-form-wrapper').classList.add('logged-in'); - } - item.querySelector('.comment-form-name').value = _.name; - item.querySelector('.comment-form-email').value = _.email; - item.querySelector('.comment-form-url').value = _.url; - item.querySelector('.comment-avatar-image').src = _.avatar; - }); - } else { - [].forEach.call(boxarr,function(item){ - item.querySelector('.comment-form-wrapper').classList.remove('logged-in'); - item.querySelector('.comment-form-name').value = ''; - item.querySelector('.comment-form-email').value = ''; - item.querySelector('.comment-form-url').value = ''; - item.querySelector('.comment-avatar-image').src = _.dom.querySelector('.comment-avatar-image').dataset.avatar; - }); - l.setItem('logged_in', 'false'); - } - }, - - // 自动登录 - autologin: function(){ - var _ = this; - getAjax( _.opts.api +'/user.php', function(resp){ - var data = JSON.parse(resp); - if( data.code == 0 ){ - _.submit(data.response); - } else { - if( _.type == '1' ){ - l.setItem('logged_in', 'false'); - _.init(); - } - } - }, function(){ - }) - }, - - // 登录 - login: function(){ - - var _ = this; - var popup = window.open(_.opts.api+'/login.php', 'Disqus Oauth', 'width=470,height=508'); - var timer; - function isLogged(){ - if (!popup || !popup.closed) return; - clearInterval(timer); - _.user.autologin(); - } - timer = setInterval(isLogged, 100); - - }, - - // 退出登录 - logout: function(){ - var _ = this; - postAjax( _.opts.api + '/logout.php', {}, function(resp){ - l.setItem('logged_in', 'false'); - l.removeItem('type'); - l.removeItem('email'); - l.removeItem('avatar'); - l.removeItem('name'); - l.removeItem('url'); - _.user.init(); - }) - }, - - // 提交访客信息 - submit: function(user){ - l.setItem('email', user.email); - l.setItem('type', user.type); - l.setItem('name', user.name); - l.setItem('url', user.url); - l.setItem('avatar', user.avatar); - l.setItem('logged_in', 'true'); - this.init(); - } - } - - var iDisqus = function () { - var _ = this; - - // 配置 - _.opts = typeof(arguments[1]) == 'object' ? arguments[1] : arguments[0]; - _.dom = d.getElementById(typeof(arguments[0]) == 'string' ? arguments[0] : 'comment'); - _.opts.api = _.opts.api.slice(-1) == '/' ? _.opts.api.slice(0,-1) : _.opts.api; - _.opts.site = _.opts.site || location.origin; - if(!!_.opts.url){ - var optsUrl = _.opts.url.replace(_.opts.site, ''); - _.opts.url = optsUrl.slice(0, 1) != '/' ? '/' + optsUrl : optsUrl; - } else if(isEdge || isIE) { - _.opts.url = encodeURI(location.pathname) + encodeURI(location.search); - } else { - _.opts.url = location.pathname + location.search; - } - _.opts.identifier = _.opts.identifier || _.opts.url; - _.opts.link = _.opts.site + _.opts.url; - _.opts.title = _.opts.title || d.title; - _.opts.slug = !!_.opts.slug ? _.opts.slug.replace(/[^A-Za-z0-9_-]+/g,'') : ''; - _.opts.desc = _.opts.desc || (!!d.querySelector('[name="description"]') ? d.querySelector('[name="description"]').content : ''); - _.opts.mode = _.opts.mode || 1; - _.opts.timeout = _.opts.timeout || 3000; - _.opts.toggle = !!_.opts.toggle ? d.getElementById(_.opts.toggle) : null; - _.opts.autoCreate = !!_.opts.autoCreate || !!_.opts.auto; - - // emoji 表情 - _.opts.emojiPath = _.opts.emojiPath || _.opts.emoji_path || 'https://cdn.jsdelivr.net/emojione/assets/png/'; - _.emojiList = _.opts.emojiList || _.opts.emoji_list || [{ - code:'smile', - title:'笑脸', - unicode:'1f604' - },{ - code:'mask', - title:'生病', - unicode:'1f637' - },{ - code:'joy', - title:'破涕为笑', - unicode:'1f602' - },{ - code:'stuck_out_tongue_closed_eyes', - title:'吐舌', - unicode:'1f61d' - },{ - code:'flushed', - title:'脸红', - unicode:'1f633' - },{ - code:'scream', - title:'恐惧', - unicode:'1f631' - },{ - code:'pensive', - title:'失望', - unicode:'1f614' - },{ - code:'unamused', - title:'无语', - unicode:'1f612' - },{ - code:'grin', - title:'露齿笑', - unicode:'1f601' - },{ - code:'heart_eyes', - title:'色', - unicode:'1f60d' - },{ - code:'sweat', - title:'汗', - unicode:'1f613' - },{ - code:'smirk', - title:'得意', - unicode:'1f60f' - },{ - code:'relieved', - title:'满意', - unicode:'1f60c' - },{ - code:'rolling_eyes', - title:'翻白眼', - unicode:'1f644' - },{ - code:'ok_hand', - title:'OK', - unicode:'1f44c' - },{ - code:'v', - title:'胜利', - unicode:'270c' - }]; - - if(!!_.opts.emoji_preview || !!_.opts.emojiPreview ){ - getAjax(_.opts.api +'/eac.min.php', function(resp){ - _.eac = JSON.parse(resp); - }, function(){ - }) - } - - // 默认状态 - _.stat = { - current: 'idisqus', // 当前显示评论框 - loaded: false, // 评论框已加载 - loading: false, // 评论加载中 - editing: false, // 评论编辑中 - offsetTop: 0, // 高度位置 - thread: null, // 本页 thread id - next: null, // 下条评论 - message: null, // 新评论 - mediaHtml: null, // 新上传图片 - root: [], // 根评论 - count: 0, // 评论数 - users: [], // Disqus 会员 - imageSize: [], // 已上传图片大小 - disqusLoaded: false // Disqus 已加载 - }; - - // Disqus 评论框设置 - window.disqus_config = function () { - this.page.identifier = _.opts.identifier; - this.page.title = _.opts.title; - this.page.url = _.opts.link; - this.callbacks.onReady.push(function() { - _.stat.current = 'disqus'; - _.stat.disqusLoaded = true; - _.dom.querySelector('#idisqus').style.display = 'none'; - _.dom.querySelector('#disqus_thread').style.display = 'block'; - if( _.opts.mode == 3 && !!_.opts.toggle) { - _.opts.toggle.disabled = ''; - _.opts.toggle.checked = true; - _.opts.toggle.addEventListener('change', _.handle.toggle, false); - } - }); - } - - // 自动初始化 - if( !!_.opts.init ){ - _.init(); - //console.log(_); - } - } - - // TimeAgo https://coderwall.com/p/uub3pw/javascript-timeago-func-e-g-8-hours-ago - iDisqus.prototype.timeAgo = function() { - - var _ = this; - var templates = { - prefix: "", - suffix: "前", - seconds: "几秒", - minute: "1分钟", - minutes: "%d分钟", - hour: "1小时", - hours: "%d小时", - day: "1天", - days: "%d天", - month: "1个月", - months: "%d个月", - year: "1年", - years: "%d年" - }; - var template = function (t, n) { - return templates[t] && templates[t].replace(/%d/i, Math.abs(Math.round(n))); - }; - - var timer = function (time) { - if (!time) return; - time = time.replace(/\.\d+/, ""); // remove milliseconds - time = time.replace(/-/, "/").replace(/-/, "/"); - time = time.replace(/T/, " ").replace(/Z/, " UTC"); - time = time.replace(/([\+\-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400 - time = new Date(time * 1000 || time); - - var now = new Date(); - var seconds = ((now.getTime() - time) * .001) >> 0; - var minutes = seconds / 60; - var hours = minutes / 60; - var days = hours / 24; - var years = days / 365; - - return templates.prefix + ( seconds < 45 && template('seconds', seconds) || seconds < 90 && template('minute', 1) || minutes < 45 && template('minutes', minutes) || minutes < 90 && template('hour', 1) || hours < 24 && template('hours', hours) || hours < 42 && template('day', 1) || days < 30 && template('days', days) || days < 45 && template('month', 1) || days < 365 && template('months', days / 30) || years < 1.5 && template('year', 1) || template('years', years)) + templates.suffix; - }; - - var elements = _.dom.querySelectorAll('.comment-item-time'); - for (var i in elements) { - var $this = elements[i]; - if (typeof $this === 'object') { - $this.title = new Date($this.getAttribute('datetime')); - $this.innerHTML = timer($this.getAttribute('datetime')); - } - } - - // update time every minute - setTimeout(_.timeAgo.bind(_), 60000); - - } - - // 初始化评论框 - iDisqus.prototype.init = function(){ - var _ = this; - if(!_.dom){ - //console.log('该页面没有评论框!'); - return - } - // 表情 - var emojiList = ''; - _.emojiList.forEach(function(item){ - emojiList += '<li class="emojione-item" title="'+ item.title+'" data-code=":'+item.code+':"><img class="emojione-item-image" src="'+_.opts.emojiPath + item.unicode+'.png" /></li>'; - }) - _.dom.innerHTML = '<div class="comment loading" id="idisqus">\n'+ - ' <div class="loading-container" data-tip="正在加载评论……"><svg class="loading-bg" width="72" height="72" viewBox="0 0 720 720" version="1.1" xmlns="http://www.w3.org/2000/svg"><path class="ring" fill="none" stroke="#9d9ea1" d="M 0 -260 A 260 260 0 1 1 -80 -260" transform="translate(400,400)" stroke-width="50" /><polygon transform="translate(305,20)" points="50,0 0,100 18,145 50,82 92,145 100,100" style="fill:#9d9ea1"/></svg></div>\n'+ - ' <div class="comment-header"><span class="comment-header-item" id="comment-count">评论</span><a target="_blank" class="comment-header-item" id="comment-link">Disqus 讨论区</a></div>\n'+ - ' <div class="comment-box">\n'+ - ' <div class="comment-avatar avatar"><img class="comment-avatar-image" src="//a.disquscdn.com/images/noavatar92.png" data-avatar="//a.disquscdn.com/images/noavatar92.png"></div>\n'+ - ' <div class="comment-form">\n'+ - ' <div class="comment-form-wrapper">\n'+ - ' <textarea class="comment-form-textarea" placeholder="加入讨论……"></textarea>\n'+ - ' <div class="comment-form-alert"></div>\n'+ - ' <div class="comment-image">\n'+ - ' <ul class="comment-image-list"></ul>\n'+ - ' <div class="comment-image-progress">\n'+ - ' <div class="comment-image-loaded"></div>\n'+ - ' </div>\n'+ - ' </div>\n'+ - ' <div class="comment-actions">\n'+ - ' <div class="comment-actions-group">\n'+ - ' <input id="emoji-input" class="comment-actions-input" type="checkbox"> \n'+ - ' <label class="comment-actions-label emojione" for="emoji-input">\n'+ - ' <svg class="icon" fill="#c2c6cc" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">\n'+ - ' <g>\n'+ - ' <title>选择表情</title>\n'+ - ' <path d="M512 1024c-282.713043 0-512-229.286957-512-512s229.286957-512 512-512c282.713043 0 512 229.286957 512 512S792.486957 1024 512 1024zM512 44.521739c-258.226087 0-467.478261 209.252174-467.478261 467.478261 0 258.226087 209.252174 467.478261 467.478261 467.478261s467.478261-209.252174 467.478261-467.478261C979.478261 253.773913 768 44.521739 512 44.521739z"></path>\n'+ - ' <path d="M801.391304 554.295652c0 160.278261-129.113043 289.391304-289.391304 289.391304s-289.391304-129.113043-289.391304-289.391304L801.391304 554.295652z"></path>\n'+ - ' <path d="M674.504348 349.495652m-57.878261 0a2.6 2.6 0 1 0 115.756522 0 2.6 2.6 0 1 0-115.756522 0Z"></path>\n'+ - ' <path d="M347.269565 349.495652m-57.878261 0a2.6 2.6 0 1 0 115.756522 0 2.6 2.6 0 1 0-115.756522 0Z"></path>\n'+ - ' </g>\n'+ - ' </svg>\n'+ - ' <ul class="emojione-list">'+emojiList+'</ul>\n'+ - ' </label>\n'+ - ' <input id="upload-input" class="comment-actions-input comment-image-input" type="file" accept="image/*" name="file"> \n'+ - ' <label class="comment-actions-label" for="upload-input">\n'+ - ' <svg class="icon" fill="#c2c6cc" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">\n'+ - ' <g>\n'+ - ' <title>上传图片</title>\n'+ - ' <path d="M15.515152 15.515152 15.515152 15.515152 15.515152 15.515152Z"></path>\n'+ - ' <path d="M15.515152 139.636364l0 806.787879 992.969697 0 0-806.787879-992.969697 0zM946.424242 884.363636l-868.848485 0 0-682.666667 868.848485 0 0 682.666667zM698.181818 356.848485c0-51.417212 41.673697-93.090909 93.090909-93.090909s93.090909 41.673697 93.090909 93.090909c0 51.417212-41.673697 93.090909-93.090909 93.090909s-93.090909-41.673697-93.090909-93.090909zM884.363636 822.30303l-744.727273 0 186.181818-496.484848 248.242424 310.30303 124.121212-93.090909z"></path>\n'+ - ' </g>\n'+ - ' </svg>\n'+ - ' </label>\n'+ - ' </div>\n'+ - ' <div class="comment-actions-form">\n'+ - ' <label class="comment-actions-label exit" title="退出登录">\n'+ - ' <svg class="icon" fill="#c2c6cc" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48">\n'+ - ' <path d="M348.870666 210.685443l378.570081 0c32.8205 0 58.683541 26.561959 58.683541 58.683541 0 162.043606 0 324.804551 0 486.848157 0 32.81129-26.561959 58.674331-58.683541 58.674331L348.870666 814.891472c-10.477632 0-18.850323-8.363482-18.850323-18.841114l0-37.728276c0-10.477632 8.372691-18.841114 18.850323-18.841114l343.645664 0c10.477632 0 18.850323-8.372691 18.850323-18.850323L711.366653 304.983109c0-10.477632-8.372691-18.841114-18.850323-18.841114L348.870666 286.141996c-10.477632 0-18.850323-8.363482-18.850323-18.841114l0-37.728276C329.98248 219.095997 338.393034 210.685443 348.870666 210.685443z"></path>\n'+ - ' <path d="M128.152728 526.436804l112.450095 112.450095c6.985088 6.985088 19.567661 6.985088 26.552749 0l26.561959-26.561959c6.985088-6.985088 6.985088-19.567661 0-26.552749l-34.925441-34.925441L494.168889 550.84675c10.477632 0 18.850323-8.372691 18.850323-18.850323l0-37.719066c0-10.477632-8.372691-18.850323-18.850323-18.850323L258.754229 475.427036l34.925441-34.925441c6.985088-6.985088 6.985088-19.567661 0-26.552749l-26.561959-26.524097c-6.985088-6.985088-19.567661-6.985088-26.552749 0L128.152728 499.875868C120.431883 506.859933 120.431883 519.451716 128.152728 526.436804z"></path>\n'+ - ' </svg>\n'+ - ' </label>\n'+ - ' <button class="comment-form-submit">\n'+ - ' <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">\n'+ - ' <path d="M565.747623 792.837176l260.819261 112.921839 126.910435-845.424882L66.087673 581.973678l232.843092 109.933785 562.612725-511.653099-451.697589 563.616588-5.996574 239.832274L565.747623 792.837176z" fill="#ffffff"></path>\n'+ - ' </svg>\n'+ - ' </button>\n'+ - ' </div>\n'+ - ' </div>\n'+ - ' </div>\n'+ - ' <div class="comment-form-user">'+ ( _.opts.mode != 1 ? '<div class="comment-form-auth"><button class="comment-form-login" title="使用 Disqus 帐号登录"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 200 200"><path fill="#2E9FFF" d="M102.535 167.5c-16.518 0-31.621-6.036-43.298-16.021L30.5 155.405l11.102-27.401A67.658 67.658 0 0 1 35.564 100c0-37.277 29.984-67.5 66.971-67.5 36.984 0 66.965 30.223 66.965 67.5 0 37.284-29.98 67.5-66.965 67.5zm36.567-67.693v-.188c0-19.478-13.736-33.367-37.42-33.367h-25.58v67.5h25.201c23.868.001 37.799-14.468 37.799-33.945zm-37.138 17.361h-7.482V82.841h7.482c10.989 0 18.283 6.265 18.283 17.07v.188c0 10.896-7.294 17.069-18.283 17.069z"/></svg></button></div><span> 或 </span>' : '' ) + '<div class="comment-form-guest"><input class="comment-form-input comment-form-name" type="text" name="name" placeholder="名字(必填)" autocomplete="name"><input class="comment-form-input comment-form-email" type="email" name="email" placeholder="邮箱(必填)" autocomplete="email"><input class="comment-form-input comment-form-url" type="url" name="url" placeholder="网址(可选)" autocomplete="url"></div></div>\n'+ - ' </div>\n'+ - ' </div>\n'+ - ' <ul id="comments" class="comment-list"></ul>\n'+ - ' <a href="javascript:;" class="comment-loadmore">加载更多</a>\n'+ - '</div>\n'+ - '<div class="comment" id="disqus_thread"></div>'; - - _.user = new User(_.dom,_.opts); - _.box = _.dom.querySelector('.comment-box').outerHTML.replace(/<label class="comment-actions-label exit"(.|\n)*<\/label>\n/,'').replace('comment-form-wrapper','comment-form-wrapper editing').replace(/加入讨论……/,''); - _.handle = { - logout: _.user.logout.bind(_), - login: _.user.login.bind(_), - loadMore: _.loadMore.bind(_), - post: _.post.bind(_), - postThread: _.postThread.bind(_), - remove: _.remove.bind(_), - show: _.show.bind(_), - toggle: _.toggle.bind(_), - upload: _.upload.bind(_), - verify: _.verify.bind(_), - jump: _.jump.bind(_), - mention: _.mention.bind(_), - keySelect: _.keySelect.bind(_), - field: _.field, - focus: _.focus, - input: _.input - }; - - switch(_.opts.mode){ - case 1: - _.disqus(); - break; - case 2: - _.getlist(); - break; - case 3: - _.getlist(); - _.disqus(); - break; - default: - _.disqus(); - break; - } - } - - // 切换评论框 - iDisqus.prototype.toggle = function(){ - var _ = this; - if( _.stat.current == 'disqus' ){ - _.stat.current = 'idisqus'; - _.dom.querySelector('#idisqus').style.display = 'block'; - _.dom.querySelector('#disqus_thread').style.display = 'none'; - } else { - _.disqus(); - } - } - - // 加载 Disqus 评论 - iDisqus.prototype.disqus = function(){ - var _ = this; - var _tip = _.dom.querySelector('.loading-container').dataset.tip; - //if(_.opts.site != location.origin){ - // //console.log('本地环境不加载 Disqus 评论框!'); - // if( _.opts.mode == 1 ){ - // _.getlist(); - // } - // return; - //} - if(!_.stat.disqusLoaded ){ - _tip = '尝试连接 Disqus……'; - - var s = d.createElement('script'); - s.src = '//'+_.opts.forum+'.disqus.com/embed.js'; - s.dataset.timestamp = Date.now(); - s.onload = function(){ - _.stat.disqusLoaded = true; - _tip = '连接成功,加载 Disqus 评论框……' - } - s.onerror = function(){ - if( _.opts.mode == 1){ - _tip = '连接失败,加载简易评论框……'; - _.getlist(); - } - } - - var xhr = new XMLHttpRequest(); - xhr.open('GET', '//disqus.com/next/config.json?' + Date.now(), true); - xhr.timeout = _.opts.timeout; - xhr.onreadystatechange = function () { - if (xhr.readyState == 4 && xhr.status == 200) { - (d.head || d.body).appendChild(s); - } - } - xhr.ontimeout = function () { - xhr.abort(); - if( _.opts.mode == 1){ - _tip = '连接超时,加载简易评论框……'; - _.getlist(); - } - } - xhr.onerror = function() { - if( _.opts.mode == 1){ - _tip = '连接失败,加载简易评论框……'; - _.getlist(); - } - } - xhr.send(); - } else { - _.stat.current = 'disqus'; - _.dom.querySelector('#idisqus').style.display = 'none'; - _.dom.querySelector('#disqus_thread').style.display = 'block'; - } - } - - // 添加事件监听 - iDisqus.prototype.addListener = function (els, evt, func){ - var _ = this; - var el = _.dom.getElementsByClassName(els); - [].forEach.call(el, function(item){ - item.addEventListener(evt, func, false); - }); - } - - // 移除事件监听 - iDisqus.prototype.removeListener = function (els, evt, func){ - var _ = this; - var el = _.dom.getElementsByClassName(els); - [].forEach.call(el, function(item){ - item.removeEventListener(evt, func, false); - }); - } - - // 添加所有事件监听 - iDisqus.prototype.addAllListeners = function (){ - var _ = this; - _.addListener('exit', 'click', _.handle.logout); - _.addListener('comment-form-textarea', 'blur', _.handle.focus); - _.addListener('comment-form-textarea', 'focus', _.handle.focus); - _.addListener('comment-form-textarea', 'input', _.handle.input); - _.addListener('comment-form-textarea', 'keyup', _.handle.mention); - _.addListener('comment-form-email', 'blur', _.handle.verify); - _.addListener('comment-form-submit', 'click', _.handle.post); - _.addListener('comment-form-login', 'click', _.handle.login); - _.addListener('comment-image-input', 'change', _.handle.upload); - _.addListener('emojione-item', 'click', _.handle.field); - } - - // 评论计数 - iDisqus.prototype.count = function (){ - var _ = this; - var counts = d.querySelectorAll('[data-disqus-url]'); - var qty = counts.length; - if(qty > 0){ - var commentArr = []; - for( var i = 0; i < qty; i++){ - commentArr[i] = counts[i].dataset.disqusUrl.replace(_.opts.site, ''); - } - getAjax( - _.opts.api + '/count.php?links=' + commentArr.join(','), - function(resp) { - var data = JSON.parse(resp); - var posts = data.response; - posts.forEach(function(item){ - var link = document.createElement('a'); - link.href = item.link; - var itemLink = link.href.replace(link.origin, ''); - var el = d.querySelector('[data-disqus-url$="'+itemLink+'"]') - if(!!el ){ - el.innerHTML = item.posts; - el.dataset.disqusCount = item.posts; - } - }); - }, function(){ - console.log('获取数据失败!') - } - ); - } - }; - - // 热门评论 - iDisqus.prototype.popular = function(){ - var _ = this; - if(!!_.opts.popular){ - getAjax( - _.opts.api + '/popular.php', - function(resp) { - var data = JSON.parse(resp); - if(data.code == 0){ - var posts = data.response; - var postsHtml = ''; - posts.forEach(function(item){ - postsHtml += '<li><a href="' + item.link.replace(_.opts.site, '') + '" title="' + item.title + '">' + item.title + '</a></li>'; - }); - _.opts.popular.innerHTML = postsHtml; - } - },function(){ - console.log('获取数据失败!') - } - ); - } - } - - // 获取评论列表 - iDisqus.prototype.getlist = function(){ - var _ = this; - _.stat.loading = true; - _.dom.querySelector('#idisqus').style.display = 'block'; - _.dom.querySelector('#disqus_thread').style.display = 'none'; - getAjax( - _.opts.api + '/getcomments.php?ident=' + _.opts.identifier + (!!_.stat.next ? '&cursor=' + _.stat.next : ''), - function(resp){ - var data = JSON.parse(resp); - if (data.code === 0) { - _.stat.offsetTop = d.documentElement.scrollTop || d.body.scrollTop; - _.stat.thread = data.thread; - _.stat.count = data.posts; - _.opts.avatar = data.forum.avatar; - _.dom.querySelector('.comment-avatar-image').dataset.avatar = data.forum.avatar; - if( _.user.logged_in == 'false' ){ - _.dom.querySelector('.comment-avatar-image').src = data.forum.avatar; - } - _.opts.badge = data.forum.moderatorBadgeText; - _.dom.querySelector('#idisqus').classList.remove('loading'); - _.dom.querySelector('#comment-link').href = data.link; - _.dom.querySelector('#comment-count').innerHTML = _.stat.count + ' 条评论'; - var loadmore = _.dom.querySelector('.comment-loadmore'); - var posts = !!data.response ? data.response : []; - _.stat.root = []; - posts.forEach(function(item){ - _.load(item); - if(!item.parent){ - _.stat.root.unshift(item.id); - } - }); - - if ( data.cursor.hasPrev ){ - _.stat.root.forEach(function(item){ - _.dom.querySelector('.comment-list').appendChild(_.dom.querySelector('#comment-' + item)); - }) - } else { - loadmore.addEventListener('click', _.handle.loadMore, false); - _.addAllListeners(); - } - if ( data.cursor.hasNext ){ - _.stat.next = data.cursor.next; - loadmore.classList.remove('loading'); - } else { - _.stat.next = null; - loadmore.classList.add('hide'); - } - if (posts.length == 0) { - return; - } - - window.scrollTo(0, _.stat.offsetTop); - - _.timeAgo(); - - if (/^#disqus|^#comment-/.test(location.hash) && !data.cursor.hasPrev && !_.stat.disqusLoaded && !_.stat.loaded) { - var el = _.dom.querySelector('#idisqus ' + location.hash) - if( !!el ){ - window.scrollBy(0, el.getBoundingClientRect().top); - } - } - _.stat.loading = false; - _.stat.loaded = true; - } else if ( data.code === 2 ){ - _.create(); - } - },function(){ - alert('获取数据失败,请检查服务器设置。') - } - ); - } - - // 读取评论 - iDisqus.prototype.load = function(post){ - - var _ = this; - - var parentPostDom = _.dom.querySelector('.comment-item[data-id="'+post.parent+'"]'); - - var user = { - username: post.username, - name: post.name, - avatar: post.avatar - } - if(!!post.username && _.stat.users.map(function(user) { return user.username; }).indexOf(post.username) == -1){ - _.stat.users.push(user); - } - - var parentPost = !!post.parent ? { - name: '<a class="comment-item-pname" href="#'+parentPostDom.id+'"><svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1.664 902.144s97.92-557.888 596.352-557.888V129.728L1024 515.84l-425.984 360.448V628.8c-270.464 0-455.232 23.872-596.352 273.28"></path></svg>' + parentPostDom.dataset.name + '</a>', - dom: parentPostDom.querySelector('.comment-item-children'), - insert: 'afterbegin' - } : { - name: '', - dom: _.dom.querySelector('.comment-list'), - insert: post.id == 'preview' || !!post.isPost ? 'afterbegin' : 'beforeend' - }; - - var mediaHTML = ''; - if( post.media.length == 1 ){ - mediaHTML = '<div class="comment-item-images"><a class="comment-item-image" target="_blank" href="' + post.media[0] + '" style="background-image: url('+post.media[0]+');width: 167px;height: 167px"></a></div>'; - } else if( post.media.length > 1 ){ - post.media.forEach(function(item){ - mediaHTML += '<a class="comment-item-image" target="_blank" href="' + item + '" style="background-image: url('+item+')"></a>'; - }) - mediaHTML = '<div class="comment-item-images">' + mediaHTML + '</div>'; - } - - var html = '<li class="comment-item" data-id="' + post.id + '" data-name="'+ post.name + '" id="comment-' + post.id + '">' + - '<div class="comment-item-body">'+ - '<a class="comment-item-avatar" href="#comment-'+post.id+'"><img src="' + post.avatar + '"></a>'+ - '<div class="comment-item-main">'+ - '<div class="comment-item-header"><a class="comment-item-name" title="' + post.name + '" rel="nofollow" target="_blank" href="' + ( post.url ? post.url : 'javascript:;' ) + '">' + post.name + '</a>'+ (post.isMod ?'<span class="comment-item-badge">'+_.opts.badge+'</span>' :'')+parentPost.name+'<span class="comment-item-bullet"> • </span><time class="comment-item-time" datetime="' + post.createdAt + '"></time></div>'+ - '<div class="comment-item-content">' + post.message + mediaHTML + '</div>'+ - '<div class="comment-item-footer">' + (!!post.isPost ? '<span class="comment-item-manage"><a class="comment-item-edit" href="javascript:;">编辑</a><span class="comment-item-bullet"> • </span><a class="comment-item-delete" href="javascript:;">删除</a><span class="comment-item-bullet"> • </span></span>' : '') + '<a class="comment-item-reply" href="javascript:;">回复</a> </div>'+ - '</div></div>'+ - '<ul class="comment-item-children"></ul>'+ - '</li>'; - - // 已删除评论 - if(!!post.isDeleted){ - html = '<li class="comment-item" data-id="' + post.id + '" id="comment-' + post.id + '" data-name="已删除">' + - '<div class="comment-item-body">'+ - '<a class="comment-item-avatar" href="#comment-'+post.id+'"><img src="' + post.avatar + '"></a>'+ - '<div class="comment-item-main" data-message="此评论已被删除。"></div></div>'+ - '<ul class="comment-item-children"></ul>'+ - '</li>'; - } - - - // 更新 or 创建 - if(!!_.dom.querySelector('.comment-item[data-id="' + post.id + '"]')){ - _.dom.querySelector('.comment-item[data-id="' + post.id + '"]').outerHTML = html; - } else { - parentPost.dom.insertAdjacentHTML(parentPost.insert, html); - } - - if(!post.isDeleted){ - _.dom.querySelector('.comment-item[data-id="' + post.id + '"] .comment-item-reply').addEventListener('click', _.handle.show, false); - _.dom.querySelector('.comment-item[data-id="' + post.id + '"] .comment-item-avatar').addEventListener('click', _.handle.jump, false); - if( !!post.parent ) { - _.dom.querySelector('.comment-item[data-id="' + post.id + '"] .comment-item-pname').addEventListener('click', _.handle.jump, false); - } - } - - // 发布留言,可编辑删除 - if(!!post.isPost && !_.stat.editing){ - var $this = _.dom.querySelector('.comment-item[data-id="' + post.id + '"]'); - - var postEdit = setTimeout(function(){ - // 十分钟后 - if(!!$this.querySelector('.comment-item-manage')){ - $this.querySelector('.comment-item-manage').outerHTML = ''; - } - }, 600000); - - // 删除 - $this.querySelector('.comment-item-delete').addEventListener('click',function(e){ - var postData = { - id: post.id - } - var delDom = e.currentTarget; - delDom.innerHTML = '删除中'; - postAjax( _.opts.api + '/removecomment.php', postData, function(resp){ - var data = JSON.parse(resp); - if (data.code === 0) { - if(data.response.isDeleted == true){ - $this.outerHTML = ''; - } else { - alert(data.response.message); - $this.querySelector('.comment-item-manage').outerHTML = ''; - } - } else if (data.code === 2) { - alert(data.response); - $this.querySelector('.comment-item-manage').outerHTML = ''; - } - }, function(){ - alert('删除出错,请稍后重试'); - }) - clearTimeout(postEdit); - }, false) - - // 编辑 - $this.querySelector('.comment-item-edit').addEventListener('click',function(){ - _.stat.editing = post; - _.edit(post); - }, false) - } - } - - // 读取更多 - iDisqus.prototype.loadMore = function(e){ - var _ = this; - _.stat.offsetTop = d.documentElement.scrollTop || d.body.scrollTop; - if( !_.stat.loading ){ - e.currentTarget.classList.add('loading'); - _.getlist(); - } - } - - // 评论框焦点 - iDisqus.prototype.focus = function(e){ - var wrapper = e.currentTarget.closest('.comment-form-wrapper'); - wrapper.classList.add('editing'); - if (wrapper.classList.contains('focus')){ - wrapper.classList.remove('focus'); - } else{ - wrapper.classList.add('focus'); - } - } - - // 输入事件 - iDisqus.prototype.input = function(e){ - var form = e.currentTarget.closest('.comment-form'); - var alertmsg = form.querySelector('.comment-form-alert'); - alertmsg.innerHTML = ''; - } - - // 提醒用户 @ mention - iDisqus.prototype.mention = function(e){ - var _ = this; - var textarea = e.currentTarget; - var selStart = textarea.selectionStart; - var mentionIndex = textarea.value.slice(0, selStart).lastIndexOf('@'); - var mentionText = textarea.value.slice(mentionIndex, selStart); - var mentionDom = _.dom.querySelector('.mention-user'); - if(mentionText.search(/^@\w+$|^@$/) == 0){ - if( e.keyCode == 38 || e.keyCode == 40){ - return; - } - var showUsers = _.stat.users.filter(function(user){ - var re = new RegExp(mentionText.slice(1), 'i'); - return user.username.search(re) > -1; - }); - var coord = _.getCaretCoord(textarea); - var list='', html = ''; - - if( showUsers.length > 0){ - showUsers.forEach(function(item, i){ - list += '<li class="mention-user-item'+(i == 0 ? ' active' : '')+'" data-username="'+item.username+'"><img class="mention-user-avatar" src="'+item.avatar+'"><div class="mention-user-username">'+item.username+'</div><div class="mention-user-name">'+item.name+'</div></li>'; - }) - if(!!mentionDom){ - mentionDom.innerHTML = '<ul class="mention-user-list">'+list+'</ul>'; - mentionDom.style.left = coord.left + 'px'; - mentionDom.style.top = coord.top + 'px'; - } else { - html = '<div class="mention-user" style="left:'+coord.left+'px;top:'+coord.top+'px"><ul class="mention-user-list">'+list+'</ul></div>'; - _.dom.querySelector('#idisqus').insertAdjacentHTML('beforeend', html); - } - - // 鼠标悬浮 - _.addListener('mention-user-item', 'mouseover', function(){ - _.dom.querySelector('.mention-user-item.active').classList.remove('active'); - this.classList.add('active'); - }) - - // 鼠标点击 - _.addListener('mention-user-item', 'click', function(){ - var username = '@' + this.dataset.username + ' '; - textarea.value = textarea.value.slice(0, mentionIndex) + username + textarea.value.slice(selStart); - _.dom.querySelector('.mention-user').outerHTML = ''; - textarea.focus(); - textarea.setSelectionRange(mentionIndex + username.length, mentionIndex + username.length) - textarea.removeEventListener('keydown', _.handle.keySelect, false); - }) - - // 键盘事件 - textarea.addEventListener('keydown', _.handle.keySelect, false); - } else{ - if(!!mentionDom){ - mentionDom.outerHTML = ''; - textarea.removeEventListener('keydown', _.handle.keySelect, false); - } - } - } else { - if(!!mentionDom){ - mentionDom.outerHTML = ''; - textarea.removeEventListener('keydown', _.handle.keySelect, false); - } - } - } - - // 获取光标坐标 https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a - iDisqus.prototype.getCaretCoord = function(textarea){ - var _ = this; - var carPos = textarea.selectionEnd, - div = d.createElement('div'), - span = d.createElement('span'), - copyStyle = getComputedStyle(textarea); - [].forEach.call(copyStyle, function(prop){ - div.style[prop] = copyStyle[prop]; - }); - div.style.position = 'absolute'; - _.dom.appendChild(div); - div.textContent = textarea.value.substr(0, carPos); - span.textContent = textarea.value.substr(carPos) || '.'; - div.appendChild(span); - var coords = { - 'top': textarea.offsetTop - textarea.scrollTop + span.offsetTop + parseFloat(copyStyle.lineHeight), - 'left': textarea.offsetLeft - textarea.scrollLeft + span.offsetLeft - }; - _.dom.removeChild(div); - return coords; - } - - // 键盘选择用户 - iDisqus.prototype.keySelect = function(e){ - var _ = this; - var textarea = e.currentTarget; - var selStart = textarea.selectionStart; - var mentionIndex = textarea.value.slice(0, selStart).lastIndexOf('@'); - var mentionText = textarea.value.slice(mentionIndex, selStart); - var mentionDom = _.dom.querySelector('.mention-user'); - var current = _.dom.querySelector('.mention-user-item.active') - switch(e.keyCode){ - case 13: - //回车 - var username = '@' + current.dataset.username + ' '; - textarea.value = textarea.value.slice(0, mentionIndex) + username + textarea.value.slice(selStart); - textarea.setSelectionRange(mentionIndex + username.length, mentionIndex + username.length) - _.dom.querySelector('.mention-user').outerHTML = ''; - textarea.removeEventListener('keydown', _.handle.keySelect, false); - e.preventDefault(); - break; - case 38: - //上 - if(!!current.previousSibling){ - current.previousSibling.classList.add('active'); - current.classList.remove('active'); - } - e.preventDefault(); - break; - case 40: - //下 - if(!!current.nextSibling){ - current.nextSibling.classList.add('active'); - current.classList.remove('active'); - } - e.preventDefault(); - break; - default: - break; - } - } - - // 跳到评论 - iDisqus.prototype.jump = function(e){ - var _ = this; - var $this = e.currentTarget; - var hash = getLocation($this.href).hash; - var el = _.dom.querySelector('#idisqus ' + hash); - history.replaceState(undefined, undefined, hash); - window.scrollBy(0, el.getBoundingClientRect().top); - e.preventDefault(); - } - - // 点选表情 - iDisqus.prototype.field = function(e){ - var item = e.currentTarget; - var form = item.closest('.comment-form'); - var textarea = form.querySelector('.comment-form-textarea'); - var selStart = textarea.selectionStart; - var shortCode = selStart == 0 ? item.dataset.code + ' ' : ' ' + item.dataset.code + ' ' - textarea.value = textarea.value.slice(0, selStart) + shortCode + textarea.value.slice(selStart) - textarea.focus(); - textarea.setSelectionRange(selStart + shortCode.length, selStart + shortCode.length); - } - - // 显示回复框 or 取消回复框 - iDisqus.prototype.show = function(e){ - var _ = this; - - var $this = e.currentTarget; - var item = $this.closest('.comment-item'); - - // 无论取消还是回复,移除已显示回复框 - var box = _.dom.querySelector('.comment-item .comment-box:not([data-current-id])'); - if( box ){ - var $show = box.closest('.comment-item'); - var cancel = $show.querySelector('.comment-item-cancel') - cancel.outerHTML = cancel.outerHTML.replace('cancel','reply'); - box.outerHTML = ''; - } - - // 回复时,显示评论框 - if( $this.className == 'comment-item-reply' ){ - $this.outerHTML = $this.outerHTML.replace('reply','cancel'); - var commentBox = _.box.replace(/emoji-input/g,'emoji-input-'+item.dataset.id).replace(/upload-input/g,'upload-input-'+item.dataset.id); - item.querySelector('.comment-item-children').insertAdjacentHTML('beforebegin', commentBox); - _.user.init(); - - _.addAllListeners(); - item.querySelector('.comment-form-textarea').focus(); - } - - // 监听事件 - _.addListener('comment-item-reply', 'click', _.handle.show); - _.addListener('comment-item-cancel', 'click', _.handle.show); - - } - - // 验证表单 - iDisqus.prototype.verify = function(e){ - var _ = this; - var box = e.currentTarget.closest('.comment-box'); - var avatar = box.querySelector('.comment-avatar-image'); - var email = box.querySelector('.comment-form-email'); - var alertmsg = box.querySelector('.comment-form-alert'); - if(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(email.value)){ - getAjax( - _.opts.api + '/getgravatar.php?email=' + email.value, - function(resp) { - if (resp == 'false') { - _.errorTips('您所填写的邮箱地址有误。', email); - } else { - avatar.src = resp; - } - }, function(){ - } - ); - } - } - - // 上传图片 - iDisqus.prototype.upload = function(e){ - var _ = this; - var file = e.currentTarget; - var form = file.closest('.comment-form'); - var progress = form.querySelector('.comment-image-progress'); - var loaded = form.querySelector('.comment-image-loaded'); - var wrapper = form.querySelector('.comment-form-wrapper'); - var alertmsg = form.querySelector('.comment-form-alert'); - alertmsg.innerHTML = ''; - if(file.files.length === 0){ - return; - } - - // 以文件大小识别是否为同张图片 - var size = file.files[0].size; - - if( size > 5000000 ){ - alertmsg.innerHTML = '请选择 5M 以下图片。'; - setTimeout(function(){ - alertmsg.innerHTML = ''; - }, 3000); - return; - } - - if( _.stat.imageSize.indexOf(size) == -1 ){ - progress.style.width = '80px'; - } else { - alertmsg.innerHTML = '请勿选择已存在的图片。'; - setTimeout(function(){ - alertmsg.innerHTML = ''; - }, 3000); - return; - } - - // 展开图片上传界面 - wrapper.classList.add('expanded'); - - // 图片上传请求 - var data = new FormData(); - data.append('file', file.files[0] ); - var filename = file.files[0].name; - - var $item; - - var xhrUpload = new XMLHttpRequest(); - xhrUpload.withCredentials = true; - xhrUpload.onreadystatechange = function(){ - if(xhrUpload.readyState == 4 && xhrUpload.status == 200){ - var data = JSON.parse(xhrUpload.responseText); - if( data.code == 0 ){ - _.stat.imageSize.push(size); - var imageUrl = data.response[filename].url; - var image = new Image(); - image.src = imageUrl; - image.onload = function(){ - $item.innerHTML = '<img class="comment-image-object" src="'+imageUrl+'">'; - $item.dataset.imageUrl = imageUrl; - $item.classList.remove('loading'); - $item.addEventListener('click', _.handle.remove, false); - } - } else { - alertmsg.innerHTML = '图片上传出错。'; - $item.innerHTML = ''; - if( !!form.getElementsByClassName('comment-image-item').length){ - wrapper.classList.remove('expanded'); - } - setTimeout(function(){ - alertmsg.innerHTML = ''; - }, 3000); - } - } - }; - xhrUpload.upload.addEventListener('progress', function(e){ - loaded.style.width = Math.ceil((e.loaded/e.total) * 100)+ '%'; - }, false); - xhrUpload.upload.addEventListener('load', function(e){ - loaded.style.width = 0; - progress.style.width = 0; - var imageItem = '<li class="comment-image-item loading" data-image-size="' + size + '">\n'+ - ' <svg version="1.1" class="comment-image-object" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\n'+ - ' width="24px" height="30px" viewBox="0 0 24 30" style="enable-background: new 0 0 50 50;" xml:space="preserve">\n'+ - ' <rect x="0" y="10" width="4" height="10" fill="rgba(127,145,158,1)" opacity="0.2">\n'+ - ' <animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' </rect>\n'+ - ' <rect x="8" y="10" width="4" height="10" fill="rgba(127,145,158,1)" opacity="0.2">\n'+ - ' <animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.15s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' </rect>\n'+ - ' <rect x="16" y="10" width="4" height="10" fill="rgba(127,145,158,1)" opacity="0.2">\n'+ - ' <animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.3s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' <animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite" />\n'+ - ' </rect>\n'+ - ' </svg>\n'+ - '</li>\n'; - form.querySelector('.comment-image-list').insertAdjacentHTML('beforeend', imageItem); - $item = form.querySelector('[data-image-size="'+size+'"]'); - }, false); - xhrUpload.open('POST', _.opts.api + '/upload.php', true); - xhrUpload.send(data); - } - - // 移除图片 - iDisqus.prototype.remove = function(e){ - var _ = this; - var $item = e.currentTarget.closest('.comment-image-item'); - var wrapper = e.currentTarget.closest('.comment-form-wrapper'); - $item.outerHTML = ''; - _.stat.imageSize = []; - var imageArr = wrapper.getElementsByClassName('comment-image-item'); - [].forEach.call(imageArr, function(item, i){ - _.stat.imageSize[i] = item.dataset.imageSize; - }); - if(_.stat.imageSize.length == 0){ - wrapper.classList.remove('expanded'); - } - wrapper.querySelector('.comment-image-input').value = ''; - } - - // 错误提示 - iDisqus.prototype.errorTips = function(Text, Dom){ - var _ = this; - if( _.user.logged_in == 'true' ){ - _.handle.logout(); - } - var idisqus = _.dom.querySelector('#idisqus'); - var errorDom = _.dom.querySelector('.comment-form-error'); - if(!!errorDom){ - errorDom.outerHTML = ''; - } - var Top = Dom.offsetTop; - var Left = Dom.offsetLeft; - var errorHtml = '<div class="comment-form-error" style="top:'+Top+'px;left:'+Left+'px;">'+Text+'</div>'; - idisqus.insertAdjacentHTML('beforeend', errorHtml); - setTimeout(function(){ - var errorDom = _.dom.querySelector('.comment-form-error'); - if(!!errorDom){ - errorDom.outerHTML = ''; - } - }, 3000); - } - - // 发表/回复评论 - iDisqus.prototype.post = function(e){ - var _ = this; - var item = e.currentTarget.closest('.comment-box[data-current-id]') || e.currentTarget.closest('.comment-item') || e.currentTarget.closest('.comment-box'); - var message = item.querySelector('.comment-form-textarea').value; - var parentId = !!item.dataset.id ? item.dataset.id : ''; - var imgArr = item.getElementsByClassName('comment-image-item'); - var media = []; - var mediaStr = ''; - [].forEach.call(imgArr, function(image,i){ - media[i] = image.dataset.imageUrl; - mediaStr += ' ' + image.dataset.imageUrl; - }); - - // 不是编辑框需预览 - if( !item.dataset.currentId ){ - var elName = item.querySelector('.comment-form-name'); - var elEmail = item.querySelector('.comment-form-email'); - var elUrl = item.querySelector('.comment-form-url'); - var user = { - name: elName.value, - email: elEmail.value, - url: elUrl.value.replace(/\s/g,''), - avatar: item.querySelector('.comment-avatar-image').src, - type: 0 - } - var alertmsg = item.querySelector('.comment-form-alert'); - var alertClear = function() { - setTimeout(function(){ - alertmsg.innerHTML = ''; - }, 3000); - } - - if(_.user.type != '1'){ - if(/^\s*$/i.test(user.name)){ - _.errorTips('名字不能为空。', elName); - return; - } - if(/^\s*$/i.test(user.email)){ - _.errorTips('邮箱不能为空。', elEmail); - return; - } - if(!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(user.email)){ - _.errorTips('请正确填写邮箱。', elEmail); - return; - } - if(!/^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$|^\s*$/i.test(user.url)){ - _.errorTips('请正确填写网址。', elUrl); - return; - } - _.user.submit(user); - - if( !_.user.name && !_.user.email ){ - return; - } - } - - if(!_.stat.message && !_.stat.mediaHtml){ - _.box = _.dom.querySelector('.comment-box').outerHTML.replace(/<label class="comment-actions-label exit"(.|\n)*<\/label>\n/,'').replace('comment-form-wrapper','comment-form-wrapper editing').replace(/加入讨论……/,''); - } - - if( media.length == 0 && /^\s*$/i.test(message)){ - alertmsg.innerHTML = '评论不能为空或空格。'; - item.querySelector('.comment-form-textarea').focus(); - return; - }; - - var preMessage = message; - - if( !!_.opts.emoji_preview ){ - preMessage = preMessage.replace(/:([-+\w]+):/g, function (match){ - var emojiShort = match.replace(/:/g,''); - var emojiImage = !!_.eac[emojiShort] ? '<img class="emojione" width="24" height="24" alt="'+emojiShort+'" title=":'+emojiShort+':" src="'+_.opts.emojiPath +_.eac[emojiShort]+'.png">' : match; - return emojiImage; - }); - } else { - _.emojiList.forEach(function(item){ - preMessage = preMessage.replace(':'+item.code+':', '<img class="emojione" width="24" height="24" src="' + _.opts.emojiPath + item.unicode + '.png" />'); - }); - } - - var post = { - 'url': !!_.user.url ? _.user.url : '', - 'isMod': false, - 'username': null, - 'name': _.user.name, - 'avatar': _.user.avatar, - 'id': 'preview', - 'parent': parentId, - 'createdAt': (new Date()).toJSON(), - 'message': '<p>' + preMessage + '</p>', - 'media': media - }; - - _.load(post); - - _.timeAgo(); - - // 清空或移除评论框 - _.stat.message = message; - _.stat.mediaHtml = item.querySelector('.comment-image-list').innerHTML; - - if( parentId ){ - item.querySelector('.comment-item-cancel').click(); - } else { - item.querySelector('.comment-form-textarea').value = ''; - item.querySelector('.comment-image-list').innerHTML = ''; - item.querySelector('.comment-form-wrapper').classList.remove('expanded','editing'); - } - } - - // @ - var mentions = message.match(/@\w+/g); - if( !!mentions ){ - mentions = mentions.filter(function(mention) { - return _.stat.users.map(function(user) { return user.username; }).indexOf(mention.slice(1)) > -1; - }); - if( mentions.length > 0 ){ - var re = new RegExp('('+mentions.join('|')+')','g'); - message = message.replace(re,'$1:disqus'); - } - } - - // 文本 + 图片 - message += mediaStr; - - // POST 操作 - // 编辑框则更新评论 - if( !!item.dataset.currentId ){ - var postData = { - id: item.dataset.currentId, - message: message, - } - postAjax( _.opts.api + '/updatecomment.php', postData, function(resp){ - var data = JSON.parse(resp); - if (data.code === 0) { - _.stat.message = null; - _.stat.mediaHtml = null; - var post = data.response; - _.load(post); - _.timeAgo(); - _.stat.editing = false; - } else { - // 取消编辑 - _.load(_.stat.editing) - _.timeAgo(); - _.stat.editing = false; - } - }, function(){ - // 取消编辑 - _.load(_.stat.editing) - _.timeAgo(); - _.stat.editing = false; - }) - } else { - var postData = { - thread: _.stat.thread, - parent: parentId, - message: message, - name: _.user.name, - email: _.user.email, - url: _.user.url, - } - postAjax( _.opts.api + '/postcomment.php', postData, function(resp){ - var data = JSON.parse(resp); - if (data.code === 0) { - _.dom.querySelector('.comment-item[data-id="preview"]').outerHTML = ''; - _.stat.count += 1; - _.dom.querySelector('#comment-count').innerHTML = _.stat.count + ' 条评论'; - var post = data.response; - post.isPost = true; - _.load(post); - _.timeAgo(); - } else if (data.code === 2) { - alertmsg.innerHTML = data.response; - _.dom.querySelector('.comment-item[data-id="preview"]').outerHTML = ''; - _.reEdit(item); - - if( data.response.indexOf('author') > -1){ - _.handle.logout(); - } - } else { - alertmsg.innerHTML = '提交失败,请稍后重试,错误代码:' + data.code; - alertClear(); - - _.dom.querySelector('.comment-item[data-id="preview"]').outerHTML = ''; - _.reEdit(item); - } - - }, function(){ - alertmsg.innerHTML = '提交出错,请稍后重试。'; - alertClear(); - - _.dom.querySelector('.comment-item[data-id="preview"]').outerHTML = ''; - _.reEdit(item); - }) - } - } - - // 重新编辑 - iDisqus.prototype.reEdit = function(item){ - var _ = this; - - if( !!item.dataset.id ){ - item.querySelector('.comment-item-reply').click(); - } else { - item.querySelector('.comment-form-wrapper').classList.add('editing'); - } - - // 重新填充文本图片 - if(!!_.stat.message){ - item.querySelector('.comment-form-textarea').value = _.stat.message; - } - if(!!_.stat.mediaHtml){ - item.querySelector('.comment-form-wrapper').classList.add('expanded'); - item.querySelector('.comment-image-list').innerHTML = _.stat.mediaHtml; - _.addListener('comment-image-item', 'click', _.handle.remove); - } - } - - // 编辑 - iDisqus.prototype.edit = function(post){ - var _ = this; - var commentBox = _.box.replace('comment-box','comment-box comment-box-'+post.id).replace(/emoji-input/g,'emoji-input-'+post.id).replace(/upload-input/g,'upload-input-'+ post.id); - var $this = _.dom.querySelector('.comment-item[data-id="' + post.id + '"] .comment-item-body'); - $this.outerHTML = commentBox; - _.user.init(); - var item = _.dom.querySelector('.comment-box-' + post.id); - item.dataset.currentId = post.id; - _.addAllListeners(); - item.querySelector('.comment-form-textarea').focus(); - - // 取消编辑 - item.querySelector('.comment-actions-form').insertAdjacentHTML('afterbegin', '<a class="comment-form-cancel" href="javascript:;">取消</a>') - item.querySelector('.comment-form-cancel').addEventListener('click', function(){ - _.stat.editing = false; - _.load(post); - _.timeAgo(); - }, false); - - // 重新填充文本图片,连续回复、连续编辑会有 bug - if(!!_.stat.message){ - item.querySelector('.comment-form-textarea').value = _.stat.message; - } - if(!!_.stat.mediaHtml){ - item.querySelector('.comment-form-wrapper').classList.add('expanded'); - item.querySelector('.comment-image-list').innerHTML = _.stat.mediaHtml; - _.addListener('comment-image-item', 'click', _.handle.remove); - } - - } - - // 创建 Thread 表单 - iDisqus.prototype.create = function(){ - var _ = this; - if(_.opts.autoCreate){ - _.dom.querySelector('.loading-container').dataset.tip = '正在创建 Thread……'; - var postData = { - url: _.opts.link, - identifier: _.opts.identifier, - title: _.opts.title, - slug: _.opts.slug, - message: _.opts.desc - } - _.postThread(postData); - return; - } - _.dom.querySelector('#idisqus').classList.remove('loading'); - _.dom.querySelector('#idisqus').innerHTML = '<div class="comment-header"><span class="comment-header-item">创建 Thread<\/span><\/div>'+ - '<div class="comment-thread-form">'+ - '<p>由于 Disqus 没有本页面的相关 Thread,故需先创建 Thread<\/p>'+ - '<div class="comment-form-item"><label class="comment-form-label">url:<\/label><input class="comment-form-input" id="thread-url" name="url" value="' + _.opts.link + '" disabled \/><\/div>'+ - '<div class="comment-form-item"><label class="comment-form-label">identifier:<\/label><input class="comment-form-input" id="thread-identifier" name="identifier" value="'+_.opts.identifier+'" disabled \/><\/div>'+ - '<div class="comment-form-item"><label class="comment-form-label">title:<\/label><input class="comment-form-input" id="thread-title" name="title" value="'+_.opts.title+'" disabled \/><\/div>'+ - '<div class="comment-form-item"><label class="comment-form-label">slug:<\/label><input class="comment-form-input" id="thread-slug" name="slug" value="' + _.opts.slug + '" \/><\/div>'+ - '<div class="comment-form-item"><label class="comment-form-label">message:<\/label><textarea class="comment-form-textarea" id="thread-message" name="message">'+_.opts.desc+'<\/textarea><\/div>'+ - '<button id="thread-submit" class="comment-form-submit">提交<\/button><\/div>'; - _.dom.querySelector('#thread-submit').addEventListener('click', _.handle.postThread, false); - } - - // 创建 Thread 事件 - iDisqus.prototype.postThread = function(){ - var _ = this; - if( !!arguments[0].target ){ - var postData = { - url: _.dom.querySelector('#thread-url').value, - identifier: _.dom.querySelector('#thread-identifier').value, - title: _.dom.querySelector('#thread-title').value, - slug: _.dom.querySelector('#thread-slug').value.replace(/[^A-Za-z0-9_-]+/g,''), - message: _.dom.querySelector('#thread-message').value - } - } else { - var postData = arguments[0]; - } - postAjax( _.opts.api + '/createthread.php', postData, function(resp){ - var data = JSON.parse(resp); - if( data.code === 0 ) { - alert('创建 Thread 成功,刷新后便可愉快地评论了!'); - setTimeout(function(){location.reload();},2000); - } else if( data.code === 2 ) { - if (data.response.indexOf('A thread already exists with link') > -1) { - alert(data.response.replace('A thread already exists with link,', '已存在此链接的相关 Thread,')); - return; - } - if (data.response.indexOf('Invalid URL') > -1) { - alert('参数错误,无效的\'URL\''); - return; - } - if (data.response.indexOf('Invalid slug') > -1) { - alert('参数错误,无效的\'slug\''); - return; - } - alert(data.response); - return; - } else { - alert(data.response); - return; - } - }, function(){ - alert('创建 Thread 出错,请稍后重试!'); - }) - } - - // 销毁评论框 - iDisqus.prototype.destroy = function(){ - var _ = this; - _.removeListener('exit', 'click', _.handle.logout); - _.removeListener('comment-form-textarea', 'blur', _.handle.focus); - _.removeListener('comment-form-textarea', 'focus', _.handle.focus); - _.removeListener('comment-form-textarea', 'keyup', _.handle.mention); - _.removeListener('comment-form-email', 'blur', _.handle.verify); - _.removeListener('comment-form-submit', 'click', _.handle.post); - _.removeListener('comment-image-input', 'change', _.handle.upload); - _.removeListener('comment-item-reply', 'click', _.handle.show); - _.removeListener('comment-loadmore', 'click', _.handle.loadMore); - _.removeListener('emojione-item', 'click', _.handle.field); - _.dom.innerHTML = ''; - delete _.box; - delete _.dom; - delete _.emojiList; - delete _.user; - delete _.handle; - delete _.opts; - delete _.stat; - } - - /* CommonJS */ - if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports) - module.exports = iDisqus; - /* AMD */ - else if (typeof define === 'function' && define['amd']) - define(function () { - return iDisqus; - }); - /* Global */ - else - global['iDisqus'] = global['iDisqus'] || iDisqus; - -})(window || this); +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["iDisqus"] = factory(); + else + root["iDisqus"] = factory(); +})(window, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/iDisqus.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js!./src/iDisqus.scss": +/*!***************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/src??ref--4-2!./node_modules/sass-loader/dist/cjs.js!./src/iDisqus.scss ***! + \***************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("exports = module.exports = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\")(false);\n// Module\nexports.push([module.i, \".comment{position:relative;font:13.5px/1.6 \\\"Helvetica Neue\\\", Helvetica, Arial, \\\"微软雅黑\\\", \\\"Microsoft YaHei\\\", sans-serif;color:#2a2e2e;margin:5px auto;word-wrap:break-word;padding:0;box-sizing:border-box}.comment#disqus_thread{display:none}.comment input,.comment textarea,.comment select,.comment button{font:13.5px/1.6 \\\"Helvetica Neue\\\", Helvetica, Arial, \\\"微软雅黑\\\", \\\"Microsoft YaHei\\\", sans-serif}.comment a{text-decoration:none}.comment .icon{max-width:20px}.comment *{margin:0;padding:0;box-sizing:border-box}.comment strong,.comment b{font-weight:bold;color:#000}.comment :focus{outline:none}.comment abbr[title]{text-decoration:none}.comment .hide{display:none}.comment .init-bg{display:none}.comment.init{display:block}.comment.init>*{display:none}.comment.init .init-container{margin:20px auto 20px;color:#9d9ea1;text-align:center;display:block;position:relative;height:100px;line-height:40px;width:250px}.comment.init .init-container .init-bg{display:block;transform:rotate(-135deg);margin:0 auto}.comment.init .init-container:before,.comment.init .init-container:after{display:block;position:absolute}.comment.init .init-container:before{content:attr(data-tips);top:64px;left:0;width:100%;height:30px;line-height:30px}.comment.init .init-container:after{content:\\\"\\\";box-sizing:border-box;width:26px;height:26px;top:20px;left:115px;border-width:3px;border-style:solid;border-color:#9d9ea1 transparent;border-radius:13px;transform-origin:50% 50% 0;-webkit-animation:disqus-loader-spinner-animation .7s infinite linear;animation:disqus-loader-spinner-animation .7s infinite linear}.comment.loading .comment-order{pointer-events:none}.comment-box{display:flex;margin:0 0 20px}.comment-navbar{display:flex;justify-content:space-between;align-items:center;height:48px}.comment-navbar .comment-navbar-item{display:flex}.comment-navbar .comment-recommend{display:flex;align-items:center;line-height:27px;height:27px;border:1px solid #656c7a;padding:0 5px;border-radius:3px;color:#656c7a;font-size:12px}.comment-navbar .comment-recommend .icon{fill:#656c7a;width:16px;height:16px}.comment-navbar .comment-recommend.voted .icon{fill:#f05f70}.comment-navbar .comment-recommend-text{margin:0 5px}.comment-navbar .comment-order-label{display:block;height:20px;line-height:20px;margin-right:10px;font-size:12px;border-radius:2px;padding:0 5px;background-color:#e7e9ee;cursor:pointer}.comment-navbar .comment-order-label:last-child{margin-right:0}.comment-navbar .comment-order-radio{display:none}.comment-navbar .comment-order-radio:checked+.comment-order-label{color:#fff;background-color:#c2c6cc}.comment-header{display:flex;justify-content:space-between;border-bottom:2px solid #e7e9ee}.comment-header .comment-header-item{height:36px;line-height:36px;font-weight:bold;font-size:15px;color:#656c7a;display:inline-block;border-bottom:2px solid #656c7a;margin-bottom:-2px;margin-right:10px;padding:0 5px}.comment-header .comment-header-item:last-child{margin-right:0;border-bottom-color:transparent}.comment-header .comment-header-item:last-child:hover{color:#2a2a2a}.comment-header #comment-user{display:none}.comment-header #comment-user:checked+.comment-user{color:#2a2a2a}.comment-header #comment-user:checked+.comment-user:after{border-top-color:#2a2a2a}.comment-header #comment-user:checked+.comment-user .comment-logout{display:block}.comment-header .comment-login{cursor:pointer}.comment-header .comment-user{cursor:pointer;position:relative;padding-right:15px}.comment-header .comment-user:after{content:\\\"\\\";display:block;position:absolute;height:0;width:0;border:5px solid transparent;border-top-color:#656c7a;top:50%;right:0;margin-top:0}.comment-header .comment-user:hover:after{border-top-color:#2a2a2a}.comment-header .comment-logout{cursor:pointer;z-index:1;display:none;position:absolute;border-radius:3px;border:2px solid #c2c6cc;width:80px;background-color:#fff;height:32px;line-height:28px;text-align:center;right:0;top:80%;color:#656c7a;font-size:13px}.comment-header .comment-logout:hover{color:#0095dd}.comment-header .comment-show{width:120px;text-align:center;position:relative;transition:all 0.2s ease-in-out;color:#2a2e2e;text-transform:capitalize;cursor:pointer;display:none}.comment-header .comment-header-count{width:120px;text-align:center;transition:all 0.2s ease-in-out;text-transform:capitalize;display:inline-block}.comment-header .comment-header-count:after{content:\\\" \\\";display:block;height:2px;position:absolute;bottom:-2px;left:0px;right:0px;background:#2e9fff}.comment-form{display:flex;flex-direction:column;width:calc(100% - 60px)}.comment-item-child .comment-form{width:calc(100% - 42px)}.placeholder{color:#7f919e;line-height:30px;font-size:12px;position:absolute;top:7px;left:10px;right:9px;white-space:nowrap;text-overflow:ellipsis;cursor:text;overflow:hidden}.comment-form-wrapper{display:flex;flex-direction:column;border:2px solid #dbdfe4;border-radius:4px;width:100%}.comment-actions{background:#f6f8f9;border-radius:0 0 2px 2px;display:flex;justify-content:space-between;height:0;transition:opacity linear .2s;opacity:0;filter:alpha(opacity=0);visibility:hidden}.comment-actions .comment-actions-group{display:flex;position:relative}.comment-actions .comment-actions-input{display:none}.comment-actions .comment-actions-input[type=\\\"checkbox\\\"]:checked+.comment-actions-label .icon{fill:#1d2f3a}.comment-actions .comment-actions-label{display:inline-block;width:34px;height:34px;cursor:pointer}.comment-actions .comment-actions-label .icon{height:18px;margin:8px;display:inline-block;color:#737474;cursor:pointer;fill:#c2c6cc;transition:all .2s}.comment-actions .comment-actions-label:hover .icon{fill:#1d2f3a !important}.comment-actions .emojione-list{cursor:default;position:absolute;opacity:0;filter:alpha(opacity=0);visibility:hidden;list-style:none;width:125px;background-color:#fff;padding:5px 0 0 5px;border-radius:2px;border:2px solid #c2c6cc;bottom:100%;left:-2px;margin-left:0;display:flex;flex-wrap:wrap}.comment-actions .emojione-item{position:relative;height:24px;width:24px;margin:0 5px 5px 0}.comment-actions .emojione-item:before{content:\\\"\\\";display:inline-block;position:absolute;left:0;top:0;bottom:0;right:0;z-index:4}.comment-actions .emojione-item-image{height:24px;width:24px}.comment-actions .comment-actions-input[type=\\\"checkbox\\\"]:checked+.emojione:before{position:fixed;top:0;left:0;width:100%;height:100%;content:\\\"\\\";display:block;cursor:default}.comment-actions .comment-actions-input[type=\\\"checkbox\\\"]:checked+.emojione .emojione-list{opacity:1;filter:alpha(opacity=100);visibility:visible !important}.expanded .comment-image{display:flex;overflow-x:auto}.expanded .comment-image .comment-image-progress{position:relative;height:80px;width:0;background:url(\\\"https://a.disquscdn.com/next/embed/assets/img/loader.5cc23909da9c4a9874500d7a85c4125f.gif\\\") center no-repeat;margin:0 5px;overflow:hidden}.expanded .comment-image .comment-image-progress:before{position:absolute;content:\\\"\\\";display:block;top:55px;bottom:20px;left:0;right:0;height:5px;width:100%;background-color:#dbdfe4}.expanded .comment-image .comment-image-progress .comment-image-loaded{position:absolute;background-color:#7f919e;top:55px;left:0;right:0;bottom:20px;height:5px;width:0}.expanded .comment-image .comment-image-list{list-style:none;display:flex}.expanded .comment-image .comment-image-item{height:80px;margin-left:5px;position:relative;border-radius:3px;overflow:hidden;flex:none}.expanded .comment-image .comment-image-item .comment-image-object{display:block;height:100%;border-radius:3px;overflow:hidden}.expanded .comment-image .comment-image-item.loading .comment-image-object{width:20px;margin:0 30px}.comment-form-wrapper.editing+.comment-form-user{opacity:1;height:auto;margin-top:10px}.comment-form-wrapper.editing .comment-form-textarea{height:74px;font-size:13.5px;line-height:16px}.comment-form-wrapper.editing .comment-image{transition:padding-bottom .15s ease-in-out;background-color:rgba(16,48,68,0.03)}.comment-form-wrapper.editing .comment-actions{transition:all 0.2s ease-in-out;border-top:solid 2px #dbdfe4;opacity:1;height:36px;filter:alpha(opacity=100);visibility:visible !important}.comment-form-wrapper.editing .comment-actions-form{transition:all .3s .5s;margin:87px -2px -2px}.comment-form-wrapper.editing .comment-form-submit{opacity:1}.comment-form-wrapper.focus{border:2px solid #c2c6cc}.comment-form-wrapper.focus .comment-actions{border-top:2px solid #c2c6cc}.comment-form-wrapper.focus .comment-actions-label .icon{fill:#656c7a}.comment-form-wrapper.focus.expanded .comment-image{border-top:2px solid #c2c6cc}.comment-form-wrapper.preview{border:2px solid #c2c6cc}.comment-form-wrapper.preview .comment-actions{border-top:2px solid #c2c6cc}.comment-form-wrapper.preview .comment-actions-label{pointer-events:none}.comment-form-wrapper.preview .comment-actions-label[for^=\\\"preview-input\\\"]{pointer-events:auto}.comment-form-wrapper.preview .comment-actions-label[for^=\\\"preview-input\\\"] .icon{fill:#656c7a}.comment-form-wrapper.expanded .comment-image{border-top:2px solid #dbdfe4;padding:10px 0 8px}.comment-form-wrapper.logged-in .comment-form-submit{border-radius:0 0 4px;transition:none;opacity:1}.comment-form-wrapper.logged-in .comment-actions-form{margin:0;transition:all .5s}.comment-form-wrapper.logged-in+.comment-form-user{height:0;opacity:0;margin-top:-40px}.comment-form-wrapper.logged-in .exit{display:block}.comment-form-wrapper .comment-form-preview{border-radius:4px;display:none;min-height:74px;padding:7px;white-space:pre-wrap}.comment-form-wrapper .comment-form-textarea{width:100%;display:block;border:none;font-size:18px;line-height:30px;border-radius:4px;color:#2a2e2e;cursor:text;resize:none;height:44px;padding:7px;transition:all .2s ease-in-out;background-color:#fefefe}.comment-form-wrapper .comment-form-textarea::-webkit-input-placeholder{color:#7f919e}.comment-form-wrapper .comment-form-textarea::-moz-placeholder{color:#7f919e}.comment-form-wrapper .comment-form-alert:not(:empty){background-color:#f05f70;padding:10px;line-height:20px;font-size:13px;font-weight:700;color:#fff;margin:0 -2px;border-top:2px solid #dbdfe4}.comment-actions-form{display:flex}.comment-actions-form .comment-form-cancel{line-height:36px;padding:0 15px;font-size:12px}.comment-actions-form .comment-form-submit{z-index:1;border:none;opacity:0;margin:-2px;white-space:nowrap;border-radius:4px;height:38px;width:80px;display:inline-block;background-color:rgba(29,47,58,0.6);cursor:pointer;line-height:38px}.comment-actions-form .comment-form-submit .icon{margin:9px;fill:#fff;cursor:pointer;width:20px;height:20px}.comment-actions-form .comment-form-submit:hover{background-color:rgba(29,47,58,0.75)}.comment-form-user{display:flex;opacity:0;transition:all .5s .2s;height:0;margin:-40px -5px 40px;overflow:hidden;line-height:32px}.comment-form-user .comment-form-guest{display:flex;flex-wrap:wrap;flex:1}.comment-form-user .comment-form-auth{height:32px}.comment-form-user .comment-form-login{background-color:transparent;border:none;height:32px;width:32px;margin:0 0 0 5px;cursor:pointer}.comment-thread-form{text-align:center;color:#656c7a;line-height:32px}.comment-thread-form .comment-form-submit{background-color:rgba(29,47,58,0.6);border:none;white-space:nowrap;border-radius:4px;height:38px;width:120px;display:inline-block;cursor:pointer;line-height:38px;margin:10px 0;color:#fff;font-size:15px}.comment-thread-form .comment-form-submit:hover{background-color:rgba(29,47,58,0.75)}.comment-form-item{display:flex;margin:10px 0}.comment-form-item .comment-form-label{display:block;height:32px;line-height:32px;color:#656c7a;width:100px;text-align:right;font-weight:bold}.comment-form-item .comment-form-textarea{background-color:#fff;border:2px solid #dbdfe4;transition:all .2s linear;padding:2px 10px;border-radius:4px;height:64px;margin:0 5px;width:30px;line-height:20px;flex:auto}.comment-form-item .comment-form-textarea:focus{border:2px solid #c2c6cc}.comment-form-input{background-color:#fff;border:2px solid #dbdfe4;transition:all .2s linear;padding:0 7px;border-radius:4px;height:32px;margin:0 5px;width:30px;line-height:32px;flex:auto}.comment-form-input::-webkit-input-placeholder{color:#7f919e}.comment-form-input::-moz-placeholder{color:#7f919e}.comment-form-input:focus{border:2px solid #c2c6cc}.comment-form-input[disabled]{color:#656c7a}.comment-list:empty:after{content:attr(data-tips);display:block;opacity:.6;line-height:80px;text-align:center}.comment-list p{margin:0}.comment-list a{text-decoration:none;color:#288ce4}.comment-list a[href=\\\"javascript:void(0);\\\"]{color:#000;cursor:default}.comment-list code{line-height:20px;font-size:12px;font-family:monaco,menlo,monospace;padding:0 .3em;display:inline-block;vertical-align:top;margin:2px}.comment-list pre{overflow-x:auto;margin:0 0 15px;border-left:4px solid #7f919e;padding:0 0 0 12px}.comment-list pre code{display:block;overflow-y:hidden;white-space:pre;line-height:1.1}.comment-list #comment-preview{opacity:.6}.comment-list .comment-item{padding-top:6px}.comment-list .comment-item-body{display:flex;margin-bottom:5px}.comment-list .comment-item-header,.comment-list .comment-item-footer{line-height:1.2;color:#c2c6cc}.comment-list .comment-item-header .comment-item-bullet,.comment-list .comment-item-footer .comment-item-bullet{padding:0 2px}.comment-list .comment-item-header{font-size:13px}.comment-list .comment-item-header .comment-item-pname{color:#656c7a;position:relative}.comment-list .comment-item-header .comment-item-pname .icon{width:12px;height:12px;margin:1px 2px;vertical-align:top;fill:#656c7a}.comment-list .comment-item-header .comment-item-pname:hover{color:#2a2e2e}.comment-list .comment-item-header .comment-item-pname:hover .icon{fill:#656c7a}.comment-list .comment-item-header .comment-item-pname:hover .comment-item-parent{display:flex}.comment-list .comment-item-header .comment-item-parent{display:none;position:absolute;border-radius:3px;border:2px solid #dbdfe4;padding:5px;width:250px;background-color:#fff;align-items:center;height:48px;top:50%;margin-top:-24px;left:15px;line-height:18px;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1)}.comment-list .comment-item-header .comment-item-parent .comment-item-pmain{width:calc(100% - 42px)}.comment-list .comment-item-header .comment-item-parent .comment-item-pheader{color:#656c7a}.comment-list .comment-item-header .comment-item-parent .comment-item-pcontent{font-size:12px;padding:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.comment-list .comment-item-header .comment-item-badge{color:#fff;background:#7f919e;padding:1px 3px;margin:0 2px;font-size:10px;line-height:1.1;font-weight:700;border-radius:3px;display:inline-block}.comment-list .comment-item-header .comment-item-time{font-size:12px;color:#7f919e;word-spacing:-2px;font-weight:400}.comment-list .comment-item-header .comment-item-name{color:#0095dd;font-weight:700}.comment-list .comment-item-header .comment-item-name[href^=\\\"javascript\\\"]{cursor:text;color:#000}.comment-list .comment-item-footer{font-size:12px;padding:5px 0}.comment-list .comment-item-footer .comment-item-reply,.comment-list .comment-item-footer .comment-item-edit,.comment-list .comment-item-footer .comment-item-delete{color:#656c7a;font-weight:500}.comment-list .comment-item-footer .comment-item-reply:hover,.comment-list .comment-item-footer .comment-item-edit:hover,.comment-list .comment-item-footer .comment-item-delete:hover{color:#2a2e2e}.comment-list .comment-item-footer .comment-item-cancel{color:#0095dd;font-weight:700}.comment-list .comment-item-image a{display:inline-block}.comment-list .comment-item-image img{display:block;border-radius:3px;max-width:100%;max-height:480px}.comment-list iframe{width:100%}.comment-list .comment-item.transparent{opacity:.4}.comment-list .comment-item-content{padding-top:5px;letter-spacing:.5px}.comment-list .comment-item-content spoiler{display:inline;background-color:#687a86;color:transparent;white-space:pre-wrap}.comment-list .comment-item-content spoiler:hover{color:#2e2e2e;background-color:transparent}.comment-list .comment-item-content p{margin-bottom:5px}.comment-list .comment-item-content p:last-child{margin-bottom:0}.comment-list .comment-item-content a[data-dsq-mention]:before{content:\\\"@\\\"}.comment-list .comment-item-content .comment-item-content{min-height:20px}.comment-list .comment-item-content img.emojione{vertical-align:top;width:24px;height:24px;margin:0 3px}.comment-list .comment-item-children .comment-item-avatar,.comment-list .comment-item-children .comment-item-avatar img,.comment-list .comment-item-children .comment-box .comment-avatar,.comment-list .comment-item-children .comment-box .comment-avatar-image,.comment-list .comment-item-body+.comment-box .comment-avatar,.comment-list .comment-item-body+.comment-box .comment-avatar-image{width:36px;height:36px;margin-right:6px;box-shadow:0 0.5px 0.5px 0 rgba(0,0,0,0.05)}.comment-list .comment-form-textarea{height:32px;padding:5px;line-height:22px;font-size:15px}.comment-list .comment-item-main{width:calc(100% - 60px)}.comment-list .comment-item-main:empty{line-height:48px}.comment-list .comment-item-main:empty:after{content:attr(data-message);line-height:36px;color:#7f919e}.comment-list .comment-box{margin:0}.comment-list .comment-box+.comment-item-body{display:none}.comment-list .comment-item-body+.comment-box{padding-left:60px;padding-top:6px;margin-bottom:20px}.comment-list .comment-item-children{padding-left:60px}.comment-list .comment-item-children .comment-item-main{width:calc(100% - 42px)}.comment-list .comment-item-children .comment-item-main:empty{line-height:36px}.comment-list .comment-item-children .comment-item-children,.comment-list .comment-item-children .comment-item-body+.comment-box{padding-left:42px}.comment-list .comment-item-children .comment-item-children .comment-item-children .comment-item-children,.comment-list .comment-item-children .comment-item-children .comment-item-children .comment-box,.comment-list .comment-item-children .comment-item-body+.comment-box .comment-item-children .comment-item-children,.comment-list .comment-item-children .comment-item-body+.comment-box .comment-item-children .comment-box{padding-left:0}.comment-list .comment-item-loadmore{font-size:13px;text-decoration:underline;display:block;margin:10px 0}.comment-loadmore{font-weight:500;display:block;text-align:center;padding:11px 14px;background-color:rgba(29,47,58,0.6);color:#fff !important;line-height:1.1;border-radius:3px;transition:background .2s;text-shadow:none}.comment-loadmore:hover{background-color:rgba(29,47,58,0.7)}.comment-loadmore.loading{background-color:#edeff2;color:#444 !important;cursor:wait}.comment-form-error{position:absolute;background-color:#fff;padding:10px;line-height:20px;border-radius:3px;box-shadow:0 0 5px 1px rgba(0,0,0,0.3);margin-top:40px;margin-left:2px;z-index:10}.comment-form-error:before{content:\\\"\\\";display:block;position:absolute;width:10px;height:10px;transform:rotate(45deg);background-color:#fff;box-shadow:0 0 5px 1px rgba(0,0,0,0.3);top:-4px;left:15px}.comment-form-error:after{content:\\\"\\\";display:block;position:absolute;width:20px;height:12px;top:0;left:10px;background-color:#fff}.comment-list,.comment-item-children{text-align:left;list-style:none;margin-left:0;line-height:20px}.comment-avatar,.comment-item-avatar{display:block;width:48px;height:48px;margin-right:12px}.comment-avatar img,.comment-item-avatar img{border-radius:3px;width:48px;height:48px}.mention-user{background-color:#fff;border-radius:2px;box-shadow:1px 1px 2px 1px rgba(29,47,58,0.2);position:absolute;overflow:hidden}.mention-user .mention-user-list{list-style:none}.mention-user .mention-user-item{height:30px;padding:3px;line-height:24px;font-size:12px;display:flex;cursor:default}.mention-user .mention-user-item.active{background-color:#2e9fff;color:#fff}.mention-user .mention-user-item.active .mention-user-name{color:#fff}.mention-user .mention-user-avatar{width:24px;height:24px;border-radius:3px;display:block}.mention-user .mention-user-username{font-weight:600;padding-left:4px}.mention-user .mention-user-name{color:#656c7a;padding-left:4px}.comment-related{color:#444;margin-top:20px;width:100%}.comment-related .comment-related-title{font-weight:700;text-transform:uppercase;color:rgba(34,59,74,0.5);margin-bottom:5px;white-space:nowrap;text-overflow:ellipsis}.comment-related .comment-related-forumname{color:#413a3a}.comment-related .related-list{display:flex;flex-wrap:wrap;list-style:none}.comment-related .related-list .related-item{width:48%;margin-bottom:10px}.comment-related .related-list .related-item:nth-child(odd){margin-right:4%}.comment-related .related-list .related-item-link{color:#000}.comment-related .related-list .related-item-link:hover .related-item-avatar{opacity:.8}.comment-related .related-list .related-item-link:hover .related-item-name{color:#aaa}.comment-related .related-list .related-item-title{display:block;overflow:hidden;font-weight:700}.comment-related .related-list .related-item-desc{color:rgba(30,55,70,0.4);font-weight:500;font-size:12px}.comment-related .related-list .related-item-post{padding:5px 0;display:flex}.comment-related .related-list .related-item-avatar{width:30px;height:30px;margin-right:5px;flex:none}.comment-related .related-list .related-item-avatar img{display:block;width:100%;border-radius:3px}.comment-related .related-list .related-item-main{flex:1;height:30px;line-height:15px;overflow:hidden;font-size:13px}.comment-related .related-list .related-item-name{color:rgba(30,55,70,0.4);font-weight:600}.comment-related .related-list .related-item-message{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.comment-reaction{display:flex;flex-direction:column}.comment-reaction .comment-reaction-header{text-align:center;line-height:25px}.comment-reaction .comment-reaction-list{display:flex;justify-content:center;list-style-type:none;flex-wrap:wrap;align-items:center}.comment-reaction .comment-reaction-list:not(:empty){padding:10px 0}.comment-reaction .comment-reaction-list .comment-reaction-item{display:flex;flex-direction:column;justify-content:center;align-items:center;font-size:12px;color:#656c7a;margin-right:10px}.comment-reaction .comment-reaction-list .comment-reaction-item:last-child{margin-right:0}.comment-reaction .comment-reaction-list .comment-reaction-btn{display:flex;align-items:center;padding:0 5px;border:1px solid #c2c6cc;border-radius:3px;height:30px;line-height:30px;max-width:100px;color:#656c7a}.comment-reaction .comment-reaction-list .comment-reaction-btn.selected{border-color:#656c7a}.comment-reaction .comment-reaction-list .comment-reaction-count{padding:5px 0}.comment-reaction .comment-reaction-list .comment-reaction-text{margin-left:5px}.comment-reaction .comment-reaction-list img{width:20px;height:20px}@-webkit-keyframes disqus-loader-spinner-animation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes disqus-loader-spinner-animation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width: 450px){.comment-reaction-text{display:none}.comment-form-wrapper.editing .comment-actions-form{margin:180px 0 0}.comment-form-wrapper.logged-in .comment-actions-form{margin:0}.comment-item .at{display:none}.comment-item .comment-avatar{display:none}.comment-item .comment-form{width:100%}.comment-item .comment-item-children .comment-item-children,.comment-item .comment-item-children .comment-box{padding-left:0 !important}.comment-item .comment-item-children .comment-item-avatar{display:none}.comment-item .comment-item-children .comment-item-main,.comment-item .comment-item-children .comment-form{width:100%}.comment-form-user{line-height:42px}.comment-form-user .comment-form-auth{margin:5px}.comment-form-user .comment-form-input{margin:5px;width:100%}.comment-related .related-list .related-item{width:100%;padding-left:10px}}\\n\", \"\"]);\n\n\n\n//# sourceURL=webpack://%5Bname%5D/./src/iDisqus.scss?./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/src??ref--4-2!./node_modules/sass-loader/dist/cjs.js"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/api.js": +/*!*****************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/api.js ***! + \*****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function (useSourceMap) {\n var list = []; // return the list of modules as css string\n\n list.toString = function toString() {\n return this.map(function (item) {\n var content = cssWithMappingToString(item, useSourceMap);\n\n if (item[2]) {\n return '@media ' + item[2] + '{' + content + '}';\n } else {\n return content;\n }\n }).join('');\n }; // import a list of modules into the list\n\n\n list.i = function (modules, mediaQuery) {\n if (typeof modules === 'string') {\n modules = [[null, modules, '']];\n }\n\n var alreadyImportedModules = {};\n\n for (var i = 0; i < this.length; i++) {\n var id = this[i][0];\n\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n\n for (i = 0; i < modules.length; i++) {\n var item = modules[i]; // skip already imported module\n // this implementation is not 100% perfect for weird media query combinations\n // when a module is imported multiple times with different media queries.\n // I hope this will never occur (Hey this way we have smaller bundles)\n\n if (item[0] == null || !alreadyImportedModules[item[0]]) {\n if (mediaQuery && !item[2]) {\n item[2] = mediaQuery;\n } else if (mediaQuery) {\n item[2] = '(' + item[2] + ') and (' + mediaQuery + ')';\n }\n\n list.push(item);\n }\n }\n };\n\n return list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n var content = item[1] || '';\n var cssMapping = item[3];\n\n if (!cssMapping) {\n return content;\n }\n\n if (useSourceMap && typeof btoa === 'function') {\n var sourceMapping = toComment(cssMapping);\n var sourceURLs = cssMapping.sources.map(function (source) {\n return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */';\n });\n return [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n }\n\n return [content].join('\\n');\n} // Adapted from convert-source-map (MIT)\n\n\nfunction toComment(sourceMap) {\n // eslint-disable-next-line no-undef\n var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n return '/*# ' + data + ' */';\n}\n\n//# sourceURL=webpack://%5Bname%5D/./node_modules/css-loader/dist/runtime/api.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/lib/addStyles.js": +/*!****************************************************!*\ + !*** ./node_modules/style-loader/lib/addStyles.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n\nvar stylesInDom = {};\n\nvar\tmemoize = function (fn) {\n\tvar memo;\n\n\treturn function () {\n\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\treturn memo;\n\t};\n};\n\nvar isOldIE = memoize(function () {\n\t// Test for IE <= 9 as proposed by Browserhacks\n\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n\t// Tests for existence of standard globals is to allow style-loader\n\t// to operate correctly into non-standard environments\n\t// @see https://github.com/webpack-contrib/style-loader/issues/177\n\treturn window && document && document.all && !window.atob;\n});\n\nvar getTarget = function (target, parent) {\n if (parent){\n return parent.querySelector(target);\n }\n return document.querySelector(target);\n};\n\nvar getElement = (function (fn) {\n\tvar memo = {};\n\n\treturn function(target, parent) {\n // If passing function in options, then use it for resolve \"head\" element.\n // Useful for Shadow Root style i.e\n // {\n // insertInto: function () { return document.querySelector(\"#foo\").shadowRoot }\n // }\n if (typeof target === 'function') {\n return target();\n }\n if (typeof memo[target] === \"undefined\") {\n\t\t\tvar styleTarget = getTarget.call(this, target, parent);\n\t\t\t// Special case to return head of iframe instead of iframe itself\n\t\t\tif (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n\t\t\t\ttry {\n\t\t\t\t\t// This will throw an exception if access to iframe is blocked\n\t\t\t\t\t// due to cross-origin restrictions\n\t\t\t\t\tstyleTarget = styleTarget.contentDocument.head;\n\t\t\t\t} catch(e) {\n\t\t\t\t\tstyleTarget = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmemo[target] = styleTarget;\n\t\t}\n\t\treturn memo[target]\n\t};\n})();\n\nvar singleton = null;\nvar\tsingletonCounter = 0;\nvar\tstylesInsertedAtTop = [];\n\nvar\tfixUrls = __webpack_require__(/*! ./urls */ \"./node_modules/style-loader/lib/urls.js\");\n\nmodule.exports = function(list, options) {\n\tif (typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif (typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\n\toptions.attrs = typeof options.attrs === \"object\" ? options.attrs : {};\n\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n\t// tags it will allow on a page\n\tif (!options.singleton && typeof options.singleton !== \"boolean\") options.singleton = isOldIE();\n\n\t// By default, add <style> tags to the <head> element\n if (!options.insertInto) options.insertInto = \"head\";\n\n\t// By default, add <style> tags to the bottom of the target\n\tif (!options.insertAt) options.insertAt = \"bottom\";\n\n\tvar styles = listToStyles(list, options);\n\n\taddStylesToDom(styles, options);\n\n\treturn function update (newList) {\n\t\tvar mayRemove = [];\n\n\t\tfor (var i = 0; i < styles.length; i++) {\n\t\t\tvar item = styles[i];\n\t\t\tvar domStyle = stylesInDom[item.id];\n\n\t\t\tdomStyle.refs--;\n\t\t\tmayRemove.push(domStyle);\n\t\t}\n\n\t\tif(newList) {\n\t\t\tvar newStyles = listToStyles(newList, options);\n\t\t\taddStylesToDom(newStyles, options);\n\t\t}\n\n\t\tfor (var i = 0; i < mayRemove.length; i++) {\n\t\t\tvar domStyle = mayRemove[i];\n\n\t\t\tif(domStyle.refs === 0) {\n\t\t\t\tfor (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();\n\n\t\t\t\tdelete stylesInDom[domStyle.id];\n\t\t\t}\n\t\t}\n\t};\n};\n\nfunction addStylesToDom (styles, options) {\n\tfor (var i = 0; i < styles.length; i++) {\n\t\tvar item = styles[i];\n\t\tvar domStyle = stylesInDom[item.id];\n\n\t\tif(domStyle) {\n\t\t\tdomStyle.refs++;\n\n\t\t\tfor(var j = 0; j < domStyle.parts.length; j++) {\n\t\t\t\tdomStyle.parts[j](item.parts[j]);\n\t\t\t}\n\n\t\t\tfor(; j < item.parts.length; j++) {\n\t\t\t\tdomStyle.parts.push(addStyle(item.parts[j], options));\n\t\t\t}\n\t\t} else {\n\t\t\tvar parts = [];\n\n\t\t\tfor(var j = 0; j < item.parts.length; j++) {\n\t\t\t\tparts.push(addStyle(item.parts[j], options));\n\t\t\t}\n\n\t\t\tstylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};\n\t\t}\n\t}\n}\n\nfunction listToStyles (list, options) {\n\tvar styles = [];\n\tvar newStyles = {};\n\n\tfor (var i = 0; i < list.length; i++) {\n\t\tvar item = list[i];\n\t\tvar id = options.base ? item[0] + options.base : item[0];\n\t\tvar css = item[1];\n\t\tvar media = item[2];\n\t\tvar sourceMap = item[3];\n\t\tvar part = {css: css, media: media, sourceMap: sourceMap};\n\n\t\tif(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});\n\t\telse newStyles[id].parts.push(part);\n\t}\n\n\treturn styles;\n}\n\nfunction insertStyleElement (options, style) {\n\tvar target = getElement(options.insertInto)\n\n\tif (!target) {\n\t\tthrow new Error(\"Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.\");\n\t}\n\n\tvar lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];\n\n\tif (options.insertAt === \"top\") {\n\t\tif (!lastStyleElementInsertedAtTop) {\n\t\t\ttarget.insertBefore(style, target.firstChild);\n\t\t} else if (lastStyleElementInsertedAtTop.nextSibling) {\n\t\t\ttarget.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);\n\t\t} else {\n\t\t\ttarget.appendChild(style);\n\t\t}\n\t\tstylesInsertedAtTop.push(style);\n\t} else if (options.insertAt === \"bottom\") {\n\t\ttarget.appendChild(style);\n\t} else if (typeof options.insertAt === \"object\" && options.insertAt.before) {\n\t\tvar nextSibling = getElement(options.insertAt.before, target);\n\t\ttarget.insertBefore(style, nextSibling);\n\t} else {\n\t\tthrow new Error(\"[Style Loader]\\n\\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\\n Must be 'top', 'bottom', or Object.\\n (https://github.com/webpack-contrib/style-loader#insertat)\\n\");\n\t}\n}\n\nfunction removeStyleElement (style) {\n\tif (style.parentNode === null) return false;\n\tstyle.parentNode.removeChild(style);\n\n\tvar idx = stylesInsertedAtTop.indexOf(style);\n\tif(idx >= 0) {\n\t\tstylesInsertedAtTop.splice(idx, 1);\n\t}\n}\n\nfunction createStyleElement (options) {\n\tvar style = document.createElement(\"style\");\n\n\tif(options.attrs.type === undefined) {\n\t\toptions.attrs.type = \"text/css\";\n\t}\n\n\tif(options.attrs.nonce === undefined) {\n\t\tvar nonce = getNonce();\n\t\tif (nonce) {\n\t\t\toptions.attrs.nonce = nonce;\n\t\t}\n\t}\n\n\taddAttrs(style, options.attrs);\n\tinsertStyleElement(options, style);\n\n\treturn style;\n}\n\nfunction createLinkElement (options) {\n\tvar link = document.createElement(\"link\");\n\n\tif(options.attrs.type === undefined) {\n\t\toptions.attrs.type = \"text/css\";\n\t}\n\toptions.attrs.rel = \"stylesheet\";\n\n\taddAttrs(link, options.attrs);\n\tinsertStyleElement(options, link);\n\n\treturn link;\n}\n\nfunction addAttrs (el, attrs) {\n\tObject.keys(attrs).forEach(function (key) {\n\t\tel.setAttribute(key, attrs[key]);\n\t});\n}\n\nfunction getNonce() {\n\tif (false) {}\n\n\treturn __webpack_require__.nc;\n}\n\nfunction addStyle (obj, options) {\n\tvar style, update, remove, result;\n\n\t// If a transform function was defined, run it on the css\n\tif (options.transform && obj.css) {\n\t result = typeof options.transform === 'function'\n\t\t ? options.transform(obj.css) \n\t\t : options.transform.default(obj.css);\n\n\t if (result) {\n\t \t// If transform returns a value, use that instead of the original css.\n\t \t// This allows running runtime transformations on the css.\n\t \tobj.css = result;\n\t } else {\n\t \t// If the transform function returns a falsy value, don't add this css.\n\t \t// This allows conditional loading of css\n\t \treturn function() {\n\t \t\t// noop\n\t \t};\n\t }\n\t}\n\n\tif (options.singleton) {\n\t\tvar styleIndex = singletonCounter++;\n\n\t\tstyle = singleton || (singleton = createStyleElement(options));\n\n\t\tupdate = applyToSingletonTag.bind(null, style, styleIndex, false);\n\t\tremove = applyToSingletonTag.bind(null, style, styleIndex, true);\n\n\t} else if (\n\t\tobj.sourceMap &&\n\t\ttypeof URL === \"function\" &&\n\t\ttypeof URL.createObjectURL === \"function\" &&\n\t\ttypeof URL.revokeObjectURL === \"function\" &&\n\t\ttypeof Blob === \"function\" &&\n\t\ttypeof btoa === \"function\"\n\t) {\n\t\tstyle = createLinkElement(options);\n\t\tupdate = updateLink.bind(null, style, options);\n\t\tremove = function () {\n\t\t\tremoveStyleElement(style);\n\n\t\t\tif(style.href) URL.revokeObjectURL(style.href);\n\t\t};\n\t} else {\n\t\tstyle = createStyleElement(options);\n\t\tupdate = applyToTag.bind(null, style);\n\t\tremove = function () {\n\t\t\tremoveStyleElement(style);\n\t\t};\n\t}\n\n\tupdate(obj);\n\n\treturn function updateStyle (newObj) {\n\t\tif (newObj) {\n\t\t\tif (\n\t\t\t\tnewObj.css === obj.css &&\n\t\t\t\tnewObj.media === obj.media &&\n\t\t\t\tnewObj.sourceMap === obj.sourceMap\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tupdate(obj = newObj);\n\t\t} else {\n\t\t\tremove();\n\t\t}\n\t};\n}\n\nvar replaceText = (function () {\n\tvar textStore = [];\n\n\treturn function (index, replacement) {\n\t\ttextStore[index] = replacement;\n\n\t\treturn textStore.filter(Boolean).join('\\n');\n\t};\n})();\n\nfunction applyToSingletonTag (style, index, remove, obj) {\n\tvar css = remove ? \"\" : obj.css;\n\n\tif (style.styleSheet) {\n\t\tstyle.styleSheet.cssText = replaceText(index, css);\n\t} else {\n\t\tvar cssNode = document.createTextNode(css);\n\t\tvar childNodes = style.childNodes;\n\n\t\tif (childNodes[index]) style.removeChild(childNodes[index]);\n\n\t\tif (childNodes.length) {\n\t\t\tstyle.insertBefore(cssNode, childNodes[index]);\n\t\t} else {\n\t\t\tstyle.appendChild(cssNode);\n\t\t}\n\t}\n}\n\nfunction applyToTag (style, obj) {\n\tvar css = obj.css;\n\tvar media = obj.media;\n\n\tif(media) {\n\t\tstyle.setAttribute(\"media\", media)\n\t}\n\n\tif(style.styleSheet) {\n\t\tstyle.styleSheet.cssText = css;\n\t} else {\n\t\twhile(style.firstChild) {\n\t\t\tstyle.removeChild(style.firstChild);\n\t\t}\n\n\t\tstyle.appendChild(document.createTextNode(css));\n\t}\n}\n\nfunction updateLink (link, options, obj) {\n\tvar css = obj.css;\n\tvar sourceMap = obj.sourceMap;\n\n\t/*\n\t\tIf convertToAbsoluteUrls isn't defined, but sourcemaps are enabled\n\t\tand there is no publicPath defined then lets turn convertToAbsoluteUrls\n\t\ton by default. Otherwise default to the convertToAbsoluteUrls option\n\t\tdirectly\n\t*/\n\tvar autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;\n\n\tif (options.convertToAbsoluteUrls || autoFixUrls) {\n\t\tcss = fixUrls(css);\n\t}\n\n\tif (sourceMap) {\n\t\t// http://stackoverflow.com/a/26603875\n\t\tcss += \"\\n/*# sourceMappingURL=data:application/json;base64,\" + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + \" */\";\n\t}\n\n\tvar blob = new Blob([css], { type: \"text/css\" });\n\n\tvar oldSrc = link.href;\n\n\tlink.href = URL.createObjectURL(blob);\n\n\tif(oldSrc) URL.revokeObjectURL(oldSrc);\n}\n\n\n//# sourceURL=webpack://%5Bname%5D/./node_modules/style-loader/lib/addStyles.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/lib/urls.js": +/*!***********************************************!*\ + !*** ./node_modules/style-loader/lib/urls.js ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("\n/**\n * When source maps are enabled, `style-loader` uses a link element with a data-uri to\n * embed the css on the page. This breaks all relative urls because now they are relative to a\n * bundle instead of the current page.\n *\n * One solution is to only use full urls, but that may be impossible.\n *\n * Instead, this function \"fixes\" the relative urls to be absolute according to the current page location.\n *\n * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.\n *\n */\n\nmodule.exports = function (css) {\n // get current location\n var location = typeof window !== \"undefined\" && window.location;\n\n if (!location) {\n throw new Error(\"fixUrls requires window.location\");\n }\n\n\t// blank or null?\n\tif (!css || typeof css !== \"string\") {\n\t return css;\n }\n\n var baseUrl = location.protocol + \"//\" + location.host;\n var currentDir = baseUrl + location.pathname.replace(/\\/[^\\/]*$/, \"/\");\n\n\t// convert each url(...)\n\t/*\n\tThis regular expression is just a way to recursively match brackets within\n\ta string.\n\n\t /url\\s*\\( = Match on the word \"url\" with any whitespace after it and then a parens\n\t ( = Start a capturing group\n\t (?: = Start a non-capturing group\n\t [^)(] = Match anything that isn't a parentheses\n\t | = OR\n\t \\( = Match a start parentheses\n\t (?: = Start another non-capturing groups\n\t [^)(]+ = Match anything that isn't a parentheses\n\t | = OR\n\t \\( = Match a start parentheses\n\t [^)(]* = Match anything that isn't a parentheses\n\t \\) = Match a end parentheses\n\t ) = End Group\n *\\) = Match anything and then a close parens\n ) = Close non-capturing group\n * = Match anything\n ) = Close capturing group\n\t \\) = Match a close parens\n\n\t /gi = Get all matches, not the first. Be case insensitive.\n\t */\n\tvar fixedCss = css.replace(/url\\s*\\(((?:[^)(]|\\((?:[^)(]+|\\([^)(]*\\))*\\))*)\\)/gi, function(fullMatch, origUrl) {\n\t\t// strip quotes (if they exist)\n\t\tvar unquotedOrigUrl = origUrl\n\t\t\t.trim()\n\t\t\t.replace(/^\"(.*)\"$/, function(o, $1){ return $1; })\n\t\t\t.replace(/^'(.*)'$/, function(o, $1){ return $1; });\n\n\t\t// already a full url? no change\n\t\tif (/^(#|data:|http:\\/\\/|https:\\/\\/|file:\\/\\/\\/|\\s*$)/i.test(unquotedOrigUrl)) {\n\t\t return fullMatch;\n\t\t}\n\n\t\t// convert the url to a full url\n\t\tvar newUrl;\n\n\t\tif (unquotedOrigUrl.indexOf(\"//\") === 0) {\n\t\t \t//TODO: should we add protocol?\n\t\t\tnewUrl = unquotedOrigUrl;\n\t\t} else if (unquotedOrigUrl.indexOf(\"/\") === 0) {\n\t\t\t// path should be relative to the base url\n\t\t\tnewUrl = baseUrl + unquotedOrigUrl; // already starts with '/'\n\t\t} else {\n\t\t\t// path should be relative to current directory\n\t\t\tnewUrl = currentDir + unquotedOrigUrl.replace(/^\\.\\//, \"\"); // Strip leading './'\n\t\t}\n\n\t\t// send back the fixed url(...)\n\t\treturn \"url(\" + JSON.stringify(newUrl) + \")\";\n\t});\n\n\t// send back the fixed css\n\treturn fixedCss;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D/./node_modules/style-loader/lib/urls.js?"); + +/***/ }), + +/***/ "./node_modules/webpack/buildin/module.js": +/*!***********************************!*\ + !*** (webpack)/buildin/module.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("module.exports = function(module) {\n\tif (!module.webpackPolyfill) {\n\t\tmodule.deprecate = function() {};\n\t\tmodule.paths = [];\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D/(webpack)/buildin/module.js?"); + +/***/ }), + +/***/ "./src/iDisqus.js": +/*!************************!*\ + !*** ./src/iDisqus.js ***! + \************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_RESULT__;/*!\r\n * \r\n * @author fooleap\r\n * @email fooleap@gmail.com\r\n * @create 2017-06-17 20:48:25\r\n * @update 2021-05-11 11:58:38\r\n * @version 0.2.31\r\n * Copyright 2017-2021 fooleap\r\n * Released under the MIT license\r\n */\r\n__webpack_require__(/*! ./iDisqus.scss */ \"./src/iDisqus.scss\");\r\n(function (global) {\r\n 'use strict';\r\n\r\n var d = document,\r\n l = localStorage,\r\n scripts = d.scripts,\r\n lasturl = scripts[scripts.length - 1].src,\r\n filepath = lasturl.substring(0, lasturl.lastIndexOf('/')),\r\n isEdge = navigator.userAgent.indexOf(\"Edge\") > -1,\r\n isIE = !!window.ActiveXObject || \"ActiveXObject\" in window;\r\n\r\n function getLocation(href) {\r\n var link = d.createElement('a');\r\n link.href = href;\r\n return link;\r\n }\r\n\r\n function getAjax(url, success, error) {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open('GET', encodeURI(url));\r\n xhr.onreadystatechange = function () {\r\n if (xhr.readyState == 4 && xhr.status == 200) {\r\n success(xhr.responseText);\r\n }\r\n }\r\n xhr.onerror = error;\r\n xhr.withCredentials = true;\r\n xhr.send();\r\n return xhr;\r\n }\r\n\r\n function postAjax(url, data, success, error) {\r\n var params = typeof data == 'string' ? data : Object.keys(data).filter(function (k) {\r\n return data[k] != null;\r\n }).map(function (k) {\r\n return encodeURIComponent(k) + '=' + encodeURIComponent(data[k])\r\n }).join('&');\r\n\r\n var xhr = new XMLHttpRequest();\r\n xhr.open('POST', url);\r\n xhr.onreadystatechange = function () {\r\n if (xhr.readyState == 4 && xhr.status == 200) {\r\n success(xhr.responseText);\r\n }\r\n };\r\n xhr.onerror = error;\r\n xhr.withCredentials = true;\r\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\r\n xhr.send(params);\r\n return xhr;\r\n }\r\n\r\n function generateGUID() {\r\n var time = Number(new Date().getTime().toString().substring(3));\r\n var guid = Math.abs(time + Math.floor(Math.random() * 1e5) - 48 * 1e6 + Math.floor(Math.random() * 1e6)).toString(32);\r\n guid += Math.floor(Math.random() * 1e9).toString(32);\r\n return guid;\r\n }\r\n\r\n (function (ElementProto) {\r\n // matches & closest polyfill https://github.com/jonathantneal/closest\r\n if (typeof ElementProto.matches !== 'function') {\r\n ElementProto.matches = ElementProto.msMatchesSelector || ElementProto.mozMatchesSelector || ElementProto.webkitMatchesSelector || function matches(selector) {\r\n var element = this;\r\n var elements = (element.document || element.ownerDocument).querySelectorAll(selector);\r\n var index = 0;\r\n\r\n while (elements[index] && elements[index] !== element) {\r\n ++index;\r\n }\r\n\r\n return Boolean(elements[index]);\r\n };\r\n }\r\n\r\n if (typeof ElementProto.closest !== 'function') {\r\n ElementProto.closest = function closest(selector) {\r\n var element = this;\r\n\r\n while (element && element.nodeType === 1) {\r\n if (element.matches(selector)) {\r\n return element;\r\n }\r\n\r\n element = element.parentNode;\r\n }\r\n\r\n return null;\r\n };\r\n }\r\n\r\n // 事件委托\r\n ElementProto.on = function on(eventName, selector, handler) {\r\n this.addEventListener(eventName, function (e) {\r\n for (var target = e.target; target && target != this; target = target.parentNode) {\r\n if (target.matches(selector)) {\r\n handler.call(null, e, target);\r\n break;\r\n }\r\n }\r\n }, true);\r\n };\r\n\r\n })(window.Element.prototype);\r\n\r\n // 访客信息\r\n var User = function () {\r\n this.dom = arguments[0];\r\n this.opts = arguments[1];\r\n this.init();\r\n this.autologin();\r\n }\r\n\r\n User.prototype = {\r\n // 初始化访客信息\r\n init: function () {\r\n var _ = this;\r\n // 读取访客信息\r\n _.name = l.getItem('name');\r\n _.email = l.getItem('email');\r\n _.url = l.getItem('url');\r\n _.avatar = l.getItem('avatar');\r\n _.type = l.getItem('type');\r\n _.logged_in = l.getItem('logged_in');\r\n _.unique = l.getItem('disqus_unique')\r\n if (!l.getItem('vote')) {\r\n l.setItem('vote', JSON.stringify({}));\r\n }\r\n if (!l.getItem('reaction_vote')) {\r\n l.setItem('reaction_vote', JSON.stringify({}));\r\n }\r\n _.vote = JSON.parse(l.getItem('vote'));\r\n _.reactionVote = JSON.parse(l.getItem('reaction_vote'));\r\n\r\n var boxarr = _.dom.getElementsByClassName('comment-box');\r\n if (_.logged_in == 'true') {\r\n [].forEach.call(boxarr, function (item) {\r\n if (_.type == '1') {\r\n item.querySelector('.comment-form-wrapper').classList.add('logged-in');\r\n }\r\n item.querySelector('.comment-form-name').value = _.name;\r\n item.querySelector('.comment-form-email').value = _.email;\r\n item.querySelector('.comment-form-url').value = _.url;\r\n item.querySelector('.comment-avatar-image').src = _.avatar;\r\n });\r\n } else {\r\n [].forEach.call(boxarr, function (item) {\r\n item.querySelector('.comment-form-wrapper').classList.remove('logged-in');\r\n item.querySelector('.comment-form-name').value = '';\r\n item.querySelector('.comment-form-email').value = '';\r\n item.querySelector('.comment-form-url').value = '';\r\n item.querySelector('.comment-avatar-image').src = _.dom.querySelector('.comment-avatar-image').dataset.avatar;\r\n });\r\n l.setItem('logged_in', 'false');\r\n }\r\n\r\n if (_.type == '1' && _.logged_in == 'true') {\r\n var $login = _.dom.querySelector('.comment-login');\r\n if (!!$login) {\r\n $login.innerHTML = _.name + '<label class=\"comment-logout\" title=\"退出\" for=\"comment-user\">退出登录</label>';\r\n $login.title = _.name;\r\n $login.classList.add('comment-user');\r\n $login.classList.remove('comment-login');\r\n _.dom.querySelector('#comment-user').checked = false;\r\n }\r\n } else {\r\n var $user = _.dom.querySelector('.comment-user');\r\n if (!!$user) {\r\n $user.innerHTML = '登录';\r\n $user.title = '使用 Disqus 帐号授权登录';\r\n $user.classList.add('comment-login');\r\n $user.classList.remove('comment-user');\r\n }\r\n }\r\n\r\n },\r\n\r\n // 自动登录\r\n autologin: function () {\r\n var _ = this;\r\n getAjax(_.opts.api + '/user.php', function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code == 0) {\r\n var user = data.response;\r\n _.avatar = user.avatar;\r\n _.name = user.name;\r\n _.username = user.username;\r\n _.url = user.url;\r\n _.type = user.type\r\n _.submit();\r\n } else {\r\n if (_.type == '1') {\r\n l.setItem('logged_in', 'false');\r\n _.init();\r\n } else {\r\n l.setItem('type', '0');\r\n if (!_.unique) {\r\n l.setItem('disqus_unique', generateGUID());\r\n }\r\n _.init();\r\n }\r\n }\r\n }, function () {\r\n })\r\n },\r\n\r\n // 登录\r\n login: function () {\r\n\r\n var _ = this;\r\n var popup = window.open(_.opts.api + '/login.php', 'Disqus Oauth', 'width=470,height=508');\r\n var timer;\r\n function isLogged() {\r\n if (!popup || !popup.closed) return;\r\n clearInterval(timer);\r\n _.user.autologin();\r\n }\r\n timer = setInterval(isLogged, 100);\r\n\r\n },\r\n\r\n // 退出登录\r\n logout: function () {\r\n var _ = this;\r\n postAjax(_.opts.api + '/logout.php', {}, function (resp) {\r\n l.setItem('logged_in', 'false');\r\n l.removeItem('type');\r\n l.removeItem('email');\r\n l.removeItem('avatar');\r\n l.removeItem('name');\r\n l.removeItem('url');\r\n l.removeItem('disqus_unique');\r\n l.removeItem('vote');\r\n l.removeItem('reaction_vote');\r\n _.user.init();\r\n })\r\n },\r\n\r\n // 提交访客信息\r\n submit: function () {\r\n var _ = this;\r\n l.setItem('email', _.email);\r\n l.setItem('type', _.type);\r\n l.setItem('name', _.name);\r\n l.setItem('url', _.url);\r\n l.setItem('avatar', _.avatar);\r\n l.setItem('disqus_unique', _.unique);\r\n l.setItem('logged_in', 'true');\r\n this.init();\r\n }\r\n }\r\n\r\n var iDisqus = function () {\r\n var _ = this;\r\n\r\n // 配置\r\n _.opts = typeof (arguments[1]) == 'object' ? arguments[1] : arguments[0];\r\n _.dom = d.getElementById(typeof (arguments[0]) == 'string' ? arguments[0] : 'comment');\r\n _.opts.api = _.opts.api.slice(-1) == '/' ? _.opts.api.slice(0, -1) : _.opts.api;\r\n _.opts.site = _.opts.site || location.origin;\r\n if (!!_.opts.url) {\r\n var optsUrl = _.opts.url.replace(_.opts.site, '');\r\n _.opts.url = optsUrl.slice(0, 1) != '/' ? '/' + optsUrl : optsUrl;\r\n } else if (isEdge || isIE) {\r\n _.opts.url = encodeURI(location.pathname) + encodeURI(location.search);\r\n } else {\r\n _.opts.url = location.pathname + location.search;\r\n }\r\n _.opts.identifier = _.opts.identifier || _.opts.url;\r\n _.opts.link = _.opts.site + _.opts.url;\r\n _.opts.title = _.opts.title || d.title;\r\n _.opts.slug = !!_.opts.slug ? _.opts.slug.replace(/[^A-Za-z0-9_-]+/g, '') : '';\r\n _.opts.desc = _.opts.desc || (!!d.querySelector('[name=\"description\"]') ? d.querySelector('[name=\"description\"]').content : '');\r\n _.opts.mode = _.opts.mode || 1;\r\n _.opts.timeout = _.opts.timeout || 3000;\r\n _.opts.toggle = !!_.opts.toggle ? d.getElementById(_.opts.toggle) : null;\r\n _.opts.autoCreate = !!_.opts.autoCreate || !!_.opts.auto;\r\n _.opts.relatedType = _.opts.relatedType || 'related'\r\n\r\n // emoji 表情\r\n _.opts.emojiPath = _.opts.emojiPath || _.opts.emoji_path || 'https://github.githubassets.com/images/icons/emoji/unicode/';\r\n _.emojiList = _.opts.emojiList || _.opts.emoji_list || [{\r\n code: 'smile',\r\n title: '笑脸',\r\n unicode: '1f604'\r\n }, {\r\n code: 'mask',\r\n title: '生病',\r\n unicode: '1f637'\r\n }, {\r\n code: 'joy',\r\n title: '破涕为笑',\r\n unicode: '1f602'\r\n }, {\r\n code: 'stuck_out_tongue_closed_eyes',\r\n title: '吐舌',\r\n unicode: '1f61d'\r\n }, {\r\n code: 'flushed',\r\n title: '脸红',\r\n unicode: '1f633'\r\n }, {\r\n code: 'scream',\r\n title: '恐惧',\r\n unicode: '1f631'\r\n }, {\r\n code: 'pensive',\r\n title: '失望',\r\n unicode: '1f614'\r\n }, {\r\n code: 'unamused',\r\n title: '无语',\r\n unicode: '1f612'\r\n }, {\r\n code: 'grin',\r\n title: '露齿笑',\r\n unicode: '1f601'\r\n }, {\r\n code: 'heart_eyes',\r\n title: '色',\r\n unicode: '1f60d'\r\n }, {\r\n code: 'sweat',\r\n title: '汗',\r\n unicode: '1f613'\r\n }, {\r\n code: 'smirk',\r\n title: '得意',\r\n unicode: '1f60f'\r\n }, {\r\n code: 'relieved',\r\n title: '满意',\r\n unicode: '1f60c'\r\n }, {\r\n code: 'rolling_eyes',\r\n title: '翻白眼',\r\n unicode: '1f644'\r\n }, {\r\n code: 'ok_hand',\r\n title: 'OK',\r\n unicode: '1f44c'\r\n }, {\r\n code: 'v',\r\n title: '胜利',\r\n unicode: '270c'\r\n }];\r\n\r\n if (!!_.opts.emoji_preview || !!_.opts.emojiPreview) {\r\n getAjax(_.opts.api + '/eac.php', function (resp) {\r\n _.eac = JSON.parse(resp);\r\n }, function () {\r\n })\r\n }\r\n\r\n // 默认状态\r\n _.stat = {\r\n current: 'idisqus', // 当前显示评论框\r\n loaded: false, // 评论框已加载\r\n loading: false, // 评论加载中\r\n editing: false, // 评论编辑中\r\n offsetTop: 0, // 高度位置\r\n next: null, // 下条评论\r\n message: null, // 新评论\r\n mediaHtml: null, // 新上传图片\r\n forum: {}, // 站点信息\r\n thread: {}, // 文章信息\r\n post: {}, // 评论数据\r\n media: {}, // 媒体信息\r\n root: [], // 根评论\r\n order: 'desc', // 排序\r\n users: [], // Disqus 会员\r\n imageSize: [], // 已上传图片大小\r\n disqusLoaded: false // Disqus 已加载\r\n };\r\n\r\n // Disqus 评论框设置\r\n window.disqus_config = function () {\r\n this.page.identifier = _.opts.identifier;\r\n this.page.title = _.opts.title;\r\n this.page.url = _.opts.link;\r\n this.callbacks.onReady.push(function () {\r\n _.stat.current = 'disqus';\r\n _.stat.disqusLoaded = true;\r\n _.dom.querySelector('#idisqus').style.display = 'none';\r\n _.dom.querySelector('#disqus_thread').style.display = 'block';\r\n if (_.opts.mode == 3 && !!_.opts.toggle) {\r\n _.opts.toggle.disabled = '';\r\n _.opts.toggle.checked = true;\r\n _.opts.toggle.addEventListener('change', _.handle.toggle, false);\r\n }\r\n });\r\n // 原生评论框发邮件\r\n this.callbacks.onNewComment = [function (comment, a) {\r\n var postData = {\r\n id: comment.id\r\n }\r\n // 异步发送邮件\r\n setTimeout(function () {\r\n postAjax(_.opts.api + '/sendemail.php', postData, function (resp) {\r\n console.info('邮件发送成功!');\r\n })\r\n }, 2000);\r\n }];\r\n }\r\n\r\n // 自动初始化\r\n if (!!_.opts.init) {\r\n _.init();\r\n //console.log(_);\r\n }\r\n }\r\n\r\n // TimeAgo https://coderwall.com/p/uub3pw/javascript-timeago-func-e-g-8-hours-ago\r\n iDisqus.prototype.timeAgo = function () {\r\n\r\n var _ = this;\r\n var templates = {\r\n prefix: \"\",\r\n suffix: \"前\",\r\n seconds: \"几秒\",\r\n minute: \"1分钟\",\r\n minutes: \"%d分钟\",\r\n hour: \"1小时\",\r\n hours: \"%d小时\",\r\n day: \"1天\",\r\n days: \"%d天\",\r\n week: \"1周\",\r\n weeks: \"%d周\",\r\n month: \"1个月\",\r\n months: \"%d个月\",\r\n year: \"1年\",\r\n years: \"%d年\"\r\n };\r\n var template = function (t, n) {\r\n return templates[t] && templates[t].replace(/%d/i, Math.abs(Math.round(n)));\r\n };\r\n\r\n var timer = function (time) {\r\n if (!time) return;\r\n time = time.replace(/\\.\\d+/, \"\"); // remove milliseconds\r\n time = time.replace(/-/, \"/\").replace(/-/, \"/\");\r\n time = time.replace(/T/, \" \").replace(/Z/, \" UTC\");\r\n time = time.replace(/([\\+\\-]\\d\\d)\\:?(\\d\\d)/, \" $1$2\"); // -04:00 -> -0400\r\n time = new Date(time * 1000 || time);\r\n\r\n var now = new Date();\r\n var seconds = ((now.getTime() - time) * .001) >> 0;\r\n var minutes = seconds / 60;\r\n var hours = minutes / 60;\r\n var days = hours / 24;\r\n var weeks = days / 7;\r\n var months = days / 30;\r\n var years = days / 365;\r\n\r\n return templates.prefix + (seconds < 45 && template('seconds', seconds) || seconds < 90 && template('minute', 1) || minutes < 45 && template('minutes', minutes) || minutes < 90 && template('hour', 1) || hours < 24 && template('hours', hours) || hours < 42 && template('day', 1) || days < 30 && template('days', days) || days < 45 && template('month', 1) || days < 365 && template('months', months) || years < 1.5 && template('year', 1) || template('years', years)) + templates.suffix;\r\n };\r\n\r\n var elements = _.dom.querySelectorAll('time[datetime]');\r\n for (var i in elements) {\r\n var $this = elements[i];\r\n if (typeof $this === 'object') {\r\n $this.title = new Date($this.getAttribute('datetime'));\r\n $this.innerHTML = timer($this.getAttribute('datetime'));\r\n }\r\n }\r\n\r\n // update time every minute\r\n setTimeout(_.timeAgo.bind(_), 60000);\r\n\r\n }\r\n\r\n // 初始化评论框\r\n iDisqus.prototype.init = function () {\r\n var _ = this;\r\n if (!_.dom) {\r\n //console.log('该页面没有评论框!');\r\n return\r\n }\r\n // 表情\r\n var emojiList = '';\r\n _.emojiList.forEach(function (item) {\r\n emojiList += '<li class=\"emojione-item\" title=\"' + item.title + '\" data-code=\":' + item.code + ':\"><img class=\"emojione-item-image\" src=\"' + _.opts.emojiPath + item.unicode + '.png\" /></li>';\r\n })\r\n _.dom.innerHTML = `<div class=\"comment init\" id=\"idisqus\">\r\n <div class=\"comment-reaction\">\r\n <div class=\"comment-reaction-header\">\r\n <div class=\"comment-reaction-prompt\"></div>\r\n <div class=\"comment-reaction-total\"></div>\r\n </div>\r\n <div class=\"comment-reaction-list\"></div>\r\n </div>\r\n <div class=\"init-container\" data-tips=\"正在初始化……\"><svg class=\"init-bg\" width=\"72\" height=\"72\" viewBox=\"0 0 720 720\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path class=\"ring\" fill=\"none\" stroke=\"#9d9ea1\" d=\"M 0 -260 A 260 260 0 1 1 -80 -260\" transform=\"translate(400,400)\" stroke-width=\"50\" /><polygon transform=\"translate(305,20)\" points=\"50,0 0,100 18,145 50,82 92,145 100,100\" style=\"fill:#9d9ea1\"/></svg></div>\r\n <div class=\"comment-header\">\r\n <div class=\"comment-header-primary\">\r\n <span class=\"comment-header-item\" id=\"comment-count\">评论</span>\r\n <a class=\"comment-header-item\" id=\"comment-link\" target=\"_blank\">在线讨论</a>\r\n </div>\r\n <div class=\"comment-header-menu\">\r\n <input class=\"comment-header-checkbox\" type=\"checkbox\" id=\"comment-user\">\r\n <label class=\"comment-header-item comment-login\" title=\"使用 Disqus 帐号授权登录\" for=\"comment-user\">登录</label>\r\n </div>\r\n </div>\r\n <div class=\"comment-navbar\">\r\n <div class=\"comment-navbar-item\">\r\n <a class=\"comment-recommend\" href=\"javascript:;\"><svg t=\"1537508059126\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3234\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"24\" height=\"24\"><path d=\"M489.993 887.107 177.906 586.021c-4.002-3.501-114.033-104.031-114.033-224.063 0-146.54 89.526-234.065 239.069-234.065 87.523 0 169.546 69.019 209.058 108.03 39.512-39.011 121.535-108.03 209.059-108.03 149.542 0 239.068 87.525 239.068 234.065 0 120.033-110.031 220.563-114.533 225.065L534.007 887.107c-6 6-14.003 9-22.007 9C503.997 896.107 495.993 893.107 489.993 887.107z\" p-id=\"3235\"></path></svg><span class=\"comment-recommend-text\">推荐</span><span class=\"comment-recommend-count\"></span></a>\r\n </div>\r\n <div class=\"comment-navbar-item comment-order\">\r\n <input class=\"comment-order-radio\" id=\"order-popular\" type=\"radio\" name=\"comment-order\" value=\"popular\" />\r\n <label class=\"comment-order-label\" for=\"order-popular\" title=\"按评分高低排序\">最佳</label>\r\n <input class=\"comment-order-radio\" id=\"order-desc\" type=\"radio\" name=\"comment-order\" value=\"desc\" />\r\n <label class=\"comment-order-label\" for=\"order-desc\" title=\"按从新到旧排序\">最新</label>\r\n <input class=\"comment-order-radio\" id=\"order-asc\" type=\"radio\" name=\"comment-order\" value=\"asc\" />\r\n <label class=\"comment-order-label\" for=\"order-asc\" title=\"按从旧到新排序\">最早</label>\r\n </div>\r\n </div>\r\n <div class=\"comment-box\">\r\n <div class=\"comment-avatar avatar\"><img class=\"comment-avatar-image\" src=\"//a.disquscdn.com/images/noavatar92.png\" data-avatar=\"//a.disquscdn.com/images/noavatar92.png\"></div>\r\n <div class=\"comment-form\">\r\n <div class=\"comment-form-wrapper\">\r\n <textarea class=\"comment-form-textarea\" placeholder=\"加入讨论……\"></textarea>\r\n <div class=\"comment-form-alert\"></div>\r\n <div class=\"comment-image\">\r\n <ul class=\"comment-image-list\"></ul>\r\n <div class=\"comment-image-progress\"><div class=\"comment-image-loaded\"></div></div>\r\n </div>\r\n \r\n <div class=\"comment-actions\">\r\n \r\n <div class=\"comment-actions-group\">\r\n <input id=\"emoji-input\" class=\"comment-actions-input\" type=\"checkbox\">\r\n <label class=\"comment-actions-label emojione\" for=\"emoji-input\">\r\n <svg class=\"icon\" fill=\"#c2c6cc\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"200\" height=\"200\">\r\n <g>\r\n <title>选择表情</title>\r\n <path d=\"M512 1024c-282.713043 0-512-229.286957-512-512s229.286957-512 512-512c282.713043 0 512 229.286957 512 512S792.486957 1024 512 1024zM512 44.521739c-258.226087 0-467.478261 209.252174-467.478261 467.478261 0 258.226087 209.252174 467.478261 467.478261 467.478261s467.478261-209.252174 467.478261-467.478261C979.478261 253.773913 768 44.521739 512 44.521739z\"></path>\r\n <path d=\"M801.391304 554.295652c0 160.278261-129.113043 289.391304-289.391304 289.391304s-289.391304-129.113043-289.391304-289.391304L801.391304 554.295652z\"></path>\r\n <path d=\"M674.504348 349.495652m-57.878261 0a2.6 2.6 0 1 0 115.756522 0 2.6 2.6 0 1 0-115.756522 0Z\"></path>\r\n <path d=\"M347.269565 349.495652m-57.878261 0a2.6 2.6 0 1 0 115.756522 0 2.6 2.6 0 1 0-115.756522 0Z\"></path>\r\n </g>\r\n </svg>\r\n <ul class=\"emojione-list\">${ emojiList}</ul>\r\n </label>\r\n <input id=\"upload-input\" class=\"comment-actions-input comment-image-input\" type=\"file\" accept=\"image/*\" name=\"file\">\r\n <label class=\"comment-actions-label\" for=\"upload-input\">\r\n <svg class=\"icon\" fill=\"#c2c6cc\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"200\" height=\"200\">\r\n <g>\r\n <title>上传图片</title>\r\n <path d=\"M15.515152 15.515152 15.515152 15.515152 15.515152 15.515152Z\"></path>\r\n <path d=\"M15.515152 139.636364l0 806.787879 992.969697 0 0-806.787879-992.969697 0zM946.424242 884.363636l-868.848485 0 0-682.666667 868.848485 0 0 682.666667zM698.181818 356.848485c0-51.417212 41.673697-93.090909 93.090909-93.090909s93.090909 41.673697 93.090909 93.090909c0 51.417212-41.673697 93.090909-93.090909 93.090909s-93.090909-41.673697-93.090909-93.090909zM884.363636 822.30303l-744.727273 0 186.181818-496.484848 248.242424 310.30303 124.121212-93.090909z\"></path>\r\n </g>\r\n </svg>\r\n </label>\r\n </div>\r\n \r\n <div class=\"comment-actions-form\">\r\n <button class=\"comment-form-submit\">\r\n <svg class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"200\" height=\"200\">\r\n <path d=\"M565.747623 792.837176l260.819261 112.921839 126.910435-845.424882L66.087673 581.973678l232.843092 109.933785 562.612725-511.653099-451.697589 563.616588-5.996574 239.832274L565.747623 792.837176z\" fill=\"#ffffff\"></path>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"comment-form-user\">\r\n <form class=\"comment-form-guest\"><input class=\"comment-form-input comment-form-name\" type=\"text\" name=\"name\" placeholder=\"名字(必填)\" autocomplete=\"name\" /><input class=\"comment-form-input comment-form-email\" type=\"email\" name=\"email\" placeholder=\"邮箱(必填)\" autocomplete=\"email\" /><input class=\"comment-form-input comment-form-url\" type=\"url\" name=\"url\" placeholder=\"网址(可选)\" autocomplete=\"url\" /></form>\r\n </div>\r\n </div>\r\n </div>\r\n <ul id=\"comments\" class=\"comment-list\" data-tips=\"评论加载中……\"></ul>\r\n <a href=\"javascript:;\" class=\"comment-loadmore hide\">加载更多</a>\r\n <div class=\"comment-related\"></div>\r\n </div>\r\n <div class=\"comment\" id=\"disqus_thread\"></div>`;\r\n\r\n _.user = new User(_.dom, _.opts);\r\n _.handle = {\r\n logout: _.user.logout.bind(_),\r\n login: _.user.login.bind(_),\r\n loadMore: _.loadMore.bind(_),\r\n loadMoreReply: _.loadMoreReply.bind(_),\r\n post: _.post.bind(_),\r\n threadCreate: _.threadCreate.bind(_),\r\n threadVote: _.threadVote.bind(_),\r\n reactionVote: _.reactionVote.bind(_),\r\n remove: _.remove.bind(_),\r\n show: _.show.bind(_),\r\n toggle: _.toggle.bind(_),\r\n upload: _.upload.bind(_),\r\n verify: _.verify.bind(_),\r\n jump: _.jump.bind(_),\r\n mention: _.mention.bind(_),\r\n keySelect: _.keySelect.bind(_),\r\n field: _.field.bind(_),\r\n focus: _.focus,\r\n input: _.input.bind(_),\r\n parentShow: _.parentShow.bind(_),\r\n selectOrder: _.selectOrder.bind(_)\r\n };\r\n\r\n var $iDisqus = _.dom.querySelector('#idisqus');\r\n $iDisqus.on('blur', '.comment-form-textarea', _.handle.focus);\r\n $iDisqus.on('focus', '.comment-form-textarea', _.handle.focus);\r\n $iDisqus.on('input', '.comment-form-textarea', _.handle.input);\r\n $iDisqus.on('propertychange', '.comment-form-textarea', _.handle.input);\r\n $iDisqus.on('keyup', '.comment-form-textarea', _.handle.mention);\r\n $iDisqus.on('keydown', '.comment-form-textarea', _.handle.keySelect);\r\n $iDisqus.on('blur', '.comment-form-name', _.handle.verify);\r\n $iDisqus.on('blur', '.comment-form-email', _.handle.verify);\r\n $iDisqus.on('click', '.comment-form-submit', _.handle.post);\r\n $iDisqus.on('click', '.comment-login', _.handle.login);\r\n $iDisqus.on('change', '.comment-image-input', _.handle.upload);\r\n $iDisqus.on('click', '.emojione-item', _.handle.field);\r\n $iDisqus.on('click', '.comment-logout', _.handle.logout);\r\n $iDisqus.on('click', '.comment-item-reply', _.handle.show);\r\n $iDisqus.on('click', '.comment-item-cancel', _.handle.show);\r\n $iDisqus.on('click', '.comment-item-avatar', _.handle.jump);\r\n $iDisqus.on('click', '.comment-item-pname', _.handle.jump);\r\n $iDisqus.on('mouseover', '.comment-item-pname', _.handle.parentShow);\r\n $iDisqus.on('click', '.comment-loadmore', _.handle.loadMore);\r\n $iDisqus.on('click', '.comment-item-loadmore', _.handle.loadMoreReply);\r\n $iDisqus.on('click', '#thread-submit', _.handle.threadCreate);\r\n $iDisqus.on('click', '.comment-recommend', _.handle.threadVote);\r\n $iDisqus.on('click', '.comment-reaction-btn:not(.selected)', _.handle.reactionVote);\r\n $iDisqus.on('change', '.comment-order-radio', _.handle.selectOrder);\r\n\r\n switch (_.opts.mode) {\r\n case 1:\r\n _.disqus();\r\n break;\r\n case 2:\r\n _.threadInit();\r\n break;\r\n case 3:\r\n _.threadInit();\r\n _.disqus();\r\n break;\r\n default:\r\n _.disqus();\r\n break;\r\n }\r\n }\r\n\r\n // 切换评论框\r\n iDisqus.prototype.toggle = function () {\r\n var _ = this;\r\n if (_.stat.current == 'disqus') {\r\n _.stat.current = 'idisqus';\r\n _.dom.querySelector('#idisqus').style.display = 'block';\r\n _.dom.querySelector('#disqus_thread').style.display = 'none';\r\n } else {\r\n _.disqus();\r\n }\r\n }\r\n\r\n // 加载 Disqus 评论\r\n iDisqus.prototype.disqus = function () {\r\n var _ = this;\r\n var _tips = _.dom.querySelector('.init-container').dataset.tips;\r\n if (_.opts.site != location.origin) {\r\n console.log('本地环境不加载 Disqus 评论框!');\r\n if (_.opts.mode == 1) {\r\n _.threadInit();\r\n }\r\n return;\r\n }\r\n if (!_.stat.disqusLoaded) {\r\n _tips = '尝试连接 Disqus……';\r\n\r\n var s = d.createElement('script');\r\n s.src = '//' + _.opts.forum + '.disqus.com/embed.js';\r\n s.dataset.timestamp = Date.now();\r\n s.onload = function () {\r\n _.stat.disqusLoaded = true;\r\n _tips = '连接成功,加载 Disqus 评论框……'\r\n }\r\n s.onerror = function () {\r\n if (_.opts.mode == 1) {\r\n _tips = '连接失败,加载简易评论框……';\r\n _.threadInit();\r\n }\r\n }\r\n\r\n\r\n var img = new Image();\r\n img.onerror = function () {\r\n if (_.opts.mode == 1) {\r\n _tips = '连接超时,加载简易评论框……';\r\n _.threadInit();\r\n }\r\n }\r\n img.onload = function () {\r\n (d.head || d.body).appendChild(s);\r\n clearTimeout(timer)\r\n };\r\n img.src = 'https://disqus.com/favicon.ico?' + Date.now();\r\n var timer = setTimeout(function () {\r\n if ( !img.complete || !img.naturalWidth ) {\r\n if (_.opts.mode == 1) {\r\n _tips = '连接失败,加载简易评论框……';\r\n _.threadInit();\r\n }\r\n }\r\n }, _.opts.timeout);\r\n } else {\r\n _.stat.current = 'disqus';\r\n _.dom.querySelector('#idisqus').style.display = 'none';\r\n _.dom.querySelector('#disqus_thread').style.display = 'block';\r\n }\r\n }\r\n\r\n // 添加事件监听\r\n iDisqus.prototype.addListener = function (els, evt, func) {\r\n var _ = this;\r\n var el = _.dom.getElementsByClassName(els);\r\n [].forEach.call(el, function (item) {\r\n item.addEventListener(evt, func, false);\r\n });\r\n }\r\n\r\n // 评论计数\r\n iDisqus.prototype.count = function () {\r\n var _ = this;\r\n var counts = d.querySelectorAll('[data-disqus-url]');\r\n var qty = counts.length;\r\n if (qty > 0) {\r\n var commentArr = [];\r\n for (var i = 0; i < qty; i++) {\r\n commentArr[i] = counts[i].dataset.disqusUrl.replace(_.opts.site, '');\r\n }\r\n getAjax(\r\n _.opts.api + '/threadsList.php?links=' + commentArr.join(','),\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n var posts = data.response;\r\n posts.forEach(function (item) {\r\n var link = document.createElement('a');\r\n link.href = item.link;\r\n var itemLink = link.href.replace(link.origin, '');\r\n var el = d.querySelector('[data-disqus-url$=\"' + itemLink + '\"]')\r\n if (!!el) {\r\n el.innerHTML = item.posts;\r\n el.dataset.disqusCount = item.posts;\r\n }\r\n });\r\n }, function () {\r\n console.log('获取数据失败!')\r\n }\r\n );\r\n }\r\n };\r\n\r\n // 加载最近评论\r\n iDisqus.prototype.postsList = function (listLimit, containerId) {\r\n var _ = this;\r\n listLimit = listLimit || 5;\r\n var listContainer = d.getElementById(typeof (containerId) == 'string' ? containerId : 'disqusPostsList');\r\n if (listContainer) {\r\n getAjax(\r\n _.opts.api + '/postsList.php?limit=' + listLimit,\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n var posts = data.response;\r\n var popHtml = '';\r\n posts.forEach(function (item) {\r\n popHtml += `<li style=\"list-style-type: none;\">${item.name}: ${item.raw_message}</br>评: <a href=\"${item.thread.link}\">${item.thread.title}</a></li>`;\r\n });\r\n popHtml = `<ul>${popHtml}</ul`;\r\n listContainer.innerHTML = popHtml;\r\n }, function () {\r\n console.log('获取数据失败!')\r\n }\r\n );\r\n }\r\n };\r\n\r\n // 加载相关话题\r\n iDisqus.prototype.loadRelated = function () {\r\n var _ = this;\r\n if (_.stat.forum.settings.organicDiscoveryEnabled == false || _.stat.relatedLoaded) {\r\n return;\r\n }\r\n getAjax(\r\n _.opts.api + '/threadsList.php?type=' + _.opts.relatedType.toLowerCase() + '&thread=' + _.stat.thread.id,\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code == 0) {\r\n _.stat.relatedLoaded = true;\r\n var threads = data.response;\r\n var popHtml = '';\r\n threads.forEach(function (item) {\r\n var message = item.topPost.message.replace(/<[^>]*>/g, '');\r\n popHtml += `<li class=\"related-item\">\r\n <a class=\"related-item-link\" href=\"${item.link}\" title=\"${item.title}\">\r\n <div class=\"related-item-title\">${item.title}</div>\r\n <div class=\"related-item-desc\">${item.posts}条评论<span class=\"related-item-bullet\"> • </span><time class=\"related-item-time\" datetime=\"${item.createdAt}\"></time></div></a>\r\n <a class=\"related-item-link\" href=\"${item.link}?#comment-${item.topPost.id}\" title=\"${message}\">\r\n <div class=\"related-item-post\">\r\n <div class=\"related-item-avatar\"><img src=\"${item.topPost.avatar}\" /></div>\r\n <div class=\"related-item-main\">\r\n <div class=\"related-item-name\">${ item.topPost.name}</div>\r\n <div class=\"related-item-message\">${ message}</div>\r\n </div>\r\n </div></a>\r\n </li>`;\r\n });\r\n popHtml = `<div class=\"comment-related-title\">在<span class=\"comment-related-forumname\">${_.stat.forum.name}</span>上还有</div><div class=\"comment-related-content\"><ul class=\"related-list\">${popHtml}</ul></div>`;\r\n _.dom.querySelector('.comment-related').innerHTML = popHtml;\r\n _.timeAgo();\r\n }\r\n }, function () {\r\n console.log('获取数据失败!')\r\n }\r\n );\r\n };\r\n\r\n // 加载反应\r\n iDisqus.prototype.loadReactions = function () {\r\n var _ = this;\r\n if (_.stat.forum.settings.threadReactionsEnabled == false) {\r\n return;\r\n }\r\n getAjax(_.opts.api + '/threadReactionsLoadReations.php' + '?thread=' + _.stat.thread.id, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.response.eligible) {\r\n _.dom.querySelector('.comment-reaction-prompt').innerHTML = data.response.prompt;\r\n var reactions = data.response.reactions;\r\n var total = 0;\r\n var reaListHtml = '';\r\n var selectedId = _.user.reactionVote[_.stat.thread.id];\r\n selectedId = selectedId || (!!data.selected ? data.selected.id : 0);\r\n reactions.forEach(function (item) {\r\n total += item.votes;\r\n reaListHtml += `<li class=\"comment-reaction-item\"><a class=\"comment-reaction-btn${(selectedId == item.id ? ' selected' : '')}\" data-id=\"${item.id}\" href=\"javascript:;\"><img class=\"comment-reaction-image\" src=\"${item.imageUrl}\"> ${item.text}</a><div class=\"comment-reaction-count\">${item.votes}</div></li>`;\r\n })\r\n _.dom.querySelector('.comment-reaction-list').innerHTML = reaListHtml;\r\n _.dom.querySelector('.comment-reaction-total').innerHTML = total + ' 人次参与';\r\n }\r\n }, function () { })\r\n\r\n };\r\n\r\n // 反应打分事件\r\n iDisqus.prototype.reactionVote = function (e, target) {\r\n var _ = this;\r\n var $reaction = target.closest('.comment-reaction-item');\r\n var $count = $reaction.querySelector('.comment-reaction-count');\r\n var reactionId = target.dataset.id;\r\n var postData = {\r\n thread: _.stat.thread.id,\r\n unique: _.user.unique,\r\n reaction: reactionId\r\n }\r\n postAjax(_.opts.api + '/threadReactionsVote.php', postData, function (resp) {\r\n _.user.reactionVote[_.stat.thread.id] = reactionId;\r\n l.setItem('reaction_vote', JSON.stringify(_.user.reactionVote));\r\n target.classList.add('selected');\r\n $count.innerHTML++\r\n })\r\n }\r\n\r\n // 排序\r\n iDisqus.prototype.selectOrder = function (e, target) {\r\n var _ = this;\r\n var order = target.value;\r\n sessionStorage.setItem('order', order);\r\n _.stat.order = order;\r\n _.dom.querySelector('.comment-list').innerHTML = '';\r\n _.dom.querySelector('.comment-loadmore').classList.add('hide');\r\n _.stat.next = null;\r\n _.getlist();\r\n }\r\n\r\n // 获取评论列表\r\n iDisqus.prototype.getlist = function () {\r\n var _ = this;\r\n _.stat.loading = true;\r\n _.dom.querySelector('#idisqus').classList.add('loading');\r\n _.dom.querySelector('.comment-list').dataset.tips = '评论加载中……';\r\n getAjax(\r\n _.opts.api + '/getcomments.php?thread=' + _.stat.thread.id + (!!_.stat.next ? '&cursor=' + _.stat.next : '') + '&order=' + _.stat.order,\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code === 0) {\r\n _.stat.offsetTop = d.documentElement.scrollTop || d.body.scrollTop;\r\n\r\n _.dom.querySelector('#idisqus').classList.remove('loading')\r\n var loadmore = _.dom.querySelector('.comment-loadmore');\r\n var posts = !!data.response ? data.response : [];\r\n _.stat.root = [];\r\n posts.forEach(function (item) {\r\n _.load(item);\r\n if (!item.parent) {\r\n _.stat.root.unshift(item.id);\r\n }\r\n });\r\n\r\n if (data.cursor.hasPrev) {\r\n _.stat.root.forEach(function (item) {\r\n _.dom.querySelector('.comment-list').appendChild(_.dom.querySelector('#comment-' + item));\r\n })\r\n }\r\n if (data.cursor.hasNext) {\r\n _.stat.next = data.cursor.next;\r\n loadmore.classList.remove('loading');\r\n loadmore.classList.remove('hide');\r\n } else {\r\n _.stat.next = null;\r\n loadmore.classList.add('hide');\r\n }\r\n\r\n if (_.stat.thread.posts == 0) {\r\n _.dom.querySelector('.comment-list').dataset.tips = '来做第一个留言的人吧!';\r\n return;\r\n }\r\n\r\n if (posts.length == 0) {\r\n return;\r\n }\r\n _.timeAgo();\r\n\r\n var iframe = _.dom.querySelectorAll('.comment-item-body iframe');\r\n [].forEach.call(iframe, function (item) {\r\n item.style.width = item.clientWidth + 'px';\r\n item.style.height = item.clientWidth * 9 / 16 + 'px';\r\n setTimeout(function () {\r\n item.src = item.src;\r\n }, 1000)\r\n })\r\n var tweet = _.dom.querySelectorAll('.comment-item-body .twitter-tweet');\r\n if (tweet.length > 0) {\r\n var head = document.getElementsByTagName('head')[0];\r\n var script = document.createElement('script');\r\n script.type = 'text/javascript';\r\n script.src = '//platform.twitter.com/widgets.js';\r\n head.appendChild(script);\r\n }\r\n\r\n window.scrollTo(0, _.stat.offsetTop);\r\n\r\n if (/^#disqus|^#comment-/.test(location.hash) && !data.cursor.hasPrev && !_.stat.disqusLoaded && !_.stat.loaded) {\r\n var el = _.dom.querySelector('#idisqus ' + location.hash)\r\n if (!!el) {\r\n window.scrollBy(0, el.getBoundingClientRect().top);\r\n }\r\n }\r\n _.stat.loading = false;\r\n _.stat.loaded = true;\r\n }\r\n }, function () {\r\n alert('获取数据失败,请检查服务器设置。')\r\n }\r\n );\r\n }\r\n\r\n // 读取评论\r\n iDisqus.prototype.load = function (post) {\r\n\r\n var _ = this;\r\n\r\n _.stat.post[post.id] = post;\r\n\r\n var parentPostDom = _.dom.querySelector('.comment-item[data-id=\"' + post.parent + '\"]');\r\n\r\n var user = {\r\n username: post.username,\r\n name: post.name,\r\n avatar: post.avatar\r\n }\r\n if (!!post.username && _.stat.users.map(function (user) { return user.username; }).indexOf(post.username) == -1) {\r\n _.stat.users.push(user);\r\n }\r\n\r\n var parentPost = !!post.parent ? {\r\n name: `<a class=\"comment-item-pname\" data-parent=\"${post.parent}\" href=\"#${parentPostDom.id}\"><svg class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"200\" height=\"200\"><path d=\"M1.664 902.144s97.92-557.888 596.352-557.888V129.728L1024 515.84l-425.984 360.448V628.8c-270.464 0-455.232 23.872-596.352 273.28\"></path></svg>${parentPostDom.dataset.name}</a>`,\r\n dom: parentPostDom.querySelector('.comment-item-children'),\r\n insert: 'afterbegin'\r\n } : {\r\n name: '',\r\n dom: _.dom.querySelector('.comment-list'),\r\n insert: post.id == 'preview' || !!post.isPost ? 'afterbegin' : 'beforeend'\r\n };\r\n\r\n\r\n var html = `<li class=\"comment-item\" data-id=\"${post.id}\" data-name=\"${post.name}\" id=\"comment-${post.id}\">\r\n <div class=\"comment-item-body\">\r\n <a class=\"comment-item-avatar\" href=\"#comment-${ post.id}\"><img src=\"${post.avatar}\"></a>\r\n <div class=\"comment-item-main\">\r\n <div class=\"comment-item-header\"><a class=\"comment-item-name\" title=\"${ post.name}\" rel=\"nofollow\" target=\"_blank\" href=\"${(post.url || 'javascript:;')}\">${post.name}</a>${(post.isMod ? `<span class=\"comment-item-badge\">${_.opts.badge}</span>` : ``)}${parentPost.name}<span class=\"comment-item-bullet\"> • </span><time class=\"comment-item-time\" datetime=\"${post.createdAt}\"></time></div>\r\n <div class=\"comment-item-content\">${ post.message}</div>\r\n <div class=\"comment-item-footer\">${!!post.isPost ? `<span class=\"comment-item-manage\"><a class=\"comment-item-edit\" href=\"javascript:;\">编辑</a><span class=\"comment-item-bullet\"> • </span><a class=\"comment-item-delete\" href=\"javascript:;\">删除</a><span class=\"comment-item-bullet\"> • </span></span>` : ``}<a class=\"comment-item-reply\" href=\"javascript:;\">回复</a></div>\r\n </div></div>\r\n <ul class=\"comment-item-children\">\r\n ${ post.hasMore ? `<li><a class=\"comment-item-loadmore\" href=\"javascript:;\">显示更多回复</a></li>` : `` }\r\n </ul>\r\n </li>`;\r\n\r\n // 已删除评论\r\n if (!!post.isDeleted) {\r\n html = `<li class=\"comment-item\" data-id=\"${post.id}\" id=\"comment-${post.id}\" data-name=\"${post.name}\">\r\n <div class=\"comment-item-body\">\r\n <a class=\"comment-item-avatar\" href=\"#comment-${ post.id}\"><img src=\"${post.avatar}\"></a>\r\n <div class=\"comment-item-main\" data-message=\"此评论已被删除。\"></div></div>\r\n <ul class=\"comment-item-children\">\r\n ${ post.hasMore ? `<li><a class=\"comment-item-loadmore\" href=\"javascript:;\">显示更多回复</a></li>` : `` }\r\n </ul>\r\n </li>`;\r\n }\r\n\r\n\r\n // 更新 or 创建\r\n if (!!_.dom.querySelector('.comment-item[data-id=\"' + post.id + '\"]')) {\r\n _.dom.querySelector('.comment-item[data-id=\"' + post.id + '\"]').outerHTML = html;\r\n } else {\r\n parentPost.dom.insertAdjacentHTML(parentPost.insert, html);\r\n }\r\n\r\n // 发布留言,可编辑删除\r\n if (!!post.isPost && !_.stat.editing) {\r\n var $this = _.dom.querySelector('.comment-item[data-id=\"' + post.id + '\"]');\r\n\r\n var postEdit = setTimeout(function () {\r\n // 十分钟后\r\n if (!!$this.querySelector('.comment-item-manage')) {\r\n $this.querySelector('.comment-item-manage').outerHTML = '';\r\n }\r\n }, 6 * 1e5);\r\n\r\n // 删除\r\n $this.querySelector('.comment-item-delete').addEventListener('click', function (e) {\r\n var postData = {\r\n id: post.id\r\n }\r\n var delDom = e.currentTarget;\r\n delDom.innerHTML = '删除中';\r\n postAjax(_.opts.api + '/removecomment.php', postData, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code === 0) {\r\n if (data.response.isDeleted == true) {\r\n $this.outerHTML = '';\r\n _.stat.thread.posts = parseInt(_.dom.querySelector('#comment-count').innerHTML) - 1;\r\n _.dom.querySelector('#comment-count').innerHTML = _.stat.thread.posts + ' 条评论';\r\n } else {\r\n alert(data.response.message);\r\n $this.querySelector('.comment-item-manage').outerHTML = '';\r\n }\r\n } else if (data.code === 2) {\r\n alert(data.response);\r\n $this.querySelector('.comment-item-manage').outerHTML = '';\r\n }\r\n }, function () {\r\n alert('删除出错,请稍后重试');\r\n })\r\n clearTimeout(postEdit);\r\n }, false)\r\n\r\n // 编辑\r\n $this.querySelector('.comment-item-edit').addEventListener('click', function () {\r\n _.stat.editing = post;\r\n _.edit(post);\r\n }, false)\r\n }\r\n }\r\n\r\n // 读取更多\r\n iDisqus.prototype.loadMore = function (e, target) {\r\n var _ = this;\r\n _.stat.offsetTop = d.documentElement.scrollTop || d.body.scrollTop;\r\n if (!_.stat.loading) {\r\n target.classList.add('loading');\r\n _.getlist();\r\n }\r\n }\r\n\r\n // 读取更多回复\r\n iDisqus.prototype.loadMoreReply = function (e, target) {\r\n var _ = this;\r\n target.innerHTML = '加载中……';\r\n var $children = target.closest('.comment-item-children');\r\n var $post = target.closest('.comment-item');\r\n getAjax(\r\n _.opts.api + '/descendants.php?post=' + $post.dataset.id,\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n if( data.code == 0 ){\r\n $children.removeChild(target.parentNode);\r\n var posts = data.response;\r\n posts.forEach(function (item) {\r\n _.load(item);\r\n });\r\n _.timeAgo();\r\n } else {\r\n target.innerHTML = '读取失败';\r\n }\r\n }, function () {\r\n target.innerHTML = '读取出错';\r\n }\r\n );\r\n }\r\n\r\n // 评论框焦点\r\n iDisqus.prototype.focus = function (e, target) {\r\n var wrapper = target.closest('.comment-form-wrapper');\r\n wrapper.classList.add('editing');\r\n if (wrapper.classList.contains('focus')) {\r\n wrapper.classList.remove('focus');\r\n } else {\r\n wrapper.classList.add('focus');\r\n }\r\n }\r\n\r\n // 输入事件\r\n iDisqus.prototype.input = function (e, target) {\r\n var _ = this;\r\n var form = target.closest('.comment-form');\r\n var alertmsg = form.querySelector('.comment-form-alert');\r\n alertmsg.innerHTML = '';\r\n var wrapper = form.querySelector('.comment-form-wrapper');\r\n var filterText = target.value.replace(/<code>.*?<\\/code>/g, '');\r\n var urls = filterText.match(/(^|\\s|\\r|\\n)*(http:\\/\\/|https:\\/\\/)(\\w|-|\\.)*(disqus|sinaimg|giphy|imgur|instagram|twimg|twitter|youtube|youtu\\.be)((\\w|=|\\?|\\.|\\/|&|\\%|-)*)(jpg|png|gif|gallery\\/\\w+|p\\/[a-zA-Z0-9]{11}.*|status\\/\\d{19}|v=[a-zA-Z0-9]{11}|\\/[a-zA-Z0-9]{11})(\\s|$|\\n)/g);\r\n form.querySelector('.comment-image-list').innerHTML = '';\r\n if (!!urls) {\r\n urls.forEach(function (item, i) {\r\n item = item.replace('/\\n|\\r\\n|^\\s|\\s$/g', '');\r\n var image = _.stat.media[item];\r\n if (!!image) {\r\n var imageHtml = `<li class=\"comment-image-item\" data-image-url=\"${image.thumbnailUrl}\"><img class=\"comment-image-object\" src=\"https:${image.thumbnailUrl}\"></li>`;\r\n form.querySelector('.comment-image-list').insertAdjacentHTML('beforeend', imageHtml);\r\n wrapper.classList.add('expanded');\r\n return;\r\n }\r\n postAjax(_.opts.api + '/media.php', { url: item }, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code == 0) {\r\n image = data.response;\r\n var imageHtml = `<li class=\"comment-image-item\" data-image-url=\"${image.thumbnailUrl}\"><img class=\"comment-image-object\" src=\"https:${image.thumbnailUrl}\"></li>`;\r\n form.querySelector('.comment-image-list').insertAdjacentHTML('beforeend', imageHtml);\r\n _.stat.media[item] = image;\r\n wrapper.classList.add('expanded');\r\n }\r\n }, function () {\r\n })\r\n })\r\n } else {\r\n wrapper.classList.remove('expanded');\r\n }\r\n\r\n }\r\n\r\n // 提醒用户 @ mention \r\n iDisqus.prototype.mention = function (e, target) {\r\n var _ = this;\r\n var textarea = target;\r\n var selStart = textarea.selectionStart;\r\n var mentionIndex = textarea.value.slice(0, selStart).lastIndexOf('@');\r\n var mentionText = textarea.value.slice(mentionIndex, selStart);\r\n var mentionDom = _.dom.querySelector('.mention-user');\r\n var showUsers = _.stat.users.filter(function (user) {\r\n var re = new RegExp(mentionText.slice(1), 'i');\r\n return user.username.search(re) > -1;\r\n });\r\n if (mentionText.search(/^@\\w+$|^@$/) == 0 && showUsers.length > 0) {\r\n if (e.keyCode == 38 || e.keyCode == 40) {\r\n return;\r\n }\r\n var coord = _.getCaretCoord(textarea);\r\n var list = '', html = '';\r\n\r\n showUsers.forEach(function (item, i) {\r\n list += `<li class=\"mention-user-item${(i == 0 ? ' active' : '')}\" data-username=\"${item.username}\"><img class=\"mention-user-avatar\" src=\"${item.avatar}\"><div class=\"mention-user-username\">${item.username}</div><div class=\"mention-user-name\">${item.name}</div></li>`;\r\n })\r\n if (!!mentionDom) {\r\n mentionDom.innerHTML = '<ul class=\"mention-user-list\">' + list + '</ul>';\r\n mentionDom.style.left = coord.left + 'px';\r\n mentionDom.style.top = coord.top + 'px';\r\n } else {\r\n html = `<div class=\"mention-user\" style=\"left:${coord.left}px;top:${coord.top}px\"><ul class=\"mention-user-list\">${list}</ul></div>`;\r\n _.dom.querySelector('#idisqus').insertAdjacentHTML('beforeend', html);\r\n }\r\n\r\n // 鼠标悬浮\r\n _.addListener('mention-user-item', 'mouseover', function () {\r\n _.dom.querySelector('.mention-user-item.active').classList.remove('active');\r\n this.classList.add('active');\r\n })\r\n\r\n // 鼠标点击\r\n _.addListener('mention-user-item', 'click', function () {\r\n var username = '@' + this.dataset.username + ' ';\r\n textarea.value = textarea.value.slice(0, mentionIndex) + username + textarea.value.slice(selStart);\r\n mentionDom.outerHTML = '';\r\n textarea.focus();\r\n textarea.setSelectionRange(mentionIndex + username.length, mentionIndex + username.length)\r\n })\r\n } else if (!!mentionDom) {\r\n mentionDom.outerHTML = '';\r\n }\r\n }\r\n\r\n // 获取光标坐标 https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a\r\n iDisqus.prototype.getCaretCoord = function (textarea) {\r\n var _ = this;\r\n var carPos = textarea.selectionEnd,\r\n div = d.createElement('div'),\r\n span = d.createElement('span'),\r\n copyStyle = getComputedStyle(textarea);\r\n [].forEach.call(copyStyle, function (prop) {\r\n div.style[prop] = copyStyle[prop];\r\n });\r\n div.style.position = 'absolute';\r\n _.dom.appendChild(div);\r\n div.textContent = textarea.value.substr(0, carPos);\r\n span.textContent = textarea.value.substr(carPos) || '.';\r\n div.appendChild(span);\r\n var coords = {\r\n 'top': textarea.offsetTop - textarea.scrollTop + span.offsetTop + parseFloat(copyStyle.lineHeight),\r\n 'left': textarea.offsetLeft - textarea.scrollLeft + span.offsetLeft\r\n };\r\n _.dom.removeChild(div);\r\n return coords;\r\n }\r\n\r\n // 键盘选择用户\r\n iDisqus.prototype.keySelect = function (e, target) {\r\n var _ = this;\r\n var textarea = target;\r\n var selStart = textarea.selectionStart;\r\n var mentionIndex = textarea.value.slice(0, selStart).lastIndexOf('@');\r\n var mentionText = textarea.value.slice(mentionIndex, selStart);\r\n var mentionDom = _.dom.querySelector('.mention-user');\r\n if (!mentionDom) {\r\n return;\r\n }\r\n var current = _.dom.querySelector('.mention-user-item.active')\r\n switch (e.keyCode) {\r\n case 13:\r\n //回车\r\n var username = '@' + current.dataset.username + ' ';\r\n textarea.value = textarea.value.slice(0, mentionIndex) + username + textarea.value.slice(selStart);\r\n textarea.setSelectionRange(mentionIndex + username.length, mentionIndex + username.length)\r\n _.dom.querySelector('.mention-user').outerHTML = '';\r\n e.preventDefault();\r\n break;\r\n case 38:\r\n //上\r\n if (!!current.previousSibling) {\r\n current.previousSibling.classList.add('active');\r\n current.classList.remove('active');\r\n }\r\n e.preventDefault();\r\n break;\r\n case 40:\r\n //下\r\n if (!!current.nextSibling) {\r\n current.nextSibling.classList.add('active');\r\n current.classList.remove('active');\r\n }\r\n e.preventDefault();\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n // 跳到评论\r\n iDisqus.prototype.jump = function (e, target) {\r\n var _ = this;\r\n var hash = getLocation(target.href).hash;\r\n var el = _.dom.querySelector('#idisqus ' + hash);\r\n history.replaceState(undefined, undefined, hash);\r\n window.scrollBy(0, el.getBoundingClientRect().top);\r\n e.preventDefault();\r\n }\r\n\r\n // 显示父评论\r\n iDisqus.prototype.parentShow = function (e, target) {\r\n var _ = this;\r\n if (!!target.querySelector('.comment-item-parent')) {\r\n return;\r\n }\r\n var comment = _.stat.post[target.dataset.parent];\r\n if (comment.isDeleted) {\r\n return;\r\n }\r\n var message = comment.message.replace(/<[^>]*>/g, '');\r\n var parentHtml = `<div class=\"comment-item-parent\"><a class=\"comment-item-avatar\" href=\"javascript:;\"><img src=\"${comment.avatar}\"></a><div class=\"comment-item-pmain\"><div class=\"comment-item-pheader\">${comment.name}</div><div class=\"comment-item-pcontent\" title=\"${message}\">${message}</div></div></div>`;\r\n target.insertAdjacentHTML('beforeend', parentHtml);\r\n }\r\n\r\n // 点选表情\r\n iDisqus.prototype.field = function (e, target) {\r\n var _ = this;\r\n var item = target;\r\n var form = item.closest('.comment-form');\r\n var textarea = form.querySelector('.comment-form-textarea');\r\n _.appendText(textarea, item.dataset.code);\r\n }\r\n\r\n // 显示回复框 or 取消回复框\r\n iDisqus.prototype.show = function (e, target) {\r\n var _ = this;\r\n\r\n var $this = target;\r\n var item = $this.closest('.comment-item');\r\n\r\n // 无论取消还是回复,移除已显示回复框\r\n var box = _.dom.querySelector('.comment-item .comment-box:not([data-current-id])');\r\n if (box) {\r\n var $show = box.closest('.comment-item');\r\n var cancel = $show.querySelector('.comment-item-cancel')\r\n cancel.outerHTML = cancel.outerHTML.replace('cancel', 'reply');\r\n box.outerHTML = '';\r\n }\r\n\r\n // 回复时,显示评论框\r\n if ($this.className == 'comment-item-reply') {\r\n $this.outerHTML = $this.outerHTML.replace('reply', 'cancel');\r\n var commentBox = _.box.replace(/emoji-input/g, 'emoji-input-' + item.dataset.id).replace(/upload-input/g, 'upload-input-' + item.dataset.id);\r\n item.querySelector('.comment-item-children').insertAdjacentHTML('beforebegin', commentBox);\r\n _.user.init();\r\n\r\n item.querySelector('.comment-form-textarea').focus();\r\n }\r\n\r\n }\r\n\r\n // 验证表单\r\n iDisqus.prototype.verify = function (e, target) {\r\n var _ = this;\r\n var $this = target;\r\n var box = $this.closest('.comment-box');\r\n var $avatar = box.querySelector('.comment-avatar-image');\r\n var $name = box.querySelector('.comment-form-name');\r\n var $email = box.querySelector('.comment-form-email');\r\n var alertmsg = box.querySelector('.comment-form-alert');\r\n if ($email.value == '') {\r\n return;\r\n }\r\n getAjax(\r\n _.opts.api + '/getgravatar.php?email=' + $email.value + '&name=' + $name.value,\r\n function (resp) {\r\n var data = JSON.parse(resp);\r\n if (!data.isEmail && $this == $email) {\r\n _.errorTips('您所填写的邮箱地址有误。', $email);\r\n }\r\n if ($name.value != '') {\r\n $avatar.src = data.gravatar;\r\n }\r\n }, function () {\r\n }\r\n );\r\n }\r\n\r\n // 添加文本\r\n iDisqus.prototype.appendText = function (textarea, text) {\r\n var _ = this;\r\n var selStart = textarea.selectionStart;\r\n var text = selStart == 0 ? text + ' ' : ' ' + text + ' ';\r\n textarea.value = textarea.value.slice(0, selStart) + text + textarea.value.slice(selStart);\r\n textarea.focus();\r\n textarea.setSelectionRange(selStart + text.length, selStart + text.length);\r\n }\r\n\r\n // 上传图片\r\n iDisqus.prototype.upload = function (e, target) {\r\n var _ = this;\r\n var file = target;\r\n var form = file.closest('.comment-form');\r\n var progress = form.querySelector('.comment-image-progress');\r\n var loaded = form.querySelector('.comment-image-loaded');\r\n var wrapper = form.querySelector('.comment-form-wrapper');\r\n var alertmsg = form.querySelector('.comment-form-alert');\r\n alertmsg.innerHTML = '';\r\n if (file.files.length === 0) {\r\n return;\r\n }\r\n\r\n // 以文件大小识别是否为同张图片\r\n var size = file.files[0].size;\r\n\r\n if (size > 5 * 1e6) {\r\n alertmsg.innerHTML = '请选择 5M 以下图片。';\r\n setTimeout(function () {\r\n alertmsg.innerHTML = '';\r\n }, 3000);\r\n return;\r\n }\r\n\r\n if (_.stat.imageSize.indexOf(size) == -1) {\r\n progress.style.width = '80px';\r\n } else {\r\n alertmsg.innerHTML = '请勿选择已存在的图片。';\r\n setTimeout(function () {\r\n alertmsg.innerHTML = '';\r\n }, 3000);\r\n return;\r\n }\r\n\r\n // 展开图片上传界面\r\n wrapper.classList.add('expanded');\r\n\r\n // 图片上传请求\r\n var data = new FormData();\r\n data.append('file', file.files[0]);\r\n var filename = file.files[0].name;\r\n\r\n var $item;\r\n\r\n var xhrUpload = new XMLHttpRequest();\r\n xhrUpload.withCredentials = true;\r\n xhrUpload.onreadystatechange = function () {\r\n if (xhrUpload.readyState == 4 && xhrUpload.status == 200) {\r\n var data = JSON.parse(xhrUpload.responseText);\r\n if (data.code == 0) {\r\n _.stat.imageSize.push(size);\r\n var imageUrl = data.response.thumbnailUrl;\r\n var textarea = form.querySelector('.comment-form-textarea');\r\n _.appendText(textarea, 'https:'+imageUrl);\r\n\r\n var image = new Image();\r\n image.src = imageUrl;\r\n image.onload = function () {\r\n $item.innerHTML = '<img class=\"comment-image-object\" src=\"https:' + imageUrl + '\">';\r\n $item.dataset.imageUrl = imageUrl;\r\n $item.classList.remove('loading');\r\n }\r\n } else {\r\n alertmsg.innerHTML = '图片上传出错。';\r\n $item.innerHTML = '';\r\n if (!!form.getElementsByClassName('comment-image-item').length) {\r\n wrapper.classList.remove('expanded');\r\n }\r\n setTimeout(function () {\r\n alertmsg.innerHTML = '';\r\n }, 3000);\r\n }\r\n }\r\n };\r\n xhrUpload.upload.addEventListener('progress', function (e) {\r\n loaded.style.width = Math.ceil((e.loaded / e.total) * 100) + '%';\r\n }, false);\r\n xhrUpload.upload.addEventListener('load', function (e) {\r\n loaded.style.width = 0;\r\n progress.style.width = 0;\r\n var imageItem = `<li class=\"comment-image-item loading\" data-image-size=\"${size}\">\r\n <svg version=\"1.1\" class=\"comment-image-object\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"24px\" height=\"30px\" viewBox=\"0 0 24 30\" style=\"enable-background: new 0 0 50 50;\" xml:space=\"preserve\">\r\n <rect x=\"0\" y=\"10\" width=\"4\" height=\"10\" fill=\"rgba(127,145,158,1)\" opacity=\"0.2\">\r\n <animate attributeName=\"opacity\" attributeType=\"XML\" values=\"0.2; 1; .2\" begin=\"0s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"height\" attributeType=\"XML\" values=\"10; 20; 10\" begin=\"0s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"y\" attributeType=\"XML\" values=\"10; 5; 10\" begin=\"0s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n </rect>\r\n <rect x=\"8\" y=\"10\" width=\"4\" height=\"10\" fill=\"rgba(127,145,158,1)\" opacity=\"0.2\">\r\n <animate attributeName=\"opacity\" attributeType=\"XML\" values=\"0.2; 1; .2\" begin=\"0.15s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"height\" attributeType=\"XML\" values=\"10; 20; 10\" begin=\"0.15s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"y\" attributeType=\"XML\" values=\"10; 5; 10\" begin=\"0.15s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n </rect>\r\n <rect x=\"16\" y=\"10\" width=\"4\" height=\"10\" fill=\"rgba(127,145,158,1)\" opacity=\"0.2\">\r\n <animate attributeName=\"opacity\" attributeType=\"XML\" values=\"0.2; 1; .2\" begin=\"0.3s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"height\" attributeType=\"XML\" values=\"10; 20; 10\" begin=\"0.3s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n <animate attributeName=\"y\" attributeType=\"XML\" values=\"10; 5; 10\" begin=\"0.3s\" dur=\"0.6s\" repeatCount=\"indefinite\" />\r\n </rect>\r\n </svg>\r\n </li>`;\r\n form.querySelector('.comment-image-list').insertAdjacentHTML('beforeend', imageItem);\r\n $item = form.querySelector('[data-image-size=\"' + size + '\"]');\r\n }, false);\r\n xhrUpload.open('POST', _.opts.api + '/media.php', true);\r\n xhrUpload.send(data);\r\n }\r\n\r\n // 移除图片\r\n iDisqus.prototype.remove = function (e) {\r\n var _ = this;\r\n var $item = e.currentTarget.closest('.comment-image-item');\r\n var wrapper = e.currentTarget.closest('.comment-form-wrapper');\r\n $item.outerHTML = '';\r\n _.stat.imageSize = [];\r\n var imageArr = wrapper.getElementsByClassName('comment-image-item');\r\n [].forEach.call(imageArr, function (item, i) {\r\n _.stat.imageSize[i] = item.dataset.imageSize;\r\n });\r\n if (_.stat.imageSize.length == 0) {\r\n wrapper.classList.remove('expanded');\r\n }\r\n wrapper.querySelector('.comment-image-input').value = '';\r\n }\r\n\r\n // 错误提示\r\n iDisqus.prototype.errorTips = function (Text, Dom) {\r\n var _ = this;\r\n if (_.user.logged_in == 'true') {\r\n _.handle.logout();\r\n }\r\n var idisqus = _.dom.querySelector('#idisqus');\r\n var errorDom = _.dom.querySelector('.comment-form-error');\r\n if (!!errorDom) {\r\n errorDom.outerHTML = '';\r\n }\r\n var Top = Dom.offsetTop;\r\n var Left = Dom.offsetLeft;\r\n var errorHtml = '<div class=\"comment-form-error\" style=\"top:' + Top + 'px;left:' + Left + 'px;\">' + Text + '</div>';\r\n idisqus.insertAdjacentHTML('beforeend', errorHtml);\r\n setTimeout(function () {\r\n var errorDom = _.dom.querySelector('.comment-form-error');\r\n if (!!errorDom) {\r\n errorDom.outerHTML = '';\r\n }\r\n }, 3000);\r\n }\r\n\r\n // 发表/回复评论\r\n iDisqus.prototype.post = function (e, target) {\r\n var _ = this;\r\n var item = target.closest('.comment-box[data-current-id]') || target.closest('.comment-item') || target.closest('.comment-box');\r\n var message = item.querySelector('.comment-form-textarea').value;\r\n var parentId = !!item.dataset.id ? item.dataset.id : '';\r\n var imgArr = item.getElementsByClassName('comment-image-item');\r\n\r\n // 不是编辑框需预览\r\n if (!item.dataset.currentId) {\r\n var elName = item.querySelector('.comment-form-name');\r\n var elEmail = item.querySelector('.comment-form-email');\r\n var elUrl = item.querySelector('.comment-form-url');\r\n var alertmsg = item.querySelector('.comment-form-alert');\r\n var alertClear = function () {\r\n setTimeout(function () {\r\n alertmsg.innerHTML = '';\r\n }, 3000);\r\n }\r\n\r\n if (_.user.type != '1') {\r\n var anonName = elName.value;\r\n var anonEmail = elEmail.value;\r\n var anonUrl = elUrl.value.replace(/\\s/g, '');\r\n if (/^\\s*$/i.test(anonName)) {\r\n _.errorTips('名字不能为空或空格。', elName);\r\n return;\r\n }\r\n if (/^\\s*$/i.test(anonEmail)) {\r\n _.errorTips('邮箱不能为空或空格。', elEmail);\r\n return;\r\n }\r\n if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i.test(anonEmail)) {\r\n _.errorTips('请正确填写邮箱。', elEmail);\r\n return;\r\n }\r\n if (!/^([hH][tT]{2}[pP]:\\/\\/|[hH][tT]{2}[pP][sS]:\\/\\/)(([A-Za-z0-9-~]+)\\.)+([A-Za-z0-9-~\\/])+$|^\\s*$/i.test(anonUrl)) {\r\n _.errorTips('请正确填写网址。', elUrl);\r\n return;\r\n }\r\n _.user.unique = _.user.email == anonEmail ? _.user.unique : generateGUID();\r\n _.user.name = anonName;\r\n _.user.email = anonEmail;\r\n _.user.url = anonUrl;\r\n _.user.avatar = item.querySelector('.comment-avatar-image').src;\r\n _.user.submit();\r\n\r\n if (!_.user.name && !_.user.email) {\r\n return;\r\n }\r\n }\r\n\r\n if (!_.stat.message && !_.stat.mediaHtml) {\r\n _.box = _.dom.querySelector('.comment-box').outerHTML.replace('comment-form-wrapper', 'comment-form-wrapper editing').replace(/加入讨论……/, '');\r\n }\r\n\r\n if (/^\\s*$/i.test(message)) {\r\n alertmsg.innerHTML = '评论不能为空或空格。';\r\n item.querySelector('.comment-form-textarea').focus();\r\n return;\r\n };\r\n\r\n var preMessage = message;\r\n\r\n if (!!_.opts.emoji_preview) {\r\n preMessage = preMessage.replace(/:([-+\\w]+):/g, function (match) {\r\n var emojiShort = match.replace(/:/g, '');\r\n var emojiImage = !!_.eac[emojiShort] ? `<img class=\"emojione\" width=\"24\" height=\"24\" alt=\"'+emojiShort+'\" title=\":${emojiShort}:\" src=\"${_.opts.emojiPath + _.eac[emojiShort]}.png\">` : match;\r\n return emojiImage;\r\n });\r\n } else {\r\n _.emojiList.forEach(function (item) {\r\n preMessage = preMessage.replace(`:${item.code}:`, `<img class=\"emojione\" width=\"24\" height=\"24\" src=\"${_.opts.emojiPath + item.unicode}.png\" />`);\r\n });\r\n }\r\n\r\n var post = {\r\n 'url': !!_.user.url ? _.user.url : '',\r\n 'isMod': false,\r\n 'username': null,\r\n 'name': _.user.name,\r\n 'avatar': _.user.avatar,\r\n 'id': 'preview',\r\n 'parent': parentId,\r\n 'createdAt': (new Date()).toJSON(),\r\n 'message': '<p>' + preMessage + '</p>',\r\n };\r\n\r\n _.load(post);\r\n\r\n _.timeAgo();\r\n\r\n // 清空或移除评论框\r\n _.stat.message = message;\r\n _.stat.mediaHtml = item.querySelector('.comment-image-list').innerHTML;\r\n\r\n if (parentId) {\r\n item.querySelector('.comment-item-cancel').click();\r\n } else {\r\n item.querySelector('.comment-form-textarea').value = '';\r\n item.querySelector('.comment-image-list').innerHTML = '';\r\n item.querySelector('.comment-form-wrapper').classList.remove('expanded', 'editing');\r\n }\r\n }\r\n\r\n // @\r\n var mentions = message.match(/@\\w+/g);\r\n if (!!mentions) {\r\n mentions = mentions.filter(function (mention) {\r\n return _.stat.users.map(function (user) { return user.username; }).indexOf(mention.slice(1)) > -1;\r\n });\r\n if (mentions.length > 0) {\r\n var re = new RegExp('(' + mentions.join('|') + ')', 'g');\r\n message = message.replace(re, '$1:disqus');\r\n }\r\n }\r\n\r\n // POST 操作\r\n // 编辑框则更新评论\r\n if (!!item.dataset.currentId) {\r\n var postData = {\r\n id: item.dataset.currentId,\r\n message: message,\r\n unique: _.user.unique\r\n }\r\n postAjax(_.opts.api + '/updatecomment.php', postData, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code === 0) {\r\n _.stat.message = null;\r\n _.stat.mediaHtml = null;\r\n var post = data.response;\r\n _.load(post);\r\n _.timeAgo();\r\n _.stat.editing = false;\r\n } else {\r\n // 取消编辑\r\n _.load(_.stat.editing)\r\n _.timeAgo();\r\n _.stat.editing = false;\r\n }\r\n }, function () {\r\n // 取消编辑\r\n _.load(_.stat.editing)\r\n _.timeAgo();\r\n _.stat.editing = false;\r\n })\r\n } else {\r\n var postData = {\r\n thread: _.stat.thread.id,\r\n parent: parentId,\r\n message: message,\r\n name: _.user.name,\r\n email: _.user.email,\r\n url: _.user.url,\r\n unique: _.user.unique\r\n }\r\n postAjax(_.opts.api + '/postcomment.php', postData, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code === 0) {\r\n _.dom.querySelector('.comment-item[data-id=\"preview\"]').outerHTML = '';\r\n _.stat.thread = data.thread;\r\n _.stat.thread.posts = parseInt(_.dom.querySelector('#comment-count').innerHTML) + 1;\r\n _.dom.querySelector('#comment-count').innerHTML = _.stat.thread.posts + ' 条评论';\r\n var post = data.response;\r\n post.isPost = true;\r\n _.load(post);\r\n _.timeAgo();\r\n var postData = {\r\n post: JSON.stringify(post),\r\n thread: JSON.stringify(_.stat.thread),\r\n parent: JSON.stringify(_.stat.post[parentId]),\r\n code: data.verifyCode\r\n }\r\n if (!!data.verifyCode) {\r\n // 异步发送邮件\r\n postAjax(_.opts.api + '/sendemail.php', postData, function (resp) {\r\n console.info('邮件发送成功!');\r\n })\r\n }\r\n } else if (data.code === 2) {\r\n alertmsg.innerHTML = data.response;\r\n _.dom.querySelector('.comment-item[data-id=\"preview\"]').outerHTML = '';\r\n _.reEdit(item);\r\n\r\n if (data.response.indexOf('author') > -1) {\r\n _.handle.logout();\r\n }\r\n } else {\r\n alertmsg.innerHTML = '提交失败,请稍后重试,错误代码:' + data.code;\r\n alertClear();\r\n\r\n _.dom.querySelector('.comment-item[data-id=\"preview\"]').outerHTML = '';\r\n _.reEdit(item);\r\n }\r\n\r\n }, function () {\r\n alertmsg.innerHTML = '提交出错,请稍后重试。';\r\n alertClear();\r\n\r\n _.dom.querySelector('.comment-item[data-id=\"preview\"]').outerHTML = '';\r\n _.reEdit(item);\r\n })\r\n }\r\n }\r\n\r\n // 重新编辑\r\n iDisqus.prototype.reEdit = function (item) {\r\n var _ = this;\r\n\r\n if (!!item.dataset.id) {\r\n item.querySelector('.comment-item-reply').click();\r\n } else {\r\n item.querySelector('.comment-form-wrapper').classList.add('editing');\r\n }\r\n\r\n // 重新填充文本图片\r\n if (!!_.stat.message) {\r\n item.querySelector('.comment-form-textarea').value = _.stat.message;\r\n }\r\n if (!!_.stat.mediaHtml) {\r\n item.querySelector('.comment-form-wrapper').classList.add('expanded');\r\n item.querySelector('.comment-image-list').innerHTML = _.stat.mediaHtml;\r\n }\r\n }\r\n\r\n // 编辑\r\n iDisqus.prototype.edit = function (post) {\r\n var _ = this;\r\n var commentBox = _.box.replace('comment-box', 'comment-box comment-box-' + post.id).replace(/emoji-input/g, 'emoji-input-' + post.id).replace(/upload-input/g, 'upload-input-' + post.id);\r\n var $this = _.dom.querySelector('.comment-item[data-id=\"' + post.id + '\"] .comment-item-body');\r\n $this.outerHTML = commentBox;\r\n _.user.init();\r\n var item = _.dom.querySelector('.comment-box-' + post.id);\r\n item.dataset.currentId = post.id;\r\n item.querySelector('.comment-form-textarea').focus();\r\n\r\n // 取消编辑\r\n item.querySelector('.comment-actions-form').insertAdjacentHTML('afterbegin', '<a class=\"comment-form-cancel\" href=\"javascript:;\">取消</a>')\r\n item.querySelector('.comment-form-cancel').addEventListener('click', function () {\r\n _.stat.editing = false;\r\n _.load(post);\r\n _.timeAgo();\r\n }, false);\r\n\r\n // 重新填充文本图片,连续回复、连续编辑会有 bug\r\n if (!!_.stat.message) {\r\n item.querySelector('.comment-form-textarea').value = _.stat.message;\r\n }\r\n if (!!_.stat.mediaHtml) {\r\n item.querySelector('.comment-form-wrapper').classList.add('expanded');\r\n item.querySelector('.comment-image-list').innerHTML = _.stat.mediaHtml;\r\n }\r\n\r\n }\r\n\r\n // Thread 初始化\r\n iDisqus.prototype.threadInit = function (e, target) {\r\n var _ = this;\r\n _.dom.querySelector('#idisqus').style.display = 'block';\r\n _.dom.querySelector('#disqus_thread').style.display = 'none';\r\n getAjax(_.opts.api + '/threadsDetails.php?ident=' + _.opts.identifier + '&link=' + _.opts.url, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code == 0) {\r\n _.stat.thread = data.response;\r\n _.stat.forum = data.forum;\r\n _.dom.querySelector('#comment-link').href = `https://disqus.com/home/discussion/${_.stat.forum.id}/${_.stat.thread.slug}/?l=zh`;\r\n _.dom.querySelector('.comment-avatar-image').dataset.avatar = _.stat.forum.avatar;\r\n _.dom.querySelector('.comment-recommend-count').innerHTML = _.stat.thread.likes || '';\r\n if (_.stat.forum.settings.mediaembedEnabled == false) {\r\n _.dom.querySelector('.comment-image-input').outerHTML = ''\r\n _.dom.querySelector('[for=\"upload-input\"]').outerHTML = ''\r\n }\r\n if (_.user.logged_in == 'false') {\r\n _.dom.querySelector('.comment-avatar-image').src = _.stat.forum.avatar;\r\n }\r\n _.box = _.dom.querySelector('.comment-box').outerHTML.replace(/<label class=\"comment-actions-label exit\"(.|\\n)*<\\/label>\\n/, '').replace('comment-form-wrapper', 'comment-form-wrapper editing').replace(/加入讨论……/, '');\r\n _.opts.badge = _.stat.forum.moderatorBadgeText;\r\n if (!_.stat.order) {\r\n switch (_.stat.forum.order) {\r\n case 1:\r\n _.stat.order = 'asc';\r\n break;\r\n case 2:\r\n _.stat.order = 'desc';\r\n break;\r\n case 4:\r\n _.stat.order = 'popular';\r\n break;\r\n }\r\n }\r\n _.dom.querySelector('.comment-order-radio[value=\"' + _.stat.order + '\"]').checked = true;\r\n\r\n var users = data.votedusers;\r\n var vote = 0;\r\n if (_.user.type == 1) {\r\n // 已登录\r\n vote = users.filter(function (user) {\r\n return user.username == _.user.username;\r\n }).length > 0 ? 1 : 0;\r\n } else {\r\n // 未登录\r\n vote = !!_.user.vote[_.stat.thread.id] ? 1 : 0;;\r\n }\r\n _.user.vote[_.stat.thread.id] = vote;\r\n l.setItem('vote', JSON.stringify(_.user.vote));\r\n if (!!vote) {\r\n _.dom.querySelector('.comment-recommend').classList.add('voted');\r\n _.dom.querySelector('.comment-recommend-text').innerHTML = '已推荐';\r\n }\r\n _.dom.querySelector('#idisqus').classList.remove('init')\r\n _.loadRelated();\r\n _.loadReactions();\r\n _.dom.querySelector('#comment-count').innerHTML = _.stat.thread.posts + ' 条评论';\r\n _.getlist();\r\n } else if (data.code === 2) {\r\n // 自动创建\r\n if (_.opts.autoCreate) {\r\n _.dom.querySelector('.init-container').dataset.tips = '正在创建 Thread……';\r\n var postData = {\r\n url: _.opts.link,\r\n identifier: _.opts.identifier,\r\n title: _.opts.title,\r\n slug: _.opts.slug,\r\n message: _.opts.desc\r\n }\r\n _.threadCreate(postData);\r\n return;\r\n }\r\n _.dom.querySelector('#idisqus').classList.remove('init');\r\n var threadForm = `<div class=\"comment-header\"><span class=\"comment-header-item\">创建 Thread</span></div>\r\n <div class=\"comment-thread-form\">\r\n <p>由于 Disqus 没有本页面的相关 Thread,故需先创建 Thread</p>\r\n <div class=\"comment-form-item\"><label class=\"comment-form-label\">url:</label><input class=\"comment-form-input\" id=\"thread-url\" name=\"url\" value=\"${ _.opts.link}\" disabled /></div>\r\n <div class=\"comment-form-item\"><label class=\"comment-form-label\">identifier:</label><input class=\"comment-form-input\" id=\"thread-identifier\" name=\"identifier\" value=\"${ _.opts.identifier}\" disabled /></div>\r\n <div class=\"comment-form-item\"><label class=\"comment-form-label\">title:</label><input class=\"comment-form-input\" id=\"thread-title\" name=\"title\" value=\"${ _.opts.title}\" disabled /></div>\r\n <div class=\"comment-form-item\"><label class=\"comment-form-label\">slug:</label><input class=\"comment-form-input\" id=\"thread-slug\" name=\"slug\" value=\"${ _.opts.slug}\" /></div>\r\n <div class=\"comment-form-item\"><label class=\"comment-form-label\">message:</label><textarea class=\"comment-form-textarea\" id=\"thread-message\" name=\"message\">${ _.opts.desc}</textarea></div>\r\n <button id=\"thread-submit\" class=\"comment-form-submit\">提交</button></div>`;\r\n _.dom.querySelector('#idisqus').innerHTML = threadForm;\r\n }\r\n }, function () { })\r\n }\r\n\r\n // Thread 打分事件\r\n iDisqus.prototype.threadVote = function (e, target) {\r\n var _ = this;\r\n var vote = !!_.user.vote[_.stat.thread.id] ? 0 : 1;\r\n var postData = {\r\n thread: _.stat.thread.id,\r\n unique: _.user.unique,\r\n vote: vote\r\n }\r\n postAjax(_.opts.api + '/threadsVote.php', postData, function (resp) {\r\n _.user.vote[_.stat.thread.id] = vote;\r\n l.setItem('vote', JSON.stringify(_.user.vote));\r\n if (!!vote) {\r\n _.dom.querySelector('.comment-recommend').classList.add('voted');\r\n _.stat.thread.likes++;\r\n } else {\r\n _.dom.querySelector('.comment-recommend').classList.remove('voted');\r\n _.stat.thread.likes = _.stat.thread.likes == 0 ? 0 : _.stat.thread.likes - 1;\r\n }\r\n _.dom.querySelector('.comment-recommend-count').innerHTML = _.stat.thread.likes || '';\r\n })\r\n }\r\n\r\n // Thread Create 事件\r\n iDisqus.prototype.threadCreate = function (e, target) {\r\n var _ = this;\r\n if (!!target) {\r\n var postData = {\r\n url: _.dom.querySelector('#thread-url').value,\r\n identifier: _.dom.querySelector('#thread-identifier').value,\r\n title: _.dom.querySelector('#thread-title').value,\r\n slug: _.dom.querySelector('#thread-slug').value.replace(/[^A-Za-z0-9_-]+/g, ''),\r\n message: _.dom.querySelector('#thread-message').value\r\n }\r\n } else {\r\n var postData = arguments[0];\r\n }\r\n postAjax(_.opts.api + '/createthread.php', postData, function (resp) {\r\n var data = JSON.parse(resp);\r\n if (data.code === 0) {\r\n alert('创建 Thread 成功,刷新后便可愉快地评论了!');\r\n setTimeout(function () { location.reload(); }, 2000);\r\n } else if (data.code === 2) {\r\n if (data.response.indexOf('A thread already exists with link') > -1) {\r\n alert(data.response.replace('A thread already exists with link,', '已存在此链接的相关 Thread,'));\r\n return;\r\n }\r\n if (data.response.indexOf('Invalid URL') > -1) {\r\n alert('参数错误,无效的\\'URL\\'');\r\n return;\r\n }\r\n if (data.response.indexOf('Invalid slug') > -1) {\r\n alert('参数错误,无效的\\'slug\\'');\r\n return;\r\n }\r\n alert(data.response);\r\n return;\r\n } else {\r\n alert(data.response);\r\n return;\r\n }\r\n }, function () {\r\n alert('创建 Thread 出错,请稍后重试!');\r\n })\r\n }\r\n\r\n // 销毁评论框\r\n iDisqus.prototype.destroy = function () {\r\n var _ = this;\r\n _.dom.innerHTML = '';\r\n delete _.dom;\r\n delete _.box;\r\n delete _.emojiList;\r\n delete _.user;\r\n delete _.handle;\r\n delete _.stat;\r\n delete _.opts;\r\n }\r\n\r\n /* CommonJS */\r\n if ( true && module && typeof exports === 'object' && exports)\r\n module.exports = iDisqus;\r\n /* AMD */\r\n else if (true)\r\n !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {\r\n return iDisqus;\r\n }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n /* Global */\r\n else\r\n {}\r\n\r\n})(window || this);\r\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../node_modules/webpack/buildin/module.js */ \"./node_modules/webpack/buildin/module.js\")(module)))\n\n//# sourceURL=webpack://%5Bname%5D/./src/iDisqus.js?"); + +/***/ }), + +/***/ "./src/iDisqus.scss": +/*!**************************!*\ + !*** ./src/iDisqus.scss ***! + \**************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("\nvar content = __webpack_require__(/*! !../node_modules/css-loader/dist/cjs.js!../node_modules/postcss-loader/src??ref--4-2!../node_modules/sass-loader/dist/cjs.js!./iDisqus.scss */ \"./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js!./src/iDisqus.scss\");\n\nif(typeof content === 'string') content = [[module.i, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = __webpack_require__(/*! ../node_modules/style-loader/lib/addStyles.js */ \"./node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(false) {}\n\n//# sourceURL=webpack://%5Bname%5D/./src/iDisqus.scss?"); + +/***/ }) + +/******/ }); +});
\ No newline at end of file |