Skip to content

Instantly share code, notes, and snippets.

@baio
Created November 14, 2013 15:51
Show Gist options
  • Save baio/7469141 to your computer and use it in GitHub Desktop.
Save baio/7469141 to your computer and use it in GitHub Desktop.
#Default render engine, use `jsrender` templates to generate partial views
define ->
_getViewFullPath = null
#get real path by virtual, could be omitted
setGetViewPath = (getViewPathFunc) ->
_getViewFullPath = getViewPathFunc
_getViewFullPath = (path) ->
theme = $.cookie("theme")
theme ?= "admin"
"app/views/#{theme}/#{path}"
#**render (path, done)**#
#
#Render html, by the template defined in file with path `path`
#
#+ Partial views could be included
#+ Any element with `data-partial-view='path-to-partial-view'` will be considered as container for partial view
#+ Partial view containers also could define parameters via `data-partial-view-bag='{json-stingifyed}'`
#these parameters will be used while generating elements values/attributes via `jsrender` engine
#+ Partial views are loaded asyncronously from server via `requirejs`.
#+ After all partial views loaded and genrated (each partial view is appended as nested element to its container)
# `done` method is invoked such as `done (err, html)`, where html is generated html.
render = (bodyPath, done) ->
bodyPath = _getViewFullPath bodyPath
async.waterfall [
(ck) ->
require ["ural/libs/text!#{bodyPath}"], (bodyHtml) ->
ck null, bodyHtml
, (bodyHtml, ck) ->
_renderPartialViews bodyHtml, ck
], done
_renderPartialViews = (html, callback) ->
html = "<div>#{html}</div>"
__renderPartialViews html, (err, renderedHtml) ->
if renderedHtml then renderedHtml = $(renderedHtml).html()
callback err, renderedHtml
__renderPartialViews = (html, callback) ->
partialViews = $("[data-partial-view]", html)
rawPaths = $.makeArray(partialViews.map (i, p) -> {type : "html", path : $(p).attr("data-partial-view"), html : $(html)})
rawPaths = rawPaths.concat _getScriptPartialViews html
paths = rawPaths.map (p) => "ural/libs/text!#{if _getViewFullPath then _getViewFullPath(p.path) else p.path}"
if paths.length
require paths, ->
partialHtmls = _argsToArray arguments
partialHtmls = partialHtmls.filter (f, i) -> rawPaths[i].type == "html"
partialScripts = partialHtmls.filter (f, i) -> rawPaths[i].type == "script"
viewsHash = []
for partialHtml, i in partialHtmls
#get container html
$h = rawPaths[i].html
#find partial view tag in html container
rawPath = rawPaths[i].path
idx = viewsHash[rawPath]
idx ?= 0
$pratialViewTag = $h.find "[data-partial-view='#{rawPath}']:eq(#{idx})"
viewsHash[rawPath] = idx + 1
#get view-bag from this tag
viewBag = $pratialViewTag.attr "data-partial-view-bag"
#remove attributes from tag in html container
$pratialViewTag.removeAttr "data-partial-view"
$pratialViewTag.removeAttr "data-partial-view-bag"
#get json object (data) from view bag for this tag
jViewBag = if viewBag then eval "(#{viewBag})" else {}
#render partial html
$.templates pvt : partialHtml
partialHtml = $.render.pvt jViewBag
#inject rendered html into container tag
$pratialViewTag.html partialHtml
$html = $(html)[0]
async.forEachSeries partialHtmls
,(ph, ck) ->
__renderPartialViews $html, (err, renderedHtml) ->
html = renderedHtml
ck err
,(err) -> callback err, html
else
callback null, html
_getScriptPartialViews = (html) ->
res = []
$("script[type='text/html']", html).each (i, p) ->
$h = $.parseHTML(p.innerHTML)
for p in $h
p = $(p).attr("data-partial-view")
if p then res.push type : "script", path : p, html : $h
res
_argsToArray = (args) ->
for i in [0..args.length-1]
args[i]
render : render
setGetViewPath : setGetViewPath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment