V2EXcellent.js

A Better V2EX

当前为 2017-05-29 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           V2EXcellent.js
// @namespace      http://vitovan.github.io/v2excellent.js/
// @version        1.1.1
// @description    A Better V2EX
// @author         VitoVan
// @include        http*://*v2ex.com/*
// @grant          none
// ==/UserScript==

var currentLocation = location.href;
//If this is the thread page
if (currentLocation.match(/\/t\/\d+/g)) {
  //Enable Reply Directly Feature
  $('div.topic_buttons').append('<a " href="#;" onclick="$(\'#reply_content\').focus();" class="tb">回复</a>');
  //Enable Img Uploader Feature
  enableUploadImg();
  var comments = [];
  //loading
  showSpinner();
  //Get comments from current page
  fillComments($('body'));
  //Get other pages comments
  var CURRENT_PAGE_URLS = [];
  $('a[href].page_normal').each(function (i, o) {
    if (CURRENT_PAGE_URLS.indexOf(o.href) === -1) {
      CURRENT_PAGE_URLS.push(o.href);
    }
  });
  var LEFT_PAGES_COUNT = CURRENT_PAGE_URLS.length;
  var CURRENT_PAGE = 0;
  var DOMS = [$(document)];
  if (LEFT_PAGES_COUNT>0) {
    $(CURRENT_PAGE_URLS).each(function(i,o) {
      $.get(o,function(result) {
        var resultDom = $('<output>').append($.parseHTML(result));
        DOMS.push(resultDom);
        fillComments(resultDom);
        CURRENT_PAGE ++;
        //if all comments are sucked.
        if (CURRENT_PAGE === LEFT_PAGES_COUNT) {
          //stack'em
          stackComments();
          //reArrange
          reArrangeComments();
        }
      });
    });
  }else{
    stackComments();
    //reArrange
    reArrangeComments();
  }
  // Clear Default Pager
  $('a[href^="?p="]').parents('div.cell').remove();
}else if (currentLocation.match(/\/new/)) {
  $('<a href="https://imgur.com/upload" target="_blank" style="padding:0 5px;">上传图片</a>')
    .insertAfter($('button[onclick="previewTopic();"]'))
}

function jumpToReply () {
  var floorSpecArr = currentLocation.match(/#reply\d+/g);
  var floorSpec = floorSpecArr && floorSpecArr.length ? floorSpecArr[0] : false;
  if (floorSpec) {
    floorSpec = floorSpec.match(/\d+/g)[0];
    var specFloor = $('span.no').filter(function () {return $(this).text() === floorSpec;});
    $('body').scrollTop(specFloor.offset().top - $('body').offset().top);
  }
}

//Remove #reply42 from index
$('span.item_title>a').attr("href",function (i,val) {return val.replace(/#reply\d+/g,'');});

function fillComments (jqDom) {
  jqDom.find('div[id^="r_"]').each(function (i,o) {
    var cmno = parseInt($(o).find('span.no').text());
    comments[cmno] =
      {
        id: $(o).attr('id'),
        no: cmno,
        user: $(o).find('strong>a').text(),
        content: $(o).find('div.reply_content').text(),
        mentioned: (function () {
          var mentionedNames = [];
          $(o)
            .find('div.reply_content>a[href^="/member/"]:not("dark")')
            .each(function (i,o) {
              mentionedNames.push(o.innerHTML);
            });
          return mentionedNames;
        }()),
        subComments: []
      };
  });
}

//Enable Floor Specification Feature
$('a[href="#;"]:has(img[alt="Reply"])').click(function (e) {
  var floorNo = $(e.currentTarget).parent().find('span.no').text();
  replyContent = $("#reply_content");
  oldContent = replyContent.val().replace(/^#\d+ /g,'');
  postfix = " " + "#" + floorNo + " ";
  newContent = ''
  if (oldContent.length > 0) {
    if (oldContent != postfix) {
      newContent = oldContent + postfix;
    }
  } else {
    newContent = postfix;
  }
  replyContent.focus();
  replyContent.val(newContent);
  moveEnd($("#reply_content"));
});

//Enable Gift ClickOnce Feature
$('a[href="/mission/daily"]').attr('id','gift_v2excellent').attr('href','#').click(function () {
  $('#gift_v2excellent').text('正在领取......');
  $.get('/mission/daily',function (result) {
    var giftLink = $('<output>')
      .append($.parseHTML(result))
      .find('input[value^="领取"]')
      .attr('onclick').match(/\/mission\/daily\/redeem\?once=\d+/g)[0];
    $.get(giftLink,function (checkResult) {
      var okSign = $('<output>').append($.parseHTML(checkResult)).find('li.fa.fa-ok-sign');
      if (okSign.length>0) {
        $.get('/balance',function (result) {
          var amount = $('<output>').append($.parseHTML(result)).find('table>tbody>tr:contains("每日登录"):first>td:nth(2)').text();
          $('#gift_v2excellent').html('已领取 <strong>' + amount + '</strong> 铜币。' );
          setTimeout(function () {
            $('#Rightbar>.sep20:nth(1)').remove();
            $('#Rightbar>.box:nth(1)').remove();
          },2000);
        });
      }
    });
  });
  return false;
});

//Get comment's parent
function findParentComment (comment) {
  var parent = undefined;
  if (comment) {
    var floorRegex = comment.content.match(/#\d+ /g);
    if (floorRegex && floorRegex.length>0) {
      var floorNo = parseInt(floorRegex[0].match(/\d+/g)[0]);
      parent = comments[floorNo];
    }else{
      for(var i=comment.no-1;i>0;i--) {
        var cc = comments[i];
        if (cc) {
          if ($.inArray(cc.user, comment.mentioned) !== -1 && parent === undefined) {
            parent = cc;
          }
          //If they have conversation, then make them together.
          if (comment.mentioned.length>0 && cc.user === comment.mentioned[0] && cc.mentioned[0] === comment.user) {
            parent = cc;
            break;
          }
        }
      }
    }
  }
  return parent;
}

//Stack comments, make it a tree
function stackComments () {
  for(var i=comments.length-1;i>0;i--) {
    var parent = findParentComment(comments[i]);
    if (parent) {
      parent.subComments.unshift(comments[i]);
      comments.splice(i,1);
    }
  }
}

function getCommentDom (id) {
  var commentDom = undefined;
  $.each(DOMS,function (i,o) {
    var result = o.find('div[id="' + id + '"]');
    if (result.length>0) {
      commentDom = result;
    }
  });
  return commentDom;
}

function moveComment (comment,parent) {
  if (comment) {
    var commentDom = getCommentDom(comment.id);
    $.each(comment.subComments,function (i,o) {
      moveComment(o,commentDom);
    });
    commentDom.appendTo(parent);
  }
}

function getCommentBox () {
  var commentBox = $('#Main>div.box:nth(1)');
  if (commentBox.length === 0) { // Maybe using mobile
    commentBox = $('#Wrapper>div.content>div.box:nth(1)');
    if ($('#v2excellent-mobile-tip').length === 0) {
      $('<div class="cell" id="v2excellent-mobile-tip" style="background: #CC0000;font-weight: bold;text-align: center;"><span><a style="color:white;text-decoration:underline;" target="_blank" href="https://github.com/VitoVan/v2excellent.js/issues/7#issuecomment-304674654">About V2EXcellent.js on Mobile</a></span></div>').insertBefore('#Wrapper>div.content>div.box:nth(1)>.cell:first');
    }
  }
  return commentBox;
};

function showSpinner () {
  var commentBox = getCommentBox();
  $('body').append('<style>.spinner{width:40px;height:40px;position:relative;margin:100px auto}.double-bounce1,.double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#333;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-bounce 2.0s infinite ease-in-out;animation:sk-bounce 2.0s infinite ease-in-out}.double-bounce2{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}@-webkit-keyframes sk-bounce{0%,100%{-webkit-transform:scale(0.0)}50%{-webkit-transform:scale(1.0)}}@keyframes sk-bounce{0%,100%{transform:scale(0.0);-webkit-transform:scale(0.0)}50%{transform:scale(1.0);-webkit-transform:scale(1.0)}}</style>');
  $('<div class="spinner"><div class="double-bounce1"></div><div class="double-bounce2"></div></div>').insertBefore(commentBox);
  commentBox.hide();
}

function reArrangeComments () {
  $('div.inner:has(a[href^="/t/"].page_normal)').remove();
  var commentBox = getCommentBox();
  $.each(comments,function (i,o) {
    moveComment(o,commentBox);
  });
  $('div[id^="r_"]>table>tbody>tr>td:first-child').attr('width','20');
  $('body').append('<style>.cell{background-color: inherit;}.cell .cell{border-bottom:none;min-width: 250px;}div[id^="r_"] img.avatar{width:20px;height:20px;border-radius:50%;}div[id^="r_"]>div{margin-left: 5px;}</style>');
  commentBox.show();
  //removeSpinner
  $('.spinner').remove();
  jumpToReply();
}

function enableUploadImg () {
  $('div.cell:contains("添加一条新回复")').append('<div class="fr"><a href="https://imgur.com/upload" target="_blank"> 上传图片</a> - </div>');
}