Aligning bootstrap well heights within the same row

On a bootstrapped page layout, misaligned well heights within a single row are ugly at best and downright unprofessional looking at worst

d1

 

So I created a simple jQuery routine which will:

  • Cycle through each row
  • Create a variable = 0
  • For each well in this row
    • Check the height of each well
    • If the height is larger than the current largest value increase it
  • Once finished set the height of all the wells in this row (already selected) to be the largest height

$('.row').each(function(){
  var wellHeight=0
  $(this).find('.well').each( function(){
      var temp = $(this).height()
      if (temp>wellHeight){
       wellHeight=temp
      }
  }).height(wellHeight+"px")
})

d2

 

 

 

Using CSS3 border-radius to round a Bootstrap button

This is a really simple observation, but relevant to the side project I have started to work on for my wife (more to come later)

If we create a simple Bootstrap button

b1

<button type="button" class="btn btn-default">Single toggle</button>

It looks something like this in firebug

b2

Looking at the .btn style on the right we can see border-radius: 4px

Messing with this value can create a much more rounded button – if that is your desire

b3

This is border-radius: 20px – Cool 🙂

 

Dynamically changing form labels into placeholders for mobile devices

When building a mobile interface with bootstrap, one design option is to use placeholders to signify the field label.

a1

This approach has many critics who questions the page accessibility, the fact that when you click into the field and start typing you lose the context, and so on. It is however an approach which is frequently used. In this article I wanted to show how I made the PSC contest submission form go from “Labels” to “placeholders” using media queries.

Labels

Looking at the form normally we see labels and fields

a2

If we have Labels and placeholders together at the same time, the effect is not really all that pleasing to the eye

a3

As the screen size is reduced the bootstrap styling kicks in around the Galaxy Note 4 size

a4

But when we get to the phone size screen the labels are removed and the the placeholders are made visible.

a5

 

If you go the https://contest.psclistens.com site you can play with it yourself by resizing the page

How does that work then?

The labels are easy – they are hidden with a media query

@media screen and (max-width: 460px), screen and (max-device-width: 460px){
	label:not(.projectSponsor) {
		display: none !important;
	}
}

The placeholders are not so easy though. The first problem is that the “placeholder” attribute does not have a CSS value to “display:none”. The second is that they are as yet not governed by a non-vendor prefixed style. Although you cannot hide the placeholders you can color them.

The code below is a media query which basically says that when the screen is above 768 pixels then the placeholders get a style color of white. I had to !important then to get it to override bootstrap properly. When the screen gets smaller the white override is lost and the bootstrap grey is seen.

	@media (min-width: 768px) {
		.form-control::-moz-placeholder {
		    color: white !important;
		    opacity: 1;
		}
		.form-control::-moz-placeholder {
		    color: white  !important;
		    opacity: 1;
		}
		*::-moz-placeholder {
		    color: white !important;
		}
		.::-webkit-input-placeholder {
		    color: white !important;
		    opacity: 1;
		}
		::-webkit-input-placeholder {
		    color: white  !important;
		    opacity: 1;
		}
		*::-webkit-input-placeholder {
		    color: white !important;
		}

	}

 

So the labels are hidden at 460 but the placeholder is displayed at 768 – so yes if you watch carefully as the screen is reduced you will see a screen size between the iPad and the phone where both are visible. This was done for effect so that you can see it happen.

Conclusion

Without going into the merits of whether or not this is an appropriate design method for displaying information to users, this served as a nice example of what is possible. This was all done within the context of an XPage.

Check it out – https://contest.psclistens.com

jQuery event delegation

So it turns out that I may have blogged a moment too soon over the weekend….

While the following code works

	$('.modal').on('shown.bs.modal', function () {
		$('FORM')
			.append($('.modal-backdrop, .modal-scrollable'));
	})

It only works the FIRST time – and if you had tested your code properly Mark you would have found this out to be the case. Too eager to blog weren’t we Marky……*pouts*

So anyway like all mistakes a good excuse for more learning – and in this case it wasn’t so much learning it was more muscle memory and more (oh duh Marky – which happens a lot)

The problem
What is happening is that the original code above is only binding to the modal once – and once the modal is being shown on the page and then hidden again apparently that event binding is being lost. I have no proof of this but I suspect that the DOM objects are being destroyed and recreated which is what is causing the loss 😦

The solution
Event delegation – oh it is a wonderful thing once you get your head around it and extremely powerful – go read up about it here and check out the last example specifically

What I was doing is binding to the exact element and once that element is gone – no more binding.

What is Event Delegation?
Event delegation is basically the same thing as event binding, but it works on any matching element whether it exists yet or not.
Que?
What I mean to say is that this piece of code REALLY WORKS and I will explain

$('body').on('shown.bs.modal', '.modal', function () {
    $('FORM')
        .append($('.modal-backdrop, .modal-scrollable'));
})

In this example we are:

  • Selecting the Body
  • And then in the shown.bs.modal event of anything matching the .modal selector
  • do stuff as before.

So if you imagine a simple analogy of feeding a dog.

If you have a child – let’s say your son and you tell him that on the “breakfast event” put food in that exact blue dog bowl – he will do that

Being the obedient child that he is he will fill that bowl every day when it appears.

But being the obstinate child he is, when you replace *that* blue bowl with a new one he will not fill it because you told him to fill the old one

A fight ensues and he loses minecraft privileges!

You then change your instructions:  On the “breakfast event” put food in any dog bowl which appears in the Kitchen. So even if you replace it every day he will have to still do as he is told and fill the bowl.

That is what Event Delegation is – telling the DOM to do things to anything which exists now and anything which appears in the future.

The way it works is because of the second selector – you are telling the DOM body to look for anything with a shown.bs.modal and bind to it. So even though my original dialog apparently lost the binding, in the new case it is automatically re-applied because of the delegated event on the Body

If only I had remembered that before blogging earlier…….

Ah well – we all learned something new

I wonder what I missed today………..

Making XPages partialRefresh work in a bootstrap 3 dialog box.

In this article I will improve on the solution I posted last week to my form submittal problem and actually provide a more elegant and robust solution.

The problem

Dave Leedy

I mean to say that Dave Leedy posed a problem to me last Friday which gave me pause for thought. Obviously he had come across this issue before. “Marky have you tried to do a partialRefresh inside of the bootstrap modal dialog?”. I had not and I knew that I had plans to…..

Then it struck me – of course the partialRefresh can’t work in the dialog because the dialog is outside of the form. The partialRefresh relies on the ability to post data back to the server (via the form) and the collect the response and re-draw. Of course it isn’t going to work.

The solution

As I said the other day – the bootstrap dialog is not purposefully removing itself from the form, it is moving itself to the end of the DOM tree. Why? I couldn’t say but it seems to be pretty consistent. So on the assumption it is nothing to do with the “form” I figured the easiest solution would be to put it back *into* the form once it was visible.

As we saw before when the modal is created there are two elements moved to the end – the dialog itself and the faded out background

b3

Using a bit of jQuery magic we select those two DIVs and “append()” them back into the form. Using the append() method they are always added to the end of the target DOM element container. You should add this code to every page where you have a dialog. Add this code to a CSJS library and include it on every page where you have a bootstrap modal.

$(document).ready( function(){
	$('.modal').on('shown.bs.modal', function () {
		$('FORM').append($('.modal-backdrop, .modal-scrollable'));
	})
})

  What does that mean exactly?

  • In the ‘shown.bs.modal’ event of the selected $(‘.modal’)
  • Get the $(‘FORM’) and .append() into it the two selected $(‘.modal-backdrop, .modal-scrollable’) DIVs

and then you get this

b4

Once the modal is then inside the dialog we can post it to our hearts content.

We can prove that with a simple @Random within the dialog box and a quick code snippet in firebug

We add a “random” class to the computed text so that we can select it

b5

We then load up the dialog

b6

Run the JavaScript to cause a partialRefresh

b7

Et voila a partialRefresh with a dialog. It also works of course with XPage controls and buttons and the like but this was just a simple way to demonstrate how to do it

Conclusion

Once we understand the DOM changes which are being made for a bootstrap dialog we are able to use jQuery to easily manipulate the  resulting DOM to be able to make our application work.

 

ADDENDUM – updated

Please see the jQuery Event Delegation blog post to understand why this approach is limited and needed to be updated….new solution provided

Why does hitting submit from within a bootstrap dialog not work?

In this article I will show why submitting an XPage from within a Bootstrap dialog does not work correctly and also discuss some options for working around the issue.

Introduction  

The bootstrap modal rocks (In Marky’s opinion) and it can be enhanced with the Bootstrap-Modal extension which gives greater control and more options. But I came across an issue recently whereby I could not “Submit” from within a dialog. Well ok I could submit but none of the fields seemed to be updated.

The Dialog

Initially the bootstrap dialog code sits within the XPage quite happily and it is hidden by CSS.

b1

But what happen when the dialog is displayed on the page? The HTML is manipulated and the modal dialog HTML code is moved within the DOM and apparently outside of the <form> tags.

b2

I do not think that it is intentionally moved outside of the form – what is really happening is that it is being moved to the last entry within the DOM – the following highlights it better – it is moved to the last DOM element within the body

b3

What does this mean?

Well what it means is that then you have a custom control displayed within the Dialog, and you try to hit a submit button from within the dialog, the fields are not “in the form” and therefore are not submitted back to the server. Simple answer once you figure it out (an “oh well no duh” moment)

So what can we do about it?

We have a number of options all of which are to do…….

  1. Do not submit from a dialog (not always practical)
  2. Looking at the bootstrap modal API event (http://getbootstrap.com/javascript/#modals-usage) we can see that there is a hidden.bs.modal event with this we know that the modal is closed. Once the modal is closed it is reinserted back into the DOM correctly in the same place as it was originally. Once that happens if the form is submitted then the fields are in the “<form>” tag and we are good to go.
  3. We can manipulate the form to “re-surround” the whole page including the dialog
  4. We can insert a new <xp:form> tag within the dialog and submit that one instead http://stackoverflow.com/a/9349329/1171653
    1. (in this author’s opinion embedded forms are just asking for trouble and should be avoided)

Whichever you prefer to do depends on your circumstances and needs from the code. If anyone has any other suggestions I would love to hear them!

Conclusion

Love Bootstrap, Love the Dialog, but like everything, sometimes you need to get a better understanding of how it works and tweak it a little.