在Chrome扩展程序中保留页面操作的状态

时间:2015-08-04 02:54:35

标签: javascript google-chrome google-chrome-extension

所以,我有以下代码:

var clicks = 0; // click counter

// Make sure this only runs on facebook
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (tab.url.indexOf("facebook.com") > -1) {
        chrome.pageAction.show(tabId);
    }
});

// Called when the user clicks on the page action.
chrome.pageAction.onClicked.addListener(function(tab) {
  if (clicks == 0) {
    chrome.pageAction.setIcon({path: "dontlike.png", tabId: tab.id}); // Update icon
    chrome.pageAction.setTitle({title: "idontlike", tabId: tab.id}); // Update title
    chrome.tabs.executeScript({ // Hide like buttons
      code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display="none"; }'
    });
  } 
  else {
    chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
    chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
    chrome.tabs.executeScript({ // Show like buttons
      code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display=""; }'
    });
  }

  // wrap coutner around
  clicks++;
  if (clicks > 1)
    clicks = 0;
});

用于Chrome扩展程序,当点击pageaction图标时,它会隐藏facebook上的所有“赞”按钮。这有效;但是,无论何时加载新的facebook网址,扩展的状态都会丢失,例如如果按钮处于不喜欢模式(隐藏所有喜欢),如果我转到新页面,它将被重置为类似模式。

我有一个想法是使用点击计数器来保持扩展的状态,并使代码更具功能性,如下所示

var clicks = 0; // click counter

function like() {
  chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
  chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
  chrome.tabs.executeScript({ // Show like buttons
    code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display="none"; }'
  });

  clicks++;
  if (clicks > 1) {
    clicks = 0;
  }
}

function dislike() {
  chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
  chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
  chrome.tabs.executeScript({ // Show like buttons
    code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display=""; }'
  });

  clicks++;
  if (clicks > 1) {
    clicks = 0;
  }
}

// Make sure this only runs on facebook
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (tab.url.indexOf("facebook.com") > -1) {
      chrome.pageAction.show(tabId);
      if (clicks == 0) {
        like();
      } 
      else {
        dislike();
      }
    }
});

// Called when the user clicks on the page action.
chrome.pageAction.onClicked.addListener(function(tab) {
  if (clicks == 0) {
    like();
  } 
  else {
    dislike();
  }
});

但是该代码根本不起作用(当我点击页面操作图标时,没有任何反应,并且Chrome控制台中没有出现错误消息)。

我是JS和Chrome扩展程序的新手。是否有一种简单的方法来保持我的扩展状态,以及一种更好的方法来执行我需要隐藏所有类似按钮的脚本?

谢谢!

2 个答案:

答案 0 :(得分:6)

chrome扩展中的状态问题可以有几个答案。选择取决于具体情况。我在你的情况下理解的是你只有两个状态,所以我会给你一些想法。

1。持久背景脚本

默认情况下,后台脚本在chrome启动时加载,因此它会在整个执行chrome期间生效,直到用户明确关闭chrome。结合内容脚本,您可以拥有状态完整系统。

因此,您可以使用此后台脚本在执行期间保存状态,并通知侦听内容脚本更改:

background.js

var state = 0;

chrome.pageAction.onClicked.addListener(function(tab) {
    if (state = 0) {
        state = 1;
        state0Actions(); //Do what you want
    } 
    else {
        state = 0;
        state1Actions(); //Do what you want
    }

    //Inform content scripts that the state have changed
    chrome.tabs.sendMessage(tab.id, {state : state});
});

//At initialisation, Content scipts will request the current state to background script.
chrome.runtime.onMessage(function(message, sender, callback){
    if(message.getState) callback({state : state});
});

然后,您可以将内容脚本添加到所有Facebook页面,方法是将其添加到manifest.json文件

"content_scripts" :
[
    {
        "matches": ["https://www.facebook.com/*","http://www.facebook.com/*"],
        "all_frames": true,

        "js": ["contentScript.js"]
    }
]

它会自动将contentScipt.js脚本注入以http(s)://www.facebook.com开头的所有页面。

contenScript.js         //为每个州做的行动     function state0Actions()     {         //为状态0做你想做的事     }

function state1Actions()
{
    //Do what you want for the state 1
}

//Message will be received at each update of state in the background page
chrome.runtime.onMessage.addListner(function(message, sender, callback))
{
    //Check the message is valid
    if(message.state == null)
    {
        console.log("Unreconized message");
        return;
    }

    //Do actions for the right state
    //You also can use if statements here... Switch are more used when there is lots of states
    switch(message.state) {
        case 0 : state0Actions(); break;
        case 1 : state1Actions(); break;
    }
}

//Request the current state to initialise the script
chrome.runtime.sendMessage({getState: true});

这里,onMessage处理程序将在加载时第一次调用,然后每次后台更改状态。

注意在Chrome启动时将重置状态。

2。 Chrome存储空间

您可以使用chrome.storage API来管理状态。其重点是状态将被保存,并且不会在chrome启动时重置。

为此,您使用相同的背景代码:

chrome.pageAction.onClicked.addListener(function(tab) {
    chrome.storage.local.get("state", function(result)
    {
        //First initialisation of the state in the local storage
        if(result.state == null)
        {
            chrome.storage.local.set({state: 0});
            state0Actions(); //Do what you want
        }
        else if (result.state == 0) {
            result.state = 1;
            state0Actions(); //Do what you want
        } 
        else {
            result.state = 0;
            state1Actions(); //Do what you want
        }

        //Save the new state to the storage
        chrome.storage.set({state: result.state});
    }
});

内容脚本将监听本地存储的更改,而不是从后台页面中获取更新通知:

//the actions to do for each states
function state0Actions()
{
    //Do what you want for the state 0
}

function state1Actions()
{
    //Do what you want for the state 1
}

chrome.storage.local.onChanged.addListener(function(changes, areaName)
{
    if(areaName != "local" || changes.state == null) return;

    switch(changes.state)
    {
        case 0 : state0Actions(); break;
        case 1 : state1Actions(); break;
    }
})

chrome.storage.local.get("state", function(result){
    if(result.state == null) state0Actions(); //Do what you want if the state is not yet initialised
    else if (result.state == 0) state0Actions(); //Do what you want
    else if (result.state == 1) state1Actions(); //Do what you want
})

您还可以使用chrome.storage.sync代替chrome.storage.local与所有用户的设备共享状态。

这是与国家一起玩的方式。你必须比较你的用例更好。我写的代码没有经过测试,它们只是用来说明我的解释的例子。

请勿忘记查看Chrome API documentation

答案 1 :(得分:1)

当扩展程序使用非持久性背景页面Event page时,它会在大约5秒不活动后卸载。每次重新加载时,代码都会再次运行,所有变量都会重新初始化,从而失去以前的状态。

解决方案是将状态存储在localStorage中,不需要manifest.json中的任何其他权限:

  • 初始化:

    var clicks = localStorage.clicks || 0; // click counter
    
  • 切换和存储(无需++if):

    var clicks = localStorage.clicks = 1 - clicks;
    

该值将被字符串化并存储为“0”或“1”,但对于上述算法,这不是问题。