This information is accurate for YUI 3.5.0pr2 - there are cross browser issues with the following method on previous versions.

From time to time you may find yourself loading modules that aren’t available. Whether it be from a user supplied modules list or an unreliable source, the YUI instance confg gives you an easy way to check if there are any errors while loading your modules.

A common YUI config and use statement would look like the following.

YUI({
  modules: { // Define your custom module meta data
    'custom-module' : {
      fullpath: 'path/to/module.js'
    }
  }
}).use('node', 'custom-module', function(Y) {
  // Your code here
});

If for some reason the loader was unable to fetch a required module and you wanted to act on that event, the loader provides you with an onFailure method that is called with an object that has details about the modules it failed to fetch.

To use this method you would amend the above code to include that method.

YUI({
  modules: { // Define your custom module meta data
    'custom-module' : {
      fullpath: 'path/to/module.js'
    }
  },
  onFailure: function(error) {
  	// Error handling code
  }
}).use('node', 'custom-module', function(Y) {
  // Your code here
});

The error object is structured.

{
  data: Array[], // Contains a list of the requested modules
  msg: "Failed to load path/to/module", // A string error message
  success: false // A bool representation of the success of the requests
}

It’s that simple, by setting up your onFailure callback you can easily handle any errors that may arise by an improperly structured config or use statement.

Warning

If there is a failure in your initial module request the onFailure callback will be called before the Y instance is set-up. This means that no YUI methods will be available and calls to them will cause your application to fail. In this case the this property will point to YUI.

More Reading

In the following example the onFailure callback will be called if at any time there is a failure while trying to load modules. You will need to keep this in mind if your doing any lazy loading of modules so that you can appropriately handle the errors.

YUI({
  modules: { // Define your custom module meta data
    'good-module' : {
      fullpath: 'correct/path/to/good-module.js'
    },
    'bad-module' : {
      fullpath: 'path/to/bad-module'
    }
  },
  onFailure: function(error) {
  	// I'm going to be called when the request for bad-module is made
  }
}).use('node', 'good-module', function(Y) {

  Y.use('bad-module', function() {
  	// More code here
  });

});

The error.msg property string will contain comma delimited messages about which values failed.

YUI({
  modules: { // Define your custom module meta data
    'wrong-module' : {
      fullpath: 'path/to/wrong-module'
    },
    'bad-module' : {
      fullpath: 'path/to/bad-module'
    }
  },
  onFailure: function(error) {
  	console.log(error);
  }
}).use('node', 'wrong-module', 'bad-module', function(Y) {
  // Code here
});
{
  data: Array[22],
  msg: "Failed to load path/to/wrong-module,Failed to load path/to/bad-module",
  success: false
}

This method only works if the module has been defined. You will not receive an error for the crazy-module.

YUI({
  modules: { // Define your custom module meta data
    'wrong-module' : {
      fullpath: 'path/to/wrong-module'
    }
  },
  onFailure: function(error) {
  	console.log(error);
  }
}).use('node', 'wrong-module', 'crazy-module', function(Y) {
  // Code here
});

You will however get a string error logged to the console in addition to the onFailure if the undefined module comes before the defined custom modules.

YUI({
  modules: { // Define your custom module meta data
    'wrong-module' : {
      fullpath: 'path/to/wrong-module'
    }
  },
  onFailure: function(error) {
  	console.log(error);
  }
}).use('node', 'crazy-module', 'wrong-module', function(Y) {
  // Code here
});
"yui: NOT loaded: crazy-module"

After a year of trying to get the time to roll my own blog I cut my losses and set up with tumblr. The plan is to write a quality article every week on web development but you will probably see an odd one here and there about other things that I find interesting.

I hope you enjoy the things to come and I look forward to your comments.

-Jeff Pihach

YUI Popup Calendar

The YUI Popup Calendar component extends YUI’s Calendar Widget as well as a few other Widget modules you likely have already loaded on the page giving you a very lightweight (1.6KB minified) way to add date picker like functionality to your web page or application.

You can find the code via Github here: YUI Gallery fork

How to use

Almost all of the configuration properties for Y.PopupCalendar are for Y.Calendar and the other modules that it extends.

HTML

<form class="yui3-skin-sam">
	<input name="name" type="text" autocomplete="off"/>
	<input name="date" type="text" autocomplete="off"/>
	<input name="phone" type="text" autocomplete="off"/>
</form>

CSS

In order to style this calendar like the YUI default calendar you need to add the class .yui3-skin-sam to a parent container of the calendar.

To have the calendar positioned overtop of other contents on your page and to hide when you click away the following two classes need to be added to your css

.yui3-popup-calendar {
  position: absolute;
}

.yui3-popup-calendar-hidden {
  display: none;
}

Javascript

YUI().use('popup-calendar', function(Y) {

  var input =  Y.one('form input[name=date]'),
      popupcalendar = new Y.PopupCalendar({
    // Popup Calendar config properties
    // input: the text input that will trigger
    // the calendar to show
    input: input,

    // focus the calendar on input focus for
    // keyboard control (default is false)
    autoFocusOnFieldFocus: false,

    // depending on the browser you may  
    // need to have all tabindex's defined on
    // inputs, you can use this attribute to do
    // it so you don't have to (default is false);
    // doesn't specify the tabindex then this is required
    autoTabIndexFormElements: false,

    // Calendar config properties
    width:'400px',
    showPrevMonth: true,
    showNextMonth: true,
    date: new Date(),

    // Widget Position Align configuration properties
    // This is now optional and defaults to the following
    align: {
      node: input,
        points: [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]
    }
  });

  // The popup calendar makes no assumptions as to
  // what you want to do with the selected date
  // so it is up to you to do something with the emitted event.
  popupcalendar.on('dateSelected', function(e) {
    var d = e.newSelection[0];
    popupcalendar.get('input').set('value', d.getDate() + "/" + d.getMonth() + "/" + d.getFullYear());
  });

});

Repositioning the calendar on resize

If the user resizes the browser once the calendar is open they run the risk of covering it up. To remedy this, you simply need to interact with widget-position-align on resize

Y.on('resize', function(e) {

  // Use the resize event object `e` and the position of the
  // bounding box popupcalendar.get('boundingBox'); to
  // check if the calendar is outside of the viewport
  // use that calculation to determine the points to set the
  // new alignment points to

  // Change the points that the calendar aligns with
  popupcalendar.align: {
    node: input,
    points: [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BR]
  }
});

Known Bugs

Opera in Ubuntu (possibly other os’s as well) has an odd keyboard navigation highlighting alignment issue with the Calendar. The calendar is still functional albeit a little odd to navigate via keyboard.

Hitting enter when navigating the calendar by keyboard does not select a date in IE7 & IE8

I'm Jeff Pihach, welcome to From An Egg. I’m a senior software engineer at Canonical, entrepreneur and front end developer. I focus primarily on web application development for mobile and desktop. I blog about web development but will mix in the odd post about other things that interest me.

Active

Bit Rot