2017-08-04 26 views
1

我有一些編程知識,但是我沒有在Javascript中進行廣泛的工作或者之前處理過Chrome擴展。我期望構建一個Chrome擴展程序,在新選項卡中打開選定的鏈接(這是我想實現的最初目標,因爲我的最終目標是打開相同選項卡的框架中的鏈接 - 如果可能)爲了保存這些鏈接中的圖像,類似於Firefox的Save Images擴展所做的)。在Chrome擴展程序中關閉彈出框後記住數組

我有一個問題,但彈出窗口關閉後(由於打開新標籤),我彈出的選定鏈接不被「記住」以便使用延遲打開它們。我想這是關於不做一個後臺腳本來執行操作,而不是popup.js?也許在這兩個Javascipt文件之間傳遞一些消息?只是猜測這裏...

這是到目前爲止我的代碼:

manifest.json的

{ 
    "name": "Get links", 
    "version": "1.0", 
    "manifest_version": 2, 
    "description": "Get links from a page", 
    "browser_action": { 
    "default_icon": "icon.png", 
    "default_popup": "popup.html" 
    }, 
    "permissions": ["tabs", "downloads", "<all_urls>"] 
} 

popup.html

<!DOCTYPE html> 
<html> 
    <head> 
    <script src="popup.js"></script> 
    </head> 
    <body style="width:400px;"> 
    <form id="linksform"> 
     <p> 
     <label for="matchregex" style="margin-left: 7px;">RegEx Match: </label> 
     <input id="regextext" type="text" style="width:90px;" name="matchregex" value="" /> 
     <input id="togglematches" type="button" value="Toggle Matches" /> 
     <input id="openselected" type="button" value="Open Selected" /> 
     </p> 
     <table id='links'> 
     <th></th> 
     </table> 
    </form> 
    </body> 
</html> 

popup.js

var alllinks = []; 
var visiblelinks = []; 
var selectedlinks = []; 
var delay = 1000; 

// Display all visible links. 

function showlinks() 
    { 
    var togglematchesbutton = document.getElementById('togglematches'); 
    var openselectedbutton = document.getElementById('openselected'); 
    var linkstable = document.getElementById('links'); 
    while (linkstable.children.length > 1) 
    { 
    linkstable.removeChild(linkstable.children[linkstable.children.length - 1]) 
    } 
    for (var i = 0; i < visiblelinks.length; ++i) 
    { 
    var row = document.createElement('tr'); 
    var col0 = document.createElement('td'); 
    var col1 = document.createElement('td'); 
    var checkbox = document.createElement('input'); 
    checkbox.type = 'checkbox'; 
    checkbox.id = 'check' + i; 
    checkbox.checked = false; 
    checkbox.value = visiblelinks[i]; 
    col0.appendChild(checkbox); 
    col1.innerText = visiblelinks[i]; 
    col1.style.whiteSpace = 'nowrap'; 
    col1.onclick = function() 
     { 
     checkbox.checked = !checkbox.checked; 
     } 
    row.appendChild(col0); 
    row.appendChild(col1); 
    linkstable.appendChild(row); 
    } 
    togglematchesbutton.onclick = function() 
    { 
    var regex = new RegExp(document.getElementById("regextext").value); 
    var getinputs = document.getElementsByTagName("input"); 
    for (var i = 0, max = getinputs.length; i < max; i++) 
     { 
     if ((getinputs[i].type === 'checkbox') && (regex.test(getinputs[i].value))) getinputs[i].checked = !getinputs[i].checked; 
     } 
    } 
    openselectedbutton.onclick = function() 
    { 
    var getinputs = document.getElementsByTagName("input"); 
    for (var i = 0, max = getinputs.length; i < max; i++) 
     { 
     if ((getinputs[i].type === 'checkbox') && (getinputs[i].checked)) 
     { 
     selectedlinks.push(getinputs[i].value); 
     } 
     } 
    for (var i = 0, max = selectedlinks.length; i < max; i++) 
     { 
     window.setTimeout(function() {chrome.tabs.create({url: selectedlinks[i]});}, delay); 
     //chrome.tabs.create({url: selectedlinks[i]}); 
     } 
    } 
    } 

// Add links to alllinks and visiblelinks, sort and show them. Sendlinks.js is 
// injected into all frames of the active tab, so this listener may be called 
// multiple times. 

chrome.extension.onMessage.addListener 
    (
    function(links) 
    { 
    for (var index in links) 
     { 
     alllinks.push(links[index]); 
     } 
    alllinks.sort(); 
    visiblelinks = alllinks; 
    //console.log(links); 
    showlinks(); 
    } 
); 

// Set up event handlers and inject sendlinks.js into all frames in the active 
// tab. 

window.onload = function() 
    { 
    chrome.windows.getCurrent 
    (
    function (currentWindow) 
     { 
     chrome.tabs.query 
     (
     {active: true, windowId: currentWindow.id}, 
     function(activeTabs) 
      { 
      chrome.tabs.executeScript(activeTabs[0].id, {file: 'sendlinks.js', allFrames: true}); 
      } 
     ); 
     } 
    ); 
    }; 

sendlinks.js

// Send back to the popup a sorted deduped list of valid link URLs on this page. 
// The popup injects this script into all frames in the active tab. 
console.log("Injected"); 

var links = [].slice.apply(document.getElementsByTagName('a')); 
console.log(links); 
links = links.map 
    (
    function(element) 
    { 
    // Return an anchor's href attribute, stripping any URL fragment (hash '#'). 
    // If the html specifies a relative path, chrome converts it to an absolute 
    // URL. 
    var href = element.href; 
    var hashIndex = href.indexOf('#'); 
    if (hashIndex >= 0) 
     { 
     href = href.substr(0, hashIndex); 
     } 
    return href; 
    } 
); 

links.sort(); 

// Remove duplicates and invalid URLs. 
var kBadPrefix = 'javascript'; 
for (var i = 0; i < links.length;) 
    { 
    if (((i > 0) && (links[i] == links[i - 1])) || (links[i] == '') || (kBadPrefix == links[i].toLowerCase().substr(0, kBadPrefix.length))) 
    { 
    links.splice(i, 1); 
    } 
    else 
    { 
    ++i; 
    } 
    } 
console.log(links); 

chrome.extension.sendMessage(links); 

注:這段代碼的大部分是從其他地方取,並已被修改,以滿足我的需求。

的主要問題是從popup.js此代碼段:

for (var i = 0, max = selectedlinks.length; i < max; i++) 
    { 
    window.setTimeout(function() {chrome.tabs.create({url: selectedlinks[i]});}, delay); 
    //chrome.tabs.create({url: selectedlinks[i]}); 
    } 

如果我評論的setTimeout的線,並取消對以下行,它的工作原理(如擴展打開的選項卡成功),但它不會在打開連續的選項卡之間使用延遲 - 這是避免某些網站上的「請求太多」錯誤所必需的。如果我放過它,它會打開它應該打開的標籤數量(使用指定的延遲),但這些標籤的URL不匹配選定的值(基本上它們是空白的)。我想要的是後者發生,但打開選定的鏈接,而不是空白標籤。

請您指出我的錯誤在哪裏,並建議修改代碼以使其工作?如果可行,通過保持現有代碼儘可能接近發佈的版本(也就是隻對源代碼進行小修改)。謝謝。

回答

0

沒關係,我解決了這個問題。事實證明,由於某種原因,Chrome不記得for循環內部的變量(可能由於settimeout()for循環相比異步工作,由於延遲?),所以它不能引用正確的數組元素。

我所要做的就是與

window.setTimeout(function() {chrome.tabs.create({url: selectedlinks.shift()});}, delay); 

替換上面

window.setTimeout(function() {chrome.tabs.create({url: selectedlinks[i]});}, delay); 

,它完美地工作。基本上,代替使用變量引用數組元素,更新後的代碼始終引用第一個數組元素,同時將其刪除,從而「遍歷」整個數組,並消除爲其設置的元素選項卡已創建。

相關問題