assoc_whisperer 1.2.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3b0faee0f011a70f467c0952840bf4f9769b2d7
4
- data.tar.gz: 3c79fa3dd430cd87812df970f2587c3582fedbf0
3
+ metadata.gz: c12d3a84dff2b3fcedf60c2abd790d235626c566
4
+ data.tar.gz: aacfc5036d39c470b1301cc6b7f853f0dded41d0
5
5
  SHA512:
6
- metadata.gz: 03278adaba130fbe47971380cfb6c34c3835fd19d1aa8fd2df0a7f018f658ecfac25a976e642761ec4bd0c3a9b0cfd8cb06e09f5f2bb01bd080a7138514d915d
7
- data.tar.gz: c368cf1dcb3f33d4fb6c258d810d6a197403da440f411cff62aafe43b46d02edca3424db4383ee965c5c707ee0a29e8d934653045c64573970b9bb2fd4a31883
6
+ metadata.gz: 760054c15cc9fc0aea5357f11db45cfb81e5245a3747f574ba6fccc1abeb3a50aac045d17a08e26a09122f238e5744ea18239fb4775977ef388cc82bc481c9ce
7
+ data.tar.gz: 6309409f36c8087a4460dc542eaaf2b3d05fa1850f0df4cd5f2d20a4dd145eb97812a5cd4eafb542d946b9f9658576e0233bfb9c0f4917f75e33d0c45939c3bc
@@ -15,7 +15,7 @@ document.AssocWhisperer = (function () {
15
15
 
16
16
  // This is where Whisperer Object is created - with all hidden inner methods.
17
17
  function createWhisperer(dom_node) {
18
- var el, w, _nodes, opts, params, _timer;
18
+ var el, w, opts, _nodes, _timer;
19
19
 
20
20
  el = $(dom_node);
21
21
  _nodes = {
@@ -25,22 +25,25 @@ document.AssocWhisperer = (function () {
25
25
  list: null
26
26
  };
27
27
  opts = el.data('opts');
28
- if (!opts['action']) throw 'Missing action in '+JSON.stringify(opts);
29
- if (!opts['url']) throw 'Missing url in '+JSON.stringify(opts);
28
+ if (!opts['action']) throw 'Missing action path in '+JSON.stringify(opts);
30
29
  if (typeof opts['params']!=='object') opts['params'] = {};
30
+ // opts['cs'] = parseInt(opts['cs']);
31
31
 
32
32
  w = Object.create(proto, {
33
33
  nodes: {value: _nodes},
34
- action: {value: opts['action']},
35
- url: {value: opts['url']},
36
- params: {value: opts['params']},
37
34
  focused: {value: false, writable: true},
38
35
  filled: {value: _nodes['value_field'].val()!=='', writable: true},
39
- client_side: {value: opts['cs']===true},
40
- preload: {value: opts['pre']===true},
41
- full_data: {value: null, writable: true}
36
+ // setting
37
+ action: {value: opts['action']},
38
+ params: {value: opts['params']}
42
39
  });
43
- w.params['data_action'] = w.action;
40
+ // if (!isNaN(opts['cs'])) {
41
+ // // client side
42
+ // Object.defineProperties({
43
+ // client_side: {value: opts['cs']},
44
+ // full_data: {value: null, writable: true}
45
+ // });
46
+ // }
44
47
 
45
48
  _nodes.text_field.on('keyup', function(e){
46
49
  var input_text;
@@ -67,11 +70,11 @@ document.AssocWhisperer = (function () {
67
70
  }
68
71
  _timer = setTimeout(function () {
69
72
  if (w.client_side) {
70
- if (!w.full_data) query(w, null, function (html_text) {
71
- w.full_data = $(html_text);
72
- showList(digest(input_text));
73
- });
74
- else showList(digest(input_text));
73
+ // if (!w.full_data) query(w, null, function (html_text) {
74
+ // w.full_data = $(html_text);
75
+ // showList(digest(input_text));
76
+ // });
77
+ // else showList(digest(input_text));
75
78
  }
76
79
  else query(w, input_text, function (html_text) {
77
80
  showList($(html_text));
@@ -86,20 +89,20 @@ document.AssocWhisperer = (function () {
86
89
  var f;
87
90
  if (_timer) clearTimeout(_timer);
88
91
  if (w.client_side) {
89
- f = function () {
90
- var input_text;
91
- if (w.filled) showList(w.full_data);
92
- else {
93
- input_text = _nodes['text_field'].val();
94
- showList(digest(input_text==='' ? null : input_text));
95
- }
96
- _nodes['list'].focus();
97
- };
98
- if (!w.full_data) query(w, null, function (html_text) {
99
- w.full_data = $(html_text);
100
- f();
101
- });
102
- else f();
92
+ // f = function () {
93
+ // var input_text;
94
+ // if (w.filled) showList(w.full_data);
95
+ // else {
96
+ // input_text = _nodes['text_field'].val();
97
+ // showList(digest(input_text==='' ? null : input_text));
98
+ // }
99
+ // _nodes['list'].focus();
100
+ // };
101
+ // if (!w.full_data) query(w, null, function (html_text) {
102
+ // w.full_data = $(html_text);
103
+ // f();
104
+ // });
105
+ // else f();
103
106
  }
104
107
  else {
105
108
  query(w, (w.filled ? null : _nodes['text_field'].val()), function (html_text) {
@@ -110,19 +113,19 @@ document.AssocWhisperer = (function () {
110
113
  });
111
114
  el.children('.dropdown_button').removeClass('querying'); // css class is set, hence gif gets pre-loaded
112
115
 
113
- // For local full_data finds matching rows and shows them.
114
- function digest(input_text) {
115
- var narrowed_list = w.full_data;
116
- if (input_text && input_text!=='') {
117
- input_text = input_text.toLowerCase();
118
- narrowed_list = $(narrowed_list[0].cloneNode());
119
- w.full_data.children().each(function () {
120
- if (this.innerText.toLowerCase().indexOf(input_text)!==-1)
121
- narrowed_list.append($(this).clone());
122
- });
123
- }
124
- return narrowed_list;
125
- }
116
+ // // For local full_data finds matching rows and shows them.
117
+ // function digest(input_text) {
118
+ // var narrowed_list = w.full_data;
119
+ // if (input_text && input_text!=='') {
120
+ // input_text = input_text.toLowerCase();
121
+ // narrowed_list = $(narrowed_list[0].cloneNode());
122
+ // w.full_data.children().each(function () {
123
+ // if (this.innerText.toLowerCase().indexOf(input_text)!==-1)
124
+ // narrowed_list.append($(this).clone());
125
+ // });
126
+ // }
127
+ // return narrowed_list;
128
+ // }
126
129
 
127
130
  // Attaches a List sent by html string within Whisperer's tag. Positions it underneath the text field.
128
131
  function showList (list) {
@@ -187,8 +190,8 @@ document.AssocWhisperer = (function () {
187
190
  klass.querying = true;
188
191
  btn = w.nodes['base'].find('.dropdown_button');
189
192
  btn.addClass('querying');
190
- w.params['input'] = input || '';
191
- $.ajax(w.url, {
193
+ w.params['input'] = input;
194
+ $.ajax(w.action, {
192
195
  type: 'GET',
193
196
  dataType: 'html',
194
197
  data: w.params,
@@ -206,7 +209,6 @@ document.AssocWhisperer = (function () {
206
209
  // public interface //
207
210
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208
211
 
209
-
210
212
  klass = Object.create(Object, {querying: {value: false, writable: true}});
211
213
 
212
214
  // Return a Whisperer instance by its data-action attribute.
@@ -214,7 +216,7 @@ document.AssocWhisperer = (function () {
214
216
  var i, w;
215
217
  for (i = 0; i < all_array.length; i += 1) {
216
218
  w = all_array[i];
217
- if (w.action===action) return w;
219
+ if (w.params['action']===action || w.action.indexOf(action)!==-1) return w;
218
220
  }
219
221
  return null;
220
222
  }
@@ -3,54 +3,29 @@ module ActionView
3
3
 
4
4
  module AssocWhispererHelper
5
5
 
6
- # Createa an association whisperer tag, that will attach javascript object to self
7
- # allowing user to select a text but stores something differend (mostly respective id).
8
- #
9
- # ==== Examples
10
- # assoc_whisperer :task, :worker, :workers, size: 25, url: '/whisp'
11
- # # => <span class="assoc_whisperer" data-action="workers" data-url="/whisp">
12
- # <input class="value_field" id="task_worker_id" name="task[worker_id]" type="hidden" value="">
13
- # <input autocomplete="off" class="text_field unfilled" id="task_worker_txt" name="task[worker_txt]" size="25" type="text" value="">
14
- # <span class="dropdown_button">▾</span></span>
15
- #
16
- # Let's say your association looks like this:
17
- #
18
- # class Task
19
- # belongs_to :worker, class_name: 'Worker', foreign_key: :manager
20
- # end
21
- # class Worker
22
- # def full_name; end
23
- # def manager_id; end
24
- # end
25
- #
26
- # assoc_whisperer :task, :worker, :workers, name: :manager, value_method: :manager_id, text_method: :full_name
27
- # # => <span class="assoc_whisperer" data-action="workers" data-url="">
28
- # <input class="value_field" id="task_manager" name="task[manager]" type="hidden" value="">
29
- # <input autocomplete="off" class="text_field unfilled" id="task_manager_txt" name="task[manager_txt]" size="12" type="text" value="">
30
- # <span class="dropdown_button">▾</span></span>
31
- #
32
- # And the 'value_field' would be filled by +manager_id+ of +worker+ associated to +task+, 'text_field' by his +full_name+
33
- #
34
- def assoc_whisperer(object_name, method, data_action, options={})
35
- raise "Helper '#assoc_whisperer' is for Rails >= 4.x. Use '#assoc_whisperer_tag' instead." if Rails::VERSION::STRING.to_i < 4
36
- wrapper_assoc_whisperer_assets
6
+ def whisperer(object_name, method, template, field_attrs={})
7
+ raise "Helper '#whisperer' cannot be used in Rails < 4.x. Use '#whisperer_tag' instead." if Rails::VERSION::STRING.to_i < 4
8
+ wrapper_whisperer_assets
37
9
 
38
- Tags::AssocWhispererField.new(object_name, method, self, data_action, options).render
10
+ Tags::AssocWhispererField.new(object_name, method, self, template, field_attrs).render
39
11
  end
40
12
 
41
- def assoc_whisperer_tag(name, data_action, options = {})
42
- wrapper_assoc_whisperer_assets
13
+ def whisperer_tag(name, template, field_attrs={})
14
+ wrapper_whisperer_assets
43
15
 
44
- template = AssocWhisperer::Template.new data_action, options
45
- content_tag :span, template.simple_tag_contents(name).html_safe, 'class' => 'assoc_whisperer',
46
- 'data-opts' => template.whisperer_options.to_json
16
+ content_tag :span, template.tag_contents(name, field_attrs).html_safe, 'class' => 'assoc_whisperer',
17
+ 'data-opts' => template.whisperer_settings.to_json
18
+ end
19
+
20
+ def whisperer_template(action, opts={})
21
+ AssocWhisperer::Template.new action, opts
47
22
  end
48
23
 
49
24
  private
50
25
 
51
- def wrapper_assoc_whisperer_assets
26
+ def wrapper_whisperer_assets
52
27
  unless @assoc_whisp_attached
53
- attach_method = AssocWhisperer.attach_assets_method
28
+ attach_method = AssocWhisperer.attach_assets
54
29
  self.send attach_method if attach_method && self.respond_to?(attach_method)
55
30
  @assoc_whisp_attached = true
56
31
  end
@@ -59,8 +34,8 @@ module ActionView
59
34
  end
60
35
 
61
36
  class FormBuilder
62
- def assoc_whisperer(method, data_action, options = {})
63
- @template.assoc_whisperer @object_name, method, data_action, objectify_options(options)
37
+ def whisperer(method, template, field_attrs={})
38
+ @template.assoc_whisperer @object_name, method, template, objectify_options(field_attrs)
64
39
  end
65
40
  end
66
41
 
@@ -3,20 +3,20 @@ module ActionView
3
3
  module Tags # :nodoc:
4
4
  class AssocWhispererField < Base # :nodoc:
5
5
 
6
- def initialize(object_name, method_name, template_object, action, options={})
7
- options[:value_method] = AssocWhisperer.def_value_method unless options.has_key? :value_method
8
- options[:text_method] = AssocWhisperer.def_text_method unless options.has_key? :text_method
6
+ def initialize(object_name, method_name, template_object, whisp_template, options={})
7
+ @whisp_template = whisp_template
9
8
  super object_name, method_name, template_object, options
10
- @template = AssocWhisperer::Template.new action, @options
11
9
  end
12
10
 
13
11
  def render
14
- contents = @template.value_field_tag value_tag_id, value_tag_name, value_tag_value
15
- contents += @template.text_field_tag text_tag_id, text_tag_name, text_tag_value, !whispered_object
16
- contents += @template.dropdown_button_tag
12
+ @whisp_template.value_text whispered_object
13
+
14
+ contents = @whisp_template.value_field_tag value_tag_id, value_tag_name
15
+ contents += @whisp_template.text_field_tag text_tag_id, text_tag_name, @options
16
+ contents += @whisp_template.dropdown_button_tag
17
17
 
18
18
  content_tag :span, contents.html_safe, 'class' => 'assoc_whisperer',
19
- 'data-opts' => @template.whisperer_options.to_json
19
+ 'data-opts' => @whisp_template.whisperer_settings.to_json
20
20
  end
21
21
 
22
22
  private
@@ -25,11 +25,6 @@ module ActionView
25
25
  @whispered_object ||= value @object
26
26
  end
27
27
 
28
- def whispered_object_attribute(method)
29
- wo = whispered_object
30
- wo.send method if wo && wo.respond_to?(method)
31
- end
32
-
33
28
  def text_tag_name
34
29
  "#{@object_name}[#{text_sanitized_method_name}]"
35
30
  end
@@ -38,18 +33,8 @@ module ActionView
38
33
  "#{sanitized_object_name}_#{text_sanitized_method_name}"
39
34
  end
40
35
 
41
- def text_tag_value
42
- text = @template.opts[:text_method]
43
- text = if text.respond_to? :call
44
- text.call whispered_object
45
- else
46
- whispered_object_attribute(text)
47
- end
48
- ERB::Util.html_escape text
49
- end
50
-
51
36
  def text_sanitized_method_name
52
- @text_sanitized_method_name ||= "#{@template.opts[:name] || @method_name}_txt".sub(/\?$/,"")
37
+ @text_sanitized_method_name ||= "#{@whisp_template.opts[:name] || @method_name}_txt".sub(/\?$/,"")
53
38
  end
54
39
 
55
40
  def value_tag_name
@@ -60,18 +45,14 @@ module ActionView
60
45
  "#{sanitized_object_name}_#{value_sanitized_method_name}"
61
46
  end
62
47
 
63
- def value_tag_value
64
- whispered_object_attribute @template.opts[:value_method]
65
- end
66
-
67
48
  def value_sanitized_method_name
68
49
  return @value_sanitized_method_name if defined? @value_sanitized_method_name
69
- wsmn = if @template.opts[:name]
70
- @template.opts[:name].to_s
50
+ name = if @whisp_template.opts[:name]
51
+ @whisp_template.opts[:name].to_s
71
52
  else
72
- "#{@method_name}_#{@template.opts[:value_method]}"
53
+ "#{@method_name}_#{@template.opts[:value]}"
73
54
  end
74
- @value_sanitized_method_name = wsmn.sub(/\?$/,"")
55
+ @value_sanitized_method_name = name.sub(/\?$/, '')
75
56
  end
76
57
 
77
58
  end
@@ -1,9 +1,9 @@
1
1
  <%
2
2
  text_method = local_assigns[:text] || :to_s
3
- val_method = local_assigns[:val] || :id
3
+ value_method = local_assigns[:value] || :id
4
4
  %>
5
5
  <div tabindex=0 class="list">
6
6
  <% @objects.each do |o| %>
7
- <div data-value="<%= o.send val_method %>"><%= o.send text_method %></div>
7
+ <div data-value="<%= o.send value_method %>"><%= o.send text_method %></div>
8
8
  <% end %>
9
9
  </div>
@@ -2,47 +2,64 @@
2
2
 
3
3
  module AssocWhisperer
4
4
  class Template
5
- attr_reader :action, :opts
5
+ attr_reader :opts
6
6
 
7
7
  def initialize(action, opts={})
8
- @action = action
8
+ @action = action[0]=='/' ? action : "#{AssocWhisperer.def_url}/#{action}"
9
9
  @opts = opts
10
10
  end
11
11
 
12
- def simple_tag_contents(input_name)
12
+ def params(params)
13
+ @params = params
14
+ self
15
+ end
16
+
17
+ def value_text(object_or_params, name=nil)
18
+ if object_or_params.is_a?(Hash) && name
19
+ @value = object_or_params[name]
20
+ @text = object_or_params["#{name}_txt"]
21
+ elsif object_or_params
22
+ value = @opts[:value] || AssocWhisperer.def_value
23
+ text = @opts[:text] || AssocWhisperer.def_text
24
+ @value = (object_or_params.send value if object_or_params.respond_to? value)
25
+ @text = (object_or_params.send text if object_or_params.respond_to? text)
26
+ else
27
+ @value = nil
28
+ @text = nil
29
+ end
30
+ self
31
+ end
32
+
33
+ def tag_contents(input_name, field_attrs={})
13
34
  input_name = input_name.to_s
14
35
  sanitized_id = input_name.dup.delete(']').gsub(/[^-a-zA-Z0-9:.]/, "_")
15
36
  text_tag_name = input_name.dup
16
37
  text_tag_name.insert (text_tag_name[-1]==']' ? -2 : -1), '_txt'
17
38
 
18
- contents = value_field_tag sanitized_id, input_name, @opts[:value]
19
- contents += text_field_tag "#{sanitized_id}_txt", text_tag_name, @opts[:text], @opts[:value].blank?
39
+ contents = value_field_tag sanitized_id, input_name
40
+ contents += text_field_tag "#{sanitized_id}_txt", text_tag_name, field_attrs
20
41
  contents + dropdown_button_tag
21
42
  end
22
43
 
23
- def whisperer_options
24
- h = {url: (@opts[:url]||AssocWhisperer.def_url), action: @action}
25
- h.merge cs: true, pre: !!@opts[:preload] if @opts[:client_side]
26
- h[:params] = @opts[:params] unless @opts[:params].blank?
44
+ def whisperer_settings
45
+ h = {action: @action}
46
+ # h[:cs] = @opts[:client_side] if @opts[:client_side]
47
+ h[:params] = @params if @params
27
48
  h
28
49
  end
29
50
 
30
- def value_field_tag(id, name, value)
31
- %(<input type="hidden" id="#{id}" name="#{name}" value="#{value}" class="value_field">)
51
+ def value_field_tag(id, name)
52
+ %(<input type="hidden" id="#{id}" name="#{name}" value="#{@value}" class="value_field">)
32
53
  end
33
54
 
34
- def text_field_tag(id, name, value, unfilled=true)
35
- opts = @opts[:text_field]
36
- if opts
37
- opts[:size] ||= 12
38
- keys_whitelist = (opts.keys & [:size, :placeholder, :maxlength, :title])
39
- opts = keys_whitelist.inject [] do |arr, k|
40
- arr << %(#{k}="#{opts[k]}")
41
- arr
42
- end
43
- opts = opts * ' '
55
+ def text_field_tag(id, name, attrs={})
56
+ attrs[:size] = 12 unless attrs.has_key? :size
57
+ keys_whitelist = (attrs.keys & [:size, :placeholder, :maxlength, :title])
58
+ attrs = keys_whitelist.inject [] do |arr, k|
59
+ arr << %(#{k}="#{attrs[k]}")
60
+ arr
44
61
  end
45
- %(<input type="text" autocomplete="off" id="#{id}" name="#{name}" value="#{value}" class="text_field#{' unfilled' if unfilled}"#{opts}>)
62
+ %(<input type="text" autocomplete="off" id="#{id}" name="#{name}" value="#{@text}" class="text_field#{' unfilled' unless @value}"#{attrs * ' '}>)
46
63
  end
47
64
 
48
65
  def dropdown_button_tag
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
  module AssocWhisperer
3
- VERSION = "1.2.1"
3
+ VERSION = "2.0.1"
4
4
 
5
5
  end
@@ -5,7 +5,7 @@ require 'assoc_whisperer/template'
5
5
  module AssocWhisperer
6
6
 
7
7
  class << self
8
- attr_accessor :def_url, :attach_assets_method, :def_value_method, :def_text_method
8
+ attr_accessor :def_url, :attach_assets, :def_value, :def_text
9
9
  end
10
10
 
11
11
  module Rails
@@ -13,23 +13,10 @@ module AssocWhisperer
13
13
  end
14
14
  end
15
15
 
16
- def self.value_field_html(id, name, value)
17
- %(<input type="hidden" id="#{id}" name="#{name}" value="#{value}" class="value_field">)
18
- end
19
-
20
- def self.text_field_html(id, name, value, unfilled=true, opts={})
21
- opts = opts.keys.inject([]){|arr, k| arr << %(#{k}="#{opts[k]}"); arr }*' '
22
- %(<input type="text" id="#{id}" name="#{name}" value="#{value} class="text_field#{' unfilled' if unfilled}"#{opts}>)
23
- end
24
-
25
- def self.dropdown_button_html
26
- @dropdown_button_html ||= "<span class=\"dropdown_button\">\u25BE</span>"
27
- end
28
-
29
16
  end
30
17
 
31
18
  AssocWhisperer.def_url = '/whisp'
32
- AssocWhisperer.attach_assets_method = :attach_assoc_whisperer_assets
19
+ AssocWhisperer.attach_assets = :attach_whisperer_assets
33
20
 
34
- AssocWhisperer.def_value_method = :id
35
- AssocWhisperer.def_text_method = :to_s
21
+ AssocWhisperer.def_value = :id
22
+ AssocWhisperer.def_text = :to_s
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assoc_whisperer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ondřej Želazko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-31 00:00:00.000000000 Z
11
+ date: 2014-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler