📄 btg.js
字号:
/** * Callback for btg_contextClean. * Called when a torrent was successfully deleted. */function cb_contextClean(response){ refreshContextList();}/** * Error Callback for btg_contextClean. * Called when a clean operation fails. */function cb_contextClean_err(error, errStr){ setError(error, "Failed to move torrent: "+ errStr);}/************************************************** * Misc shortcut functions. **************************************************//* Set the status message */function setStatus(msg){ isStatusIdle = 0; if(msg == '' || msg == null || msg == undefined) { isStatusIdle = 1; msg = "Idle."; } document.getElementById('statusMessage').innerHTML = msg;}/* Set an error message. * error should be error DOM from cb_._err. * msg should be error to display. */function setError(error, msg){ for(var i=0; i < error.length; i++) { var code = error[i].getAttribute('code'); if(code != null) { if(code == '1') { /* Failed to connect to BTG, or failed to init session.. This is fatal */ setUIState(0); document.getElementById('layer_fatal').innerHTML = "<h2>Fatal error</h2><p>" + error[i].childNodes[0].nodeValue + "</p>"; document.getElementById('layer_fatal').style.display="block"; setStatus('Cannot connect to BTG. Please refresh this page and try later.'); return; } else if(code == '2') { /* Failed to authorize */ setUIState(1); setStatus('Failed to authorize.'); return; } else if(code == '3') { /* Failed to attach session, let user select new session */ sessionList(); setUIState(2); setStatus(error[i].childNodes[0].nodeValue); return; } else if(code == '4') { /* Failed to setup session */ setUIState(2); setStatus(error[i].childNodes[0].nodeValue); return; } } } setStatus(msg);}/** Retreive a specific field value in DOM node */function getFirstChildValue(node, field){ var elem = node.getElementsByTagName(field); if(elem.length == 0) return ""; if(elem[0].childNodes.length == 0) return ""; else return elem[0].childNodes[0].nodeValue;}/** Round a number X to N decimals */function RoundToNdp(X, N) { var T = Number("1e" + N); return Math.round(X * T) / T;}/** Shortcut to rounding val with 1 decimal */function round1(val){ return RoundToNdp(val,1);}/** Shortcut to rounding val with 2 decimals */function round2(val){ return RoundToNdp(val,2);}/** Converts size (in bytes) to a human readble figure */function humanizeSize(size, precision){ if(size < bytesPerKiB) return size + "b"; size = size / bytesPerKiB; if(size < bytesPerKiB) return RoundToNdp(size, precision) + " kB"; size = size / bytesPerKiB; if(size < bytesPerKiB) return RoundToNdp(size, precision) + " MB"; size = size / bytesPerKiB; if(size < bytesPerKiB) return RoundToNdp(size, precision) + " GB";}/** Converts speed (in byte/s) to a human readble figure */function humanizeSpeed(size, precision){ return humanizeSize(size, precision) + "/s";}/* Refresh the context list */function refreshContextList(){ setStatus("Updating torrent list..."); btg_contextStatus(cb_contextStatus, cb_contextStatus_err, -1, true);}/** Handles updating of the visuals. * This is called from cb_contextStatus, the newList will be a list of fresh Status objects. Here * how it works: * * 1. Iteration over all items: * 1. Item is added to a temporary list. * 2. If the item exist in the previously initiated global contextList, it will be removed from there. * 3. If a table row with this context ID exists (a previously known context), it will be updated. * Else a new row is added (a new context). * 2. When all items has been processed, any items left in contextList will be removed (those items * did not exist in the new list, in other words they have been removed from the session) and their * row in the context table will be removed. * 3. The (now empty) contextList will be replaced with the newly created temporary list for use the next * this function is called. */function updateContextTable(newList){ var tempList = new Array(); var totalUpRate = 0; var totalDownRate = 0; var table = document.getElementById('torrent_table'); var evenOrUneven = 'uneven'; /* Iterate over all new items */ for(var i=0; i < newList.length; i++) { var s = newList[i]; /* Add it to the new list */ tempList.push(s); /* Remove it from the current list (isn't there any better way to do this???) */ for(var y=0; y < contextList.length; y++) { if(s.compare(contextList[y])) { contextList.splice(y, 1); break; } } /* Determine the state of the torrent */ if(s.status == ts_queued) { /* Some other torrent is checking its data and this torrent is in the wait queue */ s.statusMessage = "Queued for check" } else if(s.status == ts_checking) { /* This torrent is currently checking its data */ s.statusMessage = "Checking data (" + s.done + "%)" } else if(s.status == ts_connecting) { /* Connecting to tracker or peers */ s.statusMessage = "Connecting" } else if(s.status == ts_downloading) { /* This torrent is currently downloading data, not finished */ s.statusMessage = "Downloading (" + humanizeSpeed(s.downloadrate,1) + "): "+ round1(s.done) +"% (" + s.timeleft + " left)" } else if(s.status == ts_seeding) { /* This torrent is fully downloaded and is seeding */ s.statusMessage = "Seeding (" + humanizeSpeed(s.uploadrate,1) + "): "+ round1(s.done) + "%"; } else if(s.status == ts_stopped) { /* User has stopped torrent, not finished */ s.statusMessage = "Stopped ("+ round1(s.done) +"%)" } else if(s.status == ts_finished) { /* Torrent is fully downloaded and is stopped */ s.statusMessage = "Finished ("+ round1(s.done)+"%)" } else { /* Undefined...? Use the specified statustext... */ s.statusMessage = s.statustext } if(s.trackerstatus != 200 && s.trackerstatus != -1) s.statusMessage+='. Error '+s.trackerstatus + ': '+s.trackerstatustext; if(s.trackerstatusmessage != "") { s.statusMessage+='. '+s.trackerstatusmessage; } /* Check if we can find the row already (existing torrent) */ var row = document.getElementById('context_'+s.contextID+'_row'); var detailsTable = document.getElementById('context_'+s.contextID+'_details_table'); var detailsRow = document.getElementById('context_'+s.contextID+'_details_row'); var details = document.getElementById('context_'+s.contextID+'_details'); /* Not found, create it */ if(!row) { /* This torrent is new! Create a new row at index 0 */ row = createTorrentTableRow(table, s); /* Create a hidden details row. Insert this as THIRD row! (headers, main row, info row..) */ detailsRow = table.insertRow(2); detailsRow.className = "ctx_details"; detailsRow.style.display = 'none'; detailsRow.id = 'context_'+s.contextID+'_details_row'; detailsRow.contextID = s.contextID; detailsRow.onclick = function(){ toogleContextDetails(this.contextID); } /* Create the details cell and insert a detailsTable in it */ detailsCell = detailsRow.insertCell(-1); detailsCell.colSpan = 3; detailsCell.className = "ctx_details"; details = createTorrentDetails(); details.id = 'context_'+s.contextID+'_details'; detailsCell.appendChild(details); var controlRow = table.insertRow(3); controlRow.className = "ctx_control"; controlRow.style.display = 'none'; controlRow.id = 'context_'+s.contextID+'_control_row'; controlRow.contextID = s.contextID; var controlCell = controlRow.insertCell(-1); controlCell.colSpan = 3; controlCell.className = "ctx_control"; var control = createTorrentExtendedControls(s.contextID); control.id = 'context_'+s.contextID+'_control'; controlCell.appendChild(control); } if(evenOrUneven == 'even') evenOrUneven = 'uneven' else evenOrUneven = 'even' /* Update the data */ updateTorrentTableRow(row, s); row.className=evenOrUneven+'_row'; //detailsRow.className='extra_'+evenOrUneven+'_row'; updateTorrentDetails(details, s) totalUpRate+= s.uploadrate; totalDownRate+= s.downloadrate; } /* Okay. All available items has been processed and removed from contextList if they * where there before. Any contexts still there has been removed from the session. * Delete all those rows.. */ for(var i=0; i < contextList.length; i++) { var s = contextList[i]; var row = document.getElementById('context_'+s.contextID+'_row'); if(!row) { alert('Error! '+s.contextID+' was found in contextList on cleanup, but no table row is found!'); continue; } table.deleteRow(row.rowIndex); var detailsRow = document.getElementById('context_'+s.contextID+'_details_row'); table.deleteRow(detailsRow.rowIndex); var controlRow = document.getElementById('context_'+s.contextID+'_control_row'); table.deleteRow(controlRow.rowIndex); delete s; delete contextList[i]; } /* Done! Replace the contextList with the new list we created. */ contextList = tempList; /* Refresh total counters */ document.getElementById('status_download').innerHTML = 'Total download speed is: ' + humanizeSpeed(totalDownRate, 2); document.getElementById('status_upload').innerHTML = 'Total upload speed is: ' + humanizeSpeed(totalUpRate, 2); /* Call IE specific crap to get mouseover working */ if(parseStylesheets) parseStylesheets();}/** * Clear the context list from all entrys. Done on detach. */function clearContextList(){ var totalUpRate = 0; var totalDownRate = 0; var table = document.getElementById('torrent_table'); /* Iterate over all items */ for(var i=0; i < contextList.length; i++) { var s = contextList[i]; var row = document.getElementById('context_'+s.contextID+'_row'); if(!row) { alert('Error! '+s.contextID+' was found in contextList on cleanup, but no table row is found!'); continue; } table.deleteRow(row.rowIndex); var detailsRow = document.getElementById('context_'+s.contextID+'_details_row'); table.deleteRow(detailsRow.rowIndex); var controlRow = document.getElementById('context_'+s.contextID+'_control_row'); table.deleteRow(controlRow.rowIndex); delete s; delete contextList[i]; } contextList = new Array(); /* Refresh total counters */ document.getElementById('status_download').innerHTML = 'Total download speed is: ' + humanizeSpeed(totalDownRate, 2); document.getElementById('status_upload').innerHTML = 'Total upload speed is: ' + humanizeSpeed(totalUpRate, 2);}/** * Create a table row for a torrent. * @param t The table in which to create the row. * @param s The status object for this torrent. * @return A HTMLTableRowElement. */function createTorrentTableRow(t, s){ // Insert AFTER headers... var r = t.insertRow(1); r.contextID = s.contextID; r.id = 'context_'+s.contextID+'_row'; /* Caller should change this */ r.className='even_row'; /* Filename cell */ var c = r.insertCell(-1); c.contextID = r.contextID; c.onclick = function(){ toogleContextDetails(this.contextID); } c.className = 'column_torrent'; /* Status bar cell */ c = r.insertCell(-1); c.contextID = r.contextID; c.onclick = function(){ toogleContextDetails(this.contextID); } c.className = 'column_status'; var d1 = document.createElement('div'); d1.className = 'status_bar'; var d2 = document.createElement('div'); d2.style.width = '0%'; var p = document.createElement('pre'); d2.appendChild(p); d1.appendChild(d2); c.appendChild(d1); /* Controls cell */ c = r.insertCell(-1); c.className = 'column_control'; return r;}/** * Update a torrent info row created by createTorrentTableRow(). * @param r The HTMLTableRowElement to be updated. * @param s The Status object containing the information to put in the table. */function updateTorrentTableRow(r, s){ // Strip .torrent extension var f = s.filename var rexp = f.match(/^(.*)\.torrent$/) if(rexp) f = rexp[1] // and then cut it if to long if(f.length > 60) f = f.substr(0,60) + '...'; r.cells[0].innerHTML = f; r.cells[0].title = s.filename; if(s.done > 100) r.cells[1].childNodes[0].childNodes[0].style.width = '100%'; else r.cells[1].childNodes[0].childNodes[0].style.width = ''+s.done+'%'; if(s.status == ts_downloading) r.cells[1].childNodes[0].childNodes[0].className = 'downloading_bar'; else if(s.status == ts_seeding) r.cells[1].childNodes[0].childNodes[0].className = 'seeding_bar'; else if(s.status == ts_finished) r.cells[1].childNodes[0].childNodes[0].className = 'finished_bar'; var stxt=r.cells[1].childNodes[0].childNodes[0].childNodes[0]; if(s.statusMessage.length > 50) stxt.innerHTML = s.statusMessage.substr(0, 50)+"..."; else stxt.innerHTML = s.statusMessage; // erase all controls var ctrl = r.cells[2]; while(ctrl.childNodes.length > 0) ctrl.removeChild(ctrl.childNodes[0]); // and create new createTorrentControls(s, r.cells[2]);}/** * Creates a "button". */function createButton(title){ var b = document.createElement('span'); b.className = 'button'; b.innerHTML = title; return b;}/** * Create control buttons for a torrent. * @param s Status object with torrent info. * @param d A DOM object in which the controls will be placed. * @return A list of HTMLSpanElement's */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -