Skip to content

Instantly share code, notes, and snippets.

@html
Last active December 10, 2015 11:28
Show Gist options
  • Save html/4427596 to your computer and use it in GitHub Desktop.
Save html/4427596 to your computer and use it in GitHub Desktop.
Replacement for render-menu function. Depends on https://gist.github.com/4427396 Uses mustache views and replaces most of (or all of) standard markup.
(def-weblocks-yaclml-mustache
navigation-tabs-item-layout
(<:li :id "{{{item-id}}}" :class "{{{item-class}}}"
(<:span :class "{{{inner-class}}}"
"{{#pane-selected-or-disabled-p}}"
(<:span :class "label" "{{{label}}}")
"{{/pane-selected-or-disabled-p}}"
"{{^pane-selected-or-disabled-p}}"
(<:a :href "{{{link}}}"
(<:as-is "{{{label}}}"))
"{{/pane-selected-or-disabled-p}}")))
(def-weblocks-yaclml-mustache
navigation-tabs-layout
(<:div :class "view menu" :id "{{menu-id}}"
"{{#header}}"
(<:h1 "{{{header}}}")
"{{/header}}"
"{{#empty-menu-p}}"
(<:div :class "empty-menu"
(<:as-is "{{{empty-message}}}"))
"{{/empty-menu-p}}"
"{{^empty-menu-p}}"
(<:ul "{{{menu-content}}}")
"{{/empty-menu-p}}"))
(defun render-menu-with-template (options &key selected-pane header (container-id (gen-id)) (base "")
ordered-list-p (empty-message *menu-empty-message*)
disabled-pane-names
(layout #'navigation-tabs-layout)
(item-layout #'navigation-tabs-item-layout))
"Renders a menu snippet based on given options and selected
option. An option may be a dotted pair of a label and URL to link to,
or a name (which will be converted to a label and a URL via
humanize-name and attributize-name, respectively). The selected-pane
will be compared to an option's URL via equalp. If the selected
option isn't specified, the first option is rendered as selected. If
CONTAINER-ID is provided, it is used as the basis of DOM IDs for the
menu and each menu item generated with `unattributized-name'. If a
given pane name is found in `disabled-pane-names', it's rendered in
the navigation as disabled."
(flet ((render-menu-items (&optional orderedp)
(with-output-to-string (out)
(loop
for option in options
for item-number from 1
do (progn
(unless (consp option)
(setf option
(cons (humanize-name option)
(attributize-name option))))
(let* ((label (car option))
(target (cdr option))
(pane-selected-p (equalp target (or selected-pane "")))
(pane-disabled-p (unless (functionp label)
(member (attributize-name label)
disabled-pane-names
:key #'attributize-name
:test #'string-equal)))
(pane-class (cond
(pane-selected-p "selected-item")
(pane-disabled-p "disabled-item"))))
(assert (not (functionp label)))
(write-string
(funcall item-layout `((:item-id .
,(weblocks::unattributized-name (format nil "~A-~A" container-id label)
'menu-item))
(:item-class . ,pane-class)
(:inner-class . ,(concatenate 'string
"item-wrapper"
(when orderedp
(format nil " item-number-~A" item-number))))
(:pane-selected-p . ,pane-selected-p)
(:pane-disabled-p . ,pane-disabled-p)
(:pane-selected-or-disabled-p . ,(or pane-selected-p pane-disabled-p))
(:label . ,label)
(:link . ,(when (not (or pane-selected-p pane-disabled-p))
(concatenate 'string
(string-right-trim "/" base)
"/"
(string-left-trim "/" target))))))
out)))))))
(write-string
(funcall
layout `((:menu-id . ,(weblocks::unattributized-name container-id 'menu))
(:header . ,header)
(:empty-menu-p . ,(null options))
(:empty-message . ,empty-message)
(:menu-content . ,(render-menu-items))))
weblocks:*weblocks-output-stream*)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment