Module: JqrHelpers::Helpers

Defined in:
lib/jqr-helpers/helpers.rb

Defined Under Namespace

Classes: PanelRenderer

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._random_stringString

Generate a random string for IDs.

Returns:

  • (String)


446
447
448
# File 'lib/jqr-helpers/helpers.rb', line 446

def self._random_string
  SecureRandom.hex(16)
end

Instance Method Details

#ajax_change(url, options = {}, &block) ⇒ String

Observe a field for changes. On change, post to the Ajax URL and calculate callbacks.

Parameters:

  • url (String)

    the URL to send to.

  • options (Hash) (defaults to: {})

    Ajax options - see above.

Returns:

  • (String)


436
437
438
439
440
441
# File 'lib/jqr-helpers/helpers.rb', line 436

def ajax_change(url, options={}, &block)
  options[:class] = 'ujs-ajax-change'
  options = _process_ajax_options(options)
  options['data-url'] = url
   :span, options, &block
end

#button_to_ajax(body, url, options = {}) ⇒ String

Create a button that fires off a jQuery Ajax request. This does not use button_to, so it can be used inside forms.

Parameters:

  • body (String)

    the text/content that goes inside the tag.

  • url (String)

    the URL to connect to.

  • options (Hash) (defaults to: {})

    Ajax options - see above.

Returns:

  • (String)


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/jqr-helpers/helpers.rb', line 200

def button_to_ajax(body, url, options={})

  # Specifically do not add data-remote
  options[:'data-method'] = options.delete(:method)
  options[:class] ||= ''
  options[:class] << ' ujs-ajax-button'
  options[:type] = 'button'
  options[:'data-url'] = url
  if options.key?(:confirm)
    options[:'data-confirm'] = options.delete(:confirm)
  end
  options.merge!(_process_ajax_options(options))

   :button, body, options
end

#button_to_dialog(dialog_id, html_content, dialog_options = {}, html_options = {}) ⇒ String

Add a button to create a jQuery dialog.

Parameters:

  • dialog_id (String)

    The ID of the element to put in the dialog.

  • html_content (String)

    Text or HTML tags to use as the button body.

  • html_options (Hash) (defaults to: {})

    Attributes to put on the button tag.

  • dialog_options (Hash) (defaults to: {})

    Dialog options as described in the readme.

Returns:

  • (String)


102
103
104
105
106
# File 'lib/jqr-helpers/helpers.rb', line 102

def button_to_dialog(dialog_id, html_content, dialog_options={},
  html_options={})
  link_to_dialog(dialog_id, html_content, dialog_options,
               html_options.merge(:tag_name => 'button', :type => 'button'))
end

#button_to_external(content, url, options = {}) ⇒ Object

This is identical to the built-in Rails button_to() in every way except that it will work inside an existing form. Instead, it appends a form to the body, and uses a click handler to submit it. This does not support the :remote option - instead, use #button_to_ajax. This supports the :target option to pass to the form.

Parameters:

  • content (String)

    the text of the button.

  • url (String|Hash)

    the URL (or URL hash) the button should go to.

  • options (Hash) (defaults to: {})

    HTML Options to pass to the button.



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
# File 'lib/jqr-helpers/helpers.rb', line 376

def button_to_external(content, url, options={})
  options[:disabled] = 'disabled' if options.delete(:disabled)
  method = (options.delete(:method) || 'post').to_s.downcase
  confirm = options.delete(:confirm)
  disable_with = options.delete(:disable_with)

  token_name = token_value = nil
  if %w(post put).include?(method) && protect_against_forgery?
    token_name = request_forgery_protection_token.to_s
    token_value = form_authenticity_token
  end
  url = url_for(url) if url.is_a?(Hash)

  options[:type] = 'button'
  options['data-confirm'] = confirm if confirm
  options['data-disable-with'] = disable_with if disable_with
  options['data-method'] = method if method
  options['data-url'] = url
  options[:'data-target'] = options.delete(:target)
  options[:class] ||= ''
  options[:class] << ' ujs-external-button'
  if token_name
    options['data-token-name'] = token_name
    options['data-token-value'] = token_value
  end

  (:button, content, options)
end

#button_to_remote_dialog(url, html_content, dialog_options = {}, html_options = {}) ⇒ String

Same as button_to_dialog, but loads content from a remote URL instead of using content already on the page.

Parameters:

  • url (String)

    The URL to load the content from.

  • html_content (String)

    Text or HTML tags to use as the button body.

  • dialog_options (Hash) (defaults to: {})

    Dialog options as described in the readme.

  • html_options (Hash) (defaults to: {})

    Attributes to put on the button tag.

Returns:

  • (String)


161
162
163
164
165
# File 'lib/jqr-helpers/helpers.rb', line 161

