Class: JsMenuBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/jsmenubuilder.rb

Constant Summary collapse

TABS_CSS =
<<EOF
/* Style the tab */
.tab {
  overflow: hidden;
  border: 1px solid #ccc;
  background-color: #f1f1f1;
}

/* Style the buttons that are used to open the tab content */
.tab button {
  background-color: inherit;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  transition: 0.3s;
}

/* Change background color of buttons on hover */
.tab button:hover {
  background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
  background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
  display: none;
  padding: 6px 12px;
  border: 1px solid #ccc;
  border-top: none;
}
EOF
TABS_JS =
<<EOF
function openTab(evt, tabName) {
  // Declare all variables
  var i, tabcontent, tablinks;

  // Get all elements with class="tabcontent" and hide them
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }

  // Get all elements with class="tablinks" and remove the class "active"
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }

  // Show the current tab, and add an "active" class to the button that opened the tab
  document.getElementById(tabName).style.display = "block";
  evt.currentTarget.className += " active";
}

// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
EOF
FULL_PAGE_TABS_CSS =
<<EOF
/* Set height of body and the document to 100% to enable "full page tabs" */
body, html {
  height: 100%;
  margin: 0;
  font-family: Arial;
}

/* Style tab links */
.tablink {
  background-color: #555;
  color: white;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  font-size: 17px;
  width: 25%;
}

button.active {
  background-color: #c55;
}

.tablink:hover {
  background-color: #777;
}



/* Style the tab content (and add height:100% for full page content) */
.tabcontent {
  color: #000;
  display: none;
  padding: 100px 20px;
  height: 100%;
}

EOF
ACCORDION_CSS =
%q(



.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #ccc;
}

.accordion:after {
  content: '\002B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "\2212";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
)
<<EOF
/* Style the navbar */
#navbar {
  overflow: hidden;
  background-color: #333;
}

/* Navbar links */
#navbar a {
  float: left;
  display: block;
  color: #f2f2f2;
  text-align: center;
  padding: 14px;
  text-decoration: none;
}

/* Page content */
.content {
  padding: 16px;
}

/* The sticky class is added to the navbar with JS when it reaches its scroll position */
.sticky {
  position: fixed;
  top: 0;
  width: 100%;
}

/* Add some top padding to the page content to prevent sudden quick movement (as the navigation bar gets a new position at the top of the page (position:fixed and top:0) */
.sticky + .content {
  padding-top: 60px;
}
/* see https://stackoverflow.com/questions/10732690/offsetting-an-html-anchor-to-adjust-for-fixed-header */
.anchor {
  background-color: transparent;
  padding-top: 70px;
  margin-top: -70px;
  display: block;
}

h2.anchor {
  background-color: transparent; 
  padding-top: 60px;
  margin-top: 0px;
}

EOF
FULL_PAGE_TABS_JS =
<<EOF
function openPage(pageName,elmnt) {
  var i, tabcontent;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }

  // Get all elements with class="tablink" and remove the class "active"
  tablink = document.getElementsByClassName("tablink");
  for (i = 0; i < tablink.length; i++) {
    tablink[i].className = tablink[i].className.replace(" active", "");
  }


  document.getElementById(pageName).style.display = "block";
  elmnt.className += " active";
}

// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
EOF
ACCORDION_JS =
<<EOF
var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    e = panel.children[0];

    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
                              
      if (e && e.tagName == 'INPUT' && e.type == 'hidden')  {
                              
        let event = new Event("dblclick");
        e.dispatchEvent(event);                              

      }
    }                                               
    else {
      panel.style.maxHeight = panel.scrollHeight + "px";
      if (e && e.tagName == 'INPUT' && e.type == 'hidden') 
        e.click()            
    } 
  });
}

EOF
<<EOF

// When the user scrolls the page, execute myFunction 
window.onscroll = function() {myFunction()};

// Get the navbar
var navbar = document.getElementById("navbar");

// Get the offset position of the navbar
var sticky = navbar.offsetTop;

// Add the sticky class to the navbar when you reach its scroll position. Remove "sticky" when you leave the scroll position
function myFunction() {
  if (window.pageYOffset >= sticky) {
    navbar.classList.add("sticky")
  } else {
    navbar.classList.remove("sticky");
  }
}
EOF

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(unknown = nil, options = {}) ⇒ JsMenuBuilder

Returns a new instance of JsMenuBuilder.



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/jsmenubuilder.rb', line 285

def initialize(unknown=nil, options={})
  
  @debug = options[:debug]
  puts 'options: ' + options.inspect if @debug    
  
  if unknown.is_a? Symbol
    type = unknown.to_sym
    
  elsif unknown.is_a? String then
    
    s, _ = RXFHelper.read unknown
    if s =~ /^<tags/ then
      options = parse_xml(s)
      type = options.keys.first
    else
      type = unknown.to_sym
    end

  elsif unknown.is_a? Hash
    options = unknown
  end    

  @types = %i(tabs full_page_tabs accordion sticky_navbar)
  
  build(type, options) if type

end

Instance Attribute Details

#cssObject (readonly)

Returns the value of attribute css.



283
284
285
# File 'lib/jsmenubuilder.rb', line 283

def css
  @css
end

#htmlObject (readonly)

Returns the value of attribute html.



283
284
285
# File 'lib/jsmenubuilder.rb', line 283

def html
  @html
end

#jsObject (readonly)

Returns the value of attribute js.



283
284
285
# File 'lib/jsmenubuilder.rb', line 283

def js
  @js
end

Instance Method Details

#import(xml) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/jsmenubuilder.rb', line 313

def import(xml)
  
  puts 'inside import'.info if @debug
  doc = Rexle.new(xml)
  type = doc.root.attributes[:mode]
  
  type = if type == 'fullpage' then
  'full_page_tabs'
  elsif type.nil?
    doc.root.name unless type
  end
  
  tabs = doc.root.xpath('tab').inject({}) do |r, tab|
    r.merge(tab.attributes[:title] => tab.children.join.strip)
  end
  
  e = doc.root.element('tab[@mode="active"]')
  
  default_tab = if e then
    title = e.attributes[:title]
    (tabs.keys.index(title) + 1).to_s
  else
    '1'
  end

  h = { active: default_tab, tabs: tabs}
  build(type, h)
  self
  
end

#to_cssObject



344
345
346
# File 'lib/jsmenubuilder.rb', line 344

def to_css()
  @css
end

#to_hObject



348
349
350
# File 'lib/jsmenubuilder.rb', line 348

def to_h()
  @h
end

#to_htmlObject



352
353
354
# File 'lib/jsmenubuilder.rb', line 352

def to_html()
  @html
end

#to_jsObject



356
357
358
# File 'lib/jsmenubuilder.rb', line 356

def to_js()
  @js
end

#to_webpageObject



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/jsmenubuilder.rb', line 360

def to_webpage()

  r = block_given? ? yield(@css, @html, @js) : @css, @html, @js
  css, html, js = *r.flatten
  puts 'css: ' + css.inspect if @debug
  
  a = RexleBuilder.build do |xml|
    xml.html do 
      xml.head do
        xml.meta name: "viewport", content: \
            "width=device-width, initial-scale=1"
        xml.style "\nbody {font-family: Arial;}\n\n" + css
      end
      xml.body
    end
  end

  doc = Rexle.new(a)
  e = Rexle.new("<html>%s</html>" % html).root
  
  e.children.each {|child| doc.root.element('body').add child }
  
  doc.root.element('body').add \
      Rexle::Element.new('script').add_text "\n" + 
      js.gsub(/^ +\/\/[^\n]+\n/,'')
  
  "<!DOCTYPE html>\n" + doc.xml(pretty: true, declaration: false)\
      .gsub(/<\/div>/,'\0' + "\n").gsub(/\n *<!--[^>]+>/,'')
  
end

#to_xmlObject



391
392
393
# File 'lib/jsmenubuilder.rb', line 391

def to_xml()
  @xml
end