weaver 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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