def button_to_remote_dialog(url, html_content, dialog_options={},
  html_options={})
  link_to_remote_dialog(url, html_content, dialog_options,
               html_options.merge(:tag_name => 'button', :type => 'button'))
end

#button_to_toggle(body, id, options = {}) ⇒ Object

Add a button which toggles the visibility of a separate element.

Parameters:

  • body (String)

    the text for the button.

  • id (String)

    the ID of the element to toggle.

  • options (Hash) (defaults to: {})

    HTML options for the button.



427
428
429
# File 'lib/jqr-helpers/helpers.rb', line 427

def button_to_toggle(body, id, options={})
  link_to_toggle(body, id, options.merge(:tag_name => 'button'))
end

#buttonset(name, values, selected = nil, html_options = {}) ⇒ Object

Print a button set. Each button will be a radio button, and the group will then be passed into jQuery’s buttonset() method.

Parameters:

  • name (String)

    the name of the form element.

  • values (Hash<String, String>)

    a hash of value => label.

  • selected (String) (defaults to: nil)

    the selected value, if any.

  • html_options (Hash) (defaults to: {})

    a set of options that will be passed into the parent div tag. Special option is :input_id, which will be appended to both label and radio button to avoid having the same ID on different buttons (e.g. when displaying multiple times for different objects), which would cause the buttonset not to work.



322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/jqr-helpers/helpers.rb', line 322

def buttonset(name, values, selected=nil, html_options={})
  html_options[:class] ||= ''
  html_options[:class] << ' ujs-button-set'
  given_id = html_options.delete(:input_id)
  content = values.inject('') do |sum, (value, label)|
    id = "#{sanitize_to_id(name)}_#{sanitize_to_id(value)}"
    id << "_#{given_id}" if given_id
    sum += radio_button_tag(name, value, selected == value, :id => id) +
      label_tag(id, label)
  end
  (:div, raw(content), html_options)
end

#confirm_button(html_content, url, message, html_options = {}) ⇒ Object

Create a button that prompts a jQuery confirm dialog, which is nicer-looking than the default window.confirm() which is used by Rails. Done using button_to, so note that a form element will be added.

Parameters:

  • html_content (String)

    the text or content to go inside the button

  • url (String)

    the URL which the button should go to if confirmed

  • message (String)

    the confirm message to prompt

  • html_options (Hash) (defaults to: {})

    HTML attributes.



115
116
117
118
119
120
# File 'lib/jqr-helpers/helpers.rb', line 115

def confirm_button(html_content, url, message, html_options={})
  button_to html_content, url, html_options.merge(
    :'data-message' => simple_format(message), # turn text into HTML
    :'data-ujs-confirm' => true
  )
end

#date_picker_tag(name, value = Date.today, options = {}, html_options = {}) ⇒ String

Create a date picker field. The attributes given are passed to text_field_tag. There is a special option :format - this expects a Ruby style date format. It will format both the initial display of the date and the jQuery date format to be the same.

Parameters:

  • name (String)

    the name of the form element.

  • value (Date) (defaults to: Date.today)

    the initial value.

  • options (Hash) (defaults to: {})

    options to be passed to datepicker().

  • html_options (Hash) (defaults to: {})

    options to be passed to text_field_tag.

Returns:

  • (String)


299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/jqr-helpers/helpers.rb', line 299

def date_picker_tag(name, value=Date.today, options={}, html_options={})
  format = options.delete(:format) || '%Y-%m-%d'
  if value.present?
    value = Date.parse(value) if value.is_a?(String)
    value = value.strftime(format)
  end
  options[:dateFormat] = _map_date(format)
  html_options[:'data-date-options'] = options.to_json
  html_options[:class] ||= ''
  html_options[:class] << ' ujs-date-picker'
  text_field_tag(name, value, html_options)
end

#dialog_title(content) ⇒ Object

Set the dialog title from inside the dialog itself. This prints a hidden div which is read by the UJS callback to set the title.



169
170
171
# File 'lib/jqr-helpers/helpers.rb', line 169

def dialog_title(content)
   :div, content, :class => 'ujs-dialog-title-hidden'
end

#form_for_ajax(record, options = {}, &block) ⇒ String

Identical to form_tag_ajax except that this passes the given model into form_for instead of form_tag.

Parameters:

  • record (ActiveRecord::Base)
  • options (Hash) (defaults to: {})

Returns:

  • (String)


237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/jqr-helpers/helpers.rb', line 237

def form_for_ajax(record, options={}, &block)
  options[:remote] = true
  # note that we only override if nil - not false
  options[:close_dialog] = true if options[:close_dialog].nil?
  options[:use_dialog_opener] = true if options[:use_dialog_opener].nil?
  options[:html] ||= {}
  orig_class = options[:html][:class]
  options[:html].merge!(_process_ajax_options(options))
  options[:html][:class] << " #{orig_class}"

  form_for record, options, &block

