Greasy Fork

A zarashi, No zarashi

ニコニコ動画サイト内の動画リストに投稿者・タグ等の情報を併せて表示し、また特定の動画ID・投稿者・タグ・コミュニティの動画及び、削除済み・非公開動画を非表示にする簡易NG機能を追加するスクリプト (Bad Nicouser Blocker(Author:favril)を元に作成)

// Generated by CoffeeScript 1.8.0

/*
// ==UserScript==
// @name           A zarashi, No zarashi
// @author         el&
// @version        0.6.1
// @description    ニコニコ動画サイト内の動画リストに投稿者・タグ等の情報を併せて表示し、また特定の動画ID・投稿者・タグ・コミュニティの動画及び、削除済み・非公開動画を非表示にする簡易NG機能を追加するスクリプト (Bad Nicouser Blocker(Author:favril)を元に作成)
// @license        MIT
// @namespace      https://greasyfork.org/ja/users/16539
// @match          http://*.nicovideo.jp/*
// @grant          GM_info
// @grant          GM_addStyle
// @grant          GM_listValues
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_deleteValue
// @grant          GM_xmlhttpRequest
// @grant          GM_notification
// @run-at         document-start
// @noframes
// ==/UserScript==
 */

(function() {
  'use strict';
  var AUTOPAGE_EVENT_LIST, CHAIN_LATENCY, CSS, CommunityVideoInfoFinder, DEST, DIRECT_NG, DelayInserter, EARLY, FinderParameter, HEADER, HREF_SCRIPT, INTERVAL, InitParameter, InserterParameter, InserterWithWrap, LATENCY, ManagerParameter, NG, NGItemElement, NGItemList, NGListElement, NGListElementInNicopedia, NO_EARLY, NicovideoNGSystem, OverwritableParameter, PF, PFL, PLACE, PLACE_CSS, PLACE_RULE, PRESET, PREVISIBLE, Place, REGEXP, RETRY, RULE, RefererParameter, RequestQueManager, SearcherParameter, TIMEOUT, UadVideoIdFinder, UserNameFinder, Util, VideoInfoElement, VideoInfoFinder, VideoInfoInserter, VideoNodeSearcher, main, parser,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  if (window.top !== window.self) {
    return;
  }


  /*
   * JSON文字列でのNG項目の指定
   * 配列の要素としてNG項目の種別に
   * ["video", "<動画id(数字)>"]
   * ["user", "<ユーザーid(数字)>"]
   * ["channel", "<チャンネルid(数字)>"]
   * ["community", "<コミュニティid(数字)>"]
   * ["tag", "タグ名(文字)"]
   *と書く
   *
   * 例: タグ名 テスト 及びユーザーid 1 をNG項目に指定する場合
   *  DIRECT_NG = '[["tag", "テスト"], ["user", "1"]]'
   */

  DIRECT_NG = '[]';


  /*
   * PREVISIBLE: ページ読込時における不可視設定についてのフラグ
   * at_startはページに移動してから少しの間(ページ構成の読込が完了したことを示すDOMContentLoadedイベントが起きるまで)ページ全体を可視のままにしておくかどうかのフラグ(NG機能をoffにしている場合はこのフラグの値に関わらず可視のままとなる)
   * at_loadedはNG確認前の動画を可視にしておくかどうかのフラグ
   * 値をfalseにすると、不可視(visibility: hidden;)に設定される
   * 大雑把には、
   * (デフォルト)NGに指定した動画はなるべく画面に映したくない場合 at_start: false, at_loaded: false
   * 回線が不安定でページの読み込みがもたつくような環境では at_start: true, at_loaded: false
   * NG確認前の動画リストを不可視にしておく必要が無い人は at_start: true, at_loaded: true
   * というような使用を想定。
   */

  PREVISIBLE = {
    at_start: false,
    at_loaded: false
  };


  /*
   * 特定の場所ではこのスクリプトが動作しないようにするには
   * 対象とする場所のenableプロパティをtrueからfalseに変える
   *
   * また場所ごとにPREVISIBLEフラグの上書きができる
   * 回線が不安定な環境の場合、NG未確認の動画が表示される事を気にしないならばニコニコ大百科においてはat_startをtrueに設定しておいた方が良いかもしれない(DOMContentLoadedイベントが発生しない事が良くある)
   *  nicopedia: {
   *    url: /^http:\/\/dic\.nicovideo\.jp/,
   *    enable: true,
   *    previsible: {
   *      at_start: true,
   *      at_loaded: true
   *    }
   * },
   */

  PLACE = {
    video_top: {
      url: /^http:\/\/www\.nicovideo\.jp\/video_top/,
      enable: true
    },
    ranking: {
      url: /^http:\/\/www\.nicovideo\.jp\/ranking/,
      enable: true
    },
    tag: {
      url: /^http:\/\/www\.nicovideo\.jp\/tag\//,
      enable: true
    },
    search: {
      url: /^http:\/\/www\.nicovideo\.jp\/search\//,
      enable: true
    },
    watch: {
      url: /^http:\/\/www\.nicovideo\.jp\/watch\//,
      enable: true
    },
    recommend: {
      url: /^http:\/\/www\.nicovideo\.jp\/recommendations/,
      enable: true
    },
    newarrival: {
      url: /^http:\/\/www\.nicovideo\.jp\/newarrival/,
      enable: true
    },
    recent: {
      url: /^http:\/\/www\.nicovideo\.jp\/recent/,
      enable: true
    },
    mylist: {
      url: /^http:\/\/www\.nicovideo\.jp\/mylist\//,
      enable: true
    },
    vocanico: {
      url: /^http:\/\/ex\.nicovideo\.jp\/vocaloid/,
      enable: true
    },
    newworld: {
      url: /^http:\/\/live\.nicovideo\.jp\/newworld/,
      enable: true
    },
    uni_ranking: {
      url: /^http:\/\/www\.nicovideo\.jp\/uni_ranking/,
      enable: true
    },
    surema_ranking: {
      url: /^http:\/\/ex\.nicovideo\.jp\/surema_ranking/,
      enable: true
    },
    uad_ranking: {
      url: /^http:\/\/uad\.nicovideo\.jp\/rank\//,
      enable: true
    },
    uad_latest: {
      url: /^http:\/\/uad\.nicovideo\.jp\/latest\//,
      enable: true
    },
    community: {
      url: /^http:\/\/com\.nicovideo\.jp\/(?:community|video)\//,
      enable: true
    },
    nicopedia: {
      url: /^http:\/\/dic\.nicovideo\.jp/,
      enable: true,
      __previsible: {
        at_start: true,
        at_loaded: true
      }
    },
    blomaga: {
      url: /^http:\/\/ch\.nicovideo\.jp(?!\/portal\/)(?!\/tool\/)\/.+\/blomaga/,
      enable: true
    },
    top: {
      url: /^http:\/\/www\.nicovideo\.jp\/(?:\?.*)?$/,
      enable: true
    }
  };

  LATENCY = 1000;

  INTERVAL = 400;

  EARLY = {
    interval: 250,
    count: 8
  };

  NO_EARLY = {
    interval: INTERVAL,
    count: 0
  };

  TIMEOUT = 5000;

  RETRY = {
    count: 4,
    wait: 1000
  };

  CHAIN_LATENCY = 200;

  AUTOPAGE_EVENT_LIST = ['AutoPatchWork.DOMNodeInserted', 'AutoPagerize_DOMNodeInserted'];

  PF = "AN_";

  PFL = PF.toLowerCase();

  NG = {
    id: {
      base: PF + "NGListBase",
      list: PF + "NGListContainer",
      status: PF + "NGStatus",
      menu: PF + "NGMenu"
    },
    class_name: {
      item: {
        base: PF + "NGListBaseClass",
        ng: PF + "NGItem",
        direct_ng: PF + "directNGItem",
        video_info: PF + "videoInfo",
        title: PF + "videoTitle",
        video_id: PF + "videoId",
        uploader: PF + "uploader",
        tag: PF + "tag",
        tag_list: PF + "tagList",
        tag_base: PF + "tagBase",
        community: PF + "community",
        video_wrap: PF + "videoWrap"
      },
      state: {
        undef: PF + "isUndefined",
        ng: PF + "isNG",
        failed: PF + "isFailed",
        other: PF + "isOther",
        no_community: PF + "NoCommunity",
        ng_enable: PF + "NGEnable"
      }
    },
    data: {
      enable: 'data-' + PFL + "ng-enable",
      number: 'data-' + PFL + "ng-number",
      video_state: 'data-' + PFL + "video-state"
    },
    key: {
      enable: PF + "NGEnable"
    },
    value: {
      "true": "true",
      "false": "false"
    },
    type: {
      user: 'user',
      channel: 'channel',
      tag: 'tag',
      video: 'video',
      community: 'community'
    },
    event: {
      retry: PF + "retry"
    }
  };

  HEADER = {
    'User-Agent': "Mozilla/5.0 Greasemonkey (A zarashi, No zarashi)"
  };

  HREF_SCRIPT = "javascript:void(0);";

  DEST = {
    thumb: {
      prepend: 'http://ext.nicovideo.jp/api/getthumbinfo/',
      append: ''
    },
    nicoapi: {
      prepend: 'http://api.ce.nicovideo.jp/nicoapi/v1/video.info?__format=xml&v=',
      append: ''
    },
    uad: {
      prepend: 'http://api.uad.nicovideo.jp/UadsBannerService/send?bannerid',
      append: ''
    },
    mylist: {
      prepend: 'http://www.nicovideo.jp/mylist/',
      append: '?rss=2.0'
    },
    user: {
      prepend: 'http://seiga.nicovideo.jp/api/user/info?id=',
      append: ''
    },
    relation: {
      prepend: 'http://flapi.nicovideo.jp/api/getrelation?page=1&sort=p&order=d&video=',
      append: ''
    }
  };

  REGEXP = {
    video: /watch\/((?:so|nm|sm)?[0-9]+)/,
    thumb: /thumb\/((?:so|nm|sm)?[0-9]+)/,
    thumb_watch: /thumb_watch\/((?:so|nm|sm)?[0-9]+)/,
    thumb_and_thumb_watch: /thumb(?:_watch)?\/((?:so|nm|sm)?[0-9]+)/,
    uad: /bannerid(\=.+)$/,
    top_uad: /video_id\=((?:so|nm|sm)?[0-9]+)/,
    uni_ranking: /(?:watch\/|cc_video_id\=)((?:so|nm|sm)?[0-9]+)/,
    top_hot: /[0-9]+$/,
    ext_player: /videoId\=((?:so|nm|sm)?[0-9]+)/
  };

  CSS = {
    ng_list: "#" + NG.id.base + " {\n  width: auto;\n}\n#siteHeaderRightMenu.siteHeaderOther:hover + #" + NG.id.base + " > [href=\"" + HREF_SCRIPT + "\"] {\n}\nli#" + NG.id.base + "." + NG.class_name.item.base + " > a[href=\"" + HREF_SCRIPT + "\"] > span#" + NG.id.status + " {\n  border-left: #666 solid 1px;\n  border-right: none;\n}\nli#" + NG.id.base + "." + NG.class_name.item.base + ":hover > a[href=\"" + HREF_SCRIPT + "\"] > span#" + NG.id.status + " {\n  border-left: #272727 solid 1px;\n  border-right: none;\n}\n#siteHeaderRightMenu.siteHeaderOther:hover + #" + NG.id.base + "." + NG.class_name.item.base + " > a > #" + NG.id.status + " {\n  border-left: #272727 solid 1px;\n}\n#" + NG.id.base + "." + NG.class_name.item.base + " > #" + NG.id.list + "[style=\"display: block;\"] {\n  width: 150px;\n}\n#" + NG.id.base + "." + NG.class_name.item.base + " > #" + NG.id.list + " > li > ." + NG.class_name.item.ng + " {\n  width: 144px;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  white-space: nowrap;\n  padding: 6px 0px 6px 6px;\n}\n#" + NG.id.base + "." + NG.class_name.item.base + " > #" + NG.id.list + " > li > ." + NG.class_name.item.direct_ng + " {\n  width: 144px;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  white-space: nowrap;\n  padding: 6px 0px 6px 6px;\n  color: #fff;\n  background: #898989;\n}",
    video_info: "span." + NG.class_name.item.video_info + " {\n  display: block;\n  clear: both;\n  /* width: inherit; */\n  text-align: left;\n  padding-top: 0.2em;\n}\nspan." + NG.class_name.item.video_info + " > span {\n  display: block;\n  /* width: inherit; */\n  font-size: 12px;\n  color: black;\n  font-weight: normal;\n  text-decoration: none;\n}\nspan." + NG.class_name.item.video_info + " > span:not(." + NG.class_name.item.tag_list + ") {\n  padding: 0.1em 0px 0.1em 0px;\n  text-align: inherit;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\nspan." + NG.class_name.item.video_info + " > span." + NG.class_name.item.tag_list + " {\n  padding: 0.2em 0px 0.2em 0px;\n}\nspan." + NG.class_name.item.tag_list + " > span {\n  display: list-item;\n  list-style-type: none;\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  padding: 0.1em 0px 0.1em 0.5em;\n}\nspan." + NG.class_name.item.video_info + " > span." + NG.class_name.item.title + " {\n  display: none;\n}\nspan > span." + NG.class_name.item.tag_base + " {\n  color: black;\n  font-weight: bold;\n  text-decoration: none;\n  cursor: pointer;\n}\nspan > span." + NG.class_name.item.video_id + ",\nspan > span." + NG.class_name.item.uploader + ",\nspan > span." + NG.class_name.item.community + ",\nspan > span." + NG.class_name.item.tag + " {\n  color: crimson;\n  font-weight: normal;\n  text-decoration: none;\n  cursor: pointer;\n}\n." + NG.class_name.state.no_community + " {\n  visibility: hidden;\n}\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.ng + " {\n  display: none;\n}\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.undef + ",\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.failed + ",\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.other + " {\n  visibility: hidden;\n}\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.failed + " > ." + NG.class_name.item.video_info + " > span:nth-child(4),\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.failed + " > * > ." + NG.class_name.item.video_info + " > span:nth-child(4),\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.other + " > ." + NG.class_name.item.video_info + " > span:nth-child(4),\n." + NG.class_name.state.ng_enable + " ." + NG.class_name.state.other + " > * > ." + NG.class_name.item.video_info + " > span:nth-child(4) {\n  visibility: visible;\n}"
  };

  PLACE_CSS = {
    tag: {
      video_info: ".video:not(.videoList01) > ul.list {\n  width: 700px;\n}\n." + NG.class_name.state.ng_enable + " .video:not(.videoList01) > .list > ." + NG.class_name.state.ng + " {\n  display: list-item;\n  visibility: hidden;\n}",
      __video_info: ".column.main {\n  padding-right: 0px;\n}\n.toolbar > .pager {\n  padding-right: 20px;\n}\n.video > ul.list {\n  width: 720px;\n}\n.video > .list > li.item {\n  margin-right: 20px;\n  clear: none;\n}\n.video.videoList01 > .list > li.item {\n  padding-right: 20px;\n}\n.video.videoList02 > .list > .item {\n  margin-bottom: 10px;\n  min-height: 275px;\n}\n.video:not(.videoList01):not(.videoList02) > .list > .item {\n  margin-bottom: 10px;\n  min-height: 300px;\n}"
    },
    search: {
      video_info: ".video:not(.videoList01) > ul.list {\n  width: 700px;\n}\n." + NG.class_name.state.ng_enable + " .video:not(.videoList01) > .list > ." + NG.class_name.state.ng + " {\n  display: list-item;\n  visibility: hidden;\n}",
      __video_info: ".column.main {\n  padding-right: 0px;\n}\n.toolbar > .pager {\n  padding-right: 20px;\n}\n.video > ul.list {\n  width: 720px;\n}\n.video > .list > li.item {\n  margin-right: 20px;\n  clear: none;\n}\n.video.videoList01 > .list > li.item {\n  padding-right: 20px;\n}\n.video.videoList02 > .list > .item {\n  margin-bottom: 10px;\n  min-height: 275px;\n}\n.video:not(.videoList01):not(.videoList02) > .list > .item {\n  margin-bottom: 10px;\n  min-height: 300px;\n}"
    },
    ranking: {
      video_info: "td[data-video-item] > ." + NG.class_name.item.video_info + " {\n  width: 152px;\n  background-color: #F9FCFC;\n}\n[valign] > td[data-video-item] {\n  background-position-y: top;\n  background-size: auto 175px;\n  background-color: #F9FCFC;\n  padding: 4px 0px;\n}\n." + NG.class_name.state.ng_enable + " td." + NG.class_name.state.ng + " {\n  display: table-cell;\n  visibility: hidden;\n}"
    },
    video_top: {
      video_info: "#newworld > .video > .list {\n  width: 700px;\n}\n." + NG.class_name.state.ng_enable + " #newworld > .video > .list > ." + NG.class_name.state.ng + " {\n  display: list-item;\n  visibility: hidden;\n}\n.newvideoBox > .video >.list {\n  width: 700px;\n}\n." + NG.class_name.state.ng_enable + " .newvideoBox > .video > .list > ." + NG.class_name.state.ng + " {\n  display: list-item;\n  visibility: hidden;\n}"
    },
    watch: {
      video_info: "#playlistContainerInner {\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n.playlistItem > ." + NG.class_name.item.video_info + " > span {\n  color: #eaeaea;\n  /* background: inherit; */\n  /* display: inline; */\n  /* padding: 0px 0px 0px 0px; */\n}\n.playlistItem > ." + NG.class_name.item.video_info + " > span > ." + NG.class_name.item.tag_base + " {\n  color: #eaeaea;\n}\n.playlistItem > ." + NG.class_name.item.video_info + " > span > ." + NG.class_name.item.uploader + ",\n.playlistItem > ." + NG.class_name.item.video_info + " > span > ." + NG.class_name.item.video_id + ",\n.playlistItem > ." + NG.class_name.item.video_info + " > span > ." + NG.class_name.item.community + ",\nli.playlistItem > ." + NG.class_name.item.video_info + " > ." + NG.class_name.item.tag_list + " > span > ." + NG.class_name.item.tag + " {\n  color: tomato;\n}\n." + NG.class_name.state.ng_enable + " .column4 > ." + NG.class_name.state.ng + " {\n  display: list-item;\n  visibility: hidden;\n}\n.uadTagRelated > .default > .itemList > div > .item." + NG.class_name.state.ng + " {\n  display: none;\n}"
    },
    mylist: {
      video_info: ".SYS_box_item {\n  padding: 10px 0px 10px 0px;\n  border-bottom-width: 1px;\n  border-bottom-color: #000;\n  border-bottom-style: dotted;\n}\n#SYS_page_items > .SYS_box_item > table {\n  margin-bottom: 0px;\n}\n." + NG.class_name.item.video_info + " {\n  margin: 0px 0px 0px 24px;\n}"
    },
    vocanico: {
      ng_list: "#" + NG.id.base + " > [href=\"" + HREF_SCRIPT + "\"] {\n  display: inline-block;\n  margin: -4px 0px 0px 0px;\n}\n#" + NG.id.status + " {\n  padding-left: 6px;\n}\n#" + NG.id.list + " {\n  position: absolute;\n  top: 31px;\n  border: #272727 solid 1px;\n  border-top: none;\n  z-index: 9999;\n}\n#" + NG.id.list + " > li {\n  height: 28px;\n  line-height: normal;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.ng + " {\n  display: inline-block;\n  margin-right: 0px;\n  color: #353535;\n  background: #eae8eb;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.ng + ":hover {\n  color: #fff;\n  background: #898989;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.direct_ng + " {\n  display: inline-block;\n  margin-right: 0px;\n  color: #fff;\n  background: #898989;\n}",
      video_info: ".left > ." + NG.class_name.item.video_info + " > ." + NG.class_name.item.tag_list + " {\n  display: block !important;\n}\n.right > ul > li > ." + NG.class_name.item.video_info + " {\n clear: both;\n}\n.fan_ranking_cnt > ul > li > .ttl {\n  height: auto;\n  width: inherit;\n}\n.new_list > .clearfix {\n  margin: 10px 0px 10px 0px;\n  border-bottom: #ccc 1px dashed;\n}\n.new_list > li > .right_box {\n  border-bottom: none;\n}"
    },
    top: {
      video_info: "#uadVideo ." + NG.class_name.item.video_info + " > span:nth-child(2),\n#uadVideo ." + NG.class_name.item.video_info + " > span:nth-child(3) {\n  font-size: 0px\n}\n#uadVideo ." + NG.class_name.item.video_id + ",\n#uadVideo ." + NG.class_name.item.uploader + " {\n  font-size: 12px;\n  display: inline-block;\n  width: 92px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}"
    },
    uad_ranking: {
      video_info: "li.rank1 {\n  height: auto;\n}"
    },
    newworld: {
      overwrite: {
        ng_list: true
      },
      ng_list: "#box_footer > ul > #" + NG.id.base + " {\n  background-color: #F5F5EB;\n  text-align: center;\n  width: 200px;\n  padding: 0px 0px 0px 0px;\n}\n#" + NG.id.base + " > #" + NG.id.list + " {\n  padding: 0px 0px 0px 0px;\n}\n#" + NG.id.base + " > #" + NG.id.list + " > li {\n  width: 200px;\n  padding: 0px 0px 0px 0px;\n  text-align: left;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.ng + " {\n  white-space: nowrap;\n  padding-left: 6px;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.direct_ng + " {\n  white-space: nowrap;\n  padding-left: 6px;\n}",
      video_info: "." + NG.class_name.state.ng_enable + " > #container ." + NG.class_name.state.ng + " {\n  display: none;\n}"
    },
    uni_ranking: {
      video_info: ".thumbWrap > ." + NG.class_name.item.video_info + " {\n  display: none;\n}\nspan." + NG.class_name.item.video_info + " {\n  text-indent: 0px;\n}"
    },
    nicopedia: {
      overwrite: {
        ng_list: true
      },
      ng_list: "#" + NG.id.base + " {\n  white-space: nowrap;\n}\n#" + NG.id.base + ":hover {\n  background-color: #474747;\n}\n#" + NG.id.status + " {\n  padding-left: 10px;\n  border-left: solid 1px #474747;\n}\n#" + NG.id.base + " > #" + NG.id.list + " {\n  position: absolute;\n  top: 36px;\n  width: 150px;\n  background: #eae8eb;\n  border: solid 1px #272727;\n  text-align: left;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.ng + " {\n  display: block;\n  line-height: 1.5em;\n  height: 1.5em;\n  padding: 6px 0px 6px 6px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: #272727;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.ng + ":hover{\n  text-decoration: none;\n  color: white;\n  background-color: #898989;\n}\n#" + NG.id.list + " > li > ." + NG.class_name.item.direct_ng + " {\n  display: block;\n  line-height: 1.5em;\n  height: 1.5em;\n  padding: 6px 0px 6px 6px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: white;\n  background-color: #898989;\n}",
      video_info: "span." + NG.class_name.item.video_wrap + " {\n  display: inline-block;\n}\n." + NG.class_name.item.video_wrap + " > ." + NG.class_name.item.video_info + " {\n  width: inherit;\n}\n.left-box ." + NG.class_name.item.video_info + " {\n  margin: -6px 0px 6px 0px;\n  border: solid 1px #ccc;\n  background-color: #eee;\n  text-indent: 10px;\n}\n#bbs ." + NG.class_name.item.video_info + " {\n  width: 312px;\n  margin-top: -4px;\n}\n#entry > .entry_article {\n  border-bottom-width: 1px;\n  border-bottom-style: dotted;\n  border-bottom-color: #CCCCCC;\n  margin-bottom: 15px;\n}\n#entry > .entry_article > .entry_comment {\n  margin-bottom: 0px;\n  border-bottom-width: 0px;\n}"
    },
    blomaga: {
      video_info: "span." + NG.class_name.item.video_wrap + " {\n  display: inline-block;\n}\n." + NG.class_name.item.video_wrap + " > ." + NG.class_name.item.video_info + " {\n  margin: -6px 0px 6px 0px;\n  border: solid 1px #ccc;\n  background-color: #eee;\n  text-indent: 10px;\n  padding-top: 10px;\n  width: inherit;\n}\niframe[style*=\"border: none;\"] + ." + NG.class_name.item.video_info + " {\n  border: none;\n}"
    }
  };

  PLACE_RULE = {
    vocanico: {
      add_to: {
        parent: {
          csss: '#socialList'
        }
      },
      findNodeSet: function(_video_node) {
        if (_video_node.tagName === 'P') {
          return [_video_node.previousElementSibling, _video_node];
        } else {
          return [_video_node];
        }
      }
    },
    newworld: {
      add_to: {
        parent: {
          csss: '#box_footer > ul'
        }
      }
    },
    surema_ranking: {
      add_to: {
        parent: {
          csss: '.siteHeaderGlovalNavigation'
        }
      }
    },
    community: {
      findNode: function(_info_elem) {
        return _info_elem.parentNode.parentNode;
      }
    },
    top: {
      findNode: function(_info_elem) {
        var check_node, video_node;
        check_node = _info_elem.parentNode;
        video_node = check_node.tagName === 'LI' ? check_node : check_node.parentNode;
        return video_node;
      }
    },
    nicopedia: {
      add_to: {
        parent: {
          csss: '.toplinetable > tbody > tr'
        }
      },
      getNGList: function(_ng_item) {
        return new NGListElementInNicopedia(_ng_item);
      },
      findNode: function(_info_elem) {
        var node;
        node = _info_elem.parentNode.parentNode.parentNode.id === 'bbs' ? _info_elem.previousElementSibling : _info_elem.parentNode;
        return node;
      },
      findNodeSet: function(_video_node) {
        var node_list;
        if (_video_node.parentNode.parentNode.parentNode.id === 'bbs') {
          node_list = [_video_node, _video_node.nextElementSibling, _video_node.previousElementSibling.previousElementSibling];
        } else {
          node_list = [_video_node];
        }
        return node_list;
      }
    }
  };

  PRESET = {
    init: {
      query: {
        sub: {
          csss: '.videoRcolumn > .list'
        },
        uad: {
          csss: '[data-uad-video-list]'
        },
        top_hot: {
          csss: '#hotVideo > div > ul.clearfix'
        },
        top_uad: {
          csss: '#uadVideo > div > ul.clearfix'
        },
        ranking_matrix: {
          csss: 'td[data-video-item]'
        },
        ranking_sub: {
          csss: ':not(.ichiba).videoRcolumn > ol.list, :not(.seiga).videoRcolumn > div > ol.list'
        },
        video_top_top_upper: {
          csss: '#recommend > .video> .list, #topics > .video> .list, #newworld > .video > .list, #newworld_ornament > .video > .list, #nsen_ornament > .video > .list'
        },
        video_top_top_under: {
          csss: '#uad ~ .videoBox > .video > .list'
        },
        video_top_comment: {
          csss: '.newvideoBox > .video > .list[data-recent-video-list]'
        },
        video_top_new: {
          csss: '.newvideoBox > .video > :not([data-recent-video-list]).list'
        },
        watch_playlist: {
          csss: '.playlistItemList'
        },
        watch_explorer: {
          csss: ':not(.channelGuideVideo).contentItemList'
        },
        watch_channelguide: {
          csss: '.channelGuideVideo'
        },
        watch_uad: {
          csss: '.uadTagRelated > .default > .itemList > .item'
        },
        vocanico_home_left: {
          csss: '#head_ranking_cnt > .clearfix > .left'
        },
        vocanico_home_right: {
          csss: '#head_ranking_cnt > .clearfix > .right > ul'
        },
        vocanico_home_new: {
          csss: '#new_video > .new_video_cnt > ul.clearfix'
        },
        vocanico_home_fan_ranking: {
          csss: '.fan_ranking_cnt > ul > li > .ttl'
        },
        vocanico_ranking1: {
          csss: '.ranking_cnt > li:nth-child(1)'
        },
        vocanico_ranking2: {
          csss: '.ranking_cnt > li:nth-child(2)'
        },
        vocanico_ranking3: {
          csss: '.ranking_cnt > li:nth-child(3)'
        },
        vocanico_ranking4: {
          csss: '.ranking_cnt > li:nth-child(4)'
        },
        vocanico_new: {
          csss: '.new_list'
        },
        vocanico_about_thumb: {
          csss: '#fame_video > .video_thumb > ul'
        },
        vocanico_about_video: {
          csss: '#video_watch_player'
        },
        newarrival: {
          csss: '.content_672 > div > div'
        },
        recent: {
          csss: '.content_672 > div > div'
        },
        recommend: {
          csss: '.rec_movlist'
        },
        mylist: {
          csss: '#SYS_page_items'
        },
        mylist_search_thumb: {
          csss: 'div.content_672 > div > table > tbody > tr'
        },
        uni_ranking: {
          csss: '#mainRanking > :not(.chblog):not(.hotLive):not(.popLive) > .clearfix > ol, ul.surema, ul.cateTops'
        },
        uni_ranking_thumb: {
          csss: '.thumbWrap'
        },
        uni_ranking_past: {
          csss: '.listRankingLibrary'
        },
        surema_ranking_sub: {
          csss: '.shootup_list'
        },
        newworld: {
          csss: '#box_b > ul'
        },
        uad_ranking_left: {
          csss: '#left-column > div > div > ol'
        },
        uad_ranking_right: {
          csss: '#right-column > div > div > ol'
        },
        uad_latest: {
          csss: 'td'
        },
        community_top: {
          csss: '#community_side > [summary=""] > tbody'
        },
        community_video: {
          csss: '#main0727 > [summary=""] > tbody'
        },
        blomaga: {
          csss: '.main_blog_txt iframe'
        },
        nicopedia_article: {
          csss: '#article iframe.nicovideo'
        },
        nicopedia_bbs: {
          csss: '#bbs iframe.nicovideo'
        },
        nicopedia_flog: {
          csss: '#entry'
        }
      }
    },
    searcher: {
      regexp: {
        uad: REGEXP.uad
      }
    },
    manager: {
      latency: {
        sub: LATENCY * 2
      },
      quick: {
        sub: NO_EARLY
      }
    },
    finder: {
      regexp: {
        uad: REGEXP.video
      }
    },
    observer: {
      checkcount: {
        top_hot: [0, 0, 0, 0]
      }
    }
  };

  RULE = {
    search: {
      normal: {
        main: {},
        sub: {
          init: {
            query: null
          },
          manager: {
            latency: null,
            quick: null
          }
        }
      },
      autopager: {
        ap_main: {
          target_label: 'main',
          query: false
        }
      }
    },
    tag: {
      normal: {
        main: {},
        sub: {
          init: {
            query: null
          },
          manager: {
            latency: null,
            quick: null
          }
        },
        uad: {
          referer: {
            finder: function() {
              return UadVideoIdFinder;
            }
          },
          init: {
            query: {
              csss: '[data-uad-video-list]'
            }
          },
          searcher: {
            regexp: null
          },
          manager: {
            quick: NO_EARLY
          },
          finder: {
            regexp: null
          }
        }
      },
      observer: {
        dl_uad: {
          target_label: 'uad',
          into: {
            csss: '[data-uad-video-list]'
          },
          type: 'DOMNodeInserted',
          query: false,
          cancelable: false,
          as_parent: false,
          checklist: [true, true, true, false],
          filter: function(_ev) {
            var node, num, result;
            result = false;
            node = _ev.target;
            num = Number(_ev.currentTarget.childElementCount) - 1;
            if (this.checklist[num]) {
              this.checklist[num] = false;
              result = node;
            }
            return result;
          }
        }
      },
      autopager: {
        ap_main: {
          target_label: 'main',
          query: false
        }
      }
    },
    ranking: {
      normal: {
        main: {},
        ranking_matrix: {
          init: {
            query: null,
            as_parent: false
          }
        },
        ranking_sub: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 2,
            quick: NO_EARLY
          }
        }
      },
      autopager: {
        ap_main: {
          target_label: 'main',
          query: false
        }
      }
    },
    video_top: {
      normal: {
        video_top_top_upper: {
          init: {
            query: null
          },
          manager: {
            quick: {
              count: EARLY.count / 2,
              interval: EARLY.interval
            }
          }
        },
        video_top_top_under: {
          init: {
            query: null
          },
          manager: {
            quick: {
              count: EARLY.count / 2,
              interval: EARLY.interval
            }
          }
        },
        video_top_new: {
          init: {
            query: null
          },
          manager: {
            quick: {
              count: EARLY.count / 2,
              interval: EARLY.interval
            }
          }
        },
        video_top_comment: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 1.5,
            quick: {
              count: EARLY.count / 2,
              interval: EARLY.interval
            }
          }
        },
        sub: {
          init: {
            query: null
          },
          manager: {
            latency: null,
            quick: null
          }
        },
        uad: {
          referer: {
            finder: function() {
              return UadVideoIdFinder;
            }
          },
          init: {
            query: {
              csss: '#uad > div > ul'
            }
          },
          searcher: {
            regexp: null,
            manager: {
              quick: NO_EARLY
            }
          },
          finder: {
            regexp: null
          }
        }
      },
      observer: {
        dl_video_top_top_upper: {
          target_label: 'video_top_top_upper',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: true,
          as_parent: true,
          filter: function(_ev) {
            if (_ev.target.className === 'inner') {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_video_top_top_under: {
          target_label: 'video_top_top_under',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: true,
          as_parent: true,
          filter: function(_ev) {
            if (_ev.target.className === 'inner') {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_video_top_new: {
          target_label: 'video_top_new',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: true,
          as_parent: true,
          filter: function(_ev) {
            if (_ev.target.className === 'inner') {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_video_top_comment: {
          target_label: 'video_top_comment',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: true,
          as_parent: true,
          filter: function(_ev) {
            if (_ev.target.className === 'inner') {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_video_top_sub: {
          target_label: 'sub',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: true,
          as_parent: true,
          filter: function(_ev) {
            if (_ev.target.className === 'inner') {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_video_top_uad: {
          target_label: 'uad',
          into: {
            csss: '.column700-300'
          },
          type: 'DOMNodeInserted',
          query: false,
          cancelable: false,
          as_parent: false,
          filter: function(_ev) {
            var node, result;
            result = false;
            node = _ev.target;
            if ((node.tagName != null) && (node.tagName === 'IMG')) {
              node = node.parentNode;
              if ((node.dataset.topUad0 != null) || (node.dataset.topUad1 != null) || (node.dataset.topUad2 != null) || (node.dataset.topUad3 != null)) {
                result = node;
              }
            }
            return result;
          }
        }
      }
    },
    watch: {
      normal: {
        watch_playlist: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        },
        watch_explorer: {
          init: {
            query: null
          }
        },
        watch_channelguide: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        },
        watch_uad: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        }
      },
      observer: {
        dl_watch_playlist_chrome: {
          target_label: 'watch_playlist',
          into: {
            csss: '.playlistItemList'
          },
          type: 'DOMCharacterDataModified',
          query: false,
          as_parent: false,
          cancelable: false,
          filter: function(_ev) {
            if (_ev.target.parentNode.className === 'videoTitle') {
              return _ev.target.parentNode.parentNode.parentNode;
            } else {
              return false;
            }
          }
        },
        dl_watch_playlist_opera_firefox: {
          target_label: 'watch_playlist',
          into: {
            csss: '.playlistItemList'
          },
          type: 'DOMAttrModified',
          query: false,
          as_parent: false,
          cancelable: false,
          filter: function(_ev) {
            if ((_ev.attrChange === 2) && (_ev.attrName === 'href')) {
              return _ev.target.parentNode;
            } else {
              return false;
            }
          }
        },
        dl_watch_explorer: {
          target_label: 'watch_explorer',
          into: {
            csss: '.videoExplorerContent'
          },
          type: 'DOMNodeInserted',
          query: false,
          as_parent: true,
          cancelable: true,
          filter: function(_ev) {
            if ((_ev.target.tagName === 'UL') && (!_ev.target.classList.contains('channelGuideVideo'))) {
              return _ev.target;
            } else {
              return false;
            }
          }
        },
        dl_watch_channelguide: {
          target_label: 'watch_channelguide',
          into: {
            csss: '.videoExplorerContent'
          },
          type: 'DOMNodeInserted',
          query: false,
          as_parent: false,
          cancelable: false,
          filter: function(_ev) {
            var node, parent4, result;
            node = _ev.target;
            result = false;
            if (node.nodeType === Node.TEXT_NODE) {
              if (node.parentNode.className === 'descriptionShort') {
                parent4 = node.parentNode.parentNode.parentNode.parentNode;
                if (parent4.className === 'column1') {
                  if (parent4.parentNode.parentNode.classList.contains('channelGuideVideo')) {
                    result = parent4.parentNode;
                  }
                }
              }
            }
            return result;
          }
        },
        dl_watch_uad: {
          target_label: 'watch_uad',
          into: {
            csss: '.videoExplorerContent'
          },
          type: 'DOMNodeInserted',
          query: false,
          as_parent: true,
          cancelable: false,
          filter: function(_ev) {
            var node, result;
            node = _ev.target;
            result = false;
            if (node.parentNode.parentNode.parentNode.classList.contains('uadTagRelated')) {
              result = node;
            }
            return result;
          }
        }
      }
    },
    mylist: {
      normal: {
        mylist: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        }
      },
      observer: {
        dl_mylist: {
          target_label: 'mylist',
          into: {
            csss: '#SYS_box_mylist_body'
          },
          type: 'DOMNodeInserted',
          query: false,
          as_parent: false,
          cancelable: false,
          filter: function(_ev) {
            var result;
            result = _ev.target.className === 'SYS_box_item' ? _ev.target : false;
            return result;
          }
        },
        dl_mylist_cancel: {
          target_label: 'mylist',
          into: {
            csss: '#SYS_box_mylist_body'
          },
          type: 'DOMNodeInserted',
          query: {
            csss: 'dummy'
          },
          as_parent: true,
          cancelable: true,
          filter: function(_ev) {
            var result;
            result = _ev.target.id === 'SYS_page_items' ? document.createElement('div') : false;
            return result;
          }
        }
      }
    },
    vocanico: {
      normal: {
        vocanico_home_left: {
          init: {
            query: null,
            as_parent: false
          }
        },
        vocanico_home_right: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        },
        vocanico_home_new: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        },
        vocanico_home_fan_ranking: {
          init: {
            query: null,
            as_parent: false
          }
        },
        vocanico_ranking1: {
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          }
        },
        vocanico_ranking2: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 1.25,
            quick: NO_EARLY
          }
        },
        vocanico_ranking3: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 1.5,
            quick: NO_EARLY
          }
        },
        vocanico_ranking4: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 1.75,
            quick: NO_EARLY
          }
        },
        vocanico_new: {
          init: {
            query: null
          }
        },
        vocanico_about_thumb: {
          init: {
            query: null
          }
        }
      }
    },
    recommend: {
      normal: {
        recommend: {
          init: {
            query: null
          }
        }
      },
      observer: {
        dl_recommend: {
          into: {
            csss: '#recommend_item_list'
          },
          type: 'DOMNodeInserted',
          query: false,
          target_label: 'recommend',
          as_parent: true,
          cancelable: false,
          filter: function(_ev) {
            if (_ev.target.className === 'rec_movlist clearfix') {
              return _ev.target;
            } else {
              return false;
            }
          }
        }
      }
    },
    recent: {
      normal: {
        recent: {
          init: {
            query: null
          }
        }
      },
      autopager: {
        ap_recent: {
          target_label: 'recent',
          query: null
        }
      }
    },
    newarrival: {
      normal: {
        newarrival: {
          init: {
            query: null
          }
        }
      },
      autopager: {
        ap_newarrival: {
          target_label: 'newarrival',
          query: null
        }
      }
    },
    top: {
      normal: {
        top_hot: {
          referer: {
            inserter: function() {
              return DelayInserter;
            }
          },
          init: {
            query: null
          },
          searcher: {
            checkreg: REGEXP.top_hot
          },
          inserter: {
            target: {
              parent: {
                csss: '.videoComment'
              }
            }
          }
        },
        top_uad: {
          init: {
            query: null
          },
          namager: {
            latency: LATENCY * 2
          },
          searcher: {
            regexp: REGEXP.top_uad
          }
        }
      },
      observer: {
        dl_top_hot: {
          target_label: 'top_hot',
          into: {
            csss: '#hotVideo > .listWrap'
          },
          type: 'DOMNodeInserted',
          query: false,
          as_parent: false,
          cancelable: false,
          checkreg: REGEXP.top_hot,
          checkcount: PRESET.observer.checkcount.top_hot,
          filter: function(_ev) {
            var href, node, num, result;
            result = false;
            node = _ev.target.parentNode;
            if (node.className === 'videoTitle contentTitle') {
              href = node.href;
              num = Number(href.match(this.checkreg)[0]);
              if ((0 <= num && num < 4)) {
                if (this.checkcount[num] === 2) {
                  result = node.parentNode;
                }
                this.checkcount[num] += 1;
              }
            }
            return result;
          }
        },
        dl_top_hot_assist: {
          target_label: 'top_hot',
          into: {
            csss: '#reloadHotVideo'
          },
          type: 'click',
          query: {
            csss: 'dummy'
          },
          as_parent: false,
          calncelable: false,
          checkcount: PRESET.observer.checkcount.top_hot,
          filter: function(_ev) {
            var i, _i, _ref;
            for (i = _i = 0, _ref = this.checkcount.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
              this.checkcount[i] = 0;
            }
            return false;
          }
        }
      }
    },
    newworld: {
      normal: {
        newworld: {
          init: {
            query: null
          }
        }
      }
    },
    uni_ranking: {
      normal: {
        uni_ranking: {
          init: {
            query: null
          },
          searcher: {
            regexp: REGEXP.uni_ranking
          }
        },
        uni_ranking_thumb: {
          init: {
            query: null,
            as_parent: false
          },
          searcher: {
            regexp: REGEXP.uni_ranking
          },
          manager: {
            latency: LATENCY * 1.5,
            quick: NO_EARLY
          }
        },
        uni_ranking_past: {
          init: {
            query: null
          }
        }
      }
    },
    surema_ranking: {
      normal: {
        main: {},
        surema_ranking_sub: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 2,
            quick: NO_EARLY
          }
        }
      }
    },
    uad_ranking: {
      normal: {
        uad_ranking_left: {
          init: {
            query: null
          }
        },
        uad_ranking_right: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 1.5
          }
        }
      }
    },
    uad_latest: {
      normal: {
        uad_latest: {
          init: {
            query: null
          }
        }
      }
    },
    blomaga: {
      normal: {
        blomaga: {
          referer: {
            inserter: function() {
              return InserterWithWrap;
            }
          },
          init: {
            query: null,
            as_parent: false
          },
          searcher: {
            check: {
              tag: false,
              attr: 'src'
            },
            regexp: REGEXP.thumb_and_thumb_watch
          },
          inserter: {
            target: {
              parent: true
            }
          }
        }
      },
      autopager: {
        ap_blomaga: {
          target_label: 'blomaga',
          query: null
        }
      }
    },
    nicopedia: {
      normal: {
        nicopedia_article: {
          referer: {
            inserter: function() {
              return InserterWithWrap;
            }
          },
          init: {
            query: null,
            as_parent: false
          },
          searcher: {
            check: {
              tag: false,
              attr: 'src'
            },
            regexp: REGEXP.thumb
          },
          inserter: {
            target: {
              parent: true
            }
          }
        },
        nicopedia_bbs: {
          init: {
            query: null,
            as_parent: false
          },
          searcher: {
            check: {
              tag: false,
              attr: 'src'
            },
            regexp: REGEXP.thumb
          },
          manager: {
            latency: LATENCY * 1.5,
            quick: NO_EARLY
          },
          inserter: {
            target: {
              before: false
            }
          }
        },
        nicopedia_flog: {
          init: {
            query: null
          },
          manager: {
            latency: LATENCY * 2,
            quick: NO_EARLY
          }
        }
      },
      observer: {
        dl_nicopedia_flog: {
          target_label: 'nicopedia_flog',
          into: {
            csss: '#right-column'
          },
          type: 'DOMNodeInserted',
          query: null,
          cancelable: false,
          as_parent: true,
          filter: function(_ev) {
            var result;
            result = _ev.target.id === 'flogbox' ? _ev.target : false;
            return result;
          }
        }
      },
      autopager: {
        ap_nicopedia_bbs: {
          target_label: 'nicopedia_bbs',
          query: null
        }
      }
    },
    community: {
      normal: {
        community_top: {
          referer: {
            finder: function() {
              return CommunityVideoInfoFinder;
            }
          },
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          },
          inserter: {
            target: {
              parent: {
                csss: 'td:last-child'
              }
            }
          }
        },
        community_video: {
          referer: {
            finder: function() {
              return CommunityVideoInfoFinder;
            }
          },
          init: {
            query: null
          },
          manager: {
            quick: NO_EARLY
          },
          inserter: {
            target: {
              parent: {
                csss: 'td:last-child'
              }
            }
          }
        }
      },
      autopager: {
        ap_community_video: {
          target_label: 'community_video',
          query: null
        }
      }
    }
  };

  parser = new DOMParser();

  Place = (function() {
    function Place() {}

    Place.current = null;

    Place.add_to = {
      parent: {
        csss: '.siteHeaderMenuList'
      }
    };

    Place.previsible = {
      at_start: PREVISIBLE.at_start,
      at_loaded: PREVISIBLE.at_loaded
    };

    Place.getNGItem = function() {
      return new NGItemElement;
    };

    Place.getNGList = function(_ng_item) {
      return new NGListElement(_ng_item);
    };

    Place.findNode = function(_info_elem) {
      return _info_elem.parentNode;
    };

    Place.findNodeSet = function(_video_node) {
      return [_video_node];
    };

    Place.__matchURL = function(_cur_url, _url) {
      var res;
      res = _cur_url.indexOf(_url) !== -1;
      return res;
    };

    Place.check = function() {
      var current, current_url, label, prop;
      current_url = window.location.href;
      current = null;
      for (label in PLACE) {
        prop = PLACE[label];
        if (prop.enable && prop.url.test(current_url)) {
          current = label;
          break;
        }
      }
      this.current = current;
      return current;
    };

    Place.init = function() {
      var css_list, css_part, name, overwrite, place_css, rule, value, _ref, _ref1;
      this.check();
      if (this.current == null) {
        return;
      }
      if (((_ref = PLACE[this.current].previsible) != null ? _ref.at_start : void 0) != null) {
        this.previsible.at_start = PLACE[this.current].previsible.at_start;
      }
      if (((_ref1 = PLACE[this.current].previsible) != null ? _ref1.at_loaded : void 0) != null) {
        this.previsible.at_loaded = PLACE[this.current].previsible.at_loaded;
      }
      rule = PLACE_RULE[this.current];
      for (name in rule) {
        value = rule[name];
        this[name] = value;
      }
      css_list = [CSS.ng_list, CSS.video_info];
      if ((place_css = PLACE_CSS[this.current]) != null) {
        overwrite = place_css.overwrite;
        if ((css_part = place_css.ng_list) != null) {
          css_list[0] = (overwrite != null ? overwrite.ng_list : void 0) ? css_part : css_list[0] + '\n' + css_part;
        }
        if ((css_part = place_css.video_info) != null) {
          css_list[1] = (overwrite != null ? overwrite.video_info : void 0) ? css_part : css_list[1] + '\n' + css_part;
        }
      }
      this.css_full = css_list.join('\n');
      GM_addStyle(this.css_full);
      return this.current;
    };

    return Place;

  })();

  Util = (function() {
    function Util() {}

    Util.alert = function(msg) {
      if ((typeof GM_notification) !== 'function') {
        return alert(msg);
      } else {
        return GM_notification(msg);
      }
    };

    Util.treatError = function() {
      var node, node_list, _i, _len, _ref;
      node_list = document.querySelectorAll('[style*="visibility: hidden;"]');
      for (_i = 0, _len = node_list.length; _i < _len; _i++) {
        node = node_list[_i];
        if (node.style.visibility === 'hidden') {
          node.style.visibility = 'visible';
        }
      }
      if ((_ref = document.documentElement) != null) {
        _ref.classList.remove(NG.class_name.state.ng_enable);
      }
    };

    Util.errorHandle = function(_process) {
      var func;
      func = function() {
        var e;
        try {
          return _process.apply(this, arguments);
        } catch (_error) {
          e = _error;
          Util.treatError();
          throw e;
        }
      };
      return func;
    };

    Util.xpath = function(_query, _current, _all) {
      var i, len, node, nodes, result;
      if (_current == null) {
        _current = document;
      }
      if (_all == null) {
        _all = true;
      }
      if (_all) {
        result = document.evaluate(_query, _current, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        if ((len = result.snapshotLength)) {
          nodes = (function() {
            var _i, _results;
            _results = [];
            for (i = _i = 0; 0 <= len ? _i < len : _i > len; i = 0 <= len ? ++_i : --_i) {
              _results.push(result.snapshotItem(i));
            }
            return _results;
          })();
        } else {
          node = null;
        }
      } else {
        result = document.evaluate(_query, _current, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        nodes = result.singleNodeValue != null ? [result.singleNodeValue] : null;
      }
      return nodes;
    };

    Util.csss = function(_query, _current, _all) {
      var node, nodes;
      if (_current == null) {
        _current = document;
      }
      if (_all == null) {
        _all = true;
      }
      if (_all) {
        nodes = _current.querySelectorAll(_query);
      } else {
        nodes = (node = _current.querySelector(_query)) != null ? [node] : null;
      }
      return nodes;
    };

    Util.lookUp = function(_query, _current, _all) {
      var nodes;
      if ((_query.csss != null) || (_query.xpath != null)) {
        nodes = _query.csss != null ? this.csss(_query.csss, _current, _all) : this.xpath(_query.xpath, _current, _all);
      } else {
        nodes = null;
      }
      return nodes;
    };

    Util.setNGEnableInBody = function(_ng_enable) {
      if (_ng_enable) {
        document.documentElement.classList.add(NG.class_name.state.ng_enable);
      } else {
        document.documentElement.classList.remove(NG.class_name.state.ng_enable);
      }
    };

    Util.getNGStatus = function() {
      var en_val, ng_enable, ng_num, ng_status;
      ng_num = 0;
      ng_enable = false;
      ng_status = document.getElementById(NG.id.status);
      if (ng_status != null) {
        ng_num = Number(ng_status.getAttribute(NG.data.number));
        en_val = ng_status.getAttribute(NG.data.enable);
        if (en_val === NG.value["true"]) {
          ng_enable = true;
        } else {
          ng_enable = false;
        }
      }
      return [ng_enable, ng_num];
    };

    Util.setNGStatus = function(_ng_enable, _ng_num) {
      var ng_enable_val, ng_status, ng_text, pre_ng_enable, state;
      ng_status = document.getElementById(NG.id.status);
      if (ng_status != null) {
        if (_ng_num == null) {
          _ng_num = Number(ng_status.getAttribute(NG.data.number));
        }
        if (_ng_enable == null) {
          _ng_enable = ng_status.getAttribute(NG.data.enable);
        }
        pre_ng_enable = ng_status.getAttribute(NG.data.enable);
        if (_ng_enable !== pre_ng_enable) {
          this.setNGEnableInBody(_ng_enable);
          GM_setValue(NG.key.enable, _ng_enable);
        }
        if (_ng_enable) {
          ng_enable_val = NG.value["true"];
          state = "●";
        } else {
          ng_enable_val = NG.value["false"];
          state = "×";
        }
        ng_text = "NG (" + _ng_num + ")" + state;
        ng_status.setAttribute(NG.data.number, String(_ng_num));
        ng_status.setAttribute(NG.data.enable, ng_enable_val);
        ng_status.textContent = ng_text;
      }
    };

    Util.findInsertTarget = function(_target, _current) {
      var before, parent_node, _ref;
      parent_node = null;
      if (_target.before === false) {
        parent_node = _current != null ? _current.parentNode : void 0;
        before = _current != null ? _current.nextSibling : void 0;
      } else if (_target.before != null) {
        before = this.lookUp(_target.before, _current, false);
        if (before != null) {
          before = before[0];
          parent_node = before.parentNode;
        }
      } else {
        before = null;
        if (_target.parent != null) {
          if (_target.parent === true) {
            parent_node = _current;
          } else {
            parent_node = (_ref = this.lookUp(_target.parent, _current, false)) != null ? _ref[0] : void 0;
          }
        }
      }
      return [parent_node, before];
    };

    Util.toKeyFromTypeId = function(_type, _id) {
      var item_key;
      item_key = PF + _type + "_" + _id;
      return item_key;
    };

    Util.toTypeIdFromKey = function(_key) {
      var item_id, item_type, temp_type_id;
      temp_type_id = _key.split('_');
      item_type = temp_type_id[1];
      item_id = temp_type_id.slice(2).join('_');
      return [item_type, item_id];
    };

    Util.addClassToNodeSet = function(_target, _class) {
      var node, node_set, _i, _len;
      node_set = Place.findNodeSet(_target);
      for (_i = 0, _len = node_set.length; _i < _len; _i++) {
        node = node_set[_i];
        node.classList.add(_class);
      }
    };

    Util.removeClassFromNodeSet = function(_target, _class) {
      var node, node_set, _i, _len;
      node_set = Place.findNodeSet(_target);
      for (_i = 0, _len = node_set.length; _i < _len; _i++) {
        node = node_set[_i];
        node.classList.remove(_class);
      }
    };

    Util.setClassByKey = function(_key, _class, _enable) {
      var node, node_list, setFunc, type, video_node, _i, _j, _len, _len1;
      type = this.toTypeIdFromKey(_key)[0];
      node_list = document.getElementsByClassName(_key);
      if (_enable) {
        setFunc = this.addClassToNodeSet;
      } else {
        setFunc = this.removeClassFromNodeSet;
      }
      if (type === NG.type.tag) {
        for (_i = 0, _len = node_list.length; _i < _len; _i++) {
          node = node_list[_i];
          video_node = Place.findNode(node.parentNode.parentNode.parentNode);
          setFunc(video_node, _class);
        }
      } else {
        for (_j = 0, _len1 = node_list.length; _j < _len1; _j++) {
          node = node_list[_j];
          video_node = Place.findNode(node.parentNode.parentNode);
          setFunc(video_node, _class);
        }
      }
    };

    return Util;

  })();

  NGItemElement = (function() {
    function NGItemElement() {
      this.cbClick = __bind(this.cbClick, this);
    }

    NGItemElement.prototype.cbClick = function(_ev) {
      var item_key, last, li, ng_enable, ng_num, parent_node, _ref;
      li = _ev.target.parentNode;
      item_key = li.id;
      if (NGItemList.removeKey(item_key)) {
        last = li.nextElementSibling == null;
        parent_node = li.parentNode;
        parent_node.removeChild(li);
        Util.setClassByKey(item_key, NG.class_name.state.ng, false);
        _ref = Util.getNGStatus(), ng_enable = _ref[0], ng_num = _ref[1];
        ng_num -= 1;
        Util.setNGStatus(ng_enable, ng_num);
        if (last) {
          parent_node.style.display = 'none';
        }
      }
    };

    NGItemElement.prototype.make = function(_item_key, _item_name) {
      var a, a_text, item_id, item_type, li, title_text, _ref;
      li = document.createElement('li');
      a = document.createElement('a');
      li.id = _item_key;
      a.className = NG.class_name.item.ng;
      a.href = HREF_SCRIPT;
      _ref = Util.toTypeIdFromKey(_item_key), item_type = _ref[0], item_id = _ref[1];
      if (item_type !== NG.type.user && item_type !== NG.type.channel) {
        title_text = "クリックで " + item_type + ":" + _item_name + " のNG登録を解除します";
      } else {
        title_text = "クリックで " + item_type + ":" + _item_name + " (id:" + item_id + ") のNG登録を解除します";
      }
      a.title = title_text;
      a_text = document.createTextNode(item_type + ":" + _item_name);
      a.appendChild(a_text);
      a.addEventListener('click', this.cbClick, false);
      li.appendChild(a);
      return li;
    };

    NGItemElement.prototype.makeDirectNG = function(_item_key) {
      var item_id, item_type, li, p, p_text, title_text, _ref;
      li = document.createElement('li');
      p = document.createElement('p');
      li.id = _item_key;
      p.className = NG.class_name.item.direct_ng;
      _ref = Util.toTypeIdFromKey(_item_key), item_type = _ref[0], item_id = _ref[1];
      if (item_type !== NG.type.user && item_type !== NG.type.channel) {
        title_text = item_type + ":" + item_id;
      } else {
        title_text = "" + item_type + ":(id:" + item_id + ")";
      }
      p.title = title_text;
      p_text = document.createTextNode(title_text);
      p.appendChild(p_text);
      li.appendChild(p);
      return li;
    };

    return NGItemElement;

  })();

  NGListElement = (function() {
    function NGListElement(__ng_item) {
      this.__ng_item = __ng_item;
      this.cbClick = __bind(this.cbClick, this);
      this.__element = null;
    }

    NGListElement.prototype.cbMouseOver = function() {
      var ul;
      ul = document.getElementById(NG.id.list);
      if (ul.style.display === 'none') {
        ul.style.display = 'block';
      }
    };

    NGListElement.prototype.cbMouseOut = function() {
      var ul;
      ul = document.getElementById(NG.id.list);
      if (ul.style.display === 'block') {
        ul.style.display = 'none';
      }
    };

    NGListElement.prototype.cbClick = function(_ev) {
      var ng_enable, ng_num, _ref;
      _ref = Util.getNGStatus(), ng_enable = _ref[0], ng_num = _ref[1];
      ng_enable = !ng_enable;
      Util.setNGStatus(ng_enable, ng_num);
    };

    NGListElement.prototype.make = function(_ng_dict, _direct_ng_list, _ng_enable) {
      var a, item_key, item_name, li, ng_num, span, span_text, state, ul, _i, _len;
      ng_num = Object.keys(_ng_dict).length + _direct_ng_list.length;
      li = document.createElement('li');
      a = document.createElement('a');
      span = document.createElement('span');
      ul = document.createElement('ul');
      li.id = NG.id.base;
      li.className = NG.class_name.item.base;
      li.title = "クリックでNG機能の有効・無効を切り替えます";
      a.href = HREF_SCRIPT;
      span.id = NG.id.status;
      span.setAttribute(NG.data.number, ng_num);
      if (_ng_enable) {
        state = "●";
        span.setAttribute(NG.data.enable, NG.value["true"]);
      } else {
        state = "×";
        span.setAttribute(NG.data.enable, NG.value["false"]);
      }
      span_text = 'NG (' + String(ng_num) + ')' + state;
      span.appendChild(document.createTextNode(span_text));
      ul.style.display = 'none';
      ul.id = NG.id.list;
      li.onmouseover = this.cbMouseOver;
      li.onmouseout = this.cbMouseOut;
      a.addEventListener('click', this.cbClick, false);
      a.appendChild(span);
      li.appendChild(a);
      li.appendChild(ul);
      this.__element = li;
      for (item_key in _ng_dict) {
        item_name = _ng_dict[item_key];
        ul.appendChild(this.__ng_item.make(item_key, item_name));
      }
      for (_i = 0, _len = _direct_ng_list.length; _i < _len; _i++) {
        item_key = _direct_ng_list[_i];
        ul.appendChild(this.__ng_item.makeDirectNG(item_key));
      }
    };

    NGListElement.prototype.addToPage = function(_add_to) {
      var before, parent_node, _ref;
      _ref = Util.findInsertTarget(_add_to, null), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        parent_node.insertBefore(this.__element, before);
      }
    };

    NGListElement.prototype.addNGItemElement = function(_item_key, _item_name) {
      var before, new_li, ul;
      ul = this.__element.lastElementChild;
      new_li = this.__ng_item.make(_item_key, _item_name);
      before = ul.firstElementChild;
      while ((before != null ? before.firstElementChild.className : void 0) === NG.class_name.item.ng) {
        before = before.nextElementSibling;
      }
      ul.insertBefore(new_li, before);
    };

    return NGListElement;

  })();

  NGListElementInNicopedia = (function(_super) {
    __extends(NGListElementInNicopedia, _super);

    function NGListElementInNicopedia(__ng_item) {
      this.__ng_item = __ng_item;
      this.cbClick = __bind(this.cbClick, this);
      this.__element = null;
    }

    NGListElementInNicopedia.prototype.cbMouseOver = function() {
      var ul;
      ul = document.getElementById(NG.id.list);
      if (ul.style.display === 'none') {
        ul.style.display = 'block';
      }
    };

    NGListElementInNicopedia.prototype.cbMouseOut = function() {
      var ul;
      ul = document.getElementById(NG.id.list);
      if (ul.style.display === 'block') {
        ul.style.display = 'none';
      }
    };

    NGListElementInNicopedia.prototype.cbClick = function(_ev) {
      var ng_enable, ng_num, _ref;
      _ref = Util.getNGStatus(), ng_enable = _ref[0], ng_num = _ref[1];
      ng_enable = !ng_enable;
      Util.setNGStatus(ng_enable, ng_num);
    };

    NGListElementInNicopedia.prototype.make = function(_ng_dict, _direct_ng_list, _ng_enable) {
      var a, item_key, item_name, ng_num, span, span_text, state, table, tbody, td_base, td_menu, tr, ul, _i, _len;
      ng_num = Object.keys(_ng_dict).length + _direct_ng_list.length;
      td_base = document.createElement('td');
      table = document.createElement('table');
      tbody = document.createElement('tbody');
      tr = document.createElement('tr');
      td_menu = document.createElement('td');
      a = document.createElement('a');
      span = document.createElement('span');
      ul = document.createElement('ul');
      td_base.id = NG.id.base;
      td_base.class_name = NG.class_name.item.base;
      td_base.title = "クリックでNG機能の有効・無効を切り替えます";
      a.href = HREF_SCRIPT;
      span.id = NG.id.status;
      span.setAttribute(NG.data.number, ng_num);
      if (_ng_enable) {
        state = "●";
        span.setAttribute(NG.data.enable, NG.value["true"]);
      } else {
        state = "×";
        span.setAttribute(NG.data.enable, NG.value["false"]);
      }
      span_text = 'NG (' + String(ng_num) + ')' + state;
      span.appendChild(document.createTextNode(span_text));
      ul.style.display = 'none';
      ul.id = NG.id.list;
      td_base.onmouseover = this.cbMouseOver;
      td_base.onmouseout = this.cbMouseOut;
      ul.onmouseover = this.cbMouseOver;
      ul.onmouseout = this.cbMouseOut;
      a.addEventListener('click', this.cbClick, false);
      a.appendChild(span);
      td_menu.appendChild(a);
      tr.appendChild(td_menu);
      tbody.appendChild(tr);
      table.appendChild(tbody);
      td_base.appendChild(table);
      td_base.appendChild(ul);
      this.__element = td_base;
      for (item_key in _ng_dict) {
        item_name = _ng_dict[item_key];
        ul.appendChild(this.__ng_item.make(item_key, item_name));
      }
      for (_i = 0, _len = _direct_ng_list.length; _i < _len; _i++) {
        item_key = _direct_ng_list[_i];
        ul.appendChild(this.__ng_item.makeDirectNG(item_key));
      }
    };

    NGListElementInNicopedia.prototype.addToPage = function(_add_to) {
      var before, parent_node, _ref;
      _ref = Util.findInsertTarget(_add_to, null), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        parent_node.insertBefore(this.__element, before);
      }
    };

    NGListElementInNicopedia.prototype.addNGItemElement = function(_item_key, _item_name) {
      var before, new_li, ul;
      ul = this.__element.lastElementChild;
      new_li = this.__ng_item.make(_item_key, _item_name);
      before = ul.firstElementChild;
      while ((before != null ? before.firstElementChild.className : void 0) === NG.class_name.item.ng) {
        before = before.nextElementSibling;
      }
      ul.insertBefore(new_li, before);
    };

    return NGListElementInNicopedia;

  })(NGListElement);

  NGItemList = (function() {
    function NGItemList() {}

    NGItemList.__list_elem = null;

    NGItemList.__ng_dict = {};

    NGItemList.__direct_ng_list = [];

    NGItemList.__getDirectNGList = function() {
      var direct_ng_list, error_msg, id, ng_item, num, parse_list, type, valid, _i, _len;
      parse_list = JSON.parse(DIRECT_NG);
      direct_ng_list = [];
      error_msg = "";
      for (num = _i = 0, _len = parse_list.length; _i < _len; num = ++_i) {
        ng_item = parse_list[num];
        valid = true;
        if (ng_item.length !== 2) {
          valid = false;
          error_msg += "index: " + num + ", value: [" + (ng_item.toString()) + "]; NG項目の指定に必要な要素は2つ(種類、IDまたはタグ名)です。\n";
        } else {
          type = NG.type[ng_item[0]];
          id = ng_item[1];
          if (type == null) {
            valid = false;
            error_msg += "index: " + num + ", value: " + ng_item[0] + "; NG項目の種類の指定が正しくありません。\n";
          } else if (isNaN(id) && (type !== NG.type.tag)) {
            valid = false;
            error_msg += "index: " + num + ", value: " + id + "; NG項目のIDが数値に変換できません。\n";
          }
        }
        if (valid) {
          direct_ng_list.push(Util.toKeyFromTypeId(type, id));
        }
      }
      if (error_msg) {
        Util.alert(error_msg);
      }
      return direct_ng_list;
    };

    NGItemList.init = function(_place_label) {
      var e, ng_enable, ng_id, ng_item, ng_list, _i, _len;
      ng_item = Place.getNGItem();
      this.__list_elem = Place.getNGList(ng_item);
      try {
        this.__direct_ng_list = this.__getDirectNGList();
      } catch (_error) {
        e = _error;
        this.__direct_ng_list = [];
        Util.alert("JSON文字列でのNGリストの指定に失敗\n\n" + e.message);
      }
      ng_list = GM_listValues();
      for (_i = 0, _len = ng_list.length; _i < _len; _i++) {
        ng_id = ng_list[_i];
        if (__indexOf.call(this.__direct_ng_list, ng_id) < 0) {
          this.__ng_dict[decodeURI(ng_id)] = GM_getValue(ng_id);
        }
      }
      ng_enable = this.__ng_dict[NG.key.enable];
      if (ng_enable != null) {
        delete this.__ng_dict[NG.key.enable];
      } else {
        ng_enable = true;
        GM_setValue(NG.key.enable, ng_enable);
      }
    };

    NGItemList.addElementToPage = function() {
      var add_to, ng_enable;
      ng_enable = GM_getValue(NG.key.enable);
      this.__list_elem.make(this.__ng_dict, this.__direct_ng_list, ng_enable);
      add_to = Place.add_to;
      this.__list_elem.addToPage(add_to);
      Util.setNGEnableInBody(ng_enable);
    };

    NGItemList.__addKey = function(_key, _name) {
      this.__ng_dict[_key] = _name;
      GM_setValue(encodeURI(_key), _name);
    };

    NGItemList.removeKey = function(_key) {
      var removable;
      removable = !(__indexOf.call(this.__direct_ng_list, _key) >= 0);
      if (removable) {
        delete this.__ng_dict[_key];
        GM_deleteValue(encodeURI(_key));
      }
      return removable;
    };

    NGItemList.contains = function(_item_key) {
      var result;
      result = (_item_key in this.__ng_dict) || (__indexOf.call(this.__direct_ng_list, _item_key) >= 0);
      return result;
    };

    NGItemList.addNGItem = function(_item_key, _item_name) {
      var addable, ng_enable, ng_num, _ref;
      addable = !this.contains(_item_key);
      if (addable) {
        _ref = Util.getNGStatus(), ng_enable = _ref[0], ng_num = _ref[1];
        ng_num += 1;
        Util.setNGStatus(ng_enable, ng_num);
        this.__addKey(_item_key, _item_name);
        this.__list_elem.addNGItemElement(_item_key, _item_name);
        Util.setClassByKey(_item_key, NG.class_name.state.ng, true);
      }
    };

    return NGItemList;

  })();

  VideoInfoElement = (function() {
    function VideoInfoElement() {
      this.cbClickItem = __bind(this.cbClickItem, this);
      this.__template = this.__makeTemplate();
      this.__push = Array.prototype.push;
      this.__manager = null;
    }

    VideoInfoElement.prototype.__makeTemplate = function() {
      var community, community_wrap, info_base, tag_base, tag_base_wrap, tag_list, title, uploader, uploader_wrap, video_id, video_id_wrap;
      info_base = document.createElement('span');
      title = document.createElement('span');
      video_id_wrap = document.createElement('span');
      video_id = document.createElement('span');
      uploader_wrap = document.createElement('span');
      uploader = document.createElement('span');
      tag_base_wrap = document.createElement('span');
      tag_base = document.createElement('span');
      tag_list = document.createElement('span');
      community_wrap = document.createElement('span');
      community = document.createElement('span');
      info_base.className = NG.class_name.item.video_info;
      title.className = NG.class_name.item.title;
      title.appendChild(document.createTextNode("title"));
      video_id.className = NG.class_name.item.video_id;
      video_id_wrap.appendChild(document.createTextNode("動画ID: "));
      video_id.appendChild(document.createTextNode(""));
      uploader.className = NG.class_name.item.uploader;
      uploader_wrap.appendChild(document.createTextNode("type: "));
      uploader.appendChild(document.createTextNode(""));
      tag_base_wrap.appendChild(document.createTextNode(""));
      tag_base.className = NG.class_name.item.tag_base;
      tag_base.appendChild(document.createTextNode("タグ >"));
      tag_list.className = NG.class_name.item.tag_list;
      tag_list.style.display = 'none';
      community.className = NG.class_name.item.community;
      community_wrap.appendChild(document.createTextNode("コミュID: "));
      community.appendChild(document.createTextNode(""));
      tag_base_wrap.appendChild(tag_base);
      video_id_wrap.appendChild(video_id);
      uploader_wrap.appendChild(uploader);
      community_wrap.appendChild(community);
      info_base.appendChild(title);
      info_base.appendChild(video_id_wrap);
      info_base.appendChild(uploader_wrap);
      info_base.appendChild(tag_base_wrap);
      info_base.appendChild(tag_list);
      info_base.appendChild(community_wrap);
      return info_base;
    };

    VideoInfoElement.prototype.setRetryManager = function(_manager) {
      _manager.setForRetry();
      this.__manager = _manager;
    };

    VideoInfoElement.prototype.cbClickItem = function(_ev) {
      var id, key, name, node, tag_base_wrap, tag_list, type, _ref;
      node = _ev.target;
      key = node.className.split(' ')[1];
      _ref = Util.toTypeIdFromKey(key), type = _ref[0], id = _ref[1];
      if (type === NG.type.tag) {
        name = node.firstChild.nodeValue;
        tag_list = node.parentNode.parentNode;
      } else {
        name = node.firstChild.nodeValue;
        tag_list = node.parentNode.parentNode.getElementsByClassName(NG.class_name.item.tag_list)[0];
      }
      name = node.firstChild.nodeValue;
      NGItemList.addNGItem(key, name);
      if (tag_list.style.display !== 'none') {
        tag_list.style.display = 'none';
        tag_base_wrap = tag_list.previousElementSibling;
        tag_base_wrap.lastElementChild.title = "クリックでタグの一覧を表示します";
      }
    };

    VideoInfoElement.prototype.cbClickTagBase = function(_ev) {
      var tag_base, tag_base_wrap, tag_list;
      tag_base = _ev.target;
      tag_base_wrap = tag_base.parentNode;
      tag_list = tag_base_wrap.nextElementSibling;
      if (tag_list.style.display === 'none') {
        tag_list.style.display = '';
        tag_base.title = "クリックでタグの一覧を非表示にします";
      } else {
        tag_list.style.display = 'none';
        tag_base.title = "クリックでタグの一覧を表示します";
      }
    };

    VideoInfoElement.prototype.make = function() {
      var info_base;
      info_base = this.__template.cloneNode(true);
      return info_base;
    };

    VideoInfoElement.prototype.write = function(_info, _info_node) {
      var community, community_key, community_wrap, key_list, tag_base, tag_base_wrap, tag_elem, tag_elem_wrap, tag_key, tag_key_list, tag_list, tag_name, title, type_text, uploader, uploader_key, uploader_wrap, video_id, video_id_wrap, video_key, _i, _len, _ref;
      title = _info_node.getElementsByClassName(NG.class_name.item.title)[0];
      video_id = _info_node.getElementsByClassName(NG.class_name.item.video_id)[0];
      video_id_wrap = video_id.parentNode;
      uploader = _info_node.getElementsByClassName(NG.class_name.item.uploader)[0];
      uploader_wrap = uploader.parentNode;
      tag_base = _info_node.getElementsByClassName(NG.class_name.item.tag_base)[0];
      tag_base_wrap = tag_base.parentNode;
      tag_list = _info_node.getElementsByClassName(NG.class_name.item.tag_list)[0];
      community = _info_node.getElementsByClassName(NG.class_name.item.community)[0];
      community_wrap = community.parentNode;
      title.firstChild.nodeValue = _info.title;
      video_key = Util.toKeyFromTypeId(NG.type.video, _info.id);
      video_id.firstChild.nodeValue = _info.id;
      video_id.title = "クリックで video id:" + _info.id + " の動画を非表示にします";
      video_id.classList.add(video_key);
      type_text = _info.type === NG.type.user ? "投稿者: " : "チャンネル: ";
      uploader_wrap.firstChild.nodeValue = type_text;
      uploader.title = "クリックで " + type_text + ": " + _info.uploader_name + " の動画を非表示にします";
      uploader_key = Util.toKeyFromTypeId(_info.type, _info.uploader_id);
      uploader.firstChild.nodeValue = _info.uploader_name;
      uploader.classList.add(uploader_key);
      if (_info.community_id != null) {
        community.title = "クリックで community id: " + _info.community_id + " の動画を非表示にします";
        community_key = Util.toKeyFromTypeId(NG.type.community, _info.community_id);
        community.firstChild.nodeValue = _info.community_id;
        community.classList.add(community_key);
      } else {
        community_wrap.className = NG.class_name.state.no_community;
      }
      tag_base.title = "クリックでタグの一覧を表示します";
      video_id.addEventListener('click', this.cbClickItem, false);
      uploader.addEventListener('click', this.cbClickItem, false);
      community.addEventListener('click', this.cbClickItem, false);
      tag_base.addEventListener('click', this.cbClickTagBase, false);
      tag_key_list = [];
      _ref = _info.tags;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        tag_name = _ref[_i];
        tag_elem_wrap = document.createElement('span');
        tag_elem = document.createElement('span');
        tag_elem.className = NG.class_name.item.tag;
        tag_key = Util.toKeyFromTypeId(NG.type.tag, tag_name);
        tag_elem.classList.add(tag_key);
        tag_elem.appendChild(document.createTextNode(tag_name));
        tag_elem.title = "クリックで tag: " + tag_name + " の動画を非表示にします";
        tag_elem.addEventListener('click', this.cbClickItem, false);
        tag_elem_wrap.appendChild(tag_elem);
        tag_list.appendChild(tag_elem_wrap);
        tag_key_list.push(tag_key);
      }
      key_list = [video_key, uploader_key, community_key].concat(tag_key_list);
      return key_list;
    };

    VideoInfoElement.prototype.__genCbClickNotFoundVisible = function(_video) {
      var func;
      func = function(_ev) {
        if (_video.node.classList.contains(NG.class_name.state.other)) {
          _video.node.classList.remove(NG.class_name.state.other);
          _ev.target.title = "クリックでこの動画を不可視にします (注意:この動画はNG未確認です)";
        } else {
          _video.node.classList.add(NG.class_name.state.other);
          _ev.target.title = "クリックでこの動画を可視にします (注意:この動画はNG未確認です)";
        }
      };
      return func;
    };

    VideoInfoElement.prototype.__genCbRetry = function(_video) {
      var func;
      func = (function(_this) {
        return function(_ev) {
          var new_info_elem, old_info_elem;
          new_info_elem = _this.make();
          old_info_elem = _video.info_elem;
          old_info_elem.parentNode.replaceChild(new_info_elem, old_info_elem);
          _video.info_elem = new_info_elem;
          if (!Place.previsible.at_loaded) {
            Util.addClassToNodeSet(_video.node, NG.class_name.state.undef);
          }
          Util.removeClassFromNodeSet(_video.node, NG.class_name.state.failed);
          _this.__manager.add([_video]);
        };
      })(this);
      return func;
    };

    VideoInfoElement.prototype.cbClickNotFoundRetry = function() {
      var ev, retry_list, video_node, _i, _len;
      ev = new Event(NG.event.retry);
      retry_list = document.querySelectorAll('.' + NG.class_name.state.failed);
      for (_i = 0, _len = retry_list.length; _i < _len; _i++) {
        video_node = retry_list[_i];
        if (video_node != null) {
          video_node.dispatchEvent(ev);
        }
      }
    };

    VideoInfoElement.prototype.writeNotFound = function(_type, _video) {
      var tag_base, tag_base_wrap;
      tag_base = _video.info_elem.getElementsByClassName(NG.class_name.item.tag_base)[0];
      tag_base.firstChild.nodeValue = _type;
      tag_base_wrap = tag_base.parentNode;
      tag_base_wrap.firstChild.nodeValue = "取得失敗: ";
      if ((_type === 'ERROR') || (_type === 'TIMEOUT') || (_type === 'ABORT') || (_type === 'BUSY')) {
        _video.node.addEventListener(NG.event.retry, this.__genCbRetry(_video), false);
        Util.addClassToNodeSet(_video.node, NG.class_name.state.failed);
        tag_base.title = "クリックで動画情報の再取得を試みます";
        tag_base.addEventListener('click', this.cbClickNotFoundRetry, false);
      } else if ((_type !== 'DELETED') && (_type !== 'NOT_FOUND')) {
        tag_base.title = "クリックでこの動画を可視にします (注意:この動画はNG未確認です)";
        tag_base.addEventListener('click', this.__genCbClickNotFoundVisible(_video), false);
        Util.addClassToNodeSet(_video.node, NG.class_name.state.other);
      } else {
        Util.addClassToNodeSet(_video.node, NG.class_name.state.ng);
      }
    };

    return VideoInfoElement;

  })();

  VideoInfoInserter = (function() {
    function VideoInfoInserter(_label, _param_set, __video_info_elem) {
      this.__video_info_elem = __video_info_elem;
      this.__param = new InserterParameter(_label, _param_set);
    }

    VideoInfoInserter.prototype.__checkNG = function(_video, _key_list) {
      var key, ng, _i, _len;
      ng = false;
      for (_i = 0, _len = _key_list.length; _i < _len; _i++) {
        key = _key_list[_i];
        if (NGItemList.contains(key)) {
          ng = true;
          break;
        }
      }
      if (ng) {
        Util.setClassByKey(key, NG.class_name.state.ng, true);
      }
    };

    VideoInfoInserter.prototype.insertElement = function(_video_node) {
      var before, elem, parent_node, _ref;
      elem = this.__video_info_elem.make();
      elem.style.display = 'none';
      _ref = Util.findInsertTarget(this.__param.target, _video_node), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        parent_node.insertBefore(elem, before);
      }
      if (!Place.previsible.at_loaded) {
        Util.addClassToNodeSet(_video_node, NG.class_name.state.undef);
      }
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.ng);
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.failed);
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.other);
      elem.style.display = '';
      return [elem, _video_node];
    };

    VideoInfoInserter.prototype.insertInfo = function(_video, _info) {
      var key_list;
      key_list = this.__video_info_elem.write(_info, _video.info_elem);
      this.__checkNG(_video, key_list);
      Util.removeClassFromNodeSet(_video.node, NG.class_name.state.undef);
    };

    VideoInfoInserter.prototype.insertNotFoundInfo = function(_video, _type) {
      this.__video_info_elem.writeNotFound(_type, _video);
      Util.removeClassFromNodeSet(_video.node, NG.class_name.state.undef);
    };

    return VideoInfoInserter;

  })();

  DelayInserter = (function(_super) {
    __extends(DelayInserter, _super);

    function DelayInserter() {
      return DelayInserter.__super__.constructor.apply(this, arguments);
    }

    DelayInserter.prototype.insertElement = function(_video_node) {
      var elem;
      elem = this.__video_info_elem.make();
      if (!Place.previsible.at_loaded) {
        Util.addClassToNodeSet(_video_node, NG.class_name.state.undef);
      }
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.ng);
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.failed);
      Util.removeClassFromNodeSet(_video_node, NG.class_name.state.other);
      return [elem, _video_node];
    };

    DelayInserter.prototype.insertInfo = function(_video, _info) {
      var before, children, key_list, parent_node, _ref;
      key_list = this.__video_info_elem.write(_info, _video.info_elem);
      _video.info_elem.style.display = 'none';
      _ref = Util.findInsertTarget(this.__param.target, _video.node), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        children = parent_node.children;
        if (children.length) {
          parent_node.replaceChild(_video.info_elem, children[0]);
        } else {
          parent_node.insertBefore(_video.info_elem, before);
        }
      }
      this.__checkNG(_video, key_list);
      Util.removeClassFromNodeSet(_video.node, NG.class_name.state.undef);
      _video.info_elem.style.display = '';
    };

    DelayInserter.prototype.insertNotFoundInfo = function(_video, _type) {
      var before, parent_node, _ref;
      this.__video_info_elem.writeNotFound(_type, _video);
      _video.info_elem.style.display = 'none';
      _ref = Util.findInsertTarget(this.__param.target, _video.node), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        parent_node.insertBefore(_video.info_elem, before);
      }
      Util.removeClassFromNodeSet(_video.node, NG.class_name.state.undef);
      _video.info_elem.style.display = '';
    };

    return DelayInserter;

  })(VideoInfoInserter);

  InserterWithWrap = (function(_super) {
    __extends(InserterWithWrap, _super);

    function InserterWithWrap() {
      return InserterWithWrap.__super__.constructor.apply(this, arguments);
    }

    InserterWithWrap.prototype.insertElement = function(_video_node) {
      var before, elem, node_style, node_wrap, parent_node, wrap_before, wrap_parent, _ref;
      node_wrap = document.createElement('span');
      wrap_parent = _video_node.parentNode;
      wrap_before = _video_node.nextSibling;
      node_wrap.className = NG.class_name.item.video_wrap;
      node_style = window.getComputedStyle(_video_node, null);
      if (node_style.width != null) {
        node_wrap.style.width = node_style.width;
      }
      if (node_style.float != null) {
        node_wrap.style.float = node_style.float;
        _video_node.style.float = 'none';
      }
      if (node_style.margin != null) {
        node_wrap.style.margin = node_style.margin;
        _video_node.style.margin = '0px';
      }
      wrap_parent.removeChild(_video_node);
      node_wrap.appendChild(_video_node);
      wrap_parent.insertBefore(node_wrap, wrap_before);
      elem = this.__video_info_elem.make();
      elem.style.display = 'none';
      _ref = Util.findInsertTarget(this.__param.target, node_wrap), parent_node = _ref[0], before = _ref[1];
      if (parent_node != null) {
        parent_node.insertBefore(elem, before);
      }
      if (!Place.previsible.at_loaded) {
        Util.addClassToNodeSet(node_wrap, NG.class_name.state.undef);
      }
      elem.style.display = '';
      return [elem, node_wrap];
    };

    return InserterWithWrap;

  })(VideoInfoInserter);

  VideoInfoFinder = (function() {
    function VideoInfoFinder(_label, _param_set, __inserter) {
      this.__inserter = __inserter;
      this.find = __bind(this.find, this);
      this.__param = new FinderParameter(_label, _param_set);
      this.__next_finder = new CommunityVideoInfoFinder(_label, _param_set, this.__inserter);
      this.__method = 'GET';
      this.__header = HEADER;
      this.__parser = parser;
      this.request_time = [0];
    }

    VideoInfoFinder.prototype.__searchInfo = function(_xmlstr) {
      var dom, fail_type, res_status, tag, tag_list, up_id, up_name, up_type, video_id, video_info, video_name, video_tags;
      dom = this.__parser.parseFromString(_xmlstr, 'application/xml');
      res_status = dom.getElementsByTagName('nicovideo_thumb_response')[0].getAttribute('status');
      if (res_status === 'ok') {
        video_name = dom.getElementsByTagName('title')[0].textContent;
        tag_list = dom.getElementsByTagName('tag');
        video_tags = (function() {
          var _i, _len, _results;
          _results = [];
          for (_i = 0, _len = tag_list.length; _i < _len; _i++) {
            tag = tag_list[_i];
            _results.push(tag.textContent);
          }
          return _results;
        })();
        video_id = dom.getElementsByTagName('video_id')[0].textContent;
        if (video_id.slice(0, 2) === 'so') {
          up_type = NG.type.channel;
          up_name = dom.getElementsByTagName('ch_name')[0].textContent;
          up_id = dom.getElementsByTagName('ch_id')[0].textContent;
        } else {
          up_type = NG.type.user;
          up_name = dom.getElementsByTagName('user_nickname')[0].textContent;
          up_id = dom.getElementsByTagName('user_id')[0].textContent;
        }
        video_info = {
          type: up_type,
          uploader_name: up_name,
          uploader_id: up_id,
          tags: video_tags,
          title: video_name,
          id: video_id
        };
      } else {
        fail_type = dom.getElementsByTagName('code')[0].textContent;
        video_info = {
          code: fail_type
        };
      }
      return [res_status, video_info];
    };

    VideoInfoFinder.prototype.__genCbLoad = function(_video) {
      var func;
      func = (function(_this) {
        return function(_res) {
          var res_status, video_info, _ref;
          _ref = _this.__searchInfo(_res.responseText), res_status = _ref[0], video_info = _ref[1];
          if (res_status === 'ok') {
            _this.__inserter.insertInfo(_video, video_info);
          } else {
            if (video_info.code === 'COMMUNITY') {
              _this.__next_finder.find(_video, 0, _this.__param.chain_latency);
            } else {
              _this.__inserter.insertNotFoundInfo(_video, video_info.code);
            }
          }
        };
      })(this);
      return Util.errorHandle(func);
    };

    VideoInfoFinder.prototype.__genCbFail = function(_video, _type, _count) {
      var func;
      if (_count < this.__param.retry.count) {
        _count += 1;
        func = (function(_this) {
          return function(_res) {
            setTimeout(Util.errorHandle(_this.find), _this.__param.retry.wait * _count, _video, _count);
          };
        })(this);
      } else {
        func = (function(_this) {
          return function(_res) {
            _this.__inserter.insertNotFoundInfo(_video, _type);
          };
        })(this);
      }
      return Util.errorHandle(func);
    };

    VideoInfoFinder.prototype.find = function(_video, _count, _wait) {
      var onabort_func, onerror_func, onload_func, ontimeout_func, _ref;
      onload_func = this.__genCbLoad(_video);
      onerror_func = this.__genCbFail(_video, "ERROR", _count);
      onabort_func = this.__genCbFail(_video, "ABORT", _count);
      ontimeout_func = this.__genCbFail(_video, "TIMEOUT", _count);
      GM_xmlhttpRequest({
        method: this.__method,
        headers: this.__header,
        url: this.__param.destination.prepend + _video.id + this.__param.destination.append,
        timeout: this.__param.timeout,
        onload: onload_func,
        onerror: onerror_func,
        ontimeout: ontimeout_func,
        onabort: onabort_func
      });
      if ((_ref = this.request_time) != null) {
        _ref[0] = Date.now();
      }
    };

    return VideoInfoFinder;

  })();

  CommunityVideoInfoFinder = (function(_super) {
    __extends(CommunityVideoInfoFinder, _super);

    function CommunityVideoInfoFinder(_label, _param_set, __inserter) {
      this.__inserter = __inserter;
      this.find = __bind(this.find, this);
      this.__param = new FinderParameter(_label, _param_set);
      this.__next_finder = new UserNameFinder(_label, _param_set, this.__inserter);
      this.__method = 'GET';
      this.__header = HEADER;
      this.__parser = parser;
      this.__param.destination = DEST.nicoapi;
      this.request_time = [0];
    }

    CommunityVideoInfoFinder.prototype.__searchInfo = function(_xmlstr) {
      var commu_id, deleted, dom, fail_type, res_status, tag, tag_list, up_id, up_type, video_id, video_info, video_name, video_tags;
      dom = this.__parser.parseFromString(_xmlstr, 'application/xml');
      res_status = dom.getElementsByTagName('nicovideo_video_response')[0].getAttribute('status');
      if (res_status === 'ok') {
        deleted = Number(dom.getElementsByTagName('deleted')[0].textContent);
        if (deleted === 0) {
          video_name = dom.getElementsByTagName('title')[0].textContent;
          tag_list = dom.getElementsByTagName('tag');
          video_tags = (function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = tag_list.length; _i < _len; _i++) {
              tag = tag_list[_i];
              _results.push(tag.textContent);
            }
            return _results;
          })();
          video_id = dom.getElementsByTagName('id')[0].textContent;
          commu_id = dom.getElementsByTagName('community_id')[0].textContent;
          up_id = dom.getElementsByTagName('user_id')[0].textContent;
          up_type = video_id.slice(0, 2) === 'so' ? NG.type.channel : NG.type.user;
          video_info = {
            type: up_type,
            uploader_name: "(id:" + up_id + ")",
            uploader_id: up_id,
            tags: video_tags,
            title: video_name,
            id: video_id,
            community_id: commu_id
          };
        } else {
          res_status = 'fail';
          fail_type = 'DELETED';
          video_info = {
            code: fail_type
          };
        }
      } else {
        fail_type = dom.getElementsByTagName('code')[0].textContent;
        video_info = {
          code: fail_type
        };
      }
      return [res_status, video_info];
    };

    CommunityVideoInfoFinder.prototype.__genCbLoad = function(_video) {
      var func;
      func = (function(_this) {
        return function(_res) {
          var id, res_status, video_info, _ref;
          _ref = _this.__searchInfo(_res.responseText), res_status = _ref[0], video_info = _ref[1];
          if (res_status === 'ok') {
            _video['temp_info'] = video_info;
            id = video_info;
            _this.__next_finder.find(_video, 0, _this.__param.chain_latency);
          } else {
            _this.__inserter.insertNotFoundInfo(_video, video_info.code);
          }
        };
      })(this);
      return Util.errorHandle(func);
    };

    CommunityVideoInfoFinder.prototype.find = function(_video, _count, _wait) {
      CommunityVideoInfoFinder.__super__.find.call(this, _video, _count, _wait);
    };

    return CommunityVideoInfoFinder;

  })(VideoInfoFinder);

  UserNameFinder = (function(_super) {
    __extends(UserNameFinder, _super);

    function UserNameFinder(_label, _param_set, __inserter) {
      this.__inserter = __inserter;
      this.find = __bind(this.find, this);
      this.__param = new FinderParameter(_label, _param_set);
      this.__method = 'GET';
      this.__header = HEADER;
      this.__parser = parser;
      this.__param.destination = DEST.user;
    }

    UserNameFinder.prototype.__searchInfo = function(_xmlstr) {
      var dom, nickname, up_name;
      dom = this.__parser.parseFromString(_xmlstr, 'application/xml');
      nickname = dom.getElementsByTagName('nickname');
      if (nickname.length) {
        up_name = nickname[0].textContent;
      } else {
        up_name = null;
      }
      return up_name;
    };

    UserNameFinder.prototype.__genCbLoad = function(_video) {
      var func;
      func = (function(_this) {
        return function(_res) {
          var up_name, video_info;
          up_name = _this.__searchInfo(_res.responseText);
          video_info = _video.temp_info;
          _video.id = video_info.id;
          delete _video.temp_info;
          if (up_name != null) {
            video_info.uploader_name = up_name;
          }
          _this.__inserter.insertInfo(_video, video_info);
        };
      })(this);
      return Util.errorHandle(func);
    };

    UserNameFinder.prototype.__genCbFail = function(_video, _type, _count) {
      var func;
      if (_count < this.__param.retry.count) {
        _count += 1;
        func = (function(_this) {
          return function(_res) {
            _video.id = _video.temp_info.id;
            _this.find(_video, _count, _this.__param.retry.wait);
          };
        })(this);
      } else {
        func = (function(_this) {
          return function(_res) {
            var video_info;
            _video.id = _video.temp_info.id;
            video_info = _video.temp_info;
            delete _video.temp_info;
            _this.__inserter.insertInfo(_video, video_info);
          };
        })(this);
      }
      return Util.errorHandle(func);
    };

    UserNameFinder.prototype.find = function(_video, _count, _wait) {
      _video.id = _video.temp_info.uploader_id;
      UserNameFinder.__super__.find.call(this, _video, _count, _wait);
    };

    return UserNameFinder;

  })(VideoInfoFinder);

  UadVideoIdFinder = (function(_super) {
    __extends(UadVideoIdFinder, _super);

    function UadVideoIdFinder(_label, _param_set, __inserter) {
      this.__inserter = __inserter;
      this.find = __bind(this.find, this);
      this.__param = new FinderParameter(_label, _param_set);
      this.__next_finder = new VideoInfoFinder(_label, _param_set, this.__inserter);
      this.__method = 'HEAD';
      this.__header = HEADER;
      this.__parser = parser;
      this.__param.destination = DEST.uad;
      this.request_time = [0];
    }

    UadVideoIdFinder.prototype.__genCbLoad = function(_video) {
      var func;
      func = (function(_this) {
        return function(_res) {
          var video_id, _ref;
          if (_res.finalUrl == null) {
            _this.__inserter.insertNotFoundInfo(_video, "NOT_FOUND_VIDEOID");
            return;
          }
          if ((video_id = (_ref = _res.finalUrl.match(_this.__param.regexp)) != null ? _ref[1] : void 0) != null) {
            _video.id = video_id;
            _this.__next_finder.find(_video, 0, _this.__param.chain_latency);
          } else {
            _this.__inserter.insertNotFoundInfo(_video, "ERROR");
          }
        };
      })(this);
      return func;
    };

    UadVideoIdFinder.prototype.find = function(_video, _count, _wait) {
      if (_video.id[0] === '=') {
        UadVideoIdFinder.__super__.find.call(this, _video, _count, _wait);
      } else {
        this.__next_finder.find(_video, 0, this.__param.chain_latency);
      }
    };

    return UadVideoIdFinder;

  })(VideoInfoFinder);

  RequestQueManager = (function() {
    function RequestQueManager(__label, _param_set, __finder) {
      this.__label = __label;
      this.__finder = __finder;
      this.cbWork = __bind(this.cbWork, this);
      this.__param = new ManagerParameter(this.__label, _param_set);
      this.__video_que = [];
      this.__timer_id = null;
      this.__count = 0;
      this.cbRefDeleteManager = NicovideoNGSystem.cbDeleteManager;
    }

    RequestQueManager.prototype.setForRetry = function() {
      this.__label = this.__label + "retry";
      this.__param.deletable = false;
    };

    RequestQueManager.prototype.add = function(_video_list) {
      var ended;
      ended = !this.__video_que.length;
      this.__video_que.push.apply(this.__video_que, _video_list);
      if (ended) {
        setTimeout(Util.errorHandle(this.cbWork), this.__param.latency);
      }
    };

    RequestQueManager.prototype.cbWork = function() {
      var add_interval, delta_time, interval, video;
      if ((video = this.__video_que.shift()) != null) {
        delta_time = Date.now() - this.__finder.request_time[0];
        if (delta_time < this.__param.quick.interval) {
          add_interval = this.__param.quick.interval - delta_time;
          setTimeout(Util.errorHandle(this.__finder.find), add_interval, video, 0, 0);
        } else {
          add_interval = 0;
          this.__finder.find(video, 0, 0);
        }
        if (this.__count < this.__param.quick.count) {
          this.__count += 1;
          interval = this.__param.quick.interval;
        } else {
          interval = this.__param.interval;
        }
        this.__timer_id = setTimeout(Util.errorHandle(this.cbWork), interval + add_interval);
      } else {
        this.__timer_id = null;
        this.__count = 0;
        if (this.__param.deletable) {
          setTimeout(Util.errorHandle(this.cbRefDeleteManager), 0, this.__label);
        }
      }
    };

    RequestQueManager.prototype.cancel = function() {
      if (this.__timer_id != null) {
        clearTimeout(this.__timer_id);
        this.__timer_id = null;
      }
      this.__video_que = [];
      this.__count = 0;
    };

    return RequestQueManager;

  })();

  VideoNodeSearcher = (function() {
    function VideoNodeSearcher(_label, _param_set, __inserter) {
      this.__inserter = __inserter;
      this.__param = new SearcherParameter(_label, _param_set);
      this.__push = Array.prototype.push;
    }

    VideoNodeSearcher.prototype.__findVideoId = function(_node) {
      var elem, element_list, video_id, _i, _len, _ref, _ref1, _ref2, _ref3;
      if (this.__param.check.tag === false) {
        video_id = (_ref = _node[this.__param.check.attr]) != null ? (_ref1 = _ref.match(this.__param.regexp)) != null ? _ref1[1] : void 0 : void 0;
      } else {
        video_id = null;
        element_list = _node.getElementsByTagName(this.__param.check.tag);
        for (_i = 0, _len = element_list.length; _i < _len; _i++) {
          elem = element_list[_i];
          if ((video_id = (_ref2 = elem[this.__param.check.attr]) != null ? (_ref3 = _ref2.match(this.__param.regexp)) != null ? _ref3[1] : void 0 : void 0)) {
            break;
          }
        }
      }
      return video_id;
    };

    VideoNodeSearcher.prototype.__getVideoList = function(_node_list) {
      var elem, node, video_id, video_list, video_node, _i, _len, _ref;
      video_list = [];
      for (_i = 0, _len = _node_list.length; _i < _len; _i++) {
        node = _node_list[_i];
        if ((video_id = this.__findVideoId(node)) != null) {
          _ref = this.__inserter.insertElement(node), elem = _ref[0], video_node = _ref[1];
          video_list.push({
            node: video_node,
            id: video_id,
            info_elem: elem
          });
        }
      }
      return video_list;
    };

    VideoNodeSearcher.prototype.__getVideoListInParent = function(_parent_node_list) {
      var new_video_list, node_list, parent_node, refPush, video_list, _i, _len;
      refPush = Array.prototype.push;
      video_list = [];
      for (_i = 0, _len = _parent_node_list.length; _i < _len; _i++) {
        parent_node = _parent_node_list[_i];
        node_list = parent_node.children;
        new_video_list = this.__getVideoList(node_list);
        refPush.apply(video_list, new_video_list);
      }
      return video_list;
    };

    VideoNodeSearcher.prototype.search = function(_query, _current, _as_parent) {
      var node_list, video_list;
      if (_as_parent == null) {
        _as_parent = true;
      }
      if (_query === false) {
        node_list = [_current];
      } else {
        node_list = Util.lookUp(_query, _current);
      }
      if (node_list != null) {
        if (_as_parent) {
          video_list = this.__getVideoListInParent(node_list);
        } else {
          video_list = this.__getVideoList(node_list);
        }
      }
      return video_list;
    };

    return VideoNodeSearcher;

  })();

  NicovideoNGSystem = (function() {
    function NicovideoNGSystem() {}

    NicovideoNGSystem.__manager_dict = {};

    NicovideoNGSystem.__dynamic_load_count = 0;

    NicovideoNGSystem.__normal_setting = function(_normal_rule) {
      var element, finder, init_param, inserter, manager, normal_dict, normal_label, normal_label_list, refElement, refFinder, refInserter, refManager, refSearcher, referer_param, searcher, setting, video_list_dict;
      video_list_dict = {};
      normal_dict = {};
      normal_label_list = [];
      for (normal_label in _normal_rule) {
        setting = _normal_rule[normal_label];
        normal_label_list.push(normal_label);
        referer_param = new RefererParameter(normal_label, setting.referer);
        refElement = referer_param.element();
        refInserter = referer_param.inserter();
        refFinder = referer_param.finder();
        refManager = referer_param.manager();
        refSearcher = referer_param.searcher();
        element = new refElement();
        inserter = new refInserter(normal_label, setting.inserter, element);
        finder = new refFinder(normal_label, setting.finder, inserter);
        manager = new refManager(normal_label, setting.manager, finder);
        searcher = new refSearcher(normal_label, setting.searcher, inserter);
        element.setRetryManager(new refManager(normal_label, setting.manager, finder));
        init_param = new InitParameter(normal_label, setting.init);
        video_list_dict[normal_label] = searcher.search(init_param.query, document, init_param.as_parent);
        normal_dict[normal_label] = {
          refManager: refManager,
          searcher: searcher,
          finder: finder,
          manager_setting: setting.manager,
          init_param: init_param
        };
        this.__manager_dict[normal_label] = manager;
      }
      return [video_list_dict, normal_dict, normal_label_list];
    };

    NicovideoNGSystem.__observer_setting = function(_observer_rule, _normal_dict) {
      var label, observer, observer_label, observer_list, observer_param, target_set;
      observer_list = [];
      for (observer_label in _observer_rule) {
        observer_param = _observer_rule[observer_label];
        if (observer_param['into'] == null) {
          observer_param['into'] = PRESET.observer.into[observer_label];
        }
        if (observer_param['filter'] == null) {
          observer_param['filter'] = PRESET.observer.filter[observer_label];
        }
        label = observer_param.target_label;
        target_set = _normal_dict[label];
        observer = this.genCbDynamicLoad(observer_param, target_set);
        observer_list.push([observer, observer_param]);
      }
      return observer_list;
    };

    NicovideoNGSystem.__autopager_setting = function(_autopager_rule, _normal_dict) {
      var label, pager_label, pager_list, pager_param, query, target_set;
      pager_list = [];
      for (pager_label in _autopager_rule) {
        pager_param = _autopager_rule[pager_label];
        label = pager_param.target_label;
        target_set = _normal_dict[label];
        query = pager_param.query != null ? pager_param.query : target_set.init_param.query;
        pager_list.push(this.genCbAutopage(label, target_set, query));
      }
      return pager_list;
    };

    NicovideoNGSystem.init = function() {
      var current_place, normal_dict, normal_label_list, observer_list, pager_list, rule, video_list_dict, _ref;
      current_place = Place.current;
      NGItemList.init(current_place);
      NGItemList.addElementToPage();
      rule = RULE[current_place];
      _ref = NicovideoNGSystem.__normal_setting(rule.normal), video_list_dict = _ref[0], normal_dict = _ref[1], normal_label_list = _ref[2];
      observer_list = NicovideoNGSystem.__observer_setting(rule.observer, normal_dict);
      pager_list = NicovideoNGSystem.__autopager_setting(rule.autopager, normal_dict);
      return [normal_label_list, video_list_dict, observer_list, pager_list];
    };

    NicovideoNGSystem.start = function(_set_list) {
      var autopage_event, doc, func, manager, normal_label, observer, param, peger, target, video_list, _i, _j, _k, _l, _len, _len1, _len2, _len3, _normal_label_list, _observer_list, _pager_list, _video_list_dict;
      _normal_label_list = _set_list[0], _video_list_dict = _set_list[1], _observer_list = _set_list[2], _pager_list = _set_list[3];
      for (_i = 0, _len = _normal_label_list.length; _i < _len; _i++) {
        normal_label = _normal_label_list[_i];
        video_list = _video_list_dict[normal_label];
        if (video_list.length) {
          manager = NicovideoNGSystem.__manager_dict[normal_label];
          manager.add(video_list);
        }
      }
      for (_j = 0, _len1 = _observer_list.length; _j < _len1; _j++) {
        observer = _observer_list[_j];
        func = observer[0];
        param = observer[1];
        doc = document;
        target = Util.lookUp(param.into, document, false);
        if (target != null) {
          target[0].addEventListener(param.type, Util.errorHandle(func), false);
        }
      }
      for (_k = 0, _len2 = _pager_list.length; _k < _len2; _k++) {
        peger = _pager_list[_k];
        for (_l = 0, _len3 = AUTOPAGE_EVENT_LIST.length; _l < _len3; _l++) {
          autopage_event = AUTOPAGE_EVENT_LIST[_l];
          document.body.addEventListener(autopage_event, Util.errorHandle(peger), false);
        }
      }
    };

    NicovideoNGSystem.genCbDynamicLoad = function(_dynamic_param, _target_set) {
      var func;
      func = (function(_this) {
        return function(_ev) {
          var as_parent, manager, node, query, result, searcher;
          if ((result = _dynamic_param.filter(_ev))) {
            node = result;
            query = _dynamic_param.query != null ? _dynamic_param.query : _target_set.init_param.query;
            as_parent = _dynamic_param.as_parent;
            manager = _this.__manager_dict[_dynamic_param.target_label];
            searcher = _target_set.searcher;
            if (_dynamic_param.cancelable) {
              manager.cancel();
            }
            manager.add(searcher.search(query, node, as_parent));
          }
        };
      })(this);
      return func;
    };

    NicovideoNGSystem.genCbAutopage = function(_label, _target_set, _query) {
      var func;
      func = (function(_this) {
        return function(_ev) {
          var autopage_label, manager, node, refManager, searcher;
          node = _ev.target;
          refManager = _target_set.refManager;
          autopage_label = "" + _label + "_" + _this.__dynamic_load_count;
          _this.__dynamic_load_count += 1;
          manager = new refManager(autopage_label, _target_set.manager_setting, _target_set.finder);
          searcher = _target_set.searcher;
          manager.add(searcher.search(_query, node, _target_set.init_param.as_parent));
        };
      })(this);
      return func;
    };

    NicovideoNGSystem.cbDeleteManager = function(_label) {
      delete NicovideoNGSystem.__manager_dict[_label];
    };

    return NicovideoNGSystem;

  })();

  OverwritableParameter = (function() {
    function OverwritableParameter(_label, _param_set, _job_type) {
      this.__overwrite(_label, _param_set, _job_type);
    }

    OverwritableParameter.prototype.__overwrite = function(_label, _param_set, _job_type) {
      var param_name, param_value;
      for (param_name in _param_set) {
        param_value = _param_set[param_name];
        this[param_name] = param_value != null ? param_value : PRESET[_job_type][param_name][_label];
      }
    };

    return OverwritableParameter;

  })();

  RefererParameter = (function(_super) {
    __extends(RefererParameter, _super);

    function RefererParameter(_label, _param_set) {
      this.element = function() {
        return VideoInfoElement;
      };
      this.searcher = function() {
        return VideoNodeSearcher;
      };
      this.manager = function() {
        return RequestQueManager;
      };
      this.finder = function() {
        return VideoInfoFinder;
      };
      this.inserter = function() {
        return VideoInfoInserter;
      };
      RefererParameter.__super__.constructor.call(this, _label, _param_set, 'referer');
    }

    return RefererParameter;

  })(OverwritableParameter);

  InitParameter = (function(_super) {
    __extends(InitParameter, _super);

    function InitParameter(_label, _param_set) {
      this.query = {
        csss: '.contentBody.video > ul.list'
      };
      this.as_parent = true;
      InitParameter.__super__.constructor.call(this, _label, _param_set, 'init');
    }

    return InitParameter;

  })(OverwritableParameter);

  SearcherParameter = (function(_super) {
    __extends(SearcherParameter, _super);

    function SearcherParameter(_label, _param_set) {
      this.regexp = REGEXP.video;
      this.check = {
        tag: 'a',
        attr: 'href'
      };
      SearcherParameter.__super__.constructor.call(this, _label, _param_set, 'searcher');
    }

    return SearcherParameter;

  })(OverwritableParameter);

  ManagerParameter = (function(_super) {
    __extends(ManagerParameter, _super);

    function ManagerParameter(_label, _param_set) {
      this.interval = INTERVAL;
      this.quick = EARLY;
      this.latency = LATENCY;
      this.deletable = false;
      ManagerParameter.__super__.constructor.call(this, _label, _param_set, 'manager');
      this.__limit();
    }

    ManagerParameter.prototype.__limit = function() {
      this.interval = Math.max(this.interval, 100);
      this.latency = Math.max(this.latency, 50);
      this.quick.interval = Math.max(this.quick.interval, 100);
      this.quick.count = Math.min(this.quick.count, 10);
    };

    return ManagerParameter;

  })(OverwritableParameter);

  FinderParameter = (function(_super) {
    __extends(FinderParameter, _super);

    function FinderParameter(_label, _param_set) {
      this.destination = DEST.thumb;
      this.timeout = TIMEOUT;
      this.retry = RETRY;
      this.chain_latency = CHAIN_LATENCY;
      FinderParameter.__super__.constructor.call(this, _label, _param_set, 'finder');
      this.__limit();
    }

    FinderParameter.prototype.__limit = function() {
      this.timeout = Math.min(Math.max(this.timeout, 1000), 10000);
      this.retry.wait = Math.max(this.retry.wait, 100);
      this.retry.count = Math.min(this.retry.count, 5);
      this.chain_latency = Math.max(this.chain_latency, 100);
    };

    return FinderParameter;

  })(OverwritableParameter);

  InserterParameter = (function(_super) {
    __extends(InserterParameter, _super);

    function InserterParameter(_label, _param_set) {
      this.target = {
        parent: true
      };
      InserterParameter.__super__.constructor.call(this, _label, _param_set, 'inserter');
    }

    return InserterParameter;

  })(OverwritableParameter);

  main = function() {
    var set_list;
    document.removeEventListener('DOMContentLoaded', main, false);
    set_list = Util.errorHandle(NicovideoNGSystem.init)();
    Util.errorHandle(NicovideoNGSystem.start)(set_list);
    if (!Place.previsible.at_start) {
      document.documentElement.style.visibility = '';
    }
  };

  Place.init();

  if (Place.current === null) {
    return;
  }

  document.addEventListener('DOMContentLoaded', main, false);

  if ((!Place.previsible.at_start) && GM_getValue(NG.key.enable, true)) {
    document.documentElement.style.visibility = 'hidden';
  }

}).call(this);