Archives

All posts for the month July, 2013

Bootstrap 3 Change Notes

blurred code

After spending the last two days working with Bootstrap 3 I wanted to jot down a few of the things I found in case I forget them tomorrow or to help anyone else running into similar issues.

Forms, Grid System, and Screen Resolutions

We have converted our forms from form-horizontal to the default Bootstrap form.  We think it looks better with the new update.

Old code:

New code:

Cleaned up a bit as we had that extra label tag on our old code which was unnecessary as Django adds the label tag correctly on render.  One of the biggest thing to notice is that the span4 tag changed to col-4.  Bootstrap is now responsive by design and mobile first which means that the col- tags are meant for display on a mobile device but are the default when no other tags are found.  This gives us the ability to make pages and forms that appear differently depending on screen resolution.  There are three tags for column spacing, col- for mobile devices, col-sm- for tablet screens, and col-lg- for desktops.  To use the various screen sizes just add on more tags.  The sizes will appear when viewed on different resolutions.  Making the above example take up the whole row on a mobile device and only a third of the screen on a desktop would change the code like so:

Easy enough right?  I thought so too!  Not all of us will have a mobile device or tablet ready to go to test our site on different resolutions.  You can always just resize your window to see what happens but that is annoying too.  Luckily, we found a great site that will take any URL and display the page at any screen resolution and has a lot of built-in resolutions for common devices called Screenfly.  This even works for pages hosted locally.

Modals

Modals had a lot of changes made to them which made us redo all of our current modals because they were all broken.  Example:

Old code:

New code:

A few things to note, the first of which is that the old code was using JavaScript to load in the contents of a page into the modal. Turns our Bootstrap did this already if you just provided the link in the href.  Now we know.  The hide class has been removed.  When the modal is opened Bootstrap adds the modal-open class to the body which stops scrolling on the page and limits it to the modal only.  Pretty awesome.  Make sure your JavaScript files are being loaded at the bottom of your HTML pages to ensure this works correctly.

One thing we have been trying to do is put all Save buttons on the right side of our pages and modals.  Using the Bootstrap pull-right class floats objects to the right.  The problem with this is the modal-content div will not grow with floated objects.  More specifically no outer div will grow with floated elements by default.  To get around this you simply need to add a bit of CSS.

This works perfectly for any modal with a floated right button at the bottom but if there isn’t anything floated at the very bottom of the modal this will add an extra 15px to the padding, which we don’t want. To fix that just make that CSS a bit more specific by using id’s on the modals you want to specifically fix.  I have made a jsFiddle which demonstrates exactly what I am talking about.

Closing

That’s it so far.  Most of that took a really long time to figure out.  Bootstrap dropped their typeahead JavaScript in favor of typeahead.js which I’m still trying to figure out fully.  I’ve got it to work but there are some really weird things happening that I think have to do with Bootstrap 3.  The biggest problem we are running into is that Bootstrap 3 is so new no one has written much about how to fix little problems like the ones we’ve had so far and other utilities haven’t updated to fully support it yet so we soldier on.

Let me know if you have any other tips or if you’ve had anything that has tripped you up so far.

EDIT – 8/1/13

Bootstrap dropped support for their own bootstrap-typeahead.js and has instead suggested typeahead.js by Twitter.  One of the biggest problems with that right now is typeahead.js does not support Bootstrap 3 and so the CSS is messed up.  Here is an example I wrote up quickly to demonstrate it and I have commented on their GitHub project page on the issue of Bootstrap 3 CSS problems..  They say they are aware of it and the CSS is on their TODO list.  Here’s to hoping it happens quickly!

Bootstrap 3 RC1

Bootstrap 3

Creating our new site required a better base.  We chose to use the popular Bootstrap CSS engine to unify our CSS and help us get things started quickly.  After using Bootstrap 2.3.2 for nearly three months Bootstrap 3 was released.  We had hoped that the update would not affect our code base but we were wrong.  Nearly everything has changed in our styling.  Bootstrap 3 has gone for a mobile-first approach making even the basic framework responsive.  This is great for most developers, and even for us, because we can make wonderful sites that look and feel great on all platforms.  Our company had talked about wanting mobile versions of applications but we had put that on the back burner as many of our applications involve data entry.  Converting our project to use Bootstrap 3 has been a headache due to changes to simple classes that were used before but we are moving forward and should have things squared away by tomorrow.  The site looks cleaner, runs faster, and works on mobile already.  All in all it has been for the best but the headache will continue probably through the rest of the week as we smash all the bugs related to their new JavaScript and CSS.

Let me know if you’re using it and what you think about the changes.

Simple JavaScript Clock with Time Zone Support

Just wanted to write down a quick little JavaScript clock I made that converts to the user’s time zone.  Since we have offices all over the world and the date time fields keep track of time in UTC it is important for users to know what time zone they are currently logged into.  I have placed this clock in the navbar at the top of the page next to the user to let them know what the current time is for their settings.  If they need to change it they can do so by clicking on it and changing their user profile.  Here is the code and feel free to fork this project at GitHub.

Let’s break it down a bit.  At the beginning we get the user’s current office which is held in an input hidden in a modal on every page.  We then run the startTime function and begin our journey.  First we add a couple of features to the JavaScript Date to help us account for day light savings time in countries that follow that.  Then we figure out the time zone offset from UTC time depending on the office.  This offset is not including day light savings time which is what gets calculated next.  We get the current date by calling new Date().  This gets the system time which we use to see if it is day light savings time.  Day light savings time is not followed in China and so the check for office number is there to not do the calculation for China and Taiwan.  We then convert the current time to UTC and add the offset to the hours.

At this point we just need to output our result to be displayed.  The checkTime function is called to add a zero in front of numbers less than 10.  Then we get AM/PM and calculate for a 12 hour clock.  Modding by 12 will give us the current hour for all cases except noon and midnight where 0 is returned.  In these cases we simply check and return 12.  Then we output to our div and we’re done.  Then we run a timer to run every half-second.  It may run a bit fast but the results are negligible when it has a run-time of a certain amount of milliseconds and the timer gets recalculated at each page refresh it is not noticeable.  I’d rather have it a moment or two fast than slow.

I got a lot of this code from Googleing around but altered it almost entirely to fit my needs.  I couldn’t find anything that consistently accounted for time zones and day light savings time easily so I wrote my own.  Now when users log into our site and are looking at data they can make sure they are seeing the times for their office and won’t need to calculate time zone conversions on their own.

Final product!  Works great.  Everyone I’ve showed seems to love it and I’m pretty proud of it.

Screenshot from 2013-07-29 17:10:06

 

EDIT:

Here’s a shot when the user clicks on the time.  It displays the user’s office.  Clicking on the office will bring up their profile where they can change this setting.

Screenshot from 2013-07-29 17:13:02

MySQL Collation Matters

When creating databases and tables with MySQL there seems to be one setting that gets overlooked, collation and character set.  For most smaller sites, and maybe those purely in English, this may not be such a huge deal but for a larger application site and one that will be holding characters from various languages this is essential.

UTF-8 is the collation and character set we want and the MySQL command to create a database with these settings is CREATE DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;

Bringing this back to Django, when Django creates new tables within a database it will use whatever the default character set and collation is for that database.  This is why it is important to get this right at the beginning with the command above.  If you do not, however, there are ways to make future tables created have the right encoding.  Simply add these lines at the bottom of your database connection settings in your settings.py file:

I put mine right below the PORT variable in my default database connection.  This will ensure that all new tables created will have the correct collation and character set.  But what about those tables already created that need their settings changed to accommodate these special characters?  You can find out what collation the columns are using by entering this command for MySQL: SHOW FULL COLUMNS FROM my_table.  One of the columns shown is the Collation column.  Make sure this is some utf8 encoding and you’re good.  If it isn’t simply use the command ALTER TABLE my_table MODIFY column_name varchar(30) CHARACTER SET utf8; to change the column to the appropriate character set.  Make sure that the varchar(30) in the example is set appropriately to your column whether it be a text field, varchar(255), etc. make sure it is the same column it was before just with the new character set.  Run that command for every column that needs changing.  Run the SHOW FULL COLUMNS line again and make sure everything is right and that’s it!

Hope this helps someone, I know it has come up a lot in the project we are working on now and has become kind of a headache because we didn’t start the tables out correctly.

Django Context Processors

