Firefox插件(拓展)开发

news2024/12/27 20:55:23

目录

0、一些概念

1、创建一个项目

2、创建内容脚本

3、将拓展临时添加到浏览器中进行测试

3-1、Ctrl+Shift+A 或:

3-2、选择调试附加组件

 3-3、选择临时加载附加组件

3-4、选择我们项目中的 manifest.json 文件打开

3-5、如果打开成功:

4、继续开发和调试

 5、添加拓展按钮到工具栏

6、为在浏览器工具栏中的拓展按钮指定一个弹出窗

 7、为弹出窗中的按钮绑定点击事件

8、插件侧边栏的开启和切换

9、插件配置侧边栏

10、添加并处理侧边栏元素事件

11、通过右键菜单来取消事件

12、参考


0、关于插件中脚本的一些概念

JavaScript编写插件时,通常分为以下几个脚本:

1. Content Script(内容脚本):用于操作网页内容,可以访问DOM和页面元素,可以修改页面样式和行为,与页面共享同一个JavaScript环境。

2. Background Script(后台脚本):用于处理插件的后台任务,例如处理网络请求、管理插件状态、与其他插件通信等,与页面不共享JavaScript环境。

3. Popup Script(弹出窗口脚本):用于处理插件弹出窗口的交互逻辑,例如响应用户点击事件、发送消息给后台脚本等。

4. Options Script(选项页面脚本):用于处理插件选项页面的交互逻辑,例如保存用户设置、发送消息给后台脚本等。

1、创建一个项目

        新建一个目录,在目录下创建一个 manifest.json 配置文件,写入最简单的基本配置:

/* 注意,这是一个 json 文件,文件里面不能有注释性的内容 */
{
    "manifest_version": 2,      // 必须是2或3
    "name": "FirstTest",        // 拓展的名称
    "version": "0.0.1",         // 拓展的版本号
 
    "description": "my first test",    // 对当前拓展的描述

    "icons": {                 // 配置拓展的图标
        "48": "./java.jpg",
        "96": "./java.jpg"
    },

    "content_scripts": [       // 内容脚本配置
        {
            "matches": ["*://*/*"],    // 匹配应该当前拓展的URL,当前是匹配全部URL
            "js": ["index.js"]         // 脚本文件
        }
    ]
}

2、创建内容脚本

        在项目目录下创建一个 index.js 写一个简单的内容脚本。

        这个 index.js 就是manifest.json文件中("content_scripts"."js")[1]中的内容(名字要一致才匹配到)。

document.body.style.backgroundColor = '#ff8f0029';

        这个index.js 文件只写一段代码,内容是让 body 的背景色变成一种浅肉色。

3、将拓展临时添加到浏览器中进行测试

        在火狐中添加:

3-1、Ctrl+Shift+A 或:

3-2、选择调试附加组件

 3-3、选择临时加载附加组件

3-4、选择我们项目中的 manifest.json 文件打开

        在谷歌浏览器中是要将整个项目的文件夹导入

3-5、如果打开成功:

         此时我们打开其他的网页查看,如进入到百度:

        可以看到网页加载完成后,在短暂的时间内背景色会变成上面的颜色,页面的body元素确实添加了我们在内容脚本中设置的样式。

4、继续开发和调试

        当我们完成了上述的步骤之后,我们可以继续在我们的项目中进行开发。

        当我们需要继续到浏览器中进行调试和观察的时候,只需要将文件保存,然后到浏览器临时扩展处点击重载按钮,即可实现同步(确保项目文件路径没有改变)。

 5、添加拓展按钮到工具栏

        在 manifest.json 文件中添加:

    "browser_action": {
        "default_icon": {        // 指定图标
            "19": "./java.jpg",
            "38": "./java.jpg"
        },
        "default_title": "这个是工具栏按钮"
    }

6、为在浏览器工具栏中的拓展按钮指定一个弹出窗

        在项目中新建一个 popup 文件夹,在文件夹下建立一个 popup.html 文件,在里面编写弹出窗的html代码,也可以编写与之相关的css、js代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        html,body{
            width: 100px;
            box-sizing: border-box;
            /* padding: 5px 8px; */
        }
        .popup-content{
            width: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        .popup-content > button{
            width: 95%;
            height: 35px;
            border-radius: 12px;
            border: 0;
            box-shadow: 0 1px 10px 1px #cccfff;
            margin: 5px 0;
            background-color: rgb(188, 209, 249);
        }
        button:hover{
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="popup-content">
        <button>选项A</button>
        <button>选项B</button>
        <button>选项C</button>
    </div>
</body>
</html>

        在 manifest.json 文件中添加 default_popup:

    "browser_action": {
        "default_icon": {
            "19": "./java.jpg",
            "38": "./java.jpg"
        },
        "default_title": "这个是工具栏按钮",
        "default_popup": "popup/popup.html"  // 添加这一句,指定弹出窗的html文件
    }

         到临时拓展中对当前拓展进行重载,然后点击工具栏对应的按钮,就可以看到弹出窗:

 7、为弹出窗中的按钮绑定点击事件

        刚才的 .html 文件中提供了三个按钮,现在试图为每一个按钮绑定一个点击事件,当用户点击到一个按钮时,切换当前页面的 body 元素的背景色。

        先修改 .html 文件,为按钮添加一个相同的类名以及不同的innerText:

    <div id="popup-content">
        <button class="popup-btn">#ff00002e</button>
        <button class="popup-btn">#0000ff21</button>
        <button class="popup-btn">#2cff0026</button>
    </div>

        在 popup 目录下新建一个 popup.js 文件,然后在.html 文件中引入:

<script src="./popup.js"></script>

        编写 popup.js 文件来实现要求:

// 这里的 document 就是我们 编写的 popup.html
let btns = document.querySelectorAll('.popup-btn');

// 这里的打印是在调试插件的控制台中打印
console.log('btns:', btns);

// 为每一个 button 绑定事件
btns.forEach(e => {
    e.addEventListener('click', ()=>{
        // 这里的 innerText 就是一个十六进制的颜色值
        action(e.innerText);
    })
})

function action(color){
    // 使用 tabs 可以与浏览器系统标签进行交互
    /*
        tabs.query 获取具有指定属性的所有选项卡,如果未指定任何属性,则获取所有选项卡
        配置对象的 active:true 表示要获取的选项卡在页面中处于活动状态
        currentWindow:true 表示在当前的窗口中进行操作
    */
    browser.tabs.query({active: true, currentWindow: true}, tabs => {
        // 为当前窗口注入脚本
        browser.tabs.executeScript({code: `
            // 此时是在页面的控制台中打印,操作的是当前浏览的页面 
            console.log('color: ${color}');
            document.body.style.backgroundColor = '${color}';
        `});
    });
}

        由于要使用到 tab 这个API,需要在manifest.json 文件中添加许可:

    "permissions":[
        "activeTab"
    ]

        到临时拓展的位置,点击当前临时拓展模块上的“检查”按钮,即可打开插件开发的检查调试工具。

        当点击工具栏上的插件图标时, 会在插件的开发者工具的控制台中打印 popup.html 中三个按钮。

        当点击插件弹窗的第一个按钮时,页面背景色改变,同时在控制台中输出当前背景色号:

 

        点击第二个按钮后:

8、插件侧边栏的开启和切换

 

         将侧栏拖动到工具栏的位置:

 

         点击该侧栏按钮就能打开或关闭插件的侧边栏(只有插件提供了侧边栏,才有侧边栏的服务)。

9、插件配置侧边栏

        在 manifest.json 中添加 “sidebar_action” 配置项,default_title 设置侧边栏的名称为“My sidebar”,default_panel 设置面板的界面文件为指定的html文件,“default_icon”设置侧边栏的图标。

    "sidebar_action": {
        "default_title": "My sidebar",
        "default_panel": "./sidebar/sidebar.html",
        "default_icon": "./sidebar/sidebar_icon.png"
    },

         在项目文件夹下创建一个 sidebar 目录,并在该目录下创建一个 sidebar.html 文件,用来配置侧边栏的界面。

        写一个简单的侧边栏界面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .container{
            border: 3px solid pink;
            width: 100%;
            height: 100vh;
            box-sizing: border-box;
        }
        .top-btns{
            width: 100%;
            height: 50px;
            display: flex;
            justify-content: space-around;
            padding: 5px 8px;
        }
        .top-btns > button{
            outline: none;
            padding: 3px 12px;
            border-radius: 8px;
            box-shadow: 0 1px 10px 2px #eeefff;
            border: 0;
            background-color: rgb(209, 165, 251);
        }
        .top-btns > button:hover{
            cursor: pointer;
            box-shadow: 0 1px 5px .5px #cacaca;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="top-btns">
            <button>btn A</button>
            <button>btn B</button>
        </div>
    </div>
</body>
</html>

         在这里可以切换插件的侧边栏,当前只有一个插件(就是现在这个插件)提供了侧边栏服务,所以没有其他可以切换。

 

10、添加并处理侧边栏元素事件

        在 sidebar.html 文件中添加 script 标签,引入script 脚本处理侧边栏事件:

<script src="./index.js"></script>

        在 index.js 文件中,为两个按钮添加点击事件。当点击第一个按钮后,操作鼠标在当前浏览的页面中滑动,当鼠标悬浮在某元素上时,为该元素进行高亮描边。当点击第二个按钮时,取消该事件,操作鼠标在网页上滑动时,悬浮在某元素上,元素的 border 不再改变。

// 获取到两个按钮
const btns = document.querySelectorAll('.top-btns button');

// 获取当前激活的标签页面
browser.tabs.query({active: true, currentWindow: true}).then((logTabs,onError)=>{
    // 然后往当前页面中注入内容脚本,就行操作当前页面一样
    browser.tabs.executeScript({
        code:`
            // 将函数挂在window身上,可以让下次注入的脚本共享此函数
            window.mouseOverFunc = (e) => {         // 鼠标悬浮
                let target = e.target;
                target.style.border= '3px ridge red';    // 当前鼠标悬浮的元素描边
            }
            window.mouseOutFunc = (e) => {          // 鼠标离开
                let target = e.target;
                target.style.border = '';
            }
        `
    })
})

// 点击第一个按钮 开启悬浮高亮
btns[0].addEventListener('click',()=>{
    browser.tabs.query({active: true, currentWindow: true}).then((logTabs,onError)=>{
        browser.tabs.executeScript({
            code:`
                // 注入的脚本可以共享 mouseOverFunc、mouseOutFunc 函数
                document.addEventListener('mouseover', mouseOverFunc)
                document.addEventListener('mouseout', mouseOutFunc)
            `
        })
    })
})

// 点击第二个按钮取消悬浮高亮
btns[1].addEventListener('click',()=>{
    browser.tabs.query({active: true, currentWindow: true}, tabs => {
        // 为当前窗口注入脚本
        browser.tabs.executeScript({code: `
            // 移除鼠标悬浮和离开的border
            document.removeEventListener('mouseover',mouseOverFunc);
            document.removeEventListener('mouseout',mouseOutFunc);
        `});
    });
})

 

11、通过右键菜单来取消事件

         继续在 index.js 文件中增加代码:

// 创建右键菜单选项,用于停止选择
browser.contextMenus.create({
    id: "stop-select-element",              // id在菜单中唯一
    title: "stop select element",           // 名称
    contexts: ["page", "selection", "link"]     // 在哪些情况下有该选项
});
// 监听右键菜单选项被点击
browser.contextMenus.onClicked.addListener((info,tab)=>{
    // 判断是否执行
    if(info.menuItemId === 'stop-select-element'){
        // 注入脚本,移除事件监听器
        browser.tabs.query({active:true, currentWindow:true}).then(()=>{
            browser.tabs.executeScript({
                code:`
                    document.removeEventListener('mouseover',mouseOverFunc);
                    document.removeEventListener('mouseout',mouseOutFunc);
                `
            })
        })
    }
})

 

12、参考

你的第一个拓展 - Mozilla | MDN 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/617585.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】深入理解Java虚拟机 | 垃圾收集器GC

《深入理解Java虚拟机》的阅读笔记——第三章 垃圾收集器与内存分配策略。 参考了JavaGuide网站的相关内容&#xff1a;https://javaguide.cn/ Q&#xff1a;哪些内存需要回收&#xff1f;什么时候回收&#xff1f;如何回收&#xff1f; 2 对象已死吗&#xff1f; 2.1 引用…

4种普遍的机器学习分类算法

朴素贝叶斯分类 朴素贝叶斯分类是基于贝叶斯定理与特征条件独立假设的分类方法&#xff0c;发源于古典数学理论&#xff0c;拥有稳定的数学基础和分类效率。它是一种十分简单的分类算法&#xff0c;当然简单并不一定不好用。通过对给出的待分类项求解各项类别的出现概率大小&a…

Linux驱动开发(使用I2C总线设备驱动模型编写AT24C02驱动程序)

文章目录 前言一、I2C总线设备驱动模型二、设备树编写三、驱动程序编写1.提供i2c_driver结构体变量并且注册2.注册file_operations结构体3.操作AT24C02 四、应用程序编写五、上机测试总结 前言 本篇文章将讲解如何使用I2C总线设备驱动模型编写AT24C02驱动程序。 一、I2C总线设…

Linux platform 设备驱动实验

目录 1. platform平台简介 1.1 platform总线 1.2 platform 驱动 1.3 platform设备 2.platform平台总线初始化 3. platform驱动框架 4.实验 4.1 无设备树的platform设备注册 4.2 无设备树的platform驱动 4.3 有设备树的platform驱动 1. platform平台简介 当我们向系统…

java设计模式(十二)代理模式

目录 定义模式结构角色职责代码实现静态代理动态代理jdk动态代理cglib代理 适用场景优缺点 定义 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。说简单点&#xff0c;代理模式就是设置一个中间代理来控制访问原目标对象&#xff0c;以达到…

高度平衡二叉搜索树(AVLTree)(插入与旋转)

目录 简介 AVL的结点类 平衡因子的性质 AVL树的插入 更新平衡因子的接口(ChangeBf) 第一种情况&#xff1a;插入后父节点的平衡因子为0 第二种情况&#xff1a;更新后父节点的平衡因子的绝对值为1 第三种情况&#xff1a;更新后父节点的平衡因子的绝对值为2 旋转接口(…

cam_lidar_calibration代码详解(一)采样优化部分

目录 一、launch启动程序 1.1 run_optimiser.launch标定优化程序 1.2 assess_results.launch重投影误差评估程序 二、主要代码 2.1 feature_extraction_node.cpp文件 2.2 feature_extractor.cpp文件 2.2.1 FeatureExtractor::callback_camerainfo函数 2.2.2 serviceCB函…

QT快速操作Excel的实现介绍及操作类封装

QT中操作Excel还是比较简单的&#xff0c;Qt提供了QAxObject&#xff0c;包装COM组件的类&#xff0c;通过COM通过COM操作使用QAxObject类&#xff0c;使用此类&#xff0c;需要在pro文件中添加"QT   axcontainer "。 基本流程介绍 QAxObject&#xff1a; QAxObj…

SAP从入门到放弃系列之pMRP

最近学习pMRP&#xff0c;查了很多博客&#xff0c;机翻一篇内容非常详细的文章&#xff0c;感谢大佬&#xff1a; 原文地址&#xff1a; pMRP–Predictive Material and Resource Planning in SAP S/4HANA : Step by Step execution pMRP https://blogs.sap.com/2020/04/14/p…

机器学习【线性回归】

机器学习【线性回归】 回归预测的结果是离散型变量&#xff0c;身高和年龄 损失函数&#xff1a;SSE&#xff08;误差平方和&#xff09;&#xff0c;RSS&#xff08;残差平方和&#xff09;&#xff0c;误差越大越差 最小二乘法&#xff1a;通过最小化真实值和预测值之间的…

大数据:sparkSQL,历史,DataSet,DataFrame,sparkSession

大数据&#xff1a;sparkSQL 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sql要学…

第十章:创建和管理表

第十章&#xff1a;创建和管理表 10.1&#xff1a;基础知识 一条数据存储的过程 ​ 存储数据是处理数据的第一步。只有正确地把数据存储起来&#xff0c;我们才能进行有效的处理和分析。否则&#xff0c;只能是一团乱麻&#xff0c;无从下手。 ​ 在MySQL中&#xff0c;一个完…

使用模板方法模式封装协议消息

目录 整体框架 模板方法介绍 关于本案例设计 c impl惯用法 cimpl惯用法好处 此案例impl惯用法的设计 关于序列化和反序列化 序列化和反序列化 本项目使用介绍 谷歌测试 谷歌测试环境 谷歌测试用例 完整源码地址 概述 本文介绍了从 设计模式之模板方法模式协议消…

面对CPU狂飙时的5步解决方案

现在企业对后端开发的要求越来越高&#xff0c;不仅要求我们会写代码&#xff0c;还要我们能够进行部署和运维&#xff01; 项目上线并运行一段时间后&#xff0c;可能会发现部署所在的Linux服务器CPU占用过高&#xff0c;该如何排查解决&#xff1f; 本文用5步带你搞定线上CPU…

操作系统-进程和线程-同步、互斥、死锁

目录 一、同步互斥 二、互斥的实现方法 2.1软件实现 2.1.1单标志法 2.1.2双标志先检查 2.1.3双标志后检查 2.1.4Petersons算法 2.2硬件实现 2.2.1 TestAndSet指令 2.2.2 Swap指令 三、信号量机制 3.1整形变量 3.2 记录型变量 3.3用信号量实现进程互斥、同步、前驱关系…

Sui与F1甲骨文红牛车队达成合作

在近期达成的一项为期多年的合作协议中&#xff0c;甲骨文红牛车队将利用Sui网络开发&#xff0c;为粉丝带来全新的数字化体验。 甲骨文红牛车队的粉丝将很快在Sui网络上体验到他们最爱的一级方程式车队带来的激情。最近几个赛季一直统治着F1赛场的甲骨文红牛车队&#xff0c;与…

代码随想录算法训练营第五十三天 | 力扣 1143.最长公共子序列, 1035.不相交的线, 53. 最大子序和

1143.最长公共子序列 题目 1143. 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符…

2022年值得关注的7个主要SD-WAN趋势

随着SD-WAN技术在2022年继续发展成熟&#xff0c;该技术在集成远程访问、自动化和多云连接方面的支持有望得到更多的改进。 软件定义WAN仍然是增强用户体验(UX)&#xff0c;提高安全性&#xff0c;以及提供与基于云计算的应用程序的连接的一项关键技术。 随着SD-WAN的成熟&…

java设计模式之:原型模式

在我们的生活中&#xff0c;有很多例子&#xff0c;都是用到了原型模式&#xff0c;例如&#xff1a;我们去配钥匙的时候&#xff0c;肯定先要有一个原配钥匙才可以去配钥匙&#xff1b;《西游记》中孙悟空可以用猴毛根据自己的形象&#xff0c;复制&#xff08;又称“克隆”或…

时间序列预测 | Matlab基于北方苍鹰算法优化随机森林(NGO-RF)与随机森林(RF)的时间序列预测对比

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab基于北方苍鹰算法优化随机森林(NGO-RF)与随机森林(RF)的时间序列预测对比 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %-----------…