weaver 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +1 -1
- data/bin/console +3 -3
- data/exe/weaver +112 -122
- data/lib/weaver.rb +24 -2654
- data/lib/weaver/element_types/accordion.rb +122 -0
- data/lib/weaver/element_types/action.rb +38 -0
- data/lib/weaver/element_types/code.rb +81 -0
- data/lib/weaver/element_types/dynamic_table.rb +324 -0
- data/lib/weaver/element_types/dynamic_table_cell.rb +16 -0
- data/lib/weaver/element_types/form.rb +47 -0
- data/lib/weaver/element_types/form_elements.rb +297 -0
- data/lib/weaver/element_types/javascript_object.rb +28 -0
- data/lib/weaver/element_types/modal_dialog.rb +68 -0
- data/lib/weaver/element_types/panel.rb +124 -0
- data/lib/weaver/element_types/row.rb +117 -0
- data/lib/weaver/element_types/tabs.rb +75 -0
- data/lib/weaver/element_types/textfield_javascript.rb +58 -0
- data/lib/weaver/elements.rb +406 -0
- data/lib/weaver/page_types/center_page.rb +25 -0
- data/lib/weaver/page_types/empty_page.rb +26 -0
- data/lib/weaver/page_types/nav_page.rb +39 -0
- data/lib/weaver/page_types/nonnav_page.rb +35 -0
- data/lib/weaver/page_types/page.rb +234 -0
- data/lib/weaver/page_types/raw_page.rb +17 -0
- data/lib/weaver/page_types/sidenav_page.rb +119 -0
- data/lib/weaver/page_types/structured_page.rb +19 -0
- data/lib/weaver/page_types/topnav_page.rb +167 -0
- data/lib/weaver/version.rb +1 -1
- data/lib/weaver/weave.rb +44 -0
- data/weaver.gemspec +27 -24
- metadata +37 -13
@@ -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 || ' '
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|