IOS不支持浏览器自动播放音乐

说到这个东西,肯定是碰到了这个需求。

直接上文档:
苹果官方文档地址
文档里面有一段注意:

To prevent unsolicited downloads over cellular networks at the user’s expense, embedded media cannot be played automatically in Safari on iOS—the user always initiates playback. A controller is automatically supplied on iPhone or iPod touch once playback in initiated, but for iPad you must either set the controls attribute or provide a controller using JavaScript.

大意就是为了避免不可预期的网络流量,而造成手机用户额外的下载费用,嵌入式的媒体没有办法在ios中自动播放,你需要加个控制器或者按钮(竟然没有机翻我也看得懂了)。

但是需求为大,还是要尽量解决这个问题,难道要我用js写音乐么~
如果这个问题可以得到解决欢迎大家提示我=。=

移动端的select解决方案

lucky-select

https://github.com/gaofeiyu/lucky-select.git

移动端的select解决方案,可级联(现在只有二级联动)。 组件参考自新浪的微招聘,致敬!

基本指令说明

单级指令 singleSelectorPopup 二级联动指令 doubleSelectorPopup 上面两个指令主要是生成下拉部分

参数

//初始化的值
title 标题
initData 初始化的值
data 下拉数据
getRightListData 二级联动通过该属性的方法过滤生成二级菜单,单级联动不存在该属性

这里的data为数组,包含两个必要键值

{id:1,name:"id对应的展示名称"}

方法

  • show(val) val为初始化的对象
  • hide() 隐藏
  • onConfirm() 确认
  • onCancel() 取消

selector单级指令

该指令是在singleSelectorPopup基础上封装的选择的部分,供使用者参考。

        scope: {value: "=", options: "=", name: "@", readonly:"@", index:"="},
        template: "<span class='selector' ng-click='showPopup();'>{{str}}</span>",
        restrict: "EA",

参数说明

  • value 显示在前台的值
  • options 下拉的数据
  • name 下拉标题
  • readonly 是否只读(不弹出下拉,只展示值)
  • index 当前选择值的索引

效果

例图1 例图2

overlay遮罩指令

通用的遮罩指令,也可以用在其他组件上。

指令说明

replace: true,
template: '<div id="overlay"  ng-click="bindClick();"></div>',
restrict:"EA"

方法

  • show(hideCallback) hideCallback会在hide里面回调
  • hide()
  • clear()

[正版汉化] 生化奇兵1steam版汉化补丁(无盒子无BUG)

原文来自SteamCN

说明

此汉化补丁只用于steam版和破解的英文版(不适用于中文版)

因(因为中文版修改了exe文件,才导致了bug和盒子)

11月17号更新完美汉化补丁(使用方法)
11月19号更新360手柄补丁(使用方法)
优点
  • 人物死后不会变盒子
  • 血液不会被和҉谐
  • 没有bug跳出问题
  • 有的地方不会缺语音
  • 不用替换exe文件
  • 不用替换C盘ini文件
  • 可以使用360手柄
缺点
  • 每次进入游戏最少1~2分钟——最多3~4分钟(载入地图不会出现此情况)

 

感谢@SunZz测试
 
汉化补丁使用方法

 

第一步
验证游戏完整性(打过之前的汉化补丁)
 
删除C:\Documents and Settings\Administrator\Application Data\Bioshock里的Bioshock.ini

 

删除Bioshock\Content\BinkMovies里的2klogo和vidlogo(可以不删)

 

修改Bioshock\Content\Maps里所有的xxxx_int.bsm为xxxx_chn.bsm

 

第二步
覆盖汉化补丁即可享受无盒子中文版
360手柄补丁使用方法
第一步
删除C:\Documents and Settings\Administrator\Application Data\Bioshock里的Bioshock.ini
(这里如果进不去需要获取管理员控制权)
 
第二步
覆盖360手柄补丁(需要先完成汉化补丁的步骤)

进入游戏后

调整分辨率和字幕等
然后自定义——使用360手柄——是
(定义了手柄,没找到方法弄回去)
 
缺点(因为加入了主机的汉化补丁)
载入地图的界面有点花(字还是看得清的)
没有退出游戏选项

汉化补丁

点击进入/开始下载
360手柄补丁
点击进入/开始下载
如果链接失效可以反馈

总结一下写grunt脚本的思路

今天终于写个接近最终版的脚本,简单总结一下思路。
先确定我都要干什么,总结如下:

【cssmin】压缩css

【uglify】压缩js

【cssmin】合并css到style.css

【uglify】合并js库/框架文件到lib.js

【uglify】合并自定义js到script.js

【copy】复制需要处理的html到目标地点(单页面项目只涉及到一个文件)

【usemin】然后处理目标文件

【filerev】处理目标文件版本号问题(对合并后的制定文件,现在只写了js和css)

 

弄清思路后一步步操作,这个脚本总算是正常工作了。

 

和一些说明有所不同的是,我这里没有用concat、jshint、clean。

concat是被cssmin和uglify的功能替代掉了,不写也可以合并。

jshint没用主要是因为对自己代码不是特别有自信,用了以后感觉要花好多时间调试…

clean是真心用不上。

 

参考文章:

http://ericnishio.com/blog/compile-less-files-with-grunt
http://www.xuanfengge.com/npm-installation-did-not-succeed-and-github-will-not-open-solutions.html
https://www.npmjs.org/package/grunt-html-build
https://www.npmjs.org/package/grunt-contrib-concat
https://www.npmjs.org/package/grunt-contrib-less
https://www.npmjs.org/package/grunt-contrib-watch

 

grunt-usemin(中文文档)

grunt-usemin的作用

usemin用来生成优化后(合并,压缩)的脚本,然后以此替换html文件里面的javascript, css和其他脚本的引用

使用方式

npm install grunt-usemin --save-dev

任务

usemin通过两个内置的任务来完成上述的功能,分别是useminPrepare和usemin,同时还需要其它一些优化工具(cssmin,concat等)来完成优化工作。usemin通过动态的为这些优化工具插件生成子任务的方式来实现整个的目标。

usemin的两个内置的任务

  • useminPrepare 准备配置文件。配置文件是根据结构化的文件(如html)里面的块声明来生成的。最终把这些应用替换成优化后的文件引用。在这个过程中,为每个优化的步骤生成了很多的名为generated的子任务,这些优化的步骤每步都是一个grunt插件,下面将会列举出来。
  • usemin 把结构化文件(html)的块声明里面的文件引用替换。如果那些脚本文件有打过版本声明的,将会用版本声明的文件应用来替换。这个个过程会直接修改结构化文件(如html)的内容。

你必须手动的install和load构建过程中需要的依赖插件 基本例子:

grunt.registerTask('build', [
    'useminPrepare',
    'concat:generated',
    'cssmin:generated',
    'uglify:generated',
    'filerev',
    'usemin'
    ]);

useminPrepare任务

useminPrepare 在之前配置基础上,生成新的配置文件,在这个新的配置文件里定义了文件整个处理过程。默认情况下js文件会做concat,uglify处理,css文件会做concat,cssmin处理。

结构化文件(html)的块声明

<!-- build:<type>(alternate search path) <path> -->
    ... HTML Markup, list of script / link tags.
    <!-- endbuild -->
  • type 文件类型 可以是css,js,或者其他自定义类型(后面会讲到)。如果都不是构建脚本会忽略。这个引用块只会在开发环境出现,最后的build成功后不会出现。
  • alternate search path (可选的)默认情况下那些脚本文件的查找都是相对当前处理的文件的。
  • path 优化后文件的输出目录。
<!-- build:js js/app.js -->
    <script src="js/app.js"></script>
    <script src="js/controllers/thing-controller.js"></script>
    <script src="js/models/thing-model.js"></script>
    <script src="js/views/thing-view.js"></script>
    <!-- endbuild -->

处理流程

整个处理流程分很多步骤:每个步骤处理完后,useminPrepare就会修改配置文件,确保整个流程正确的执行。

默认的处理流程是合并后压缩。除此之后,在合并压缩之后可以定义一个后置的处理函数来做一个额外的工作,来修改配置文件。

下面看一个例子,使用了默认的处理流程。

下面是block声明
<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

处理后的生成的配置文件如下:

{
    concat:
    generated: {
    files: [
    {
    dest: '.tmp/concat/js/app.js',
    src: [
    'app/js/app.js',
    'app/js/controllers/thing-controller.js',
    'app/js/models/thing-model.js',
    'app/js/views/thing-view.js'
    ]
    }
    ]
    }
    },
    uglify: {
    generated: {
    files: [
    {
    dest: 'dist/js/app.js',
    src: [ '.tmp/concat/js/app.js' ]
    }
    ]
    }
    }
    }

