google 浏览器插件开发简单学习案例:TodoList;打包成crx离线包

news2024/11/24 6:16:19

参考:
google插件支持:
https://blog.csdn.net/weixin_42357472/article/details/140412993

这里是把前面做的TodoList做成google插件,具体网页可以参考下面链接

TodoList网页:
https://blog.csdn.net/weixin_42357472/article/details/140594704

1、代码部分

下面开始把内容转成google插件:

在这里插入图片描述
为扩展准备三个不同尺寸的图标(16x16, 48x48, 128x128像素),并将它们放在 icons 文件夹中
在这里插入图片描述
manifest.json
google浏览器差距定义文件

{
    "manifest_version": 3,
    "name": "TodoList Extension",
    "version": "1.0",
    "description": "A simple TodoList Chrome extension",
    "action": {
      "default_icon": {
        "16": "icons/icon16.png",
        "48": "icons/icon48.png",
        "128": "icons/icon128.png"
      }
    },
    "permissions": ["storage", "sidePanel"],
    "background": {
      "service_worker": "background.js"
    },
    "icons": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    },
    "side_panel": {
      "default_path": "index.html"
    }
  }

background.js
想在侧边栏打开

chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TodoList</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>TodoList</h1>
    <form id="todo-form">
        <input type="text" id="todo-input" placeholder="Enter a new task" required>
        <button type="submit" id="add-button">Add</button>
    </form>
    <ul id="todo-list"></ul>

    <script src="script.js"></script>
</body>
</html>

script.js

const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');

function loadTodos() {
    chrome.storage.sync.get(['todos'], function(result) {
        const todos = result.todos || [];
        todos.forEach(todo => {
            addTodoToDOM(todo.text, todo.completed);
        });
    });
}

function saveTodos() {
    const todos = Array.from(todoList.children).map(li => ({
        text: li.querySelector('span').textContent,
        completed: li.classList.contains('completed')
    }));
    chrome.storage.sync.set({todos: todos});
}

function addTodoToDOM(text, completed = false) {
    const li = document.createElement('li');
    li.className = 'todo-item' + (completed ? ' completed' : '');
    li.innerHTML = `
        <input type="checkbox" ${completed ? 'checked' : ''}>
        <span>${text}</span>
        <button class="delete-button">Delete</button>
    `;

    li.querySelector('input[type="checkbox"]').addEventListener('change', function() {
        li.classList.toggle('completed');
        if (li.classList.contains('completed')) {
            todoList.appendChild(li);
        } else {
            todoList.insertBefore(li, todoList.firstChild);
        }
        saveTodos();
    });

    li.querySelector('.delete-button').addEventListener('click', function() {
        li.remove();
        saveTodos();
    });

    if (completed) {
        todoList.appendChild(li);
    } else {
        todoList.insertBefore(li, todoList.firstChild);
    }
}

todoForm.addEventListener('submit', function(e) {
    e.preventDefault();
    if (todoInput.value.trim() === '') return;

    addTodoToDOM(todoInput.value);
    saveTodos();
    todoInput.value = '';
});

loadTodos();

styles.css

body {
    font-family: Arial, sans-serif;
    max-width: 500px;
    margin: 0 auto;
    padding: 20px;
}
h1 {
    text-align: center;
}
#todo-form {
    display: flex;
    margin-bottom: 20px;
}
#todo-input {
    flex-grow: 1;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ddd;
    border-radius: 4px 0 0 4px;
}
#add-button {
    padding: 10px 20px;
    font-size: 16px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 0 4px 4px 0;
    cursor: pointer;
}
#todo-list {
    list-style-type: none;
    padding: 0;
}
.todo-item {
    display: flex;
    align-items: center;
    padding: 10px;
    background-color: #f9f9f9;
    border: 1px solid #ddd;
    margin-bottom: 10px;
    border-radius: 4px;
}
.todo-item.completed {
    text-decoration: line-through;
    opacity: 0.6;
}
.todo-item input[type="checkbox"] {
    margin-right: 10px;
}
.delete-button {
    margin-left: auto;
    background-color: #f44336;
    color: white;
    border: none;
    padding: 5px 10px;
    border-radius: 4px;
    cursor: pointer;
}

