SmartNicorepo

ニコレポの「投稿」以外をデフォルトで折りたたむ & お気に入りユーザーに最終更新を表示

当前为 2015-10-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name SmartNicorepo
  3. // @namespace https://github.com/segabito/
  4. // @description ニコレポの「投稿」以外をデフォルトで折りたたむ & お気に入りユーザーに最終更新を表示
  5. // @include http://www.nicovideo.jp/my/*
  6. // @include http://www.nicovideo.jp/user/*
  7. // @include http://www.nicovideo.jp/my/fav/user
  8. // @include http://www.nicovideo.jp/mylist/*
  9. // @version 2.3.1
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. var monkey =
  15. (function() {
  16. var $ = window.jQuery;
  17.  
  18. function addStyle(styles, id) {
  19. var elm = document.createElement('style');
  20. elm.type = 'text/css';
  21. if (id) { elm.id = id; }
  22.  
  23. var text = styles.toString();
  24. text = document.createTextNode(text);
  25. elm.appendChild(text);
  26. var head = document.getElementsByTagName('head');
  27. head = head[0];
  28. head.appendChild(elm);
  29. return elm;
  30. }
  31.  
  32. var __nicorepocss__ = (function() {/*
  33. .nicorepo .log.log-user-video-upload {
  34. background: #ffe;
  35. }
  36. .nicorepo .log.log-user-video-upload .log-target-thumbnail ,.nicorepo .log.log-user-seiga-image-upload .log-target-thumbnail {
  37. width: auto; margin-left: -30px;
  38. }
  39. .nicorepo .log.log-user-video-upload .video , .nicorepo .log.log-user-seiga-image-upload .seiga_image {
  40. height: auto !important; width: 130px !important; margin-top: 0px;
  41. margin-bottom: 0 !important; margin-left: 0 !important;
  42. }
  43. #nicorepo .timeline > .log {
  44. max-height: 500px;
  45. transition: max-height 0.4s ease-in-out;
  46. }
  47. #nicorepo.show-upload-only .timeline > .log:not(.log-user-video-upload):not(.log-user-seiga-image-upload):not(.log-user-register-chblog) {
  48. max-height: 22px;
  49. overflow: hidden;
  50. }
  51. #nicorepo .timeline > .log:not(.log-user-video-upload):not(.log-user-seiga-image-upload):not(.log-user-register-chblog):hover {
  52. max-height: 500px;
  53. overflow: hidden;
  54. transition: max-height 0.4s ease-in-out 0.8s;
  55. }
  56. .toggleUpload {
  57. position: absolute; top: 32px; right: 32px; font-weight: bolder; cursor: pointer; color: #888; padding: 8px;
  58. z-index: 1000;
  59. box-shadow: 2px 2px 2px #333;
  60. }
  61. .toggleUpload.bottom {
  62. top: auto; right: 32px; bottom: 32px;
  63. }
  64. .show-upload-only .toggleUpload {
  65. color: red;
  66. }
  67. .toggleUpload:after {
  68. content: ': OFF';
  69. }
  70. .show-upload-only .toggleUpload:after {
  71. content: ': ON';
  72. }
  73.  
  74. .togglePagerize {
  75. position: fixed;
  76. bottom: 0;
  77. right: 0;
  78. color: #888;
  79. font-weight: bolder;
  80. cursor: pointer;
  81. border: 2px solid #666;
  82. }
  83. .togglePagerize.enable {
  84. color: red;
  85. }
  86. .togglePagerize:after {
  87. content: ': OFF';
  88. }
  89. .togglePagerize.enable:after {
  90. content: ': ON';
  91. }
  92.  
  93. */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/');
  94.  
  95. var __favusercss__ = (function() {/*
  96.  
  97. #favUser .outer.updating {
  98. }
  99. #favUser .outer.updating * {
  100. cursor: wait;
  101. }
  102. #favUser .outer.done .showNicorepo {
  103. display: none;
  104. }
  105.  
  106. #favUser .nicorepo {
  107. color: #800;
  108. clear: both;
  109. margin-bottom: 24px;
  110. }
  111. #favUser .uploadVideoList, #favUser .seigaUserPage {
  112. font-size: 80%;
  113. margin-left: 16px;
  114. }
  115.  
  116. #favUser .nicorepo.fail {
  117. color: #800;
  118. clear: both;
  119. margin-left: 64px;
  120. }
  121.  
  122.  
  123. #favUser .nicorepo.success {
  124. padding: 8px;
  125. overflow: auto;
  126. border: 1px inset;
  127. max-height: 300px;
  128. }
  129.  
  130. .nicorepo .log-target-thumbnail,
  131. .nicorepo .log-target-info {
  132. display: inline-block;
  133. vertical-align: middle;
  134. }
  135. .nicorepo .log-target-thumbnail .imageContainer {
  136. width: 64px;
  137. height: 48px;
  138. background-color: #fff;
  139. background-size: contain;
  140. background-repeat: no-repeat;
  141. background-position: center;
  142. transition: 0.2s width ease 0.4s, 0.2s height ease 0.4s;
  143. }
  144. .nicorepo .log-target-thumbnail .imageContainer:hover {
  145. width: 128px;
  146. height: 96px;
  147. }
  148. .nicorepo .log-target-info .time {
  149. display: block;
  150. font-size: 80%;
  151. color: black;
  152. }
  153. .nicorepo .log-target-info .logComment {
  154. display: block;
  155. font-size: 80%;
  156. color: black;
  157. }
  158. .nicorepo .log-target-info .logComment:before {
  159. content: '「';
  160. }
  161. .nicorepo .log-target-info .logComment:after {
  162. content: '」';
  163. }
  164. .nicorepo .log-target-info a {
  165. display: inline-block;
  166. min-width: 100px;
  167. }
  168. .nicorepo .log-target-info a:hover {
  169. background: #ccf;
  170. }
  171.  
  172.  
  173. .nicorepo .log.log-user-video-round-number-of-view-counter {
  174. display: none;
  175. }
  176.  
  177. .nicorepo .log-content {
  178. margin: 4px 8px;
  179. position: relative;
  180. }
  181. .nicorepo .log-footer {
  182. position: absolute;
  183. top: 0;
  184. left: 138px;
  185. }
  186. .nicorepo .log-footer a {
  187. font-size: 80%;
  188. color: black;
  189. }
  190.  
  191. .nicorepo .log .time:after {
  192. background: #888;
  193. color: #fff;
  194. border-radius: 4px;
  195. display: inline-block;
  196. padding: 2px 4px;
  197. }
  198. .nicorepo .log.log-user-register-chblog .time:after,
  199. .nicorepo .log.log-user-video-upload .time:after,
  200. .nicorepo .log.log-user-seiga-image-upload .time:after {
  201. content: '投稿';
  202. background: #866;
  203. }
  204.  
  205. .nicorepo .log.log-user-mylist-add-blomaga .time:after,
  206. .nicorepo .log.log-user-mylist-add .time:after {
  207. content: 'マイリスト';
  208. }
  209. .nicorepo .log.log-user-live-broadcast .time:after {
  210. content: '放送';
  211. }
  212. .nicorepo .log.log-user-seiga-image-clip .time:after {
  213. content: 'クリップ';
  214. }
  215. .nicorepo .log.log-user-video-review .time:after {
  216. content: 'レビュー';
  217. }
  218. .nicorepo .log.log-user-uad-advertise .time:after {
  219. content: '広告';
  220. }
  221.  
  222. .nicorepo .log.log-user-video-upload {
  223. background: #ffe;
  224. }
  225.  
  226. .nicorepo .log.log-user-video-upload .log-target-thumbnail,
  227. .nicorepo .log.log-user-seiga-image-upload .log-target-thumbnail {
  228. }
  229. .nicorepo .log.log-user-video-upload .video,
  230. .nicorepo .log.log-user-seiga-image-upload .seiga_image {
  231. }
  232.  
  233.  
  234. .nicorepo .log-author,
  235. .nicorepo .log-body,
  236. .nicorepo .log-res,
  237. .nicorepo .log-comment,
  238. .nicorepo .log-footer {
  239. display: none !important;
  240. }
  241. */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/');
  242.  
  243. var __large_thumbnail_css__ = (function() {/*
  244.  
  245. .largeThumbnailLink {
  246. display: inline-block;
  247. }
  248.  
  249. .largeThumbnailLink::after {
  250. content: "";
  251. position: fixed;
  252. bottom: -280px;
  253. width: 360px;
  254. height: 270px;
  255. left: 24px;
  256. opacity: 0;
  257. background-color: #fff;
  258. background-size: contain;
  259. background-repeat: no-repeat;
  260. background-position: center center;
  261. transition:
  262. bottom 0.5s ease 0.5s,
  263. z-index 0.5s ease,
  264. box-shadow 0.5s ease 0.5s,
  265. opacity 0.5s ease 0.5s;
  266. z-index: 100000;
  267. }
  268.  
  269. #PAGEBODY .largeThumbnailLink::after {
  270. left: auto;
  271. right: 24px;
  272. }
  273.  
  274. .largeThumbnailLink:hover::after {
  275. position: fixed;
  276. bottom: 32px;
  277. opacity: 1;
  278. box-shadow: 4px 4px 4px #333;
  279. transition:
  280. bottom 0.2s ease,
  281. z-index 0.2s ease,
  282. box-shadow 0.2s ease,
  283. opacity 0.2s ease;
  284. z-index: 100100;
  285. }
  286. */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/');
  287.  
  288. var __tagrepocss__ = (function() {/*
  289. .newVideoChannel .post-item,
  290. .newVideoUser .post-item {
  291. {* background: #ffe;*}
  292. }
  293.  
  294. .newLiveChannel .post-item,
  295. .newLiveUser .post-item {
  296. background: #eee;
  297. }
  298. */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/');
  299.  
  300. var initializeLargeThumbnail = function(type, container, selector) {
  301. console.log('%cinitializeLargeThumbnail: type=%s', 'background: lightgreen;', type);
  302. addStyle(__large_thumbnail_css__);
  303.  
  304. // 大サムネが存在する最初の動画ID。 ソースはちゆ12歳
  305. // ※この数字以降でもごく稀に例外はある。
  306. var threthold = 16371888;
  307. var hasLargeThumbnail = function(videoId) { // return true;
  308. var cid = videoId.substr(0, 2);
  309. if (cid !== 'sm') { return false; }
  310.  
  311. var fid = videoId.substr(2) * 1;
  312. if (fid < threthold) { return false; }
  313.  
  314. return true;
  315. };
  316.  
  317. var onLoadImageError = function() {
  318. console.log('%c large thumbnail load error!', 'background: red;', this);
  319. this.src = this.src.replace('.L', '');
  320. $(this)
  321. .removeClass('largeThumbnail')
  322. .closest('a')
  323. .removeClass('largeThumbnailLink');
  324. };
  325.  
  326. var updatedItems = [];
  327. var each = function(i, v) {
  328. //console.log(i, v); //return;
  329. var href = v.href;
  330. if (typeof href !== 'string' || href.toString().indexOf('/watch/sm') < 0) {
  331. return;
  332. }
  333.  
  334. var videoId = href.replace(/^.+(sm\d+).*$/, '$1');
  335.  
  336. if (!hasLargeThumbnail(videoId)) {
  337. return;
  338. }
  339.  
  340. var $this = $(v);
  341. var $thumbnail = $this.find('img');
  342. var src = $thumbnail.attr('src');
  343. var org = $thumbnail.attr('data-original');
  344. var attr = org ? 'data-original' : 'src';
  345. src = org ? org : src;
  346.  
  347. //console.log('', attr, src, org);
  348.  
  349. if (src && src.indexOf('.L') < 0 && src.indexOf('/smile?i=') > 0) {
  350. var url = src.replace('.M', '') + '.L';
  351. $thumbnail
  352. .on('error', onLoadImageError)
  353. .addClass('largeThumbnail ' + videoId)
  354. .attr(attr, url);
  355.  
  356. $this.addClass('largeThumbnailLink ' + videoId);
  357. updatedItems.push([videoId, url]);
  358. }
  359. };
  360.  
  361. var cssExist = {};
  362. var updateCss = function(items) {
  363. if (items.length < 1) { return; }
  364. var css = [];
  365. for (var i = 0, len = items.length; i < len; i++) {
  366. var videoId = items[i][0], src = items[i][1];
  367. if (cssExist[videoId]) {
  368. continue;
  369. }
  370. cssExist[videoId] = true;
  371. css.push([
  372. '.largeThumbnailLink.', videoId, '::after {',
  373. ' background-image: url(', src, ');',
  374. // ' content: url(', src, ');',
  375. '}',
  376. '\n'].join(''));
  377. }
  378. if (css.length > 0) {
  379. addStyle(css.join(''));
  380. }
  381. };
  382.  
  383. var delayTimer;
  384. var update = function() {
  385. if (delayTimer) {
  386. clearTimeout(delayTimer);
  387. }
  388.  
  389. delayTimer = setTimeout(function() {
  390. console.log('%cupdate large thumbnail', 'background: lightgreen;');
  391. updatedItems = [];
  392. $(selector).each(each);
  393. updateCss(updatedItems);
  394. delayTimer = null;
  395. }, 500);
  396. };
  397.  
  398. update();
  399.  
  400. $(container).on('DOMNodeInserted', update);
  401. };
  402.  
  403. var initializeSeigaThumbnail = function(type, container, selector) {
  404. console.log('%cinitializeSeigaThumbnail: type=%s', 'background: lightgreen;', type);
  405.  
  406. var onLoadImageError = function() {
  407. console.log('%c large thumbnail load error!', 'background: red;', this);
  408. this.src = this.src.replace(/i$/, 'z');
  409. $(this)
  410. .removeClass('largeThumbnail')
  411. .closest('a')
  412. .removeClass('largeThumbnailLink');
  413. };
  414.  
  415. var updatedItems = [];
  416. var each = function(i, v) {
  417. var href = v.href;
  418. if (typeof href !== 'string' || href.indexOf('/seiga/im') < 0) {
  419. //console.log(i, href, href.indexOf('/seiga/im'), typeof href , v);
  420. return;
  421. }
  422.  
  423. var seigaId = href.replace(/^.+(im\d+).*$/, '$1');
  424.  
  425. var $this = $(v);
  426. var $thumbnail = $this.find('img');
  427. var src = $thumbnail.attr('src');
  428. var org = $thumbnail.attr('data-original');
  429. var attr = org ? 'data-original' : 'src';
  430. src = org ? org : src;
  431.  
  432. if (src && src.match(/thumb\/\d+z$/)) {
  433. var url = src.replace(/z$/, 'i');
  434. $thumbnail
  435. .on('error', onLoadImageError)
  436. .addClass('largeThumbnail ' + seigaId)
  437. .attr(attr, url);
  438.  
  439. $this.addClass('largeThumbnailLink ' + seigaId);
  440. updatedItems.push([seigaId, url]);
  441. }
  442.  
  443. };
  444.  
  445. var cssExist = {};
  446. var updateCss = function(items) {
  447. if (items.length < 1) { return; }
  448. var css = [];
  449. for (var i = 0, len = items.length; i < len; i++) {
  450. var seigaId = items[i][0], src = items[i][1];
  451. if (cssExist[seigaId]) {
  452. continue;
  453. }
  454. cssExist[seigaId] = true;
  455. css.push([
  456. '.largeThumbnailLink.', seigaId, '::after {',
  457. ' background-image: url(', src, ');',
  458. '}',
  459. '\n'].join(''));
  460. }
  461. if (css.length > 0) {
  462. addStyle(css.join(''));
  463. }
  464. };
  465.  
  466. var delayTimer;
  467. var update = function() {
  468. if (delayTimer) {
  469. clearTimeout(delayTimer);
  470. }
  471.  
  472. delayTimer = setTimeout(function() {
  473. console.log('%cupdate seiga thumbnail', 'background: lightgreen;');
  474. updatedItems = [];
  475. $(selector).each(each);
  476. updateCss(updatedItems);
  477. delayTimer = null;
  478. }, 500);
  479. };
  480.  
  481. update();
  482.  
  483. $(container).on('DOMNodeInserted', update);
  484. };
  485.  
  486.  
  487.  
  488. window.SmartNicorepo = {
  489. model: {},
  490. util: {},
  491. initialize: function() {
  492. this.initializeUserConfig();
  493. if (location.pathname === '/my/fav/user') {
  494. this.initializeFavUser();
  495. } else
  496. if (location.pathname.indexOf('/my/tagrepo/') === 0) {
  497. this.initializeTagrepo();
  498. } else {
  499. this.initializeNicorepo();
  500. this.initializeAutoPageRize();
  501. }
  502. },
  503. initializeUserConfig: function() {
  504. var prefix = 'SmartNicorepo_';
  505. var conf = {
  506. showUploadOnly: false,
  507. autoPagerize: true
  508. };
  509.  
  510. this.config = {
  511. get: function(key) {
  512. try {
  513. if (window.localStorage.hasOwnProperty(prefix + key)) {
  514. return JSON.parse(window.localStorage.getItem(prefix + key));
  515. }
  516. return conf[key];
  517. } catch (e) {
  518. return conf[key];
  519. }
  520. },
  521. set: function(key, value) {
  522. //console.log('%cupdate config {"%s": "%s"}', 'background: cyan', key, value);
  523. window.localStorage.setItem(prefix + key, JSON.stringify(value));
  524. }
  525. };
  526. },
  527. initializeNicorepo: function() {
  528. addStyle(__nicorepocss__, 'nicorepoCss');
  529.  
  530. var config = this.config;
  531. var toggle = $.proxy(function() {
  532. $nicorepo.toggleClass('show-upload-only');
  533. config.set('showUploadOnly', $nicorepo.hasClass('show-upload-only'));
  534. }, this);
  535.  
  536. var $nicorepo = $('#nicorepo').dblclick(toggle);
  537. var $button = $('<button class="toggleUpload">投稿だけ表示</button>').click(toggle);
  538.  
  539. $nicorepo.toggleClass('show-upload-only', config.get('showUploadOnly'));
  540.  
  541.  
  542. $('.timeline>*:first').before($button);
  543. $('.timeline>*:last').before($button.clone(true).addClass('bottom'));
  544. },
  545. initializeTagrepo: function() {
  546. console.log('%cinitializeTagrepo', 'background: lightgreen;');
  547. addStyle(__tagrepocss__, 'tagrepoCss');
  548. },
  549. initializeFavUser: function() {
  550. addStyle(__favusercss__, 'favUserCss');
  551. // this.loadFavUserList()
  552. // .then($.proxy(function(watchitems) {
  553. // console.log('%c ok:', 'background: #8f8;', watchitems.length);
  554. //
  555. // this._itemList = new window.SmartNicorepo.model.WatchItemList(watchitems);
  556. //
  557. // console.log('item list', this._itemList.getSortedItems());
  558. //
  559. // }, this));
  560. $('.posRight .arrow').each(function(i, elm) {
  561. var $elm = $(elm), $lnk = $elm.clone();
  562. $lnk
  563. .html('<span></span> ニコレポを表示&nbsp;')
  564. .addClass('showNicorepo');
  565. $elm.before($lnk);
  566. });
  567.  
  568. $('.outer .section a').each(function(i, elm) {
  569. var $elm = $(elm), href = $elm.attr('href');
  570. if (href.match(/\/(\d+)$/)) {
  571. var userId = RegExp.$1;
  572. var $video = $('<a class="uploadVideoList">動画一覧</a>')
  573. .attr('href', '/user/' + userId + '/video');
  574. var $seiga = $('<a class="seigaUserPage">静画一覧</a>')
  575. .attr('href', 'http://seiga.nicovideo.jp/user/illust/' + userId);
  576. $elm.after($seiga).after($video);
  577. }
  578. });
  579.  
  580. var getClearBusy = function($elm) {
  581. return function() {
  582. $elm.removeClass('updating').addClass('done');
  583. };
  584. };
  585.  
  586. $('#favUser .showNicorepo').off().on('click', $.proxy(function(e) {
  587. if (e.button !== 0 || e.metaKey || e.shiftKey || e.altKey || e.ctrlKey) {
  588. return;
  589. }
  590. e.preventDefault();
  591. e.stopPropagation();
  592. var $elm = $(e.target);
  593. var userId = $elm.attr('data-nico-nicorepolistid');
  594. if (!userId) { return; }
  595. var $outer = $elm.closest('.outer');
  596. if ($outer.hasClass('updating')) {
  597. return;
  598. }
  599.  
  600. var clearBusy = getClearBusy($outer);
  601. $outer.addClass('updating');
  602. window.setTimeout(clearBusy, 3000);
  603.  
  604. this.loadNicorepo(userId, $outer).then(clearBusy, clearBusy);
  605.  
  606. }, this));
  607. },
  608. initializeAutoPageRize: function() {
  609. if (!window._) { return; }
  610. var config = this.config;
  611. var $button = $('<button class="togglePagerize">自動読込</button>');
  612. var timer = null;
  613.  
  614. var onButtonClick = function(e) {
  615. toggle();
  616. updateView();
  617. };
  618. var toggle = $.proxy(function() {
  619. this._isAutoPagerizeEnable = !this._isAutoPagerizeEnable;
  620. config.set('autoPagerize', this._isAutoPagerizeEnable);
  621. if (this._isAutoPagerizeEnable) {
  622. bind();
  623. } else {
  624. unbind();
  625. }
  626. }, this);
  627. var updateView = $.proxy(function() {
  628. $button.toggleClass('enable', this._isAutoPagerizeEnable);
  629. }, this);
  630. var onWindowScroll = _.debounce($.proxy(this._onWindowScroll, this), 100);
  631. var bind = $.proxy(function() {
  632. $(window).on('scroll', onWindowScroll);
  633. timer = window.setInterval($.proxy(this._autoPagerize, this), 1000);
  634. }, this);
  635. var unbind = $.proxy(function() {
  636. $(window).off('scroll', onWindowScroll);
  637. window.clearInterval(timer);
  638. }, this);
  639.  
  640.  
  641. $button.click(onButtonClick);
  642. $('body').append($button);
  643.  
  644. this._isAutoPagerizeEnable = config.get('autoPagerize');
  645. if (this._isAutoPagerizeEnable) { bind(); }
  646.  
  647. updateView();
  648.  
  649. },
  650. _onWindowScroll: function() {
  651. this._autoPagerize();
  652. },
  653. _autoPagerize: function() {
  654. if (!this._isAutoPagerizeEnable) { return; }
  655.  
  656. // TODO: キャッシュする
  657. var $nextPage = $('.next-page');
  658. var $window = $(window);
  659.  
  660. var isLoading = function() {
  661. return $nextPage.hasClass('loading');
  662. };
  663.  
  664. var isScrollIn = function() {
  665. var bottom =
  666. $window.scrollTop() + $window.innerHeight() - $nextPage.offset().top;
  667. return bottom > 100;
  668. };
  669.  
  670. if (isScrollIn() && !isLoading()) {
  671. this._$nextPage = null;
  672. $nextPage.find('.next-page-link').click();
  673. }
  674. },
  675. loadNicorepo: function(userId, $container) {
  676. // http://www.nicovideo.jp/user/[userId]/top?innerPage=1
  677. var url = 'http://www.nicovideo.jp/user/' + userId + '/top?innerPage=1';
  678.  
  679. var fail = function(msg) {
  680. var $fail = $('<div class="nicorepo fail">' + msg + '</div>');
  681. $container.append($fail);
  682. autoScrollIfNeed($fail);
  683. };
  684.  
  685. // ニコレポが画面の一番下よりはみ出していたら見える位置までスクロール
  686. var autoScrollIfNeed = function($target) {
  687. var
  688. scrollTop = $('html').scrollTop(),
  689. targetOffset = $target.offset(),
  690. clientHeight = $(window).innerHeight(),
  691. clientBottom = scrollTop + clientHeight,
  692. targetBottom = targetOffset.top + $target.outerHeight();
  693.  
  694. if (targetBottom > clientBottom) {
  695. $('html').animate({
  696. scrollTop: scrollTop + $target.outerHeight()
  697. }, 500);
  698. }
  699. };
  700.  
  701. var success = function($dom, $logBody) {
  702. var $result = $('<div class="nicorepo success" />');
  703. var $img = $logBody.find('img'), $log = $logBody.find('.log');
  704. $img.each(function() {
  705. var $this = $(this), $parent = $this.parent();
  706. var lazyImg = $this.attr('data-original');
  707. if (lazyImg) {
  708. var $imageContainer = $('<div class="imageContainer"/>');
  709. $imageContainer.css('background-image', 'url(' + lazyImg + ')');
  710. $this.before($imageContainer);
  711. $this.remove();
  712. }
  713. if (window.WatchItLater) {
  714. var href = $parent.attr('href');
  715. if (href) {
  716. $parent.attr('href', href.replace('http://www.nicovideo.jp/watch/', 'http://nico.ms/'));
  717. }
  718. }
  719. });
  720. $logBody.each(function() {
  721. var $this = $(this), time = $this.find('time:first').text(), logComment = $this.find('.log-comment').text();
  722.  
  723. $this.find('.log-target-info>*:first')
  724. .before($('<span class="time">' + time + '</span>'));
  725. if (logComment) {
  726. $this.find('.log-target-info')
  727. .append($('<span class="logComment">' + logComment + '</span>'));
  728. }
  729. });
  730.  
  731. $result.append($logBody);
  732. $container.append($result);
  733. $result.scrollTop(0);
  734.  
  735. autoScrollIfNeed($result);
  736. };
  737.  
  738. return $.ajax({
  739. url: url,
  740. timeout: 30000
  741. }).then(
  742. function(resp) {
  743. var
  744. $dom = $(resp),
  745. // 欲しいのはそのユーザーの「行動」なので、
  746. // xx再生やスタンプみたいなのはいらない
  747. $logBody = $dom.find('.log:not(.log-user-video-round-number-of-view-counter):not(.log-user-action-stamp):not(.log-user-live-video-introduced)');
  748. if ($logBody.length < 1) {
  749. fail('ニコレポが存在しないか、取得に失敗しました');
  750. } else {
  751. success($dom, $logBody);
  752. }
  753. },
  754. function() {
  755. fail('ニコレポの取得に失敗しました');
  756. });
  757.  
  758. },
  759. loadFavUserList: function() {
  760. var def = new $.Deferred();
  761. // このAPIのupdate_timeが期待していた物と違ったのでボツ
  762. // create_timeとupdate_timeはどちらも同じ値が入ってるだけだった。(なんのためにあるんだ?)
  763. //
  764. $.ajax({
  765. url: 'http://www.nicovideo.jp/api/watchitem/list',
  766. timeout: 30000,
  767. complete: function(resp) {
  768. var json;
  769. try {
  770. json = JSON.parse(resp.responseText);
  771. } catch (e) {
  772. console.log('%c parse error: ', 'background: #f88', e);
  773. return def.reject('json parse error');
  774. }
  775.  
  776. if (json.status !== 'ok') {
  777. console.log('%c status error: ', 'background: #f88', json.status);
  778. return def.reject('status error', json.status);
  779. }
  780. return def.resolve(json.watchitem);
  781. },
  782. error: function(req, status, thrown) {
  783. if (status === 'parsererror') {
  784. return;
  785. }
  786. console.log('%c ajax error: ' + status, 'background: #f88', thrown);
  787. return def.reject(status);
  788. }
  789. });
  790. return def.promise();
  791. }
  792.  
  793. };
  794.  
  795.  
  796. window.SmartNicorepo.model.WatchItem = function() { this.initialize.apply(this, arguments); };
  797. window.SmartNicorepo.model.WatchItem.prototype = {
  798. initialize: function(seed) {
  799. this._seed = seed;
  800. this.itemType = seed.item_type || '1';
  801. this.itemId = seed.item_id || '';
  802. if (typeof seed.item_data === 'object') {
  803. var data = seed.item_data;
  804. this.userId = data.id;
  805. this.nickname = data.nickname;
  806. this.thumbnailUrl = data.thumbnail_url;
  807. }
  808. var now = (new Date()).getTime();
  809. this.createTime = new Date(seed.create_time ? seed.create_time * 1000 : now);
  810. this.updateTime = new Date(seed.update_time ? seed.update_time * 1000 : now);
  811. }
  812. };
  813.  
  814. window.SmartNicorepo.model.WatchItemList = function() { this.initialize.apply(this, arguments); };
  815. window.SmartNicorepo.model.WatchItemList.prototype = {
  816. initialize: function(watchItems) {
  817. this._seed = watchItems;
  818. this._items = {};
  819. this._itemArray = [];
  820. for (var i = 0, len = watchItems.length; i < len; i++) {
  821. var item = new window.SmartNicorepo.model.WatchItem(watchItems[i]);
  822. this._items[item.userId] = item;
  823. this._itemArray.push(item);
  824. }
  825. },
  826. getItem: function(userId) {
  827. return this._items[userId];
  828. },
  829. getSortedItems: function() {
  830. var result = this._itemArray.concat();
  831. result.sort(function(a, b) {
  832. return (a.updateTime < b.updateTime) ? 1 : -1;
  833. });
  834. return result;
  835. }
  836. };
  837.  
  838.  
  839. window.Nico.onReady(function() {
  840. console.log('%cNico.onReady', 'background: lightgreen;');
  841. if (location.pathname.indexOf('/my/top') === 0) {
  842. initializeLargeThumbnail('nicorepo', '.nicorepo', '.log-target-thumbnail a[href*=nicovideo.jp/watch/sm]:not(.largeThumbnailLink)');
  843. initializeSeigaThumbnail('nicorepo', '.nicorepo', '.log-target-thumbnail a:not(.largeThumbnailLink)');
  844. //initializeSeigaThumbnail('nicorepo', '.nicorepo', '.log-target-thumbnail a[href*=/seiga/im]:not(.largeThumbnailLink)');
  845. } else
  846. if (location.pathname.indexOf('/my/mylist') === 0) {
  847. initializeLargeThumbnail('mylist', '#mylist', '.thumbContainer a:not(.largeThumbnailLink)');
  848. } else
  849. if (location.pathname.indexOf('/my/video') === 0) {
  850. initializeLargeThumbnail('video', '#video', '.thumbContainer a:not(.largeThumbnailLink)');
  851. } else
  852. if (location.pathname.indexOf('/mylist') === 0) {
  853. initializeLargeThumbnail('openMylist', '#PAGEBODY', '.SYS_box_item a:not(.watch):not(.largeThumbnailLink):visible');
  854. } else
  855. if (location.pathname.match(/\/user\/\d+\/video/)) {
  856. initializeLargeThumbnail('video', '#video', '.thumbContainer a:not(.largeThumbnailLink)');
  857. } else
  858. if (location.pathname.match(/\/user\/\d+\/top/)) {
  859. initializeLargeThumbnail('nicorepo', '.nicorepo', '.log-target-thumbnail a[href*=nicovideo.jp/watch/sm]:not(.largeThumbnailLink)');
  860. } else
  861. if (location.pathname.match(/\/my\/tagrepo\//)) {
  862. initializeLargeThumbnail('tagrepo', '#tagrepo', '.newVideoUser .contents-thumbnail a[href*=nicovideo.jp/watch/sm]:not(.largeThumbnailLink)');
  863. }
  864. });
  865.  
  866. if (location.pathname.indexOf('/mylist') < 0) {
  867. window.SmartNicorepo.initialize();
  868. }
  869.  
  870. }); // end of monkey
  871.  
  872. var gm = document.createElement('script');
  873. gm.id = 'smartNicorepoScript';
  874. gm.setAttribute("type", "text/javascript");
  875. gm.setAttribute("charset", "UTF-8");
  876. gm.appendChild(document.createTextNode("(" + monkey + ")(window)"));
  877. document.body.appendChild(gm);
  878.  
  879. })();