1 // analyse.js 2 // date: /^(\d{4}|\d{2})\/(\d{2})\/(\d{2})/ 3 // time: /(\d{2}):(\d{2}):(\d{2}).(\d{2})$/ 4 // /(\d{2}):(\d{2}):(\d{2})$/ 5 // /(\d{2}):(\d{2})$/ 6 7 /** 8 * @fileOverview [スレッド情報...]で表示される画面を扱います。 9 */ 10 11 /** 12 * スレッドから情報を解析してまとめて表示します。 13 * @static 14 */ 15 var Analyse = { 16 /** [スレッド情報] ダイアログを表示します。 */ 17 analyse: function() { 18 dialogAnalyse.clear(); 19 // ------------- 20 dialogAnalyse.addPage ("Thread", "スレッド", SKIN_PATH + "img/thread.png"); 21 dialogAnalyse.addFrame("Thread", "Summary", "概要"); 22 dialogAnalyse.addLabel("Thread", "Summary", "", "タイトル:"); 23 dialogAnalyse.addLabel("Thread", "Summary", "", ThreadDocument.title,null,1); 24 dialogAnalyse.addLabel("Thread", "Summary", "", "URL:"); 25 dialogAnalyse.addLink ("Thread", "Summary", "", EXACT_URL, EXACT_URL,null,1); 26 dialogAnalyse.addLabel("Thread", "Summary", "", "総レス数:"); 27 dialogAnalyse.addLabel("Thread", "Summary", "", ThreadDocument.countAll,null,1); 28 dialogAnalyse.addLabel("Thread", "Summary", "", "期間:"); 29 var lastIndex = (ThreadDocument.countAll > 1000) ? 1000 : ThreadDocument.countAll; 30 dialogAnalyse.addLabel("Thread", "Summary", "", this.getDate(1).toLocaleString() + " ~ " + this.getDate(lastIndex).toLocaleString(),null,1); 31 dialogAnalyse.addLabel("Thread", "Summary", "", "(" + this.toStringfromTimeDiff((this.getDate(lastIndex).getTime() - this.getDate(1).getTime())) + ")",null,1); 32 dialogAnalyse.addLabel("Thread", "Summary", "", "勢い:"); 33 dialogAnalyse.addLabel("Thread", "Summary", "", this.getPaceString(),null,1); 34 // ------------- 35 dialogAnalyse.addPage ("User", "中の人", SKIN_PATH + "img/user.png"); 36 dialogAnalyse.addFrame("User", "Name", "名前",96); 37 var nameArray = []; 38 var nameTable = []; 39 var arrayIndex = 0; 40 var nameItems = ResNodes.getNames(); 41 for (var i = 0; i < nameItems.length; i++) { 42 var node = nameItems.items(i); 43 var name = node.textContent; 44 if (nameTable["_" + name]) { 45 nameArray[nameTable["_" + name]].count++; 46 } else { 47 nameTable["_" + name] = arrayIndex; 48 nameArray[arrayIndex] = {name: name, count: 1}; 49 arrayIndex++; 50 } 51 } 52 nameArray.sort(function(a,b){return b.count - a.count}); 53 for (var i = 0; i < nameArray.length; i++) { 54 if (nameArray[i].count > 1) dialogAnalyse.addLabel("User", "Name", "", nameArray[i].name + "(" + nameArray[i].count + ")"); 55 } 56 // --- 57 dialogAnalyse.addFrame("User", "ID", "ID",96); 58 var idArray = []; 59 for (var id in ID.items) { 60 idArray.push({id: id, count: ID.items[id].length}); 61 } 62 idArray.sort(function(a,b){return b.count - a.count}); 63 dialogAnalyse.addLabel("User", "ID", "", "合計 " + idArray.length + " 個のID"); 64 for (var i = 0; i < idArray.length; i++) { 65 if (idArray[i].count > 1) dialogAnalyse.addID("User", "ID", "", idArray[i].id, idArray[i].count); 66 } 67 // --- 68 dialogAnalyse.addFrame("User", "Trackback", "人気レス",96); 69 var trackbackArray = []; 70 Trackback.traverse(); 71 for (var index in Trackback.items) { 72 trackbackArray.push({index: index, count: Trackback.items[index].length}); 73 } 74 trackbackArray.sort(function(a,b){return b.count - a.count}); 75 var hasbeenAdded = false; 76 for (var i = 0; i < trackbackArray.length; i++) { 77 if (trackbackArray[i].count > 1) { 78 dialogAnalyse.addTrackback("User", "Trackback", "", trackbackArray[i].index, trackbackArray[i].count); 79 hasbeenAdded = true; 80 } 81 } 82 if (!hasbeenAdded) dialogAnalyse.addLabel("User", "Trackback", "", "なし"); 83 // ------------- 84 dialogAnalyse.addPage ("Link", "リンク", SKIN_PATH + "img/external.png"); 85 dialogAnalyse.addFrame("Link", "2ch", "2ch", 128); 86 dialogAnalyse.addFrame("Link", "External", "外部サイト",128); 87 dialogAnalyse.addPage ("Image", "画像", SKIN_PATH + "img/image.png"); 88 dialogAnalyse.addFrame("Image", "Image", "一覧",256); 89 dialogAnalyse.addPage ("Video", "動画", SKIN_PATH + "img/video.png"); 90 dialogAnalyse.addFrame("Video", "Video", "一覧",256); 91 var externalLinks = ResNodes.getOutLinks(); 92 var urlTable = []; 93 var imageCount = 0; 94 var videoCount = 0; 95 var extCount = 0; 96 var chCount = 0; 97 for (var i = 0; i < externalLinks.length; i++) { 98 var node = externalLinks.items(i); 99 var href = node.rel; 100 if (urlTable[href]) { continue } else { urlTable[href] = true }; 101 var container = ResNodes.getParentContainer(node); 102 var index = ResNodes.getIndexByContainer(container); 103 if (ImagePopup.isImage(href)) { 104 imageCount++; 105 dialogAnalyse.addLink ("Image", "Image", "", href, node.href, index); 106 } else if (VideoPopup.getVideoSource(href)) { 107 videoCount++; 108 dialogAnalyse.addLink ("Video", "Video", "", href, node.href, index); 109 } else { 110 if (!href.match(/\.2ch\.net\/|\.bbspink\.com\/|\.machi\.to\/|jbbs\.livedoor\.jp\//)) { 111 extCount++; 112 dialogAnalyse.addLink ("Link", "External", "", href, node.href, index); 113 } else { 114 chCount++; 115 dialogAnalyse.addLink ("Link", "2ch", "", href, node.href, index); 116 } 117 } 118 } 119 if (!imageCount) dialogAnalyse.addLabel ("Image", "Image", "", "なし"); 120 if (!videoCount) dialogAnalyse.addLabel ("Video", "Video", "", "なし"); 121 if (!extCount) dialogAnalyse.addLabel ("Link", "External", "", "なし"); 122 if (!chCount) dialogAnalyse.addLabel ("Link", "2ch", "", "なし"); 123 // ------------- 124 dialogAnalyse.show(); 125 }, 126 /** 指定されたレス番号の日付を、日付型に変換して返します。 127 * @param {Number} index レス番号 128 * @return {Date} 日付 129 */ 130 getDate: function(index) { 131 var str = Nodes.getDate(index).textContent; 132 str.match(/^(\d{4}|\d{2})\/(\d{2})\/(\d{2})/); 133 var fullYear = parseInt(RegExp.$1); 134 if (fullYear < 100) fullYear += (fullYear >= 90) ? 1900 : 2000; 135 var date = new Date(RegExp.$2 + "/" + RegExp.$3 + "/" + fullYear); 136 if (str.match(/(\d{2}):(\d{2}):(\d{2}).(\d{2})(\s|$)/)) { 137 date.setHours(parseInt(RegExp.$1)); 138 date.setMinutes(parseInt(RegExp.$2)); 139 date.setSeconds(parseInt(RegExp.$3)); 140 date.setMilliseconds(parseInt(RegExp.$4)); 141 } else if (str.match(/(\d{2}):(\d{2}):(\d{2})(\s|$)/)) { 142 date.setHours(parseInt(RegExp.$1)); 143 date.setMinutes(parseInt(RegExp.$2)); 144 date.setSeconds(parseInt(RegExp.$3)); 145 } else if (str.match(/(\d{2}):(\d{2})(\s|$)/)) { 146 date.setHours(parseInt(RegExp.$1)); 147 date.setMinutes(parseInt(RegExp.$2)); 148 } 149 return date; 150 }, 151 /** ミリ秒を日本語の時間表記に変換します。 152 * @param {Number} arg 時間(ミリ秒) 153 * @return {String} 変換された文字列 154 */ 155 toStringfromTimeDiff: function(arg){ 156 var strReturn = new String(); 157 var valDate = Math.floor(arg / 31536000000); 158 if (valDate > 0) strReturn += valDate + "年"; 159 var valDate = Math.floor((arg % 31536000000) / 2628000000); 160 if (valDate > 0) strReturn += valDate + "ヶ月"; 161 var valDate = Math.floor(((arg % 31536000000) % 2628000000) / 86400000); 162 if (valDate > 0) strReturn += valDate + "日 "; 163 var valDate = Math.floor((((arg % 31536000000) % 2628000000) % 86400000) / 3600000) ; 164 if (valDate > 0) strReturn += valDate + "時間"; 165 var valDate = Math.floor(((((arg % 31536000000) % 2628000000) % 86400000) % 3600000) / 60000); 166 if (valDate > 0) strReturn += valDate + "分"; 167 if (strReturn.length == 0) { 168 var valDate = Math.floor((((((arg % 31536000000) % 2628000000) % 86400000) % 3600000) % 60000) / 1000 * 1000) / 1000; 169 } else { 170 var valDate = Math.floor((((((arg % 31536000000) % 2628000000) % 86400000) % 3600000) % 60000) / 1000); 171 } 172 if (valDate > 0) strReturn += valDate + "秒"; 173 return strReturn; 174 }, 175 /** スレッドの勢いを取得します。 176 * @return {String} 勢い 177 */ 178 getPaceString: function(){ 179 var lastIndex = (ThreadDocument.countAll > 1000) ? 1000 : ThreadDocument.countAll; 180 return this.toStringfromTimeDiff((this.getDate(lastIndex).getTime() - this.getDate(1).getTime()) / lastIndex) + " / レス"; 181 } 182 }; 183 184 /** 185 * [スレッド情報] ダイアログを管理します。 186 * @static 187 */ 188 var dialogAnalyse = { 189 /** ダイアログの親要素 190 * @type element 191 */ 192 content: document.createElement("div"), 193 /** [OK] ボタンが押されたときの処理をします。*/ 194 onOK: function(){ 195 this.hide(); 196 }, 197 /** リサイズされたときの処理をします。*/ 198 onResize: function(){ 199 dialogAnalyse.content.style.left = (document.body.offsetWidth - dialogAnalyse.content.offsetWidth) / 2 200 dialogAnalyse.content.style.top = (window.innerHeight - dialogAnalyse.content.offsetHeight) / 2 201 var bg = document.getElementById("dialogAnalyseBackground"); 202 if (bg) { 203 bg.style.width = document.body.offsetWidth; 204 bg.style.height = window.innerHeight; 205 } 206 }, 207 /** ダイアログを表示します。*/ 208 show: function(){ 209 var bg = document.createElement("div"); 210 bg.id = "dialogAnalyseBackground"; 211 bg.style.width = document.body.offsetWidth; 212 bg.style.height = window.innerHeight; 213 document.body.appendChild(bg); 214 215 this.content.style.position = "fixed"; 216 this.content.style.width = 512; 217 this.content.style.visibility = "hidden" 218 this.content.style.display = "block"; 219 this.selectPage(this.content.childNodes[1].id.replace("Page_", "")); 220 this.content.style.left = (document.body.offsetWidth - this.content.offsetWidth) / 2 221 this.content.style.top = (window.innerHeight - this.content.offsetHeight) / 2 222 this.content.style.visibility = "visible"; 223 window.addEventListener("resize", dialogAnalyse.onResize, false); 224 }, 225 /** ダイアログを非表示にします。*/ 226 hide: function(){ 227 this.content.style.display = "none"; 228 var bg = document.getElementById("dialogAnalyseBackground"); 229 if (bg) document.body.removeChild(bg); 230 window.removeEventListener("resize", dialogAnalyse.onResize, false); 231 }, 232 /** ダイアログの内容をクリアします。*/ 233 clear: function(){ 234 if (document.getElementById("dialogAnalyse")) { 235 document.body.removeChild(document.getElementById("dialogAnalyse")); 236 this.content = document.createElement("div"); 237 } 238 }, 239 /** ダイアログのページを切り替えます。 240 * @param {String} id ページの ID 241 */ 242 selectPage: function(id){ 243 var divHeader = document.getElementById("dialogAnalyseHeader"); 244 for (var i = 0; i < divHeader.childNodes.length - 1; i++) { 245 var icon = divHeader.childNodes[i]; 246 if (icon.id == "Icon_" + id) { 247 icon.className = "icon" + " " + "selected"; 248 } else { 249 icon.className = "icon"; 250 } 251 } 252 for (var i = 1; i < this.content.childNodes.length - 1; i++) { 253 var page = this.content.childNodes[i]; 254 if (page.id == "Page_" + id) { 255 page.style.display = "block"; 256 } else { 257 page.style.display = "none"; 258 } 259 } 260 if ((this.content.offsetTop + this.content.offsetHeight) > window.innerHeight) this.onResize(); 261 }, 262 /** ページを追加します。 263 * @param {String} id ID 264 * @param {String} caption キャプション 265 * @param {String} icon アイコンの URI 266 */ 267 addPage: function(id, caption, icon){ 268 if (!this.content.id) this.content.id = "dialogAnalyse"; 269 if (!document.getElementById("dialogAnalyse")) document.body.appendChild(this.content); 270 var divHeader = document.getElementById("dialogAnalyseHeader"); 271 if (!divHeader) { 272 divHeader = document.createElement("div"); 273 divHeader.id = "dialogAnalyseHeader"; 274 divHeader.className = "header"; 275 var divHeaderEnd = document.createElement("div"); 276 divHeaderEnd.id = "dialogAnalyseHeaderEnd"; 277 divHeaderEnd.className = "null"; 278 divHeader.appendChild(divHeaderEnd); 279 this.content.appendChild(divHeader); 280 281 var p = document.createElement("p"); 282 var ok = document.createElement("input"); 283 ok.setAttribute("type", "submit"); 284 ok.setAttribute("value", "OK"); 285 ok.setAttribute("onclick", "dialogAnalyse.onOK()"); 286 p.appendChild(ok); 287 this.content.appendChild(p); 288 } 289 290 var divIcon = document.createElement("div"); 291 divIcon.id = "Icon_" + id; 292 divIcon.className = "icon"; 293 divIcon.textContent = caption; 294 divIcon.style.backgroundImage = "url(" + icon + ")"; 295 divIcon.setAttribute("onclick", "dialogAnalyse.selectPage('" + id + "')"); 296 divHeader.insertBefore(divIcon, document.getElementById("dialogAnalyseHeaderEnd")); 297 298 var divPage = document.createElement("div"); 299 divPage.id = "Page_" + id; 300 divPage.style.display = "none"; 301 this.content.insertBefore(divPage, this.content.lastChild); 302 }, 303 /** フレームを追加します。 304 * @param {String} page 追加するページの ID 305 * @param {String} id ID 306 * @param {String} caption キャプション 307 * @param {Number} maxheight 最大の高さ 308 */ 309 addFrame: function(page, id, caption, maxheight){ 310 var fieldset = document.createElement("fieldset"); 311 fieldset.id = "Frame_" + page + "_" + id; 312 var legend = document.createElement("legend"); 313 legend.textContent = caption; 314 fieldset.appendChild(legend); 315 var ul = document.createElement("ul"); 316 if (maxheight) ul.style.maxHeight = maxheight; 317 fieldset.appendChild(ul); 318 var divPage = document.getElementById("Page_" + page); 319 if (divPage) divPage.appendChild(fieldset); 320 }, 321 /** ラベルを追加します。 322 * @param {String} page 追加するページの ID 323 * @param {String} frame フレームの ID 324 * @param {String} id ID 325 * @param {String} caption キャプション 326 * @param {Number} [index] 表示するレス番号へのアンカー 327 * @param {Number} [level] インデントする階層 328 */ 329 addLabel: function(page, frame, id, caption, index, level){ 330 var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild; 331 if (level > 0) { 332 for (var i = 1; i <= level; i++) { 333 parentObject.appendChild(document.createElement("ul")); 334 parentObject = parentObject.lastChild; 335 } 336 } 337 var li = document.createElement("li"); 338 var label = document.createElement("label"); 339 label.className = "dialogAnalyseLabel"; 340 var span = document.createElement("span"); 341 span.textContent = caption; 342 label.appendChild(span); 343 if (index) { 344 var a = document.createElement("a"); 345 a.setAttribute("href", "javascript:void(0)"); 346 a.setAttribute("className", "resPointer"); 347 a.textContent = "(>>" + index + ")"; 348 label.appendChild(a); 349 } 350 li.appendChild(label); 351 parentObject.appendChild(li); 352 }, 353 /** リンクを追加します。 354 * @param {String} page 追加するページの ID 355 * @param {String} frame フレームの ID 356 * @param {String} id ID 357 * @param {String} caption キャプション 358 * @param {String} uri URI 359 * @param {Number} [index] 表示するレス番号へのアンカー 360 * @param {Number} [level] インデントする階層 361 */ 362 addLink: function(page, frame, id, caption, uri, index, level){ 363 var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild; 364 if (level > 0) { 365 for (var i = 1; i <= level; i++) { 366 parentObject.appendChild(document.createElement("ul")); 367 parentObject = parentObject.lastChild; 368 } 369 } 370 var li = document.createElement("li"); 371 var label = document.createElement("label"); 372 label.className = "dialogAnalyseLabel"; 373 var a = document.createElement("a"); 374 a.setAttribute("href", uri); 375 a.setAttribute("target", "_blank"); 376 a.className = "outLink"; 377 a.textContent = caption; 378 label.appendChild(a); 379 if (index) { 380 label.appendChild(document.createTextNode(" (")); 381 var a = document.createElement("a"); 382 a.setAttribute("href", "javascript:void(0)"); 383 a.className = "resPointer"; 384 a.textContent = ">>" + index; 385 label.appendChild(a); 386 label.appendChild(document.createTextNode(")")); 387 } 388 li.appendChild(label); 389 parentObject.appendChild(li); 390 }, 391 /** ID を追加します。 392 * @param {String} page 追加するページの ID 393 * @param {String} frame フレームの ID 394 * @param {String} id ID 395 * @param {String} caption キャプション 396 * @param {Number} count ID の発言回数 397 * @param {Number} [level] インデントする階層 398 */ 399 addID: function(page, frame, id, caption, count, level){ 400 var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild; 401 if (level > 0) { 402 for (var i = 1; i <= level; i++) { 403 parentObject.appendChild(document.createElement("ul")); 404 parentObject = parentObject.lastChild; 405 } 406 } 407 var li = document.createElement("li"); 408 var label = document.createElement("label"); 409 label.className = "dialogAnalyseLabel"; 410 /* 411 var a = document.createElement("a"); 412 a.setAttribute("href", "javascript:void(0)"); 413 a.setAttribute("target", "_blank"); 414 a.className = "mesID_" + caption; 415 a.textContent = "ID:" + caption; 416 label.appendChild(a); 417 */ 418 var span = document.createElement("span"); 419 span.className = "mesID_" + caption + " resID2"; 420 span.textContent = "ID:" + caption; 421 label.appendChild(span) 422 label.appendChild(document.createTextNode("(" + count + ")")); 423 li.appendChild(label); 424 parentObject.appendChild(li); 425 }, 426 /** 逆参照を追加します。 427 * @param {String} page 追加するページの ID 428 * @param {String} frame フレームの ID 429 * @param {String} id ID 430 * @param {Number} index レス番号 431 * @param {Number} count レス番号に対する言及回数 432 * @param {Number} [level] インデントする階層 433 */ 434 addTrackback: function(page, frame, id, index, count, level){ 435 var parentObject = document.getElementById("Frame_" + page + "_" + frame).lastChild; 436 if (level > 0) { 437 for (var i = 1; i <= level; i++) { 438 parentObject.appendChild(document.createElement("ul")); 439 parentObject = parentObject.lastChild; 440 } 441 } 442 var li = document.createElement("li"); 443 var label = document.createElement("label"); 444 label.className = "dialogAnalyseLabel"; 445 var a = document.createElement("a"); 446 a.setAttribute("href", "javascript:void(0)"); 447 //a.setAttribute("target", "_blank"); 448 a.className = "resPointer"; 449 a.textContent = ">>" + index; 450 label.appendChild(a); 451 label.appendChild(document.createTextNode("(" + count + ")