在网页中实现“截屏”上传图片功能

2011年12月19日 satans17 没有评论
最近手上负责的一个web产品做了一个用户调研,用研那边反馈用户最期待的两个功能之一是“希望有与QQ聊天一样的截图功能”。

对于web来说,用户提到这个需求,我们起初的想法可能都是:除非开发嵌入式控件,不然根本无法实现。

不过随着webkit等内核的浏览器兴起,我们完全可以借助W3C的一些API,和一些变通的方式实现这个功能。

今天就讲讲如何在web页面中实现“截屏”并且上传。

这里“截屏”之所以要打引号,是因为确实无法实现“截屏”,但是我们可以通过变通方式实现,比如客户短聊天软件,QQ,旺旺等,这些软件截屏之后,数据都会在“剪切板”中保存一份副本,这里其实主要是讲如何获取”剪切板”中的图片上传,并且显示在网页上。

我们需要用到以下两个功能

This document describes APIs for clipboard operations such as copy, cut and paste in web applications.
This specification provides an API for representing file objects in web applications, as well as programmatically selecting them and accessing their data.
有了这些资料,其实实现起来也是so easy!!

将下面的代码保存成html页面,然后使用QQ或者旺旺随便截一个图,回到该页面,ctrl+v,你会发现神奇的事情发生了
//因为安全原因,浏览器为我们提供了onpaste事件,读取剪贴板数据仅能在该事件发生时在事件处理程序中进行。
document.body.onpaste = function(e) {
	//console.log(e)
	var items = e.clipboardData.items;
	for (var i = 0; i < items.length; ++i) {
		var item = e.clipboardData.items[i];
		if (items[i].kind == 'file' && items[i].type == 'image/png') {
			//FileReader可以参考API
			var fileReader = new FileReader();
			//readAsDataURL是一个异步过程,这里提供回调方法
			fileReader.onloadend = function () {
				var d = this.result.substr( this.result.indexOf(',')+1);
				var img = document.createElement("img");
				img.src= "data:image/jpeg;base64,"+d;
				document.body.appendChild(img);
			};
			//DataURL,不清楚了可以去看下资料
			fileReader.readAsDataURL(item.getAsFile());
			break; // Just get one
		}
	}
};

—————————-
如果要实现上传其实很简单了,将DataURL保存到form中,然后异步提交
后端服务器将DataURL转换成图片,然后将物理路径返回
这样,一个完整的在网页中“截屏”上传图片的功能就实现了 ^.^

分类: 大千世界 标签:

Node.js下实现LessCss多文件编译打包

2011年12月15日 satans17 没有评论

LessCss的思路很不错,可以让我们像编程一些写css
但是lesscss源码包中只有“编译”less文件的示例,没有多文件combo的示例
实际应用中这个功能还是很有必要的,类似Bootstrap中的“Makefile”功能

但是我的需求比他这个更复杂,需要支持多文件夹深度遍历
其实用nodejs解决这个问题还是so easy的~
直接上代码

var fs = require('fs'),
    util = require('util'),
	less = require('../lib/less');

combocss("./dpl/tabs","./dpl/test.css");

//两个参数,要打包的路径,希望生成的文件路径
function combocss(path,combofile){
	fs.writeFile(combofile, "<!--..-->", function (err) {});
	mkcss(path,combofile);
}

function mkcss(path,combofile){
	fs.readdirSync(path).forEach(function (file) {

		//如果是文件夹,继续遍历
		if(fs.lstatSync(path+"/"+file).isDirectory()){
			//arguments.caller(path+"/"+file);
			mkcss(path+"/"+file);
		}

		//处理文件
		else{
			//不是less文件忽略
			if (! /\.less/.test(file)) {
				return
			}

			//开始处理编译less文件
			var str = fs.readFileSync(path+"/"+file, 'utf-8');

			//less to css
			new(less.Parser)({
				paths: [require('path').dirname(path+"/"+file)],
				optimization: 0
			}).parse(str, function (err, tree) {
				if (err) {
					console.log("parse error");
				} else {
					try {
						var old = fs.readFileSync(combofile, 'utf-8');
						var css = tree.toCSS();
						fs.writeFileSync(combofile, old+css, 'utf-8');
					} catch (e) {
						console.log("toCss error!");
					}
				}
			});
		}

	});
}

学习Node.js时间也不长,基本上是边看文档边写代码
总结两点:
1.Node.js中貌似不能使用arguments.caller了
2.fs操作有同步和异步两种,但是最好不好混用

分类: 大千世界 标签:

Node.js学习系列笔记:Events 事件模块

2011年12月7日 satans17 没有评论

官方文档中是这么解释Events事件模块的

Node引擎中很多对象都会触发事件:例如net.Server会在每一次有客户端连接到它时触发事件,又如fs.readStream会在文件打开时触发事件。所有能够触发事件的对象都是events.EventEmitter的实例。你可以通过require(“events”);访问这个模块。

起初看到“所有能够触发事件的对象都是events.EventEmitter的实例。”这句很迷茫,也许是翻译不好吧,按照估计,估计也是用KISSY一样,通过继承events.EventEmitter类来实现事件机制的,写了个例子实验下,果不其然,看下面的列子

var util = require("util");
var event = new require("events").EventEmitter;

function Dog(name){
	//event.call(this);
	//console.log(Dog.super_);
	this.name=name;
}

util.inherits(Dog, event);

Dog.prototype.run = function(){
	this.emit("run","10M/S");
}

var mimi = new Dog("mimi");
mimi.on("run", function(speed){
	console.log(this.name + "is running!!" + speed);
})

mimi.run();

so easy!!

其实你也可以这么理解,当一个类继承了events.EventEmitter,相当于给这个类增加了addListener,removeListener等原型方法。

events.EventEmitter方法

下面简单介绍events.EventEmitter中的方法和属性

addListener(event, listener) or on(event, listener)

将一个监听器添加到指定事件的监听器数组的末尾。

mimi.on("run", function(speed){
	console.log(speed);
})

emitter.once(event, listener)

为事件添加一次性的监听器。该监听器在事件第一次触发时执行,过后将被移除。

mimi.once("die", function(){
	console.log("die");
})

removeListener(event, listener)

将监听器从指定事件的监听器数组中移除出去。

//想要移除就不能写匿名函数了
function evtRunFun(){
	console.log("remove test");
}
mimi.on("run", evtRunFun);
mimi.run(); // remove test
mimi.removeListener("run",evtRunFun);
mimi.run(); // 不输入remove test

removeAllListeners(event)

将指定事件的所有监听器从监听器数组中移除。

mimi.on("run", function(){
	console.log("run");
})
mimi.run();
mimi.removeAllListeners("run");
mimi.run();

setMaxListeners(n)

设置监听器的最大数量。个人觉得没什么用还误导人。

listeners(event)

返回指定事件的监听器数组对象,你可以对该数组进行操作,比如说删除监听器等。

mimi.listeners("run");
console.log(util.inspect(mimi.listeners('run')); // [ [Function] ]

emit(event, [arg1], [arg2], [...])

以提供的参数作为监听器函数的参数,顺序执行监听器列表中的每个监听器函数。

Dog.prototype.work = function(){
	this.emit("work","a","b","c");
}
mimi.on("work", function(arg1,arg2,arg3){
	console.log(arg1,arg2,arg3);
})
mimi.work();//a,b,c
分类: 大千世界 标签:

Ubuntu下安装NodeJS,npm,express

2011年12月7日 satans17 没有评论

第一步,安装依赖包

//安装编译器和运行环境
sudo apt-get install g++ curl libssl-dev apache2-utils

//安装git,如果直接下载源码,git也可以不装,下面会讲
sudo apt-get install git-core

第二步,获取node源码

1) 去官网直接下载:http://nodejs.org/#download node-v0.6.5.tar.gz

//解压
tar -zxf node-v0.6.5.tar.gz
//进入解压后的文件夹
cd node-v0.6.5

2) git clone git://github.com/joyent/node.git

#指定迁出版本,如果不迁出安装的就是最新版本
git checkout v0.6.5
#进入node文件夹
cd node

第三步,编译,安装

1) 不指定安装路径,三步搞定

./configure
make (要持续几分钟)
sudo make install

2) 指定安装路径,安装到/opt/node目录里,安装完后记得给opt/node加权限,不然运行不了

./configure --prefix=/opt/node
make
sudo make install

第四步,设置环境变量

//如果不设置环境变量,你将只能在bin目录下运行node
export PATH=$PATH:/opt/node/bin

第五步,测试node是否安装成功

//显示node版本号,表示安装成功
node -v

第六步,安装npm

//一句话搞定
curl http://npmjs.org/install.sh | sh
//如果失败
curl http://npmjs.org/install.sh | sudo sh

第六步,安装express

#记得一定要加-gd,不然他就会安装到当前文件夹下
npm install express -gd
#-g代表安装到NODE_PATH的lib里面,而-d代表把相依性套件也一起安装。如果沒有-g的话会安装目前所在的目录(会建立一个node_modules的文件夹),你可以透过以下指令来比较两者的不同:
npm list -g
npm list

第七步,测试express

//随便进入一个你的工作目录
//创建一个testapp的应用
express testapp
cd testapp
node app.js

都安装好了,至此你可以进入nodejs的奇幻世界了!!

分类: NodeJS 标签:

IE内存泄漏检测工具JavaScript Memory Leak Detector

2011年10月12日 satans17 没有评论

JavaScript Memory Leak Detector is a debugging tool to detect memory leaks and enforce best practices in JavaScript code when working with version of Internet Explorer older than IE8.

下载地址

下载后无需安装,可以直接使用。不过使用前要确保你安装了Script Debugger ,还需要在IE->工具->Internet选项->高级->浏览->去掉禁用脚本调试(其他)的勾选

具体用法自己看这里:http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

———————————–

附另外一款名气比较大的IE内存泄漏工具:sIEve,这个作者还写过另外一款类似的工具 Drip,不过没什么功能,基本上有sIEve就够了。

分类: 前端知识 标签:

我们为什么要使用NodeJS

2011年8月1日 satans17 没有评论

记得前几个月有个PD同学问我:NodeJS有什么意义或者是商业价值?

当时我对NodeJS也是一知半解,觉得它就是一个能在服务端运行javascript的环境,有Apache,IIS,有asp.net,jsp,php,ruby on rails,Nodejs不可能会有任何商业价值。

现在想想真是误人子弟

存在即合理,任何东西只要存在肯定会有他存在的价值,今天看到李牧写的“我们为什么要使用NodeJS”让我受益匪浅。

特意转一下:http://limu.iteye.com/blog/1013223

“Node.js 是服务器端的 JavaScript 运行环境,它具有无阻塞(non-blocking)事件驱动(event-driven)等的特色,Node.js 采用 V8 引擎,同样,Node.js 实现了类似 Apache 和 nginx 的web服务,让你可以通过它来搭建基于 JavaScript 的 Web App。”

分类: 前端知识 标签:

Grids(D2开场视频)

2011年7月17日 satans17 没有评论

本次视频收集了100多个UED同学的表情
文龙同学用canvas做了一个画图供大家涂鸦
涂鸦数据以50*30像素的形式保存,后端使用PHP将画图拼成一张大图
最后导入到视频中
很多人都参与进来了,虽然折腾,不过挺有意思

分类: 大千世界 标签:

有用的前端扩展

2011年7月12日 satans17 没有评论

Blackbird: Open Source JavaScript Logging Utility
Blackbird 是一款非常酷的 JavaScript 调试工具,带有一个漂亮的界面显示和过滤调试信息
http://www.gscottolson.com/blackbirdjs/

Highcharts – Interactive JavaScript charts
Highcharts 是一个纯 JavaScript 编写,用于生产交互式图表的 JavaScript 库。
http://www.highcharts.com/

jStat: a JavaScript statistical library
Stat是一个采用JavaScript开发的统计工具包,可以让你执行高级统计操作,而不需要专门的统计语言。
http://www.jstat.org/

highlight.js
Highlight.js 是一个用于高亮显示程序代码的 JavaScript 库,简单易用。
http://softwaremaniacs.org/soft/highlight/en/

SlickGrid!
SlickGrid 是一个用于构建简单的、快速、灵活的表格的库。
https://github.com/mleibman/SlickGrid/wiki/Examples

分类: 前端知识 标签:

JsDoc Toolkit 自动化文档工具

2011年6月30日 satans17 1 条评论

JsDoc Toolkit 是一个Google code上的一个开源项目,可以自动从Javascript代码中提取注释生成格式化文档。

项目地址

http://code.google.com/p/jsdoc-toolkit/

运行环境
JsDoc Toolkit是用Java开发的,运行时需要 Java 1.5+。

如何安装
1.安装JDK
2.设置环境变量
3.解压jsdoc_toolkit

如何使用
你可以在wiki里面看到一堆命令参数
比如在命令行中敲如下代码你可以执行jsdoc
java -jar jsrun.jar app\run.js -a -t=templates\jsdoc mycode.js

但是如果每次都要敲这些实在太麻烦
把下面的代码复制到记事本中,另外为jsdoc.bat文件,放到你的项目中,然后按照注释改成你的设置

@echo off
rem 关闭自动输出
echo  ____     ______  ____                     ____       ___    ____
echo /\  _`\  /\__  _\/\  _`\                  /\  _`\   /'___`\ /\  _`\
echo \ \,\L\_\\/_/\ \/\ \,\L\_\                \ \ \L\_\/\_\ /\ \\ \ \L\_\
echo  \/_\__ \   \ \ \ \/_\__ \       _______   \ \  _\/\/_/// /__\ \  _\L
echo    /\ \L\ \  \ \ \  /\ \L\ \    /\______\   \ \ \/    // /_\ \\ \ \L\ \
echo    \ `\____\  \ \_\ \ `\____\   \/______/    \ \_\   /\______/ \ \____/
echo     \/_____/   \/_/  \/_____/                 \/_/   \/_____/   \/___/
echo \ http://code.google.com/p/jsdoc-toolkit/

:: jsdoc安装的路径
set jdt=C:/tools/jsdoc-toolkit/
:: jsdoc模版路径
set tpm=%jdt%templates/jsdoc/
:: 文档输出路径
set doc=docs/
:: 要生成js模版的文件路径
set js=sample/

echo \ start ...
echo \ ...
echo \ ...
java -jar %jdt%jsrun.jar %jdt%app/run.js  -t=%tpm% -d=%doc%  %js%
echo \ succeed

pause

一切就这么简单 ^^

不熟悉jsdoc注释规范?可以把下面的代码存成window.js练练手先

/**
 * Window
 * @creator changyin
 */

/**
* @class 一个窗体类.
* @constructor
* @param {String} 页面名称
* @param {Object} 页面配置
* @return 一个窗体实例
*/
var Window = function(title,config){

   /**
    * 窗体名称
    * @type String
    */
	this.title = title;

	//初始化窗体
	this.init();

}

/**
* 页面初始化
* @private
*/
Window.prototype.init = function(){
	//dostr
}

/**
* 获取窗体的宽度
* @returns url地址
*/
Window.prototype.getWidth = function(){
	return this.widht;
}

/**
* 设置窗体的宽度
* @param {Number} 要设置的窗体的宽度
*/
Window.prototype.setWidth = function(width){
	this.width = width
}

我在组内分享JsDoc Toolkit的PPT

分类: 大千世界 标签:

jasmine:javascript单元测试框架

2011年6月2日 satans17 没有评论

jasmine是一个有名的javascript单元测试框架,它是独立的“行为驱动开发”框架,提供了对javascript开发者来说相对容易使用的测试语法,可以帮助你轻松写出自己的单元测试代码。

WIKI:https://github.com/pivotal/jasmine/wiki

API: http://pivotal.github.com/jasmine/jsdoc/index.html
(Jasmine的API文档是用jsdoc生成的,关于jsdoc)

可以在下载页面直接下载jasmine的源码:https://github.com/pivotal/jasmine

还可以使用git下载(关于git的用法,可以看这里http://progit.org/book/zh/ch1-4.html)

$ git clone https:\/\/github.com/pivotal/jasmine.git

下载jasmine的源码之后,可以看到目录有一个example的文件夹,这里就是我们要说的例子
还有一个文件夹lib,这里放了运行测试案例所必须的文件
其中jasmine.js就是整个框架的核心代码,
jasmine-html.js用来展示测试结果,jasmine.css用来美化测试结果。

打开example目录,可以看到里面有两个文件夹,一个文件:

spec/: 包含了就是这个测试案例所有的测试规则
src/: 存放了我们需要测试的js文件对象
SpecRunner.html: 运行测试用例的环境

spec文件夹下的几个文件,PlayerSpec.js就是针对src文件夹下的Player.js所写的测试用例。

//it用于描述一条简单的规则,其中第一个参数为实例的名称
//一般需要使用有实际判定式的有意义的语句来描述
//第二个参数为测试需要执行的代码
it('should increment a variable', function () {
  var foo = 0;// set up the world
  foo++;// call your application code
  expect(foo).toEqual(1); // passes because foo == 1
});

jasmine有一些自带的规则

//compares objects or primitives x and y and passes if they are equivalent
expect(x).toEqual(y);

//compares objects or primitives x and y and passes if they are the same object
expect(x).toBe(y); 

//compares x to string or regular expression pattern and passes if they match
expect(x).toMatch(pattern); 

// passes if x is not undefined
expect(x).toBeDefined();

//passes if x is null
expect(x).toBeNull(); 

//passes if x evaluates to true
expect(x).toBeTruthy();

//passes if x evaluates to false
expect(x).toBeFalsy(); 

//passes if array or string x contains y
expect(x).toContain(y); 

//passes if x is less than y
expect(x).toBeLessThan(y);

//passes if x is greater than y
expect(x).toBeGreaterThan(y); 

passes if function fn throws exception e when executed
expect(fn).toThrow(e);

如果以上规则不能满足你的需求,你还以为自定义规则

beforeEach(function() {
  this.addMatchers({
    //这里就是自己定义的规则
    toBePlaying: function(expectedSong) {
      //运行校验代码,最终返回boolean值
      var player = this.actual;
      return player.currentlyPlayingSong === expectedSong &&
             player.isPlaying;
    }
  });
});
分类: 前端知识 标签: