谷歌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 相关文章推荐
javascript 禁用IE工具栏,导航栏等等实现代码
Apr 01 Javascript
node.js中的console.dir方法使用说明
Dec 10 Javascript
jquery实现焦点图片随机切换效果的方法
Mar 12 Javascript
Node.js程序中的本地文件操作用法小结
Mar 06 Javascript
jQuery UI Grid 模态框中的表格实例代码
Apr 01 jQuery
微信小程序 支付功能实现PHP实例详解
May 12 Javascript
vue使用监听实现全选反选功能
Jul 06 Javascript
vue中的自定义分页插件组件的示例
Aug 18 Javascript
Nuxt.js开启SSR渲染的教程详解
Nov 30 Javascript
解决Echarts 显示隐藏后宽度高度变小的问题
Jul 19 Javascript
原生js实现自定义难度的扫雷游戏
Jan 22 Javascript
JS中如何优雅的使用async await详解
Oct 05 Javascript
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 Ajax实现无刷新附件上传
2016/08/17 PHP
PHP获取二叉树镜像的方法
2018/01/17 PHP
Laravel中9个不经常用的小技巧汇总
2019/04/16 PHP
javascript 一个函数对同一元素的多个事件响应
2009/07/25 Javascript
js下将阿拉伯数字每三位一逗号分隔(如:15000000转化为15,000,000)
2014/06/02 Javascript
jquery动态遍历Json对象的属性和值的方法
2016/07/27 Javascript
jQuery实现的图片轮播效果完整示例
2016/09/12 Javascript
jquery移除了live()、die(),新版事件绑定on()、off()的方法
2016/10/26 Javascript
vue中mint-ui的使用方法
2018/04/04 Javascript
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
vue 实现 rem 布局或vw 布局的方法
2019/11/13 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
[02:47]3.19DOTA2发布会 国服成长历程回顾
2014/03/25 DOTA
[01:08:30]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第一场 2月28日
2021/03/11 DOTA
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
pytorch载入预训练模型后,实现训练指定层
2020/01/06 Python
python函数enumerate,operator和Counter使用技巧实例小结
2020/02/22 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
HTML5 Video/Audio播放本地文件示例介绍
2013/11/18 HTML / CSS
土耳其家居建材网站:Koçtaş
2016/11/22 全球购物
TripAdvisor印尼站:全球领先的旅游网站
2018/03/15 全球购物
香港通票:Hong Kong Pass
2019/02/26 全球购物
服务中心夜班服务员岗位职责
2013/11/27 职场文书
体育专业学生自我评价范文
2014/01/17 职场文书
《去年的树》教学反思
2014/04/11 职场文书
做一个有道德的人演讲稿
2014/05/14 职场文书
亲子运动会的活动方案
2014/08/17 职场文书
党委书记个人检查对照材料思想汇报
2014/10/11 职场文书
2014社区健康教育工作总结
2014/12/16 职场文书
清洁工工作总结
2015/08/11 职场文书
2016年国陪研修感言
2015/11/18 职场文书
销区经理年终述职报告模板
2019/11/28 职场文书
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL
java设计模式--七大原则详解
2021/07/21 Java/Android
详解Flutter和Dart取消Future的三种方法
2022/04/07 Java/Android
CSS list-style-type属性使用方法
2023/05/21 HTML / CSS