1. 程式人生 > >使用django + layui實現側邊欄多級選單的功能

使用django + layui實現側邊欄多級選單的功能

layui本身是個非常棒的前段框架,自帶的也有側邊欄功能,不過不 支援多級,子選單也沒有縮排,因此,我做了些調整。

樹形選單是通過Django的自定義標籤渲染的。自定義標籤程式碼如下:

def is_ancestor(current, menu):
    """
    menu是否current的祖先
    :param current: 當前選單
    :param menu:
    :return: bool
    """
    parent_id = current.parent_id
    while parent_id != 0:
        if parent_id == menu.unique_id:
            return True
        try:
            parent_id = Menu.objects.get(pk=parent_id).parent_id
        except Menu.DoesNotExist:
            return False
    return current.unique_id == menu.unique_id


@register.simple_tag(takes_context=True)
def side_bar(context):
    root_menus = context["root_menus"]
    current_menu = context["current_menu"]
    request = context["request"]
    html = '<ul class=" layui-nav layui-nav-tree">'
    lists = []
    for menu in root_menus:
        # menu為根選單,也就是一級選單
        menu = ObjectDict(menu)
        # 確保右對齊,每個字的預設寬度為12px
        arrow_distance = 120 - len(menu.name) * 12
        url = menu.url or "javascript:;"
        if url == request.path or is_ancestor(current_menu, menu):
            extra_cls = "layui-nav-itemed"
            arrow_icon = ""  # 摺疊的箭頭
        else:
            extra_cls = ""
            arrow_icon = ""  # 展開的箭頭
        if menu.sub_menus:  # 有子選單才會有箭頭
            arrow = '<i class="layui-icon" style="font-size:15px;margin-left:{distance}px;">{code}</i>'.format(
                distance=arrow_distance, code=arrow_icon)
        else:
            arrow = ''
        # 一級選單有兩個圖示,最左側的圖示代表的是選單的含義,最右側的圖示代表的是箭頭
        # 二級及以下菜單隻有箭頭圖示
        li = '''<li class="layui-nav-item {extra_cls}">
        <a href="{url}">
        <i class="layui-icon" style="font-size:20px; margin-right:10px;">{icon}</i>
        {name}{arrow}</a>
        {sub_menus}
        </li>'''.format(extra_cls=extra_cls, name=menu.name,
                        icon=menu.icon_code, url=url, arrow=arrow,
                        sub_menus=render_sub_menus(current_menu, request, menu))
        lists.append(li)
    html += "\n".join(lists) + '</ul>'
    # mark_safe確保html能被正確渲染
    return mark_safe(html)


def render_sub_menus(current_menu, request, menu, level=1):
    """
    此函式遞迴渲染子選單
    :param current_menu: 當前選單
    :param request:
    :param menu: 渲染menu的子選單
    :param level: 為了縮排
    :return: 返回子選單渲染結果
    """
    if not menu.sub_menus:  # 遞迴終止
        return ""
    if not is_ancestor(current_menu, menu):  # 控制選單是否展開
        display = "none"
    else:
        display = "block"
    html = '<dl class="layui-nav-child" style="display:{}">\n'.format(display)
    for m in menu.sub_menus:
        m = ObjectDict(m)
        url = m.url or "javascript:;"
        arrow_distance = 120 - len(m.name)*12
        if url == request.path:
            extra_cls = "layui-this"  # 此樣式加亮當前選單背景色
            arrow_icon = ""
        elif is_ancestor(current_menu, m):
            extra_cls = "layui-nav-itemed"  # 此樣式開啟選單
            arrow_icon = ""
        else:
            extra_cls = ""
            arrow_icon = ""
        if m.sub_menus:
            arrow = '<i class="layui-icon" style="font-size:15px;margin-left:{distance}px;">{code}</i>'.format(
                distance=arrow_distance, code=arrow_icon)
        else:
            arrow = ''
        cls = 'class="active"' if m.unique_id == current_menu.unique_id else ''
        li = '''\t<dd class="layui-nav-item {extra_cls}"><a href="{url}" style="text-indent:{indent}px;" {cls}>
        {name}{arrow}</a>
        {sub_menus}</dd>\n'''.format(url=url, indent=level*30, cls=cls, name=m.name,
                                     extra_cls=extra_cls, arrow=arrow,
                                     sub_menus=render_sub_menus(current_menu, request, m, level+1))
        html += li
    html += "</dl>\n"
    return html

之後在頁面中載入自定義標籤檔案,然後使用{% side_bar %}即可渲染出所需要的選單。

不過此時還沒有點選選單開啟、收起選單的功能。使用如下JavaScript程式碼即可實現此功能。

$(".layui-nav-item a").click(function () {
            var uncles = $(this).parent().siblings();
            $.each(uncles, function (i, uncle) {
                var brothers = $(uncle).children();
                if (brothers.length >= 2){
                    $(brothers[1]).css("display", "none");
                    var b_icons = $(brothers[0]).children();
                    var b_arrow;
                    if (b_icons.length >= 2){
                        b_arrow = $(b_icons[1]);
                    }else {
                        b_arrow = $(b_icons[0]);
                    }
                    b_arrow.html("")
                }
            });
            var children = $(this).parent().children();
            if (children.length >= 2){
                var icons = $(children[0]).children();
                var arrow;
                if (icons.length >= 2){
                    arrow = $(icons[1]);
                }else{
                    arrow = $(icons[0]);
                }
                children = $(children[1]);
                if (children.css("display") == "none"){
                    children.css("display", "block");
                    arrow.html("")
                }else {
                    children.css("display", "none");
                    arrow.html("")
                }
            }
        });
layui提供的圖示很有限,擴充套件圖示功能參見:http://fly.layui.com/jie/5122/

