js拦截页面跳转并获取目标地址

  1. navigation.onnavigate = function () {
  2. // 这里可以获取到最终跳转到的url
  3. var url = arguments[0].destination.url;
  4. console.log('url: ', url);
  5. return window.event.returnValue = false;
  6. }

关于Chrome跨域The request client is not a secure context and the resource is in more-private address space loca相关提示的解决

最近想使用serve 配置一个本地的 chrome 脚本注入功能, 没想到浏览器提示:

Access to script at ‘http://localhost:85/index.js‘ from origin ‘http://www.xxx.com‘ has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space local.

貌似是chrome有设置, 在地址栏中输入:
chrome://flags/#block-insecure-private-network-requests

然后选Disabled ,relaunch 后就能恢复正常了, 根据翻译:

block-insecure-private-network-requests
防止非安全上下文向更私密的IP地址发出子资源请求。如果1)IP1是本地主机,而IP2不是,或者2)IP1是私有的,而IP2是公共的,则IP地址IP1比IP2更私有。这是全面实施CORS-RFC1918的第一步:https://wicg.github.io/cors-rfc1918–Mac、Windows、Linux、Chrome OS、Android、Fuchsia
阻止不安全的专用网络请求

应该是处于安全考虑, 禁止向私有地址请求和发生数据

Espruino单片机上的javascript

  话说一直想用javascript语法写单片机程序, 因为我本身是web开发出身, 太熟悉js语法了, 以至于看到c 或 python都感觉很别扭, 于是就在网上找到了这个espruino, espruino是一个固件, 可以让esp8266等芯片支持使用js语法编程, 大大减少了web人员学习单片机开发的成本, 甚至可以让本身会js的人直接上手, 了解基础api后, 就可以直接开发自己的单片机项目了, 这里是官网: https://www.espruino.com/ , Espruino文档: http://www.espruino.com/Reference#software

  但是, 官网提供的开发工具用着很不习惯, 而且代码都在一个文件中, 很不方便管理.

  于是我就自己根据espruino的aip, 自己写了个命令行工具, 可以使用自己熟练的ide, 然后配合命令行工具进行开发, 执行的时候就像nodejs一样方便, 目前这个命令行工具叫espjs, 文档地址: https://www.kancloud.cn/shuai/espjs

espjs开源地址 github: https://github.com/zhaishuaigan/espjs
espjs国内下载: https://fetch.ngapp.net/soft/espjs/espjs-latest.zip

  这里简单说明一下使用方法:

  1. 将此压缩包里面的文件放到不包含空格和中文的目录中. 如 c:\espruino-tools
  2. 配置系统环境变量path, 添加 c:\espruino-tools
  3. 进入项目目录, 在目录的地址栏输入 cmd, 进入命令行.
  4. 输入espjs flash esp01s 烧写espruino固件
  5. 输入espjs upload 上传当前目录中的代码到设备

然后设备就开始运行代码了, 之后修改代码只需要执行upload 即可更新代码,
实例可参考 demo 目录下的文件
index.js 或 main.js 会被当做入口文件加载执行

注意事项:
1: 端口是自动选择的, 插上设备后会自动选择, 如果有多个设备, 可以使用port命令切换设备
2: 默认的波特率是115200, 如需修改请到config.json中修改
3: 如果要增加开发板支持, 请到config.json 的Flash字段追加
4: 模块不支持远程加载, 例如 require(“MQTT”) 会提示模块不存在, 解决方法是 手动下载mqtt模块(modules add MQTT), 然后使用 require(“modules/MQTT.min.js”) 进行引用.

nodejs开发的神器 now

now是什么?

now 允许您轻松、快速和可靠地将JavaScript(Node.js)或Docker支持的网站、应用程序和服务带到云中。实际上,包含package.json或Dockerfile的任何目录都可以通过一个命令:now传输到云。

每次部署一个项目,now 将提供一个新的、唯一的URL(甚至在上传完成之前)。这些URL将看起来像这样(我的应用程序-随机字符串):my-app-erkgfjtrna.now.sh 。

当您部署到生产时,您只需选择适当的别名(自定义域)即可。

官网地址: https:/zeit.co

使用方法

  1. 下载命令行工具: npm install -g now
  2. 创建开发目录 mkdir my-project && cd my-project
  3. 创建package.json
    1. {
    2. "name": "koa",
    3. "version": "1.0.0",
    4. "description": "",
    5. "main": "index.js",
    6. "scripts": {
    7. "start": "node index.js"
    8. },
    9. "author": "",
    10. "license": "ISC",
    11. "dependencies": {
    12. "koa": "^2.6.1"
    13. }
    14. }
  4. 创建index.js
    1. const Koa = require('koa');
    2. const app = new Koa();
    3. app.use(ctx => {
    4. ctx.body = 'Hello Koa';
    5. });
    6. app.listen(80);
  5. 登录 now login 然后输入邮箱地址收取验证邮件, 点击邮件里的验证链接, 这里需要翻墙, 因为验证页面有个js在google上.
  6. 执行 now --public 会输出类似下面的结果.
    1. > Deploying D:\xxxx\my-project under shuai
    2. > Synced 2 files (366B) [1s]
    3. > Using Node.js 8.11.3 (default)
    4. > https://my-project-lcjucjkwmi.now.sh [in clipboard] (sfo1) [3s]
    5. > Building
  7. 执行完成后, 就可以打开上面的地址看到运行结果

别名使用

now --public && now alias shuai
即可生成一个 shuai.now.sh 的地址, 方便记忆

使用自己的域名

now --public && now alias shuai.com
需要根据提示验证域名所有权就能使用自己的域名访问了, 而且自动生成https证书

前端框架Semantic-ui

官网: http://www.semantic-ui.cn/

更快地设计赏心悦目的网站

Semantic作为一款开发框架,帮助开发者使用对人类友好的HTML语言构建优雅的响应式布局。

简洁的 HTML

Semantic UI中词语和类(css clases)是可以相互替换的概念

直观的使用自然语言中的语法,词汇和语序等来定义一个类(css class)。

取BEM 和 SMACSS 的精华,同时使之更易于使用。

直观明了的 Javascript

Semantic 使用被叫做 behaviors 的简单短语来触发功能

开发者可以更改任何组件中的配置来设置该组件中的某一设置

化繁为简的调试

记录日志使您很方便的追踪到性能瓶颈,而不必去堆栈轨迹中发掘问题所在。

官网: http://www.semantic-ui.cn/

写了个jquery的自动填充form插件

最近发现每次做后台编辑数据的时候, 给表单设置默认值都很麻烦, 这次干脆写了一个jquery插件, 直接自动填充表单, 省去php一个一个的写, 这样代码可读性也好了很多.

jquery.autofill.js

  1. jQuery.fn.extend({
  2. autofill: function (data) {
  3. if (!data || !$.isPlainObject(data)) {
  4. return;
  5. }
  6. for (var name in data) {
  7. if ($.isArray(data[name])) {
  8. var field = $('[name="' + name + '[]"]', this);
  9. field.each(function () {
  10. if (data[name].indexOf($(this).val()) >= 0) {
  11. $(this).attr('checked', 'checked');
  12. }
  13. });
  14. } else {
  15. var field = $('[name="' + name + '"]', this);
  16. field.each(function () {
  17. switch ($(this).attr('type')) {
  18. case 'radio':
  19. if ($(this).val() === data[name].toString()) {
  20. $(this).attr('checked', 'checked');
  21. }
  22. break;
  23. default:
  24. $(this).val(data[name]);
  25. break;
  26. }
  27. });
  28. }
  29. }
  30. }
  31. });

使用方法 ./test.php

  1. <!DOCTYPE HTML>
  2. <html lang="en-US">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link href="css/bootstrap.css" rel="stylesheet" type="text/css"/>
  7. </head>
  8. <body>
  9. <div class="container">
  10. <form action="?" method="post" id="form">
  11. 姓名: <input type="text" name="name" id="" />
  12. <br />
  13. 年龄: <input type="number" name="age" id="" />
  14. <br />
  15. 性别:
  16. <input type="radio" name="sex" value="1" id="" />
  17. <input type="radio" name="sex" value="0" id="" />
  18. <br />
  19. 省份:
  20. <select name="area" id="">
  21. <option value="-1">选择省份</option>
  22. <option value="shanghai">上海</option>
  23. <option value="beijing">北京</option>
  24. <option value="henan">河南</option>
  25. </select>
  26. <br />
  27. 爱好:
  28. <input type="checkbox" name="hobby[]" value="book" id="" /> 看书
  29. <input type="checkbox" name="hobby[]" value="coding" id="" /> 写代码
  30. <input type="checkbox" name="hobby[]" value="games" id="" /> 打游戏<br />
  31. 简介:
  32. <textarea name="content"></textarea>
  33. <br />
  34. <input type="submit" value="提交" />
  35. </form>
  36. <!-- 这里是数据 -->
  37. <div class="hidden" id="data">
  38. <?php
  39. $data = [
  40. 'name' => 'shuai',
  41. 'age' => '25',
  42. 'area' => 'henan',
  43. 'sex' => 0,
  44. 'hobby' => ['book', 'games'],
  45. 'content' => 'hello world',
  46. ];
  47. echo json_encode($data);
  48. ?>
  49. </div>
  50. </div>
  51. <script src="jquery.min.js" type="text/javascript"></script>
  52. <script src="jquery.autofill.js" type="text/javascript"></script>
  53. <script type="text/javascript">
  54. $(function () {
  55. var data = $.parseJSON($('#data').text());
  56. $('#form').autofill(data);
  57. });
  58. </script>
  59. </body>
  60. </html>

访问

写了一个ThinkPHP的模板引擎, 仿angular的, 简单版

前段时间学习angularjs, 里面的模板思想和实现方法很酷, 就心血来潮, 想实现一个php版的, 今天试着写了一下, 发现貌似可以, 具体看源码.

