weaver 0.8.0 → 0.8.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.
@@ -0,0 +1,122 @@
1
+ module Weaver
2
+ # Accordion element
3
+ class Accordion
4
+ def initialize(page, anchors)
5
+ @anchors = anchors
6
+ @tabs = {}
7
+ @paneltype = :panel
8
+ @is_collapsed = false
9
+ @page = page
10
+
11
+ @anchors['accordia'] = [] unless @anchors['accordia']
12
+
13
+ accArray = @anchors['accordia']
14
+
15
+ @accordion_name = "accordion#{accArray.length}"
16
+ accArray << @accordion_name
17
+ end
18
+
19
+ def collapsed(isCollapsed)
20
+ @is_collapsed = isCollapsed
21
+ end
22
+
23
+ def type(type)
24
+ @paneltype = type
25
+ end
26
+
27
+ def tab(title, options = {}, &block)
28
+ @anchors['tabs'] = [] unless @anchors['tabs']
29
+
30
+ tabArray = @anchors['tabs']
31
+
32
+ elem = Elements.new(@page, @anchors)
33
+ elem.instance_eval(&block)
34
+
35
+ tabname = "tab#{tabArray.length}"
36
+ tabArray << tabname
37
+
38
+ @tabs[tabname] =
39
+ {
40
+ title: title,
41
+ elem: elem
42
+ }
43
+
44
+ if options[:mixpanel_event_name]
45
+ @tabs[tabname][:mixpanel_event_name] = options[:mixpanel_event_name]
46
+ end
47
+
48
+ if options[:mixpanel_event_props]
49
+ @tabs[tabname][:mixpanel_event_props] = options[:mixpanel_event_props]
50
+ end
51
+ end
52
+
53
+ def generate
54
+ tabbar = Elements.new(@page, @anchors)
55
+
56
+ tabs = @tabs
57
+ paneltype = @paneltype
58
+ accordion_name = @accordion_name
59
+ is_collapsed = @is_collapsed
60
+
61
+ tabbar.instance_eval do
62
+ div class: 'panel-group', id: accordion_name do
63
+ cls = 'panel-collapse collapse in'
64
+ cls = 'panel-collapse collapse' if is_collapsed
65
+ tabs.each do |anchor, value|
66
+ ibox do
67
+ type paneltype
68
+ body false
69
+ title do
70
+ div class: 'panel-title' do
71
+ options = {
72
+ "data-toggle": 'collapse',
73
+ "data-parent": "##{accordion_name}",
74
+ href: "##{anchor}"
75
+ }
76
+
77
+ if value[:mixpanel_event_name]
78
+ props = {}
79
+ if value[:mixpanel_event_props].is_a? Hash
80
+ props = value[:mixpanel_event_props]
81
+ end
82
+ options[:onclick] = "mixpanel.track('#{value[:mixpanel_event_name]}', #{props.to_json.tr('"', "'")})"
83
+ end
84
+
85
+ a options do
86
+ if value[:title].is_a? Symbol
87
+ icon value[:title]
88
+ else
89
+ text value[:title]
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ extra do
96
+ div id: anchor, class: cls do
97
+ div class: 'panel-body' do
98
+ text value[:elem].generate
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ cls = 'panel-collapse collapse'
105
+ end
106
+ end
107
+ end
108
+
109
+ tabbar.generate
110
+ end
111
+ end
112
+
113
+ # Add accordion to elements
114
+ class Elements
115
+ def accordion(&block)
116
+ acc = Accordion.new(@page, @anchors)
117
+ acc.instance_eval(&block)
118
+
119
+ @inner_content << acc.generate
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,38 @@
1
+ module Weaver
2
+ class Action
3
+ def initialize(page, anchors, &block)
4
+ @page = page
5
+ @anchors = anchors
6
+
7
+ actionsArray = @anchors['action']
8
+
9
+ @anchors['action'] = [] unless @anchors['action']
10
+
11
+ actionsArray = @anchors['action']
12
+
13
+ @actionName = "action#{actionsArray.length}"
14
+ actionsArray << @actionName
15
+
16
+ @code = ''
17
+
18
+ instance_eval(&block)
19
+ end
20
+
21
+ def script(code)
22
+ @code = code
23
+ end
24
+
25
+ def generate
26
+ # puts @code
27
+ <<-FUNCTION
28
+ function #{@actionName}(caller, data) {
29
+ #{@code}
30
+ }
31
+ FUNCTION
32
+ end
33
+
34
+ def name
35
+ @actionName
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,81 @@
1
+ module Weaver
2
+ class Code
3
+ def initialize(page, anchors, lang)
4
+ @page = page
5
+ @anchors = anchors
6
+ @content = ''
7
+ @options = {}
8
+
9
+ codeArray = @anchors['code']
10
+
11
+ @anchors['code'] = [] unless @anchors['code']
12
+
13
+ codeArray = @anchors['code']
14
+
15
+ @codeName = "code#{codeArray.length}"
16
+ codeArray << @codeName
17
+
18
+ @page.request_css 'css/plugins/codemirror/codemirror.css'
19
+ @page.request_js 'js/plugins/codemirror/codemirror.js'
20
+
21
+ language lang
22
+ end
23
+
24
+ def language(lang)
25
+ # TODO: improve langmap
26
+ langmap = {
27
+ javascript: { mime: 'text/javascript', file: 'javascript/javascript' }
28
+ }
29
+
30
+ if langmap[lang]
31
+ @options[:mode] = langmap[lang][:mime]
32
+ @page.request_js "js/plugins/codemirror/mode/#{langmap[lang][:file]}.js"
33
+ else
34
+ @options[:mode] = "text/x-#{lang}"
35
+ @page.request_js "js/plugins/codemirror/mode/#{lang}/#{lang}.js"
36
+ end
37
+ end
38
+
39
+ def content(text)
40
+ @content = text
41
+ end
42
+
43
+ def theme(name)
44
+ @options[:theme] = name
45
+
46
+ @page.request_css "css/plugins/codemirror/#{name}.css"
47
+ end
48
+
49
+ def generate_script
50
+ @options[:lineNumbers] ||= true
51
+ @options[:matchBrackets] ||= true
52
+ @options[:styleActiveLine] ||= true
53
+ @options[:mode] ||= 'javascript'
54
+ @options[:readOnly] ||= true
55
+
56
+ <<-CODESCRIPT
57
+ $(document).ready(function()
58
+ {
59
+ CodeMirror.fromTextArea(document.getElementById("#{@codeName}"),
60
+ JSON.parse('#{@options.to_json}')
61
+ );
62
+ });
63
+ CODESCRIPT
64
+ end
65
+
66
+ def generate
67
+ content = @content
68
+ codeName = @codeName
69
+
70
+ elem = Elements.new(@page, @anchors)
71
+
72
+ elem.instance_eval do
73
+ textarea id: codeName do
74
+ text content
75
+ end
76
+ end
77
+
78
+ elem.generate
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,324 @@
1
+ require 'weaver/element_types/dynamic_table_cell'
2
+ module Weaver
3
+ # Tables that dynamically load data
4
+ class DynamicTable
5
+ def initialize(page, anchors, url, options = {}, &block)
6
+ @page = page
7
+ @anchors = anchors
8
+ @url = url
9
+ @options = options
10
+ @columns = nil
11
+ @query_object = nil
12
+
13
+ instance_eval(&block) if block
14
+
15
+ @options[:id] ||= @page.create_anchor 'dyn_table'
16
+ @table_name = @options[:id]
17
+ @head_name = "#{@table_name}_head"
18
+ @body_name = "#{@table_name}_body"
19
+ end
20
+
21
+ def column(name, options = {}, &block)
22
+ @columns = [] if @columns.nil?
23
+
24
+ title = options[:title] || name
25
+ format = nil
26
+ transform = nil
27
+
28
+ if options[:icon]
29
+ elem = Elements.new(@page, @anchors)
30
+ elem.instance_eval do
31
+ icon options[:icon]
32
+ text " #{title}"
33
+ end
34
+ title = elem.generate
35
+ end
36
+
37
+ if block
38
+ elem = DynamicTableCell.new(@page, @anchors)
39
+ elem.instance_eval(&block)
40
+ format = elem.generate
41
+ if elem.transform_script
42
+ func_name = @page.create_anchor 'transform'
43
+ @page.write_script_once <<-SCRIPT
44
+ document.transform_#{func_name} = function (input)
45
+ {
46
+ #{elem.transform_script}
47
+ }
48
+ SCRIPT
49
+
50
+ transform = func_name
51
+ end
52
+ end
53
+
54
+ @columns << { name: name, title: title, format: format, transform: transform }
55
+ end
56
+
57
+ def generate_table
58
+ table_name = @table_name
59
+ head_name = @head_name
60
+ body_name = @body_name
61
+ options = @options
62
+
63
+ columns = @columns || [{ title: 'Key' }, { title: 'Value' }]
64
+
65
+ elem = Elements.new(@page, @anchors)
66
+ elem.instance_eval do
67
+ table options do
68
+ thead id: head_name do
69
+ columns.each do |column, _|
70
+ if column.is_a? Hash
71
+ th column[:title].to_s
72
+ else
73
+ th column.to_s
74
+ end
75
+ end
76
+ end
77
+
78
+ tbody id: body_name do
79
+ end
80
+ end
81
+ end
82
+
83
+ elem.generate
84
+ end
85
+
86
+ def query(&block)
87
+ @query_object = JavaScriptObject.new(&block)
88
+ end
89
+
90
+ def generate_script
91
+ query_object_declaration = '{}'
92
+ query_string = ''
93
+
94
+ if @query_object
95
+ query_object_declaration = @query_object.generate
96
+ query_string = '+ "?" + $.param(query_object)'
97
+ end
98
+
99
+ member_expr = ''
100
+ member_expr = ".#{@options[:member]}" if @options[:member]
101
+
102
+ <<-DATATABLE_SCRIPT
103
+
104
+ function refresh_table_#{@table_name}()
105
+ {
106
+ var query_object = #{query_object_declaration};
107
+
108
+ $.get( "#{@url}" #{query_string}, function( returned_data )
109
+ {
110
+ var data = returned_data#{member_expr};
111
+ var data_object = {};
112
+ if (data !== null && typeof data === 'object')
113
+ {
114
+ data_object = data;
115
+ }
116
+ else
117
+ {
118
+ data_object = JSON.parse(data);
119
+ }
120
+
121
+ var head = $("##{@head_name}")
122
+ var body = $("##{@body_name}")
123
+
124
+ if($.isPlainObject(data_object))
125
+ {
126
+ for (var key in data_object)
127
+ {
128
+ var row = $('<tr>');
129
+ row.append($('<td>').text(key));
130
+ row.append($('<td>').text(data_object[key]));
131
+ body.append(row);
132
+ }
133
+ }
134
+
135
+ if ($.isArray(data_object))
136
+ {
137
+
138
+ var columnData = JSON.parse(#{@columns.to_json.inspect});
139
+ var columns = {};
140
+ var columnTitles = [];
141
+ head.empty();
142
+ if (#{@columns.nil?})
143
+ {
144
+ // Set up columns
145
+ for (var index in data_object)
146
+ {
147
+ for (var key in data_object[index])
148
+ {
149
+ columns[key] = Object.keys(columns).length;
150
+ }
151
+ }
152
+ for (var key in columns)
153
+ {
154
+ columnTitles.push(key);
155
+ }
156
+ }
157
+ else
158
+ {
159
+ for (var key in columnData)
160
+ {
161
+ columns[columnData[key]["name"]] = Object.keys(columns).length;
162
+ columnTitles.push(columnData[key]["title"]);
163
+ }
164
+ }
165
+
166
+ var row = $('<tr>');
167
+ for (var key in columnTitles)
168
+ {
169
+ var columnTitle = $('<th>').html(columnTitles[key]);
170
+ row.append(columnTitle);
171
+ }
172
+ head.append(row);
173
+
174
+ for (var index in data_object)
175
+ {
176
+ var row = $('<tr>');
177
+ for (var columnIndex = 0; columnIndex < Object.keys(columns).length; columnIndex++) {
178
+ var cell_data = data_object[index][ Object.keys(columns)[columnIndex] ];
179
+
180
+ if (columnData && columnData[columnIndex]["format"])
181
+ {
182
+ var format = columnData[columnIndex]["format"];
183
+ var matches = format.match(/###.+?###/g)
184
+
185
+ var result = format;
186
+ for (var matchIndex in matches)
187
+ {
188
+ var member_name = matches[matchIndex].match(/[^#]+/)[0];
189
+ result = result.replaceAll(matches[matchIndex], data_object[index][member_name]);
190
+ }
191
+
192
+ if (columnData && columnData[columnIndex]["transform"])
193
+ {
194
+ result = document["transform_" + columnData[columnIndex]["transform"]](result);
195
+ }
196
+ row.append($('<td>').html( result ).data("object", data_object[index]) );
197
+ }
198
+ else
199
+ {
200
+ if (columnData && columnData[columnIndex]["transform"])
201
+ {
202
+ cell_data = document["transform_" + columnData[columnIndex]["transform"]](cell_data);
203
+ }
204
+ row.append($('<td>').text( cell_data ).data("object", data_object[index]) );
205
+ }
206
+ }
207
+ body.append(row);
208
+ }
209
+ }
210
+
211
+ });
212
+ }
213
+
214
+ refresh_table_#{@table_name}();
215
+
216
+ DATATABLE_SCRIPT
217
+ end
218
+ end
219
+
220
+ # Add tables to elements
221
+ class Elements
222
+ def table(options = {}, &block)
223
+ table_name = options[:id] || @page.create_anchor('table')
224
+ table_style = ''
225
+
226
+ table_style = options[:style] unless options[:style].nil?
227
+
228
+ classname = 'table'
229
+
230
+ classname += ' table-bordered' if options[:bordered]
231
+ classname += ' table-hover' if options[:hover]
232
+ classname += ' table-striped' if options[:striped]
233
+
234
+ table_options = {
235
+ class: classname,
236
+ id: table_name,
237
+ style: table_style
238
+ }
239
+
240
+ if options[:system] == :data_table
241
+ @page.request_js 'js/plugins/dataTables/jquery.dataTables.js'
242
+ @page.request_js 'js/plugins/dataTables/dataTables.bootstrap.js'
243
+ @page.request_js 'js/plugins/dataTables/dataTables.responsive.js'
244
+ @page.request_js 'js/plugins/dataTables/dataTables.tableTools.min.js'
245
+
246
+ @page.request_css 'css/plugins/dataTables/dataTables.bootstrap.css'
247
+ @page.request_css 'css/plugins/dataTables/dataTables.responsive.css'
248
+ @page.request_css 'css/plugins/dataTables/dataTables.tableTools.min.css'
249
+
250
+ @page.scripts << <<-DATATABLE_SCRIPT
251
+ $('##{table_name}').DataTable();
252
+ DATATABLE_SCRIPT
253
+ end
254
+
255
+ if options[:system] == :foo_table
256
+ table_options[:"data-filtering"] = true
257
+ table_options[:"data-sorting"] = true
258
+ table_options[:"data-paging"] = true
259
+ table_options[:"data-show-toggle"] = true
260
+ table_options[:"data-toggle-column"] = 'last'
261
+
262
+ table_options[:"data-paging-size"] = (options[:max_items_per_page] || 8).to_i.to_s
263
+ table_options[:class] = table_options[:class] + ' toggle-arrow-tiny'
264
+
265
+ @page.request_js 'js/plugins/footable/footable.all.min.js'
266
+
267
+ @page.request_css 'css/plugins/footable/footable.core.css'
268
+
269
+ @page.scripts << <<-DATATABLE_SCRIPT
270
+ $('##{table_name}').footable({
271
+ paging: {
272
+ size: #{(options[:max_items_per_page] || 8).to_i}
273
+ }
274
+ });
275
+ $('##{table_name}').append(this.html).trigger('footable_redraw');
276
+
277
+
278
+
279
+ DATATABLE_SCRIPT
280
+
281
+ @page.onload_scripts << <<-SCRIPT
282
+ SCRIPT
283
+ end
284
+
285
+ method_missing(:table, table_options, &block)
286
+ ul class: 'pagination'
287
+ end
288
+
289
+ def table_from_source(url, options = {}, &block)
290
+ dyn_table = DynamicTable.new(@page, @anchors, url, options, &block)
291
+
292
+ text dyn_table.generate_table
293
+
294
+ @page.scripts << dyn_table.generate_script
295
+ end
296
+
297
+ def table_from_hashes(hashes, options = {})
298
+ keys = {}
299
+ hashes.each do |hash|
300
+ hash.each do |key, _value|
301
+ keys[key] = ''
302
+ end
303
+ end
304
+
305
+ table options do
306
+ thead do
307
+ keys.each do |key, _|
308
+ th key.to_s
309
+ end
310
+ end
311
+
312
+ tbody do
313
+ hashes.each do |hash|
314
+ tr do
315
+ keys.each do |key, _|
316
+ td (hash[key]).to_s || '&nbsp;'
317
+ end
318
+ end
319
+ end
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end