找出有限数列中和值最大的连续子数列

((list) => {
    let max = {
        total: 0,
        first: 0,
        last: 0,
    };
    let tmp = {
        total: 0,
        first: 0,
        last: 0,
    };
    let op = 0;//是否连续,0不连续,1递增连续,-1递减连续
    list.forEach((current, i) => {
        if (i === 0) {
            tmp.total = current;
            max.total = current;
            return;
        }
        const prev = list[i - 1];
        if (op === 0) {
            if (current > prev) {
                op = 1;
            } else if (current < prev) {
                op = -1;
            } else {
                op = 0;
            }
        }
        if (op !== 0 && current - prev === op) {
            tmp.total += current;
        } else {
            if (max.total < tmp.total) {
                max.total = tmp.total;
                max.first = tmp.first;
                max.last = tmp.last;
            }
            op = 0
            tmp.first = i;
            tmp.total = current;
        }
        tmp.last = i;
    });
    if (max.total < tmp.total) {
        max = tmp;
    }
    return [
        "和值:" + max.total,
        "值:" + list[max.first] + "~" + list[max.last],
        "索引:" + max.first + "~" + max.last
    ].join("\n");
})([1, 2, 3, 4, 3, 2, 5, 6, 7, 8]);

npm参数

npm init -y

-y 是初始化package.json的时候省略掉输入各种信息的步骤,都使用默认值

npm install module_name –save-dev

–save-dev 自动将依赖的模块加到devDependencies中

–save 自动将依赖的模块加到dependencies中

Chrome根据DOM属性加js断点

有的时候调页面样式时会莫名其妙出现错,比如某个东西不该显示的时候显示出来了。或者代码太多,不记得是哪个地方控制的这个地方。或者想看看别人页面的代码是怎么实现的。这时可以利用Chome的这个功能来调试。

1.选中要观察的DOM,右键”break on” -> “attribute modifications”来观察这个DOM的属性变化(一般情况下改变样式都是在改class和style属性)。

2.正常操作触发这个DOM的属性变化,当发生变化后会自动跳到断点初,这时看右边的call stack即可找到是哪个地方修改的属性。如果代码压缩了不方便看,可以点左下角的”{}”按钮来格式化代码。

 

AngularJS拦截$http请求

$httpProvider.interceptors.push(['$q',function ($q) {
    return {
        request: function (config) {
            if(config.url==='/admin.php') {
                return $q.reject('no auth!');
            }
            return config;
        },
        responseError: function(rejection) {
            if(rejection==='no auth!') {
                alert('无权限!!!');
                return {
                    data: {
                        errno: -1,
                        error:'无权限'
                    }
                }
            }
            return $q.reject(rejection);
        }
    }
}]);

ISO8601时间格式

new Date('2016-10-17 10:00:00');在Safari下会被认为是Invalid Date。

需要按照标准的IOS8601格式,如:new Date('2016-10-17T10:00:00');

或严谨点儿带上时区的new Date('2016-10-17T10:00:00+08:00');

Javascript导出Excel

  1. 引用ExcelBuilder
  2. 创建workbook
    var workbook = ExcelBuilder.createWorkbook();
  3. 创建worksheet
    var worksheet = workbook.createWorksheet({name: 'Sheet 1'});
    workbook.addWorksheet(worksheet);
  4. 加载数据
    var data = [['Name','Gender','Age']];
    data.push(['Zhang San','M', 24]);
    data.push(['Li Si','F', 18]);
    data.push(['Wang Wu','M', 22]);
    worksheet.setData(data);
  5. 下载
    var blob = ExcelBuilder.createFile(workbook, {type:'blob'});
    var url = URL.createObjectURL(blob);
    var a = document.createElement('A');
    a.href = url;
    a.download = Date.now()+'.xlsx';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    
    
  • 自动计算列宽
    //定义每个单字节的宽度
    var LETTER_WIDTH = 1.11;
    
    //定义每列最大宽度
    var MAX_COLUMN_WIDTH = 80;
    
    //定义每列的最小宽度
    var columns = [
    	{width: 10},
    	{width: 10},
    	{width: 10}
    ];
    
    //添加数据时遍历每一行,计算最大宽度
    var autoFitWidth = function(row) {
    	$.each(row, function(i,str){
    		if(str!==null&&str!==undefined&&str!=='') {
    			//英文占一个字节宽度,中文占两个
    			var match = str.toString().match(/[\\0-\\255]/ig);
    			var en = match==null?0:match.length;
    			var w = (str.length * 2 - en) * LETTER_WIDTH;
    			columns[i].width = Math.min(Math.max(columns[i].width, w), MAX_COLUMN_WIDTH);
    		}
    	});
    };
    
    //遍历完数据后将列的设置添加到worksheet中
    worksheet.setColumns(columns);
  • 过滤特殊字符
    //一些特殊字符会导致excel报错
    var specialChar = /[\u0000-\u0008\u000b\u000c\u000d-\u001f]/ig;
    val = val.replace(specialChar,'');
  • 自动换行,顶部对齐
    //创建一种样式
    var format1 = workbook.getStyleSheet().createFormat({
    	alignment:{
    		vertical:'top',
    		wrapText: true
    	}
    });
    //填充数据,给单元格增加样式
    var data = [
    	[
    		{value:'row1_col1\nline2\nline3','metadata':{'style':format1}},
    		{value:'row1_col2'},
    		'row_col3'
    	],
    	[
    		'row2_col1','row2_col2','row2_col3'
    	]
    ]
  • 全局默认样式
    workbook.getStyleSheet().masterCellFormats[0].alignment ={
    	vertical:'top',
    	wrapText: true
    };

     

 

Angular Js 事件传递、广播、Controller间数据交互

架设有这么三个Controller,Golbal在外面,另外两个在里面

  • GlobalController
    • UserListController
    • UserDetailController

UserListController触发一个事件change_user冒泡到GlobalController中

$scope.selectUser = function(user) {
    $scope.active_uid = user.uid;
    $scope.$emit('change_user',user.uid,user);//后面可以传若干个参数
};

 

GlobalController响应这个事件

$scope.$on('change_user', function(event,uid,user){
    //TODO something
});

 

GlobalController广播一个事件到自己和所有的子Controller中

$scope.$on('change_user', function(event,uid,user){
    $scope.$broadcast('parent_change_user',uid,user);//如果写成change_user就死循环了,因为这里广播的事件自己也能响应
});

 

UserDetailController接收广播

$scope.$on('parent_change_user', function(event,uid,user){
    //TODO something
});

 

JS/CSS判断是否是retina屏幕

JS:

if(window.devicePixelRatio > 1){
    //是retina屏幕
}

 

CSS:

@media screen and (-webkit-min-device-pixel-ratio: 1.5),
screen and (-moz-min-device-pixel-ratio: 1.5) ,
screen and (-ms-min-device-pixel-ratio: 1.5) ,
screen and (-o-min-device-pixel-ratio: 1.5) ,
screen and (min-device-pixel-ratio: 1.5) {
    .test {
        /*是retina屏*/
    }
}