1. 程式人生 > >Jquery-zTree學習筆記

Jquery-zTree學習筆記

zTree 簡介
zTree 是一個依靠 jQuery 實現的多功能 “樹外掛”。優異的效能、靈活的配置、多種功能的組合是 zTree 最大優點。

zTree v3.0 將核心程式碼按照功能進行了分割,不需要的程式碼可以不用載入
採用了 延遲載入 技術,上萬節點輕鬆載入,即使在 IE6 下也能基本做到秒殺
相容 IE、FireFox、Chrome、Opera、Safari 等瀏覽器
支援 JSON 資料
支援靜態 和 Ajax 非同步載入節點資料
支援任意更換面板 / 自定義圖示(依靠css)
支援極其靈活的 checkbox 或 radio 選擇功能
提供多種事件響應回撥
靈活的編輯(增/刪/改/查)功能,可隨意拖拽節點,還可以多節點拖拽喲
在一個頁面內可同時生成多個 Tree 例項
簡單的引數配置實現 靈活多變的功能

步驟 1、檔案準備

將需要使用的 zTree v3.x 相關的 js、css、img 檔案分別放置到相應目錄,並且保證相對路徑正確

步驟 2、編寫 html 頁面

按照以下程式碼,製作 html/jsp 頁面,訪問試試看吧,注意:
    1) "<!DOCTYPE html>" 是必需的!
    2) zTree 的容器 className 別忘了設定為 "ztree"
<!DOCTYPE html>
<HTML>
 <HEAD>
  <TITLE> ZTREE DEMO </TITLE>
  <meta
http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="demoStyle/demo.css" type="text/css"> <link rel="stylesheet" href="zTreeStyle/zTreeStyle.css" type="text/css"> <script type="text/javascript" src="jquery-1.4.2.js"></script> <script
type="text/javascript" src="jquery.ztree.core-3.x.js">
</script> <SCRIPT LANGUAGE="JavaScript"> var zTreeObj; // zTree 的引數配置,深入使用請參考 API 文件(setting 配置詳解) var setting = {}; // zTree 的資料屬性,深入使用請參考 API 文件(zTreeNode 節點資料詳解) var zNodes = [ {name:"test1", open:true, children:[ {name:"test1_1"}, {name:"test1_2"}]}, {name:"test2", open:true, children:[ {name:"test2_1"}, {name:"test2_2"}]} ]; $(document).ready(function(){ zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes); }); </SCRIPT> </HEAD> <BODY> <div> <ul id="treeDemo" class="ztree"></ul> </div> </BODY> </HTML>

一般來說zNodes都是拼接成的,要麼在後臺拼接好要麼在頁面拼接,當父子節點量比較大的,手動拼接是很麻煩的,下面提供由大牛ThinkGem寫的一個封裝類,實現JSON String<->Java Object的Mapper

package com.andone.common.mapper;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * 簡單封裝Jackson,實現JSON String<->Java Object的Mapper.
 * 封裝不同的輸出風格, 使用不同的builder函式建立例項.
 *
 * @author ThinkGem
 * @version 2013-11-15
 */
public class JsonMapper extends ObjectMapper {

    private static final long serialVersionUID = 1L;

    private static Logger logger = LoggerFactory.getLogger(JsonMapper.class);

    private static JsonMapper mapper;

    public JsonMapper() {
        this(Include.NON_EMPTY);
    }