end

#form_tag_ajax(url, options = {}, &block) ⇒ String

Create a form tag that submits to an Ajax request. Basically a wrapper for form_tag with :remote => true.

Parameters:

  • url (String)

    the URL to connect to.

  • options (Hash) (defaults to: {})

    Ajax options - see above.

Returns:

  • (String)


221
222
223
224
225
226
227
228
229
230
# File 'lib/jqr-helpers/helpers.rb', line 221

def form_tag_ajax(url, options={}, &block)

  options[:remote] = true
  # note that we only override if nil - not false
  options[:close_dialog] = true if options[:close_dialog].nil?
  options[:use_dialog_opener] = true if options[:use_dialog_opener].nil?
  options.merge!(_process_ajax_options(options))

  form_tag url, options, &block
end

Create a link that fires off a jQuery Ajax request. This is basically a wrapper around link_to :remote => true. If a block is given, url and options will be shifted left by 1 position and the block contents will be used for the body.

Parameters:

  • body (String)

    the text/content that goes inside the tag.

  • url (String)

    the URL to connect to.

  • options (Hash) (defaults to: {})

    Ajax options - see above.

Returns:

  • (String)


181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/jqr-helpers/helpers.rb', line 181

def link_to_ajax(body, url, options={}, &block)
  if block_given?
    options = url
    url = body
    body = capture(&block)
  end

  options[:remote] = true
  options.merge!(_process_ajax_options(options))

  link_to body, url, options
end

Add a link to create a jQuery dialog. If a block is given, dialog_options and html_options are shifted left by 1 and the block is used as the html_content.

Parameters:

  • dialog_id (String)

    The ID of the element to put in the dialog.

  • html_content (String) (defaults to: '')

    Text or HTML tags to use as the link body.

  • dialog_options (Hash) (defaults to: {})

    Dialog options as described in the readme.

  • html_options (Hash) (defaults to: {})

    Attributes to put on the link tag. There is a special :tag_name option that can be used to change the tag being created. Default is :a, but you can pass :div, :span, etc.

Returns:

  • (String)


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
# File 'lib/jqr-helpers/helpers.rb', line 58

def link_to_dialog(dialog_id, html_content='', dialog_options={},
  html_options={}, &block)

  if block_given?
    html_options = dialog_options
    dialog_options = html_content.presence || {}
    html_content = capture(&block)
  end

  html_options[:class] ||= ''
  html_options[:class] << ' ujs-dialog'
  html_options[:'data-dialog-id'] = dialog_id
  html_options[:'data-close-x'] = dialog_options[:close_x]

  tag_name = html_options.delete(:tag_name) || :a
  html_options[:href] ||= '#' if tag_name == :a

  dialog_options[:dialogClass] ||= ''
  if dialog_options[:title] == false # not nil or blank
    dialog_options[:dialogClass] << ' ujs-dialog-modal no-title'
  else
    dialog_options[:title] ||= 'Dialog'
    dialog_options[:dialogClass] << ' ujs-dialog-modal'
  end
  dialog_options[:modal] = true
  dialog_options[:width] ||= 'auto'
  if dialog_options.delete(:default_buttons)
    dialog_options[:buttons] = {
      :OK => 'submit',
      :Cancel => 'close'
    }
  end

  html_options[:'data-dialog-options'] = dialog_options.to_json

   tag_name, html_content, html_options
end

Same as link_to_dialog, but loads content from a remote URL instead of using content already on the page. If a block is given, dialog_options and html_options are shifted left by 1 and the block is used as the html_content. Note that this method should only be used if the URL being linked to is valid to display by itself (i.e. the user can copy/paste it or open it in a new tab). If it is only viewable in a partial, you should be using button_to_remote_dialog.

Parameters:

  • url (String)

    The URL to load the content from.

  • html_content (String)

    Text or HTML tags to use as the link body.

  • dialog_options (Hash) (defaults to: {})

    Dialog options as described in the readme.

  • html_options (Hash) (defaults to: {})

    Attributes to put on the link tag. There is a special :tag_name option that can be used to change the tag being created. Default is :a, but you can pass :div, :span, etc.

Returns:

  • (String)


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/jqr-helpers/helpers.rb', line 137

def link_to_remote_dialog(url, html_content, dialog_options={},
  html_options={}, &block)

  if block_given?
    html_options = dialog_options
    dialog_options = html_content
    html_content = capture(&block)
  end
  html_options[:href] = url
  html_options[:'data-throbber'] =
    dialog_options.delete(:throbber) || 'large'

  html_options[:'data-dialog-url'] = url
  link_to_dialog(Helpers._random_string, html_content,
                 dialog_options, html_options)
end

Add a link which toggles the visibility of a separate element. The link element itself will be given the class “ujs-toggle-open” and “ujs-toggle-closed” so you can style it.

