谷歌Chrome浏览器扩展程序开发小记


Posted in Javascript onJanuary 06, 2016

根据公司的规定,每月八小时,弹性工作制。所以大家平时来的不太准时,如果有事,下班也就早些回去了。所以一个月下来工作时间可能不够,但是公司的考勤日历是这样的:

谷歌Chrome浏览器扩展程序开发小记

除了请假和法定节假日外,其他样式显示都是一样的,每次都要一个个估算这个月的大概工作时间,十分不方便。后来看到公司有人在用一个Chrome扩展程序,可以计算出一个月的工作时间,但是我觉得还是没有看到我想看的东西,因为除了每个月的累计工作时间外,我还想看到:平均每天工作时长、每一天的工作时长、20点以后的天数(20点以后下班的可以报销晚饭的,哈哈……)、22点以后下班的天数(报销打车费)……所以我决定还是自己写一个吧。

第一步,我先写了一个JS方法,然后通过F12开发者工具的Console复制粘贴运行。

公司用的OA系统没有引用jQuery库,所以我刚开始的想法是想动态引用jQuery类库,如下:

var script = document.createElement("script");

script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js";

document.body.appendChild(script);

但是遇到了问题:一个是$被占用,二是HR系统采用iframe嵌套,并且还有frame嵌套,结构很复杂。而console运行的代码是在最顶层运行的,后期的chrome扩展插件是运行在内部frame中的,可能这里的JS后面不能直接使用。虽然$被占用的问题可以通过jQuery.noConflict();来解决,但是jquery库和原来系统的JS库存在调用顺序的问题,而且在内部的frame中死活访问不到jQuery这个对象。最后我决定放弃使用jQuery,该用原生JavaScript。

JS代码如下:

/*
 * author:清明雨上
 * date:2016-1-5
 */