    public JsonMapper(Include include) {
        // 設定輸出時包含屬性的風格
        if (include != null) {
            this.setSerializationInclusion(include);
        }
        // 允許單引號、允許不帶引號的欄位名稱
        this.enableSimple();
        // 設定輸入時忽略在JSON字串中存在但Java物件實際沒有的屬性
        this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 空值處理為空串
        this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jgen,
                                  SerializerProvider provider) throws IOException,
                    JsonProcessingException {
                jgen.writeString("");
            }
        });
        // 進行HTML解碼。
        this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>() {
            @Override
            public void serialize(String value, JsonGenerator jgen,
                                  SerializerProvider provider) throws IOException,
                    JsonProcessingException {
                jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
            }
        }));
        // 設定時區
        this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
    }

    /**
     * 建立只輸出非Null且非Empty(如List.isEmpty)的屬性到Json字串的Mapper,建議在外部介面中使用.
     */
    public static JsonMapper getInstance() {
        if (mapper == null) {
            mapper = new JsonMapper().enableSimple();
        }
        return mapper;
    }

    /**
     * 建立只輸出初始值被改變的屬性到Json字串的Mapper, 最節約的儲存方式,建議在內部介面中使用。
     */
    public static JsonMapper nonDefaultMapper() {
        if (mapper == null) {
            mapper = new JsonMapper(Include.NON_DEFAULT);
        }
        return mapper;
    }

    /**
     * Object可以是POJO,也可以是Collection或陣列。
     * 如果物件為Null, 返回"null".
     * 如果集合為空集合, 返回"[]".
     */
    public String toJson(Object object) {
        try {
            return this.writeValueAsString(object);
        } catch (IOException e) {
            logger.warn("write to json string error:" + object, e);
            return null;
        }
    }

    /**
     * 反序列化POJO或簡單Collection如List<String>.
     * <p>
     * 如果JSON字串為Null或"null"字串, 返回Null.
     * 如果JSON字串為"[]", 返回空集合.
     * <p>
     * 如需反序列化複雜Collection如List<MyBean>, 請使用fromJson(String,JavaType)
     *
     * @see #fromJson(String, JavaType)
     */
    public <T> T fromJson(String jsonString, Class<T> clazz) {
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }
        try {
            return this.readValue(jsonString, clazz);
        } catch (IOException e) {
            logger.warn("parse json string error:" + jsonString, e);
            return null;
        }
    }

    /**
     * 反序列化複雜Collection如List<Bean>, 先使用函式createCollectionType構造型別,然後呼叫本函式.
     *
     * @see #createCollectionType(Class, Class...)
     */
    @SuppressWarnings("unchecked")
    public <T> T fromJson(String jsonString, JavaType javaType) {
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }
        try {
            return (T) this.readValue(jsonString, javaType);
        } catch (IOException e) {
            logger.warn("parse json string error:" + jsonString, e);
            return null;
        }
    }

    /**
     * 構造泛型的Collection Type如:
     * ArrayList<MyBean>, 則呼叫constructCollectionType(ArrayList.class,MyBean.class)
     * HashMap<String,MyBean>, 則呼叫(HashMap.class,String.class, MyBean.class)
     */
    public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    /**
     * 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性.
     */
    @SuppressWarnings("unchecked")
    public <T> T update(String jsonString, T object) {
        try {
            return (T) this.readerForUpdating(object).readValue(jsonString);
        } catch (JsonProcessingException e) {
            logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
        } catch (IOException e) {
            logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
        }
        return null;
    }

    /**
     * 輸出JSONP格式資料.
     */
    public String toJsonP(String functionName, Object object) {
        return toJson(new JSONPObject(functionName, object));
    }

    /**
     * 設定是否使用Enum的toString函式來讀寫Enum,
     * 為False時時使用Enum的name()函式來讀寫Enum, 預設為False.
     * 注意本函式一定要在Mapper建立後, 所有的讀寫動作之前呼叫.
     */
    public JsonMapper enableEnumUseToString() {
        this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
        return this;
    }

    /**
     * 支援使用Jaxb的Annotation,使得POJO上的annotation不用與Jackson耦合。
     * 預設會先查詢jaxb的annotation,如果找不到再找jackson的。
     */
    public JsonMapper enableJaxbAnnotation() {
        JaxbAnnotationModule module = new JaxbAnnotationModule();
        this.registerModule(module);
        return this;
    }

    /**
     * 允許單引號
     * 允許不帶引號的欄位名稱
     */
    public JsonMapper enableSimple() {
        this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
        this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        return this;
    }

    /**
     * 取出Mapper做進一步的設定或使用其他序列化API.
     */
    public ObjectMapper getMapper() {
        return this;
    }

    /**
     * 物件轉換為JSON字串
     *
     * @param object
     * @return
     */
    public static String toJsonString(Object object) {
        return JsonMapper.getInstance().toJson(object);
    }

    /**
     * JSON字串轉換為物件
     *
     * @param jsonString
     * @param clazz
     * @return
     */
    public static Object fromJsonString(String jsonString, Class<?> clazz) {
        return JsonMapper.getInstance().fromJson(jsonString, clazz);
    }

    /**
     * 測試
     */
    public static void main(String[] args) {
        List<Map<String, Object>> list = Lists.newArrayList();
        Map<String, Object> map = Maps.newHashMap();
        map.put("id", 1);
        map.put("pId", -1);
        map.put("name", "根節點");
        list.add(map);
        map = Maps.newHashMap();
        map.put("id", 2);
        map.put("pId", 1);
        map.put("name", "你好");
        map.put("open", true);
        list.add(map);
        String json = JsonMapper.getInstance().toJson(list);
        System.out.println(json);
        Object o = JsonMapper.getInstance().fromJson(json, JSONObject.class);
        System.out.println(o);
    }

}

具體使用—————————————–

controller層:


 List<TreeNode> gradeTree = createGradeTree();
            model.addAttribute("gradeTree", JsonMapper.toJsonString(gradeTree));

JSP:

                <form:input path="gradeName" readonly="true" placeholder="請選擇"
                            onclick="showView(this.id)" cssStyle="width:80px;height:30px;"/>
                <div id="z_menuContent" class="menuContent"
                     style="display: none; position: fixed;">
                    <ul id="z_treeDemo" class="ztree"
                        style="margin-top: 0; border: 1px solid #617775; background: #f0f6e4; width: 180px; height: 200px; overflow-y: auto; overflow-x: auto;"></ul>
                </div>

JS:

//年級樹形下拉框   √
        function beforeClick(treeId, treeNode) {
            return (treeNode && !treeNode.isParent);
        }
        function treeClick(e, treeId, treeNode) {
            if (treeId == 'z_treeDemo') {
                //獲取當前節點的名稱
                var pName = treeNode.name;
                $("#gradeName").attr("value", pName);
                //為年級編號賦值
                $("#gradeId").attr("value", treeNode.id);
                selectClass(pName);
                z_hideView();
            }
        }
        function showView(id) {
            if (id == 'gradeName') {
                var cityObj = $("#" + id);
                $("#z_menuContent").css({
                    left: cityObj.offset().left + "px",
                    top: cityObj.offset().top + cityObj.outerHeight() + "px"
                }).slideDown("fast");
                $("body").bind("mousedown", z_onBodyDown);
            }
        }
        function z_hideView() {
            $("#z_menuContent").fadeOut("fast");
            $("body").unbind("mousedown", z_onBodyDown);
        }
        function z_onBodyDown(event) {
            if (!(event.target.id == "menuBtn" || event.target.id == "z_menuContent"
                || $(event.target).parents("#z_menuContent").length > 0)) {
                z_hideView();
            }
        }

父子節點關係從資料庫獲取存放在物件集合中,轉化後變成如下:

[{"id":"30319","pId":"-1","name":"小學","code":"小學"},{"id":"30320","pId":"-1","name":"初中","code":"初中"},{"id":"69629","pId":"30319","name":"畢業班","code":"小學"},{"id":"69630","pId":"30320","name":"畢業班","code":"初中"},{"id":"29963","pId":"30319","name":"小學一年級","code":"小學"},{"id":"29964","pId":"30319","name":"小學二年級","code":"小學"},{"id":"29965","pId":"30319","name":"小學三年級","code":"小學"},{"id":"29966","pId":"30319","name":"小學四年級","code":"小學"},{"id":"29967","pId":"30319","name":"小學五年級","code":"小學"},{"id":"29968","pId":"30319","name":"小學六年級","code":"小學"},{"id":"29969","pId":"30320","name":"初中三年級","code":"初中"},{"id":"29970","pId":"30320","name":"初中二年級","code":"初中"},{"id":"29971","pId":"30320","name":"初中一年級","code":"初中"}]