Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zhaohuabing/hugo-theme-cleanwhite.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'static/js/iDisqus.js')
-rw-r--r--static/js/iDisqus.js1769
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