var mydate = function() {
  //time2-time1
  function getTimeDiff(time1, time2) {
    var st1 = time1.split(':');
    var st2 = time2.split(':');
    return ((st2[0] | 0) * 60 + (st2[1] | 0)) - ((st1[0] | 0) * 60 + (st1[1] | 0) * 1);
  }

  var timeList = [];
  var mymain = window.parent.frames['Main'].document.getElementById('ctl00_cphMain_CalendarAC');
  var listAC = mymain.getElementsByClassName('listAC');
  for (var i = 0; i < listAC.length; i++) {
    var item = listAC[i];
    var t = {};
    t.timeSpan = item.getElementsByTagName('td')[1].innerText;
    t.remark = item.getElementsByTagName('td')[2].innerText;
    timeList.push(t);
  };

  var totalMin = 0;
  var noworkDays = 0; //请假天数
  var workDays = 0; //实际上班天数
  var workHourEveryday = [];
  var no8h = 0; //未满8小时天数
  var over20 = 0; //20点以后下班天数
  var over21 = 0; //21点以后下班天数
  var over22 = 0; //22点以后下班天数
  var over23 = 0; //23点以后下班天数
  for (var i = 0; i < timeList.length; i++) {
    var time = timeList[i];
    if (time.remark != '无') {
      noworkDays++;
      continue;
    }
    if (time.timeSpan == '无刷卡记录')
      continue;

    var splitTime = time.timeSpan.split('~');
    if (splitTime.length == 2) {
      //正常上下班
      var begin = splitTime[0];
      var end = splitTime[1];
      var thisMin = getTimeDiff(begin, end);
      totalMin += thisMin;
      workDays++;
      if (thisMin / 60 < 8) {
        workHourEveryday.push('<font color="red"><b style="font-size:15px">' + parseInt(thisMin / 60) + '</b>.' + thisMin % 60 + '</font>');
        no8h++;
      } else {
        workHourEveryday.push('<b style="font-size:15px">' + parseInt(thisMin / 60) + '</b>.' + thisMin % 60);
        var offworkHour = parseInt(end.split(':')[0]);
        if (offworkHour >= 20) {
          over20++;
        }
        if (offworkHour >= 21) {
          over21++;
        }
        if (offworkHour >= 22) {
          over22++;
        }
        if (offworkHour >= 23) {
          over23++;
        }
      }
    }
  };
  var myHour = parseInt(totalMin / 60); //本月工作累计小时数
  var otherMin = totalMin % 60; //本月工作出小时部分外的分钟数
  var avgHourOneDay = workDays == 0 ? '0.0' : '<b style="font-size:15px">'+(parseInt(myHour / workDays) + '</b>.' + (parseInt((myHour % workDays) * 60 / workDays) + parseInt(otherMin / workDays))); //平均每天工作时长

  var html = '<div class="alectest" style="background: #cbebfb;padding:7px;">\
        <div>出勤时间:<b style="font-size:15px;color:red">' + myHour + '</b>小时<font color="red">' + otherMin + '</font>分钟(平均<font color="red">' + avgHourOneDay + '</font>小时/天)</div>\
        <div>参考时间:' + workDays * 8 + '小时【' + workDays + '天】(除去请假和节假日,实际有打卡记录的天数)</div>\
        <div>请假/外出天数:' + noworkDays + '天</div>\
        <div>每天工作时间(格式:小时.分钟):' + workHourEveryday.join(',') + '</div>\
        <div>未满8小时天数:<b style="font-size:15px">' + no8h + '</b>天</div>\
        <div>20点以后下班天数:<b style="font-size:15px">' + over20 + '</b>天</div>\
        <div>21点以后下班天数:<b style="font-size:15px">' + over21 + '</b>天</div>\
        <div>22点以后下班天数:<b style="font-size:15px">' + over22 + '</b>天</div>\
        <div>23点以后下班天数:<b style="font-size:15px">' + over23 + '</b>天</div>\
       </div>'
  var alectest = mymain.parentNode.getElementsByClassName('alectest');
  if (alectest.length > 0) {
    // mymain.parentNode.removeChild(alectest[0]);
    alectest[0].innerHTML = html;
  } else {
    var div = document.createElement("div");
    div.innerHTML = html;
    var fragement = document.createDocumentFragment();
    while (div.childNodes[0]) {
      fragement.appendChild(div.childNodes[0]);
    }
    mymain.parentNode.insertBefore(fragement, mymain);
  }
  bindBtnClick();
}
var bindBtnClick = function() {
  window.parent.frames['Main'].document.getElementById('ctl00_cphTop_BtnQuery').addEventListener('click', function() {
    var inter = setInterval(function() {
      if (window.parent.frames['Main'].document.getElementById('ctl00_cphMain_CalendarAC') &&
        window.parent.frames['Main'].document.getElementById('ctl00_UpMaster').style.display == 'none') {
        clearInterval(inter);
        mydate();
      }
    }, 500);
  }, false);
}
bindBtnClick();

代码说明:监听考勤查询按钮的click事件,考勤信息加载完成后,执行我的JS方法。

第二步,开发Chrome扩展程序

参考资料:http://open.chrome.360.cn/extension_dev/content_scripts.html(查询manifest.json的content_scripts节点的各个属性说明)

manifest.json是必须的,最终内容如下:

{
 "manifest_version":2,
  "name": "Extension Name", 
 "version": "0.1.0", 
 "description": "插件描述",
 "icons": { "48": "icon.png" },
 "content_scripts": [
  {
   "all_frames" : true,
   "matches": ["http://*"],
   "js": ["haha.js"],
   "run_at": "document_end"
  }
 ]
}

另外,在同目录下放入一个icon.png图片,至此,所有文件都准备完毕,目录如下:

谷歌Chrome浏览器扩展程序开发小记

打开Chrome的扩展程序列表的开发者模式》大包扩展程序...,在扩展程序根目录中输入上面三个文件所在的父目录。

谷歌Chrome浏览器扩展程序开发小记

谷歌Chrome浏览器扩展程序开发小记

点击【打包扩展程序】即可。

说明:如果点击该按钮长时间未能反映,可以能是你的chrome不允许第三方非认证的扩展程序,解决方案是,点击chrome快捷方式右键》属性》目标输入框后面追加“ enable-easy-off-store-extension-install”,注意前面的空格。

谷歌Chrome浏览器扩展程序开发小记

然后再尝试以上步骤就行了。

第三步,防止Chrome屏蔽非官方扩展程序 设置

Chrome会提示暂停非官方扩展程序,每次启动就有提示,很烦人。

谷歌Chrome浏览器扩展程序开发小记

查找资料:http://www.itechzero.com/prevent-chrome-shielding-unofficial-extensions-tutorial.html(防止Chrome屏蔽非官方扩展程序教程)

根据以上资料说明,可以轻松解决这个问题。

至此,该可扩展程序全部完成,结果图如下:

谷歌Chrome浏览器扩展程序开发小记

Javascript 相关文章推荐
Jquery easyui 下loaing效果示例代码
Aug 12 Javascript
JQuery实现点击div以外的位置隐藏该div窗口
Sep 13 Javascript
javascript实现切换td中的值
Dec 05 Javascript
浅析JS动态创建元素【两种方法】
Apr 20 Javascript
bootstrap table复杂操作代码
Nov 01 Javascript
微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解
Dec 08 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
Apr 11 Javascript
详解AngularJS之$window窗口对象
Jan 17 Javascript
10 种最常见的 Javascript 错误(频率最高)
Feb 08 Javascript
node跨域转发 express+http-proxy-middleware的使用
May 31 Javascript
jQuery zTree插件快速实现目录树
Aug 16 jQuery
JavaScript自动生成 年月范围 选择功能完整示例【基于jQuery插件】
Sep 03 jQuery
JavaScript类型系统之基本数据类型与包装类型
Jan 06 #Javascript
4种JavaScript实现简单tab选项卡切换的方法
Jan 06 #Javascript
js针对ip地址、子网掩码、网关的逻辑性判断
Jan 06 #Javascript
js判断当前页面在移动设备还是在PC端中打开
Jan 06 #Javascript
js判断当前页面用什么浏览器打开的方法
Jan 06 #Javascript
javascript中闭包(Closure)详解
Jan 06 #Javascript
果断收藏9个Javascript代码高亮脚本
Jan 06 #Javascript
You might like
在PHP中操作Excel实例代码
2010/04/29 PHP
php中this关键字用法分析
2016/12/07 PHP
Javascript学习笔记9 prototype封装继承
2010/01/11 Javascript
Java 正则表达式学习总结和一些小例子
2012/09/13 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
JS验证邮箱格式是否正确的代码
2013/12/05 Javascript
jQuery实现回车键(Enter)切换文本框焦点的代码实例
2014/05/05 Javascript
js分页工具实例
2015/01/28 Javascript
浅谈javascript中for in 和 for each in的区别
2015/04/23 Javascript
js实现固定显示区域内自动缩放图片的方法
2015/07/18 Javascript
Bootstrap每天必学之按钮
2015/11/26 Javascript
jQuery验证插件validate使用详解
2016/05/11 Javascript
JS作为值的函数用法示例
2016/06/20 Javascript
jQuery得到多个值只能用取Class ,不能用取ID的方法
2016/12/04 Javascript
JavaScript设置名字输入不合法的实现方法
2017/05/23 Javascript
Angular如何引入第三方库的方法详解
2017/07/13 Javascript
详解如何理解vue的key属性
2019/04/14 Javascript
JavaScript进阶(三)闭包原理与用法详解
2020/05/09 Javascript
[07:39]第一届亚洲邀请赛回顾视频
2017/02/14 DOTA
[03:03]DOTA2 2017国际邀请赛开幕战队入场仪式
2017/08/09 DOTA
python logging类库使用例子
2014/11/22 Python
Python操作MongoDB详解及实例
2017/05/18 Python
Python使用装饰器模拟用户登陆验证功能示例
2018/08/24 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
python对常见数据类型的遍历解析
2019/08/27 Python
python super用法及原理详解
2020/01/20 Python
django3.02模板中的超链接配置实例代码
2020/02/04 Python
python def 定义函数,调用函数方式
2020/06/02 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
浅谈Selenium+Webdriver 常用的元素定位方式
2021/01/13 Python
解决tensorflow模型压缩的问题_踩坑无数,总算搞定
2021/03/02 Python
韩国知名的家庭购物网站:CJmall
2016/08/01 全球购物
365 Tickets英国:全球景点门票
2019/07/06 全球购物
扩大国家免疫规划实施方案
2014/03/21 职场文书
有限责任公司股东合作协议书
2014/12/02 职场文书
领导干部学习心得体会
2016/01/23 职场文书