Javascript


基础

好用方法

  1. 二维数组横纵列转置的方法
1
2
3
4
5
var newArray = arr[0].map(function(col, i) {
return arr.map(function(row) {
return row[i];
})
});

插件、工具等

form

  1. 使用

form简单赋值

1
2
3
4
var edit = $('#editForm');
for (var p in data) {
edit.find(":input[name='" + p + "']").val(data[p]);
}

form清空

1
document.getElementById("editForm").reset();

EJS

  1. nodejs后台渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="main-content">
<!--left-fixed -navigation-->
<% include ./layout/sidebar.html %>
<!--left-fixed -navigation-->
<!-- header-starts -->
<% include ./layout/header.html %>
<!-- //header-ends -->
<% var page ="./page/"+pagename+".html"%>//定义一个变量,用来动态引入
<%- include(page)%>
<!-- footer-starts -->
<% include ./layout/footer.html %>
<!-- //footer-ends -->
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var ejs = require('ejs');
var express = require('express');
path = require('path')

var app = express();

app.engine('html', ejs.__express);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');


exports.login = async function(req, res) {
try{
var user = req.session.user;
if (!user) {
res.render('login', {});
} else {
res.redirect('/');
}
}catch (exp){
log.error('controller login error:' + exp);
res.render('login', {});
}
};

渲染后返回html字符串

1
2
3
4
var listStr = fs.readFileSync(__dirname+"/../views/page/"+fname+"/"+fname+"L.html","utf8")
var listHtml = ejs.render(listStr, {list: result.list});
var pageStr = fs.readFileSync(__dirname+"/../views/page/page.html","utf8")
var pageHtml = ejs.render(pageStr, {data: result.data});

html替换

1
$("#downPage").html(data.pageHtml);

bootstrap modal-dialog

  1. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  <script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>

<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
<div class="modal-dialog" role="document">
<div class="modal-content modal-info">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form id="editForm" action="mail" method="post">
<input id="id" name="id" hidden>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>类别</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="rewardType" name="rewardType" type="text">
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>日期</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="date" name="date" class="form_date" type="text" required readonly>
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>描述</h5>
</div>
<div class="col-md-9 grid-form1">
<textarea id="content" name="content"></textarea>
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-9 grid-form1">
<button type="submit" class="btn btn-sm btn-primary" id="editSubmit">保存</button>
<button type="reset" class="btn btn-sm btn-default" data-dismiss="modal">关闭</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>
</div>
</div>
</div>

// 打开
<a href="#" style="line-height: 0.5em;" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editModal" onclick="editShow(<%= i %>)">编辑</a>
// 关闭
$('#editModal').modal('hide');

bootstrapValidator

  1. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>
<link href="css/bootstrapValidator.css" rel="stylesheet">
<script src="js/bootstrapValidator.js"></script>

<input id="id" name="id" type="number" required>

//移除上次的校验配置
if($("#editForm").data('bootstrapValidator')) {
$("#editForm").data('bootstrapValidator').destroy();
$('#editForm').data('bootstrapValidator', null);
}

$('#editForm')
.bootstrapValidator()
.on('success.form.bv', function(e) {
e.preventDefault();
var $form = $(e.target);
//是否通过校验
if($form.data('bootstrapValidator').isValid()){
$.post($form.attr('action'), $form.serialize(), function(result) {
console.log(result);
$('#editModal').modal('hide');
listShow(); // 刷新列表
}, 'json');
}
});

datetimepicker

  1. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>
<link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" media="all">
<script src="js/bootstrap-datetimepicker.min.js"></script>

<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>开始时间</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="startTime" name="startTime" class="form_datetime" type="text" required readonly>
</div>
<div class="clearfix"></div>
</div>

$('.form_datetime').datetimepicker({
format: 'yyyy-mm-dd hh:ii', // 格式
minView: 0, // 最小时间界面 0 分钟;1 小时;2 日期
weekStart: 1,
todayBtn: 1,
autoclose: 1,
todayHighlight: 1,
startView: 2, // 起始时间界面 0 分钟;1 小时;2 日期
forceParse: 0,
showMeridian: 1
}).on('hide',function(e) {
// 当日期选择框关闭时,执行刷新校验;与bootstrapValidator一起使用时需要注意的点
$('#editForm').data('bootstrapValidator')
.updateStatus('startTime', 'NOT_VALIDATED',null)
.validateField('startTime')
.updateStatus('endTime', 'NOT_VALIDATED',null)
.validateField('endTime');
});

其他知识点

CoffeeScript

  1. 是一门编译到 JavaScript 的小巧语言

    CoffeeScript

    # 赋值:
    number   = 42
    opposite = true
    
    # 条件:
    number = -42 if opposite
    
    # 函数:
    square = (x) -> x * x
    
    # 数组:
    list = [1, 2, 3, 4, 5]
    
    # 对象:
    math =
      root:   Math.sqrt
      square: square
      cube:   (x) -> x * square x
    
    # Splats:
    race = (winner, runners...) ->
      print winner, runners
    
    # 存在性:
    alert "I knew it!" if elvis?
    
    # 数组 推导(comprehensions):
    cubes = (math.cube num for num in list)
    
编译后输出的 JavaScript

    var cubes, list, math, num, number, opposite, race, square,
      __slice = [].slice;

    number = 42;

    opposite = true;

    if (opposite) {
      number = -42;
    }

    square = function(x) {
      return x * x;
    };

    list = [1, 2, 3, 4, 5];

    math = {
      root: Math.sqrt,
      square: square,
      cube: function(x) {
        return x * square(x);
      }
    };

    race = function() {
      var runners, winner;
      winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
      return print(winner, runners);
    };

    if (typeof elvis !== "undefined" && elvis !== null) {
      alert("I knew it!");
    }

    cubes = (function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = list.length; _i < _len; _i++) {
        num = list[_i];
        _results.push(math.cube(num));
      }
      return _results;
    })();
  1. 安装

    cnpm install -g coffee-script
    
  2. 用法

    http://coffee-script.org/

    运行 coffee 命令以执行脚本, 编译 .coffee 文件到 .js 文件, 和提供一个交互式的 REPL

    coffee --compile --output lib/ src/
    

基础知识点

GZIP和BASE64的解压解密

  1. gzip解压

    使用pako https://github.com/nodeca/pako

    <script src="resources/js/pako.min.js" charset="utf-8"></script>
    
var pako = window.pako;
// 必须使用XMLHttpRequest才能请求到arraybuffer类型数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url + '?' + para, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
  if (this.status == 200) {
    var arrayBuffer = xhr.response; // Note: not xhr.responseText
    if (arrayBuffer) {
      var byteArray = new Uint8Array(arrayBuffer);
      var json = pako.inflate(byteArray, { to: 'string' });
      json = base64.decode(json);
      json = JSON.parse(json);
    }
  }
};

xhr.send();
  1. BASE64解密
function Base64() {

    // private property
    _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    // public method for encoding
    this.encode = function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        input = _utf8_encode(input);
        while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
                _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
                _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
        }
        return output;
    }

    // public method for decoding
    this.decode = function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length) {
            enc1 = _keyStr.indexOf(input.charAt(i++));
            enc2 = _keyStr.indexOf(input.charAt(i++));
            enc3 = _keyStr.indexOf(input.charAt(i++));
            enc4 = _keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = _utf8_decode(output);
        return output;
    }

    // private method for UTF-8 encoding
    _utf8_encode = function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }
        return utftext;
    }

    // private method for UTF-8 decoding
    _utf8_decode = function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        while ( i < utftext.length ) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}


var base64 = new Base64();


// 把param对象变成string带&符号的url参数
function urlEncode(param, key, encode) {
  if(param==null) return '';
  var paramStr = '';
  var t = typeof (param);
  if (t == 'string' || t == 'number' || t == 'boolean') {
      paramStr += '&' + key + '=' + ((encode==null||encode) ? encodeURIComponent(param) : param);
  } else {
      for (var i in param) {
          var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
          paramStr += urlEncode(param[i], k, encode);
      }
  }
  return paramStr;
}

Ajax实现跨域访问的三种方法

  1. 处理跨域的方法1 – 代理

    比如在北京(www.beijing.com/sever.php)和上海(www.shanghai.com/sever.php)各有一个服务器,北京的后端(www.beijing.com/sever.php)直接访问上海的服务,然后把获取的响应值返回给前端。也就是北京的服务在后台做了一个代理,前端只需要访问北京的服务器也就相当与访问了上海的服务器。这种代理属于后台的技术。

  2. 处理跨域的方法2 – JSONP

    假设在http://www.aaa.com/index.php这个页面中向http://www.bbb.com/getinfo.php提交GET请求,那么我们在www.aaa.com页面中添加如下代码:

    var eleScript= document.createElement("script"); //创建一个script元素
    eleScript.type = "text/javascript"; //声明类型、
    eleScript.src = "http://www.bbb.com/getinfo.php"; //添加src属性 引入跨域访问的url
    document.getElementsByTagName("HEAD")[0].appendChild(eleScript); //在页面中添加新创建的script元素
    

    当GET请求从http://www.bbb.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://www.aaa.com/index.php页面中的一个callback函数。看下面一个列子:

    在www.aaa.com页面中:

    <script>
      function jsonp( json ){
        document.write( json.name ); //输出周星驰
       }
    <script>
    <script src="http://www.bbb.com/getinfo.php"></script>
    

    在www.bbb.com页面中:

   jsonp({ “name”:”周星驰”,”age”:45 });

也就是在www.aaa.com页面中声明,在www.bbb.com页面中调用。但是JSONP只支持 “GET” 请求,但不支持 “POST” 请求。
  1. 处理跨域的方法3 – XHR2(推荐方法)

    “XHR2” 全称 “XMLHttpRequest Level2” 是HTML5提供的方法,对跨域访问提供了很好的支持,并且还有一些新的功能。

    IE10以下的版本都不支持

    只需要在服务器端头部加上下面两句代码:

    header( "Access-Control-Allow-Origin:*" );
    header( "Access-Control-Allow-Methods:POST,GET" );
    

    关于 “XHR2” 的更多信息大家可以查看官方文档

JavaScript混淆和反混淆工具

  1. 混淆工具:

    YUI Compressor
    Google Closure Compiler 
    UglifyJS 
    JScrambler
    
  2. 反混淆工具:

    jsbeautifier.org 
    JSDetox
    

thymeleaf里面的th和spring security结合进行页面权限配置

<li th:if="${#authorization.expression('!isAuthenticated()')}">
       <a href="#" data-toggle="modal"
       data-target="#changePasswordModal">修改密码</a>
</li>

a