./ThinkPHP/Library/Think/Template/Driver/Angular.class.php

  1. <?php
  2. namespace Think\Template\Driver;
  3. use Think\Storage;
  4. /**
  5. * Angular模板引擎驱动
  6. */
  7. class Angular {
  8. private $config = array();
  9. private $tpl_var = array();
  10. /**
  11. * 架构函数
  12. */
  13. public function __construct() {
  14. $this->config['cache_path'] = C('CACHE_PATH');
  15. $this->config['tpl_dir'] = THEME_PATH;
  16. $this->config['cache_path'] = C('CACHE_PATH');
  17. $this->config['template_suffix'] = C('TMPL_TEMPLATE_SUFFIX');
  18. $this->config['cache_suffix'] = C('TMPL_CACHFILE_SUFFIX');
  19. $this->config['tmpl_cache'] = C('TMPL_CACHE_ON');
  20. $this->config['cache_time'] = C('TMPL_CACHE_TIME');
  21. $this->config['attr'] = 'tp-';
  22. }
  23. /**
  24. * 编译模板
  25. * @param type $tpl_file 模板文件
  26. * @param type $tpl_var 模板变量
  27. */
  28. public function fetch($tpl_file, $tpl_var) {
  29. $this->tpl_var = $tpl_var;
  30. $tpl_file = $this->load_template($tpl_file);
  31. Storage::load($tpl_file, $tpl_var, null, 'tpl');
  32. }
  33. /**
  34. * 加载主模板并缓存
  35. * @param string $tpl_file 模板文件名
  36. * @return string 缓存的模板文件名
  37. */
  38. public function load_template($tpl_file) {
  39. if (is_file($tpl_file)) {
  40. // 读取模板文件内容
  41. $tpl_content = file_get_contents($tpl_file);
  42. } else {
  43. $tpl_content = $tpl_file;
  44. }
  45. // 根据模版文件名定位缓存文件
  46. $tpl_cache_file = $this->config['cache_path'] . md5($tpl_file) . $this->config['cache_suffix'];
  47. if (Storage::has($tpl_cache_file) && !APP_DEBUG && $this->config['tmpl_cache']) {
  48. return $tpl_cache_file;
  49. }
  50. // 编译模板内容
  51. $tpl_content = $this->compiler($tpl_content);
  52. Storage::put($tpl_cache_file, trim($tpl_content), 'tpl');
  53. return $tpl_cache_file;
  54. }
  55. /**
  56. * 编译模板内容
  57. * @param string $tpl_content 模板内容
  58. * @return string 编译后端php混编代码
  59. */
  60. protected function compiler($tpl_content) {
  61. //模板解析
  62. $tpl_content = $this->parse($tpl_content);
  63. // 添加安全代码
  64. $tpl_content = '<?php if (!defined(\'THINK_PATH\')) exit();?>' . $tpl_content;
  65. // 优化生成的php代码
  66. $tpl_content = str_replace('?><?php', '', $tpl_content);
  67. return strip_whitespace($tpl_content);
  68. }
  69. /**
  70. * 解析模板标签属性
  71. * @param string $content 要模板代码
  72. * @return string 解析后的模板代码
  73. */
  74. public function parse($content) {
  75. while (true) {
  76. $sub = $this->match($content);
  77. if ($sub) {
  78. $method = 'parse_' . $sub['attr'];
  79. if (method_exists($this, $method)) {
  80. $content = $this->$method($content, $sub);
  81. } else {
  82. E("模板属性" . $this->config['attr'] . $sub['attr'] . '没有对应的解析规则');
  83. break;
  84. }
  85. } else {
  86. break;
  87. }
  88. }
  89. $content = $this->parse_value($content);
  90. return $content;
  91. }
  92. /**
  93. * 解析include属性
  94. * @param string $content 源模板内容
  95. * @param array $match 一个正则匹配结果集, 包含 html, value, attr
  96. * @return string 解析后的模板内容
  97. */
  98. private function parse_include($content, $match) {
  99. $tpl_name = $match['value'];
  100. if (substr($tpl_name, 0, 1) == '$') {
  101. //支持加载变量文件名
  102. $tpl_name = $this->get(substr($tpl_name, 1));
  103. }
  104. $array = explode(',', $tpl_name);
  105. $parse_str = '';
  106. foreach ($array as $tpl) {
  107. if (empty($tpl))
  108. continue;
  109. if (false === strpos($tpl, $this->config['template_suffix'])) {
  110. // 解析规则为 模块@主题/控制器/操作
  111. $tpl = T($tpl);
  112. }
  113. // 获取模板文件内容
  114. $parse_str .= file_get_contents($tpl);
  115. }
  116. return str_replace($match['html'], $parse_str, $content);
  117. }
  118. /**
  119. * 解析if属性
  120. * @param string $content 源模板内容
  121. * @param array $match 一个正则匹配结果集, 包含 html, value, attr
  122. * @return string 解析后的模板内容
  123. */
  124. private function parse_if($content, $match) {
  125. $new = "<?php if ({$match['value']}) { ?>";
  126. $new .= str_replace($match['exp'], '', $match['html']);
  127. $new .= '<?php } ?>';
  128. return str_replace($match['html'], $new, $content);
  129. }
  130. /**
  131. * 解析repeat属性
  132. * @param string $content 源模板内容
  133. * @param array $match 一个正则匹配结果集, 包含 html, value, attr
  134. * @return string 解析后的模板内容
  135. */
  136. private function parse_repeat($content, $match) {
  137. $new = "<?php foreach ({$match['value']}) { ?>";
  138. $new .= str_replace($match['exp'], '', $match['html']);
  139. $new .= '<?php } ?>';
  140. return str_replace($match['html'], $new, $content);
  141. }
  142. /**
  143. * 解析show属性
  144. * @param string $content 源模板内容
  145. * @param array $match 一个正则匹配结果集, 包含 html, value, attr
  146. * @return string 解析后的模板内容
  147. */
  148. private function parse_show($content, $match) {
  149. $new = "<?php if ({$match['value']}) { ?>";
  150. $new .= str_replace($match['exp'], '', $match['html']);
  151. $new .= '<?php } ?>';
  152. return str_replace($match['html'], $new, $content);
  153. }
  154. /**
  155. * 解析hide属性
  156. * @param string $content 源模板内容
  157. * @param array $match 一个正则匹配结果集, 包含 html, value, attr
  158. * @return string 解析后的模板内容
  159. */
  160. private function parse_hide($content, $match) {
  161. $new = "<?php if (!({$match['value']})) { ?>";
  162. $new .= str_replace($match['exp'], '', $match['html']);
  163. $new .= '<?php } ?>';
  164. return str_replace($match['html'], $new, $content);
  165. }
  166. /**
  167. * 解析普通变量和函数{$title}{:function_name}
  168. * @param string $content 源模板内容
  169. * @return string 解析后的模板内容
  170. */
  171. private function parse_value($content) {
  172. $content = preg_replace('/\{(\$.*?)\}/', '<?php echo \1 ?>', $content);
  173. $content = preg_replace('/\{\:(.*?)\}/', '<?php echo \1 ?>', $content);
  174. return $content;
  175. }
  176. /**
  177. * 获取第一个表达式
  178. * @param string $content 要解析的模板内容
  179. * @return array 一个匹配的标签数组
  180. */
  181. private function match($content) {
  182. $reg = '#<(?<tag>[\w]+)[^>]*?\s(?<exp>' . preg_quote($this->config['attr']) . '(?<attr>[\w]+)=([\'"])(?<value>[^\4]*?)\4)[^>]*>#s';
  183. $match = null;
  184. if (!preg_match($reg, $content, $match)) {
  185. return null;
  186. }
  187. $sub = $match[0];
  188. $tag = $match['tag'];
  189. /* 如果是但标签, 就直接返回 */
  190. if (substr($sub, -2) == '/>') {
  191. $match['html'] = $match[0];
  192. return $match;
  193. }
  194. /* 查找完整标签 */
  195. $start_tag_len = strlen($tag) + 1; // <div
  196. $end_tag_len = strlen($tag) + 3; // </div>
  197. $start_tag_count = 0;
  198. $content_len = strlen($content);
  199. $pos = strpos($content, $sub);
  200. $start_pos = $pos + strlen($sub);
  201. while ($start_pos < $content_len) {
  202. $is_start_tag = substr($content, $start_pos, $start_tag_len) == '<' . $tag;
  203. $is_end_tag = substr($content, $start_pos, $end_tag_len) == "</$tag>";
  204. if ($is_start_tag) {
  205. $start_tag_count++;
  206. }
  207. if ($is_end_tag) {
  208. $start_tag_count--;
  209. }
  210. if ($start_tag_count < 0) {
  211. $match['html'] = substr($content, $pos, $start_pos - $pos + $end_tag_len);
  212. return $match;
  213. }
  214. $start_pos++;
  215. }
  216. return null;
  217. }
  218. }

