class Showoff::Compiler::Form
Adds form processing to the compiler
Public Class Methods
form_checked?(modifier)
click to toggle source
# File lib/showoff/compiler/form.rb, line 232 def self.form_checked?(modifier) modifier.downcase.include?('x') ? "checked='checked'" : '' end
form_classes(modifier)
click to toggle source
# File lib/showoff/compiler/form.rb, line 224 def self.form_classes(modifier) modifier.downcase! classes = ['response'] classes << 'correct' if modifier.include?('=') classes.join(' ') end
form_element(id, code, name, required, rhs, text)
click to toggle source
Generates markup for any supported form element type
@param id [String]
The HTML ID for the generated markup
@param code [String]
The question code; used for indexing
@param name [String]
The full text of the question
@param required [Boolean]
Whether the rendered element should be marked as required
@param rhs [String]
The right hand side of the question specification, if on one line.
@param text [String]
The full content of the content, used for recursive multiline calls
@return [String]
The HTML markup for all the HTML nodes that the full element renders to.
@see
https://github.com/puppetlabs/showoff/blob/3f43754c84f97be4284bb34f9bc7c42175d45226/lib/showoff.rb#L880-L903
# File lib/showoff/compiler/form.rb, line 89 def self.form_element(id, code, name, required, rhs, text) required = required ? 'required' : '' str = "<div class='form element #{required}' id='#{id}' data-name='#{code}'>" str << "<label class='question' for='#{id}'>#{name}</label>" case rhs when /^\[\s+(\d*)\]$$/ # value = [ 5] (textarea) str << self.form_element_textarea(id, code, $1) when /^___+(?:\[(\d+)\])?$/ # value = ___[50] (text) str << self.form_element_text(id, code, $1) when /^\(.?\)/ # value = (x) option one (=) opt2 () opt3 -> option 3 (radio) str << self.form_element_radio(id, code, rhs.scan(/\((.?)\)\s*([^()]+)\s*/)) when /^\[.?\]/ # value = [x] option one [=] opt2 [] opt3 -> option 3 (checkboxes) str << self.form_element_checkboxes(id, code, rhs.scan(/\[(.?)\] ?([^\[\]]+)/)) when /^\{(.*)\}$/ # value = {BOS, [SFO], (NYC)} (select shorthand) str << self.form_element_select(id, code, rhs.scan(/[(\[]?\w+[)\]]?/)) when /^\{$/ # value = { (select) str << self.form_element_select_multiline(id, code, text) when '' # value = (radio/checkbox list) str << self.form_element_multiline(id, code, text) else Showoff::Logger.warn "Unmatched form element: #{rhs}" end str << '</div>' end
form_element_check_or_radio(type, id, code, value, label, modifier)
click to toggle source
# File lib/showoff/compiler/form.rb, line 214 def self.form_element_check_or_radio(type, id, code, value, label, modifier) # yes, value and id are conflated, because this is the id of the parent widget checked = self.form_checked?(modifier) classes = self.form_classes(modifier) name = (type == 'checkbox') ? "#{code}[]" : code str = "<input type='#{type}' name='#{name}' id='#{id}_#{value}' value='#{value}' class='#{classes}' #{checked} />" str << "<label for='#{id}_#{value}' class='#{classes}'>#{label}</label>" end
form_element_check_or_radio_set(type, id, code, items)
click to toggle source
# File lib/showoff/compiler/form.rb, line 197 def self.form_element_check_or_radio_set(type, id, code, items) str = '' items.each do |item| modifier = item[0] if item[1] =~ /^(\w*) -> (.*)$/ value = $1 label = $2 else value = label = item[1].strip end str << self.form_element_check_or_radio(type, id, code, value, label, modifier) end str end
form_element_checkboxes(id, code, items)
click to toggle source
# File lib/showoff/compiler/form.rb, line 127 def self.form_element_checkboxes(id, code, items) self.form_element_check_or_radio_set('checkbox', id, code, items) end
form_element_multiline(id, code, text)
click to toggle source
# File lib/showoff/compiler/form.rb, line 173 def self.form_element_multiline(id, code, text) str = '<ul>' text.split("\n")[1..-1].each do |item| case item when /\((.?)\)\s*(\w+)\s*(?:->\s*(.*)?)?/ modifier = $1 type = 'radio' value = $2 label = $3 || $2 when /\[(.?)\]\s*(\w+)\s*(?:->\s*(.*)?)?/ modifier = $1 type = 'checkbox' value = $2 label = $3 || $2 end str << '<li>' str << self.form_element_check_or_radio(type, id, code, value, label, modifier) str << '</li>' end str << '</ul>' end
form_element_radio(id, code, items)
click to toggle source
# File lib/showoff/compiler/form.rb, line 123 def self.form_element_radio(id, code, items) self.form_element_check_or_radio_set('radio', id, code, items) end
form_element_select(id, code, items)
click to toggle source
# File lib/showoff/compiler/form.rb, line 131 def self.form_element_select(id, code, items) str = "<select id='#{id}_response' name='#{code}'>" str << '<option value="">----</option>' items.each do |item| selected = classes = '' case item when /\((\w+)\)/ item = $1 selected = 'selected' when /\[(\w+)\]/ item = $1 classes = 'correct' end str << "<option value='#{item}' class='#{classes}' #{selected}>#{item}</option>" end str << '</select>' end
form_element_select_multiline(id, code, text)
click to toggle source
# File lib/showoff/compiler/form.rb, line 150 def self.form_element_select_multiline(id, code, text) str = "<select id='#{id}_response' name='#{code}'>" str << '<option value="">----</option>' text.split("\n")[1..-1].each do |item| case item when /^ +\((\w+) -> (.+)\),?$/ # (NYC -> New York City) str << "<option value='#{$1}' selected>#{$2}</option>" when /^ +\[(\w+) -> (.+)\],?$/ # [NYC -> New York City] str << "<option value='#{$1}' class='correct'>#{$2}</option>" when /^ +(\w+) -> (.+),?$/ # NYC -> New, York City str << "<option value='#{$1}'>#{$2}</option>" when /^ +\((.+)\)$/ # (Boston) str << "<option value='#{$1}' selected>#{$1}</option>" when /^ +\[(.+)\]$/ # [Boston] str << "<option value='#{$1}' class='correct'>#{$1}</option>" when /^ +([^\(].+[^\),]),?$/ # Boston str << "<option value='#{$1}'>#{$1}</option>" end end str << '</select>' end
form_element_text(id, code, length)
click to toggle source
# File lib/showoff/compiler/form.rb, line 114 def self.form_element_text(id, code, length) "<input type='text' id='#{id}_response' name='#{code}' size='#{length}' />" end
form_element_textarea(id, code, rows)
click to toggle source
# File lib/showoff/compiler/form.rb, line 118 def self.form_element_textarea(id, code, rows) rows = 3 if rows.empty? "<textarea id='#{id}_response' name='#{code}' rows='#{rows}'></textarea>" end
render!(doc, options={})
click to toggle source
Add the form markup to the slide and then render all elements
@todo UI elements to translate once i18n is baked in. @todo Someday this should be rearchitected into the markdown renderer.
@return [Nokogiri::HTML::DocumentFragment]
The slide DOM with all form elements rendered.
@see
https://github.com/puppetlabs/showoff/blob/3f43754c84f97be4284bb34f9bc7c42175d45226/lib/showoff.rb#L849-L878
# File lib/showoff/compiler/form.rb, line 16 def self.render!(doc, options={}) title = options[:form] return unless title begin tools = Nokogiri::XML::Node.new('div', doc) tools.add_class('tools') doc.add_child(tools) button = Nokogiri::XML::Node.new('input', doc) button.add_class('display') button.set_attribute('type', 'button') button.set_attribute('value', I18n.t('forms.display')) tools.add_child(button) submit = Nokogiri::XML::Node.new('input', doc) submit.add_class('save') submit.set_attribute('type', 'submit') submit.set_attribute('value', I18n.t('forms.save')) submit.set_attribute('disabled', 'disabled') tools.add_child(submit) form = Nokogiri::XML::Node.new('form', doc) form.set_attribute('id', title) form.set_attribute('action', "form/#{title}") form.set_attribute('method', 'POST') doc.add_child(form) doc.children.each do |elem| next if elem == form elem.parent = form end doc.css('p').each do |p| if p.text =~ /^(\w*) ?(?:->)? ?(.*)? (\*?)= ?(.*)?$/ code = $1 id = "#{title}_#{code}" name = $2.empty? ? code : $2 required = ! $3.empty? rhs = $4 p.replace self.form_element(id, code, name, required, rhs, p.text) end end rescue Exception => e Showoff::Logger.warn "Form parsing failed: #{e.message}" Showoff::Logger.debug "Backtrace:\n\t#{e.backtrace.join("\n\t")}" end doc end