相關推薦

使用django + layui實現多級選單功能

layui本身是個非常棒的前段框架,自帶的也有側邊欄功能,不過不 支援多級,子選單也沒有縮排,因此,我做了些調整。 樹形選單是通過Django的自定義標籤渲染的。自定義標籤程式碼如下: def is_ancestor(current, menu): """

JQuery.HoverDir庫實現二級選單

Jquery.hoverDir響應滑鼠移動方向的懸停效果外掛 HTML程式碼 <div id="sidebar"> <div class="mainNavs"> <div class="m

jQuery彈出滑動選單實現思路

昨天下午下了一個用jQuery實現彈出側邊欄滑動選單的demo,其實看明白了很簡單,現在把思路整理一下。 js部分:主要用了jQuery的toggleClass()方法,該方法檢查每個元素中指定的類。

jquery實現手風琴三級導航選單demo

jquery實現側邊欄手風琴三級導航選單 效果圖: 引入檔案,font-awesome為字型庫檔案: <link rel="stylesheet" type="text/css" href="Font-Awesome-3.2.1/css/font-aweso

個人中心的--用jq實現點擊一塊出現一塊其他幾塊隱藏並且同時改變前面的img圖片

icon -a 儀器 cor 個人 con 圖片 AC 默認 實現的效果: 默認狀態下: 點擊下面的標題時: html代碼: <h2>商品分類</h2> <div class="categories"> <ul cla

layui的使用

 不多bb,直接上程式碼 html的程式碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>後臺管理介面-電影推酷網&l

CSS3實現快速定位的隱藏和消失

Dome <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>CSS3隱藏懸浮網站左側標籤式導航欄程式碼 </title>

使用Android DrawLayout實現功能

    “千呼萬喚始出來,猶抱琵琶半遮面”,白居易的《琵琶行》中,兩句話將琵琶女的難言之痛與羞澀情態描寫的逼真生動,一個抱著琵琶的女子呼之欲出,她的羞澀之美令人久久難以忘懷。     生活中有含蓄之美,程式設計也不能將所有的功能一下子全部展示給使用者,當然這也無法實現。這個

安卓基於DrawerLayout實現實現

效果圖: 側邊欄在大多數app中都存在的, mDrawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); //關閉手勢滑動 mDrawer_layout.setDrawerLockMode(Dra

利用css3實現

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=de

關於Qt實現隱藏與顯示的效果

通過ToolButton來實現某控制元件的隱藏與顯示,具體功能為點選toolbutton後,某widget(以tabWidget為例)隱藏於左側,toolbutton位於(0,0)座標處,顯示的icon也進行切換;再次點選後,tabwidget展開,toolbutton還原

jquery實現

效果圖如下:主要用了jquery的mouseenter和mouseleave屬性和animate動畫屬性。程式碼為:<!DOCTYPE html> <html> <hea

jquery實現左右伸縮

jquery實現點選側邊欄伸縮效果。點選收縮,側邊欄向左收縮,顯示按鈕顯示;點選顯示按鈕,顯示按鈕向左收縮,側邊欄顯示。 具體程式碼如下: <!DOCTYPE html> <html

Django學習筆記三:頁面最新文章,文章歸檔,分類,標籤雲的實現

前言 執行效果 (箭頭 == 點選) 根據效果圖可以知道我們要實現的功能:將內容填充到各個側邊欄對應的內容下面,並實現對應的跳轉功能。 下面我們一項一項的實現下列的功能: 首先在blog應用下建立一個templatetags資料夾,資料夾下

JS實現

1 <!DOCTYPE html> 2 <html lang="en"> 3 <style> 4 </style> 5 <head> 6 <meta charset="UTF-8"> 7 <title&g

微信小程式之滑動實現(附完整原始碼)

目錄 一、效果圖 二、原理解析 三、原始碼 四、專案下載 同類文章推薦: 更多幹貨關注公眾號: 一、效果圖 講什麼都不如直接上效果圖好,所以我們先來看下實現效果如何。 通過滑動螢幕,或者點選左上角的圖示按鈕,都能實現側邊欄的劃出效果。   &nb

vue+elementui搭建後臺管理介面(3選單)

上一節搭好了主框架,但是標籤頁和側邊欄只是分別展示了各自的選單,如何將二者聯動起來? 定義路由規則:當有 children 屬性時,從 children 裡取出 path 填充到側邊欄,如: { path: '/', redirect: '/dashboard', name: 'Containe

android自定義View之仿通訊錄滑動,實現A-Z字母檢索

我們的手機通訊錄一般都有這樣的效果,如下圖: OK,這種效果大家都見得多了,基本上所有的android手機通訊錄都有這樣的效果。那我們今天就來看看這個效果該怎麼實現。 一.概述 1.頁面功能分析 整體上來說,左邊是一個ListView,右邊是一個自定義View,但

小程式購物車功能(支援手動輸入數量)以及和列表聯動的實現

小組剛完成一個小程式專案,第一版正式釋出了,過程中也遇到了很多問題,這裡記錄一下我負責的模組中的購物車功能的實現過程。後期再把其他小夥伴的模組也一併貼上來分析一下,自己也學習一下他們的獨門技能!效果圖如下: 在這裡,計數器、購物籃做成元件用於複用,由於左右聯動的功能

Ubuntu16.04選單不顯示

(1)只有桌面上顯示一些原有的文件或圖片。但開啟文件或者圖片後也是沒有視窗選單欄,這樣連關閉都沒法點,快捷Alt+F4也沒有反應。而且滑鼠點選拖動不了。 (2)終端不能用快捷鍵Ctrl+Alt+t 開啟。但可以滑鼠右鍵選擇開啟。另外可以Ctrl+Alt+F1進入純字元介面。