返回列表 回复 发帖

[分享] 类javaeye博客我的收藏页面中分类标签输入功能的实现

本帖最后由 hegz 于 2010-5-9 10:06 编辑

在javaeye博客的收藏管理页面,收藏分类是通过下拉列表选择来录入已有分类标签的,这个功能非常方便实用,因为不用死记旧标签,还提高了标签的录入效率,于是决定自己模仿也搞一个。



在开始之前,先说明一下,以下的模仿过程全部处于FleaPHP框架之下,数据库为MySQL。

以下为功能实现的整个过程。

第一步:相关数据表准备

先创建一个文章管理数据表articles,该表含有一个自增量字段art_id。
接着创建一个分类标签数据表tags,其表结构如下图所示:



再创建一个中间表articles_tags,其表结构如下图所示:



第二步:编写数据表对象代码

1、编写文章数据表对象代码。如下所示:
  1. <?php

  2. FLEA::loadClass('FLEA_Db_TableDataGateway');

  3. /**
  4. * 文章数据表对象
  5. */
  6. class Table_Articles extends FLEA_Db_TableDataGateway
  7. {
  8.     var $tableName = 'articles';
  9.     var $primaryKey = 'art_id';

  10.     /**
  11.      * 定义多对多关系
  12.      *
  13.      */
  14.     var $manyToMany = array(
  15.         array(
  16.             'tableClass'      => 'Table_Tags',
  17.             'joinTable'       => 'articles_tags',
  18.             'foreignKey'      => 'art_id',
  19.             'assocforeignKey' => 'tag_id',
  20.             'mappingName'     => 'tags',
  21.             'enabled'          => false
  22.         )
  23.     );
  24. }
  25. ?>
复制代码
2、编写分类标签数据表对象代码。如下所示:
  1. <?php

  2. FLEA::loadClass('FLEA_Db_TableDataGateway');

  3. /**
  4. * 分类标签数据表对象
  5. */
  6. class Table_Tags extends FLEA_Db_TableDataGateway
  7. {
  8.     var $tableName = 'tags';
  9.     var $primaryKey = 'tag_id';
  10. }
  11. ?>
复制代码
第三步:编写模型对象类代码

1、编写分类标签模型对象类代码。如下所示:
  1. <?php

  2. /**
  3. * 分类标签模型对象类
  4. */
  5. class Model_Tags
  6. {
  7.     var $_tblTags;

  8.     /**
  9.      * 构造函数
  10.      *
  11.      */
  12.     function Model_Tags()
  13.     {
  14.         $this->_tblTags = & FLEA::getSingleton('Table_Tags');
  15.     }

  16.     /**
  17.      * 生成标签下拉列表HTML代码
  18.      */
  19.     function makeTagsDropdownlist()
  20.     {
  21.         $ui = & FLEA::initWebControls();
  22.         FLEA::loadFile('FLEA_Helper_Array.php');

  23.         $rows = $this->_tblTags->findAll();

  24.         // 增加一个下拉选择项在最前面
  25.         array_unshift($rows, array('tag_id' => 0, 'label' => '选择已有分类'));

  26.         $items = array_to_hashmap($rows, 'label', 'tag_id');

  27.         return $ui->control(
  28.             'dropdownlist',
  29.             'tagsel',  // 下拉列表ID
  30.             array(
  31.                 'items' => $items,
  32.                 //'selected' => null,
  33.             ),
  34.             true // 指示返回html代码,如果为false,则不返回
  35.         );
  36.     }
  37. }
  38. ?>
复制代码
2、编写文章模型对象代码。如下所示:
  1. <?php

  2. /**
  3. * 文章模型对象
  4. */
  5. class Model_Articles
  6. {
  7.     var $_tblArt;
  8.    
  9.     /**
  10.      * 构造函数
  11.      *
  12.      */
  13.     function Model_Articles()
  14.     {
  15.         $this->_tblArt = & FLEA::getSingleton('Table_Articles');
  16.     }
  17.    
  18.     /**
  19.      * 完成对文章条目所关联的 tags 的处理
  20.      *
  21.      * @param array $row
  22.      */
  23.     function _processTags(& $row) {
  24.         // 读出数据库现有的所有 tags
  25.         $tblTags = & FLEA::getSingleton('Table_Tags');

  26.         $rows = $tblTags->findAll(null);
  27.         
  28.         FLEA::loadFile('FLEA_Helper_Array.php');
  29.         $existsTags = array_to_hashmap($rows, 'label', 'tag_id');

  30.         // 处理用户输入的 tags
  31.         $labels = explode(',', $row['tags']);
  32.         //$labels = explode(',', $tags);
  33.         $tagsIdList = array();
  34.         foreach ($labels as $label) {
  35.             $label = strtolower(trim($label));
  36.             if ($label == '') {
  37.                 continue;
  38.             }
  39.             if (isset($existsTags[$label])) {
  40.                 // 将文档登记到现有 tag
  41.                 $tagsIdList[] = $existsTags[$label];
  42.             } else {
  43.                 // 创建新 tag,并登记文档
  44.                 $tag = array('label' => $label);
  45.                 $tagsIdList[] = $tblTags->create($tag);
  46.             }
  47.         }

  48.         $row['tags'] = $tagsIdList;
  49.         //return $tagsIdList;
  50.     }
  51.    
  52.     /**
  53.      * 新增文章
  54.      *
  55.      * @param array $row
  56.      * @return int
  57.      */
  58.     function create(& $row) {
  59.         $this->_processTags($row);
  60.         $this->_tblArt->enableLink('tags');
  61.         return $this->_tblArt->create($row);
  62.     }
  63.    
  64.     /**
  65.      * 更新文章
  66.      *
  67.      * @param array $row
  68.      * @return int
  69.      */
  70.     function update(& $row) {
  71.         $this->_processTags($row);
  72.         $this->_tblArt->enableLink('tags');
  73.         return $this->_tblArt->update($row);
  74.     }
  75. }
  76. ?>
