
2010年4月21日
因为我们的项目可以通过编写脚本(javascript)进行功能扩展,所以为了方便现场实施人员,所以突发奇想想在网页上(系统是B/S的)提供一个javascript的编辑器。
为什么不用textarea呢?
1 没有高亮
2 tab键无法使用。——按tab键会切换到下个控件
3 没有代码格式化。——因为习惯了Eclipse的环境,可以使用ctrl+shift+F来代码进行格式化。
当然,我还没强大到自己实现的程度,而且用脚趾头都能想到肯定有人实现了,就看找不找得着。
经过了艰难的搜索,终于在SourceForge上找到一个叫EditArea的项目,感觉挺好。http://sourceforge.net/projects/editarea/
它的sample也很清楚
在网页上用以下方法构造

代码
<script language="Javascript" type="text/javascript" src="../edit_area/edit_area_full.js"></script>
<script language="Javascript" type="text/javascript">
// initialisation
editAreaLoader.init({
id: "example_1" // id of the textarea to transform
,start_highlight: true // if start with highlight
,allow_resize: "both"
,allow_toggle: true
,word_wrap: true
,language: "zh" //国际化
,syntax: "js" //代码的样式,支持js ,php,sql,
//以下是格式化的支持
,begin_toolbar: "btn_beautifier,|" //插入工具栏
,plugins: "beautifier" //使用控件
});
</script>
便可以在页面中出现代码的编辑框

能够解决第一个和第二个问题,但是还能解决。
因此我又找啊找,找到这个网站:http://jsbeautifier.org/。这个网站做了一个js的格式化工具,甚至可以格式化经过某个混淆器混淆的js代码。
于是我根据上面项目中的插件规范,将这两个东东整合了起来。看上面图中的
按钮,按下以后,就变成了
看,高亮和格式化都有了。
需要下载的可以从这里下载(已经包含代码格式化的插件了):/Files/anic/editarea_0_8_2.zip
样例见\exemples\example.html
格式化的插件实现在\edit_area\plugins\beautifier\beautifier.js
posted @ 2010-04-21 21:07 Anic 阅读(243) 评论(1)
编辑

2010年4月10日
2010 的笔试,没有去年的43页,也就21页,除去了不同语言(java、c/c++、C#)的题,真正要做的也就16页左右,时间是够的。
基本上当了炮灰,所以在这里列出来,和大家分享一下。其实有很多都不是很难得问题,但是多了起来就很难发挥好。
session 1(必做)
有点变态,因为无论你什么语言,都必须答——我常用java,很久没有其他的,都忘了那些语言的特性了。
1 一只蜗牛,在一根10feet的杆上,每天向上3feet,晚上休息,下降1feet,问第几天什么时候到杆顶?(应该是考虑最后一天的情况)
2 考了java,对于类的static synchronized ,问:能不能编译通过,能不能锁住对象?
3 考了c#,问一下代码输出的是什么?主要有个printer2,搞了个new virtual在搞搞阵。
1 IPrint{
2 void print();
3 }
4
5 class Printer1:IPrint {
6 public void print(){ Console.WriteLine("Printer1.")} }
7
8 class Printer2:Printer1
9 {
10 public new virtual void print() { Console.WriteLine("Printer2.")} }
11 }
12
13 class Printer3:Printer2
14 {
15 public override void print() { Console.WriteLine("Printer3.")} }
16 }
17
18 class Printer4:Printer3
19 {
20 public override void print() { Console.WriteLine("Printer4.")} }
21 }
22
23 IPrinter ip = new Printer4();
24 ip.print();
4 考了java的一个分析wait/sleep/notifyAll 的题目,问有无死锁。
5 考了一个C++版的继承与派生的问题
1 class Base
2 {
3 int val;
4 public Base():val(5);
5 public virtual void print(){printf("%d",val);}
6 }
7
8 class Child
9 {
10 int _j;
11 public Child():_j(8);
12 public void print(){printf("%d",_j);}
13 }
14
15
问以下情况什么时候会输出88888

