Showing posts with label Bootstrap. Show all posts
Showing posts with label Bootstrap. Show all posts

Wednesday, February 17, 2016

Tapestry5 and the case of the disappearing bootstrap modal dialog

Tapestry5 has a pretty neat way to support JavaScript but once in a while I forget some things. Forgetting things then leads you to errors. In my case, the error was a bootstrap modal not properly displaying or disappearing immediately.

I was working on a simple but reusable modal Tapestry5 component. For some context on how to do this, go here. The important part here is the top part where you declare your JavaScript includes:

@Import(module = {"bootstrap/modal"}) 
public class ModalDialog implements ClientElement{...}

This loads the modal.js from bootstrap. Tapestry5 can do this because the framework is bootstrap aware. We then finish this up with the javascript and tml file for the component.

Thinking all was Ok, I then use this component on a page and this is where I encountered the "disappearing modal" dialog.

After debugging, I followed the bug to my layout component. Again, the important part here is where we declare the JavaScript includes:

@Import(stylesheet = {"context:datatables/css/dataTables.jqueryui.css","context:patternfly/css/patternfly.css", 
                      "context:patternfly/css/patternfly-additions.css"},
        library = {"context:patternfly/js/patternfly.js", "context:mybootstrap/js/bootstrap.min.js"})
public class Layout{...}

Apparently, bootstrap doesn't like when we double load modules. The bootstrap.min.js is a minified bootstrap and it already has the modal.js module. Then, when we load the page where we use the ModalDialog component which double loads the modal.js module.

This bug was easily fixed by removing the import annotation in my ModalDialog component.

I forgot about my JavaScript basics that invoking the script twice equals problems.

Also, this was confirmed by this StackOverflow question.

Monday, May 4, 2015

Bootstrapping the View Parts

Time to add a face to our project. So, we break out our favorite framework for the designed-impaired programmer, Bootstrap!

Download the stuff and put it in the public/ folder. I made a bootstrap folder in my public folder to keep it organize. Don't forgot to also get jquery. Bootstrap doesn't work without jquery. This is the easy part.

The next part is kinda hit or miss: Jade

Nodejs with Express uses a templating engine to make views. There are a couple of options but jade is the default. I say hit or miss is because some take to Jade like ducklings to water. Some of you might not be ducklings. 

Here's a sample:

nav(class='navbar navbar-default navbar-static-top')
    .container
        .navbar-header
            button(type='button', class='navbar-toggle collapsed', data-toggle='collapse',                    data-target='#navbar', aria-expanded='false', aria-controls='navbar')
                span(class='sr-only') Toggle navigation
                span(class='icon-bar')
                span(class='icon-bar')
                span(class='icon-bar')
            a(class='navbar-brand', href='#')= title
        div(id='navbar',class='navbar-collapse collapse')
            ul.nav.navbar-nav
                li.active
                    a(href='#') Home
                li
                    a(href='#') About
                li
                    a(href='#') Contact

Jade templating language is quite terse to write compared to raw HTML. It also has a few fun parts like includes, conditionals and mixins.

In the Views/ folder, I made a shared folder and move the common stuff like the layout and navbars. This way I can compose the view like lego bricks AND that's where the fun starts.

Clone the repo at Github.

Monday, January 26, 2015

Dropping Bootstrap for Patternfly

Bootstrap is a godsend to single developers who suck at design. It had everything from components to simple animations for that eye candy.

And then things messy when that developer finds "themes" for bootstrap like the free ones over that bootswatch or the high-end stuff over at wrapbootstrap. I'm not saying these things are bad but all to often developers don't have the "design disciple" to use these themes. As developers, we have this tendency to use all the features, colors, suggested layout, etc.; user experience not withstanding. I'm guilty of this. We end up with this "soup" of a website or web app that's full of fancy animations and inconsistent visual design.

I think the fix for this is a set of guidelines that developers can happily follow and this is where patternfly comes in. Pattenfly is built on bootstrap so developers already using bootstrap will have no problem using it.

The nice things with Patternfly:

  1. No more trawling the net for lay-outing advice (https://www.patternfly.org/wikis/layout-templates/)
  2. Common design patterns done (https://www.patternfly.org/wikis/patterns/loginlogout/)
  3. Shitload of widgets, visual widgets and fonts
  4. And it's free; github here.




Sunday, August 18, 2013

Bootstrap tabs and the curious case of the missing bottom border

I'm a big fan of Twitter bootstrap. It's a big help for the design impaired. But as helpful Bootstrap is it still has a few things that you have to do yourself. It is where my story begins. I needed to get to here:

Tabs pulled right with an H4 element on the left WITH a bottom border


From here. This is how it should look like with the default markup using Bootstrap.

Tabs pulled right with an H4 element on the left WITHOUT a bottom border

I will post the markup here. The HTML markup is pretty standard.

     <div class="col-8 subheader">  
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The interesting part is getting the bottom border to work out. If all goes to plan it should stretch from the "Postings" element up to the first tab. My solution isn't that good if you're into strict semantic HTML5 but I'd rather get it working than worrying about writing proper semantic HTML5. At least it will validate.
     
     <div class="col-8 subheader">  
       <div id="btm-border"></div>
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The other half is the CSS rule. I write CSS using Less. Why? BECAUSE REASONS!

.subheader{
    position: relative;

    #btm-border{
        border-bottom: 1px solid #ddd;
        position: absolute;
        width: 446px;
        top: 42px;
    }
}

Tuesday, March 5, 2013

Tapestry 5.3 and the case of Twitter-Bootstrap disabled attributes

Making Tapestry5 use Twitter-Bootstrap as its style is quite easy but not everything is as it seems.

Bootstrap as some nice form style rules. It's quite easy to add them into normal tapestry5 common components. Like if you need some a textfield to look like a "search-query" field then you would write something like:

// Rounded corners
<input t:type="textfield" t:id="keyword" class="search-query" placeholder="Callslip ID"/>  

or if you need a page or event link to look like a button:

// Tapestry5 eventlink styled as a button via Bootstrap
<a t:type="eventlink" t:event="add" class="btn brn-primary" href="#">Add 1</a>  

But I have recently came across a scenario where I need to display a textfield with data that's by default is uneditable but under certain conditions can be edited. Reading the bootstrap documentation, you have to do something like this:

// As shown in the Bootstrap documentation
<input class="input-xlarge" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

OK, that should be easy to convert into tapestry5 component and use javascript to enable or disable the field. When done via jquery, removeAttr() or prop(). There's an equivalent to add an attribute.

// Tapestry5 is not happy about disabled attribute
<input class="input-xlarge" id="disabledInput" t:type="textfield" placeholder="Disabled input here..." disabled>

And that's this is where the problem crops up. Tapestry5 doesn't like any unpaired attributes. I'm talking about the disabled attribute at the end of the input element above. Fortunately, Peter Wendorff in the Tapestry mailing-list pointed me to a html microsyntax spec document explaining this unique nuance of html. You have to do a disabled="true" attribute to makeTapestry5 happy.

// How Tapestry5 wants it done
<input disabled="true" class="input-xlarge" t:id="name" t:type="textfield" placeholder="${name}" />
Other ways to write this doesn't work, even if the spec doc says its OK.

  • disabled="" -> doesn't work
  • disabled="disabled" or disabled='disabled' or disabled=disalbed -> also doesn't work
  • disabled -> obviously doesn't work

Tuesday, August 21, 2012

My CodeIgniter + Bootstrap starter kit


I thought I would share my CodeIgniter + Bootstrap starter kit.

Highlights:
- CodeIgniter 2.1.0 codebase included
- Bootstrap 2.0.3 theme with its JS extensions in a single file
- jquery 1.7.1 and knockout 2.1 included
- default controller: home/start.php; default view: home/start.php

To use, it just drop inside your /htdoc or /var/www folder.

Download the zipped file or clone it from my bitbucket mercurial repo. To clone:

hg clone https://bitbucket.org/jaypax/cibootstrap

Have fun with it.

Updated 9/29/2012

  • Updated Bootstrap to 2.1.0 
  • Added bootstrap-responsive.css (min version included)
  • Updated CodeIgniter to 2.1.2 
  • Added underscore.js 
  • Added underscore-ko.min.js (see https://github.com/kamranayub/UnderscoreKO
  • Added jquery-1.7.1-vsdoc.js