Class: AspaceFormHelper::FormContext

Inherits:
Object
  • Object
show all
Defined in:
frontend/app/helpers/aspace_form_helper.rb

Direct Known Subclasses

ReadOnlyContext

Defined Under Namespace

Classes: BaseDefinition, JSONModelDefinition, ReadOnlyContext

Constant Summary

PROPERTIES_TO_EXCLUDE_FROM_READ_ONLY_VIEW =
["jsonmodel_type", "lock_version", "_resolved", "uri", "ref", "create_time", "system_mtime", "user_mtime", "created_by", "last_modified_by", "sort_name_auto_generate", "suppressed", "display_string", "file_uri"]

Instance Method Summary (collapse)

Constructor Details

- (FormContext) initialize(name, values_from, parent)

Returns a new instance of FormContext



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'frontend/app/helpers/aspace_form_helper.rb', line 9

def initialize(name, values_from, parent)

  values = values_from.is_a?(JSONModelType) ? values_from.to_hash(:raw) : values_from

  @forms = Object.new
  @parent = parent
  @context = [[name, values]]
  @path_to_i18n_map = {}

  class << @forms
    include ActionView::Helpers::TagHelper
    include ActionView::Helpers::TextHelper
    include ActionView::Helpers::FormTagHelper
    include ActionView::Helpers::FormOptionsHelper
  end

end

Instance Method Details

- (Object) [](key)



153
154
155
# File 'frontend/app/helpers/aspace_form_helper.rb', line 153

def [](key)
  obj[key]
end

- (Object) allowable_types_for(name)



420
421
422
423
424
425
426
# File 'frontend/app/helpers/aspace_form_helper.rb', line 420

def allowable_types_for(name)
  if @active_template && @parent.templates[@active_template]
    @parent.templates[@active_template][:definition].allowable_types_for(name)
  else
    []
  end
end

- (Object) checkbox(name, opts = {}, default = true, force_checked = false)



394
395
396
397
398
399
# File 'frontend/app/helpers/aspace_form_helper.rb', line 394

def checkbox(name, opts = {}, default = true, force_checked = false)
  options = {:id => "#{id_for(name)}", :type => "checkbox", :name => path(name), :value => 1}
  options[:checked] = "checked" if force_checked or (obj[name] === true) or (obj[name] === "true") or (obj[name].nil? and default)

  @forms.tag("input", options.merge(opts), false, false)
end

- (Object) clean_mixed_content(content, root_url)



33
34
35
36
37
38
# File 'frontend/app/helpers/aspace_form_helper.rb', line 33

def clean_mixed_content(content, root_url)
  content = content.to_s
  return content if content.blank?

  MixedContentParser::parse(content, root_url, { :wrap_blocks => false } ).to_s.html_safe
end

- (Object) combobox(name, options, opts = {})



271
272
273
# File 'frontend/app/helpers/aspace_form_helper.rb', line 271

def combobox(name, options, opts = {})
  select(name, options, opts.merge({:"data-combobox" => true}))
end

- (Object) current_context



143
144
145
# File 'frontend/app/helpers/aspace_form_helper.rb', line 143

def current_context
  @context.last
end

- (Object) current_id



195
196
197
# File 'frontend/app/helpers/aspace_form_helper.rb', line 195

def current_id
  path(nil).gsub(/[\[\]]/, '_')
end

- (Object) default_for(name)



411
412
413
414
415
416
417
# File 'frontend/app/helpers/aspace_form_helper.rb', line 411

def default_for(name)
  if @active_template && @parent.templates[@active_template]
    @parent.templates[@active_template][:definition].default_for(name)
  else
    nil
  end
end

- (Object) define_template(name, definition = nil, &block)



709
710
711
712
713
714
715
# File 'frontend/app/helpers/aspace_form_helper.rb', line 709

def define_template(name, definition = nil, &block)
  @templates ||= {}
  @templates[name] = {
    :block => block,
    :definition => (definition || BaseDefinition.new),
  }
end

- (Object) emit_template(name, *args)



349
350
351
352
353
354
355
356
357
358
359
# File 'frontend/app/helpers/aspace_form_helper.rb', line 349

def emit_template(name, *args)
  if !@parent.templates[name]
    raise "No such template: #{name.inspect}"
  end

  old = @active_template
  @active_template = name
  @parent.templates[name][:block].call(self, *args)
  @active_template = old

end

- (Object) error_params(exceptions)



818
819
820
821
822
# File 'frontend/app/helpers/aspace_form_helper.rb', line 818

def error_params(exceptions)
  {
    :"data-form-errors" => (exceptions && exceptions.keys[0])
  }
end

- (Object) exceptions_for_js(exceptions)



176
177
178
179
180
181
182
183
184
185
186
187
# File 'frontend/app/helpers/aspace_form_helper.rb', line 176

def exceptions_for_js(exceptions)
  result = {}
  [:errors, :warnings].each do |condition|
    if exceptions[condition]
      result[condition] = exceptions[condition].keys.map {|property|
        id_for_javascript(property)
      }
    end
  end

  result.to_json.html_safe
end

- (Object) fields_for(object, context_name, &block)



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'frontend/app/helpers/aspace_form_helper.rb', line 77

def fields_for(object, context_name, &block)

  result = ""

  push(context_name, object) do
    result << hidden_input("lock_version", object["lock_version"]) if object
    result << @parent.capture(object, &block)
  end

  ("<div data-name-path=\"#{set_index(self.path(context_name), '${index}')}\" " +
    " data-id-path=\"#{id_for(set_index(self.path(context_name), '${index}'), false)}\" " +
    " class=\"subrecord-form-fields-for\">#{result}</div>").html_safe

end

- (Object) form_context(name, values_from = {}, &body)



542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'frontend/app/helpers/aspace_form_helper.rb', line 542

def form_context(name, values_from = {}, &body)
  context = FormContext.new(name, values_from, self)

  env = self.request.env
  env['form_context_depth'] ||= 0

  # Not feeling great about this, but we render the form twice: the first pass
  # sets up the mapping from form input names to i18n keys, while the second
  # actually uses that map to set the labels correctly.
  env['form_context_depth'] += 1
  capture(context, &body)
  env['form_context_depth'] -= 1

  s = "<div class=\"form-context\" id=\"form_#{name}\">".html_safe
  s << context.hidden_input("lock_version", values_from["lock_version"])

  env['form_context_depth'] += 1
  s << capture(context, &body)
  env['form_context_depth'] -= 1

  if env['form_context_depth'] == 0
    # Only emit the JS templates at the top-level
    s << templates_for_js(values_from["jsonmodel_type"])
  end
  s << "</div>".html_safe

  s
end

- (Object) form_top



93
94
95
# File 'frontend/app/helpers/aspace_form_helper.rb', line 93

def form_top
  @context[0].first
end

- (Object) h(str)



28
29
30
# File 'frontend/app/helpers/aspace_form_helper.rb', line 28

def h(str)
  ERB::Util.html_escape(str)
end

- (Object) help_path_for(name)



131
132
133
134
135
# File 'frontend/app/helpers/aspace_form_helper.rb', line 131

def help_path_for(name)
  names = @context.map(&:first)
  return "#{names[-1].to_s.gsub(/\[.*\]/, "").singularize}_#{name}" if names.length > 0
  name
end

- (Object) hidden_input(name, value = nil, field_opts = {})



335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'frontend/app/helpers/aspace_form_helper.rb', line 335

def hidden_input(name, value = nil, field_opts = {})
  value = obj[name] if value.nil?

  full_name = path(name)

  if value && value.is_a?(Hash) && value.has_key?('ref')
    full_name += '[ref]'
    value = value['ref']
  end

  @forms.tag("input", {:id => id_for(name), :type => "hidden", :value => h(value), :name => full_name}.merge(field_opts),
             false, false)
end

- (Object) i18n_for(name)



166
167
168
# File 'frontend/app/helpers/aspace_form_helper.rb', line 166

def i18n_for(name)
  "#{@active_template or form_top}.#{name.to_s.gsub(/\[\]$/, "")}"
end

- (Object) id



98
99
100
# File 'frontend/app/helpers/aspace_form_helper.rb', line 98

def id
  "form_#{form_top}"
end

- (Object) id_for(name, qualify = true)



199
200
201
202
203
# File 'frontend/app/helpers/aspace_form_helper.rb', line 199

def id_for(name, qualify = true)
  name = path(name) if qualify

  name.gsub(/[\[\]]/, '_')
end

- (Object) id_for_javascript(name)



190
191
192
# File 'frontend/app/helpers/aspace_form_helper.rb', line 190

def id_for_javascript(name)
  "#{form_top}#{name.split("/").collect{|a| "[#{a}]"}.join}".gsub(/[\[\]\/]/, "_")
end

- (Object) jsonmodel_definition(type, root = nil)



585
586
587
# File 'frontend/app/helpers/aspace_form_helper.rb', line 585

def jsonmodel_definition(type, root = nil)
  JSONModelDefinition.new(JSONModel(type), root)
end

- (Object) label(name, opts = {}, classes = [])



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'frontend/app/helpers/aspace_form_helper.rb', line 371

def label(name, opts = {}, classes = [])
  prefix = '' 
  prefix << "#{opts[:contextual]}." if opts[:contextual] 
  prefix << 'plugins.' if opts[:plugin]

  classes << 'control-label'

  options = {:class => classes.join(' '), :for => id_for(name)}

  tooltip = I18n.t_raw("#{prefix}#{i18n_for(name)}_tooltip", :default => '')
  if not tooltip.empty?
    options[:title] = tooltip
    options["data-placement"] = "bottom"
    options["data-html"] = true
    options["data-delay"] = 500
    options["data-trigger"] = "manual"
    options["data-template"] = '<div class="tooltip archivesspace-help"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
    options[:class] += " has-tooltip"
  end

  @forms.(:label, I18n.t(prefix + i18n_for(name)), options.merge(opts || {}))
end

- (Object) label_and_boolean(name, opts = {}, default = false, force_checked = false)



251
252
253
254
255
# File 'frontend/app/helpers/aspace_form_helper.rb', line 251

def label_and_boolean(name, opts = {}, default = false, force_checked = false)
  opts[:col_size] = 1
  opts[:controls_class] = "checkbox"
  label_with_field(name, checkbox(name, opts, default, force_checked), opts)
end

- (Object) label_and_date(name, opts = {})



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'frontend/app/helpers/aspace_form_helper.rb', line 209

def label_and_date(name, opts = {})
  field_opts = (opts[:field_opts] || {}).merge({
      :class => "date-field form-control",
      :"data-format" => "yyyy-mm-dd",
      :"data-date" => Date.today.strftime('%Y-%m-%d'),
      :"data-autoclose" => true,
      :"data-force-parse" => false
  })

  if obj[name].blank? && opts[:default]
    value = opts[:default]
  else
    value = obj[name]
  end

  opts[:col_size] = 4

  date_input = textfield(name, value, field_opts)

  label_with_field(name, date_input, opts)
end

- (Object) label_and_fourpartid



361
362
363
364
365
366
367
368
# File 'frontend/app/helpers/aspace_form_helper.rb', line 361

def label_and_fourpartid
  field_html =  textfield("id_0", obj["id_0"], :class => "id_0 form-control", :size => 10)
  field_html << textfield("id_1", obj["id_1"], :class => "id_1 form-control", :size => 10, :disabled => obj["id_0"].blank? && obj["id_1"].blank?)
  field_html << textfield("id_2", obj["id_2"], :class => "id_2 form-control", :size => 10, :disabled => obj["id_1"].blank? && obj["id_2"].blank?)
  field_html << textfield("id_3", obj["id_3"], :class => "id_3 form-control", :size => 10, :disabled => obj["id_2"].blank? && obj["id_3"].blank?)
  @forms.(:div, (I18n.t(i18n_for("id_0")) + field_html).html_safe, :class=> "identifier-fields")
  label_with_field("id_0", field_html, :control_class => "identifier-fields")
end

- (Object) label_and_password(name, opts = {})



246
247
248
# File 'frontend/app/helpers/aspace_form_helper.rb', line 246

def label_and_password(name, opts = {})
  label_with_field(name, password(name, obj[name], opts[:field_opts] || {}), opts)
end

- (Object) label_and_readonly(name, default = "", opts = {})



258
259
260
261
262
263
264
265
266
267
268
# File 'frontend/app/helpers/aspace_form_helper.rb', line 258

def label_and_readonly(name, default = "", opts = {})
  value = obj[name]

  if opts.has_key? :controls_class
    opts[:controls_class] << " label-only"
  else
    opts[:controls_class] = " label-only"
  end

  label_with_field(name, value.blank? ? default : value , opts)
end

- (Object) label_and_select(name, options, opts = {})



236
237
238
239
240
241
242
243
# File 'frontend/app/helpers/aspace_form_helper.rb', line 236

def label_and_select(name, options, opts = {})
  options = ([""] + options) if opts[:nodefault]
  opts[:field_opts] ||= {}

  opts[:col_size] = 4
  widget = options.length < COMBOBOX_MIN_LIMIT ? select(name, options, opts[:field_opts] || {}) : combobox(name, options, opts[:field_opts] || {})
  label_with_field(name, widget, opts)
end

- (Object) label_and_textarea(name, opts = {})



231
232
233
# File 'frontend/app/helpers/aspace_form_helper.rb', line 231

def label_and_textarea(name, opts = {})
  label_with_field(name, textarea(name, obj[name] || opts[:default], opts[:field_opts] || {}), opts)
end

- (Object) label_and_textfield(name, opts = {})



205
206
207
# File 'frontend/app/helpers/aspace_form_helper.rb', line 205

def label_and_textfield(name, opts = {})
  label_with_field(name, textfield(name, obj[name], opts[:field_opts] || {}), opts)
end

- (Object) label_with_field(name, field_html, opts = {})



438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'frontend/app/helpers/aspace_form_helper.rb', line 438

def label_with_field(name, field_html, opts = {})
  opts[:label_opts] ||= {}
  opts[:label_opts][:plugin] = opts[:plugin]
  opts[:col_size] ||= 9

  control_group_classes,
  label_classes,
  controls_classes = %w(form-group), [], []

  unless opts[:layout] && opts[:layout] == 'stacked'
    label_classes << 'col-sm-2'
    controls_classes << "col-sm-#{opts[:col_size]}"
  end
  # There must be a better way to say this...
  # The value of the 'required' option wins out if set to either true or false
  # if not specified, we take the value of required?
  required = [:required, 'required'].map {|r| opts[r]}.compact.first
  if required.nil?
    required = required?(name)
  end

  control_group_classes << "required" if required == true
  control_group_classes << "conditionally-required" if required == :conditionally

  control_group_classes << "#{opts[:control_class]}" if opts.has_key? :control_class
  controls_classes << "#{opts[:controls_class]}" if opts.has_key? :controls_class

  control_group = "<div class=\"#{control_group_classes.join(' ')}\">"
  control_group << label(name, opts[:label_opts], label_classes)
  control_group << "<div class=\"#{controls_classes.join(' ')}\">"
  control_group << field_html
  control_group << "</div>"
  control_group << "</div>"
  control_group.html_safe
end

- (Object) list_for(objects, context_name, &block)



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'frontend/app/helpers/aspace_form_helper.rb', line 56

def list_for(objects, context_name, &block)

  objects ||= []
  result = ""

  objects.each_with_index do |object, idx|
    push(set_index(context_name, idx), object) do
      result << "<li id=\"#{current_id}\" class=\"subrecord-form-wrapper\" data-index=\"#{idx}\" data-object-name=\"#{context_name.gsub(/\[\]/,"").singularize}\">"
      result << hidden_input("lock_version") if obj.respond_to?(:has_key?) && obj.has_key?("lock_version")
      result << @parent.capture(object, idx,  &block)
      result << "</li>"
    end
  end

  ("<ul data-name-path=\"#{set_index(self.path(context_name), '${index}')}\" " +
   " data-id-path=\"#{id_for(set_index(self.path(context_name), '${index}'), false)}\" " +
   " class=\"subrecord-form-list\">#{result}</ul>").html_safe

end

- (Object) name_to_json_path(name)

Turn a name like my[nested][object][0][title] into the equivalent JSON path (my/nested/object/0/title)



105
106
107
# File 'frontend/app/helpers/aspace_form_helper.rb', line 105

def name_to_json_path(name)
  name.gsub(/[\[\]]+/, "/").gsub(/\/+$/, "").gsub(/^\/+/, "")
end

- (Object) obj



148
149
150
# File 'frontend/app/helpers/aspace_form_helper.rb', line 148

def obj
  @context.last.second
end

- (Object) parent_context



138
139
140
# File 'frontend/app/helpers/aspace_form_helper.rb', line 138

def parent_context
  form_top
end

- (Object) password(name = nil, value = "", opts = {})



330
331
332
333
# File 'frontend/app/helpers/aspace_form_helper.rb', line 330

def password(name = nil, value = "", opts =  {})
  @forms.tag("input", {:id => id_for(name), :type => "password", :value => h(value), :name => path(name)}.merge(opts),
             false, false)
end

- (Object) path(name = nil)



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'frontend/app/helpers/aspace_form_helper.rb', line 110

def path(name = nil)
  names = @context.map(&:first)
  tail = names.drop(1)
  tail += [name] if name

  path = tail.map {|e|
    if e =~ /(.*?)\[([0-9]+)?\]$/
      "[#{$1}][#{$2}]"
    else
      "[#{e}]"
    end
  }.join("")

  if name
    @path_to_i18n_map[name_to_json_path(path)] = i18n_for(name)
  end

  "#{names.first}#{path}"
end

- (Object) path_to_i18n_key(path)



171
172
173
# File 'frontend/app/helpers/aspace_form_helper.rb', line 171

def path_to_i18n_key(path)
  path_to_i18n_map[path]
end

- (Object) path_to_i18n_map



46
47
48
# File 'frontend/app/helpers/aspace_form_helper.rb', line 46

def path_to_i18n_map
  @path_to_i18n_map
end

- (Object) possible_options_for(name, add_empty_options = false, opts = {})



429
430
431
432
433
434
435
# File 'frontend/app/helpers/aspace_form_helper.rb', line 429

def possible_options_for(name, add_empty_options = false, opts = {})
  if @active_template && @parent.templates[@active_template]
    @parent.templates[@active_template][:definition].options_for(self, name, add_empty_options, opts)
  else
    []
  end
end

- (Object) preserve_newlines(string)



802
803
804
# File 'frontend/app/helpers/aspace_form_helper.rb', line 802

def preserve_newlines(string)
  string.gsub(/\n/, '<br>')
end

- (Object) push(name, values_from = {}) {|_self| ... }

Yields:

  • (_self)

Yield Parameters:



158
159
160
161
162
163
# File 'frontend/app/helpers/aspace_form_helper.rb', line 158

def push(name, values_from = {})
  path(name) # populate the i18n mapping
  @context.push([name, values_from])
  yield(self)
  @context.pop
end

- (Object) read_only_view(hash, opts = {})



764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'frontend/app/helpers/aspace_form_helper.rb', line 764

def read_only_view(hash, opts = {})
  jsonmodel_type = hash["jsonmodel_type"]
  schema = JSONModel(jsonmodel_type).schema
  prefix = opts[:plugin] ? 'plugins.' : ''
  html = "<div class='form-horizontal'>"

  hash.reject {|k,v| PROPERTIES_TO_EXCLUDE_FROM_READ_ONLY_VIEW.include?(k)}.each do |property, value|

    if schema and schema["properties"].has_key?(property)
      if (schema["properties"][property].has_key?('dynamic_enum'))
        value = I18n.t({:enumeration => schema["properties"][property]["dynamic_enum"], :value => value}, :default => value)
      elsif schema["properties"][property].has_key?("enum")
        value = I18n.t("#{prefix}#{jsonmodel_type.to_s}.#{property}_#{value}", :default => value)
      elsif schema["properties"][property]["type"] === "boolean"
        value = value === true ? "True" : "False"
      elsif schema["properties"][property]["type"] === "date"
        value = value.blank? ? "" : Date.strptime(value, "%Y-%m-%d")
      elsif schema["properties"][property]["type"] === "array"
        # this view doesn't support arrays
        next
      elsif value.kind_of? Hash
        # can't display an object either
        next
      end
    end

    html << "<div class='form-group'>"
    html << "<div class='control-label col-sm-2'>#{I18n.t("#{prefix}#{jsonmodel_type.to_s}.#{property}")}</div>"
    html << "<div class='label-only col-sm-8'>#{value}</div>"
    html << "</div>"

  end

  html << "</div>"

  html.html_safe
end

- (Boolean) readonly?

Returns:

  • (Boolean)


41
42
43
# File 'frontend/app/helpers/aspace_form_helper.rb', line 41

def readonly?
  false
end

- (Object) readonly_context(name, values_from = {}, &body)



747
748
749
750
751
752
753
754
755
756
757
758
759
760
# File 'frontend/app/helpers/aspace_form_helper.rb', line 747

def readonly_context(name, values_from = {}, &body)
  context = ReadOnlyContext.new(name, values_from, self)

  # Not feeling great about this, but we render the form twice: the first pass
  # sets up the mapping from form input names to i18n keys, while the second
  # actually uses that map to set the labels correctly.
  capture(context, &body)

  s = "<div class=\"readonly-context form-horizontal\">".html_safe
  s << capture(context, &body)
  s << "</div>".html_safe

  s
end

- (Boolean) required?(name)

Returns:

  • (Boolean)


402
403
404
405
406
407
408
# File 'frontend/app/helpers/aspace_form_helper.rb', line 402

def required?(name)
  if @active_template && @parent.templates[@active_template]
    @parent.templates[@active_template][:definition].required?(name)
  else
    false
  end
end

- (Object) select(name, options, opts = {})



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# File 'frontend/app/helpers/aspace_form_helper.rb', line 276

def select(name, options, opts = {})
    if opts.has_key? :class
      opts[:class] << " form-control"
    else
      opts[:class] = "form-control"
    end

    @forms.select_tag(path(name), @forms.options_for_select(options, obj[name] || default_for(name) || opts[:default]), {:id => id_for(name)}.merge!(opts))
  end


  def textarea(name = nil, value = "", opts =  {})
    options = {:id => id_for(name), :rows => 3}

    placeholder = I18n.t("#{i18n_for(name)}_placeholder", :default => '')
    options[:placeholder] = placeholder if not placeholder.empty?
    options[:class] = "form-control"

    @forms.text_area_tag(path(name), h(value),  options.merge(opts))
  end


  def textfield(name = nil, value = nil, opts =  {})
    value ||= obj[name] if !name.nil?

    options = {:id => id_for(name), :type => "text", :value => h(value), :name => path(name)}

    placeholder = I18n.t("#{i18n_for(name)}_placeholder", :default => '')
    options[:placeholder] = placeholder if not placeholder.empty?
    options[:class] = "form-control"

    value = @forms.tag("input", options.merge(opts),
               false, false)

    if opts[:automatable]
      by_default = default_for("#{name}_auto_generate") || false
      value << "<label>".html_safe
      value << checkbox("#{name}_auto_generate", {
        :class => "automate-field-toggle", :display_text_when_checked => I18n.t("states.auto_generated")
        }, by_default, false)
      value << "&#160;<small>".html_safe
      value << I18n.t("actions.automate")
      value << "</small></label>".html_safe
    end

    inline_help = I18n.t("#{i18n_for(name)}_inline_help", :default => '')
    if !inline_help.empty?
      value << "<span class=\"help-inline\">#{inline_help}</span>".html_safe
    end

    value
  end


  def password(name = nil, value = "", opts =  {})
    @forms.tag("input", {:id => id_for(name), :type => "password", :value => h(value), :name => path(name)}.merge(opts),
               false, false)
  end

  def hidden_input(name, value = nil, field_opts = {})
    value = obj[name] if value.nil?

    full_name = path(name)

    if value && value.is_a?(Hash) && value.has_key?('ref')
      full_name += '[ref]'
      value = value['ref']
    end

    @forms.tag("input", {:id => id_for(name), :type => "hidden", :value => h(value), :name => full_name}.merge(field_opts),
               false, false)
  end

  def emit_template(name, *args)
    if !@parent.templates[name]
      raise "No such template: #{name.inspect}"
    end

    old = @active_template
    @active_template = name
    @parent.templates[name][:block].call(self, *args)
    @active_template = old

  end

  def label_and_fourpartid
    field_html =  textfield("id_0", obj["id_0"], :class => "id_0 form-control", :size => 10)
    field_html << textfield("id_1", obj["id_1"], :class => "id_1 form-control", :size => 10, :disabled => obj["id_0"].blank? && obj["id_1"].blank?)
    field_html << textfield("id_2", obj["id_2"], :class => "id_2 form-control", :size => 10, :disabled => obj["id_1"].blank? && obj["id_2"].blank?)
    field_html << textfield("id_3", obj["id_3"], :class => "id_3 form-control", :size => 10, :disabled => obj["id_2"].blank? && obj["id_3"].blank?)
    @forms.(:div, (I18n.t(i18n_for("id_0")) + field_html).html_safe, :class=> "identifier-fields")
    label_with_field("id_0", field_html, :control_class => "identifier-fields")
  end


  def label(name, opts = {}, classes = [])
    prefix = '' 
    prefix << "#{opts[:contextual]}." if opts[:contextual] 
    prefix << 'plugins.' if opts[:plugin]

    classes << 'control-label'

    options = {:class => classes.join(' '), :for => id_for(name)}

    tooltip = I18n.t_raw("#{prefix}#{i18n_for(name)}_tooltip", :default => '')
    if not tooltip.empty?
      options[:title] = tooltip
      options["data-placement"] = "bottom"
      options["data-html"] = true
      options["data-delay"] = 500
      options["data-trigger"] = "manual"
      options["data-template"] = '<div class="tooltip archivesspace-help"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
      options[:class] += " has-tooltip"
    end

    @forms.(:label, I18n.t(prefix + i18n_for(name)), options.merge(opts || {}))
  end

  def checkbox(name, opts = {}, default = true, force_checked = false)
    options = {:id => "#{id_for(name)}", :type => "checkbox", :name => path(name), :value => 1}
    options[:checked] = "checked" if force_checked or (obj[name] === true) or (obj[name] === "true") or (obj[name].nil? and default)

    @forms.tag("input", options.merge(opts), false, false)
  end


  def required?(name)
    if @active_template && @parent.templates[@active_template]
      @parent.templates[@active_template][:definition].required?(name)
    else
      false
    end
  end


  def default_for(name)
    if @active_template && @parent.templates[@active_template]
      @parent.templates[@active_template][:definition].default_for(name)
    else
      nil
    end
  end


  def allowable_types_for(name)
    if @active_template && @parent.templates[@active_template]
      @parent.templates[@active_template][:definition].allowable_types_for(name)
    else
      []
    end
  end


  def possible_options_for(name, add_empty_options = false, opts = {})
    if @active_template && @parent.templates[@active_template]
      @parent.templates[@active_template][:definition].options_for(self, name, add_empty_options, opts)
    else
      []
    end
  end


  def label_with_field(name, field_html, opts = {})
    opts[:label_opts] ||= {}
    opts[:label_opts][:plugin] = opts[:plugin]
    opts[:col_size] ||= 9

    control_group_classes,
    label_classes,
    controls_classes = %w(form-group), [], []

    unless opts[:layout] && opts[:layout] == 'stacked'
      label_classes << 'col-sm-2'
      controls_classes << "col-sm-#{opts[:col_size]}"
    end
    # There must be a better way to say this...
    # The value of the 'required' option wins out if set to either true or false
    # if not specified, we take the value of required?
    required = [:required, 'required'].map {|r| opts[r]}.compact.first
    if required.nil?
      required = required?(name)
    end

    control_group_classes << "required" if required == true
    control_group_classes << "conditionally-required" if required == :conditionally

    control_group_classes << "#{opts[:control_class]}" if opts.has_key? :control_class
    controls_classes << "#{opts[:controls_class]}" if opts.has_key? :controls_class

    control_group = "<div class=\"#{control_group_classes.join(' ')}\">"
    control_group << label(name, opts[:label_opts], label_classes)
    control_group << "<div class=\"#{controls_classes.join(' ')}\">"
    control_group << field_html
    control_group << "</div>"
    control_group << "</div>"
    control_group.html_safe
  end
end

- (Object) set_index(template, idx)



51
52
53
# File 'frontend/app/helpers/aspace_form_helper.rb', line 51

def set_index(template, idx)
  template.gsub(/\[\]$/, "[#{idx}]")
end

- (Object) templates



572
573
574
575
# File 'frontend/app/helpers/aspace_form_helper.rb', line 572

def templates
  @templates ||= {}
  @templates
end

- (Object) templates_for_js(jsonmodel_type = nil)



718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
# File 'frontend/app/helpers/aspace_form_helper.rb', line 718

def templates_for_js(jsonmodel_type = nil)
  result = ""

  return result if @templates.blank?

  obj = {}
  obj['jsonmodel_type'] = jsonmodel_type if jsonmodel_type

  @templates.each do |name, template|
    context = FormContext.new("${path}", obj, self)

    def context.id_for(name, qualify = true)
      name = path(name) if qualify

      name.gsub(/[\[\]]/, '_').gsub('${path}', '${id_path}')
    end

    context.instance_eval do
      @active_template = name
    end

    result << "<div id=\"template_#{name}\"><!--"
    result << capture(context, &template[:block])
    result << "--></div>"
  end

  result.html_safe
end

- (Object) textarea(name = nil, value = "", opts = {})



287
288
289
290
291
292
293
294
295
# File 'frontend/app/helpers/aspace_form_helper.rb', line 287

def textarea(name = nil, value = "", opts =  {})
  options = {:id => id_for(name), :rows => 3}

  placeholder = I18n.t("#{i18n_for(name)}_placeholder", :default => '')
  options[:placeholder] = placeholder if not placeholder.empty?
  options[:class] = "form-control"

  @forms.text_area_tag(path(name), h(value),  options.merge(opts))
end

- (Object) textfield(name = nil, value = nil, opts = {})



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'frontend/app/helpers/aspace_form_helper.rb', line 298

def textfield(name = nil, value = nil, opts =  {})
  value ||= obj[name] if !name.nil?

  options = {:id => id_for(name), :type => "text", :value => h(value), :name => path(name)}

  placeholder = I18n.t("#{i18n_for(name)}_placeholder", :default => '')
  options[:placeholder] = placeholder if not placeholder.empty?
  options[:class] = "form-control"

  value = @forms.tag("input", options.merge(opts),
             false, false)

  if opts[:automatable]
    by_default = default_for("#{name}_auto_generate") || false
    value << "<label>".html_safe
    value << checkbox("#{name}_auto_generate", {
      :class => "automate-field-toggle", :display_text_when_checked => I18n.t("states.auto_generated")
      }, by_default, false)
    value << "&#160;<small>".html_safe
    value << I18n.t("actions.automate")
    value << "</small></label>".html_safe
  end

  inline_help = I18n.t("#{i18n_for(name)}_inline_help", :default => '')
  if !inline_help.empty?
    value << "<span class=\"help-inline\">#{inline_help}</span>".html_safe
  end

  value
end

- (Object) update_monitor_params(record)



807
808
809
810
811
812
813
814
815
# File 'frontend/app/helpers/aspace_form_helper.rb', line 807

def update_monitor_params(record)
  {
    :"data-update-monitor" => true,
    :"data-update-monitor-url" => url_for(:controller => :update_monitor, :action => :poll),
    :"data-update-monitor-record-uri" => record.uri,
    :"data-update-monitor-record-is-stale" => !!@record_is_stale,
    :"data-update-monitor-lock_version" => record.lock_version
  }
end