代码A
Child[5] c;
Base* p = (Base*)c;
for(int i=0;i<5;++i)
{
p->print();
++p;
}
B...
C
Base[5] c;
Child* p = (Child*)c;
for(int i=0;i<5;++i)
{
p->print();
++p;
}
D
Base[5] c;
Child* p = //用dynamicCast
for(int i=0;i<5;++i)
{
p->print();
++p;
}
6 考了C++一个编译的问题,问哪里有bug

代码class A<T1,T2>
{
T1* t1;
T2* t2;
public A():t1(new T1()),t2(new T2()){} //choice A
public A(const A& a){ //choice B
t1 = a.t1;
t2 = a.t2;
}
operator =(const A& a) //choice C
{
t1 = a.t1;
t2 = a.t2;
}
~A() throw() //choice D
{
delete t1;
delete t2;
}
}
据说是C,因为有内存泄露。原来的指针指向的空间没有释放掉。
7 以下的java会怎么样?

代码public class Foo {
int value;
public void Foo() {
value = 100;
}
public Foo(int i) {
value = i;
}
public void print() {
System.out.println(value);
}
public static void main(String[] args)
{
Foo f1 = new Foo();
Foo f2 = new Foo(200);
f1.print();
f2.print();
}
}
a 输出100和200
b 编译不过,因为value没有初值
c 编译不过,因为没有默认构造函数(应该选这个,因为有个void Foo())
...
section2(必做,只不过是大题,上面的是选择题)
1 问实现一个priority queue需要用多少个queue实现? (不知道说什么)
2 两个已排序的O(n)的序列A、B,求两个序列merge后的中位数?如果能在O(logn)内满分,在O(n)内有一些分。
3 有两个文件夹,里面有很多文件,写一个算法,找到在一个文件夹里而不在另一个文件夹中的文件。
4 有一份文件,里面有2^32-1个数,取值范围是[0,2^32-1],系统内存只有几百k,请问如何找出[0,2^32-1]中不在文件中出现的数。
5 有一个密码锁,密码锁是转盘状,有40个数字(包括0)。按一次密码需要顺时针,先转到0,转密码的第一个数字,转到0,转密码第二个数字,如此类推。密码长度是3位。问最坏情况下转了多少个数字包括0。(排列组合的题目,描述也不很清楚)
6 写一个“非递归”的算法,找出pattern在长串中出现的位置,如输入长串是abcbc而pattern是abc时,要输出(0,1,2)、(0,3,4)、(0,1,4)
session2.1
根据自己的编程语言答题,java题目如下:
1 改写main,使得不抛出运行时异常
1 import java.lang.reflect.Constructor;
2
3 public class ConTest {
4
5 public ConTest(String... ops) {
6 System.out.println("Success");
7 }
8
9 public static void main(String[] args) {
10 Class<?> clazz;
11 try {
12 clazz = Class.forName("ConTest");
13 Constructor m = clazz.getConstructors()[0];
14 String a = "";
15 m.newInstance(a);
16
17 } catch (Exception e) {
18 // TODO Auto-generated catch block
19 e.printStackTrace();
20 }
21
22 }
23 }
24
事后试出答案是m.newInstance(new Object[] { new String[] { a } });
因为ConTest(String.. ops)等同于ConTest(String[] ops)
而newInstance(Object..objs)等同于newInstanec(Object[] objs) 然后就不知道怎么回事了
考试没得查真恼火,看看javadoc一分钟就能解决。
2 写一个类,里面用“数组”实现List接口,List接口只要求实现三个函数。(这个比较简单,主要要注意add的时候,数组需要增长的情况)
1 public interface List
2 {
3 public boolean add(Object o);
4 public int indexOf(Object o); //给出了javadoc,如果不存在返回-1
5 public boolean remove(Object o); //如果不存在,不变,返回false
6 }
posted @ 2010-04-10 21:09 Anic 阅读(543) 评论(0)
编辑

2010年3月24日
想给项目做一个Nightly build,项目特点如下:
1 使用 Eclipse开发的java和GWT混合项目
2 目前有40多个工程
3 项目处于初期,很多部分尚未稳定,因此是工程是工程间依赖工程,没有引用编译好的jar包
4 工程主要分为前台clt,公共模块common,和服务器模块svr。例如有一个A.common,一定有A.clt和A.svr依赖于A.common,但clt和svr间不相互依赖。
(这是我们项目的编译过程的特殊逻辑)
以下是选定的技术路线
- 因为编译带有特殊的逻辑,所以使用方便编程的java,而非纯ant脚本。
- 不想自己整理工程的编译顺序,太多,麻烦。所以使用了dom4j读取eclipse工程配置信息。
- 不用ant脚本,可以使用Java程序调用Ant API。
- 由于javac对模板的不友好 ,所以使用jdt
例如以下的代码
package demo.server;
import com.extjs.gxt.ui.client.data.BaseModel;
public class TestA extends BaseModel {
@Override
public <X> X get(String property) {
return super.get(property);
}
}
使用javac编译,就会出现
无法确定 <X>X 的类型参数;对于上限为 X,java.lang.Object 的类型变量 X,不存在唯一最大实例
虽然搜索了以下,说只要返回值强制转换一下就ok,即return (X)super.get(property);
但这样的代码也比较多,明明在eclipse编译通过的,在javac就不行。所以g了一下,才知道eclipse有自己的编译器(?不太确认javac和jdt的关系),叫jdt。
首先要从Eclipse中,抽取出一个JDT的包。在Eclipse/plugin目录下,找到一个org.eclipse.jdt.core_3.5.1.v_972_R35x.jar,(版本社么的没有关系)。用winrar解压出里面的一个jdtCompilerAdapter.jar包,然后从工程中引用它。
顺便把
org.eclipse.jdt.compiler.tool_1.0.100.v_972_R35x.jar
org.eclipse.jdt.core_3.5.2.v_981_R35x.jar
org.eclipse.jdt.debug.ui_3.4.1.v20090811_r351.jar
这几个包也从eclipse/plugin中引用到项目里。——为什么要单独解压jdtCompilerAdapter.jar,我不太清楚啊。
然后,由于要调用ant,所以从apache上的ant项目中下载http://ant.apache.org/bindownload.cgi,用到两个包,
ant.jar
ant-launcher.jar
使用以下代码,调用ant
package thss.platform.util.mrobuild;
import java.io.File;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.Javac.ImplementationSpecificArgument;
import org.apache.tools.ant.types.Path;
public class JavaBuilder {
public JavaBuilder() {
}
public void execute(Path classPath, File output) {
Project currentProject = new Project();
// 填写工程的绝对目录,这样后面可以使用相对目录
currentProject.setBaseDir(new File("这里是工程的绝对目录"));
Javac compileJava = new Javac();
compileJava.setProject(currentProject);
// 调用jdt编译器
compileJava.setCompiler("org.eclipse.jdt.core.JDTCompilerAdapter");
compileJava.setClasspath(classPath);
compileJava.setEncoding("UTF-8");
// 填写相对目录src
compileJava.setSrcdir(new Path(currentProject, "src"));
// 编译后的结果.class输出到哪里
compileJava.setDestdir(output);
compileJava.setTarget("1.6");
compileJava.setSource("1.6");
compileJava.setNowarn(true);
compileJava.setDebug(true);
compileJava.setDebugLevel("lines,source");
// javac需要这段,换成了jdt不知道要不要了
ImplementationSpecificArgument arg = compileJava.createCompilerArg();
arg.setLine(" -Xlint");
compileJava.execute();
}
}
可能上述文章有很多概念性的问题,例如我没有搞清的javac和jdt关系,但是问题确实是解决了,欢迎高手批评指正。by Anic
posted @ 2010-03-24 22:16 Anic 阅读(1378) 评论(0)
编辑

2010年3月6日
今天看到有个Google Code的项目,叫ZeroClipboard:http://code.google.com/p/zeroclipboard/
大意是使用flash作为媒介,将内容复制到剪贴板。这比用纯javascript好,因为不同浏览器会出于安全的原因,有不同反应,例如IE会给出提示,有的浏览器不支持复制到剪贴板。
但是用flash就可以复制。例子就是VeryCd,看“复制选中的连接”按钮是一个flash。看来flash的安全沙箱没有限制将内容复制到剪贴板
但是也是有限制的:
1 根据ZeroClipborad的人们说,这些flash必须通过网络加载。
Zero Clipboard Does Not Work From Local Disk
This is a security restriction by Adobe Flash Player. Unfortunately, since we are utilizing the JavaScript-to-Flash interface ("ExternalInterface") this only works while truly online (if the page URL starts with "http://" or "https://"). It won't work running from a local file on disk.
However, there is a way for you to edit your local Flash Player security settings and allow this. Go to this website:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04a.html
And add the path to your local "ZeroClipboard.swf" file to the trusted files list, or try the "allow all" option.
2 flash虽然提供复制功能,但是前提是要通过用户的一次点击。意思就是不能在javascript中通过函数的方式setText就复制到剪贴板,而是调用了这个setText函数后,用户的鼠标在flash上有了一次点击,才可以。
This library is fully compatible with Flash Player 10, which requires that the clipboard copy operation be initiated by a user click event inside the Flash movie.
这里和使用flash上传文件的swfupload有同样的问题。
使用ZeroClipboard,可以将网页内容复制到剪贴板。但是ZeroClipboard没有GWT封装,我们项目是用GWT的,所以就学着swfupload的GWT封装,把ZeroClipboard也封装成GWT可以调用的形式。
1 先封装了一个zeroclipboard.jar
2 项目中使用的是GXT控件库,为了和控件紧密结合,写了一个ZClipboardBinder类,将两者结合起来
3 使用方法见下(Zeroclipboard_test.java)
1 package zero.clipboard.test.client;
2
3 import java.util.Date;
4
5 import zero.clipboard.test.client.ZClipboardBinder.ClipboardListener;
6
7 import com.extjs.gxt.ui.client.widget.LayoutContainer;
8 import com.extjs.gxt.ui.client.widget.button.Button;
9 import com.google.gwt.core.client.EntryPoint;
10 import com.google.gwt.user.client.ui.RootPanel;
11
12 /**
13 * Entry point classes define <code>onModuleLoad()</code>.
14 */
15 public class Zeroclipboard_test implements EntryPoint {
16
17 public void onModuleLoad() {
18 LayoutContainer c = new LayoutContainer();
19 c.setSize(400, 300);
20
21 Button btn = new Button("Copy Hello World");
22 // 将控件和ZeroClipboard绑定
23 // ZClipboardBinder.bind(btn, "Hello World");
24 ZClipboardBinder.bind(btn, new ClipboardListener() {
25
26 @Override
27 public String prepareCopy() {
28 return (new Date()).toString();
29 }
30 });
31 c.add(btn);
32
33 RootPanel.get().add(c);
34 }
35 }
36
相关下载都在附件中了。
/Files/anic/attachment.zip
示意结果
点击按钮后——其实是点击了上面的flash,使用ctrl+v,就能看到结果。
现在发现有很多有意义的功能都不能用javascript实现,例如多文件上传和复制到剪贴板,都是通过flash做中介,“曲线”实现的 ,不知道最后HTML5有没有解决这些问题,不用我们兜兜转转。
posted @ 2010-03-06 14:31 Anic 阅读(313) 评论(0)
编辑

2010年2月2日
使用GWT已经半年了,查了很多资料,但发现国内关注它的人很少,而且骂声也不少(当然GWT也有让我恶心的地方),所以就把平时实验的结果和感想,在这里和大家分享一下。
GWT困扰我的一个最恶心的缺点,就是凡事要编译。系统一大,模块之间依赖很强,修改一个客户端(界面)的小功能,就要重编译整个项目,费时费劲,我们项目现在重编一次已经需要800多秒了——好在有Development mode(感叹这个东东的强大)。
之前看到过GWT提供JSNI的功能,能够使gwt 的java code与纯JavaScript互通信,因此打算尝试使用JSNI作为中介,看看能不能减轻模块间的依赖——或者实现多模块之间实现分模块编译。
想法是这样的,大部分模块基本是不变的,希望不要经常编译,假设其为Dll1;有些为客户开发的模块Dll2,它依赖于Dll1,而且经常发生变化(需求总是变化的)。希望修改了Dll2后,不重新编译Dll1。
Dll1和Dll2只是一个命名,并不是真正的dll啊!
如果按照GWT的依赖实现,Dll2中的gwt.xml中,声明inherit name="demo1.Dll1"后,重编Dll2其实就包含重编Dll1
使用JSNI,见http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html
将Dll1的接口,使用$entry方法,发布成为标准的javascript;Dll2不直接依赖Dll1,使用JSNI,调用Dll1发布成为javascript的接口。
Dll1中,用GWT的java实现了3个方法

代码package demo1.client;
import java.util.Date;
import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.js.JsonConverter;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.dom.client.Element;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
public class DllImpl {
public static void method1(String value) {
Window.alert(value);
}
public static String methodJson() {
BaseModel result = new BaseModel();
result.set("int", 1);
result.set("double", new Double(1.2));
result.set("string", "str");
result.set("date", new Date());
result.set("boolean", true);
JSONObject obj = JsonConverter.encode(result.getProperties());
String str = obj.toString();
return str;
}
public static Element methodJS() {
TabPanel p = new TabPanel();
TabItem item = new TabItem();
item.setClosable(true);
item.setText("dll 1");
item.setLayout(new FitLayout());
p.add(item);
RootPanel.get("cross").add(p);
return item.getElement();
}
public static native void exportStaticMethod() /*-{
$wnd.method1 =
$entry(@demo1.client.DllImpl::method1(Ljava/lang/String;));
$wnd.methodJson =
$entry(@demo1.client.DllImpl::methodJson());
$wnd.methodJS =
$entry(@demo1.client.DllImpl::methodJS());
}-*/;
}
exportStaticMothod是将类中的3个方法,发布为javascript,其路径就是$wnd.method1、$wnd.methodJson和$wnd.methodJS,参数列表参考google文档中的JSNI。
在Dll1的EntryPoint中,调用这个exportStaticMethod方法。

Dll1的Entry代码package demo1.client;
import com.google.gwt.core.client.EntryPoint;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class Dll1 implements EntryPoint {
public void onModuleLoad() {
DllImpl.exportStaticMethod();
}
}
在Dll2中,就使用JSNI调用javascript,路径就是之前的$wnd.method1、$wnd.methodJson和$wnd.methodJS

代码package demo2.client;
import java.util.Date;
import java.util.Map;
import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.js.JsonConverter;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Timer;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class Dll2 implements EntryPoint {
public void onModuleLoad() {
Timer t = new Timer() {
@Override
public void run() {
// 由于Dll1和Dll2没有声明依赖,所以使用Timer强制延时
callMethod1("Hello world form dll2.");
String json = callMethodJSON();
Map<String, Object> map = JsonConverter.decode(json);
BaseModel m = new BaseModel(map);
System.out.println(m.get("int") instanceof Integer);
System.out.println(m.get("double") instanceof Double);
System.out.println(m.get("string") instanceof String);
System.out.println(m.get("date") instanceof Date);
System.out.println(m.get("boolean") instanceof Boolean);
Element x = callMethodJS();
FormPanel f2 = new FormPanel();
f2.setHeading("dll 2");
f2.render((com.google.gwt.user.client.Element) x);
}
};
t.schedule(2000);
}
protected native void callMethod1(String value)/*-{
$wnd.method1(value);
}-*/;
protected native String callMethodJSON()/*-{
return $wnd.methodJson();
}-*/;
protected native Element callMethodJS()/*-{
var x = $wnd.methodJS();
//alert(x);
return x;
}-*/;
}
之所以要用timer,是因为Dll2没有直接依赖Dll1,所以HTML声明加载Dll1和Dll2时,不能确定Dll2就是在Dll1加载后才被加载。如果Dll2在Dll1前加载,则调用的$wnd.method1()就还没被Dll1所“导出”,调用就会失败。
HTML是这样加载2个模块的——"mce:"是CSDN的blog自动添加上去的,主要参考那两个script标记,分别使html加载dll1模块和dll2模块。

代码<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="DoubleMain.css" mce_href="DoubleMain.css">
<title>Web Application Starter Project</title>
<mce:script type="text/javascript" language="javascript"
src="doublemain/doublemain.nocache.js"></mce:script>
<mce:script type="text/javascript" language="javascript"
src="doublemain2/doublemain2.nocache.js"></mce:script>
</head>
<body>
<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" mce_src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
</body>
</html>
至此,实现了一个简单的多模块间解耦合的调用,但是这里面的问题很多,不是一劳永逸,留待下篇博文来分解。
posted @ 2010-02-02 19:28 Anic 阅读(945) 评论(0)
编辑