영원한사랑

네이버 카테고리 탐색기 흉내를 내보았다.
다음 구현 코드는 Pear::DB, prototype.js에 의존적인 코드이다.
행복한고니님의 json_encode함수를 사용했다.

자바스크립트에서 init함수와 dir함수가 많은 부분 중복되고 템플릿이 되는 문자열에 xdir이란 객체가 직접 쓰여서 코드가 꼬이는 것 같아 불만은 있지만 나의 내공으로는 도저히...ㅠ.ㅠ
 

카테고리 table 설계는 다음과 같다.
(Language : text)
+----------+
| biz_dirs |
+------------------------------------------------------------+
p>  id        : 고유번호
    name      : 이름,타이틀
k>  p_id      : 부모번호
    type      : 0x1:디렉토리, 0x2:가상디렉토리 ...
    child_cnt : 하위 노드수
    real_id   : 가상일 때 링크된 실제 디렉토리 번호
+------------------------------------------------------------+



x_dir_list.php (Language : php)
<?php
header("Content-Type: text/html; charset=euc-kr");
$id = iconv("utf-8", "euc-kr", trim($_GET['id']));
if(!is_numeric($id)) exit;
include_once 'json_encode.php';
include_once 'DB.php';
//// DB연결 정보
$DSN = array(
    'phptype'=>'mysql',
    'username'=>'xxx_id',
    'password'=>'xxx_pw',
    'hostspec'=>'xxx.xxx.xxx.xxx',
    'database'=>'xxx_db'
);
//// DB연결
$db =& DB::connect($DSN);
$data = array();
$sql
= 'SELECT name FROM biz_dirs WHERE id=?';
$data['name'] = $db->getOne($sql, array($id));
$sql = 'SELECT id, name, type, child_cnt, real_id FROM biz_dirs WHERE p_id=?';
$data['subs'] = $db->getAll($sql, array($id), DB_FETCHMODE_ASSOC);
//// DB연결 종료
$db->disconnect();
echo json_encode2($data);
?>


xdir.js (Language : javascript)
XDir = function(path) {
    this.data = {};
    this.path = path;
    this.xdir_url = 'x_dir_list.php';
    this.expand_icon = '<img src="/test/img/icn_plus.gif" />';
    this.close_icon = '<img src="/test/img/icn_minus.gif" />';
    this.leaf_icon = '<img src="/test/img/icn_nosub.gif" />';
    this.tpls = {
        'close_head': new Template('<a onclick="xdir.close(\'#{id}\')">#{icon}</a> <a href="javascript:dir(#{id})">#{name}</a>'),
        'expand_head': new Template('<a onclick="xdir.dir(\'#{id}\')">#{icon}</a> <a href="javascript:dir(#{id})">#{name}</a>'),
        'trank_node': new Template('<div id="dir_head_#{id}" style="margin-left:10px"><a onclick="xdir.dir(\'#{id}\')">#{icon}</a> <a href="javascript:dir(#{id})">#{name}</a></div><div id="dir_box_#{id}" style="margin-left:10px"><img height="1" /></div>'),
        'leaf_node': new Template('<div id="dir_head_#{id}" style="margin-left:10px">#{icon} <a href="javascript:dir(#{id})">#{name}</a></div><div style="margin-left:10px"><img height="1" /></div>')
    }
}
XDir.prototype = {
    init: function() {
        var id = this.path.shift();
        if(id == undefined) return;
        if(id != '0') {
            if($('dir_head_'+id) == null) return;
            $('dir_head_'+id).innerHTML = 'Loading...';
        }
        if(this.data[id] == undefined) {
            var o_xdir = this;
            new Ajax.Request(this.xdir_url, {
                method: 'get',
                encoding: '',
                parameters: {'id': id},
                onSuccess: function(transport) {
                    o_xdir.data[id] = transport.responseText.evalJSON(true);
                    o_xdir.expand(id);
                    o_xdir.init();
                }
            });
        }
        else {
            this.expand(id);
            this.init();
        }
    },
    dir: function(id) {
        if(id != '0') {
            if($('dir_head_'+id) == null) return;
            $('dir_head_'+id).innerHTML = 'Loading...';
        }
        if(this.data[id] == undefined) {
            var o_xdir = this;
            new Ajax.Request(this.xdir_url, {
                method: 'get',
                encoding: '',
                parameters: {'id': id},
                onSuccess: function(transport) {
                    o_xdir.data[id] = transport.responseText.evalJSON(true);
                    o_xdir.expand(id);
                }
            });
        }
        else {
            this.expand(id);
        }
    },

    expand: function(id) {
        var str = '';
        var list = this.data[id]['subs'];
        var name = this.data[id]['name'];
        for(var i=0; i<list.length; i++) {
            str += this.get_node_str(list[i]);
        }
        if($('dir_box_' + id) == null) return;
        $('dir_box_' + id).innerHTML = str;
        if(id != '0') $('dir_head_' + id).innerHTML = this.get_close_head_str(id, name);
    },
   
    close: function(id) {
        var name = this.data[id]['name'];
        $('dir_head_' + id).innerHTML = this.get_expand_head_str(id, name);
        $('dir_box_' + id).innerHTML = '<img height="1" />';
    },
   
    get_close_head_str: function(id, name) {
        return this.tpls.close_head.evaluate({'id':id,'icon': this.close_icon,'name':name});
    },
   
    get_expand_head_str: function(id, name) {
        return this.tpls.expand_head.evaluate({'id':id,'icon': this.expand_icon,'name':name});
    },
   
    get_node_str: function(dir) {
        var s_tpl = '';
        var s_node = '';
        var name = (dir.type=='2') ? dir.name + '@' : dir.name;
        var icon = (parseInt(dir.child_cnt) > 0) ? this.expand_icon : this.leaf_icon;
        var tpl_data = {'id':dir.id, 'name':name, 'icon': icon};
        if(parseInt(dir.child_cnt) > 0) {
            return this.tpls.trank_node.evaluate(tpl_data);
        }
        return this.tpls.leaf_node.evaluate(tpl_data);
    }
}


function dir(id) {
    alert('카테고리 id(' + id + ') 구현 페이지로 이동');
}
 


사용예 : http://asam.pe.kr/test/dir_test.php