./Application/Home/Controller/TestController.class.php

  1. <?php
  2. namespace Home\Controller;
  3. use Think\Controller;
  4. class TestController extends Controller {
  5. public function index() {
  6. C('SHOW_PAGE_TRACE', true);
  7. C('TMPL_ENGINE_TYPE', 'Angular');
  8. $data = array();
  9. $data['title'] = '标题';
  10. $data['nav'] = array(
  11. array('title' => '首页', 'url' => '/'),
  12. array('title' => '文章', 'url' => '/article'),
  13. array('title' => '图片', 'url' => '/pic'),
  14. array('title' => '新闻', 'url' => '/news'),
  15. );
  16. $data['count'] = 6;
  17. $data['list'] = array(
  18. array('id' => 1, 'title' => '这是标题1', 'create_time' => strtotime('-5 seconds')),
  19. array('id' => 2, 'title' => '这是标题2', 'create_time' => strtotime('-4 seconds')),
  20. array('id' => 3, 'title' => '这是标题3', 'create_time' => strtotime('-3 seconds')),
  21. array('id' => 4, 'title' => '这是标题4', 'create_time' => strtotime('-2 seconds')),
  22. array('id' => 5, 'title' => '这是标题5', 'create_time' => strtotime('-1 seconds')),
  23. array('id' => 6, 'title' => '这是标题6', 'create_time' => NOW_TIME),
  24. );
  25. $this->assign($data);
  26. $this->display('index');
  27. }
  28. }

