Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

html_helpers for hamlc

View gist:802d87e1fd6495cc4727
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
# HTML Tag class
#
# Purpose: Programmatically generate HTML so you aren't scotch-taping
# strings together all the time.
#
# Usage: targetString = Tag.make(tagName, attributeHash, text)
#
# Where: targetString: is what you will eventually inject into the DOM -- the HTML
# tagName: is the actual tag name (i.e., "tr" or "input")
# attributeHash: is the set of tag attributes, for example --
# class: "even-row", id: "row#{indexVar}", title: "Yo, Dog!"
# Note that repeating hash keys is a BAD idea. so:
# class: "even-row", class: "zebra-stripe"
# will not do what you expect. It works on the "last one wins"
# principle. Instead, use:
# class: "even-row zebra-stripe"
# text: is the text enclosed in the tag. If it is a self-closing
# tag like img or input, then leave the text empty.
 
class Tag
@make: (tagName, attributes, text...) ->
t = new Tag
t.name = tagName
t.attributes = attributes
t.text = ''
t.text = text.join('')
t
 
openTag: ->
attributeStrings = []
close = null
unless @text
close = ' />'
else
close = '>'
 
attributeStrings.push("#{key}=\"#{attribute}\"") for key, attribute of @attributes when key != 'text'
attributeString = if attributeStrings.length > 0 then ' ' + attributeStrings.join(' ') else ''
 
"<#{@name}#{attributeString}#{close}"
 
closeTag: (name) ->
"</#{@name}>"
 
tag: ->
parts = [@openTag()]
parts.push @text
parts.push @closeTag() if @text.length > 0
parts.join('')
toString: ->
@tag()
 
@HtmlHelpers =
linkTo: (name, href, options = {}) ->
options['href'] ||= href
Tag.make('a', options, name).toString()
 
textFieldTag: (name, value = "", options = {}) ->
options['type'] = 'text'
options['name'] = name
options['value'] = value
Tag.make('input', options, null).toString()
 
passwordFieldTag: (name, value = "", options = {}) ->
options['type'] = 'password'
options['name'] = name
options['value'] = value
Tag.make('input', options, null).toString()
 
textArea: (name, options = {}) ->
options['name'] = name
Tag.make('textarea', options).toString()
 
fileFieldTag: (name, options = {}) ->
options['name'] = name
options['type'] = 'file'
Tag.make('input', options).toString()
 
select: (name, collection = [], options = {}) ->
options['name'] = name
selectBody = []
selectBody.push Tag.make('option', {}, null) if options.include_blank?
for opt in collection
if opt instanceof Array
body = opt[0]
value = opt[1]
else
body = opt
value = opt
selectOptions = {}
selectOptions['value'] = value
selectOptions['selected'] = 'selected' if options['selected'] && options['selected'].toString() == value.toString()
selectBody.push Tag.make('option', selectOptions, body)
tagOptions = _.clone(options)
_.map ['selected', 'collection', 'as'], (key) -> delete tagOptions[key]
Tag.make('select', tagOptions, selectBody.join('')).toString()
 
checkBoxTag: (name, value = 1, checked = false, options = {}) ->
options['type'] = 'checkbox'
options['name'] = name
options['id'] ||= name
options['value'] = value
if checked
options['checked'] = 'checked'
Tag.make('input', options, null).toString()
 
labelTag: (name, content = null, options = {}) ->
options['for'] = name
Tag.make('label', options, content).toString()
 
submitTag: (value = "", options = {}) ->
options['type'] = 'submit'
options['value'] = value
Tag.make('input', options, null).toString()
 
FormBuilder: class FormBuilder
constructor: (model) ->
@model = model
self = this
_.map ['string', 'select', 'checkbox', 'text', 'file', 'password'], (key) ->
self[key] = (name, options = {}) ->
options['as'] = key
self['input'](name, options)
 
errors: (method) =>
if @model.get('errors') && @model.get('errors')[method]
Tag.make('div', 'class': 'errors', (@model.get('errors')[method].join(', ')))
else
""
 
input: (name, options = {}) =>
method = name.replace(/\]/, '').replace(/\[/, '.')
label = HtmlHelpers.labelTag(name, options?.label || _.humanize(name))
input = switch options['as']
when 'select'
options['selected'] ||= @model.get(method)
HtmlHelpers.select(name, options.collection || [], options)
when 'checkbox'
HtmlHelpers.checkBoxTag(name, 1, @model.get(method) || false, options)
when 'text'
options['value'] ||= @model.get(method) || ''
HtmlHelpers.textArea(name, options)
when 'file'
HtmlHelpers.fileFieldTag(name, options)
when 'password'
HtmlHelpers.passwordFieldTag(name, "", options)
else
value = options['value'] || @model.get(method) || ''
HtmlHelpers.textFieldTag(name, value, options)
 
Tag.make('div', 'class': 'input', (label + input + @errors(method))).toString()
 
button: (value = null, options = {}) =>
value ||= if @model.isNew() then 'Create' else 'Update'
HtmlHelpers.submitTag(value, options)
 
HAML.globals = -> HtmlHelpers

This helpers have to be used with the escape symbol in HAML, for example:

!= @linkTo "mysite", 'http://example.com"

If you want to use "unsafe" text, it won't be escaped:

!= @linkTo @userGeneratedText, 'http://example.com"

This is very dangerous.
I wrote wrote a version with support for escape text in a fork gist
With that code, you can do this:

!= @linkTo @userGeneratedText, 'http://example.com", escapeText: true

Sorry, last fork gist URL is wrong and I can not edit the comment.
The fork gist is here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.