Web开发 | iJohn.org

Archive for the ‘Web开发’ Category

22nd
二月 2012

Python框架
爱因万江斯坦@2012年02月22日 11:03 Post in Web开发 No Comments »

python 的框架基本上都是做了url跟action的映射配置文件

django的权限管理比较强大,如果有权限管理的可以用这个

比较轻量级的 tornado    webpy

twisted 是比较全面的框架,比较庞大

4th
十二月 2006

Spry框架初步入门
爱因万江斯坦@2006年12月04日 23:19 Post in Web开发 No Comments »

Adobe的Ajax框架spry的正式版还没放出,所以文档是少之又少,在这里接合自己使用的情况总结20个spry的知识点给大家,相信会对大家有一定帮助,至少大家也会对spry有个初步的认识了,这个轻量型的框架就一个字:“易用”。
1,使用spry框架,必须引用的两个核心js文件

<script type="text/javascript" src="../../includes/xpath.js"></script>
<script type="text/javascript" src="../../includes/SpryData.js"></script>

2,创建一个数据器dataset

var dsPhotos = new Spry.Data.XMLDataSet("/photos.php", "/gallery/photos/photo", { method: "POST", postData: "galleryid=2000&offset=20&limit=10", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" } });
var dsPhotos2 = new Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo");

method:为请求发送方式,POST / GET ;默认为GET
postData:为请求参数,可省略,可直接把”/photos.php”换成/photos.php?galleryid=2000&offset=20&limit=10
Content-Type:为头信息

3,不使用缓存

Var dsPhotos = new  Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo", { useCache:  false })

这里要重点说明一下,我在应用时,曾经发现设置不用缓存时,页面仍然不是最新数据,我是用一个servlet生成xml,然后对生成的数据进行删除和添加,但页面显示的数据不会自动更新。
后来在adobe的官方论坛上找到了答案,在IE中,使用userCache:false是不够的,还要在生成xml的jsp,php等中设置头不使用cache,如在生成xml的jsp/servlet中是要加上:
response.addHeader(”Cache-Control”,”no-cache”);
以上问题只存在IE中,在firefox和opera中不存在。注,spry对opera9版本支持很好,使用版本8的朋友要注意了。
另外,也可以在构造完数据器后,再设置缓存:

dsData.useCache = false;
dsData.loadData();

4,获取数据形式
假如我们上面的请求,返回的xml如下:

<gallery id="12345">
    <photographer id="4532">John Doe</photographer>
    <email>john@doe.com</email>  

    <photos id="2000">
        <photo path="sun.jpg" width="16" height="16" />
        <photo path="tree.jpg" width="16" height="16" />
        <photo path="surf.jpg" width="16" height="16" />  

    </photos>
</gallery>

那么“gallery/photos/photo”返回的数据是下面的数组:
[
{ “@path”: “sun.jpg”, “@width”: 16, “@height”: 16 },
{ “@path”: “tree.jpg”, “@width”: 16, “@height”: 16 },
{ “@path”: “surf.jpg”, “@width”: 16, “@height”: 16 }
]

var rows = dsPhotos.getData(); // 获取所有行.
var path = rows[0]["@path"];   // 获取第一行中"@path"的值   

dsPhotos.setCurrentRowNumber(2); // 将第3行做为当前处理行,下标以0开始   

var id = dsPhotos.getData()[2]["ds_RowID"]; // 获取第3行的ID.   

dsPhotos.setCurrentRow(id); // 通过第3行的id,将第3行设为当前处理行.

5,排序

dsPhotos.sort("@path"); //以"@path"列的值为关健字对行排序   

dsPhotos.sort("@path", "toggle");  //"ascending", "descending"和"toggle",默认是 "ascending"。
var dsPhotos = new Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo", { sortOnLoad: "@path", sortOrderOnLoad: "descending" });//也可在数据构造器中设置初始排序   

dsPhotos.setColumnType("@width", "number");//设置类型
dsPhotos.setColumnType("@height", "number");   

...   

dsPhotos.sort("@width"); // 对 "@width" 列数据进行排序.

6,去除重复

dsPhotos.distinct(); // Remove all duplicate rows.
//distinct()方法是具有破坏性的,多余的行是被删掉的,如果你想再得到所有的包括重复的原始项就得重新载入XML数据。
var dsPhotos = new Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo", { distinctOnLoad: true });//可在构造时预设

7,设置过滤器

var myFilterFunc = function(dataSet, row, rowNumber)
{
    if (row["@path"].search(/^s/) != -1)    //只返回以s开头的行
        return row;                     // Return the row to keep it in the data set.
    return null;                        // Return null to remove the row from the data set.
}   

dsPhotos.filterData(myFilterFunc); // Filter the rows in the data set.
dsPhotos.filter(myFilterFunc); // 不破坏数据,是建一个新的数组   

dsPhotos.filterData(null); // 取消过滤.

8,自动刷新,以毫秒为单位

var dsPhotos = new  Spry.Data.XMLDataSet("/photos.php?galleryid=2000", "/gallery/photos/photo", { useCache:  false, loadInterval: 10000 });//在构造器设置   

dsPhotos.startLoadInterval(10000); // 设置自动刷新
...   

dsPhotos.stopLoadInterval(); // 停止自动刷新

9,把类注册成观察器

var myObserver = new Object;
myObserver.onDataChanged = function(dataSet, data)      //可支持:onPreLoad / onPostLoad / onLoadError / onDataChanged / onPreSort / onPostSort /  onCurrentRowChanged
//第一个是发送通知的对象,做为数据器观察器,这个值永远都是dataSet对象。第二个参数可以不定义,也可以是一个对象(内置对象)
{
    alert("onDataChanged called!";
};   

dsPhotos.addObserver(myObserver);   

dsPhotos.removeObserver(myObserver);

10,把函数方法注册为观察器

function myObserverFunc(notificationType, dataSet, data)  //notfication,是通知器类型,dataSet是数据器对象,data是要观察的数据
{
    if (notificationType == "onDataChanged")
        alert("onDataChanged called!";
    else if (notificationType == "onPostSort")
        alert("onPostSort called!";
};   

dsPhotos.addObserver(myObserverFunc);

11,动态区域块
所有使用Spry动态区域块的HTML页面都要在它们的<html>标签中加入xmlns:spry=http://ns.adobe.com/spry

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry">
 .... ....
   .... ....
    <ul spry:region="dsPhotos">
        <li>{dsPhotos::path}</li>
    </ul>

COL, COLGROUP, FRAMESET, HTML, IFRAME, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR 不能设为动态区域

12,数据引用

{<数据器名>::<数据器列名>}

如果一个动态区域块只和一个数据器相关联,则你甚至可以省略掉数据器的名字
<li>{@path}</li>
ds_RowID – 这是数据器的行id。这个id可以帮我们指定数据器中的一个数据。它和数据是对应的,即使数据执行了排序操作,这个id和数据的对应关系也不会变化。
ds_RowNumber – 这是数据器当前数据的行号。
ds_RowNumberPlus1 – 这个与上面的ds_RowNumber相同,只不过它规定了数据的行号从1开始,而不是从0开始。
ds_RowCount – 它是数据器中数据的行的数量。如果使用了一个非破坏性的过滤器,则它的值是这个过滤器执行后得到的行的数量。
ds_UnfilteredRowCount – 在执行非破坏性过滤器前,数据器中行的数量。
ds_CurrentRowID – 当前行的id。这个值不会改变,除非使用了一个循环的构造。
ds_CurrentRowNumber – 当前行的行号。这个值不会改变,除非使用了一个循环的构造。
ds_SortColumn – 上一次排序所依赖的列名。如果这个数据器的数据还未进行过排序,则返回一个空字符串。
ds_SortOrder – 数据器中数据排序的参数,将返回三种字符串”ascending”, “descending”, 或空字符串.。
ds_EvenOddRow – 它返回的是”even”或”odd”,告诉我们ds_RowNumber的值是奇数还是偶数。

13,循环

//方式一:
<li spry:repeat="dsPhotos">{@path}</li>      

//方式二:
<ul spry:repeatchildren="dsPhotos">
  <li>{@path}</li>
</ul>     

//只输出以s开头的 spry:test属性的值可以是任何等于0或非0值的JavaScript表达示。如果这个表达示返回非0值,这个内容将会被输出,相当于if <>0就输出后面元素。
<li spry:repeat="dsPhotos" spry:test="'{@path}'.search(/^s/) != -1;">{@path}</li>

14,if 条件

<li spry:if="'{@path}'.search(/^s/) != -1;">{@path}</li>   

//if/else的形式,要使用"spry:choose"属性
            <div spry:choose="spry:choose">
                 <div spry:when="'{@path}' == 'surf.gif'">{@path}</div>
                 <div spry:when="'{@path}' == 'undefined'">Path was not defined.</div>
                 <div spry:default="spry:default">Unexpected value for path!</div>
          </div>

15,状态

<div spry:region="dsEmployees">
    <div spry:state="loading">正在载入数据 ...</div>
    <div spry:state="error">数据载入失败!</div>
    <ul spry:state="ready">
      <li spry:repeat="dsEmployees">{firstname} {lastname}</li>
    </ul>
</div>

16,通过对象将区域注册成观察者

myObserver = new Object;
myObserver.onPostUpdate = function(notifier, data)
{
     alert("onPostUpdate called for " + data.regionID);
};
...
// 调用addObserver() 将类注册为观察者.
Spry.Data.Region.addObserver("employeeListRegion", myObserver);
...
//注销
Spry.Data.Region.removeObserver("employeeListRegion", myObserver);
...   

<ul id="employeeListRegion" spry:region="dsEmployees">
...
</ul>

17,以函数将区域注册成观察者

function myRegionCallback(notificationState, notifier, data)
{
      if (notificationType == "onPreUpdate") //onLoadingData / onPreUpdate / onPostUpdate / onError
         alert(regionID + " is starting an update!");
      else if (notificationType == "onPostUpdate")
         alert(regionID + " is done updating!");
}   

...   

// 注册
Spry.Data.Region.addObserver("employeeListRegion", MyRegionCallback);
...   

// 注销
Spry.Data.Region.removeObserver("employeeListRegion", MyRegionCallback);
...   

<ul id="employeeListRegion" spry:region="dsEmployees">
...
</ul>

18,主细节模式,同一数据器

<span spry:region="dsEmployees">
<select spry:repeatchildren="dsEmployees" onchange="dsEmployees.setCurrentRow(this.value)">
    <option spry:if="{ds_RowNumber} == 0" value="{ds_RowID}" selected="selected">{username}</option>   

    <option spry:if="{ds_RowNumber} != 0" value="{ds_RowID}">{username}</option>
</select>
</span>
<span spry:detailregion="dsEmployees">{@id} - {firstname} {lastname} - {phone} </span>
//spry:detailregion"会在接收到"CurrentRowChanged"通知后改变自己的展示形式。

19,主细节模式,多个数据器

var dsStates = new Spry.Data.XMLDataSet("../../data/states/states.xml", "states/state");
var dsCities = new Spry.Data.XMLDataSet("../../data/states/{dsStates::url}", "state/cities/city");
//两个数据器有依赖关系,也可以用:"/webapp/cities.php?stateid={dsStates::@id}".   

<form name="selectForm">
//State:
    <span spry:region="dsStates" id="stateSelector">
        <select spry:repeatchildren="dsStates" name="stateSelect" onchange="document.forms[0].citySelect.disabled = true; dsStates.setCurrentRow(this.value);">   

            <option spry:if="{ds_RowNumber} == 0" value="{ds_RowID}" selected="selected">{name}</option>
            <option spry:if="{ds_RowNumber} != 0" value="{ds_RowID}">{name}</option>   

        </select>
    </span>   

//City:
    <span spry:region="dsCities" id="citySelector">
        <select spry:repeatchildren="dsCities" name="citySelect">   

            <option spry:if="{ds_RowNumber} == 0" value="{name}" selected="selected">{name}</option>
            <option spry:if="{ds_RowNumber} != 0" value="{name}">{name}</option>   

        </select>
    </span>
</form>

20,改变数据源

<select onchange="dsEmployees.setURL(this.value); dsEmployees.loadData();">   

    <option value="../../data/employees-01.xml" selected>Set 1</option>
    <option value="../../data/employees-02.xml">Set 2</option>
</select>   

<th scope="col" onclick="dsEmployees.sort('@id');">Employee ID </th>
7th
十一月 2006

Adobe的AJAX框架–Spry
爱因万江斯坦@2006年11月07日 00:33 Post in Web开发 No Comments »

最近看完了Adobe的AJAX框架Spry的所有文档和Demo,觉得这东西挺有意思的,在这里介绍给大家。
Spry框架的开发人员是来自于DreamWeaver开发组,他们把Spry框架做为DreamWeaver的一个完美补充为设计者和开发者提供对AJAX技术的支持。Spry框架是一个轻量级的AJAX框架,它的代码和标签十分的简洁和优雅,以保证让用户能便捷的使用,并不会为过繁杂的标签所惑。

Spry框架的官方网址:
http://labs.adobe.com/technologies/spry
在这里你能找到最新的文档和下载最新的Spry版本,目前版本是预览版1.3_08-11。
大家可以先在下面的看到Spry的示例和Demo:
http://labs.adobe.com/technologies/spry/samples/
http://labs.adobe.com/technologies/spry/demos/

 

Spry框架其实就是一个客户端的JavaScript类库,包含了一组JavaScript文件,CSS,图片文件,通过官方的框架结构图,我们能看出Spry框架的核心是四部分:XML数据器(XML Data Sets),动态区域(Dynamic Regions),装饰器库(Widgets)和变化效果库(Transition Effects)。

我们可以看出,Spry框架接收的数据格式只是XML数据格式。

一,XML数据器(XML Data Sets)
XML数据器是一个提供了从XML文档中载入和管理数据的JavaScript对象。它是Spry框架中处理XML格式数据的一个JavaScript功能实现。通过它,我们可以从XML中直接得到转换成表格数据格式的行和列的值,其实就是数组。它封装了获取XMLhttpRequest的方法,和发送并接收数据等一系列获取数据的方法。
要创建一个XML数据器,你必须在你的HTML文件中加入两行引入JavaScript文件的代码:

<script type=”text/javascript” src=”../../includes/xpath.js”></script>
<script type=”text/javascript” src=”../../includes/SpryData.js”></script>

上面引入的是Spry框架的核心js文件之一。”xpath.js”是Google基于XPath 1.0标准的JavaScript功能实现。你如果想获得更多的关于它的信息,可以访问Google的开源项目 google-ajaxslt project page .
”SpryData.js”则包含了定义XML数据器和动态区域的代码。
构造XML数据器就好像新建一个类一样,用”new”关键字即可:
<script type=”text/javascript”>
var dsPhotos = new Spry.Data.XMLDataSet(”/photos.php?galleryid=2000″, “/gallery/photos/photo”);
</script>
Spry框架为XML数据器提供了一些有特色的功能:如数据排序,数据过滤,按指定时间间隔自动更新,并引入了观察者通知模式以支持事件的触发。
关于XML数据器更多资料,大家可以参考http://labs.adobe.com/technologies/spry/articles/data_set_overview/,这一部分笔者已经翻译完成了,但英文原文其实写的通俗易懂,如果对一些名词翻译的不准确反倒会误导了大家,所以还是不贴出来了,大家可以参考官方英文文档。

二,动态区域(Dynamic Regions)
一旦你建立了XML数据器,你就可以在动态区域中去显示这个数据器的数据了。
创建动态区域块很简单,只要在html标签的相应位置加上”spry:region”属性就可以了,Spry框架就会知道这一块是被标识成动态区域了。
在动态区域,你可以有条件的选择要输出的数据,也可用循环输出。
动态区域另一个特点就是,它分为master和detail两个区域类型。
如下面的Demo截图:

master区域的数据改变会使detail区域的数据相应发生改变

两者都注册成XML数据器的观察者

当master区域的数据变化时,触发detail区域的响应事件,从面达到更新相应数据。
大家可参考http://labs.adobe.com/technologies/spry/samples/DataSetMasterDetailSample.html所示的功能。
这只是动态区域简单的示例,复杂的情况可能会有多个XML数据器与多个动态区域相互关联触发。

三,装饰器库(Widgets)
一个装饰器是由一组HTML,CSS,JavaScript封装成的高级UI。最常见的装饰器有可折叠的菜单,树型菜单和选项table面板等。这些对象都比较难于创建,需要一些更高级的编程经验。Spry的开发组在创建装饰器这一概念就是希望开发者们能相互协作,共享各自的设计,把这些高级界面元素用在自己的页面上。
Spry框架下的装饰器是易于编辑的。这种模型非常适合于设计者和编辑人员:要改变外观,只要改变CSS就可以了,要增加一个可折叠菜单只要copy和paste一个代码块就够了。
如,你能看懂的这段代码是创建了一个可折叠菜单吗?
<div id=”Acc1″ >
<div>
<div>Panel Header  1</div>
<div>Panel  1 Content </div>
</div>
<div>
<div>Panel Header  2</div>
<div>Panel  2 Content</div>
</div>
<div>
<div>Panel Header  3</div>
<div>Panel  3 Content</div>
</div>
</div>
<script>
var acc1 = new  Hanzo.Widget.Accordion(”Acc1″);
</script>
这段代码是非常简洁清晰的,没有什么繁杂的标签,这样设计是为了易于阅读。
关于这个例子,可以参考http://labs.adobe.com/technologies/spry/samples/accordion/AccordionSample.html

四,变化效果库(Transition Effects)
Spry框架的变化效果库都存于SpryEffects.js文件中,是基于JavaScript的一些动态变化效果,如,淡出,改变形状等。
Spry框架在设计时,曾考虑直接用第三方的效果库,如Script.aculo.us,但后来开发小组觉得要保证框架代码和标签的一致性,还是选择了自已开发,但是也基本上是以Script.aculo.us为原型进行设计,因为Script.aculo.us 本身就是一个非常优秀的变化效果库框架。
由于Spry框架现在只是预览版,所以目前只支持七种变换:
Appear/Fade Makes an element appear or fade away
Highlight Flashes a color as the background of an element
BlindUp/BlindDown Simulates a window blind, up or down, where the contents of the affected elements stay in place
SlideUp/SlideDown  Simulates a window blind, where the contents of the affected element scroll accordingly
Grow/Shrink Increases/reduces the size of the element
Shake Moves the element slightly to the left, then to the right, repeatedly
Squish Reduces the element to its top-left corner and disappears

可能到这大家对Spry框架已经有了大致的了解,其实这个东西已经足够我们的大多数应用的开发了,笔者也十分期待着正式版能早日放出,并打算在自己现在的项目中试一试了。