Today I started work on allowing users to edit certain settings we have for them, namely what office they are in and their language.  Using Bootstrap I changed the way our navbar worked so clicking on your name drops down to give you the option of editing your profile or logging out.  Editing your profile brings up a modal with the choices you can change.  This modal is located in our project’s base.html file so that users can change their settings on any page.  Generating the form with the options was where this post came in.

For a while now I’ve been using Django’s default language changing form.  In it they reference a variable LANGUAGES.  For the life of me I had no idea where that variable was being passed in from.  Now I needed my own variable, OFFICES, to be passed into every page as well.  After a quick Google search I found out that these variables are passed to the templates through context processors.  In your Django settings file you can see all of the context processors currently being used under TEMPLATE_CONTEXT_PROCESSORS.  Specifically, the one passing the LANGUAGES variable to all templates is django.core.context_processors.i18n.

To pass custom variables you’ll obviously need a custom context processor.  I created my own context_processors.py file in my Django project folder and this is what it looks like.

And on the settings file under TEMPLATE_CONTEXT_PROCESSORS I added:

You need to make sure to reference the method defined in the context_processors file.  With that being done you are free to add that variable in any of your templates without worrying about passing it directly through the views.

Django Translation – Going Live!

A while back I wrote a post about Django translation and getting your websites to be translated.  Since then it has been pretty successful in our development version of the site and I have continued to learn the quirks of Django translation.  A couple of things to note:

  1. In your .po files you will occasionally see that some of your strings have a #, fuzzy tag above them.  This means that there is already a translation found elsewhere and it’s not sure if it should use your translation file in this app or the other one it knows about.  I had a lot of issues with this so I have been removing the fuzzy tag entirely when I find it and this forces Django to use the translation file as is.
  2. Ordering matters in INSTALLED_APPS.  Django will load translation files in order of your INSTALLED_APPS list.  Django has a set of built in translated strings that it will use first before using your translations.  I found this was causing an issue when I didn’t like the translation used for the Chinese version of Email.  Django’s version was four characters long and the one I was using would only be two.  I had to rearrange my INSTALLED_APPS to load my translation files first before the Django ones.  Although, now that I think about it, this may be caused by fuzzy tags…I’ll look into this.

Once we had everything ready some people from the company wanted to see a demo to play around with.  We were going to put everything up and this included translation files just as a demo.  Transferring everything was easy with the new structure of Django since 1.4.  We simply dragged the apps over, updated the settings.py file, and collected static and we were ready to go!  One problem though, when I compiled the messages I was getting an error, and then another error, and another.  Here is a list of the things I did to get translation working on our Linux server.

  1. sudo apt-get install gettext – This is what Django uses to figure out translation and must be installed.
  2. Ensure USE_I18N = True in settings.py.  Ours was but it’s good to check.
  3. django.middleware.locale.LocaleMiddleware must be listed in your MIDDLEWARE_CLASSES – This is the kicker that took me a while to figure out.  Since it took me a long time to get this working on my dev server I didn’t write down all of the steps, hence this post.  This will not throw errors to your log files either so double-check.
  4. Update your project urls.py to include url(r'^i18n/', include('django.conf.urls.i18n')) – This is what Django uses to set the language of the user and is necessary for URL calls to change it.

That should be it.  If there is anything I missed I’ll be sure to update this post.

Django Timezone Conversions

Django does a great job at converting datetime objects to whatever the servers timezone is when your settings are set to do so.  For our big project we needed times to be local to the user.  Django documentation says to allow the user to select their time zone and save it to their user profile, which we plan to do.  Until then, to get things working, a few tests were in order.

I have a page where a user can make a note about a company and a timestamp is created and displayed for when the note was made.  When the template is rendered it takes the UTC specific time saved on the database and converts it to our local server timezone of ‘America/Denver’ automatically.  To make the site more responsive, and less hits to the server, I make the creation of these notes happen through an AJAX call.  The information is then displayed on the list quickly and quietly.  The problem I was running into was that the JSON object returned in the AJAX call had the UTC time and not the local time for the user.  When the page was refreshed, Django took over and displayed it correctly but I didn’t want to refresh the page every time.

Converting the timezone is pretty simple and here is what I found from the Django documentation altered to be specific to my one time zone change.

A few things to note are that the datetime object must be timezone aware and not naive.  If it is naive you will need to follow the Django documentation link to find how to give datetime objects timezones.  Hope that helped someone, I learned something.