From 3cb58ab6460048b5f9195155a119409018569e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Rune=20N=C3=B8stdal?= Date: Wed, 19 Mar 2014 05:20:54 +0100 Subject: [PATCH] mk-HTMLCTemplate: New feature; client side templating. Still needs more work, but this is the gist of it. --- src/symbolicweb/handy_handlers.clj | 1 + src/symbolicweb/html_template.clj | 48 ++++++++++++++++++++++++++++++ src/symbolicweb/viewport.clj | 1 + 3 files changed, 50 insertions(+) diff --git a/src/symbolicweb/handy_handlers.clj b/src/symbolicweb/handy_handlers.clj index 6dfe449..aa5b5a0 100644 --- a/src/symbolicweb/handy_handlers.clj +++ b/src/symbolicweb/handy_handlers.clj @@ -180,6 +180,7 @@ assoc k (assoc entry :already-added? true))))] [:body {:id "_body"} + [:div {:id "_sw_htmlctemplates" :style "display: none;"}] [:noscript [:h3 "JavaScript needs to be enabled in your browser"] [:p [:a {:href "https://encrypted.google.com/search?hl=en&q=how%20to%20enable%20javascript"} diff --git a/src/symbolicweb/html_template.clj b/src/symbolicweb/html_template.clj index 2f621e6..e9537b7 100644 --- a/src/symbolicweb/html_template.clj +++ b/src/symbolicweb/html_template.clj @@ -56,6 +56,54 @@ +(defn mk-HTMLCTemplate [^String html-resource ^Fn content-fn & args] + "Like mk-HTMLTemplate, but does the templating client side; in the browser, using jQuery." + (let [resource-hash (str "_sw_htmlctemplate-" (hash html-resource))] + (mk-WidgetBase + (fn [^WidgetBase template-widget] + (vm-observe (.viewport template-widget) (.lifetime template-widget) true + #(when %3 + ;; Add template to Viewport once. It will be cloned and filled in (templated) later. + (when-not (get (ensure (:html-templates @%3)) resource-hash) + (alter (:html-templates @%3) conj resource-hash) + (js-run template-widget + "$('#_sw_htmlctemplates').append($(" (js-handle-value html-resource false) ").attr('id', '" resource-hash "'));")) + (let [transformation-data (content-fn template-widget)] + (js-run template-widget + "$('#" (.id template-widget) "').replaceWith($('#" resource-hash "').clone().attr('id', '" + (.id template-widget) "'));") + (doseq [[^String selector content] (partition 2 transformation-data)] + (let [content-class (class content)] + (cond + (= java.lang.String content-class) + (js-run template-widget + "$('#" (.id template-widget) " > " selector "').text(" (js-handle-value content false) ");") + + (= clojure.lang.PersistentVector content-class) + (let [cmd (first content)] + (case cmd + :attr + (let [[^Keyword attr-key ^String attr-value] (rest content)] + (js-run template-widget + "$('#" (.id template-widget) " > " selector "').attr('" (name attr-key) "', " + (js-handle-value attr-value false) ");")) + + :html + (js-run template-widget + "$('#" (.id template-widget) " > " selector "').html(" (js-handle-value (second content) false) ");"))) + + (= symbolicweb.core.WidgetBase content-class) + (do + (js-run template-widget + "$('#" (.id template-widget) " > " selector "').attr('id', '" (.id ^WidgetBase content) "');") + (when-not (= content template-widget) + (binding [*in-html-container?* template-widget] + (attach-branch template-widget content)))))))))) + (str "")) + (apply hash-map args)))) + + + (defn ^WidgetBase mk-TemplateElement [^ValueModel value-model & args] "TemplateElements are meant to be used in context of HTMLContainer and its subtypes." (apply mk-he "%TemplateElement" value-model args)) diff --git a/src/symbolicweb/viewport.clj b/src/symbolicweb/viewport.clj index 6e3a5bf..7d4a271 100644 --- a/src/symbolicweb/viewport.clj +++ b/src/symbolicweb/viewport.clj @@ -41,6 +41,7 @@ :rest-css-entries (ref {}) :rest-js-entries (ref {}) :rest-head-entries (ref []) + :html-templates (ref #{}) ;; mk-HTMLCTemplate :session session :root-element root-widget ;; TODO: Rename...