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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 64d0021b8ab6a2f1c556c7708d40daa45c13b508
4
- data.tar.gz: c3b8f985efa4e770335708c0f59653de2fab749e
2
+ SHA256:
3
+ metadata.gz: 58b4fd7e453a9af4450002b361dd04c8470bf5df46c0efa0b2fa22d5b6ba0291
4
+ data.tar.gz: cb2eab30ee9995f172650fb38ea2eb8425518b930712018b8e8d155544aa6231
5
5
  SHA512:
6
- metadata.gz: 4e5339d77dcd36e560dd84ce6448a81fd07837d4a1da90a8cbbe94f38e52bff1634f40d50aa698278b4d3b460c467269aa5f0fc16283fabf3e5ce7ab62958f67
7
- data.tar.gz: 9d04d3c42cc0a707d9302dac8c47b2f2911d5807b1a1a8c82c0a2b030af2c330b0f156b03d48915aa5bd2416664d8107161f74ed5593e8394b588aa8bc55ac54
6
+ metadata.gz: 9fcf769a71319280c0b2b0373baaf22547d7e09d250513d3dcc033c09c7b18915dc86ab97f683b286e7fcc5906791bc6e7db8a044ea0bcf901fe49a5d3a5d0d8
7
+ data.tar.gz: 8ac7ecf0c589fed852fd973395d056f867d444e5c77ab5576b689d6402086f730bce10ed5866136904ee8f247b1bb9a5a83fbbb6e4894cefa16a8d607ae32982
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "weaver"
3
+ require 'bundler/setup'
4
+ require 'weaver'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "weaver"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start
data/exe/weaver CHANGED
@@ -5,160 +5,150 @@ require 'optimist'
5
5
  require 'sinatra/base'
6
6
 
7
7
  class Website < Sinatra::Base
8
+ set :static, true # set up static file routing
9
+ set :public_folder, File.join(Gem.loaded_specs['weaver'].full_gem_path, 'data', 'weaver') # set up the static dir (with images/js/css inside)
10
+ set :bind, '0.0.0.0'
11
+ set :port, ENV['PORT'] || 4567
8
12
 
9
- set :static, true # set up static file routing
10
- set :public_folder, File.join(Gem.loaded_specs['weaver'].full_gem_path, "data", "weaver") # set up the static dir (with images/js/css inside)
11
- set :bind, '0.0.0.0'
12
- set :port, ENV['PORT'] || 4567
13
+ def getWeavefile(viewname)
14
+ pathToFile = viewname.split('/').delete_if(&:empty?)
13
15
 
14
- def getWeavefile(viewname)
16
+ viewFile = nil
15
17
 
16
- pathToFile = viewname.split("/").delete_if(&:empty?)
18
+ remainingPath = []
17
19
 
18
- viewFile = nil
20
+ loop do
21
+ path = "#{File.join(['source'] + pathToFile)}.weave"
22
+ indexPath = File.join(['source'] + pathToFile + ['index.weave'])
19
23
 
20
- remainingPath = []
24
+ # puts path
25
+ # puts indexPath
21
26
 
22
- loop do
23
- path = "#{File.join(['source'] + pathToFile)}.weave"
24
- indexPath = File.join(["source"] + pathToFile + ["index.weave"])
27
+ viewFile = path if File.exist?(path)
28
+ viewFile = indexPath if File.exist?(indexPath)
25
29
 
26
- #puts path
27
- #puts indexPath
30
+ break if viewFile || pathToFile.empty?
28
31
 
29
- viewFile = path if File.exists?(path)
30
- viewFile = indexPath if File.exists?(indexPath)
32
+ remainingPath << pathToFile.last
31
33
 
32
- break if viewFile or pathToFile.length == 0
34
+ pathToFile = pathToFile.first pathToFile.size - 1
35
+ end
33
36
 
34
- remainingPath << pathToFile.last
37
+ { viewFile: viewFile, path: remainingPath }
38
+ end
35
39
 
36
- pathToFile = pathToFile.first pathToFile.size-1
37
- end
40
+ get '/*' do
41
+ if params[:splat].first.start_with? 'images/'
42
+ return send_file(params[:splat].first, disposition: 'inline')
43
+ end
38
44
 
39
- { viewFile: viewFile, path: remainingPath }
40
- end
41
-
42
- get '/*' do
43
-
44
- if params[:splat].first.start_with? "images/"
45
- return send_file(params[:splat].first, :disposition => 'inline')
46
- end
45
+ if params[:splat].first.start_with? 'js/'
46
+ return send_file(params[:splat].first, disposition: 'inline')
47
+ end
47
48
 
48
- if params[:splat].first.start_with? "js/"
49
- return send_file(params[:splat].first, :disposition => 'inline')
50
- end
49
+ if params[:splat].first.start_with? 'css/'
50
+ return send_file(params[:splat].first, disposition: 'inline')
51
+ end
51
52
 
52
- if params[:splat].first.start_with? "css/"
53
- return send_file(params[:splat].first, :disposition => 'inline')
54
- end
53
+ viewname = params[:splat].first
54
+ result = getWeavefile viewname
55
+ viewFile = result[:viewFile]
56
+ path = File.join(result[:path].reverse)
55
57
 
58
+ if viewFile
56
59
 
57
- viewname = params[:splat].first
58
- result = getWeavefile viewname
59
- viewFile = result[:viewFile]
60
- path = File.join(result[:path].reverse)
60
+ site = Weaver::Weave.new(viewFile)
61
61
 
62
- if viewFile
62
+ if site.pages.key?(path)
63
63
 