./Application/Home/View/Test/index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Angular 模板测试 - {$title}</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <style>
  8. * {
  9. margin: 0px;
  10. padding: 0px;
  11. font-size: 12px;
  12. color: #333;
  13. line-height: 20px;
  14. }
  15. a {
  16. color: #33F;
  17. text-decoration: none;
  18. }
  19. a:hover {
  20. color: #f00;
  21. text-decoration: underline;
  22. }
  23. .center {
  24. text-align: center;
  25. }
  26. h1{
  27. font-size: 30px;
  28. line-height: 50px;
  29. }
  30. .nav {
  31. line-height: 30px;
  32. }
  33. .nav a{
  34. padding: 0px;
  35. margin: 0px 20px;
  36. }
  37. .main table{
  38. width: 500px;
  39. margin: 0px auto;
  40. }
  41. table {
  42. border: 1px solid #666;
  43. }
  44. table td,
  45. table th{
  46. border: 1px solid #666;
  47. line-height: 20px;
  48. padding: 0px 5px;
  49. }
  50. table th{
  51. background: #CCC;
  52. }
  53. #footer p{
  54. text-align: center;
  55. line-height: 30px;
  56. }
  57. </style>
  58. </head>
  59. <body>
  60. <div class="header">
  61. <h1 class="center">Angular 模板测试 - {$title}</h1>
  62. <div class="nav center" tp-if="$nav">
  63. <a tp-repeat="$nav as $vo" href="{$vo['url']}">{$vo['title']}</a>
  64. </div>
  65. </div>
  66. <div class="main">
  67. <table>
  68. <tr>
  69. <th>编号</th>
  70. <th>标题</th>
  71. <th>创建时间</th>
  72. <th>操作</th>
  73. </tr>
  74. <tr tp-if="$list" tp-repeat="$list as $vo">
  75. <td>{$vo['id']}</td>
  76. <td>{$vo['title']}</td>
  77. <td>{:date('Y-m-d H:i:s', $vo['create_time'])}</td>
  78. <td><a href="#del={$vo['id']}">删除</a></td>
  79. </tr>
  80. <tr tp-if="$count">
  81. <td colspan="4" class="center">共 {$count} 条数据</td>
  82. </tr>
  83. <tr tp-hide="$list">
  84. <td colspan="4" class="center">没有数据</td>
  85. </tr>
  86. </table>
  87. </div>
  88. <div tp-include="footer"></div>
  89. </body>
  90. </html>
  1. <footer id="footer">
  2. <div class="foot-warp">
  3. <p>
  4. © 2015 {:C('SITE_TITLE')} zhaishuaigan@qq.com    豫ICP备13012601号
  5. </p>
  6. </div>
  7. </footer>

运行/Test/index, 显示结果

目前只是实现了简单的解析, 还需要进一步完善, 比如配置啊, 扩展更多的标签啊什么的.

sublime text 3 安装后要做的事

1. 安装package control

快捷键: Ctrl + 反撇号, 然后在弹框中输入以下代码回车
如果安装错误可到这个网址查找解决方法: https://packagecontrol.io/installation

  1. import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

2. 注册

  1. —– BEGIN LICENSE —–
  2. Michael Barnes
  3. Single User License
  4. EA7E-821385
  5. 8A353C41 872A0D5C DF9B2950 AFF6F667
  6. C458EA6D 8EA3C286 98D1D650 131A97AB
  7. AA919AEC EF20E143 B361B1E7 4C8B7F04
  8. B085E65E 2F5F5360 8489D422 FB8FC1AA
  9. 93F6323C FD7F7544 3F39C318 D95E6480
  10. FCCC7561 8A4A1741 68FA4223 ADCEDE07
  11. 200C25BE DBBC4855 C4CFB774 C5EC138C
  12. 0FEC1CEF D9DCECEC D3A5DAD1 01316C36
  13. —— END LICENSE ——

3. Eclipce快捷键映射

菜单 -> preferences -> 按键绑定 - 用户

  1. [{
  2. "keys": ["shift+enter"],
  3. "command": "run_macro_file",
  4. "args": {
  5. "file": "Packages/Default/Add Line.sublime-macro"
  6. }
  7. }, {
  8. "keys": ["alt+up"],
  9. "command": "swap_line_up"
  10. }, {
  11. "keys": ["alt+down"],
  12. "command": "swap_line_down"
  13. }, {
  14. "keys": ["ctrl+alt+j"],
  15. "command": "join_lines"
  16. }, {
  17. "keys": ["ctrl+alt+down"],
  18. "command": "duplicate_line"
  19. }, {
  20. "keys": ["shift+ctrl+r"],
  21. "command": "show_overlay",
  22. "args": {
  23. "overlay": "goto",
  24. "show_files": true
  25. }
  26. }, {
  27. "keys": ["ctrl+shift+s"],
  28. "command": "save_all"
  29. }, {
  30. "keys": ["ctrl+l"],
  31. "command": "show_overlay",
  32. "args": {
  33. "overlay": "goto",
  34. "text": ":"
  35. }
  36. }, {
  37. "keys": ["shift+ctrl+f4"],
  38. "command": "close_all"
  39. }, {
  40. "keys": ["shift+ctrl+y"],
  41. "command": "lower_case"
  42. }, {
  43. "keys": ["shift+ctrl+x"],
  44. "command": "upper_case"
  45. }, {
  46. "keys": ["ctrl+d"],
  47. "command": "run_macro_file",
  48. "args": {
  49. "file": "Packages/Default/Delete Line.sublime-macro"
  50. }
  51. }]

4. 汉化

运行SublimeText3
点击 菜单 Preferneces -> Browse Packages
会打开 X:\Program Files\Sublime Text\Data\Packages 目录,点击向上并找到X:\Program Files\Sublime Text\Data\Installed Packages目录,从附件中下载汉化包并解压,复制Default.sublime-package到这个目录,无需重启即可直接看到汉化效果。
汉化包下载地址: http://img.xiumu.org/blog-uploads/2013/02/Sublime_Text_CN_3059.zip

5. 插件

  1. phpfmt
  1. {
  2. "enable_auto_align": true,
  3. "format_on_save": true,
  4. "indent_with_space": true,
  5. "option": "value",
  6. "php_bin": "C:/wamp/bin/php/php7.0.4/php.exe",
  7. "psr1": true,
  8. "psr2": true,
  9. "version": 4
  10. }

2、ConvertToUTF8
支持UTF-8编码的插件
3、Bracket Highlighter
用于匹配括号,引号和html标签。对于很长的代码很有用。安装好之后,不需要设置插件会自动生效
4、DocBlockr
DocBlockr可以自动生成PHPDoc风格的注释。它支持的语言有Javascript, PHP, ActionScript, CoffeeScript, Java, Objective C, C, C++
5、Emmet(Zen Coding)
快速生成HTML代码段的插件,强大到无与伦比,不知道的请自行google
6、SideBar Enhancements
这个插件改进了侧边栏,增加了许多功能
7、Themr
主题管理,切换主题的时候,不用自己修改配置文件了,用这个可以方便的切换主题
请参考  http://www.ladyloveit.com/sublime/developers-commonly-used-10-sublime-text-plugin

JavaScript格式化时间戳

1. JavaScript格式化时间戳函数

  1. function formatTime(time, format) {
  2. var data = new Date(time * 1000);
  3. format = format.replace('y', data.getFullYear());
  4. format = format.replace('m', data.getMonth() + 1);
  5. format = format.replace('d', data.getDate());
  6. format = format.replace('h', data.getHours());
  7. format = format.replace('i', data.getMinutes());
  8. format = format.replace('s', data.getSeconds());
  9. return format;
  10. }

2. 实例

  1. var time = '1421661231';
  2. alert(formatTime(time, 'y年m月d日 h:i:s'));
  3. "2015年1月19日 17:53:51"

Javascript导出Excel表格

JavaScript导出Excel类

  1. var ExcelHelper = {};
  2. ExcelHelper.getBrowserName = function() {
  3. var ua = window.navigator.userAgent;
  4. //ie
  5. if (ua.indexOf("MSIE") >= 0) {
  6. return 'ie';
  7. }
  8. //firefox
  9. else if (ua.indexOf("Firefox") >= 0) {
  10. return 'Firefox';
  11. }
  12. //Chrome
  13. else if (ua.indexOf("Chrome") >= 0) {
  14. return 'Chrome';
  15. }
  16. //Opera
  17. else if (ua.indexOf("Opera") >= 0) {
  18. return 'Opera';
  19. }
  20. //Safari
  21. else if (ua.indexOf("Safari") >= 0) {
  22. return 'Safari';
  23. }
  24. }
  25. ExcelHelper.tableToExcel = (function() {
  26. var uri = 'data:application/vnd.ms-excel;base64,',
  27. template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>',
  28. base64 = function(s) {
  29. return window.btoa(unescape(encodeURIComponent(s)))
  30. },
  31. format = function(s, c) {
  32. return s.replace(/{(\w+)}/g,
  33. function(m, p) {
  34. return c[p];
  35. })
  36. }
  37. return function(table, name) {
  38. var ctx = {
  39. "worksheet": name || 'Worksheet',
  40. table: table.innerHTML
  41. }
  42. window.location.href = uri + base64(format(template, ctx))
  43. }
  44. })();
  45. ExcelHelper.CreateExcelByTable = function(table) {
  46. var bn = this.getBrowserName();
  47. if (bn == "ie") {
  48. var ax = new ActiveXObject("Excel.Application");
  49. var wb = ax.Workbooks.Add();
  50. var sheet = wb.Worksheets(1);
  51. var tr = document.body.createTextRange();
  52. tr.moveToElementText(table);
  53. tr.select();
  54. tr.execCommand("Copy");
  55. sheet.Paste();
  56. ax.Visible = true;
  57. var si = null;
  58. var cleanup = function() {
  59. if (si) {
  60. window.clearInterval(si);
  61. }
  62. }
  63. try {
  64. var fname = ax.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
  65. } catch (e) {
  66. print("Nested catch caught " + e);
  67. } finally {
  68. wb.SaveAs(fname);
  69. var savechanges = false;
  70. wb.Close(savechanges);
  71. ax.Quit();
  72. ax = null;
  73. si = window.setInterval(cleanup, 1);
  74. }
  75. } else {
  76. this.tableToExcel(table);
  77. }
  78. }

测试代码

  1. var table = document.getElementById('table_id');
  2. ExcelHelper.CreateExcelByTable(table);