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,124 @@
1
+ module Weaver
2
+ class Panel < Elements
3
+ def initialize(page, anchors, options = {})
4
+ super(page, anchors)
5
+ @title = nil
6
+ @footer = nil
7
+ @type = :ibox
8
+ @body = true
9
+ @extra = nil
10
+ @min_height = nil
11
+ @page = page
12
+ @options = options
13
+ end
14
+
15
+ def generate
16
+ inner = super
17
+
18
+ types =
19
+ {
20
+ ibox: { outer: 'ibox float-e-margins', header: 'ibox-title', body: 'ibox-content', footer: 'ibox-footer' },
21
+ panel: { outer: 'panel panel-default', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
22
+ primary: { outer: 'panel panel-primary', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
23
+ success: { outer: 'panel panel-success', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
24
+ info: { outer: 'panel panel-info', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
25
+ warning: { outer: 'panel panel-warning', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
26
+ danger: { outer: 'panel panel-danger', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' },
27
+ blank: { outer: 'panel blank-panel', header: 'panel-heading', body: 'panel-body', footer: 'panel-footer' }
28
+ }
29
+
30
+ title = @title
31
+ footer = @footer
32
+ hasBody = @body
33
+ extra = @extra
34
+ options = @options
35
+ classNames = types[@type]
36
+ min_height = @min_height
37
+
38
+ elem = Elements.new(@page, @anchors)
39
+
40
+ outer_class = classNames[:outer]
41
+
42
+ outer_class = 'ibox collapsed' if options[:collapsed]
43
+
44
+ elem.instance_eval do
45
+ div class: outer_class do
46
+ if title
47
+ div class: classNames[:header] do
48
+ h5 title
49
+
50
+ div class: 'ibox-tools' do
51
+ if options[:collapsible] || options[:collapsed]
52
+ a class: 'collapse-link' do
53
+ icon :"chevron-up"
54
+ end
55
+ end
56
+ if options[:expandable]
57
+ a class: 'fullscreen-link' do
58
+ icon :expand
59
+ end
60
+ end
61
+ if options[:closable]
62
+ a class: 'close-link' do
63
+ icon :times
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ if hasBody
70
+ div class: classNames[:body], style: "min-height: #{min_height}px" do
71
+ text inner
72
+ end
73
+ end
74
+ text extra if extra
75
+ if footer
76
+ div class: classNames[:footer] do
77
+ text footer
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ elem.generate
84
+ end
85
+
86
+ def min_height(val)
87
+ @min_height = val
88
+ end
89
+
90
+ def type(aType)
91
+ @type = aType
92
+ end
93
+
94
+ def body(hasBody)
95
+ @body = hasBody
96
+ end
97
+
98
+ def title(title = nil, &block)
99
+ @title = title
100
+ if block
101
+ elem = Elements.new(@page, @anchors)
102
+ elem.instance_eval(&block)
103
+ @title = elem.generate
104
+ end
105
+ end
106
+
107
+ def extra(&block)
108
+ if block
109
+ elem = Elements.new(@page, @anchors)
110
+ elem.instance_eval(&block)
111
+ @extra = elem.generate
112
+ end
113
+ end
114
+
115
+ def footer(footer = nil, &block)
116
+ @footer = footer
117
+ if block
118
+ elem = Elements.new(@page, @anchors)
119
+ elem.instance_eval(&block)
120
+ @footer = elem.generate
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,117 @@
1
+ module Weaver
2
+ # Row element
3
+ class Row < Elements
4
+ attr_accessor :extra_classes, :style
5
+
6
+ def initialize(page, anchors, options)
7
+ @columns = []
8
+ @free = 12
9
+ @extra_classes = options[:class] || ''
10
+ @style = options[:style]
11
+ @anchors = anchors
12
+ @page = page
13
+ end
14
+
15
+ def col(occupies, options = {}, &block)
16
+ raise 'Not enough columns!' if @free < occupies
17
+
18
+ @columns << Column.new(occupies, @page, @anchors, options, &block)
19
+ @free -= occupies
20
+ end
21
+
22
+ def generate
23
+ @columns.map(&:generate).join
24
+ end
25
+ end
26
+
27
+ # Column element
28
+ class Column
29
+ attr_reader :width, :options, :elem
30
+
31
+ def initialize(width, page, anchors, options = {}, &block)
32
+ @width = width
33
+ @options = options
34
+ @elem = Elements.new(page, anchors)
35
+ @elem.instance_eval(&block)
36
+ end
37
+
38
+ def colsize(size)
39
+ options[size] || width
40
+ end
41
+
42
+ def style(size)
43
+ return "hidden-#{size} " if colsize(size).zero?
44
+
45
+ "col-#{size}-#{colsize(size)}"
46
+ end
47
+
48
+ def generate
49
+ styles = %i[xs sm md lg].map { |size| style(size) }.join(' ')
50
+
51
+ <<-ENDCOLUMN
52
+ <div class="#{styles}">
53
+ #{elem.generate}
54
+ </div>
55
+ ENDCOLUMN
56
+ end
57
+ end
58
+
59
+ # Add row and column elements
60
+ class Elements
61
+ def row(options = {}, &block)
62
+ options[:class] = 'row'
63
+ div options do
64
+ instance_eval(&block)
65
+ end
66
+ end
67
+
68
+ def twothirds(&block)
69
+ opts =
70
+ {
71
+ xs: 12,
72
+ sm: 12,
73
+ md: 8,
74
+ lg: 8
75
+ }
76
+ col(4, opts, &block)
77
+ end
78
+
79
+ def half(&block)
80
+ opts =
81
+ {
82
+ xs: 12,
83
+ sm: 12,
84
+ md: 12,
85
+ lg: 6
86
+ }
87
+ col(4, opts, &block)
88
+ end
89
+
90
+ def third(&block)
91
+ opts =
92
+ {
93
+ xs: 12,
94
+ sm: 12,
95
+ md: 4,
96
+ lg: 4
97
+ }
98
+ col(4, opts, &block)
99
+ end
100
+
101
+ def quarter(&block)
102
+ opts =
103
+ {
104
+ xs: 12,
105
+ sm: 12,
106
+ md: 6,
107
+ lg: 3
108
+ }
109
+ col(3, opts, &block)
110
+ end
111
+
112
+ def col(occupies, options = {}, &block)
113
+ column = Column.new(occupies, @page, @anchors, options, &block)
114
+ text column.generate
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,75 @@
1
+ module Weaver
2
+ class Tabs
3
+ def initialize(page, anchors)
4
+ @anchors = anchors
5
+ @tabs = {}
6
+ @page = page
7
+ @orientation = :normal # :left, :right
8
+ end
9
+
10
+ def tab(title, &block)
11
+ @anchors['tabs'] = [] unless @anchors['tabs']
12
+
13
+ tabArray = @anchors['tabs']
14
+
15
+ elem = Elements.new(@page, @anchors)
16
+ elem.instance_eval(&block)
17
+
18
+ tabname = "tab#{tabArray.length}"
19
+ tabArray << tabname
20
+
21
+ @tabs[tabname] =
22
+ {
23
+ title: title,
24
+ elem: elem
25
+ }
26
+ end
27
+
28
+ def orientation(direction)
29
+ @orientation = direction
30
+ end
31
+
32
+ def generate
33
+ tabbar = Elements.new(@page, @anchors)
34
+ tabs = @tabs
35
+ orientation = @orientation
36
+
37
+ tabbar.instance_eval do
38
+ div class: 'tabs-container' do
39
+ div class: "tabs-#{orientation}" do
40
+ ul class: 'nav nav-tabs' do
41
+ cls = 'active'
42
+ tabs.each do |anchor, value|
43
+ li class: cls do
44
+ a "data-toggle": 'tab', href: "##{anchor}" do
45
+ if value[:title].is_a? Symbol
46
+ icon value[:title]
47
+ else
48
+ text value[:title]
49
+ end
50
+ end
51
+ end
52
+
53
+ cls = ''
54
+ end
55
+ end
56
+
57
+ div class: 'tab-content' do
58
+ cls = 'tab-pane active'
59
+ tabs.each do |anchor, value|
60
+ div id: anchor.to_s, class: cls do
61
+ div class: 'panel-body' do
62
+ text value[:elem].generate
63
+ end
64
+ end
65
+ cls = 'tab-pane'
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ tabbar.generate
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,58 @@
1
+ module Weaver
2
+ class TextfieldJavascript
3
+ def initialize(id)
4
+ @id = id
5
+ end
6
+
7
+ def onchange(script)
8
+ @change_script = script
9
+ end
10
+
11
+ def validate(script)
12
+ @validate_script = script
13
+ end
14
+
15
+ def generate(&block)
16
+ if block
17
+ instance_eval(&block)
18
+ <<-SCRIPT
19
+
20
+ if (!document.validators)
21
+ {
22
+ document.validators = {};
23
+ }
24
+
25
+ document.validators["##{@id}"] = function()
26
+ {
27
+ var valid = function(data) {
28
+ #{@validate_script};
29
+ return true;
30
+ }($("##{@id}").val());
31
+
32
+ var object = $("##{@id}");
33
+ #{@change_script};
34
+
35
+ if (valid)
36
+ {
37
+ object.removeClass("required");
38
+ object.removeClass("error");
39
+ object.removeAttr("aria-invalid");
40
+ }
41
+ else
42
+ {
43
+ object.addClass("required");
44
+ object.addClass("error");
45
+ object.attr("aria-required", "true");
46
+ object.attr("aria-invalid", "true");
47
+ }
48
+ }
49
+
50
+ $("##{@id}").keyup(function() { document.validators["##{@id}"](); })
51
+ $("##{@id}").blur(function() { document.validators["##{@id}"](); })
52
+ $("##{@id}").focusout(function() { document.validators["##{@id}"](); })
53
+
54
+ SCRIPT
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,406 @@
1
+ module Weaver
2
+ # Base element class for all HTML elements
3
+ class Elements
4
+ def initialize(page, anchors)
5
+ @inner_content = []
6
+ @anchors = anchors
7
+ @page = page
8
+ end
9
+
10
+ def method_missing(name, *args, &block)
11
+ tag = "<#{name} />"
12
+
13
+ inner = args.shift if args[0].is_a? String
14
+ if block
15
+ elem = Elements.new(@page, @anchors)
16
+ elem.instance_eval(&block)
17
+ inner = elem.generate
18
+ end
19
+
20
+ if !inner
21
+
22
+ options = args[0] || []
23
+ opts = options.map { |key, value| "#{key}=\"#{value}\"" }.join ' '
24
+
25
+ tag = "<#{name} #{opts} />"
26
+ elsif args.empty?
27
+ tag = "<#{name}>#{inner}</#{name}>"
28
+ elsif (args.length == 1) && args[0].is_a?(Hash)
29
+ options = args[0]
30
+ opts = options.map { |key, value| "#{key}=\"#{value}\"" }.join ' '
31
+ tag = "<#{name} #{opts}>#{inner}</#{name}>"
32
+ end
33
+
34
+ @inner_content << tag
35
+ tag
36
+ end
37
+
38
+ def root
39
+ @page.root
40
+ end
41
+
42
+ def request_js(path)
43
+ @page.request_js(path)
44
+ end
45
+
46
+ def request_css(path)
47
+ @page.request_css(path)
48
+ end
49
+
50
+ def on_page_load(script)
51
+ @page.on_page_load(script)
52
+ end
53
+
54
+ def write_script_once(script)
55
+ @page.write_script_once(script)
56
+ end
57
+
58
+ def background(&block)
59
+ @page.background(block)
60
+ end
61
+
62
+ def on_page_load(script)
63
+ @page.on_page_load(script)
64
+ end
65
+
66
+ def icon(type)
67
+ iconname = type.to_s.tr('_', '-')
68
+ if type.is_a? Symbol
69
+ i class: "fa fa-#{iconname}" do
70
+ end
71
+ else
72
+ i class: 'fa' do
73
+ text type
74
+ end
75
+ end
76
+ end
77
+
78
+ def wform(options = {}, &block)
79
+ theform = Form.new(@page, @anchors, options, &block)
80
+ @inner_content << theform.generate
81
+ @page.scripts << theform.generate_script
82
+ end
83
+
84
+ def ibox(options = {}, &block)
85
+ panel = Panel.new(@page, @anchors, options)
86
+ panel.instance_eval(&block)
87
+ @inner_content << panel.generate
88
+ end
89
+
90
+ def center(content = nil, options = {}, &block)
91
+ options[:style] = '' unless options[:style]
92
+
93
+ options[:style] += '; text-align: center;'
94
+ if !content
95
+ div options, &block
96
+ else
97
+ div content, options, &block
98
+ end
99
+ end
100
+
101
+ def panel(title, &block)
102
+ div class: 'panel panel-default' do
103
+ div class: 'panel-heading' do
104
+ h5 title
105
+ end
106
+ div class: 'panel-body', &block
107
+ end
108
+ end
109
+
110
+ def tabs(&block)
111
+ tabs = Tabs.new(@page, @anchors)
112
+ tabs.instance_eval(&block)
113
+
114
+ @inner_content << tabs.generate
115
+ end
116
+
117
+ def syntax(lang = :javascript, &block)
118
+ code = Code.new(@page, @anchors, lang)
119
+ code.instance_eval(&block)
120
+
121
+ @inner_content << code.generate
122
+
123
+ @page.scripts << code.generate_script
124
+ end
125
+
126
+ def image(name, options = {})
127
+ style = (options[:style]).to_s
128
+ if options[:rounded_corners] == true
129
+ style += ' border-radius: 8px'
130
+ elsif options[:rounded_corners] == :top
131
+ style += ' border-radius: 8px 8px 0px 0px'
132
+ else
133
+ style += " border-radius: #{options[:rounded_corners]}px" if options[:rounded_corners]
134
+
135
+ end
136
+
137
+ img_options = {
138
+ class: "img-responsive #{options[:class]}",
139
+ src: "#{@page.root}images/#{name}",
140
+ style: style
141
+ }
142
+ img_options[:id] = options[:id] if options[:id]
143
+
144
+ img img_options
145
+ end
146
+
147
+ def crossfade_image(image_normal, image_hover)
148
+ div class: 'crossfade' do
149
+ image image_hover, class: 'bottom'
150
+ image image_normal, class: 'top'
151
+ end
152
+ image image_hover
153
+ @page.request_css 'css/crossfade_style.css'
154
+ end
155
+
156
+ def gallery(images, thumbnails = images, options = {})
157
+ @page.request_css 'css/plugins/blueimp/css/blueimp-gallery.min.css'
158
+
159
+ div class: 'lightBoxGallery' do
160
+ (0...images.length).to_a.each do |index|
161
+ title = options[:titles][index] if options[:titles]
162
+
163
+ a href: (images[index]).to_s, title: title.to_s, "data-gallery": '' do
164
+ img src: (thumbnails[index]).to_s, style: 'margin: 5px;'
165
+ end
166
+ end
167
+
168
+ div id: 'blueimp-gallery', class: 'blueimp-gallery' do
169
+ div class: 'slides' do end
170
+ h3 class: 'title' do end
171
+ a class: 'prev' do end
172
+ a class: 'next' do end
173
+ a class: 'close' do end
174
+ a class: 'play-pause' do end
175
+ ol class: 'indicator' do end
176
+ end
177
+ end
178
+
179
+ @page.request_js 'js/plugins/blueimp/jquery.blueimp-gallery.min.js'
180
+ end
181
+
182
+ def breadcrumb(patharray)
183
+ ol class: 'breadcrumb' do
184
+ patharray.each do |path|
185
+ li path
186
+ end
187
+ end
188
+ end
189
+
190
+ def p(*args, &block)
191
+ method_missing(:p, *args, &block)
192
+ end
193
+
194
+ def text(theText)
195
+ @inner_content << theText
196
+ end
197
+
198
+ def badge(label, options = {})
199
+ options[:type] ||= 'plain'
200
+
201
+ kind = 'label'
202
+ kind = 'badge' if options[:rounded]
203
+ tag_options = options.clone
204
+ tag_options[:class] = "#{kind} #{kind}-#{options[:type]}"
205
+
206
+ span tag_options do
207
+ text label
208
+ end
209
+ end
210
+
211
+ def hyperlink(url, title = nil, &block)
212
+ title ||= url
213
+
214
+ if url.start_with? '/'
215
+ url.sub!(%r{^/}, @page.root)
216
+ if block
217
+ a href: url, &block
218
+ else
219
+ a title, href: url
220
+ end
221
+ else
222
+
223
+ if block
224
+ a href: url, target: '_blank' do
225
+ span do
226
+ span &block
227
+ icon :external_link
228
+ end
229
+ end
230
+ else
231
+ a href: url, target: '_blank' do
232
+ span do
233
+ text title
234
+ text ' '
235
+ icon :external_link
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ def widget(options = {}, &block)
243
+ # gray-bg
244
+ # white-bg
245
+ # navy-bg
246
+ # blue-bg
247
+ # lazur-bg
248
+ # yellow-bg
249
+ # red-bg
250
+ # black-bg
251
+
252
+ color = "#{options[:color]}-bg" || 'navy-bg'
253
+
254
+ div class: "widget style1 #{color}", &block
255
+ end
256
+
257
+ def jumbotron(options = {}, &block)
258
+ additional_style = ''
259
+
260
+ if options[:background]
261
+ additional_style += " background-image: url('#{@page.root}images/#{options[:background]}'); background-position: center center; background-size: cover;"
262
+ end
263
+
264
+ additional_style += " height: #{options[:height]}px;" if options[:height]
265
+
266
+ if options[:min_height]
267
+ additional_style += " min-height: #{options[:min_height]}px;"
268
+ end
269
+
270
+ if options[:max_height]
271
+ additional_style += " max-height: #{options[:max_height]}px;"
272
+ end
273
+
274
+ div class: 'jumbotron', style: additional_style, &block
275
+ end
276
+
277
+ def _button(options = {}, &block)
278
+ anIcon = options[:icon]
279
+ title = options[:title]
280
+
281
+ if title.is_a? Hash
282
+ options.merge! title
283
+ title = anIcon
284
+ anIcon = nil
285
+ end
286
+
287
+ style = options[:style] || :primary
288
+ size = "btn-#{options[:size]}" if options[:size]
289
+ blockstyle = 'btn-block' if options[:block]
290
+ outline = 'btn-outline' if options[:outline]
291
+ dim = 'dim' if options[:threedee]
292
+ dim = 'dim btn-large-dim' if options[:bigthreedee]
293
+ dim = 'btn-rounded' if options[:rounded]
294
+ dim = 'btn-circle' if options[:circle]
295
+
296
+ buttonOptions = {
297
+ type: options[:type] || 'button',
298
+ class: "btn btn-#{style} #{size} #{blockstyle} #{outline} #{dim}",
299
+ id: options[:id]
300
+ }
301
+
302
+ if block
303
+ closer = ''
304
+
305
+ closer = '; return false;' if options[:nosubmit]
306
+
307
+ action = Action.new(@page, @anchors, &block)
308
+ buttonOptions[:onclick] = "#{action.name}(this)"
309
+ buttonOptions[:onclick] = "#{action.name}(this, #{options[:data]})#{closer}" if options[:data]
310
+ @page.scripts << action.generate
311
+ end
312
+
313
+ type = :button
314
+
315
+ buttonOptions[:"data-toggle"] = 'button' if options[:toggle]
316
+ type = :a if options[:toggle]
317
+
318
+ method_missing type, buttonOptions do
319
+ if title.is_a? Symbol
320
+ icon title
321
+ else
322
+ icon anIcon if anIcon
323
+ text ' ' if anIcon
324
+ text title
325
+ end
326
+ end
327
+ end
328
+
329
+ def normal_button(anIcon, title = {}, options = {}, &block)
330
+ options[:icon] = anIcon
331
+ options[:title] = title
332
+ _button(options, &block)
333
+ end
334
+
335
+ def block_button(anIcon, title = {}, options = {}, &block)
336
+ options[:block] = true
337
+ options[:icon] = anIcon
338
+ options[:title] = title
339
+ _button(options, &block)
340
+ end
341
+
342
+ def outline_button(anIcon, title = {}, options = {}, &block)
343
+ options[:outline] = true
344
+ options[:icon] = anIcon
345
+ options[:title] = title
346
+ _button(options, &block)
347
+ end
348
+
349
+ def big_button(anIcon, title = {}, options = {}, &block)
350
+ options[:size] = :lg
351
+ options[:icon] = anIcon
352
+ options[:title] = title
353
+ _button(options, &block)
354
+ end
355
+
356
+ def small_button(anIcon, title = {}, options = {}, &block)
357
+ options[:size] = :sm
358
+ options[:icon] = anIcon
359
+ options[:title] = title
360
+ _button(options, &block)
361
+ end
362
+
363
+ def tiny_button(anIcon, title = {}, options = {}, &block)
364
+ options[:size] = :xs
365
+ options[:icon] = anIcon
366
+ options[:title] = title
367
+ _button(options, &block)
368
+ end
369
+
370
+ def embossed_button(anIcon, title = {}, options = {}, &block)
371
+ options[:threedee] = true
372
+ options[:icon] = anIcon
373
+ options[:title] = title
374
+ _button(options, &block)
375
+ end
376
+
377
+ def big_embossed_button(anIcon, title = {}, options = {}, &block)
378
+ options[:bigthreedee] = true
379
+ options[:icon] = anIcon
380
+ options[:title] = title
381
+ _button(options, &block)
382
+ end
383
+
384
+ def rounded_button(anIcon, title = {}, options = {}, &block)
385
+ options[:rounded] = true
386
+ options[:icon] = anIcon
387
+ options[:title] = title
388
+ _button(options, &block)
389
+ end
390
+
391
+ def circle_button(anIcon, title = {}, options = {}, &block)
392
+ options[:circle] = true
393
+ options[:icon] = anIcon
394
+ options[:title] = title
395
+ _button(options, &block)
396
+ end
397
+
398
+ def math(string)
399
+ text "$$$MATH$$$#{string}$$$ENDMATH$$$"
400
+ end
401
+
402
+ def generate
403
+ @inner_content.join
404
+ end
405
+ end
406
+ end