Parameters:

  • body (String)

    the text for the link.

  • id (String)

    the ID of the element to toggle.

  • options (Hash) (defaults to: {})

    HTML options for the link. An extra option is start_open which indicates that the content to toggle is already visible.



413
414
415
416
417
418
419
420
421
# File 'lib/jqr-helpers/helpers.rb', line 413

def link_to_toggle(body, id, options={})
  tag_name = options.delete(:tag_name) || :a
  options[:class] ||= ''
  options[:class] << ' ujs-toggle'
  options[:class] << (options.delete(:start_open) ?
    ' ujs-toggle-open' :
    ' ujs-toggle-closed')
   tag_name, body, options.merge(:'data-id' => id)
end

#quick_radio_set(name, values, selected = nil, html_options = {}) ⇒ Object

Prints a button set which pretends to be a jQuery buttonset() and is specifically for radio buttons. The main difference is that this will load much faster in DOM-heavy pages (e.g. in tables where you may have hundreds of buttons) and it does not have most of the frills of jQuery button(), such as allowing disabling.

Parameters:

  • name (String)

    the name of the form element.

  • values (Hash<String, String>)

    a hash of value => label.

  • selected (String) (defaults to: nil)

    the selected value, if any.

  • html_options (Hash) (defaults to: {})

    a set of options that will be passed into the parent div tag.



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/jqr-helpers/helpers.rb', line 345

def quick_radio_set(name, values, selected=nil, html_options={})
  html_options[:class] ||= ''
  html_options[:class] << ' ujs-quick-buttonset ui-buttonset'
  html_options[:autocomplete] = 'off'
  content = ''
  last_key = values.keys.length - 1
  values.each_with_index do |(value, label), i|
    content << radio_button_tag(name, value, selected == value,
                            :class => 'ui-helper-hidden-accessible')
    label_class = 'ui-button ui-widget ui-state-default ui-button-text-only'
    label_class << ' ui-state-active' if selected == value
    label_class << ' ui-corner-left' if i == 0
    label_class << ' ui-corner-right' if i == last_key
    content << label_tag("#{name}_#{value}", :class => label_class,
                         :role => 'button',
                         :'aria-disabled' => 'false') do
       :span, label, :class => 'ui-button-text'
    end
  end
  (:div, raw(content), html_options)

end

#tab_container(options = {}, html_options = {}, &block) ⇒ Object

Print a tab container. This expects a block, which will be passed a PanelRenderer object. Panels can be local (with content) or remote (with a URL).

Examples:

<%= tab_container {:collapsible => true}, {:class => 'my-tabs}' do |r| %>
  <% r.panel 'Tab 1' do %>
    My tab content here
  <% end %>
  <% r.panel 'Tab 2', 'http://www.foobar.com/' %>
<% end %>

Parameters:

  • options (Hash) (defaults to: {})

    options to pass to the jQuery tabs() method.

  • html_options (Hash) (defaults to: {})

    options to pass to the tab container element itself.



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/jqr-helpers/helpers.rb', line 264

def tab_container(options={}, html_options={}, &block)
  renderer = PanelRenderer.new
  capture(renderer, &block)
  html_options[:class] ||= ''
  html_options[:class] << ' ujs-tab-container'
  html_options[:'data-tab-options'] = options.to_json
  (:div, html_options) do
    s =  :ul do
      s2 = ''
      renderer.panels.each do |panel|
        s2 << (:li) do
          link_to panel[:title], panel[:url]
        end
      end
      raw s2
    end
    s3 = renderer.panels.inject('') do |sum, panel|
      if panel[:options][:id]
        sum = sum + (:div, panel[:options], &panel[:content])
      end
      sum
    end
    s + raw(s3)
  end
end

#will_paginate_ajax(collection, to_update, options = {}) ⇒ String

Create a will_paginate pagination interface which runs via Ajax. If will_paginate is not in the Gemfile or gem environment, this will throw an error.

Parameters:

  • collection (Array|ActiveRecord::Relation)

    the will_paginate collection.

  • to_update (String)

    the selector to use to update the content - either a “.class” or “#id” selector.

  • options (Hash) (defaults to: {})

    options passed through to will_paginate

Returns:

  • (String)


521
522
523
524
525
526
527
528
529
530
531
532
533
534
# File 'lib/jqr-helpers/helpers.rb', line 521

def will_paginate_ajax(collection, to_update, options={})
  if defined?(AjaxLinkRenderer)
    options[:'data-type'] = 'html'
    options[:'data-result-method'] = 'update'
    options[:'data-selector'] = to_update
    options[:'data-remote'] = true
    options[:'data-scroll-to'] = true
    options[:'data-throbber'] = options[:throbber] || 'large'
    options[:renderer] = AjaxLinkRenderer
    will_paginate(collection, options)
  else
    raise 'will_paginate not installed!'
  end
end