«
使浏览器实现JavaScript支持的方法解析

时间:2008-5-31    作者:Deri    分类: 分享


   <p>  一、 基本的JavaScript 开发环境</p><p>  JavaScript Reference与JavaScript API:</p><p>  JavaScript Reference是用于建立包含JavaScript runtime的Library或 DLL,然后编译成小的 "shell" 程序,连接Library后生成交互式的JavaScript解释器,也可以用来解释.js 文件。</p><p>  该程序不依赖Navigator代码。</p><p>  生成的"shell" 程序,对比浏览器对JavaScript的支持,相同之处是使用相同的包含JavaScript runtime的Library 或 DLL,我们把这部份相同的Library或 DLL称为JavaScript API,我们实际开发JavaScript应用,也是在JavaScript API基础上工作,而不用过多考虑其内部的实现。关于JavaScript API,参见JavaScript API详解。</p><p>  二、 JavaScript Engine</p><p>  JavaScript Engine用于初始化JavaScript环境,提供对JavaScript解释、执行的接口。</p><p>  初始化主要包括:</p><p>  内存分配:rt=JS_Init(10000L);</p><p>  初始化cx:cx = JS_NewContext(rt, STACK_CHUNK_SIZE);</p><p>  初始化globalObj:globalObj = JS_NewObject(cx, &globalClass, 0, 0);</p><p>  定义标准类:JS_InitStandardClasses(cx, globalObj);</p><p>  定义系统函数:JS_DefineFunctions(cx, globalObj, g_functions);</p><p>  定义报错函数:JS_SetErrorReporter(cx,JS_ErrorReporter);</p><p>  注册其它类:</p><p>  RegisterClassPoint(cx,globalObj);</p><p>  RegisterClassSize(cx,globalObj);</p><p>  RegisterClassRect(cx,globalObj);</p><p>  RegisterClassPolygon (cx,globalObj);</p><p>  RegisterClassColorKey (cx,globalObj);</p><p>  RegisterClassTDTimer (cx,globalObj);</p><p>  初始化定时器:TDTimerListInit();</p>
<p> </p>

   <p>  提供对JavaScript解释、执行的接口函数:</p><p>  TD_EvaluateScript(JSContext *cx,</p><p>  JSObject *obj,</p><p>  const char *bytes,</p><p>  uintN length,</p><p>  const char *filename,</p><p>  uintN lineno,</p><p>  jsval *rval)</p><p>  三、 JavaScript与浏览器接合</p><p>  基本概念:JavaScript操作HTML元素的常见方式</p><p>  例:</p><code><html><br /><head><br /><script><br /><!--<br />function ChangeImage(index)<br />{image0.src="a"+index+".gif";}<br />--><br /></script><br /></head><br /><a onmouseover="ChangeImage(0);">军人</a><br><br /><a onmouseover="ChangeImage(1);">眼睛</a><br><br /><ccid_file id="image0" values="a0" id="image0" src="a0.gif" /></img><br /></html></code></p><p>  当鼠标移到文字上时,触发事件mouseover,调用ChangeImage()函数,结果为图像源(SRC)发生变化,重新调入新图片。</p><p>  由此产生两个关键问题:</p><p>  1. Javascript如何获取HTML元素的名称和属性。</p><p>  2. Javascript如何改变HTML元素的属性,并操作WIDGET重画。</p><p>  下面分别阐述这两个问题:</p><p>  首先介绍涉及到的浏览器流程:</p><p>  Tokenize -> BuildModel -> ProcessElement -> WidgetPaint</p><p>  ---------------------  ----------------------------</p><p>   |        |</p><p>  parse       layout</p><p>  问题1解决:HTML元素作为Javascript对象进行注册。</p><p>  注册过程在BuildModel中进行。</p>
 <p> </p>

   <p>  BuildModel的首要任务是将Token后的结点按包含关系展成一棵树。</p><p>  其次就是要将某些结点注册为JavaScript对象。</p><p>  注册的过程是:</p><p>  定义新对象:JSObject *proto;</p><p>  初始化该对象:TD_JSXMLElementClassInit(JS_GetGlobalContext(),</p><p>  (void **)&proto))</p><p>  使用JS_DefineObject或JS_NewObject定义对象属性:</p><p>  根据是否定义了该元素的名称区别对待:</p><code>if(TD_XMLContentIsNamedItem(aElement,&aName))<br />{<br />parent = js_GetGlobalObject();<br />*aReturn=JS_DefineObject(JS_GetGlobalContext(),js_GetGlobalObject(),aName-><br />mStr,&ElementClass,proto,JSPROP_ENUMERATE);<br />}<br />else<br />{<br />parent=aElement->parent->mScriptObject;<br />*aReturn = JS_NewObject(JS_GetGlobalContext(), &ElementClass, proto, parent);<br />}</code></p><p>  将对象加入:</p><p>  JS_SetPrivate(JS_GetGlobalContext(), (JSObject *)*aReturn, aElement);</p><p>  这样,在编译时,HTML元素的标识就能被Javascript编译器识别,否则会报错变量未定义。</p><p>  问题2解决:利用注册给对象的函数实现操作符的功能化。</p><p>  具体可理解为:</p><p>  当image0.src ="1.gif"被执行时,相当于为对象设置或改变属性,此时SetElementProperty函数被调用(该函数在注册该对象时由 JSXMLElementClassInit捆绑给该对象,其内容由用户自己定义),SetElementProperty通过函数指针调用函数 TD_JSXMLSetAtrByID,改变结点树上结点属性,并重新生成该节点对应的widget,重画界面。</p><p>  问题:如何建立Javascript对象与结点树上结点的对应?</p></p><p>  答: Javascript对象与结点树是同时生成的,它们的共同性质是结点具有相同属性,Javascript对象根据ID属性查找树,找到要操作的对应结点。</p><p>  四、 浏览器消息响应</p><p>  在主消息循环中调用TDWidgetProcessMsg,处理与widget有关消息。</p><p>  首先:取得当前焦点所在的widgetpWidget=TDWidgetGetAtPoint(pThis->baseDoc.base.mWidget,pt,&index);</p><p>  处理该widget对该消息的响应。</p><p>  最后一般为调用javascript执行,实现实际响应。</p><code>TDVOID TDWidgetDoAction(TDPWidgetAction pAnchor)<br />{<br />jsval jval;<br />if(pAnchor)<br />TD_EvaluateScript(JS_GetGlobalContext(),js_GetGlobalObject(),<br />pAnchor->mAction.mStr,pAnchor->mAction.mLength,TDNULL,0,&jval);<br />}</code></p></p>