Posts

Showing posts from 2012

Changing Dancer::Plugin::Ajax's content type

Dancer does lots of great things. It has a nice clean way to define routes to handle AJAX routes using the plugin Dancer::Plugin::Ajax. ajax routes are defined in a clear way: ajax '/stuff' => sub { # do work and return }; This plugin technique allows for clear way to separate between ajax and other types of actions for the same route. ajax '/stuff' => sub { # do ajax-y stuff here }; get '/stuff' => sub { # handle html response }; Unfortunately, the one negative with Dancer::Plugin::Ajax is that is assumes all responses will be XML. A quick fix is to manually set the content type in each ajax handler. ajax '/stuff' => sub { content_type('application/json'); # do work }; or add set it as a general option in your main before hook or in each prefix route handler like: package WebApp; hook before => sub { if ( request->is_ajax ) { content_type('application/json'); } }; Both of thes…

Blueberry (Image slider) and YouTube video working in harmony

Do what needs to be done We recently launched a new home page and the designed used a responsive image slider called Blueberry. Well there were a few issues with navigation and I needed to be able to make sure to have the slider start to slide automatically and then stop while playing a YouTube video.

I need to fix the problem with navigation causing a speed up and unreliable timing while showing slides. I extended it to support being stopped and started. Since the project appears to be on hiatus (no changes in a year even though it has a few github issues), I forked it on github to fix the event issue and add the ability to stop/start slider.
Blueberry + YouTube sitting in a tree I found it to be a bit of challenge to update the site to support pausing the image slider when the YouTube video that is linked in through iframe started and stop being played. I found to get the correct permissions and callback into the player I needed to use the YouTube iFrame Player API. (thank you Goog…

Template Tooltip Tip #1

A bit of background

Template toolkit is a powerful and mature Perl based templating engine. It is designed to be output format agnostic and used (or able to be used) with most of the Perl based Web application frameworks like Dancer, Catalyst and CGI::Application.

TT Tip #1 - Simple html attribute macro

In this tip, i'll combine using a TT macro with HTML plugin to create a simple macro to add active class to html element.

code

TT code: (put in top of template or shared TT file pulled in with PROCESS or INCLUDE)
[% USE HTML %] [% MACRO active GET HTML.attributes( 'class' => 'active' ) %]
Usage in a template:
<ul id="navBar"> <li [% active IF page.name == 'home' %]>Home</li> <li [% active IF page.name == 'about' %]>about</li> <li [% active IF page.name == 'contact' %]>contact</li> </ul>
In this case, when page.name matches then macro will drop in class="active". Si…

5 minute guide to using JS PubSub and Noty

5 minute guide to using PubSubJS and Noty A little background, Publish/Subscribe is a design pattern for decoupling components in software (or i guess anywhere in the world). The basic idea is that one thing publishes information to a well known place and another subscribes to it. There is lots of good writing about it out there, check it out on Wikipedia. In my situation we wanted to display page level notifications. I would consider these to be messages that aren't tied to a web widget or element (like a message in a form). Page level notifications can increase the usability of your application (too many or badly placed one can reduce it :) This tutorial will show you a simple way to create a subscriber that publishes messages to the browser using noty. And uses PubSubJS to handle the Publish/Subscribe work. The toolsYou will need a few things for this tutorial. jQueryPubSubJSnoty - jquery pluginGrab them and download, or you can try this shell snippet: mkdir js wget https://r…

Using (Test::?)WWW::Mechanize to test AJAX calls

Test::WWW::Mechanize + AJAX = Love? As we use more and more client side driven forms, testing in a standard way for unit/expanded unit tests becomes more and more difficult.
I've been in the process of creating more use case tests so as underlying components in our system changes those non-web people can verify that their changes don't break the webapp. 
This is often our REST API but can apply to DB changes or modules updates.
I've found this basic code block to work pretty well at using Test::WWW::Mechanize to simulate the situations where there are elements that use client side forms. (AJAX! But really AJAJ since we use JSON instead of XML).

BEGIN { use Test::More; use Test::Exception; use Test::WWW::Mechanize; use JSON; } # # setup test data or load it from db # # # in this test, i login w/ many page, jump to account page # then run ajax form and check json results # { diag "Running login and create user test"; my $mech = Test::WWW::Mechani…

bootstrap popover responsive layout

As i was working on solving some problems with Bootstrap's popovers and our responsive webapp design, I came up w/ this simple snippet to change the location of the popover using placement option using the current window's width.

Example of how to set placement using function:

$('.show-details').popover({ placement: function(tip, ele) { var width = $(window).width(); return width >= 975 ? 'left' : ( width < 600 ? 'top' : 'right' ); } });
In the long run i think it would make more sense to setup those location options in a map or site wide setting object along the lines of:

var superapp = {}; superapp.popover_layouts = { full: { width: 975, pos: 'left'}, mid: { width: 600: pos: 'right'}, micro: { width: 320: pos: 'top' } }; function determine_placement(tip, ele) { var width = $(window).width(); var map = superapp.popover_layouts; .... TBD .... :) }
I'm not sure I'm cr…

Bootstrap popover with function driven content

In another post, I wrote about a technique that allowed loading content into a popover using a function. Its a great feature but I found one gotcha. If you set anything in the data-content attribute on the trigger element, the content will not be loaded with the function. Maybe I should say that again for myself, If you want to use content: function() {...} your element must not include data-content Don't use: <a id="mypopover" href="#" data-content="will not run function"> Label </a> Use: <a id="mypopover" href="#" > Label </a> __END__

BootstrapX clickover

Birth
The last few weeks, i've been pushing Bootstrap in various directions. Most of the time, its being hacking around Popovers. Our current design uses Popovers with forms. It provides a very nice balance between in page action and more subtle interruption to viewing the page than a modal.

Over the last few weeks, I've found a few quirks with using Popover's trigger action of 'focus'. This works fine with forms but on Chrome and Safari 'focus' events are supported incompletely. In addition to that varied support we have a few other needs that inspired a new Bootstrap extension. BootstrapX - Clickover.

Our requirements are:
Click button/link/icon to toggle display of popover contentOption to click 'away' from popover to closeAbility to have 'popover' autoclose after some amount of timeOption to have element inside of popover hide it
I suspect, in the future, it will need to only auto close when user's mouse leaves the clickover.

Out of …

Bootstrap (by Twitter) loading in page content for Popovers

Bootstrap is a nice get started HTML/CSS/JS interface toolkit. At $work our newest design has been based on it and many of its components.

One of the challenges I've run into with the Popover element is generating in attribute content for complex elements.

The basic context is:
<a id="mypopover" href="#" data-content="stuff to display"> Label </a>
The popover gets the body from the data-content attribute. The other option that doesn't appear to be documented is using a function set in the options.

$('#mypopover').popover({ // other options here content: function(ele) { return $('#popover-content').html(); } });
This will load the html content from element '#popover-content' when calling 'show' on popover.

Note: If trigger element still has a data-content element, even if its empty, the content function will not be called by method.

My biggest issue still with Bootstrap tools is that they are not g…

Sticky floating headers inside of overflowing divs

In our latest project, we have some pretty sweet designs that have headers that drift down in the page as the user scrolls. But at some point the header will hit the end of the containing div and need to stop. (We have a date header for each transaction. The header stops floating once the next day's header is met in the scroll).

We had some luck using jquery plugin based on a good tutorial at Design Woop mixed with this updated Gist

But this fell apart when trying to use it with a div that had overflow set to 'auto' or 'scroll'. Since the plugin was calculating location based on document not the div element. Plus the plugin operated on single elements not on jquery objects.

CSS Looks like:
div.scroll { background-color: #eee; width: 600px; height: 200px; overflow:scroll; } .header { float: left; height: 30px; width: 600px; background-color: black; color: white; font-family: …

New CPAN Module: WWW::DirectAdmin::API

New module for interacting with DirectAdmin's API: WWW::DirectAdmin::API

It currently supports User level functions only. More to come later

__END__

Accessing Dancer config settings inside of a template

As I continue to work more and more with Perl Dancer, I run into situations where I need to pull in application configuration data inside of the template system.

Dancer provides access to this config in your template system with the template token settings. What caught me the other day was my desire to use it in the same way as the in the app's DSL: setting. This was my misreading of the documentation. To access settings in Template Toolkit, you must grab sub areas as hash keys.

Example: (you can see this in the generated new app code) App name: [% settings.appname %] I did have a case where I wanted to pull in a value that was located in the plugin section. The plugin (like some of them) are named with double colons (::) and I couldn't get the hash key lookup to work so I used TT's item virtual method.

This example dumps out RSS version:
Using RSS Output Version: [% settings.plugins.item('XML::RSS').output %]
Disclaimer: Of course in the case of some configuratio…