指南

默认情况下usemin会把当前处理的文件作为‘根文件系统’,所有其他的相对路径,都是参照此路径。这个方式也同样适用绝对路径。如果需要改变‘根文件系统’,你需要在option中从定义root属性(下面会提到)

concat/cssmin/uglify这些任务的配置是useminPrepare生成的,没有必要专门为这些任务定义配置文件了。

options

dest string类型,默认为null 处理后的文件的基准输出路径。 staging string类型,默认.tmp 临时文件的输出路径(上面的例子提到过) root string|array类型,默认null 处理文件路径时的参考的’根文件系统’ flow object类型 默认{ steps: { js: [‘concat’, ‘uglifyjs’], css: [‘concat’, ‘cssmin’] }, post: {} } 通这个选项能在每个目标之前或者所有目标之前配置处理流程。你也能单独的配置steps属性或者post属性。

例如,为html目标改变js文件的处理流程:

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    html: {
    steps: {
    js: ['uglifyjs']
    },
    post: {}
    }
    }
    }
    }

为全部目标改变js文件的处理流程:

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    steps: {
    js: ['uglifyjs']
    },
    post: {}
    }
    }
    }

通过post属性,自定义处理配置文件

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    steps: {
    js: ['uglifyjs']
    },
    post: {
    js: [{
    name: 'uglifyjs',
    createConfig: function (context, block) {
    var generated = context.options.generated;
    generated.options = {
    foo: 'bar'
    };
    }
    }]
    }
    }
    }
    }

自定义处理步骤和后置处理器

自定义处理步骤和后置处理器有两个属性 + name string类型 在name指定相应的处理步骤上生效 + createConfig 函数 有两个参数 context block 返回配置对象

context conetxt对象包含了当前step/post-processor运行的一些信息,作为主力流程中的一步,必须要有处理输入的相关目录和文件的配置,同时也必须有输出相关的文件和目录。

context属性: + inDir 输入文件的目录 + inFiles 输入文件 + outDir 输出文件的目录 + outFiles 输出文件 + last 是否是处理步骤的最后一步 + options 此处理步骤的一些可选项

block 例子说明:

<!-- build:js scripts/site.js -->
    <script src="foo.js"></script>
    <script src="bar.js"></script>
    <script src="baz.js"></script>
    <!-- endbuild -->

被解析为block对象如下:

var block = {
    type: 'js',
    dest: 'scripts/site.js',
    src: [
    'foo.js',
    'bar.js',
    'baz.js'
    ],
    raw: [
    '    <!-- build:js scripts/site.js -->',
    '    <script src="foo.js"></script>',
    '    <script src="bar.js"></script>',
    '    <script src="baz.js"></script>',
    '    <!-- endbuild -->'
    ]
    };

usemin任务

usemin任务会做两件事 + 首先会把block替换为一行,这个引用指向之前流程生成的优化后的脚本文件。 + 之后如果找到打过版本的文件,就会用打过版本的文件引用替换当前的引用。

脚本文件的搜索

默认情况下,usemin会使用一个grunt-filerev插件map对象, 这个对象是grunt.filerev.summary,如果没找到就会到磁盘去检索,这样会需要更多的时间。

使用options.revmap会提供一个地图对象,供usemin任务查找

说明

当usemin尝试使用打过版本的文件替换当前引用(也就是之前提到的第2步操作时),就会收集脚本的所有搜索目录。最终生成一个目录的树,并尝试找到打过版本的文件。搜索目录默认是结构化文件(html)的目录,可以通过options重新指定。

例子1: dist/html/index.html有如下内容

<link rel="stylesheet" href="styles/main.css">
    <img src="../images/test.png">

默认情况下就会在dist/html/下搜索打过版本的文件。 + style/main.css将会在dist/html/styles搜索那么版本文件,例如:dist/html/style/main.1234.css就匹配,最终会替换。 + images/test.png将会在 dist/iamges搜索。

换成如下内容

<link rel="stylesheet" href="/styles/main.css">
    <img src="/images/test.png">

搜索的路径仍然不变是上面的dist/html/stylesdist/html/images,现在假如我们的脚本是在另一个目录dist/assets下,我们可以配置options,使得最终的搜索路径在dist/assets下面,例如可能就会有这样的结果:dist/assets/images/test.875487.pngdist/assets/styles/main.98090.css

options

assetsDirs array 类型 脚本搜索的目录 patterns object 类型 用户自定义替换。加入要把js文件里面的所有image.png替换为打过版本后的文件,就可以采用如下定义方式:

usemin: {
    js: '*.js',
    options: {
    assetsDirs: 'images',
    patterns: {
    js: [
    [/(image\.png)/, 'Replacing reference to image.png']
    ]
    }
    }
    }

patterns的key必须出现目标targets中,每个pattern有四个参数,最后两个是可选的,第一个参数表示那些引用是要替换的blockReplacements object 类型 默认值{ css: function (block) { … }, js: function (block) { … } } 由此可以控制替换的具体细节,返回值为最终替换的字符串。 例如:

usemin: {
    html: index.html,
    options: {
    blockReplacements: {
    less: function (block) {
    return '<link rel="stylesheet" href="' + block.dest + '">';
    }
    }
    }
    }
    //less必须和block的type相匹配.

revmap object 类型 声明版本的文件匹配,之后在版本文件的查找替换时是一个依据。 例如:

{
    "foo.png": "foo.1234.png"
    }

小结

useminPrepare任务必须声明输入,临时目录和输出路径。最终输出正确的配置文件,确保正确的文件处理流程。usemin任务,只是处理最终的输出文件。所有的脚本文件必须输出到最后的输出目录中。

useminPrepare 为整个构建过程,生成正确的配置文件,确保每步流程的处理顺序和期望的一致。在block声明的文件,有的是绝对路径,有的是相对路径,路径的文件引用是在搜索路径下(input)查找, 默认情况下就是正在文件本身所在的路径。

usemin 把images,scripts,css…的这些引用,替换为打过版本的文件引用。

例子

app
    |
    +- assets
    |  +- js
    |     +- index.js
    |     +- rank.js
    |  +- css
    |     +- layout.css
    +- index.html
    +- dist

index.html的内容

<!-- build:css(.) /assets/css/layout.min.css -->
    <link rel="stylesheet" href="/assets/css/layout.css"/>
    <!-- endbuild-->
    <!--build:js(.) /assets/js/app.min.js -->
    <script type="text/javascript" src="/assets/js/rank.js"></script>
    <script type="text/javascript" src="/assets/js/index.js"></script>
    <!-- endbuild -->

Gruntfile.js

/**
    * Created by Administrator on 2014/7/15.
    */
    module.exports = function(grunt){
    grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    clean: {
    build: ['.tmp/'],
    release: ['dist/']
    },
    jshint: {
    all: ['assets/**/*.js']
    },
    copy: {
    html: {
    files: [
    {src: ["index.html"], dest: "dist/"}
    ]
    }
    },
    useminPrepare: {
    html: ['dist/index.html']
    },
    filerev: {
    options: {
    length: 8
    },
    generated: {
    files:[
    {src: "dist/assets/**/*.min.js"},
    {src: "dist/assets/**/*.min.css"}
    ]
    }
    },
    usemin: {
    options: {
    assetsDirs: ['dist/']
    },
    html: 'dist/index.html'
    }
    });
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-usemin');
    grunt.loadNpmTasks('grunt-filerev');
    grunt.registerTask('build', [
    'clean',
    'jshint',
    'copy',
    'useminPrepare',
    'concat:generated',
    'cssmin:generated',
    'uglify:generated',
    'filerev',
    'usemin',
    'clean:build'
    ]);
    }

为angular强化Http请求

我先说问题,代码下面一起给出

添加patch

前两天了解到除了get、post、put还有一个叫patch的相对较新的提交方法,主要是用来做局部更新的意思。
但是angular没有这个方法。

改变请求的格式

angular在提交中文内容是会有乱码出现的情况,编码解码也不行,如果用过zepto的同学可能也遇到过这样的问题。结果导致无法提交服务端想要的信息。

增加请求拦截

对于请求的成功和失败进行拦截操作,比如对401做跳转登录页面的操作。

下面是代码
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
//增加拦截服务
$httpProvider.interceptors.push('userStateInterceptor');
//增加patch请求方法
$httpProvider.defaults.headers.patch = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function (obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for (name in obj) {
value = obj[name];
if (value instanceof Array) {
for (i = 0; i < value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if (value instanceof Object) {
for (subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if (value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
// Override $http service's default transformRequest
$httpProvider.defaults.transformRequest = [function (data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
}]).service("userStateInterceptor", ['$location','$q', function ($location,$q) {
//定义拦截操作
var interceptor = {
'request': function (config) {
return config;
},
'response': function (response) {
return response;
},
'requestError': function (rejection) {
return $q.reject(response);
},
'responseError': function (response) {
//这里做401的拦截
switch (response.status) {
case 401:
$location.path('login');
break;
}
return $q.reject(response);
}
}
return interceptor;
}]);

angularjs里面的事件

书上对事件的描述并不多,但实践中却是比较好用的东西。

先粘一下概念和API:

 

如同浏览器响应浏览器层的事件,比如鼠标点击、页面滚动那样,Angular应用也可以响应Angular事件。这使我们可以在应用中嵌套的各组件之间进行通信,即使这些组件在创建时并未考虑到其他组件。

 

注意:Angular事件系统并不与浏览器的事件系统相通,这意味着,我们只能在作用域上监听Angular事件而不是DOM事件。

 

  • $emit只能向parent controller传递event与data
  • $broadcast只能向child controller传递event与data
  • $on用于接收event与data

 

事件属性 目的
event.targetScope 发出或者传播原始事件的作用域
event.currentScope 目前正在处理的事件的作用域
event.name 事件名称
event.stopPropagation() 一个防止事件进一步传播(冒泡/捕获)的函数(这只适用于使用`$emit`发出的事件)
event.preventDefault() 这个方法实际上不会做什么事,但是会设置`defaultPrevented`为true。直到事件监听器的实现者采取行动之前它才会检查`defaultPrevented`的值。
event.defaultPrevented  

数据可视化初接触

之前都不怎么接触图表类的制作任务,也不是很关心,最近偶然机会有了接触,在这里记录一下。

可能大多数人接触比较多的是百度的ECharts,但是我没有从ECharts入手

最先接触的是d3.js.

展示数据的类型很多,但是不支持ie8,暂时放到了一边;

之后看了HighCharts

这个图表库支持ie8,效果也很好,功能上少d3很多,但是够用了,所以我在项目中暂时引用了HighCharts来构建图表。

回过来说百度的ECharts

ECharts本身是不支持ie8的,需要引入excanvas来达到支持,功能也很强大,符合国人需求,个人感觉跟HCharts的功能差不多,只是实现方式不同。

 

因为没有测试大数据,所以这部分先保留,不做评价。

然而三种图表主要都是两种技术(其实图标库基本都是这两种),SVG和Canvas,当然了,百度这边ie8的支持是通过转为div来实现的。

关于效率问题,引用一篇w3school上面的一篇文章

 

Canvas 和 SVG 都允许您在浏览器中创建图形,但是它们在根本上是不同的。

SVG

SVG 是一种使用 XML 描述 2D 图形的语言。

SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。

在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

Canvas

Canvas 通过 JavaScript 来绘制 2D 图形。

Canvas 是逐像素进行渲染的。

在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。

Canvas 与 SVG 的比较

下表列出了 canvas 与 SVG 之间的一些不同之处。

Canvas

  • 依赖分辨率
  • 不支持事件处理器
  • 弱的文本渲染能力
  • 能够以 .png 或 .jpg 格式保存结果图像
  • 最适合图像密集型的游戏,其中的许多对象会被频繁重绘

SVG

  • 不依赖分辨率
  • 支持事件处理器
  • 最适合带有大型渲染区域的应用程序(比如谷歌地图)
  • 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
  • 不适合游戏应用

 

因为最近接触了很多数据有关的东西,发现数据可视化还是很值得挖的东西,无论是对产品还是技术,也是考研程序效率的一个大块。

 

d3js有专门的书供学习,最近准备入一本。

 

 

VS下面的Emmet(ZenCoding)

新工作的开发环境倾向我并不是很熟悉的VS2012,代码习惯和快捷键也进入了新的环境。

经过了一番自定义以后,发现VS2012自带的类似ZenCoding的功能并不是很完整,于是…

可以去官网下载相应扩展,VS2012是最低的支持版本。

ZenCoding的新名字是Emmet(其实也不新了);

 

官方下载Emmet

 

直接在开发环境里面安装可以依据以下步骤

工具->扩展和更新->搜索Emmet 找到以后安装即可。

 

不过VS下面的快捷键不一样~

补全是Ctrl+1

还有我最爱的块选择是Ctrl+3和Ctrl+4

当然你也可以重新自定义,有兴趣的快去试试吧。