提高学习日记导航能力的思路

  下面是我对导航系统提高的思路,希望大家能够指出其中的问题并告诉我,让我少走弯路,您有什么意见和建议和问题也可以提出来。

  我会持续把我对导航系统的思考过程记录在这里。

  以前曾经就这个问题有个设想如下(http://www.learndiary.com/disDiaryContentAction.do?goalID=558):

  “4、改善系统的导航功能:

    关于保持访问路径的方法,我想了一点方法,仅供参考:用一个LinkedList对象保存访问路径字符串,其中的每一个元素是当前路径的字符串,在LinkedList中通过添加元素、查找元素、删除元素可以实现路径的跳转和回溯。”

  然后,我前些天作了一些思考,已记录在开源社区的cvs库中,其中的想法我已经初步认识是不可行的,但为了记录思路的过程,我也把它贴在这里:

  

  1.The key of this modifing is to keep the parents information of the current page.

  1).keep the information of where the goal come from:

  For example,a goal,it is maybe in "All Goals List(indexAction.do?pageNum=1),the abbreviation is 'AGL'",

"Processing Goals List(processGoalAction.do?pageNum=1,the abbreviation is 'PGL')",

"Quited Goals List(quitedGoalAction.do?pageNum=1,the abbreviation is 'QGL')",

"Finished Goals List(finishedGoalAction.do?pageNum=1,the abbreviation is 'FGL')",

"Searched Goals List(goalResultAction.do;jsessionid=4A629DA49B39A0C426F31B6DAB2FC0A3?pageNum=1),the abbreviation is 'SGL'".

So,when we click to view the content or the diaries list of a goal,we should record where

this goal come from,the item is among AGL,PGL,QGL,FGL and SGL;and,the page number "pageNum" is needed to record too.

  2).how to return to goals list when open different low level items in different windows:

  For example,when we click to view the goal content(disGoalContentAction.do?goalID=36) in

page "indexAction.do?pageNum=1",then,we click to view the same goal content(disGoalContentAction.do?goalID=36) in

page "processGoalAction.do?pageNum=1".When we want return to goals list in page "disGoalContentAction.do?goalID=36",

which goals list should we return?AGL or PGL?My answer is:return the lastest goals list,for example,if you visit

AGL before PGL,we will return to page PGL.

  3.ok,I have got a new idea,I should build a Navigator class,it will keep the all needed information concerning

navigation,and it will be transfered to it's low level page as a implicit parameter. 

  4.All paths list:

  1)all goals

  2)all goals->display goal's content

  3)all goals->display goal's content->comment goal

  昨天,我把动网的导航系统看了一下,其中的搜索帖子功能也不如我意:在查看搜索结果帖子的内容页面中点击下一篇帖子,得到的是帖子所在版块的下一篇帖子,而不是搜索到的帖子的下篇帖子。

  而且,在帖子提交、编辑等功能页面的导航可能均需要特殊的考虑。

  实际上,系统的查看帖子和搜索帖子功能总的说来都是搜索功能。导航的根本是把经历过的页面的搜索参数保留下来。

一、学习日记导航路径列举:

  总的说来,本系统存在下列几种导航路径:

  1、用户查看所有目标及其日记的导航:含有下列路径:

    1)所有目标列表->相关日记列表;(目标ID)

    2)所有目标列表->相关日记列表->显示日记内容;(日记ID)

    3)所有目标列表->相关日记列表->编辑日记内容;(日记ID)

    4)所有目标列表->相关日记列表->显示日记内容->撰写评论;

    5)所有目标列表->相关日记列表->显示日记内容->编辑评论;(评论ID)

  2、用户查看目标的内容及提交对目标的评论的导航:含有下列路径:

    1)所有目标列表->查看目标内容; (目标ID)

    2)所有目标列表->查看目标内容->撰写对目标的评论;(目标ID)

    3)所有目标列表->查看目标内容->编辑对目标的评论; (评论ID)

    3、您的进行中目标中的导航路径:

       1)目标内容:

     (1)所有目标列表-》进行中的目标列表; (用户ID)

     (2)所有目标列表-》进行中的目标列表-》查看目标内容;

     (3)所有目标列表-》进行中的目标列表-》查看目标内容->撰写对目标的评论;

     (4)所有目标列表-》进行中的目标列表-》查看目标内容->编辑对目标的评论;

    2)所有日记:

     (5)所有目标列表-》进行中的目标列表-》所有日记列表;(目标ID) 

     (6)所有目标列表-》进行中的目标列表-》所有日记列表->显示日记内容;              

     (7)所有目标列表-》进行中的目标列表-》所有日记列表->编辑日记内容;              

     (8)所有目标列表-》进行中的目标列表-》所有日记列表->显示日记内容->撰写评论;  

     (9)所有目标列表-》进行中的目标列表-》所有日记列表->显示日记内容->编辑评论;  

    3)您的日记:  

     (10)所有目标列表-》进行中的目标列表-》您的日记列表;(目标ID,用户ID) 

     (11)所有目标列表-》进行中的目标列表-》您的日记列表->显示日记内容;              

     (12)所有目标列表-》进行中的目标列表-》您的日记列表->编辑日记内容;              

     (13)所有目标列表-》进行中的目标列表-》您的日记列表->显示日记内容->撰写评论;  

     (14)所有目标列表-》进行中的目标列表-》您的日记列表->显示日记内容->编辑评论;

    4)写作日记:

     (15)所有目标列表-》进行中的目标列表-》写作日记;(目标ID)

       1》当提交日记后转到:查看您刚才提交的日记 ,路径为:3)-》(11)所有目标列表-》进行中的目标列表-》您的日记列表->显示日记内容;     

      2》当提交日记后转到:继续撰写下一篇日记  ,路径为:1)-》(1)所有目标列表-》进行中的目标列表;

      3》当提交日记后转到:查看当前目标的您的日记列表 ,路径为:3)-》(10)所有目标列表-》进行中的目标列表-》您的日记列表;    

      4》当提交日记后转到:查看当前目标的所有日记列表  ,路径为:2)-》(5)所有目标列表-》进行中的目标列表-》所有日记列表; 

    4、您的已退出的目标中的导航路径:

       1)目标内容:

     (1)所有目标列表-》已退出的目标列表; (用户ID)

     (2)所有目标列表-》已退出的目标列表-》查看目标内容;

     (3)所有目标列表-》已退出的目标列表-》查看目标内容->撰写对目标的评论;

     (4)所有目标列表-》已退出的目标列表-》查看目标内容->编辑对目标的评论;

    2)所有日记:

     (5)所有目标列表-》已退出的目标列表-》所有日记列表;(目标ID) 

     (6)所有目标列表-》已退出的目标列表-》所有日记列表->显示日记内容;              

     (7)所有目标列表-》已退出的目标列表-》所有日记列表->编辑日记内容;              

     (8)所有目标列表-》已退出的目标列表-》所有日记列表->显示日记内容->撰写评论;  

     (9)所有目标列表-》已退出的目标列表-》所有日记列表->显示日记内容->编辑评论;  

    3)您的日记:  

     (10)所有目标列表-》已退出的目标列表-》您的日记列表;(目标ID,用户ID) 

     (11)所有目标列表-》已退出的目标列表-》您的日记列表->显示日记内容;              

     (12)所有目标列表-》已退出的目标列表-》您的日记列表->编辑日记内容;              

     (13)所有目标列表-》已退出的目标列表-》您的日记列表->显示日记内容->撰写评论;  

     (14)所有目标列表-》已退出的目标列表-》您的日记列表->显示日记内容->编辑评论;

    5、您的已完成的目标中的导航路径:

       1)目标内容:

     (1)所有目标列表-》已完成的目标列表; (用户ID)

     (2)所有目标列表-》已完成的目标列表-》查看目标内容;

     (3)所有目标列表-》已完成的目标列表-》查看目标内容->撰写对目标的评论;

     (4)所有目标列表-》已完成的目标列表-》查看目标内容->编辑对目标的评论;

    2)所有日记:

     (5)所有目标列表-》已完成的目标列表-》所有日记列表;(目标ID) 

     (6)所有目标列表-》已完成的目标列表-》所有日记列表->显示日记内容;              

     (7)所有目标列表-》已完成的目标列表-》所有日记列表->编辑日记内容;              

     (8)所有目标列表-》已完成的目标列表-》所有日记列表->显示日记内容->撰写评论;  

     (9)所有目标列表-》已完成的目标列表-》所有日记列表->显示日记内容->编辑评论;  

    3)您的日记:  

     (10)所有目标列表-》已完成的目标列表-》您的日记列表;(目标ID,用户ID) 

     (11)所有目标列表-》已完成的目标列表-》您的日记列表->显示日记内容;              

     (12)所有目标列表-》已完成的目标列表-》您的日记列表->编辑日记内容;              

     (13)所有目标列表-》已完成的目标列表-》您的日记列表->显示日记内容->撰写评论;  

     (14)所有目标列表-》已完成的目标列表-》您的日记列表->显示日记内容->编辑评论;

  6、添加新目标的导航:

    1) 

     (1)所有目标列表-》添加新目标;

    2)提交新目标后的选择:

     (2)转到:查看您刚才提交的目标:导航为:所有目标列表-》进行中的目标列表-》查看目标内容;

     (3)转到:撰写日记 :导航为:所有目标列表-》进行中的目标列表;

  7、搜索功能中的导航:

    1)搜索:

     (1)所有目标列表-》检索页面;

    2)检索目标:

     (2)所有目标列表-》检索页面-》搜索结果目标列表;(条件字符串,已经存储在全局Session中)

     (3)所有目标列表-》检索页面-》搜索结果目标列表->查看目标内容;

     (4)所有目标列表-》检索页面-》搜索结果目标列表->查看目标内容->撰写对目标的评论;

     (5)所有目标列表-》检索页面-》搜索结果目标列表->查看目标内容->编辑对目标的评论;

     目标的日记的导航:

     (6)所有目标列表-》检索页面-》搜索结果目标列表->相关日记列表;(目标ID)

     (7)所有目标列表-》检索页面-》搜索结果目标列表->相关日记列表->显示日记内容;

     (8)所有目标列表-》检索页面-》搜索结果目标列表->相关日记列表->编辑日记内容;

     (9)所有目标列表-》检索页面-》搜索结果目标列表->相关日记列表->显示日记内容->撰写评论;

     (10)所有目标列表-》检索页面-》搜索结果目标列表->相关日记列表->显示日记内容->编辑评论;

    3)检索日记:

     (10)所有目标列表-》检索页面-》搜索结果日记列表;(条件字符串,已经存储在全局Session中)

      (11)所有目标列表-》检索页面-》搜索结果日记列表->显示日记内容;

      (12)所有目标列表-》检索页面-》搜索结果日记列表->编辑日记内容;

      (13)所有目标列表-》检索页面-》搜索结果日记列表->显示日记内容->撰写评论;

      (14)所有目标列表-》检索页面-》搜索结果日记列表->显示日记内容->编辑评论;

     日记所在目标的导航:

     (15)所有目标列表-》检索页面-》搜索结果日记列表->查看目标内容;(目标ID))

     (16)所有目标列表-》检索页面-》搜索结果日记列表->查看目标内容->撰写对目标的评论;

     (17)所有目标列表-》检索页面-》搜索结果日记列表->查看目标内容->编辑对目标的评论;

     日记所在目标所有日记的导航:

      (18)所有目标列表-》检索页面-》搜索结果日记列表->相关日记列表; (目标ID)

      (19)所有目标列表-》检索页面-》搜索结果日记列表->相关日记列表->显示日记内容;

      (20)所有目标列表-》检索页面-》搜索结果日记列表->相关日记列表->编辑日记内容;

      (21)所有目标列表-》检索页面-》搜索结果日记列表->相关日记列表->显示日记内容->撰写评论;

      (22)所有目标列表-》检索页面-》搜索结果日记列表->相关日记列表->显示日记内容->编辑评论;

            

二、学习日记导航功能实现思路探索:        

 例如:在下面的导航中:

  1、所有目标导航:

    (1)所有目标列表->相关日记列表;

    (2)所有目标列表->相关日记列表->显示日记内容;

    (3)所有目标列表->相关日记列表->编辑日记内容;

    (4)所有目标列表->相关日记列表->显示日记内容->撰写评论;

    (5)所有目标列表->相关日记列表->显示日记内容->编辑评论;

 中,有如下问题:

  (1)点击"所有目标列表"或"相关日记列表"是回到列表的第一页呢,还是回原来的页数呢?是使用默认的排序方式还是使用用户选定的排序方式呢?如果回到原来的页数,这时假设在这期间又有无数帖子提交了,结果是回不到原来帖子所在的那个页面的。

我看了看动网和JAVA资源网的方式,都是回到列表的第一页,所以我会采用回到第一页的做法,并且使用用户选定的排序方式-用户选定的排序方式储存在程序的Session中;

  (2)、如何唯一的定位一个特定的页面呢?

  如:如何定位”相关日记列表“呢?需要3个参数:

   1》目标ID;

   2》排序方式;

   3》每页条目数和当前页数;

  其中,2》中的排序方式已经存储在全局的Session中了,3》中每页的条目数已经定了,当前页数不用考虑,因为经过我们如(1)的分析,我们总是回到第一页中去;

  又如:如何定位显示日记内容呢?显然,仅需要这条日记的ID而已;

  现在,我把导航系统中定位每一个页面所需要的参数标在“一”中的各个导航路径后面。

  可以看到,定位一个页面需要的参数分为5种:

   1》列表:需要列表的parentID;

   2》单个条目:需要它的ID;

   3》用户的进行、完成等目标列表:需要用户ID;

   4》用户的进行、完成等目标的用户日记列表;需要用户ID和目标ID;

   5》搜索列表:什么都不需要,因为搜索字符串已保留在全局Session中了;

   然后,因为用户的ID已经存储在全局的Session中了,所以上面需要的参数进一步减为:

   1》列表:需要列表的parentID;

   2》单个条目:需要它的ID;

   3》用户的进行、完成等目标列表:什么都不需要,用户ID在Session中;

   4》用户的进行、完成等目标的用户日记列表;目标ID,所需的用户ID在Session中;

   5》搜索列表:什么都不需要,因为搜索字符串已保留在全局Session中了;

   这样,唯一定位一个页面所需要的参数变为:

   1》页面类型;

   2》参数ID;

   然后,在页面上显示url需要的参数为:

   1》标题:如一个目标的日记列表的标题应该是:“目标‘学习英语’的所有日记列表”,或者是:“目标‘学习英语’您的日记列表”,而显示一页日记的标题应该是:“日记‘今天我背了10个单词’”,等等;

   2》页面的url地址,如显示一页日记的url是:http://www.learndiary.com/disdiary.do?diaryID=10

      在页面上显示url需要的参数均可以由上面的定位页面所需的两个参数产生出来(即页面类型,参数ID);

      于是,可以考虑用一个链表保留定位页面所需的参数,把这两个参数封装为一个导航节点类:

      public class PageNavNode {

        private int typeID;

        private int parameter;

     

        public PageNavNode(int typeID,int parameter){}

        public setTypeID(){}

        ...

      }

     

      当点击一个url时,就把这个url所需的节点加入到一个链表中,这时链表变长;当在页面的导航链中点击上一个层次的链接时,就把这个节点后面的节点删除;

     也就是说,把这个链表作为一个request的参数传给页面,每一个页面中都有一个导航的链表参数在这个页面的生存周期中起作用;

     为了得到页面所需的html字符串,这个链表参数应该传入进入页面前的action中,由action负责将这个链表转变为页面导航所需要的字符串参数,为了分隔功能,可以在Pager类中设置一个方法,名称是:pageNaviGenerate(LinkedList naviLinker);

     但是,怎么保证这个链表能够继续下传下去呢?

     我知道有2种方法可以解决这个问题:

     1、把这个链表放在Session中,多个页面可以共享,并且可以修改这个链表,供下面的页面使用。但是,由于同个页面可以出现在不同的链表中,而且,系统有几个不同的链接路径,随着系统的成长,这样的链接路径还会不断增加。每一个链接路径都需要一个Session中的链表来保持这条路径的导航信息。

     比如,在“所有目标”这条路径查看某一篇日记就应该保存在“所有目标”这条链接路径中,而在“我的目标”这条路径查看同一篇日记就应该保存在“我的目标”这条路径中,显然,这在Session中需要不同的条目来保存。而且,为了识别日记页面是位于哪条路径上,打开这个页面前的action中需要上一个页面传来一个路径类别参数。这样,系统才能在Session中找到对Session中哪个链表进行修改。

    

     2、把这个链表封装成字符串,这个字符串在不同的页面间经过,然后不断的改变。把这个封装的字符串连同客户请求的url一起传给请求url前的action,由action解封并处理成下一个页面需要的导航字符串。

     今天,我尝试用第二种方法来实现。

     第一步:封装字符串传给action->action结合请求的页面和接受的封装字符串得到下一个请求页面的封装字符串并把这个封装字符串传给下一个页面,使下一个页面可以接力把这个封装字符串再传到再下一个请求页面前的action中->

     把请求页面封装的字符串转变为请求页面所需的导航字符串,并存入request中,供下一页面显示导航字符串提取使用。

    

                                                  2005年10月19日

     

     

     昨天,对导航系统的设计思路作了一下验证,基本可行。

     在设计中的选择:

     1、当前页面的导航条目灰化,主要是导航条目的页码总是第一页,当前的页面可能不是第一页,会引起混乱,而且,惯例是当前页面的导航条目灰化。

     2、设计中用到的方法:

     1)、接收来自request的导航封装编码字符串,和将要显示的页面的类型,得到将要显示的页面所需的导航封装编码字符串。

     实现方法,封装字符串采用的格式:页面类型(1位数字)+页面参数(如显示目标的日记列表所需的目标ID,显示日记内容所需的日记ID)+分隔符(我采用字符"a")

     如字符串1025,表示:所有目标-》目标:“建设“学习日记””的日记列表;

     得到将要显示的页面所需的导航封装编码字符串的方法:

     将显示页面类型ID在字符串中从前向后检索,1》如果检索到相同的类型,就把检索到的节点字符串后面的字符串截掉:

     如当前页面是查看日记内容,假设保持的编码字符串是:10a25a373,表示:所有目标-》目标:“建设“学习日记””的日记列表─》日记:用cookie保存用户密码登录流程

     这时,我点击“目标:“建设“学习日记””的日记列表”,它的类型ID是2,于是,就把25后面的字符串“a373”截掉。查看日记列表的导航封装字符串变为:10a25。

     2》如果没有检索到相同的类型,就把新的节点字符串加到现在的字符串中:

     如当前页面是查看日记内容,假设保持的编码字符串是:10a25a373,表示:所有目标-》目标:“建设“学习日记””的日记列表─》日记:用cookie保存用户密码登录流程

    这时,我点击了评论日记链接,它的类型ID是4,于是,就在后面加上:a473,评论日记的页面对应的导航封装字符串变为:10a25a373a473 

/**

* receive the encoding navigation string come from request and the type id of the page which we are going to and the parameter of the page which we are going to(it is articleID generally),

* get the encoding navigation string which it will be used in the page we are going to.

* @param naviStr the encoding navigation string come from request.

* @param toPageType the type id of the page which we are going to.

* @param parameter the parameter of the page which we are going to(it is articleID generally).

* @return the encoding navigation string which it will be used in the page we are going to.

*/

public static String encodeNaviStr(String naviStr, String toPageType, String parameter) {

String newNaviStr = naviStr;

int searchResult = naviStr.indexOf("a" + toPageType);

if (searchResult == -1) {

newNaviStr = newNaviStr.concat("a").concat(toPageType).concat(parameter);

} else {

newNaviStr = newNaviStr.substring(0, searchResult).concat("a").concat(toPageType).concat(parameter);

}

return newNaviStr;

}

public static void main(String[] args){

System.out.println( encodeNaviStr("a10a25a337", "4", "73"));

System.out.println( encodeNaviStr("a10a25a337", "2", "35"));

}

                                                                                               2005年10月20日

     

      昨天,完成了导航过程中封装字符串处理方法,今天,继续完成把封装的字符串转化为下一个页面显示导航条所需要的字符串的方法。

      如何把封装字符串“a10a25a337”转化为页面导航显示所需要的字符串:

      系统导航:<a href="http://www.learndiary.com/indexAction.do?pageNum=1">所有目标</a>-》<a href="http://www.learndiary.com/toDiaryAction.do?goalID=5&naviStr=a10>目标:“建设“学习日记””的日记列表</a>─》<a href="http://www.learndiary.com/disDiaryContentAction.do?goalID=73&naviStr=a10a25>日记:用cookie保存用户密码登录流程</a>->撰写评论(当前页面的导航条目灰化,不加超链接)

      ?

      显示这个字符串的要点:

      1、页面的类型:根据参数页面类型查找;

      2、标题:根据页面参数确定;

      3、第一个节点总是所有目标,最后一个节点不加超链接。

     

      实现方法分析:

      把“参数”和“页面标题”的对应关系做成一个map,用时在map里面查找。

      通过LearndiaryDB.getArtInfoByID(int articleID, int htmlFlag)得到页面导航所需的标题。

      为了方便处理,把每一个节点读入一个PageNavNode对象,然后用一个LinkedList来容纳这些对象。这样就可以自由处理其中的内容了。

     

      public String

     

      /**

* receive the encoding navigation string and get the navigation string which will be displayed in the page which we are going to.

* @param naviStr the encoding navigation string will be keeped in the request for the page which we are going to.

* @return the navigation string which will be displayed in the page which we are going to.

*/

public static String decodeNaviStr(String naviStr){

String navigation ="系统导航:";

String[] strArray = naviStr.split("a");

PageNaviNode[] nodesArray = new PageNaviNode[strArray.length()-1];

for (i=1;i<strArray.length();i++) {

  nodeArray[i-1] = strToPageNode(strArray[i]);

if (nodeArray.length()==1){

  navigation = navigation.concat("所有目标");

}

return navigation;

}                                                                   

  关于导航能力改进的代码,今天向http://learndiary.tigris.org中的cvs库作了第一次代码的提交。页面上基本上没有什么反映。

                                                                                 2005年10月21日

2 thoughts on “提高学习日记导航能力的思路”

  1.   还有:留言板,邮件订阅等需要导航,另外,横向导航:“上一条”、“下一条”还需要实现,这样,才是一个完整的导航系统。慢慢来吧。

  2.   实际实现的层次导航跟上面的分析不同(但基本思路是一样的),上面这个“提高学习日记导航能力的思路”的日记需要整理一下。可以写成一篇经验文章,与广大朋友交流。

Comments are closed.