64
- site = Weaver::Weave.new(viewFile)
65
-
66
- if site.pages.has_key?(path)
67
-
68
- level = viewname.split(/\//, 0).length
69
- site.pages[path].generate(level)
70
-
71
- else
72
- puts "Not found: #{viewname} in #{viewFile}"
73
- puts "Path is: #{path}"
74
- status 404
75
- end
76
- else
77
- puts "Not found: #{viewname} in #{viewFile}"
78
- puts "Path is: #{path}"
79
- status 404
80
- end
81
- end
64
+ level = viewname.split(%r{/}, 0).length
65
+ site.pages[path].generate(level)
82
66
 
67
+ else
68
+ puts "Not found: #{viewname} in #{viewFile}"
69
+ puts "Path is: #{path}"
70
+ status 404
71
+ end
72
+ else
73
+ puts "Not found: #{viewname} in #{viewFile}"
74
+ puts "Path is: #{path}"
75
+ status 404
76
+ end
77
+ end
83
78
  end
84
79
 
85
- def build!(args)
86
-
87
- opts = Optimist::options do
88
- banner <<-EOS
80
+ def build!(_args)
81
+ opts = Optimist.options do
82
+ banner <<-EOS
89
83
  Generate website
90
84
 
91
85
  Usage:
92
86
  weaver build [options]
93
87
  where [options] are:
94
- EOS
88
+ EOS
95
89
 
96
- opt :root, "The root URL to be used in links (e.g.) https://astrobunny.net", type: :string, default: "/"
97
- end
90
+ opt :root, 'The root URL to be used in links (e.g.) https://astrobunny.net', type: :string, default: '/'
91
+ end
98
92
 
99
- puts "Building site..."
100
-
101
- buildDir = "#{Dir.pwd}/build"
93
+ puts 'Building site...'
102
94
 
103
- cp_r_options = {preserve: true}
95
+ buildDir = "#{Dir.pwd}/build"
104
96
 
105
- FileUtils::rm_rf buildDir
106
- FileUtils.cp_r(File.join(Gem.loaded_specs['weaver'].full_gem_path, "data", "weaver"), buildDir, cp_r_options)
107
- if Dir.exist? "images"
108
- FileUtils.cp_r("images", buildDir, cp_r_options)
109
- end
110
- if Dir.exist? "js"
111
- Dir["js/*.*"].each do |x|
112
- FileUtils.cp_r(x, File.join(buildDir, "js"), cp_r_options)
113
- end
114
- end
115
- if Dir.exist? "css"
116
- Dir["css/*.*"].each do |x|
117
- FileUtils.cp_r(x, File.join(buildDir, "css"), cp_r_options)
118
- end
119
- end
97
+ cp_r_options = { preserve: true }
120
98
 
121
- files = Dir["source/**/*.weave"]
122
- files.each do |file|
123
- baseDir = file.chomp('.weave').chomp('index').sub(/^source\//, "")
99
+ FileUtils.rm_rf buildDir
100
+ FileUtils.cp_r(File.join(Gem.loaded_specs['weaver'].full_gem_path, 'data', 'weaver'), buildDir, cp_r_options)
101
+ FileUtils.cp_r('images', buildDir, cp_r_options) if Dir.exist? 'images'
102
+ if Dir.exist? 'js'
103
+ Dir['js/*.*'].each do |x|
104
+ FileUtils.cp_r(x, File.join(buildDir, 'js'), cp_r_options)
105
+ end
106
+ end
107
+ if Dir.exist? 'css'
108
+ Dir['css/*.*'].each do |x|
109
+ FileUtils.cp_r(x, File.join(buildDir, 'css'), cp_r_options)
110
+ end
111
+ end
124
112
 
125
- site = Weaver::Weave.new(file, opts)
113
+ files = Dir['source/**/*.weave']
114
+ files.each do |file|
115
+ baseDir = file.chomp('.weave').chomp('index').sub(%r{^source/}, '')
126
116
 
127
- site.pages.each do |localPath, page|
128
- resultPath = File.join(baseDir, localPath)
117
+ site = Weaver::Weave.new(file, opts)
129
118
 
130
- level = resultPath.split(/\//, 0).select{|x| x.length != 0}.length
119
+ site.pages.each do |localPath, page|
120
+ resultPath = File.join(baseDir, localPath)
131
121
 
132
- puts "Writing: #{file} -> #{resultPath} (Level: #{level})"
122
+ level = resultPath.split(%r{/}, 0).reject(&:empty?).length
133
123
 
134
- fileName = File.join([buildDir, resultPath, "index.html"])
135
- FileUtils::mkdir_p File.dirname(fileName)
136
- File.write(fileName, page.generate(level))
137
- end
138
- end
124
+ puts "Writing: #{file} -> #{resultPath} (Level: #{level})"
139
125
 
126
+ fileName = File.join([buildDir, resultPath, 'index.html'])
127
+ FileUtils.mkdir_p File.dirname(fileName)
128
+ File.write(fileName, page.generate(level))
129
+ end
130
+ end
140
131
  end
141
132
 
142
133
  def preview!
143
- puts "Weaver Preview Mode in: #{Dir.pwd}"
134
+ puts "Weaver Preview Mode in: #{Dir.pwd}"
144
135
 
145
- Website.run!
136
+ Website.run!
146
137
  end
147
138
 
148
139
  def create!(args)
140
+ if args.length != 1
141
+ puts 'Usage: weaver create <folder>'
142
+ return
143
+ end
149
144
 
150
- if args.length != 1
151
- puts "Usage: weaver create <folder>"
152
- return
153
- end
154
-
155
- gemfile = <<-GEMFILE
145
+ gemfile = <<-GEMFILE
156
146
  source 'https://rubygems.org'
157
147
 
158
148
  gem 'weaver', '~> #{Weaver::VERSION}'
159
- GEMFILE
149
+ GEMFILE
160
150
 
161
- source = <<-SOURCE
151
+ source = <<-SOURCE
162
152
  topnav_page "", "My first weaver page" do
163
153
  header do
164
154
  col 12 do
@@ -174,25 +164,25 @@ topnav_page "", "My first weaver page" do
174
164
  end
175
165
  end
176
166
  end
177
- SOURCE
178
-
179
- to_create = "#{args[0]}"
180
- FileUtils::mkdir_p "#{to_create}"
181
- FileUtils::mkdir_p "#{to_create}/cache"
182
- File.write("#{to_create}/cache/this_directory_is_used_by_weaver_as_a_cache","")
183
- FileUtils::mkdir_p "#{to_create}/source"
184
- FileUtils::mkdir_p "#{to_create}/images"
185
- FileUtils::mkdir_p "#{to_create}/js"
186
- FileUtils::mkdir_p "#{to_create}/css"
187
- File.write "#{to_create}/Gemfile", gemfile
188
- File.write "#{to_create}/source/index.weave", source
167
+ SOURCE
168
+
169
+ to_create = (args[0]).to_s
170
+ FileUtils.mkdir_p to_create.to_s
171
+ FileUtils.mkdir_p "#{to_create}/cache"
172
+ File.write("#{to_create}/cache/this_directory_is_used_by_weaver_as_a_cache", '')
173
+ FileUtils.mkdir_p "#{to_create}/source"
174
+ FileUtils.mkdir_p "#{to_create}/images"
175
+ FileUtils.mkdir_p "#{to_create}/js"
176
+ FileUtils.mkdir_p "#{to_create}/css"
177
+ File.write "#{to_create}/Gemfile", gemfile
178
+ File.write "#{to_create}/source/index.weave", source
189
179
  end
190
180
 
191
181
  command = ARGV.shift
192
- if command == "build"
193
- build!(ARGV)
194
- elsif command == "create"
195
- create!(ARGV)
182
+ if command == 'build'
183
+ build!(ARGV)
184
+ elsif command == 'create'
185
+ create!(ARGV)
196
186
  else
197
- preview!
187
+ preview!
198
188
  end
@@ -1,2659 +1,29 @@
1
- require "weaver/version"
1
+ require 'weaver/version'
2
2
 
3
3
  require 'fileutils'
4
4
  require 'json'
5
5
  require 'active_support/core_ext/object/to_query'
6
6
 
7
- module Weaver
8
-
9
- class Elements
10
-
11
- def initialize(page, anchors)
12
- @inner_content = []
13
- @anchors = anchors
14
- @page = page
15
- end
16
-
17
- def method_missing(name, *args, &block)
18
- tag = "<#{name} />"
19
-
20
- if args[0].is_a? String
21
- inner = args.shift
22
- end
23
- if block
24
- elem = Elements.new(@page, @anchors)
25
- elem.instance_eval(&block)
26
- inner = elem.generate
27
- end
28
-
29
- if !inner
30
-
31
- options = args[0] || []
32
- opts = options.map { |key,value| "#{key}=\"#{value}\"" }.join " "
33
-
34
- tag = "<#{name} #{opts} />"
35
- elsif args.length == 0
36
- tag = "<#{name}>#{inner}</#{name}>"
37
- elsif args.length == 1 and args[0].is_a? Hash
38
- options = args[0]
39
- opts = options.map { |key,value| "#{key}=\"#{value}\"" }.join " "
40
- tag = "<#{name} #{opts}>#{inner}</#{name}>"
41
- end
42
-
43
- @inner_content << tag
44
- tag
45
- end
46
-
47
- def root
48
- @page.root
49
- end
50
-
51
- def request_js(path)
52
- @page.request_js(path)
53
- end
54
-
55
- def request_css(path)
56
- @page.request_css(path)
57
- end
58
-
59
- def on_page_load(script)
60
- @page.on_page_load(script)
61
- end
62
-
63
- def write_script_once(script)
64
- @page.write_script_once(script)
65
- end
66
-
67
- def background(&block)
68
- @page.background(block)
69
- end
70
-
71
- def on_page_load(script)
72
- @page.on_page_load(script)
73
- end
74
-
75
- def icon(type)
76
- iconname = type.to_s.gsub(/_/, "-")
77
- if type.is_a? Symbol
78
- i class: "fa fa-#{iconname}" do
79
- end
80
- else
81
- i class: "fa" do
82
- text type
83
- end
84
- end
85
- end
86
-
87
- def wform(options={}, &block)
88
- theform = Form.new(@page, @anchors, options, &block)
89
- @inner_content << theform.generate
90
- @page.scripts << theform.generate_script
91
- end
92
-
93
- def ibox(options={}, &block)
94
- panel = Panel.new(@page, @anchors, options)
95
- panel.instance_eval(&block)
96
- @inner_content << panel.generate
97
- end
98
-
99
- def center(content=nil, options={}, &block)
100
-
101
- if !options[:style]
102
- options[:style] = ""
103
- end
104
-
105
- options[:style] += "; text-align: center;"
106
- if !content
107
- div options, &block
108
- else
109
- div content, options, &block
110
- end
111
- end
112
-
113
- def panel(title, &block)
114
- div class: "panel panel-default" do
115
- div class: "panel-heading" do
116
- h5 title
117
- end
118
- div class: "panel-body", &block
119
- end
120
- end
121
-
122
- def tabs(&block)
123
- tabs = Tabs.new(@page, @anchors)
124
- tabs.instance_eval(&block)
125
-
126
- @inner_content << tabs.generate
127
- end
128
-
129
- def syntax(lang=:javascript, &block)
130
- code = Code.new(@page, @anchors, lang)
131
- code.instance_eval(&block)
132
-
133
- @inner_content << code.generate
134
-
135
- @page.scripts << code.generate_script
136
- end
137
-
138
- def image(name, options={})
139
-
140
- style = "#{options[:style]}"
141
- if options[:rounded_corners] == true
142
- style += " border-radius: 8px"
143
- elsif options[:rounded_corners] == :top
144
- style += " border-radius: 8px 8px 0px 0px"
145
- else
146
- style += " border-radius: #{options[:rounded_corners]}px" if options[:rounded_corners]
147
-
148
- end
149
-
150
- img_options = {
151
- class: "img-responsive #{options[:class]}",
152
- src: "#{@page.root}images/#{name}",
153
- style: style
154
- }
155
- img_options[:id] = options[:id] if options[:id]
156
-
157
- img img_options
158
- end
159
-
160
- def crossfade_image(image_normal, image_hover)
161
- div class: "crossfade" do
162
- image image_hover, class: "bottom"
163
- image image_normal, class: "top"
164
- end
165
- image image_hover
166
- @page.request_css "css/crossfade_style.css"
167
- end
168
-
169
- def gallery(images, thumbnails=images, options={}, &block)
170
-
171
- @page.request_css "css/plugins/blueimp/css/blueimp-gallery.min.css"
172
-
173
- div class:"lightBoxGallery" do
174
- (0...images.length).to_a.each do |index|
175
-
176
- title = options[:titles][index] if options[:titles]
177
-
178
- a href:"#{images[index]}", title: "#{title}", :"data-gallery"=> "" do
179
- img src:"#{thumbnails[index]}", style: "margin: 5px;"
180
- end
181
- end
182
-
183
- div id:"blueimp-gallery", class:"blueimp-gallery" do
184
- div class:"slides" do end
185
- h3 class:"title" do end
186
- a class:"prev" do end
187
- a class:"next" do end
188
- a class:"close" do end
189
- a class:"play-pause" do end
190
- ol class:"indicator" do end
191
- end
192
- end
193
-
194
- @page.request_js "js/plugins/blueimp/jquery.blueimp-gallery.min.js"
195
-
196
- end
197
-
198
- def breadcrumb(patharray)
199
- ol class: "breadcrumb" do
200
- patharray.each do |path|
201
- li path
202
- end
203
- end
204
- end
205
-
206
- def p(*args, &block)
207
- method_missing(:p, *args, &block)
208
- end
209
-
210
- def text(theText)
211
- @inner_content << theText
212
- end
213
-
214
- def badge(label, options={})
215
- options[:type] ||= "plain"
216
-
217
- kind = "label"
218
- kind = "badge" if options[:rounded]
219
- tag_options = options.clone
220
- tag_options[:class] = "#{kind} #{kind}-#{options[:type]}"
221
-
222
- span tag_options do
223
- text label
224
- end
225
- end
226
-
227
- def hyperlink(url, title=nil, &block)
228
- if !title
229
- title = url
230
- end
231
-
232
- if url.start_with? "/"
233
- url.sub!(/^\//, @page.root)
234
- if block
235
- a href: url, &block
236
- else
237
- a title, href: url
238
- end
239
- else
240
-
241
- if block
242
- a href: url, target: "_blank" do
243
- span do
244
- span &block
245
- icon :external_link
246
- end
247
- end
248
- else
249
- a href: url, target: "_blank" do
250
- span do
251
- text title
252
- text " "
253
- icon :external_link
254
- end
255
- end
256
- end
257
- end
258
-
259
-
260
-
261
- end
262
-
263
- def accordion(&block)
264
- acc = Accordion.new(@page, @anchors)
265
- acc.instance_eval(&block)
266
-
267
- @inner_content << acc.generate
268
- end
269
-
270
- def widget(options={}, &block)
271
- #gray-bg
272
- #white-bg
273
- #navy-bg
274
- #blue-bg
275
- #lazur-bg
276
- #yellow-bg
277
- #red-bg
278
- #black-bg
279
-
280
- color = "#{options[:color]}-bg" || "navy-bg"
281
-
282
- div :class => "widget style1 #{color}", &block
283
- end
284
-
285
- def row(options={}, &block)
286
- options[:class] = "row"
287
- div options do
288
- instance_eval(&block)
289
- end
290
- end
291
-
292
- def twothirds(&block)
293
- opts =
294
- {
295
- xs: 12,
296
- sm: 12,
297
- md: 8,
298
- lg: 8
299
- }
300
- col(4, opts, &block)
301
- end
302
-
303
- def half(&block)
304
- opts =
305
- {
306
- xs: 12,
307
- sm: 12,
308
- md: 12,
309
- lg: 6
310
- }
311
- col(4, opts, &block)
312
- end
313
-
314
- def third(&block)
315
- opts =
316
- {
317
- xs: 12,
318
- sm: 12,
319
- md: 4,
320
- lg: 4
321
- }
322
- col(4, opts, &block)
323
- end
324
-
325
- def quarter(&block)
326
- opts =
327
- {
328
- xs: 12,
329
- sm: 12,
330
- md: 6,
331
- lg: 3
332
- }
333
- col(3, opts, &block)
334
- end
335
-
336
- def col(occupies, options={}, &block)
337
-
338
- xs = options[:xs] || occupies
339
- sm = options[:sm] || occupies
340
- md = options[:md] || occupies
341
- lg = options[:lg] || occupies
342
-
343
- hidden = ""
344
-
345
- xs_style = "col-xs-#{xs}" unless options[:xs] == 0
346
- sm_style = "col-sm-#{sm}" unless options[:sm] == 0
347
- md_style = "col-md-#{md}" unless options[:md] == 0
348
- lg_style = "col-lg-#{lg}" unless options[:lg] == 0
349
-
350
- hidden += "hidden-xs " if options[:xs] == 0
351
- hidden += "hidden-sm " if options[:sm] == 0
352
- hidden += "hidden-md " if options[:md] == 0
353
- hidden += "hidden-lg " if options[:lg] == 0
354
-
355
- div_options = {
356
- class: "#{xs_style} #{sm_style} #{md_style} #{lg_style} #{hidden}",
357
- style: options[:style]
358
- }
359
-
360
- div div_options do
361
- instance_eval(&block)
362
- end
363
- end
364
-
365
-
366
- def jumbotron(options={}, &block)
367
-
368
- additional_style = ""
369
-
370
- if options[:background]
371
- additional_style += " background-image: url('#{@page.root}images/#{options[:background]}'); background-position: center center; background-size: cover;"
372
- end
373
-
374
- if options[:height]
375
- additional_style += " height: #{options[:height]}px;"
376
- end
377
-
378
- if options[:min_height]
379
- additional_style += " min-height: #{options[:min_height]}px;"
380
- end
381
-
382
- if options[:max_height]
383
- additional_style += " max-height: #{options[:max_height]}px;"
384
- end
385
-
386
- div :class => "jumbotron", style: additional_style, &block
387
- end
388
-
389
- def modal(id=nil, &block)
390
- mm = ModalDialog.new(@page, @anchors, id, &block)
391
- @inner_content << mm.generate
392
- end
393
-
394
- def _button(options={}, &block)
395
-
396
- anIcon = options[:icon]
397
- title = options[:title]
398
-
399
- if title.is_a? Hash
400
- options.merge! title
401
- title = anIcon
402
- anIcon = nil
403
- end
404
-
405
- style = options[:style] || :primary
406
- size = "btn-#{options[:size]}" if options[:size]
407
- blockstyle = "btn-block" if options[:block]
408
- outline = "btn-outline" if options[:outline]
409
- dim = "dim" if options[:threedee]
410
- dim = "dim btn-large-dim" if options[:bigthreedee]
411
- dim = "btn-rounded" if options[:rounded]
412
- dim = "btn-circle" if options[:circle]
413
-
414
- buttonOptions = {
415
- :type => options[:type] || "button",
416
- :class => "btn btn-#{style} #{size} #{blockstyle} #{outline} #{dim}",
417
- :id => options[:id]
418
- }
419
-
420
- if block
421
- closer = ""
422
-
423
- closer = "; return false;" if options[:nosubmit]
424
-
425
- action = Action.new(@page, @anchors, &block)
426
- buttonOptions[:onclick] = "#{action.name}(this)"
427
- buttonOptions[:onclick] = "#{action.name}(this, #{options[:data]})#{closer}" if options[:data]
428
- @page.scripts << action.generate
429
- end
430
-
431
- type = :button
432
-
433
- buttonOptions[:"data-toggle"] = "button" if options[:toggle]
434
- type = :a if options[:toggle]
435
-
436
-
437
- method_missing type, buttonOptions do
438
- if title.is_a? Symbol
439
- icon title
440
- else
441
- icon anIcon if anIcon
442
- text " " if anIcon
443
- text title
444
- end
445
- end
446
- end
447
-
448
- def normal_button(anIcon, title={}, options={}, &block)
449
- options[:icon] = anIcon
450
- options[:title] = title
451
- _button(options, &block)
452
- end
453
-
454
- def block_button(anIcon, title={}, options={}, &block)
455
- options[:block] = true
456
- options[:icon] = anIcon
457
- options[:title] = title
458
- _button(options, &block)
459
- end
460
-
461
- def outline_button(anIcon, title={}, options={}, &block)
462
- options[:outline] = true
463
- options[:icon] = anIcon
464
- options[:title] = title
465
- _button(options, &block)
466
- end
467
-
468
- def big_button(anIcon, title={}, options={}, &block)
469
- options[:size] = :lg
470
- options[:icon] = anIcon
471
- options[:title] = title
472
- _button(options, &block)
473
- end
474
-
475
- def small_button(anIcon, title={}, options={}, &block)
476
- options[:size] = :sm
477
- options[:icon] = anIcon
478
- options[:title] = title
479
- _button(options, &block)
480
- end
481
-
482
- def tiny_button(anIcon, title={}, options={}, &block)
483
- options[:size] = :xs
484
- options[:icon] = anIcon
485
- options[:title] = title
486
- _button(options, &block)
487
- end
488
-
489
- def embossed_button(anIcon, title={}, options={}, &block)
490
- options[:threedee] = true
491
- options[:icon] = anIcon
492
- options[:title] = title
493
- _button(options, &block)
494
- end
495
-
496
- def big_embossed_button(anIcon, title={}, options={}, &block)
497
- options[:bigthreedee] = true
498
- options[:icon] = anIcon
499
- options[:title] = title
500
- _button(options, &block)
501
- end
502
-
503
- def rounded_button(anIcon, title={}, options={}, &block)
504
- options[:rounded] = true
505
- options[:icon] = anIcon
506
- options[:title] = title
507
- _button(options, &block)
508
- end
509
-
510
- def circle_button(anIcon, title={}, options={}, &block)
511
- options[:circle] = true
512
- options[:icon] = anIcon
513
- options[:title] = title
514
- _button(options, &block)
515
- end
516
-
517
- def math(string)
518
- text "$$$MATH$$$#{string}$$$ENDMATH$$$"
519
- end
520
-
521
- def table(options={}, &block)
522
-
523
-
524
- table_name = options[:id] || @page.create_anchor("table")
525
- table_style = ""
526
-
527
-
528
- if options[:style] != nil
529
- table_style = options[:style]
530
- end
531
-
532
- classname = "table"
533
-
534
- classname += " table-bordered" if options[:bordered]
535
- classname += " table-hover" if options[:hover]
536
- classname += " table-striped" if options[:striped]
537
-
538
- table_options = {
539
- class: classname,
540
- id: table_name,
541
- style: table_style
542
- }
543
-
544
- if options[:system] == :data_table
545
- @page.request_js "js/plugins/dataTables/jquery.dataTables.js"
546
- @page.request_js "js/plugins/dataTables/dataTables.bootstrap.js"
547
- @page.request_js "js/plugins/dataTables/dataTables.responsive.js"
548
- @page.request_js "js/plugins/dataTables/dataTables.tableTools.min.js"
549
-
550
- @page.request_css "css/plugins/dataTables/dataTables.bootstrap.css"
551
- @page.request_css "css/plugins/dataTables/dataTables.responsive.css"
552
- @page.request_css "css/plugins/dataTables/dataTables.tableTools.min.css"
553
-
554
- @page.scripts << <<-DATATABLE_SCRIPT
555
- $('##{table_name}').DataTable();
556
- DATATABLE_SCRIPT
557
- end
558
-
559
- if options[:system] == :foo_table
560
- table_options[:"data-filtering"] = true
561
- table_options[:"data-sorting"] = true
562
- table_options[:"data-paging"] = true
563
- table_options[:"data-show-toggle"] = true
564
- table_options[:"data-toggle-column"] = "last"
565
-
566
- table_options[:"data-paging-size"] = "#{(options[:max_items_per_page] || 8).to_i}"
567
- table_options[:class] = table_options[:class] + " toggle-arrow-tiny"
568
-
569
-
570
- @page.request_js "js/plugins/footable/footable.all.min.js"
571
-
572
- @page.request_css "css/plugins/footable/footable.core.css"
573
-
574
- @page.scripts << <<-DATATABLE_SCRIPT
575
- $('##{table_name}').footable({
576
- paging: {
577
- size: #{(options[:max_items_per_page] || 8).to_i}
578
- }
579
- });
580
- $('##{table_name}').append(this.html).trigger('footable_redraw');
581
-
582
-
583
-
584
- DATATABLE_SCRIPT
585
-
586
- @page.onload_scripts << <<-SCRIPT
587
- SCRIPT
588
- end
589
-
590
-
591
- method_missing(:table, table_options, &block)
592
- ul class: "pagination"
593
- end
594
-
595
- def table_from_source(url, options={}, &block)
596
-
597
- dyn_table = DynamicTable.new(@page, @anchors, url, options, &block)
598
-
599
- text dyn_table.generate_table
600
-
601
- @page.scripts << dyn_table.generate_script
602
-
603
- end
604
-
605
- def table_from_hashes(hashes, options={})
606
-
607
- keys = {}
608
- hashes.each do |hash|
609
- hash.each do |key,value|
610
- keys[key] = ""
611
- end
612
- end
613
-
614
- table options do
615
-
616
- thead do
617
- keys.each do |key, _|
618
- th key.to_s
619
- end
620
- end
621
-
622
- tbody do
623
-
624
- hashes.each do |hash|
625
-
626
- tr do
627
- keys.each do |key, _|
628
- td "#{hash[key]}" || "&nbsp;"
629
- end
630
- end
631
- end
632
- end
633
- end
634
- end
635
-
636
- def generate
637
- @inner_content.join
638
- end
639
- end
640
-
641
- class ModalDialog
642
-
643
- def initialize(page, anchors, id, &block)
644
- @page = page
645
- @anchors = anchors
646
- @id = id || @page.create_anchor("modal")
647
-
648
- @header_content = Elements.new(@page, @anchors)
649
- @body_content = Elements.new(@page, @anchors)
650
- @footer_content = Elements.new(@page, @anchors)
651
-
652
- instance_eval(&block) if block
653
- end
654
-
655
- def id
656
- @id
657
- end
658
-
659
- def header(&block)
660
- @header_content.instance_eval(&block)
661
- end
662
-
663
- def body(&block)
664
- @body_content.instance_eval(&block)
665
- end
666
-
667
- def footer(&block)
668
- @footer_content.instance_eval(&block)
669
- end
670
-
671
- def generate
672
- elem = Elements.new(@page, @anchors)
673
-
674
- id = @id
675
- header_content = @header_content
676
- body_content = @body_content
677
- footer_content = @footer_content
678
-
679
- elem.instance_eval do
680
- div class: "modal fade", id: id, tabindex: -1, role: "dialog" do
681
- div class: "modal-dialog", role: "document" do
682
- div class: "modal-content" do
683
- div class: "modal-header" do
684
- button "&times;", type: "button", class: "close", :"data-dismiss" => "modal", :"aria-label" => "Close"
685
- text header_content.generate
686
- end
687
- div class: "modal-body" do
688
- text body_content.generate
689
- end
690
- div class: "modal-footer" do
691
- text footer_content.generate
692
- end
693
- end
694
- end
695
- end
696
- end
697
-
698
- elem.generate
699
-
700
- end
701
- end
702
-
703
- class DynamicTableCell < Elements
704
-
705
- attr_accessor :transform_script
706
-
707
- def data_button(anIcon, title={}, options={}, &block)
708
- options[:icon] = anIcon
709
- options[:title] = title
710
- options[:data] = "$(this).closest('td').data('object')"
711
- _button(options, &block)
712
- end
713
-
714
- def transform(script)
715
- @transform_script = script
716
- end
717
-
718
- end
719
-
720
- class JavaScriptObject
721
- def initialize(&block)
722
- @object = {}
723
- instance_eval(&block) if block
724
- end
725
-
726
- def string(name, string)
727
- @object[name] = {type: :string, value: string}
728
- end
729
-
730
- def variable(name, var_name)
731
- @object[name] = {type: :var, value: var_name}
732
- end
733
-
734
- def generate
735
- result = @object.map {
736
- |key,value|
737
-
738
- value_expression = value[:value]
739
-
740
- if value[:type] == :string
741
- value_expression = "\"#{value[:value]}\""
742
- end
743
-
744
- "#{key}: #{value_expression}"
745
-
746
- }.join ","
747
-
748
- "{#{result}}"
749
- end
750
-
751
- end
752
-
753
- class DynamicTable
754
-
755
- def initialize(page, anchors, url, options={}, &block)
756
- @page = page
757
- @anchors = anchors
758
- @url = url
759
- @options = options
760
- @columns = nil
761
- @query_object = nil
762
-
763
- self.instance_eval(&block) if block
764
-
765
- @options[:id] ||= @page.create_anchor "dyn_table"
766
- @table_name = @options[:id]
767
- @head_name = "#{@table_name}_head"
768
- @body_name = "#{@table_name}_body"
769
-
770
-
771
- end
772
-
773
- def column(name, options={}, &block)
774
- if @columns == nil
775
- @columns = []
776
- end
777
-
778
- title = options[:title] || name
779
- format = nil
780
- transform = nil
781
-
782
- if options[:icon]
783
- elem = Elements.new(@page, @anchors)
784
- elem.instance_eval do
785
- icon options[:icon]
786
- text " #{title}"
787
- end
788
- title = elem.generate
789
- end
790
-
791
- if block
792
- elem = DynamicTableCell.new(@page, @anchors)
793
- elem.instance_eval(&block)
794
- format = elem.generate
795
- if elem.transform_script
796
- func_name = @page.create_anchor "transform"
797
- @page.write_script_once <<-SCRIPT
798
- document.transform_#{func_name} = function (input)
799
- {
800
- #{elem.transform_script}
801
- }
802
- SCRIPT
803
-
804
- transform = func_name
805
- end
806
- end
807
-
808
- @columns << {name: name, title: title, format: format, transform: transform}
809
-
810
- end
811
-
812
- def generate_table
813
-
814
- table_name = @table_name
815
- head_name = @head_name
816
- body_name = @body_name
817
- options = @options
818
-
819
- columns = @columns || [ {title: "Key"}, {title: "Value"} ]
820
-
821
- elem = Elements.new(@page, @anchors)
822
- elem.instance_eval do
823
-
824
- table options do
825
- thead id: head_name do
826
- columns.each do |column, _|
827
- if column.is_a? Hash
828
- th column[:title].to_s
829
- else
830
- th column.to_s
831
- end
832
- end
833
- end
834
-
835
- tbody id: body_name do
836
- end
837
- end
838
- end
839
-
840
- elem.generate
841
- end
842
-
843
- def query(&block)
844
- @query_object = JavaScriptObject.new(&block)
845
- end
846
-
847
- def generate_script
848
-
849
- query_object_declaration = '{}'
850
- query_string = ""
851
-
852
- if @query_object
853
- query_object_declaration = @query_object.generate
854
- query_string = "+ \"?\" + $.param(query_object)"
855
- end
856
-
857
- member_expr = ""
858
- if @options[:member]
859
- member_expr = ".#{@options[:member]}"
860
- end
861
-
862
- <<-DATATABLE_SCRIPT
863
-
864
- function refresh_table_#{@table_name}()
865
- {
866
- var query_object = #{query_object_declaration};
867
-
868
- $.get( "#{@url}" #{query_string}, function( returned_data )
869
- {
870
- var data = returned_data#{member_expr};
871
- var data_object = {};
872
- if (data !== null && typeof data === 'object')
873
- {
874
- data_object = data;
875
- }
876
- else
877
- {
878
- data_object = JSON.parse(data);
879
- }
880
-
881
- var head = $("##{@head_name}")
882
- var body = $("##{@body_name}")
883
-
884
- if($.isPlainObject(data_object))
885
- {
886
- for (var key in data_object)
887
- {
888
- var row = $('<tr>');
889
- row.append($('<td>').text(key));
890
- row.append($('<td>').text(data_object[key]));
891
- body.append(row);
892
- }
893
- }
894
-
895
- if ($.isArray(data_object))
896
- {
897
-
898
- var columnData = JSON.parse(#{@columns.to_json.inspect});
899
- var columns = {};
900
- var columnTitles = [];
901
- head.empty();
902
- if (#{@columns == nil})
903
- {
904
- // Set up columns
905
- for (var index in data_object)
906
- {
907
- for (var key in data_object[index])
908
- {
909
- columns[key] = Object.keys(columns).length;
910
- }
911
- }
912
- for (var key in columns)
913
- {
914
- columnTitles.push(key);
915
- }
916
- }
917
- else
918
- {
919
- for (var key in columnData)
920
- {
921
- columns[columnData[key]["name"]] = Object.keys(columns).length;
922
- columnTitles.push(columnData[key]["title"]);
923
- }
924
- }
925
-
926
- var row = $('<tr>');
927
- for (var key in columnTitles)
928
- {
929
- var columnTitle = $('<th>').html(columnTitles[key]);
930
- row.append(columnTitle);
931
- }
932
- head.append(row);
933
-
934
- for (var index in data_object)
935
- {
936
- var row = $('<tr>');
937
- for (var columnIndex = 0; columnIndex < Object.keys(columns).length; columnIndex++) {
938
- var cell_data = data_object[index][ Object.keys(columns)[columnIndex] ];
939
-
940
- if (columnData && columnData[columnIndex]["format"])
941
- {
942
- var format = columnData[columnIndex]["format"];
943
- var matches = format.match(/###.+?###/g)
944
-
945
- var result = format;
946
- for (var matchIndex in matches)
947
- {
948
- var member_name = matches[matchIndex].match(/[^#]+/)[0];
949
- result = result.replaceAll(matches[matchIndex], data_object[index][member_name]);
950
- }
951
-
952
- if (columnData && columnData[columnIndex]["transform"])
953
- {
954
- result = document["transform_" + columnData[columnIndex]["transform"]](result);
955
- }
956
- row.append($('<td>').html( result ).data("object", data_object[index]) );
957
- }
958
- else
959
- {
960
- if (columnData && columnData[columnIndex]["transform"])
961
- {
962
- cell_data = document["transform_" + columnData[columnIndex]["transform"]](cell_data);
963
- }
964
- row.append($('<td>').text( cell_data ).data("object", data_object[index]) );
965
- }
966
- }
967
- body.append(row);
968
- }
969
- }
970
-
971
- });
972
- }
973
-
974
- refresh_table_#{@table_name}();
975
-
976
- DATATABLE_SCRIPT
977
- end
978
- end
979
-
980
- class Action
981
- def initialize(page, anchors, &block)
982
- @page = page
983
- @anchors = anchors
984
-
985
- actionsArray = @anchors["action"]
986
-
987
- if !@anchors["action"]
988
- @anchors["action"] = []
989
- end
990
-
991
- actionsArray = @anchors["action"]
992
-
993
- @actionName = "action#{actionsArray.length}"
994
- actionsArray << @actionName
995
-
996
- @code = ""
997
-
998
- self.instance_eval(&block)
999
- end
1000
-
1001
- def script(code)
1002
- @code = code
1003
- end
1004
-
1005
- def generate
1006
- #puts @code
1007
- <<-FUNCTION
1008
- function #{@actionName}(caller, data) {
1009
- #{@code}
1010
- }
1011
- FUNCTION
1012
- end
1013
-
1014
- def name
1015
- @actionName
1016
- end
1017
- end
1018
-
1019
- class Code
1020
- def initialize(page, anchors, lang)
1021
- @page = page
1022
- @anchors = anchors
1023
- @content = ""
1024
- @options = {}
1025
-
1026
- codeArray = @anchors["code"]
1027
-
1028
- if !@anchors["code"]
1029
- @anchors["code"] = []
1030
- end
1031
-
1032
- codeArray = @anchors["code"]
1033
-
1034
- @codeName = "code#{codeArray.length}"
1035
- codeArray << @codeName
1036
-
1037
- @page.request_css "css/plugins/codemirror/codemirror.css"
1038
- @page.request_js "js/plugins/codemirror/codemirror.js"
1039
-
1040
- language lang
1041
-
1042
- end
1043
-
1044
- def language(lang)
1045
- # TODO improve langmap
1046
- langmap = {
1047
- javascript: {mime: "text/javascript", file: "javascript/javascript"}
1048
- }
1049
-
1050
- if langmap[lang]
1051
- @options[:mode] = langmap[lang][:mime]
1052
- @page.request_js "js/plugins/codemirror/mode/#{langmap[lang][:file]}.js"
1053
- else
1054
- @options[:mode] = "text/x-#{lang}"
1055
- @page.request_js "js/plugins/codemirror/mode/#{lang}/#{lang}.js"
1056
- end
1057
-
1058
- end
1059
-
1060
- def content(text)
1061
- @content = text
1062
- end
1063
-
1064
- def theme(name)
1065
- @options[:theme] = name
1066
-
1067
- @page.request_css "css/plugins/codemirror/#{name}.css"
1068
- end
1069
-
1070
- def generate_script
1071
-
1072
- @options[:lineNumbers] ||= true
1073
- @options[:matchBrackets] ||= true
1074
- @options[:styleActiveLine] ||= true
1075
- @options[:mode] ||= "javascript"
1076
- @options[:readOnly] ||= true
1077
-
1078
- <<-CODESCRIPT
1079
- $(document).ready(function()
1080
- {
1081
- CodeMirror.fromTextArea(document.getElementById("#{@codeName}"),
1082
- JSON.parse('#{@options.to_json}')
1083
- );
1084
- });
1085
- CODESCRIPT
1086
- end
1087
-
1088
- def generate
1089
-
1090
- content = @content
1091
- codeName = @codeName
1092
-
1093
- elem = Elements.new(@page, @anchors)
1094
-
1095
- elem.instance_eval do
1096
- textarea id: codeName do
1097
- text content
1098
- end
1099
- end
1100
-
1101
- elem.generate
1102
- end
1103
- end
1104
-
1105
- class TextfieldJavascript
1106
-
1107
- def initialize(id)
1108
- @id = id
1109
- end
1110
-
1111
- def onchange(script)
1112
- @change_script = script
1113
- end
1114
-
1115
- def validate(script)
1116
- @validate_script = script
1117
- end
1118
-
1119
- def generate(&block)
1120
- if block
1121
- instance_eval(&block)
1122
- <<-SCRIPT
1123
-
1124
- if (!document.validators)
1125
- {
1126
- document.validators = {};
1127
- }
1128
-
1129
- document.validators["##{@id}"] = function()
1130
- {
1131
- var valid = function(data) {
1132
- #{@validate_script};
1133
- return true;
1134
- }($("##{@id}").val());
1135
-
1136
- var object = $("##{@id}");
1137
- #{@change_script};
1138
-
1139
- if (valid)
1140
- {
1141
- object.removeClass("required");
1142
- object.removeClass("error");
1143
- object.removeAttr("aria-invalid");
1144
- }
1145
- else
1146
- {
1147
- object.addClass("required");
1148
- object.addClass("error");
1149
- object.attr("aria-required", "true");
1150
- object.attr("aria-invalid", "true");
1151
- }
1152
- }
1153
-
1154
- $("##{@id}").keyup(function() { document.validators["##{@id}"](); })
1155
- $("##{@id}").blur(function() { document.validators["##{@id}"](); })
1156
- $("##{@id}").focusout(function() { document.validators["##{@id}"](); })
1157
-
1158
- SCRIPT
1159
- end
1160
- end
1161
- end
1162
-
1163
- class FormElements < Elements
1164
-
1165
- attr_accessor :options, :scripts
1166
-
1167
- def initialize(page, anchors, formName, options={})
1168
- super(page, anchors)
1169
- @formName = formName
1170
- @options = options
1171
- @scripts = []
1172
- end
1173
-
1174
- def passwordfield(name, textfield_label=nil, options={}, &block)
1175
-
1176
- if textfield_label.is_a? Hash
1177
- options = textfield_label
1178
- textfield_label = nil
1179
- end
1180
-
1181
- options[:type] = "password"
1182
- textfield(name, textfield_label, options, &block)
1183
- end
1184
-
1185
- def textfield(name, textfield_label=nil, options={}, &block)
1186
-
1187
- if textfield_label.is_a? Hash
1188
- options = textfield_label
1189
- textfield_label = nil
1190
- end
1191
-
1192
- textfield_name = options[:id] || @page.create_anchor("textfield")
1193
- options[:type] ||= "text"
1194
- options[:placeholder] ||= ""
1195
- options[:name] = name
1196
-
1197
- input_options = {}
1198
- input_options[:type] = options[:type]
1199
- input_options[:placeholder] = options[:placeholder]
1200
- input_options[:id] = textfield_name
1201
- input_options[:name] = options[:name]
1202
- input_options[:rows] = options[:rows]
1203
- input_options[:class] = "form-control"
1204
- input_options[:value] = options[:value]
1205
- input_options[:style] = options[:style]
1206
-
1207
- input_options[:autocomplete] = options[:autocomplete] || "on"
1208
- input_options[:autocorrect] = options[:autocorrect] || "on"
1209
- input_options[:autocapitalize] = options[:autocapitalize] || "off"
1210
-
1211
- if options[:mask]
1212
- @page.request_css "css/plugins/jasny/jasny-bootstrap.min.css"
1213
- @page.request_js "js/plugins/jasny/jasny-bootstrap.min.js"
1214
-
1215
- input_options[:"data-mask"] = options[:mask]
1216
- end
1217
-
1218
- div :class => "form-group #{options[:extra_class]}", id: "#{input_options[:id]}-group" do
1219
- label textfield_label if textfield_label
1220
-
1221
- div_class = " "
1222
- if options[:front_text] || options[:back_text]
1223
- div_class = "input-group m-b"
1224
- end
1225
-
1226
- div :"class" => div_class do
1227
- span "#{options[:front_text]}", class: "input-group-addon" if options[:front_text]
1228
- if input_options[:rows] and input_options[:rows] > 1
1229
- textarea input_options do
1230
- end
1231
- else
1232
- input input_options
1233
- end
1234
- span "#{options[:back_text]}", class: "input-group-addon" if options[:back_text]
1235
- end
1236
- end
1237
-
1238
- textjs = TextfieldJavascript.new(input_options[:id])
1239
-
1240
- @page.on_page_load textjs.generate(&block) if block
1241
-
1242
- @scripts << <<-SCRIPT
1243
- object["#{name}"] = $('##{textfield_name}').val();
1244
- SCRIPT
1245
- end
1246
-
1247
- def hiddenfield(name, value, options={})
1248
- hiddenfield_name = options[:id] || @page.create_anchor("hiddenfield")
1249
-
1250
- input_options = {}
1251
- input_options[:type] = "hidden"
1252
- input_options[:value] = value
1253
- input_options[:id] = hiddenfield_name
1254
- input_options[:name] = name
1255
-
1256
- input input_options
1257
-
1258
- @scripts << <<-SCRIPT
1259
- object["#{name}"] = $('##{hiddenfield_name}').val();
1260
- SCRIPT
1261
-
1262
- end
1263
-
1264
- def dropdown(name, dropdown_label, choice_array, options={})
1265
- select_name = options[:id] || @page.create_anchor("select")
1266
-
1267
- options[:class] = "form-control"
1268
- options[:name] = name
1269
- options[:id] = select_name
1270
- options[:placeholder] ||= " "
1271
-
1272
- form_options = options.clone
1273
-
1274
- if options[:multiple]
1275
-
1276
- if options[:multiple_style] == :chosen
1277
- @page.request_css "css/plugins/chosen/chosen.css"
1278
- @page.request_js "js/plugins/chosen/chosen.jquery.js"
1279
-
1280
- @page.write_script_once <<-SCRIPT
1281
- var config = {
1282
- '.chosen-select' : {placeholder_text_multiple: "#{options[:placeholder]}"},
1283
- '.chosen-select-deselect' : {allow_single_deselect:true},
1284
- '.chosen-select-no-single' : {disable_search_threshold:10},
1285
- '.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
1286
- '.chosen-select-width' : {width:"95%"}
1287
- }
1288
- for (var selector in config) {
1289
- $(selector).chosen(config[selector]);
1290
- }
1291
- SCRIPT
1292
-
1293
- form_options[:class] = "chosen-select"
1294
- form_options[:style] = "width: 100%"
1295
- end
1296
-
1297
- @scripts << <<-SCRIPT
1298
- var selections = [];
1299
- $("##{select_name} option:selected").each(function(i, selected){
1300
- selections[i] = $(selected).text();
1301
- });
1302
- object["#{name}"] = selections;
1303
- SCRIPT
1304
-
1305
- else
1306
- @scripts << <<-SCRIPT
1307
- object["#{name}"] = $( "##{select_name} option:selected" ).text();
1308
- SCRIPT
1309
- end
1310
-
1311
-
1312
- div :class => "form-group" do
1313
- label dropdown_label, :class => "control-label"
1314
-
1315
- div :class => "input-group", style: "width: 100%" do
1316
-
1317
- method_missing :select, form_options do
1318
-
1319
- choice_array.each do |choice|
1320
- if "#{options[:value]}" == "#{choice}"
1321
- option choice, selected: true
1322
- else
1323
- option choice
1324
- end
1325
- end
1326
- end
1327
- end
1328
- end
1329
-
1330
-
1331
- end
1332
-
1333
- def knob(name, options={})
1334
-
1335
- knob_name = @page.create_anchor "knob"
1336
-
1337
- @page.request_js "js/plugins/jsKnob/jquery.knob.js"
1338
- @page.write_script_once <<-SCRIPT
1339
- $(".dial").knob();
1340
- SCRIPT
1341
-
1342
- knob_options = {}
1343
-
1344
- knob_options[:id] = knob_name
1345
- knob_options[:type] = "text"
1346
- knob_options[:value] = options[:value] || "0"
1347
- knob_options[:class] = "dial"
1348
-
1349
- options.each do |key,value|
1350
- knob_options["data-#{key}".to_sym] = value
1351
- end
1352
-
1353
- knob_options[:"data-fgColor"] = "#1AB394"
1354
- knob_options[:"data-width"] = "85"
1355
- knob_options[:"data-height"] = "85"
1356
-
1357
- input knob_options
1358
-
1359
- @scripts << <<-SCRIPT
1360
- object["#{name}"] = $('##{knob_name}').val();
1361
- SCRIPT
1362
- end
1363
-
1364
- def radio(name, choice_array, options={})
1365
-
1366
- radio_name = @page.create_anchor "radio"
1367
-
1368
- choice_array = choice_array.map do |choice|
1369
- if choice.is_a? Hash
1370
- {value: choice[:value], label: choice[:label]}
1371
- else
1372
- {value: choice, label: choice}
1373
- end
1374
- end
1375
-
1376
- active = choice_array[0][:value]
1377
- if options[:value] and choice_array.index { |x| x[:value] == options[:value] } != nil
1378
- active = options[:value]
1379
- end
1380
-
1381
- div_options = {}
1382
- curobject = self
1383
- if options[:form] == :button
1384
- div_options[:"data-toggle"] = "buttons"
1385
- end
1386
- div div_options do
1387
- choice_array.each do |choice|
1388
-
1389
- value = choice[:value]
1390
- label = choice[:label]
1391
-
1392
- the_options = Hash.new(options)
1393
-
1394
- if active == value
1395
- the_options[:checked] = ""
1396
- end
1397
-
1398
- if options[:form] == :button
1399
- the_options[:type] = "radio"
1400
- the_options[:value] = value
1401
- the_options[:name] = name
1402
- the_options[:form] = :button
1403
- text curobject.boolean_element(label, the_options)
1404
- else
1405
- the_options[:type] = "radio"
1406
- the_options[:value] = value
1407
- the_options[:name] = name
1408
- text curobject.boolean_element(label, the_options)
1409
- end
1410
- end
1411
- end
1412
-
1413
-
1414
- @scripts << <<-SCRIPT
1415
- object["#{name}"] = $('input[name=#{name}]:checked', '##{@formName}').val()
1416
- SCRIPT
1417
- end
1418
-
1419
- def checkbox(name, checkbox_label, options={})
1420
- checkbox_name = options[:id] || @page.create_anchor("checkbox")
1421
- options[:type] = "checkbox"
1422
- options[:name] = name
1423
- options[:id] = checkbox_name
1424
- text boolean_element(checkbox_label, options)
1425
- @scripts << <<-SCRIPT
1426
- object["#{name}"] = $('##{checkbox_name}').is(":checked");
1427
- SCRIPT
1428
- end
1429
-
1430
-
1431
- def submit(anIcon, title={}, options={}, &block)
1432
- options[:icon] = anIcon
1433
- options[:title] = title
1434
- options[:type] = "submit"
1435
- options[:data] = "get_#{@formName}_object()"
1436
- options[:nosubmit] = true if block
1437
- _button(options, &block)
1438
- end
1439
-
1440
- def boolean_element(checkbox_label, options={})
1441
-
1442
- @page.request_css "css/plugins/iCheck/custom.css"
1443
- @page.request_js "js/plugins/iCheck/icheck.min.js"
1444
-
1445
- @page.write_script_once <<-SCRIPT
1446
- $(document).ready(function () {
1447
- $('.i-checks').iCheck({
1448
- checkboxClass: 'icheckbox_square-green',
1449
- radioClass: 'iradio_square-green',
1450
- });
1451
- });
1452
- SCRIPT
1453
-
1454
- label_options = {}
1455
- elem = Elements.new(@page, @anchors)
1456
- elem.instance_eval do
1457
-
1458
- if options[:form] == :button
1459
- options.delete(:form)
1460
- label class: "btn btn-primary btn-block btn-outline" do
1461
- input options
1462
- text "#{checkbox_label}"
1463
- end
1464
- else
1465
- div class: "i-checks" do
1466
- label label_options do
1467
- input options do
1468
- text " #{checkbox_label}"
1469
- end
1470
- end
1471
- end
1472
- end
1473
-
1474
- end
1475
-
1476
- elem.generate
1477
- end
1478
- end
1479
-
1480
- class Form
1481
- def initialize(page, anchors, options={}, &block)
1482
-
1483
- @formName = options[:id] || page.create_anchor("form")
1484
-
1485
- @form_element = FormElements.new(page, anchors, @formName, options)
1486
-
1487
- @form_element.instance_eval(&block)
1488
- end
1489
-
1490
- def generate_script
1491
- <<-SCRIPT
1492
- function get_#{@formName}_object()
1493
- {
1494
- var object = {}
1495
- #{@form_element.scripts.join "\n"}
1496
- return object;
1497
- }
1498
- SCRIPT
1499
- end
1500
-
1501
- def generate
1502
- inner = @form_element.generate
1503
- formName = @formName
1504
- options = @form_element.options
1505
-
1506
- elem = Elements.new(@page, @anchors)
1507
- elem.instance_eval do
1508
-
1509
- form_opts = {
1510
- id: formName,
1511
- role: "form"
1512
- }
1513
-
1514
- form_opts[:action] = options[:action] if options[:action]
1515
- form_opts[:method] = options[:method] if options[:method]
1516
- form_opts[:class] = options[:class] if options[:class]
1517
-
1518
- method_missing :form, form_opts do
1519
- text inner
1520
- end
1521
- end
1522
-
1523
- elem.generate
1524
- end
1525
- end
1526
-
1527
- class Panel < Elements
1528
- def initialize(page, anchors, options={})
1529
- super(page, anchors)
1530
- @title = nil
1531
- @footer = nil
1532
- @type = :ibox
1533
- @body = true
1534
- @extra = nil
1535
- @min_height = nil
1536
- @page = page
1537
- @options = options
1538
- end
1539
-
1540
- def generate
1541
- inner = super
1542
-
1543
- types =
1544
- {
1545
- :ibox => { outer: "ibox float-e-margins",header: "ibox-title", body: "ibox-content" , footer: "ibox-footer"},
1546
- :panel => { outer: "panel panel-default", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1547
- :primary => { outer: "panel panel-primary", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1548
- :success => { outer: "panel panel-success", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1549
- :info => { outer: "panel panel-info", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1550
- :warning => { outer: "panel panel-warning", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1551
- :danger => { outer: "panel panel-danger", header: "panel-heading", body: "panel-body" , footer: "panel-footer"},
1552
- :blank => { outer: "panel blank-panel", header: "panel-heading", body: "panel-body" , footer: "panel-footer"}
1553
- }
1554
-
1555
- title = @title
1556
- footer = @footer
1557
- hasBody = @body
1558
- extra = @extra
1559
- options = @options
1560
- classNames = types[@type]
1561
- min_height = @min_height
1562
-
1563
- elem = Elements.new(@page, @anchors)
1564
-
1565
- outer_class = classNames[:outer]
1566
-
1567
- if options[:collapsed]
1568
- outer_class = "ibox collapsed"
1569
- end
1570
-
1571
- elem.instance_eval do
1572
- div class: outer_class do
1573
- if title
1574
- div class: classNames[:header] do
1575
- h5 title
1576
-
1577
- div class: "ibox-tools" do
1578
- if options[:collapsible] or options[:collapsed]
1579
- a class: "collapse-link" do
1580
- icon :"chevron-up"
1581
- end
1582
- end
1583
- if options[:expandable]
1584
- a class: "fullscreen-link" do
1585
- icon :expand
1586
- end
1587
- end
1588
- if options[:closable]
1589
- a class: "close-link" do
1590
- icon :times
1591
- end
1592
- end
1593
- end
1594
- end
1595
- end
1596
- if hasBody
1597
- div class: classNames[:body], style: "min-height: #{min_height}px" do
1598
- text inner
1599
- end
1600
- end
1601
- if extra
1602
- text extra
1603
- end
1604
- if footer
1605
- div class: classNames[:footer] do
1606
- text footer
1607
- end
1608
- end
1609
-
1610
- end
1611
- end
1612
-
1613
- elem.generate
1614
- end
1615
-
1616
- def min_height(val)
1617
- @min_height = val
1618
- end
1619
-
1620
- def type(aType)
1621
- @type = aType
1622
- end
1623
-
1624
- def body(hasBody)
1625
- @body = hasBody
1626
- end
1627
-
1628
- def title(title=nil, &block)
1629
- @title = title
1630
- if block
1631
- elem = Elements.new(@page, @anchors)
1632
- elem.instance_eval(&block)
1633
- @title = elem.generate
1634
- end
1635
- end
1636
-
1637
- def extra(&block)
1638
- if block
1639
- elem = Elements.new(@page, @anchors)
1640
- elem.instance_eval(&block)
1641
- @extra = elem.generate
1642
- end
1643
- end
1644
-
1645
- def footer(footer=nil, &block)
1646
- @footer = footer
1647
- if block
1648
- elem = Elements.new(@page, @anchors)
1649
- elem.instance_eval(&block)
1650
- @footer = elem.generate
1651
- end
1652
- end
1653
-
1654
- end
1655
-
1656
- class Accordion
1657
- def initialize(page, anchors)
1658
- @anchors = anchors
1659
- @tabs = {}
1660
- @paneltype = :panel
1661
- @is_collapsed = false
1662
- @page = page
1663
-
1664
- if !@anchors["accordia"]
1665
- @anchors["accordia"] = []
1666
- end
1667
-
1668
- accArray = @anchors["accordia"]
1669
-
1670
- @accordion_name = "accordion#{accArray.length}"
1671
- accArray << @accordion_name
1672
- end
1673
-
1674
- def collapsed(isCollapsed)
1675
- @is_collapsed = isCollapsed
1676
- end
1677
-
1678
- def type(type)
1679
- @paneltype = type
1680
- end
1681
-
1682
- def tab(title, options={}, &block)
1683
-
1684
- if !@anchors["tabs"]
1685
- @anchors["tabs"] = []
1686
- end
1687
-
1688
- tabArray = @anchors["tabs"]
1689
-
1690
- elem = Elements.new(@page, @anchors)
1691
- elem.instance_eval(&block)
1692
-
1693
- tabname = "tab#{tabArray.length}"
1694
- tabArray << tabname
1695
-
1696
- @tabs[tabname] =
1697
- {
1698
- title: title,
1699
- elem: elem
1700
- }
1701
-
1702
- if options[:mixpanel_event_name]
1703
- @tabs[tabname][:mixpanel_event_name] = options[:mixpanel_event_name]
1704
- end
1705
-
1706
- if options[:mixpanel_event_props]
1707
- @tabs[tabname][:mixpanel_event_props] = options[:mixpanel_event_props]
1708
- end
1709
-
1710
- end
1711
-
1712
- def generate
1713
- tabbar = Elements.new(@page, @anchors)
1714
-
1715
- tabs = @tabs
1716
- paneltype = @paneltype
1717
- accordion_name = @accordion_name
1718
- is_collapsed = @is_collapsed
1719
-
1720
- tabbar.instance_eval do
1721
-
1722
- div :class => "panel-group", id: accordion_name do
1723
-
1724
- cls = "panel-collapse collapse in"
1725
- cls = "panel-collapse collapse" if is_collapsed
1726
- tabs.each do |anchor, value|
1727
-
1728
- ibox do
1729
- type paneltype
1730
- body false
1731
- title do
1732
- div :class => "panel-title" do
1733
- options = {
1734
- :"data-toggle" => "collapse",
1735
- :"data-parent" => "##{accordion_name}",
1736
- href: "##{anchor}"
1737
- }
1738
-
1739
- if value[:mixpanel_event_name]
1740
- props = {}
1741
- if value[:mixpanel_event_props].is_a? Hash
1742
- props = value[:mixpanel_event_props]
1743
- end
1744
- options[:onclick] = "mixpanel.track('#{value[:mixpanel_event_name]}', #{props.to_json.gsub('"',"'")})"
1745
- end
1746
-
1747
- a options do
1748
- if value[:title].is_a? Symbol
1749
- icon value[:title]
1750
- else
1751
- text value[:title]
1752
- end
1753
- end
1754
- end
1755
- end
1756
-
1757
- extra do
1758
- div id: anchor, :class => cls do
1759
- div :class => "panel-body" do
1760
- text value[:elem].generate
1761
- end
1762
- end
1763
- end
1764
- end
1765
-
1766
- cls = "panel-collapse collapse"
1767
- end
1768
-
1769
- end
1770
-
1771
- end
1772
-
1773
- tabbar.generate
1774
- end
1775
-
1776
- end
1777
-
1778
- class Tabs
1779
- def initialize(page, anchors)
1780
- @anchors = anchors
1781
- @tabs = {}
1782
- @page = page
1783
- @orientation = :normal # :left, :right
1784
- end
1785
-
1786
- def tab(title, &block)
1787
-
1788
- if !@anchors["tabs"]
1789
- @anchors["tabs"] = []
1790
- end
1791
-
1792
- tabArray = @anchors["tabs"]
1793
-
1794
- elem = Elements.new(@page, @anchors)
1795
- elem.instance_eval(&block)
1796
-
1797
- tabname = "tab#{tabArray.length}"
1798
- tabArray << tabname
1799
-
1800
- @tabs[tabname] =
1801
- {
1802
- title: title,
1803
- elem: elem
1804
- }
1805
- end
1806
-
1807
- def orientation(direction)
1808
- @orientation = direction
1809
- end
1810
-
1811
- def generate
1812
-
1813
- tabbar = Elements.new(@page, @anchors)
1814
- tabs = @tabs
1815
- orientation = @orientation
1816
-
1817
- tabbar.instance_eval do
1818
-
1819
- div :class => "tabs-container" do
1820
-
1821
- div :class => "tabs-#{orientation}" do
1822
-
1823
- ul :class => "nav nav-tabs" do
1824
- cls = "active"
1825
- tabs.each do |anchor, value|
1826
- li :class => cls do
1827
- a :"data-toggle" => "tab", href: "##{anchor}" do
1828
- if value[:title].is_a? Symbol
1829
- icon value[:title]
1830
- else
1831
- text value[:title]
1832
- end
1833
- end
1834
- end
1835
-
1836
- cls = ""
1837
- end
1838
- end
1839
-
1840
- div :class => "tab-content" do
1841
-
1842
- cls = "tab-pane active"
1843
- tabs.each do |anchor, value|
1844
- div id: "#{anchor}", :class => cls do
1845
- div :class => "panel-body" do
1846
- text value[:elem].generate
1847
- end
1848
- end
1849
- cls = "tab-pane"
1850
- end
1851
- end
1852
- end
1853
-
1854
- end
1855
- end
1856
-
1857
- tabbar.generate
1858
- end
1859
- end
1860
-
1861
- class Page
1862
-
1863
- attr_accessor :scripts, :onload_scripts
1864
-
1865
- def initialize(title, global_settings, options, &block)
1866
- @title = title
1867
- @content = ""
1868
- @body_class = nil
1869
- @anchors = {}
1870
- @global_settings = global_settings
1871
- @options = options
1872
- @scripts = []
1873
- @top_content = ""
1874
-
1875
- @scripts_once = {}
1876
- @onload_scripts = []
1877
-
1878
- @requested_scripts = {}
1879
- @requested_css = {}
1880
-
1881
- @background = Elements.new(self, @anchors)
1882
-
1883
- @block = Proc.new &block
1884
- end
1885
-
1886
- def create_anchor(name)
1887
-
1888
- if !@anchors[name]
1889
- @anchors[name] = []
1890
- end
1891
-
1892
- anchor_array = @anchors[name]
1893
-
1894
- anchor_name = "#{name}#{anchor_array.length}"
1895
- anchor_array << anchor_name
1896
-
1897
- anchor_name
1898
- end
1899
-
1900
- def root
1901
- return @global_settings[:root]
1902
- end
1903
-
1904
- def request_js(path)
1905
- @requested_scripts[path] = true
1906
- end
1907
-
1908
- def request_css(path)
1909
- @requested_css[path] = true
1910
- end
1911
-
1912
- def on_page_load(script)
1913
- @onload_scripts << script
1914
- end
1915
-
1916
- def write_script_once(script)
1917
- @scripts_once[script] = true
1918
- end
1919
-
1920
- def background(&block)
1921
- @background.instance_eval(&block)
1922
- end
1923
-
1924
- def top(&block)
1925
- elem = Elements.new(self, @anchors)
1926
- elem.instance_eval(&block)
1927
-
1928
- @top_content = elem.generate
1929
- end
1930
-
1931
- def generate(back_folders, options={})
1932
-
1933
- if @options[:cache_file]
1934
- expired = @options[:cache_expired]
1935
- cache_exist = File.exist?("cache/cachedpage#{@options[:cache_file]}")
1936
-
1937
- if cache_exist and !expired
1938
- puts "Weaver Hit cache for file: #{@options[:cache_file]}"
1939
- puts "- expired: #{expired}"
1940
- puts "- cache_exist: #{cache_exist}"
1941
- return File.read("cache/cachedpage#{@options[:cache_file]}");
1942
- end
1943
- puts "Weaver Miss cache for file: #{@options[:cache_file]}"
1944
- puts "- expired: #{expired}"
1945
- puts "- cache_exist: #{cache_exist}"
1946
- end
1947
-
1948
- scripts = @scripts.join("\n")
1949
-
1950
- mod = "../" * back_folders
1951
-
1952
- style = <<-ENDSTYLE
1953
- <link href="#{mod}css/style.css" rel="stylesheet">
1954
- ENDSTYLE
1955
-
1956
- if options[:style] == :empty
1957
- style = ""
1958
- end
1959
-
1960
- body_tag = "<body>"
1961
-
1962
- body_tag = "<body class='#{@body_class}'>" if @body_class
1963
-
1964
- loading_bar = ""
1965
- loading_bar = "<script src='#{mod}js/plugins/pace/pace.min.js'></script>" if @loading_bar_visible
1966
-
1967
- extra_scripts = @requested_scripts.map {|key,value| <<-SCRIPT_DECL
1968
- <script src="#{mod}#{key}"></script>
1969
- SCRIPT_DECL
1970
- }.join "\n"
1971
-
1972
- extra_css = @requested_css.map {|key,value| <<-STYLESHEET_DECL
1973
- <link href="#{mod}#{key}" rel="stylesheet">
1974
- STYLESHEET_DECL
1975
- }.join "\n"
1976
-
1977
- extra_one_time_scripts = @scripts_once.map {|key,value| <<-SCRIPT_DECL
1978
- #{key}
1979
- SCRIPT_DECL
1980
- }.join "\n"
1981
-
1982
- onload_scripts = @onload_scripts.map {|value| <<-SCRIPT_DECL
1983
- #{value}
1984
- SCRIPT_DECL
1985
- }.join "\n"
1986
-
1987
- extra_stuff = ""
1988
-
1989
- if @global_settings[:mixpanel_token]
1990
- extra_stuff += '<!-- start Mixpanel --><script type="text/javascript">(function(e,a){if(!a.__SV){var b=window;try{var c,l,i,j=b.location,g=j.hash;c=function(a,b){return(l=a.match(RegExp(b+"=([^&]*)")))?l[1]:null};g&&c(g,"state")&&(i=JSON.parse(decodeURIComponent(c(g,"state"))),"mpeditor"===i.action&&(b.sessionStorage.setItem("_mpcehash",g),history.replaceState(i.desiredHash||"",e.title,j.pathname+j.search)))}catch(m){}var k,h;window.mixpanel=a;a._i=[];a.init=function(b,c,f){function e(b,a){var c=a.split(".");2==c.length&&(b=b[c[0]],a=c[1]);b[a]=function(){b.push([a].concat(Array.prototype.slice.call(arguments,
1991
- 0)))}}var d=a;"undefined"!==typeof f?d=a[f]=[]:f="mixpanel";d.people=d.people||[];d.toString=function(b){var a="mixpanel";"mixpanel"!==f&&(a+="."+f);b||(a+=" (stub)");return a};d.people.toString=function(){return d.toString(1)+".people (stub)"};k="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
1992
- for(h=0;h<k.length;h++)e(d,k[h]);a._i.push([b,c,f])};a.__SV=1.2;b=e.createElement("script");b.type="text/javascript";b.async=!0;b.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js";c=e.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c)}})(document,window.mixpanel||[]);
1993
- mixpanel.init("'+@global_settings[:mixpanel_token]+'");</script><!-- end Mixpanel -->'
1994
- end
1995
-
1996
- if @global_settings[:google_tracking_code]
1997
- extra_stuff += <<-GOOGLE
1998
- <!-- Global site tag (gtag.js) - Google Analytics -->
1999
- <script async src="https://www.googletagmanager.com/gtag/js?id=#{@global_settings[:google_tracking_code]}"></script>
2000
- <script>
2001
- window.dataLayer = window.dataLayer || [];
2002
- function gtag(){dataLayer.push(arguments);}
2003
- gtag('js', new Date());
2004
-
2005
- gtag('config', '#{@global_settings[:google_tracking_code]}');
2006
- </script>
2007
- GOOGLE
2008
- end
2009
-
2010
-
2011
- result =<<-SKELETON
2012
- <!DOCTYPE html>
2013
- <html>
2014
- <!-- Generated using weaver: https://github.com/davidsiaw/weaver -->
2015
- <head>
2016
-
2017
- <meta charset="utf-8">
2018
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
2019
-
2020
- <title>#{@title}</title>
2021
-
2022
- <link href="#{mod}css/bootstrap.min.css" rel="stylesheet">
2023
- <link href="#{mod}font-awesome/css/font-awesome.css" rel="stylesheet">
2024
- <link href="#{mod}css/plugins/iCheck/custom.css" rel="stylesheet">
2025
-
2026
- #{style}
2027
-
2028
- <link href="#{mod}css/animate.css" rel="stylesheet">
2029
-
2030
- #{extra_css}
2031
-
2032
- #{extra_stuff}
2033
-
2034
- </head>
2035
-
2036
- #{body_tag}
2037
-
2038
- <div id="background" style="z-index: -999; position:absolute; left:0px; right:0px; width:100%; height:100%">
2039
- #{@background.generate}
2040
- </div>
2041
-
2042
- <div id="content" style="z-index: 0">
2043
- #{@top_content}
2044
- #{@content}
2045
- </div>
2046
-
2047
- <!-- Mainly scripts -->
2048
- <script src="#{mod}js/jquery-3.1.1.min.js"></script>
2049
- <script src="#{mod}js/jquery-ui-1.10.4.min.js"></script>
2050
- <script src="#{mod}js/bootstrap.min.js"></script>
2051
- <script src="#{mod}js/plugins/metisMenu/jquery.metisMenu.js"></script>
2052
- <script src="#{mod}js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
2053
- <script type="text/x-mathjax-config">
2054
- MathJax.Hub.Config({
2055
- asciimath2jax: {
2056
- delimiters: [['$$$MATH$$$','$$$ENDMATH$$$']]
2057
- }
2058
- });
2059
- </script>
2060
- <script src="#{mod}js/MathJax/MathJax.js?config=AM_HTMLorMML-full" async></script>
2061
-
2062
- #{extra_scripts}
2063
-
2064
-
2065
- <!-- Custom and plugin javascript -->
2066
- <script src="#{mod}js/weaver.js"></script>
2067
- #{loading_bar}
2068
-
2069
- <script>
2070
- #{scripts}
2071
- #{extra_one_time_scripts}
2072
-
2073
- $( document ).ready(function() {
2074
-
2075
- #{onload_scripts}
2076
-
2077
- });
2078
- </script>
2079
-
2080
-
2081
-
2082
- </body>
2083
-
2084
- </html>
2085
-
2086
- SKELETON
2087
-
2088
- if @options[:cache_file]
2089
- FileUtils.mkdir_p "cache"
2090
- File.write("cache/cachedpage#{@options[:cache_file]}", result);
2091
- end
2092
-
2093
- return result
2094
-
2095
- end
2096
- end
2097
-
2098
- class Row < Elements
2099
- attr_accessor :extra_classes, :style
2100
-
2101
- def initialize(page, anchors, options)
2102
- @columns = []
2103
- @free = 12
2104
- @extra_classes = options[:class] || ""
2105
- @style = options[:style]
2106
- @anchors = anchors
2107
- @page = page
2108
- end
2109
-
2110
- def col(occupies, options={}, &block)
2111
- raise "Not enough columns!" if @free < occupies
2112
- elem = Elements.new(@page, @anchors)
2113
- elem.instance_eval(&block)
2114
-
2115
- @columns << { occupy: occupies, elem: elem, options: options }
2116
- @free -= occupies
2117
- end
2118
-
2119
- def generate
2120
-
2121
- @columns.map { |col|
2122
-
2123
- xs = col[:options][:xs] || col[:occupy]
2124
- sm = col[:options][:sm] || col[:occupy]
2125
- md = col[:options][:md] || col[:occupy]
2126
- lg = col[:options][:lg] || col[:occupy]
2127
-
2128
- hidden = ""
2129
-
2130
- xs_style = "col-xs-#{xs}" unless col[:options][:xs] == 0
2131
- sm_style = "col-sm-#{sm}" unless col[:options][:sm] == 0
2132
- md_style = "col-md-#{md}" unless col[:options][:md] == 0
2133
- lg_style = "col-lg-#{lg}" unless col[:options][:lg] == 0
2134
-
2135
- hidden += "hidden-xs " if col[:options][:xs] == 0
2136
- hidden += "hidden-sm " if col[:options][:sm] == 0
2137
- hidden += "hidden-md " if col[:options][:md] == 0
2138
- hidden += "hidden-lg " if col[:options][:lg] == 0
2139
-
2140
- <<-ENDCOLUMN
2141
- <div class="#{xs_style} #{sm_style} #{md_style} #{lg_style} #{hidden}">
2142
- #{col[:elem].generate}
2143
- </div>
2144
- ENDCOLUMN
2145
- }.join
2146
- end
2147
- end
2148
-
2149
- class Menu
2150
- attr_accessor :items
2151
- def initialize()
2152
- @items = []
2153
- end
2154
-
2155
- def nav(name, icon=:question, url=nil, options={}, &block)
2156
- if url and !block
2157
- @items << { name: name, link: url, icon: icon, options: options }
2158
- elsif block
2159
- menu = Menu.new
2160
- menu.instance_eval(&block)
2161
- @items << { name: name, menu: menu, icon: icon, options: options }
2162
- else
2163
- @items << { name: name, link: "#", icon: icon, options: options }
2164
- end
2165
- end
2166
- end
2167
-
2168
- class StructuredPage < Page
2169
-
2170
- def initialize(title, global_settings, options, &block)
2171
- @rows = []
2172
- super
2173
- end
2174
-
2175
- def header(&block)
2176
- row(class: "wrapper border-bottom white-bg page-heading", &block)
2177
- end
2178
-
2179
- def row(options={}, &block)
2180
- r = Row.new(self, @anchors, options)
2181
- r.instance_eval(&block)
2182
- @rows << r
2183
- end
2184
-
2185
-
2186
- end
2187
-
2188
- class NavPage < StructuredPage
2189
- def initialize(title, global_settings, options, &block)
2190
- super
2191
- @menu = Menu.new
2192
- end
2193
-
2194
- def menu(&block)
2195
- @menu.instance_eval(&block)
2196
- end
2197
-
2198
- def brand(text, link="/")
2199
- @brand = text
2200
- @brand_link = link
2201
- end
2202
-
2203
- end
2204
-
2205
- class SideNavPage < NavPage
2206
- def initialize(title, global_settings, options, &block)
2207
- super
2208
- end
2209
-
2210
- def generate(level)
2211
- instance_eval &@block
2212
- rows = @rows.map { |row|
2213
- <<-ENDROW
2214
- <div class="row #{row.extra_classes}" style="#{row.style}">
2215
- #{row.generate}
2216
- </div>
2217
- ENDROW
2218
- }.join
2219
-
2220
- menu = @menu
2221
-
2222
- navigation = Elements.new(self, @anchors)
2223
- navigation.instance_eval do
2224
-
2225
- menu.items.each do |item|
2226
- li item[:options] do
2227
- if item.has_key? :menu
2228
-
2229
- hyperlink "/#" do
2230
- icon item[:icon]
2231
- span :class => "nav-label" do
2232
- text item[:name]
2233
- end
2234
- span :class => "fa arrow" do
2235
- text ""
2236
- end
2237
- end
2238
-
2239
- open = ""
2240
- open = "collapse in" if item[:options][:open]
2241
- ul :class => "nav nav-second-level #{open}" do
2242
- item[:menu].items.each do |inneritem|
2243
- li inneritem[:options] do
2244
- if inneritem.has_key?(:menu)
2245
- raise "Second level menu not supported"
2246
- else
2247
- hyperlink "#{inneritem[:link]}" do
2248
- icon inneritem[:icon]
2249
- span :class => "nav-label" do
2250
- text inneritem[:name]
2251
- end
2252
- end
2253
- end
2254
- end
2255
- end
2256
- end
2257
- elsif
2258
- hyperlink "#{item[:link]}" do
2259
- icon item[:icon]
2260
- span :class => "nav-label" do
2261
- text item[:name]
2262
- end
2263
- end
2264
- end
2265
- end
2266
- end
2267
-
2268
- end
2269
-
2270
- brand_content = ""
2271
-
2272
- if @brand
2273
- brand_content = <<-BRAND_CONTENT
2274
-
2275
- <li>
2276
- <a href="#{root}"><i class="fa fa-home"></i> <span class="nav-label">#{@brand}</span> <span class="label label-primary pull-right"></span></a>
2277
- </li>
2278
- BRAND_CONTENT
2279
- end
2280
-
2281
- @loading_bar_visible = true
2282
- @content =
2283
- <<-ENDBODY
2284
- <div id="wrapper">
2285
-
2286
- <nav class="navbar-default navbar-static-side" role="navigation">
2287
- <div class="sidebar-collapse">
2288
- <ul class="nav" id="side-menu">
2289
-
2290
- #{brand_content}
2291
- #{navigation.generate}
2292
-
2293
- </ul>
2294
- </div>
2295
- </nav>
2296
- <div id="page-wrapper" class="gray-bg">
2297
- <div class="row border-bottom">
2298
- <nav class="navbar navbar-static-top " role="navigation" style="margin-bottom: 0">
2299
- <div class="navbar-header">
2300
- <a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
2301
- </div>
2302
- <ul class="nav navbar-top-links navbar-right">
2303
- <!-- NAV RIGHT -->
2304
- </ul>
2305
- </nav>
2306
- </div>
2307
- #{rows}
2308
- </div>
2309
- </div>
2310
- ENDBODY
2311
-
2312
- super
2313
- end
2314
- end
2315
-
2316
- class TopNavPage < NavPage
2317
- def initialize(title, global_settings, options, &block)
2318
- super
2319
- end
2320
-
2321
- def generate(level)
2322
- instance_eval &@block
2323
- rows = @rows.map { |row|
2324
- <<-ENDROW
2325
- <div class="row #{row.extra_classes}" style="#{row.style}">
2326
- #{row.generate}
2327
- </div>
2328
- ENDROW
2329
- }.join
2330
-
2331
- @body_class = "top-navigation"
2332
- @loading_bar_visible = true
2333
-
2334
- menu = @menu
2335
-
2336
- navigation = Elements.new(self, @anchors)
2337
- navigation.instance_eval do
2338
-
2339
- menu.items.each do |item|
2340
- li item[:options] do
2341
- if item.has_key? :menu
2342
-
2343
- li :class => "dropdown" do
2344
- a :"aria-expanded" => "false",
2345
- role: "button",
2346
- href: "#",
2347
- :class => "dropdown-toggle",
2348
- :"data-toggle" => "dropdown" do
2349
-
2350
- icon item[:icon]
2351
- text item[:name]
2352
- span :class => "caret" do
2353
- text ""
2354
- end
2355
-
2356
- end
2357
- ul role: "menu", :class => "dropdown-menu" do
2358
- item[:menu].items.each do |inneritem|
2359
- li inneritem[:options] do
2360
- if inneritem.has_key?(:menu)
2361
- raise "Second level menu not supported"
2362
- else
2363
- hyperlink inneritem[:link], inneritem[:name]
2364
- end
2365
- end
2366
- end
2367
- end
2368
- end
2369
- elsif
2370
- hyperlink "#{item[:link]}" do
2371
- span :class => "nav-label" do
2372
- icon item[:icon]
2373
- text item[:name]
2374
- end
2375
- end
2376
- end
2377
- end if item[:options][:position] != :right
2378
- end
2379
-
2380
- end
2381
-
2382
- navigation_right = Elements.new(self, @anchors)
2383
- navigation_right.instance_eval do
2384
-
2385
- menu.items.each do |item|
2386
- li item[:options] do
2387
- if item.has_key? :menu
2388
-
2389
- li :class => "dropdown" do
2390
- a :"aria-expanded" => "false",
2391
- role: "button",
2392
- href: "#",
2393
- :class => "dropdown-toggle",
2394
- :"data-toggle" => "dropdown" do
2395
-
2396
- icon item[:icon]
2397
- text item[:name]
2398
- span :class => "caret" do
2399
- text ""
2400
- end
2401
-
2402
- end
2403
- ul role: "menu", :class => "dropdown-menu" do
2404
- item[:menu].items.each do |inneritem|
2405
- li inneritem[:options] do
2406
- if inneritem.has_key?(:menu)
2407
- raise "Second level menu not supported"
2408
- else
2409
- hyperlink inneritem[:link], inneritem[:name]
2410
- end
2411
- end
2412
- end
2413
- end
2414
- end
2415
- elsif
2416
- hyperlink "#{item[:link]}" do
2417
- span :class => "nav-label" do
2418
- icon item[:icon]
2419
- text item[:name]
2420
- end
2421
- end
2422
- end
2423
- end if item[:options][:position] == :right
2424
- end
2425
-
2426
- end
2427
-
2428
-
2429
- brand_content = ""
2430
-
2431
- if @brand
2432
- brand_content = <<-BRAND_CONTENT
2433
-
2434
- <div class="navbar-header">
2435
-
2436
- <a href="#{root}" class="navbar-brand">#{@brand}</a>
2437
- </div>
2438
- BRAND_CONTENT
2439
- end
2440
-
2441
- @content =
2442
- <<-ENDBODY
2443
- <div id="wrapper">
2444
-
2445
- <div id="page-wrapper" class="gray-bg">
2446
- <div class="row border-bottom white-bg">
2447
-
2448
- <nav class="navbar navbar-static-top" role="navigation">
2449
- <button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" class="navbar-toggle collapsed" type="button">
2450
- <i class="fa fa-reorder"></i>
2451
- </button>
2452
- #{brand_content}
2453
-
2454
- <div class="navbar-collapse collapse" id="navbar">
2455
- <ul class="nav navbar-nav">
2456
- #{navigation.generate}
2457
- </ul>
2458
- <ul class="nav navbar-top-links navbar-right">
2459
- #{navigation_right.generate}
2460
- </ul>
2461
- </div>
2462
-
2463
-
2464
-
2465
- </nav>
2466
- </div>
2467
-
2468
-
2469
- <div class="wrapper-content">
2470
- <div class="container">
2471
- #{rows}
2472
- </div>
2473
- </div>
2474
- </div>
2475
- </div>
2476
- ENDBODY
2477
-
2478
- super
2479
- end
2480
- end
2481
-
2482
- class NonNavPage < StructuredPage
2483
- def initialize(title, global_settings, options, &block)
2484
- super
2485
- end
2486
-
2487
- def generate(level)
2488
- instance_eval &@block
2489
- rows = @rows.map { |row|
2490
- <<-ENDROW
2491
- <div class="row #{row.extra_classes}">
2492
- #{row.generate}
2493
- </div>
2494
- ENDROW
2495
- }.join
2496
-
2497
- @body_class = "gray-bg"
2498
-
2499
- @content = <<-CONTENT
2500
- <div id="wrapper">
2501
- <div class="wrapper-content">
2502
- <div class="container">
2503
- #{rows}
2504
- </div>
2505
- </div>
2506
- </div>
2507
- CONTENT
2508
- super
2509
- end
2510
- end
2511
-
2512
- class RawPage < Page
2513
- def initialize(title, global_settings, options, &block)
2514
- super
2515
- end
2516
-
2517
- def generate(back_folders, options={})
2518
-
2519
- elem = Elements.new(self, {})
2520
- elem.instance_eval(&@block)
2521
-
2522
- elem.generate
2523
- end
2524
-
2525
- end
2526
-
2527
- class EmptyPage < Page
2528
- def initialize(title, global_settings, options, &block)
2529
- super
2530
- end
2531
-
2532
- def generate(level)
2533
- elem = Elements.new(self, {})
2534
- elem.instance_eval(&@block)
2535
- @body_class = "gray-bg"
2536
- @content = <<-CONTENT
2537
- <div id="wrapper">
2538
- <div class="wrapper-content">
2539
- <div class="container">
2540
- #{elem.generate}
2541
- </div>
2542
- </div>
2543
- </div>
2544
- CONTENT
2545
- super
2546
- end
2547
- end
2548
-
2549
-
2550
- class CenterPage < Page
2551
- def initialize(title, global_settings, options, &block)
2552
- super
2553
- end
2554
-
2555
- def generate(level)
2556
-
2557
- elem = Elements.new(self, {})
2558
- elem.instance_eval(&@block)
2559
-
2560
- @body_class = "gray-bg"
2561
- @content = <<-CONTENT
2562
- <div class="middle-box text-center animated fadeInDown">
2563
- <div>
2564
- #{elem.generate}
2565
- </div>
2566
- </div>
2567
- CONTENT
2568
- super
2569
- end
2570
- end
2571
-
2572
- class Weave
2573
- attr_accessor :pages
2574
- def initialize(file, options={})
2575
- @pages = {}
2576
- @file = file
2577
- @global_settings = options
2578
-
2579
- @global_settings[:root] = @global_settings[:root] || "/"
2580
- @global_settings[:root] = "#{@global_settings[:root]}/" unless @global_settings[:root].end_with? "/"
2581
- instance_eval(File.read(file), file)
2582
- end
2583
-
2584
- def set_global(key, value)
2585
- @global_settings[key] = value
2586
- end
2587
-
2588
- def center_page(path, title=nil, options={}, &block)
2589
-
2590
- if title == nil
2591
- title = path
2592
- path = ""
2593
- end
2594
-
2595
- p = CenterPage.new(title, @global_settings, options, &block)
2596
- @pages[path] = p
2597
- end
2598
-
2599
- def sidenav_page(path, title=nil, options={}, &block)
2600
-
2601
- if title == nil
2602
- title = path
2603
- path = ""
2604
- end
2605
-
2606
- p = SideNavPage.new(title, @global_settings, options, &block)
2607
- @pages[path] = p
2608
- end
2609
-
2610
- def topnav_page(path, title=nil, options={}, &block)
2611
-
2612
- if title == nil
2613
- title = path
2614
- path = ""
2615
- end
2616
-
2617
- p = TopNavPage.new(title, @global_settings, options, &block)
2618
- @pages[path] = p
2619
- end
2620
-
2621
- def nonnav_page(path, title=nil, options={}, &block)
2622
-
2623
- if title == nil
2624
- title = path
2625
- path = ""
2626
- end
2627
-
2628
- p = NonNavPage.new(title, @global_settings, options, &block)
2629
- @pages[path] = p
2630
- end
2631
-
2632
-
2633
- def empty_page(path, title=nil, options={}, &block)
2634
-
2635
- if title == nil
2636
- title = path
2637
- path = ""
2638
- end
2639
-
2640
- p = EmptyPage.new(title, @global_settings, options, &block)
2641
- @pages[path] = p
2642
- end
2643
-
2644
- def raw_page(path="", options={}, &block)
2645
-
2646
- # raw pages dont even have a title
2647
-
2648
- p = RawPage.new("", @global_settings, options, &block)
2649
- @pages[path] = p
2650
- end
2651
-
2652
- def include(file)
2653
- dir = File.dirname(@file)
2654
- filename = File.join([dir, file])
2655
- File.read(filename)
2656
- load filename
2657
- end
2658
- end
2659
- end
7
+ require 'weaver/weave'
8
+
9
+ require 'weaver/page_types/page'
10
+ require 'weaver/page_types/center_page'
11
+ require 'weaver/page_types/empty_page'
12
+ require 'weaver/page_types/raw_page'
13
+ require 'weaver/page_types/nonnav_page'
14
+ require 'weaver/page_types/sidenav_page'
15
+ require 'weaver/page_types/topnav_page'
16
+
17
+ require 'weaver/elements'
18
+
19
+ require 'weaver/element_types/accordion'
20
+ require 'weaver/element_types/action'
21
+ require 'weaver/element_types/code'
22
+ require 'weaver/element_types/dynamic_table'
23
+ require 'weaver/element_types/form'
24
+ require 'weaver/element_types/javascript_object'
25
+ require 'weaver/element_types/modal_dialog'
26
+ require 'weaver/element_types/panel'
27
+ require 'weaver/element_types/row'
28
+ require 'weaver/element_types/tabs'
29
+ require 'weaver/element_types/textfield_javascript'