2、加载使用

在插件中心加载上面的文件夹,注意提前打开开发者模型
在这里插入图片描述
然后点击右上角对应的todolist插件即可
在这里插入图片描述
在这里插入图片描述

3、打包成crx离线包

chrome://extensions

打包插件
在"扩展程序"页面,点击"打包扩展程序"按钮
在"扩展程序根目录"中,选择你的插件文件夹
如果是第一次打包,可以不填"私有密钥文件"
点击"打包扩展程序"

在这里插入图片描述
打包回生成两个文件:

Chrome会生成两个文件:一个.crx文件和一个.pem文件
.crx文件就是你需要的离线安装包
.pem文件是私钥,用于后续更新,请妥善保管

在这里插入图片描述

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

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

相关文章

docker基础镜像

一、配置 docker 本地源 [docker-ce-stable] nameDocker CE Stable baseurlhttp://10.35.186.181/docker-ce-stable/ enabled1 gpgcheck0 配置阿里云Docker Yum源 yum install -y yum-utils device-mapper-persistent-data lvm2 git yum-config-manager --add-repo http://mirr…

简单修改,让UE4/5着色器编译速度变快

简单修改&#xff0c;让UE4/5着色器编译速度变快 目录 简单修改&#xff0c;让UE4/5着色器编译速度变快 一、问题描述 二、解决方法 &#xff08;一&#xff09;硬件升级 &#xff08;二&#xff09;调整相关设置和提升优先级 1.调整相关设置 &#xff08;1&#xff09…

【Android】碎片的初识

之前我们学习的是一个活动作为一个页面&#xff0c;有了平板之后&#xff0c;页面如果像手机一样设计就会浪费很多的空间&#xff0c;会有很多的空白区域&#xff0c;为了使屏幕充分利用&#xff0c;引入了碎片这样一个概念。 碎片&#xff08;Fragment&#xff09;&#xff1…

pikachu之sql lnjet 字符型注入

先测试一下闭合 注释符号&#xff1a;-- 注释符号可以忽略其后的内容&#xff0c;使得后续的原始查询内容不会影响我们注入的SQL代码。 条件测试&#xff1a;通过and 11和and 12分别测试真假条件&#xff0c;可以判断输入是否成功闭合&#xff0c;并且可以检测注入是否成功。 …

构造+位运算,CF 1901C - Add, Divide and Floor

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1901C - Add, Divide and Floor 二、解题报告 1、思路分析 我们假设将原数组排序&#xff0c;那么每次操作不会改变数组单调性 当 最大值 调整等于 最小值时 所有数都相等&#xff0c;因为单调性不变&…

VS2022下安装和配置OpenCV环境参数+QT开发环境搭建(1)

1.工具准备 VS2022,OpenCV4.5.5版本&#xff0c;QT5.12.12 VisualStudio最新版直接官网下载&#xff0c;根据需要进行下载&#xff0c;我下载的免费社区版本。日常开发完全够用。 qt官网下载5.12版本。 OpenCVReleases - OpenCV 选择Windows版本下载并解压到本地磁盘&#xff0…

操作系统——笔记(1)

操作系统是管理计算机硬件资源&#xff0c;控制其他程序运行并为用户提供交互操作界面的系统软件的集合&#xff0c;控制和管理着整个计算机系统的硬件和软件资源&#xff0c;是最基本的系统软件。 常见的操作系统&#xff1a;ios、windows、Linux。 计算机系统的结构层次&am…

【SpringCloud】微服务远程调用OpenFeign

工作原理流程图 上代码 common中添加依赖&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency><groupId>org.spri…

Android APP 音视频(01)MediaCodec解码H264码流

说明&#xff1a; 此MediaCodec解码H264实操主要针对Android12.0系统。通过读取sd卡上的H264码流Me获取视频数据&#xff0c;将数据通过mediacodec解码输出到surfaceview上。 1 H264码流和MediaCodec解码简介 1.1 H264码流简介 H.264&#xff0c;也被称为MPEG-4 AVC&#xff…

用51单片机或者stm32能否开发机器人呢?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;能的。但是由于单片机和st…

记录安装android studio踩的坑 win7系统

最近在一台新电脑上安装android studio,报了很多错误&#xff0c;也是费了大劲才解决&#xff0c;发出来大家一起避免一些问题&#xff0c;找到解决方法。 安装时一定要先安装jdk&#xff0c;cmd命令行用java -version查当前的版本&#xff0c;没有的话&#xff0c;先安装jdk,g…

ARP欺骗——华为ensp

首先&#xff0c;搭建好网络拓扑。网络设备包含客户端Client1和服务端Server1&#xff0c;交换机 以及 云。 图中的 Client和Server 配置IP地址&#xff0c;要和 vm8 在相同的网段。故设置客户端ip为192.168.11.10 &#xff0c;服务端ip为&#xff1a;192.168.11.20&#xff0…

MySQL补充性文件

数据库专属单词 authentication #身份验证 delimiter #分隔符 character #字符集 collate #整理。 指定字符集的排序规则 unicode #统一码 flush #刷新 privileges #特权 string #串 set #设置 use #使用 zerofill #修饰符。0可以填补输出的值 unsigned #修饰符。无符…

STM32--HAL库--定时器篇

一&#xff1a;如何配置定时器 打开对应工程串口配置好的工程&#xff08;上一篇博客&#xff09;做如下配置&#xff1a; 定时器的中断溢出时间计算公式是&#xff1a; 由图得T100*1000/100MHz 注&#xff1a;100MHz100000000 所以溢出时间等于1ms 关于上图4的自动重装…

Robot Operating System——初探动态配置Parameters

大纲 同步模式Node内使用declare_parameter方法声明Parameters创建Parameter同步访问客户端跨Node修改Parameters跨Node查询Parameters完整代码运行结果 异步模式创建Node&#xff0c;设置Parameters创建Parameter异步访问客户端异步设置&#xff0c;同步等待异步查询&#xff…

VMware三种网络模式---巨细

文章目录 目录 ‘一.网络模式概述 二.桥接模式 二.NAT模式 三.仅主机模式 四.案例演示 防火墙配置&#xff1a; 虚拟电脑配置 前言 本文主要介绍VMware的三种网络模式 ‘一.网络模式概述 VMware中分为三种网络模式&#xff1a; 桥接模式&#xff1a;默认与宿主机VMnet0绑…

CSP-J模拟赛day1——解析+答案

题目传送门 yjq的吉祥数 题解 送分题&#xff0c;暴力枚举即可 Code #include<bits/stdc.h> using namespace std;int l,r; int num1,tmp0,q[10000],a[10000]; int k (int x){for (int j1;j<tmp;j){if (xq[j])return 0;}return 1; } int main(){while (num<100…

php连接sql server

php连接sqlserver有三种方式 一&#xff1a;odbc连接&#xff0c;废话不多说直接上代码,封装了一个单例 <?php /*** odbcServer.php* Author: Erekys*/namespace App\Model; class odbcServer{public static $server;public static $username;public static $password;pu…

dora-rs学习之Rust 和机器人

最近在研究一个网红机器人框架 dora-rs&#xff0c;也看到一些具身智能相关&#xff0c;做机器人遥操作与数据采集及可视化系统的公司使用rust来开发&#xff0c;这里探讨一下dora-rs和rust给机器人带来什么&#xff0c;引述官方的描述&#xff1a;Hello from dora-rs | dora-r…

svelte - 5. 动画

svelte/motion模块导出两个函数&#xff1a; tweened 和 spring。 用于创建writable&#xff08;可写&#xff09;store&#xff0c;其值会在set 和 update之后更新&#xff0c;而不是立即更新。 &#xff08;人话&#xff1a;用 svelte 提供的tweened 和 spring可以达成流程变…