复制代码
第四步、编写HTML模板代码

因为要利用到jQuery,所以模板文件要引入jQuery库文件。如下所示:
  1. <!-- // 引入 jQuery 库文件 -->
  2. <script type="text/javascript" src="jquery-1.4.2.min.js"></script>
复制代码
模板文件中与标签相关的HTML代码:

<tr>
   <td>分类标签:</td>
   <td><input name="tags" type="text" id="tags" size="30" />{{ $art.taglist }}*多个标签之间用半角逗号分隔</td>
</tr>

编写选择录入已有标签的JavaScript代码:
  1. <script type="text/javascript">
  2.     $(function() {
  3.         $("#tagsel").change(function(){
  4.             var txt = $("option:selected", this).text();
  5.             if (txt == '选择已有分类') {
  6.                 txt = '';
  7.             } else {
  8.                 var label = $("#tags").val();
  9.                 if (label) {
  10.                     txt = label +  ', ' + txt;
  11.                 }
  12.             }
  13.             $("#tags").val(txt);
  14.         });
  15.     });
  16. </script>
复制代码
第五步:编写后台文章控制器类代码
  1. <?php
  2. /**
  3. * 办公网站后台管理——文章管理控制器类
  4. *
  5. * 文 件 名:Admin/Controller/Article.php
  6. * 作    者:hegz
  7. * 更新时间:2010/05/07
  8. *
  9. */

  10. /**
  11. * 装入后台管理控制器基类
  12. */

  13. //{{
  14. FLEA::loadClass('Controller_AdminBase');
  15. //}}

  16. class Controller_Article extends Controller_AdminBase
  17. {
  18.     var $_modelArt;
  19.     var $_modelTags;

  20.     /**
  21.      * 构造函数
  22.      *
  23.      */
  24.     function Controller_Article()
  25.     {
  26.         parent::Controller_AdminBase();
  27.         $this->_modelArt = & FLEA::getSingleton('Model_Articles');
  28.         $this->_modelTags = & FLEA::getSingleton('Model_Tags');
  29.     }

  30.    /**
  31.     * 显示新增文档界面操作
  32.     *
  33.     */
  34.     function actionAdd()
  35.     {
  36.         ......
  37.         
  38.         $data = array(
  39.             'header' => '攒写文档',
  40.             'action' => $this->_url('Save'),
  41.             'taglist' => $this->_modelTags->makeTagsDropdownlist()  // 注意此句代码,生成下拉列表HTML代码
  42.         );

  43.         ......

  44.         $this->tpl->assign('art', $data);   // Smarty模板引擎变量替换

  45.         ......
  46.     }

  47.     /**
  48.      * 保存文档操作
  49.      *
  50.      */
  51.     function actionSave()
  52.     {
  53.         $data = $_POST;

  54.         ......
  55.         
  56.         if ($data['art_id']) {
  57.             $this->_modelArt->update($data);
  58.             $art_id = $data['art_id'];
  59.         } else {
  60.             $art_id = $this->_modelArt->create($data);
  61.         }
  62.         
  63.         ......
  64.     }
  65. }
复制代码
结束语

上面的实现过程由于要考虑新标签的保存及旧标签的处理,以及文章表与标签表的多对多关联,所以看上去有些复杂。如果不考虑这些实现,就只是下面几行处理标签录入的JavaScript代码的事。
  1. <script type="text/javascript">
  2.     $(function() {
  3.         $("#tagsel").change(function(){
  4.             var txt = $("option:selected", this).text();
  5.             if (txt == '选择已有分类') {
  6.                 txt = '';
  7.             } else {
  8.                 var label = $("#tags").val();
  9.                 if (label) {
  10.                     txt = label +  ', ' + txt;
  11.                 }
  12.             }
  13.             $("#tags").val(txt);
  14.         });
  15.     });
  16. </script>
复制代码
最后,实现的效果如下图所示:

附件: 您所在的用户组无法下载或查看附件
做人厚德载物,做事厚积薄发。
Blog:http://hegz.javaeye.com
先顶再慢慢看
这个必须顶,经常来这,很少回帖,先检讨下,也希望大家学习后都能顶贴支持下
返回列表