Changeset 14523
- Timestamp:
- May 5, 2015, 7:12:48 PM (6 years ago)
- Location:
- trunk/web/javascript
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/web/javascript/common.js
r14518 r14523 29 29 this.find('.ui-tab-dialog-close > a').css({'float':'none','padding':'0'}); 30 30 var tabul = this.find('ul:first'); 31 this.parent().addClass('ui-tabs').prepend(tabul).draggable('option','handle',tabul); 31 this.parent().addClass('ui-tabs').prepend(tabul).draggable('option','handle',tabul); 32 32 this.siblings('.ui-dialog-titlebar').remove(); 33 33 tabul.addClass('ui-dialog-titlebar'); … … 247 247 var key = e.which || e.keyCode; 248 248 return !e.shiftKey && !e.altKey && !e.ctrlKey && 249 // numbers 249 // numbers 250 250 key >= 48 && key <= 57 || 251 251 // Numeric keypad -
trunk/web/javascript/dialog.js
r14511 r14523 16 16 */ 17 17 initialize: function() { 18 18 19 19 /* 20 20 * Private Interface Variables … … 26 26 this._confirm_button = $('#dialog_confirm_button'); 27 27 this._callback = null; 28 28 29 29 // Observe the buttons 30 30 this._cancel_button.bind('click', {dialog: this}, this.onCancelClicked); … … 109 109 this._container.show(); 110 110 } 111 111 112 112 113 113 } -
trunk/web/javascript/file-row.js
r13598 r14523 46 46 var pct = 100 * (fields.size ? (fields.have / fields.size) : 1.0), 47 47 c = [ Transmission.fmt.size(fields.have), 48 49 50 51 52 48 ' of ', 49 Transmission.fmt.size(fields.size), 50 ' (', 51 Transmission.fmt.percentString(pct), 52 '%)' ].join(''); 53 53 setTextContent(elements.progress, c); 54 54 }, -
trunk/web/javascript/formatter.js
r13556 r14523 280 280 }, 281 281 282 peerStatus: function( flagStr ) 283 { 284 var formattedFlags = []; 282 peerStatus: function( flagStr ) 283 { 284 var formattedFlags = []; 285 285 for (var i=0, flag; flag=flagStr[i]; ++i) 286 286 { … … 302 302 } 303 303 304 if (!explanation) { 305 formattedFlags.push(flag); 306 } else { 307 formattedFlags.push("<span title=\"" + flag + ': ' + explanation + "\">" + flag + "</span>"); 308 } 309 } 310 return formattedFlags.join(''); 304 if (!explanation) { 305 formattedFlags.push(flag); 306 } else { 307 formattedFlags.push("<span title=\"" + flag + ': ' + explanation + "\">" + flag + "</span>"); 308 } 309 } 310 return formattedFlags.join(''); 311 311 } 312 312 } -
trunk/web/javascript/inspector.js
r14509 r14523 8 8 function Inspector(controller) { 9 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 str = none; 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 i = addSubtreeToView (tor, div, sub.children[key]); 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 10 var data = { 11 controller: null, 12 elements: { }, 13 torrents: [ ] 14 }, 15 16 needsExtraInfo = function (torrents) { 17 var i, id, tor; 18 19 for (i = 0; tor = torrents[i]; i++) 20 if (!tor.hasExtraInfo()) 21 return true; 22 23 return false; 24 }, 25 26 refreshTorrents = function () { 27 var fields, 28 ids = $.map(data.torrents.slice(0), function (t) {return t.getId();}); 29 30 if (ids && ids.length) 31 { 32 fields = ['id'].concat(Torrent.Fields.StatsExtra); 33 34 if (needsExtraInfo(data.torrents)) 35 $.merge(fields, Torrent.Fields.InfoExtra); 36 37 data.controller.updateTorrents(ids, fields); 38 } 39 }, 40 41 onTabClicked = function (ev) { 42 var tab = ev.currentTarget; 43 44 if (isMobileDevice) 45 ev.stopPropagation(); 46 47 // select this tab and deselect the others 48 $(tab).addClass('selected').siblings().removeClass('selected'); 49 50 // show this tab and hide the others 51 $('#' + tab.id.replace('tab','page')).show().siblings('.inspector-page').hide(); 52 53 updateInspector(); 54 }, 55 56 updateInspector = function () { 57 var e = data.elements, 58 torrents = data.torrents, 59 name; 60 61 // update the name, which is shown on all the pages 62 if (!torrents || !torrents.length) 63 name = 'No Selection'; 64 else if(torrents.length === 1) 65 name = torrents[0].getName(); 66 else 67 name = '' + torrents.length+' Transfers Selected'; 68 setTextContent(e.name_lb, name || na); 69 70 // update the visible page 71 if ($(e.info_page).is(':visible')) 72 updateInfoPage(); 73 else if ($(e.peers_page).is(':visible')) 74 updatePeersPage(); 75 else if ($(e.trackers_page).is(':visible')) 76 updateTrackersPage(); 77 else if ($(e.files_page).is(':visible')) 78 updateFilesPage(); 79 }, 80 81 /**** 82 ***** GENERAL INFO PAGE 83 ****/ 84 85 updateInfoPage = function () { 86 var torrents = data.torrents, 87 e = data.elements, 88 fmt = Transmission.fmt, 89 none = 'None', 90 mixed = 'Mixed', 91 unknown = 'Unknown', 92 isMixed, allPaused, allFinished, 93 str, 94 baseline, it, s, i, t, 95 sizeWhenDone = 0, 96 leftUntilDone = 0, 97 available = 0, 98 haveVerified = 0, 99 haveUnverified = 0, 100 verifiedPieces = 0, 101 stateString, 102 latest, 103 pieces, 104 size, 105 pieceSize, 106 creator, mixed_creator, 107 date, mixed_date, 108 v, u, f, d, pct, 109 uri, 110 now = Date.now(); 111 112 // 113 // state_lb 114 // 115 116 if(torrents.length <1) 117 str = none; 118 else { 119 isMixed = false; 120 allPaused = true; 121 allFinished = true; 122 123 baseline = torrents[0].getStatus(); 124 for(i=0; t=torrents[i]; ++i) { 125 it = t.getStatus(); 126 if(it != baseline) 127 isMixed = true; 128 if(!t.isStopped()) 129 allPaused = allFinished = false; 130 if(!t.isFinished()) 131 allFinished = false; 132 } 133 if( isMixed ) 134 str = mixed; 135 else if( allFinished ) 136 str = 'Finished'; 137 else if( allPaused ) 138 str = 'Paused'; 139 else 140 str = torrents[0].getStateString(); 141 } 142 setTextContent(e.state_lb, str); 143 stateString = str; 144 145 // 146 // have_lb 147 // 148 149 if(torrents.length < 1) 150 str = none; 151 else { 152 baseline = torrents[0].getStatus(); 153 for(i=0; t=torrents[i]; ++i) { 154 if(!t.needsMetaData()) { 155 haveUnverified += t.getHaveUnchecked(); 156 v = t.getHaveValid(); 157 haveVerified += v; 158 if(t.getPieceSize()) 159 verifiedPieces += v / t.getPieceSize(); 160 sizeWhenDone += t.getSizeWhenDone(); 161 leftUntilDone += t.getLeftUntilDone(); 162 available += (t.getHave()) + t.getDesiredAvailable(); 163 } 164 } 165 166 d = 100.0 * ( sizeWhenDone ? ( sizeWhenDone - leftUntilDone ) / sizeWhenDone : 1 ); 167 str = fmt.percentString( d ); 168 169 if( !haveUnverified && !leftUntilDone ) 170 str = fmt.size(haveVerified) + ' (100%)'; 171 else if( !haveUnverified ) 172 str = fmt.size(haveVerified) + ' of ' + fmt.size(sizeWhenDone) + ' (' + str +'%)'; 173 else 174 str = fmt.size(haveVerified) + ' of ' + fmt.size(sizeWhenDone) + ' (' + str +'%), ' + fmt.size(haveUnverified) + ' Unverified'; 175 } 176 setTextContent(e.have_lb, str); 177 178 // 179 // availability_lb 180 // 181 182 if(torrents.length < 1) 183 str = none; 184 else if( sizeWhenDone == 0 ) 185 str = none; 186 else 187 str = '' + fmt.percentString( ( 100.0 * available ) / sizeWhenDone ) + '%'; 188 setTextContent(e.availability_lb, str); 189 190 // 191 // downloaded_lb 192 // 193 194 if(torrents.length < 1) 195 str = none; 196 else { 197 d = f = 0; 198 for(i=0; t=torrents[i]; ++i) { 199 d += t.getDownloadedEver(); 200 f += t.getFailedEver(); 201 } 202 if(f) 203 str = fmt.size(d) + ' (' + fmt.size(f) + ' corrupt)'; 204 else 205 str = fmt.size(d); 206 } 207 setTextContent(e.downloaded_lb, str); 208 209 // 210 // uploaded_lb 211 // 212 213 if(torrents.length < 1) 214 str = none; 215 else { 216 d = u = 0; 217 if(torrents.length == 1) { 218 d = torrents[0].getDownloadedEver(); 219 u = torrents[0].getUploadedEver(); 220 221 if (d == 0) 222 d = torrents[0].getHaveValid(); 223 } 224 else { 225 for(i=0; t=torrents[i]; ++i) { 226 d += t.getDownloadedEver(); 227 u += t.getUploadedEver(); 228 } 229 } 230 str = fmt.size(u) + ' (Ratio: ' + fmt.ratioString( Math.ratio(u,d))+')'; 231 } 232 setTextContent(e.uploaded_lb, str); 233 234 // 235 // running time 236 // 237 238 if(torrents.length < 1) 239 str = none; 240 else { 241 allPaused = true; 242 baseline = torrents[0].getStartDate(); 243 for(i=0; t=torrents[i]; ++i) { 244 if(baseline != t.getStartDate()) 245 baseline = 0; 246 if(!t.isStopped()) 247 allPaused = false; 248 } 249 if(allPaused) 250 str = stateString; // paused || finished 251 else if(!baseline) 252 str = mixed; 253 else 254 str = fmt.timeInterval(now/1000 - baseline); 255 } 256 setTextContent(e.running_time_lb, str); 257 258 // 259 // remaining time 260 // 261 262 str = ''; 263 if(torrents.length < 1) 264 str = none; 265 else { 266 baseline = torrents[0].getETA(); 267 for(i=0; t=torrents[i]; ++i) { 268 if(baseline != t.getETA()) { 269 str = mixed; 270 break; 271 } 272 } 273 } 274 if(!str.length) { 275 if(baseline < 0) 276 str = unknown; 277 else 278 str = fmt.timeInterval(baseline); 279 } 280 setTextContent(e.remaining_time_lb, str); 281 282 // 283 // last activity 284 // 285 286 latest = -1; 287 if(torrents.length < 1) 288 str = none; 289 else { 290 baseline = torrents[0].getLastActivity(); 291 for(i=0; t=torrents[i]; ++i) { 292 d = t.getLastActivity(); 293 if(latest < d) 294 latest = d; 295 } 296 d = now/1000 - latest; // seconds since last activity 297 if(d < 0) 298 str = none; 299 else if(d < 5) 300 str = 'Active now'; 301 else 302 str = fmt.timeInterval(d) + ' ago'; 303 } 304 setTextContent(e.last_activity_lb, str); 305 306 // 307 // error 308 // 309 310 if(torrents.length < 1) 311 str = none; 312 else { 313 str = torrents[0].getErrorString(); 314 for(i=0; t=torrents[i]; ++i) { 315 if(str != t.getErrorString()) { 316 str = mixed; 317 break; 318 } 319 } 320 } 321 setTextContent(e.error_lb, str || none); 322 323 // 324 // size 325 // 326 327 if(torrents.length < 1) 328 str = none; 329 else { 330 pieces = 0; 331 size = 0; 332 pieceSize = torrents[0].getPieceSize(); 333 for(i=0; t=torrents[i]; ++i) { 334 pieces += t.getPieceCount(); 335 size += t.getTotalSize(); 336 if(pieceSize != t.getPieceSize()) 337 pieceSize = 0; 338 } 339 if(!size) 340 str = none; 341 else if(pieceSize > 0) 342 str = fmt.size(size) + ' (' + pieces.toStringWithCommas() + ' pieces @ ' + fmt.mem(pieceSize) + ')'; 343 else 344 str = fmt.size(size) + ' (' + pieces.toStringWithCommas() + ' pieces)'; 345 } 346 setTextContent(e.size_lb, str); 347 348 // 349 // hash 350 // 351 352 if(torrents.length < 1) 353 str = none; 354 else { 355 str = torrents[0].getHashString(); 356 for(i=0; t=torrents[i]; ++i) { 357 if(str != t.getHashString()) { 358 str = mixed; 359 break; 360 } 361 } 362 } 363 setTextContent(e.hash_lb, str); 364 365 // 366 // privacy 367 // 368 369 if(torrents.length < 1) 370 str = none; 371 else { 372 baseline = torrents[0].getPrivateFlag(); 373 str = baseline ? 'Private to this tracker -- DHT and PEX disabled' : 'Public torrent'; 374 for(i=0; t=torrents[i]; ++i) { 375 if(baseline != t.getPrivateFlag()) { 376 str = mixed; 377 break; 378 } 379 } 380 } 381 setTextContent(e.privacy_lb, str); 382 383 // 384 // comment 385 // 386 387 if(torrents.length < 1) 388 str = none; 389 else { 390 str = torrents[0].getComment(); 391 for(i=0; t=torrents[i]; ++i) { 392 if(str != t.getComment()) { 393 str = mixed; 394 break; 395 } 396 } 397 } 398 if(!str) 399 str = none; 400 uri = parseUri(str); 401 if (uri.protocol == 'http' || uri.parseUri == 'https') { 402 str = encodeURI(str); 403 setInnerHTML(e.comment_lb, '<a href="' + str + '" target="_blank" >' + str + '</a>'); 404 } 405 else 406 setTextContent(e.comment_lb, str); 407 408 // 409 // origin 410 // 411 412 if(torrents.length < 1) 413 str = none; 414 else { 415 mixed_creator = false; 416 mixed_date = false; 417 creator = torrents[0].getCreator(); 418 date = torrents[0].getDateCreated(); 419 for(i=0; t=torrents[i]; ++i) { 420 if(creator != t.getCreator()) 421 mixed_creator = true; 422 if(date != t.getDateCreated()) 423 mixed_date = true; 424 } 425 var empty_creator = !creator || !creator.length, 426 empty_date = !date; 427 if(mixed_creator || mixed_date) 428 str = mixed; 429 else if(empty_creator && empty_date) 430 str = unknown; 431 else if(empty_date && !empty_creator) 432 str = 'Created by ' + creator; 433 else if(empty_creator && !empty_date) 434 str = 'Created on ' + (new Date(date*1000)).toDateString(); 435 else 436 str = 'Created by ' + creator + ' on ' + (new Date(date*1000)).toDateString(); 437 } 438 setTextContent(e.origin_lb, str); 439 440 // 441 // foldername 442 // 443 444 if(torrents.length < 1) 445 str = none; 446 else { 447 str = torrents[0].getDownloadDir(); 448 for(i=0; t=torrents[i]; ++i) { 449 if(str != t.getDownloadDir()) { 450 str = mixed; 451 break; 452 } 453 } 454 } 455 setTextContent(e.foldername_lb, str); 456 }, 457 458 /**** 459 ***** FILES PAGE 460 ****/ 461 462 changeFileCommand = function(fileIndices, command) { 463 var torrentId = data.file_torrent.getId(); 464 data.controller.changeFileCommand(torrentId, fileIndices, command); 465 }, 466 467 onFileWantedToggled = function(ev, fileIndices, want) { 468 changeFileCommand(fileIndices, want?'files-wanted':'files-unwanted'); 469 }, 470 471 onFilePriorityToggled = function(ev, fileIndices, priority) { 472 var command; 473 switch(priority) { 474 case -1: command = 'priority-low'; break; 475 case 1: command = 'priority-high'; break; 476 default: command = 'priority-normal'; break; 477 } 478 changeFileCommand(fileIndices, command); 479 }, 480 481 onNameClicked = function(ev, fileRow, fileIndices) { 482 $(fileRow.getElement()).siblings().slideToggle(); 483 }, 484 485 clearFileList = function() { 486 $(data.elements.file_list).empty(); 487 delete data.file_torrent; 488 delete data.file_torrent_n; 489 delete data.file_rows; 490 }, 491 492 createFileTreeModel = function (tor) { 493 var i, j, n, name, tokens, walk, tree, token, sub, 494 leaves = [ ], 495 tree = { children: { }, file_indices: [ ] }; 496 497 n = tor.getFileCount(); 498 for (i=0; i<n; ++i) { 499 name = tor.getFile(i).name; 500 tokens = name.split('/'); 501 walk = tree; 502 for (j=0; j<tokens.length; ++j) { 503 token = tokens[j]; 504 sub = walk.children[token]; 505 if (!sub) { 506 walk.children[token] = sub = { 507 name: token, 508 parent: walk, 509 children: { }, 510 file_indices: [ ], 511 depth: j 512 }; 513 } 514 walk = sub; 515 } 516 walk.file_index = i; 517 delete walk.children; 518 leaves.push (walk); 519 } 520 521 for (i=0; i<leaves.length; ++i) { 522 walk = leaves[i]; 523 j = walk.file_index; 524 do { 525 walk.file_indices.push (j); 526 walk = walk.parent; 527 } while (walk); 528 } 529 530 return tree; 531 }, 532 533 addNodeToView = function (tor, parent, sub, i) { 534 var row; 535 row = new FileRow(tor, sub.depth, sub.name, sub.file_indices, i%2); 536 data.file_rows.push(row); 537 parent.appendChild(row.getElement()); 538 $(row).bind('wantedToggled',onFileWantedToggled); 539 $(row).bind('priorityToggled',onFilePriorityToggled); 540 $(row).bind('nameClicked',onNameClicked); 541 }, 542 543 addSubtreeToView = function (tor, parent, sub, i) { 544 var key, div; 545 div = document.createElement('div'); 546 if (sub.parent) 547 addNodeToView (tor, div, sub, i++); 548 if (sub.children) 549 for (key in sub.children) 550 i = addSubtreeToView (tor, div, sub.children[key]); 551 parent.appendChild(div); 552 return i; 553 }, 554 555 updateFilesPage = function() { 556 var i, n, tor, fragment, tree, 557 file_list = data.elements.file_list, 558 torrents = data.torrents; 559 560 // only show one torrent at a time 561 if (torrents.length !== 1) { 562 clearFileList(); 563 return; 564 } 565 566 tor = torrents[0]; 567 n = tor ? tor.getFileCount() : 0; 568 if (tor!=data.file_torrent || n!=data.file_torrent_n) { 569 // rebuild the file list... 570 clearFileList(); 571 data.file_torrent = tor; 572 data.file_torrent_n = n; 573 data.file_rows = [ ]; 574 fragment = document.createDocumentFragment(); 575 tree = createFileTreeModel (tor); 576 addSubtreeToView (tor, fragment, tree, 0); 577 file_list.appendChild (fragment); 578 } else { 579 // ...refresh the already-existing file list 580 for (i=0, n=data.file_rows.length; i<n; ++i) 581 data.file_rows[i].refresh(); 582 } 583 }, 584 585 /**** 586 ***** PEERS PAGE 587 ****/ 588 589 updatePeersPage = function() { 590 var i, k, tor, peers, peer, parity, 591 html = [], 592 fmt = Transmission.fmt, 593 peers_list = data.elements.peers_list, 594 torrents = data.torrents; 595 596 for (k=0; tor=torrents[k]; ++k) 597 { 598 peers = tor.getPeers(); 599 html.push('<div class="inspector_group">'); 600 if (torrents.length > 1) { 601 html.push('<div class="inspector_torrent_label">', sanitizeText(tor.getName()), '</div>'); 602 } 603 if (!peers || !peers.length) { 604 html.push('<br></div>'); // firefox won't paint the top border if the div is empty 605 continue; 606 } 607 html.push('<table class="peer_list">', 608 '<tr class="inspector_peer_entry even">', 609 '<th class="encryptedCol"></th>', 610 '<th class="upCol">Up</th>', 611 '<th class="downCol">Down</th>', 612 '<th class="percentCol">%</th>', 613 '<th class="statusCol">Status</th>', 614 '<th class="addressCol">Address</th>', 615 '<th class="clientCol">Client</th>', 616 '</tr>'); 617 for (i=0; peer=peers[i]; ++i) { 618 parity = (i%2) ? 'odd' : 'even'; 619 html.push('<tr class="inspector_peer_entry ', parity, '">', 620 '<td>', (peer.isEncrypted ? '<div class="encrypted-peer-cell" title="Encrypted Connection">' 621 : '<div class="unencrypted-peer-cell">'), '</div>', '</td>', 622 '<td>', (peer.rateToPeer ? fmt.speedBps(peer.rateToPeer) : ''), '</td>', 623 '<td>', (peer.rateToClient ? fmt.speedBps(peer.rateToClient) : ''), '</td>', 624 '<td class="percentCol">', Math.floor(peer.progress*100), '%', '</td>', 625 '<td>', fmt.peerStatus(peer.flagStr), '</td>', 626 '<td>', sanitizeText(peer.address), '</td>', 627 '<td class="clientCol">', sanitizeText(peer.clientName), '</td>', 628 '</tr>'); 629 } 630 html.push('</table></div>'); 631 } 632 633 setInnerHTML(peers_list, html.join('')); 634 }, 635 636 /**** 637 ***** TRACKERS PAGE 638 ****/ 639 640 getAnnounceState = function(tracker) { 641 var timeUntilAnnounce, s = ''; 642 switch (tracker.announceState) { 643 case Torrent._TrackerActive: 644 s = 'Announce in progress'; 645 break; 646 case Torrent._TrackerWaiting: 647 timeUntilAnnounce = tracker.nextAnnounceTime - ((new Date()).getTime() / 1000); 648 if (timeUntilAnnounce < 0) { 649 timeUntilAnnounce = 0; 650 } 651 s = 'Next announce in ' + Transmission.fmt.timeInterval(timeUntilAnnounce); 652 break; 653 case Torrent._TrackerQueued: 654 s = 'Announce is queued'; 655 break; 656 case Torrent._TrackerInactive: 657 s = tracker.isBackup ? 658 'Tracker will be used as a backup' : 659 'Announce not scheduled'; 660 break; 661 default: 662 s = 'unknown announce state: ' + tracker.announceState; 663 } 664 return s; 665 }, 666 667 lastAnnounceStatus = function(tracker) { 668 669 var lastAnnounceLabel = 'Last Announce', 670 lastAnnounce = [ 'N/A' ], 671 lastAnnounceTime; 672 673 if (tracker.hasAnnounced) { 674 lastAnnounceTime = Transmission.fmt.timestamp(tracker.lastAnnounceTime); 675 if (tracker.lastAnnounceSucceeded) { 676 lastAnnounce = [ lastAnnounceTime, ' (got ', Transmission.fmt.countString('peer','peers',tracker.lastAnnouncePeerCount), ')' ]; 677 } else { 678 lastAnnounceLabel = 'Announce error'; 679 lastAnnounce = [ (tracker.lastAnnounceResult ? (tracker.lastAnnounceResult + ' - ') : ''), lastAnnounceTime ]; 680 } 681 } 682 return { 'label':lastAnnounceLabel, 'value':lastAnnounce.join('') }; 683 }, 684 685 lastScrapeStatus = function(tracker) { 686 687 var lastScrapeLabel = 'Last Scrape', 688 lastScrape = 'N/A', 689 lastScrapeTime; 690 691 if (tracker.hasScraped) { 692 lastScrapeTime = Transmission.fmt.timestamp(tracker.lastScrapeTime); 693 if (tracker.lastScrapeSucceeded) { 694 lastScrape = lastScrapeTime; 695 } else { 696 lastScrapeLabel = 'Scrape error'; 697 lastScrape = (tracker.lastScrapeResult ? tracker.lastScrapeResult + ' - ' : '') + lastScrapeTime; 698 } 699 } 700 return {'label':lastScrapeLabel, 'value':lastScrape}; 701 }, 702 703 updateTrackersPage = function() { 704 var i, j, tier, tracker, trackers, tor, 705 html, parity, lastAnnounceStatusHash, 706 announceState, lastScrapeStatusHash, 707 na = 'N/A', 708 trackers_list = data.elements.trackers_list, 709 torrents = data.torrents; 710 711 // By building up the HTML as as string, then have the browser 712 // turn this into a DOM tree, this is a fast operation. 713 html = []; 714 for (i=0; tor=torrents[i]; ++i) 715 { 716 html.push ('<div class="inspector_group">'); 717 718 if (torrents.length > 1) 719 html.push('<div class="inspector_torrent_label">', tor.getName(), '</div>'); 720 721 tier = -1; 722 trackers = tor.getTrackers(); 723 for (j=0; tracker=trackers[j]; ++j) 724 { 725 if (tier != tracker.tier) 726 { 727 if (tier !== -1) // close previous tier 728 html.push('</ul></div>'); 729 730 tier = tracker.tier; 731 732 html.push('<div class="inspector_group_label">', 733 'Tier ', tier+1, '</div>', 734 '<ul class="tier_list">'); 735 } 736 737 // Display construction 738 lastAnnounceStatusHash = lastAnnounceStatus(tracker); 739 announceState = getAnnounceState(tracker); 740 lastScrapeStatusHash = lastScrapeStatus(tracker); 741 parity = (j%2) ? 'odd' : 'even'; 742 html.push('<li class="inspector_tracker_entry ', parity, '"><div class="tracker_host" title="', sanitizeText(tracker.announce), '">', 743 sanitizeText(tracker.host || tracker.announce), '</div>', 744 '<div class="tracker_activity">', 745 '<div>', lastAnnounceStatusHash['label'], ': ', lastAnnounceStatusHash['value'], '</div>', 746 '<div>', announceState, '</div>', 747 '<div>', lastScrapeStatusHash['label'], ': ', lastScrapeStatusHash['value'], '</div>', 748 '</div><table class="tracker_stats">', 749 '<tr><th>Seeders:</th><td>', (tracker.seederCount > -1 ? tracker.seederCount : na), '</td></tr>', 750 '<tr><th>Leechers:</th><td>', (tracker.leecherCount > -1 ? tracker.leecherCount : na), '</td></tr>', 751 '<tr><th>Downloads:</th><td>', (tracker.downloadCount > -1 ? tracker.downloadCount : na), '</td></tr>', 752 '</table></li>'); 753 } 754 if (tier !== -1) // close last tier 755 html.push('</ul></div>'); 756 757 html.push('</div>'); // inspector_group 758 } 759 760 setInnerHTML (trackers_list, html.join('')); 761 }, 762 763 initialize = function (controller) { 764 765 var ti = '#torrent_inspector_'; 766 767 data.controller = controller; 768 769 $('.inspector-tab').click(onTabClicked); 770 771 data.elements.info_page = $('#inspector-page-info')[0]; 772 data.elements.files_page = $('#inspector-page-files')[0]; 773 data.elements.peers_page = $('#inspector-page-peers')[0]; 774 data.elements.trackers_page = $('#inspector-page-trackers')[0]; 775 776 data.elements.file_list = $('#inspector_file_list')[0]; 777 data.elements.peers_list = $('#inspector_peers_list')[0]; 778 data.elements.trackers_list = $('#inspector_trackers_list')[0]; 779 780 data.elements.have_lb = $('#inspector-info-have')[0]; 781 data.elements.availability_lb = $('#inspector-info-availability')[0]; 782 data.elements.downloaded_lb = $('#inspector-info-downloaded')[0]; 783 data.elements.uploaded_lb = $('#inspector-info-uploaded')[0]; 784 data.elements.state_lb = $('#inspector-info-state')[0]; 785 data.elements.running_time_lb = $('#inspector-info-running-time')[0]; 786 data.elements.remaining_time_lb = $('#inspector-info-remaining-time')[0]; 787 data.elements.last_activity_lb = $('#inspector-info-last-activity')[0]; 788 data.elements.error_lb = $('#inspector-info-error')[0]; 789 data.elements.size_lb = $('#inspector-info-size')[0]; 790 data.elements.foldername_lb = $('#inspector-info-location')[0]; 791 data.elements.hash_lb = $('#inspector-info-hash')[0]; 792 data.elements.privacy_lb = $('#inspector-info-privacy')[0]; 793 data.elements.origin_lb = $('#inspector-info-origin')[0]; 794 data.elements.comment_lb = $('#inspector-info-comment')[0]; 795 data.elements.name_lb = $('#torrent_inspector_name')[0]; 796 797 // force initial 'N/A' updates on all the pages 798 updateInspector(); 799 updateInfoPage(); 800 updatePeersPage(); 801 updateTrackersPage(); 802 updateFilesPage(); 803 }; 804 805 /**** 806 ***** PUBLIC FUNCTIONS 807 ****/ 808 809 this.setTorrents = function (torrents) { 810 var d = data; 811 812 // update the inspector when a selected torrent's data changes. 813 $(d.torrents).unbind('dataChanged.inspector'); 814 $(torrents).bind('dataChanged.inspector', $.proxy(updateInspector,this)); 815 d.torrents = torrents; 816 817 // periodically ask for updates to the inspector's torrents 818 clearInterval(d.refreshInterval); 819 d.refreshInterval = setInterval($.proxy(refreshTorrents,this), 2000); 820 refreshTorrents(); 821 822 // refresh the inspector's UI 823 updateInspector(); 824 }; 825 826 initialize (controller); 827 827 }; -
trunk/web/javascript/notifications.js
r13422 r14523 2 2 3 3 $(document).ready(function () { 4 5 6 4 if (!window.webkitNotifications) { 5 return; 6 } 7 7 8 9 8 var notificationsEnabled = (window.webkitNotifications.checkPermission() === 0), 9 toggle = $('#toggle_notifications'); 10 10 11 12 13 14 11 toggle.show(); 12 updateMenuTitle(); 13 $(transmission).bind('downloadComplete seedingComplete', function (event, torrent) { 14 if (notificationsEnabled) { 15 15 var title = (event.type == 'downloadComplete' ? 'Download' : 'Seeding') + ' complete', 16 16 content = torrent.getName(), 17 17 notification; 18 18 19 19 notification = window.webkitNotifications.createNotification('style/transmission/images/logo.png', title, content); 20 notification.show(); 20 notification.show(); 21 21 setTimeout(function () { 22 22 notification.cancel(); 23 23 }, 5000); 24 24 }; 25 25 }); 26 26 27 28 29 27 function updateMenuTitle() { 28 toggle.html((notificationsEnabled ? 'Disable' : 'Enable') + ' Notifications'); 29 } 30 30 31 32 33 34 35 36 37 38 39 40 41 31 Notifications.toggle = function () { 32 if (window.webkitNotifications.checkPermission() !== 0) { 33 window.webkitNotifications.requestPermission(function () { 34 notificationsEnabled = (window.webkitNotifications.checkPermission() === 0); 35 updateMenuTitle(); 36 }); 37 } else { 38 notificationsEnabled = !notificationsEnabled; 39 updateMenuTitle(); 40 } 41 }; 42 42 }); -
trunk/web/javascript/prefs-dialog.js
r13218 r14523 8 8 function PrefsDialog(remote) { 9 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 10 var data = { 11 dialog: null, 12 remote: null, 13 elements: { }, 14 15 // all the RPC session keys that we have gui controls for 16 keys: [ 17 'alt-speed-down', 18 'alt-speed-time-begin', 19 'alt-speed-time-day', 20 'alt-speed-time-enabled', 21 'alt-speed-time-end', 22 'alt-speed-up', 23 'blocklist-enabled', 24 'blocklist-size', 25 'blocklist-url', 26 'dht-enabled', 27 'download-dir', 28 'encryption', 29 'idle-seeding-limit', 30 'idle-seeding-limit-enabled', 31 'lpd-enabled', 32 'peer-limit-global', 33 'peer-limit-per-torrent', 34 'peer-port', 35 'peer-port-random-on-start', 36 'pex-enabled', 37 'port-forwarding-enabled', 38 'rename-partial-files', 39 'seedRatioLimit', 40 'seedRatioLimited', 41 'speed-limit-down', 42 'speed-limit-down-enabled', 43 'speed-limit-up', 44 'speed-limit-up-enabled', 45 'start-added-torrents', 46 'utp-enabled' 47 ], 48 49 // map of keys that are enabled only if a 'parent' key is enabled 50 groups: { 51 'alt-speed-time-enabled': ['alt-speed-time-begin', 52 'alt-speed-time-day', 53 'alt-speed-time-end' ], 54 'blocklist-enabled': ['blocklist-url', 55 'blocklist-update-button' ], 56 'idle-seeding-limit-enabled': [ 'idle-seeding-limit' ], 57 'seedRatioLimited': [ 'seedRatioLimit' ], 58 'speed-limit-down-enabled': [ 'speed-limit-down' ], 59 'speed-limit-up-enabled': [ 'speed-limit-up' ] 60 } 61 }, 62 63 initTimeDropDown = function(e) 64 { 65 var i, hour, mins, value, content; 66 67 for (i=0; i<24*4; ++i) { 68 hour = parseInt(i/4, 10); 69 mins = ((i%4) * 15); 70 value = i * 15; 71 content = hour + ':' + (mins || '00'); 72 e.options[i] = new Option(content, value); 73 } 74 }, 75 76 onPortChecked = function(response) 77 { 78 var is_open = response['arguments']['port-is-open'], 79 text = 'Port is <b>' + (is_open ? 'Open' : 'Closed') + '</b>', 80 e = data.elements.root.find('#port-label'); 81 setInnerHTML(e[0],text); 82 }, 83 84 setGroupEnabled = function(parent_key, enabled) 85 { 86 var i, key, keys, root; 87 88 if (parent_key in data.groups) 89 { 90 root = data.elements.root, 91 keys = data.groups[parent_key]; 92 93 for (i=0; key=keys[i]; ++i) 94 root.find('#'+key).attr('disabled',!enabled); 95 } 96 }, 97 98 onBlocklistUpdateClicked = function () 99 { 100 data.remote.updateBlocklist(); 101 setBlocklistButtonEnabled(false); 102 }, 103 setBlocklistButtonEnabled = function(b) 104 { 105 var e = data.elements.blocklist_button; 106 e.attr('disabled',!b); 107 e.val(b ? 'Update' : 'Updating...'); 108 }, 109 110 getValue = function(e) 111 { 112 var str; 113 114 switch (e[0].type) 115 { 116 case 'checkbox': 117 case 'radio': 118 return e.prop('checked'); 119 120 case 'text': 121 case 'url': 122 case 'email': 123 case 'number': 124 case 'search': 125 case 'select-one': 126 str = e.val(); 127 if( parseInt(str,10).toString() === str) 128 return parseInt(str,10); 129 if( parseFloat(str).toString() === str) 130 return parseFloat(str); 131 return str; 132 133 default: 134 return null; 135 } 136 }, 137 138 /* this callback is for controls whose changes can be applied 139 immediately, like checkboxs, radioboxes, and selects */ 140 onControlChanged = function(ev) 141 { 142 var o = {}; 143 o[ev.target.id] = getValue($(ev.target)); 144 data.remote.savePrefs(o); 145 }, 146 147 /* these two callbacks are for controls whose changes can't be applied 148 immediately -- like a text entry field -- because it takes many 149 change events for the user to get to the desired result */ 150 onControlFocused = function(ev) 151 { 152 data.oldValue = getValue($(ev.target)); 153 }, 154 onControlBlurred = function(ev) 155 { 156 var newValue = getValue($(ev.target)); 157 if (newValue !== data.oldValue) 158 { 159 var o = {}; 160 o[ev.target.id] = newValue; 161 data.remote.savePrefs(o); 162 delete data.oldValue; 163 } 164 }, 165 166 getDefaultMobileOptions = function() 167 { 168 return { 169 width: $(window).width(), 170 height: $(window).height(), 171 position: [ 'left', 'top' ] 172 }; 173 }, 174 175 initialize = function (remote) 176 { 177 var i, key, e, o; 178 179 data.remote = remote; 180 181 e = $('#prefs-dialog'); 182 data.elements.root = e; 183 184 initTimeDropDown(e.find('#alt-speed-time-begin')[0]); 185 initTimeDropDown(e.find('#alt-speed-time-end')[0]); 186 187 o = isMobileDevice 188 ? getDefaultMobileOptions() 189 : { width: 350, height: 400 }; 190 o.autoOpen = false; 191 o.show = o.hide = 'fade'; 192 o.close = onDialogClosed; 193 e.tabbedDialog(o); 194 195 e = e.find('#blocklist-update-button'); 196 data.elements.blocklist_button = e; 197 e.click(onBlocklistUpdateClicked); 198 199 // listen for user input 200 for (i=0; key=data.keys[i]; ++i) 201 { 202 e = data.elements.root.find('#'+key); 203 switch (e[0].type) 204 { 205 case 'checkbox': 206 case 'radio': 207 case 'select-one': 208 e.change(onControlChanged); 209 break; 210 211 case 'text': 212 case 'url': 213 case 'email': 214 case 'number': 215 case 'search': 216 e.focus(onControlFocused); 217 e.blur(onControlBlurred); 218 219 default: 220 break; 221 } 222 } 223 }, 224 225 getValues = function() 226 { 227 var i, key, val, o={}, 228 keys = data.keys, 229 root = data.elements.root; 230 231 for (i=0; key=keys[i]; ++i) { 232 val = getValue(root.find('#'+key)); 233 if (val !== null) 234 o[key] = val; 235 } 236 237 return o; 238 }, 239 240 onDialogClosed = function() 241 { 242 transmission.hideMobileAddressbar(); 243 244 $(data.dialog).trigger('closed', getValues()); 245 }; 246 247 /**** 248 ***** PUBLIC FUNCTIONS 249 ****/ 250 251 // update the dialog's controls 252 this.set = function (o) 253 { 254 var e, i, key, val, option, 255 keys = data.keys, 256 root = data.elements.root; 257 258 setBlocklistButtonEnabled(true); 259 260 for (i=0; key=keys[i]; ++i) 261 { 262 val = o[key]; 263 e = root.find('#'+key); 264 265 if (key === 'blocklist-size') 266 { 267 // special case -- regular text area 268 e.text('' + val.toStringWithCommas()); 269 } 270 else switch (e[0].type) 271 { 272 case 'checkbox': 273 case 'radio': 274 e.prop('checked', val); 275 setGroupEnabled(key, val); 276 break; 277 case 'text': 278 case 'url': 279 case 'email': 280 case 'number': 281 case 'search': 282 // don't change the text if the user's editing it. 283 // it's very annoying when that happens! 284 if (e[0] !== document.activeElement) 285 e.val(val); 286 break; 287 case 'select-one': 288 e.val(val); 289 break; 290 default: 291 break; 292 } 293 } 294 }; 295 296 this.show = function () 297 { 298 transmission.hideMobileAddressbar(); 299 300 setBlocklistButtonEnabled(true); 301 data.remote.checkPort(onPortChecked,this); 302 data.elements.root.dialog('open'); 303 }; 304 305 this.close = function () 306 { 307 transmission.hideMobileAddressbar(); 308 data.elements.root.dialog('close'); 309 }, 310 311 this.shouldAddedTorrentsStart = function() 312 { 313 return data.elements.root.find('#start-added-torrents')[0].checked; 314 }; 315 316 data.dialog = this; 317 initialize (remote); 318 318 }; -
trunk/web/javascript/remote.js
r14511 r14523 55 55 56 56 remote._error = request.responseText 57 58 57 ? request.responseText.trim().replace(/(<([^>]+)>)/ig,"") 58 : ""; 59 59 if (!remote._error.length) 60 60 remote._error = 'Server not responding'; … … 102 102 this.sendRequest(o, callback, context, async); 103 103 }, 104 104 105 105 checkPort: function(callback, context, async) { 106 106 var o = { method: 'port-test' }; … … 109 109 110 110 renameTorrent: function(torrentIds, oldpath, newname, callback, context) { 111 var o = { method: 'torrent-rename-path', 112 arguments: { 'ids': torrentIds, 113 'path': oldpath, 114 'name': newname } 111 var o = { 112 method: 'torrent-rename-path', 113 arguments: { 114 'ids': torrentIds, 115 'path': oldpath, 116 'name': newname 117 } 115 118 }; 116 119 this.sendRequest(o, callback, context); … … 125 128 var o = { 126 129 method: 'torrent-get', 127 'arguments': {130 arguments: { 128 131 'fields': fields 129 132 } … … 185 188 moveTorrents: function(torrent_ids, new_location, callback, context) { 186 189 var remote = this; 187 this.sendTorrentSetRequests( 'torrent-set-location', torrent_ids, 190 this.sendTorrentSetRequests( 'torrent-set-location', torrent_ids, 188 191 {"move": true, "location": new_location}, callback, context); 189 192 }, -
trunk/web/javascript/torrent-row.js
r14236 r14523 240 240 // append UL stats: ', uploaded 8.59 GiB (Ratio: 12.3)' 241 241 c.push(', uploaded ', 242 243 244 245 242 Transmission.fmt.size(t.getUploadedEver()), 243 ' (Ratio ', 244 Transmission.fmt.ratioString(t.getUploadRatio()), 245 ')'); 246 246 } else { // not done yet 247 247 c = [ Transmission.fmt.size(sizeWhenDone - t.getLeftUntilDone()), … … 258 258 else 259 259 c.push(Transmission.fmt.timeInterval(t.getETA()), 260 260 ' remaining'); 261 261 } 262 262 -
trunk/web/javascript/torrent.js
r13551 r14523 132 132 { 133 133 var i, observer; 134 134 135 135 if (o[name] === value) 136 136 return false; … … 421 421 return (a - b) || Torrent.compareByRatio(ta, tb); 422 422 }; 423 424 423 Torrent.compareBySize = function(ta, tb) 425 424 { 426 427 428 429 430 } 425 var a = ta.getTotalSize(), 426 b = tb.getTotalSize(); 427 428 return (a - b) || Torrent.compareByName(ta, tb); 429 }; 431 430 432 431 Torrent.compareTorrents = function(a, b, sortMethod, sortDirection) … … 448 447 i = Torrent.compareByProgress(a,b); 449 448 break; 450 451 452 449 case Prefs._SortBySize: 450 i = Torrent.compareBySize(a,b); 451 break; 453 452 case Prefs._SortByState: 454 453 i = Torrent.compareByState(a,b); … … 489 488 torrents.sort(this.compareByProgress); 490 489 break; 491 492 493 490 case Prefs._SortBySize: 491 torrents.sort(this.compareBySize); 492 break; 494 493 case Prefs._SortByState: 495 494 torrents.sort(this.compareByState); -
trunk/web/javascript/transmission.js
r14518 r14523 91 91 if (this.isMenuEnabled) 92 92 this.createSettingsMenu(); 93 93 94 94 e = {}; 95 95 e.torrent_list = $('#torrent_list')[0]; … … 607 607 delete this.sessionInterval; 608 608 if (enabled) { 609 609 var callback = $.proxy(this.loadDaemonPrefs,this), 610 610 msec = 8000; 611 611 this.sessionInterval = setInterval(callback, msec); … … 705 705 case 'tipjar': 706 706 window.open('http://www.transmissionbt.com/donate.php'); 707 break; 707 break; 708 708 709 709 case 'unlimited_download_rate': … … 945 945 jQuery.each (fileInput[0].files, function(i,file) { 946 946 var reader = new FileReader(); 947 reader.onload = function(e) { 947 reader.onload = function(e) { 948 948 var contents = e.target.result; 949 949 var key = "base64," … … 970 970 var url = $('#torrent_upload_url').val(); 971 971 if (url != '') { 972 if (url.match(/^[0-9a-f]{40}$/i)) 972 if (url.match(/^[0-9a-f]{40}$/i)) 973 973 url = 'magnet:?xt=urn:btih:'+url; 974 974 var o = { … … 1002 1002 var ids = this.getTorrentIds(torrents); 1003 1003 this.remote.moveTorrents( 1004 ids, 1005 $("input#torrent_path").val(), 1006 this.refreshTorrents, 1004 ids, 1005 $("input#torrent_path").val(), 1006 this.refreshTorrents, 1007 1007 this); 1008 1008 $('#move_container').hide(); … … 1200 1200 { 1201 1201 var limit, limited, e, b, text, 1202 1203 1202 fmt = Transmission.fmt, 1203 menu = $('#footer_super_menu'); 1204 1204 1205 1205 this.serverVersion = o.version; … … 1228 1228 1229 1229 e = menu.find('#limited_download_rate'); 1230 1231 1232 1233 1230 e.html('Limit (' + fmt.speed(limit) + ')'); 1231 1232 if (!limited) 1233 e = menu.find('#unlimited_download_rate'); 1234 1234 e.selectMenuItem(); 1235 1235 } … … 1242 1242 1243 1243 e = menu.find('#limited_upload_rate'); 1244 1245 1246 1247 1244 e.html('Limit (' + fmt.speed(limit) + ')'); 1245 1246 if (!limited) 1247 e = menu.find('#unlimited_upload_rate'); 1248 1248 e.selectMenuItem(); 1249 1249 } … … 1536 1536 for (i=0; row=rows[i]; ++i) 1537 1537 e.push(row.getElement()); 1538 $(e).filter(":odd").addClass('even'); 1539 $(e).filter(":even").removeClass('even'); 1538 $(e).filter(":odd").addClass('even'); 1539 $(e).filter(":even").removeClass('even'); 1540 1540 1541 1541 // sync gui … … 1681 1681 if (enabled) { 1682 1682 var callback = $.proxy(this.loadDaemonStats,this), 1683 1683 msec = 5000; 1684 1684 this.statsInterval = setInterval(callback, msec); 1685 1685 }
Note: See TracChangeset
for help on using the changeset viewer.