← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/new-yui3-calendar into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/new-yui3-calendar into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/new-yui3-calendar/+merge/160006

In preparation for dropping YUI 2, rewrite the calendar widget to make use of Y.Calendar from YUI 3.9.1. Sadly, it doesn't yet have pop-up functionality, so it is making use of a PrettyOverlay to provide that.
-- 
https://code.launchpad.net/~stevenk/launchpad/new-yui3-calendar/+merge/160006
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/new-yui3-calendar into lp:launchpad.
=== modified file 'lib/canonical/launchpad/icing/css/modifiers.css'
--- lib/canonical/launchpad/icing/css/modifiers.css	2012-12-07 20:37:04 +0000
+++ lib/canonical/launchpad/icing/css/modifiers.css	2013-04-22 05:04:28 +0000
@@ -252,12 +252,21 @@
     top: 4px;
     }
 
-/* Hidden must be the last rule because it overides all other rules. */
 .inline {
     display: inline;
     margin: 0;
     }
 
+/* Hidden must be the last rule because it overides all other rules. */
+.yui3-skin-sam .yui3-pretty-overlay .yui3-calendar-content {
+    background: none;
+    border: none;
+    }
+
+.yui3-calendarbase {
+    margin: 0 auto;
+    }
+
 /* Use 'hidden' to hide elements unconditionally.
  * Some things we want to hide by default only if javascript is enabled; for
  * these cases use 'hide-on-load'.

=== modified file 'lib/lp/app/javascript/calendar.js'
--- lib/lp/app/javascript/calendar.js	2012-03-08 14:47:15 +0000
+++ lib/lp/app/javascript/calendar.js	2013-04-22 05:04:28 +0000
@@ -1,4 +1,4 @@
-/* Copyright 2009 Canonical Ltd.  This software is licensed under the
+/* Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
  * GNU Affero General Public License version 3 (see the file LICENSE).
  *
  * Adds a Calendar widget to any input with the class 'yui2-calendar'.
@@ -6,7 +6,7 @@
  * fields and behave slightly differently.
 
  * @module Y.lp.app.calendar
- * @requires node
+ * @requires node, calendar, lp.ui.overlay
  */
 
 YUI.add('lp.app.calendar', function(Y) {
@@ -73,7 +73,7 @@
     }
 
     var inner_html = [
-        '<div style="margin-top:1em;text-align:center">Time ',
+        '<div class="yui3-u" style="margin-top:1em;text-align:center">Time ',
         '  <input class="hours" maxlength="2" size="2"',
         '    value="' + pad_with_zero(selected_time.getHours()) +'"/>',
         '  : ',
@@ -89,82 +89,59 @@
 /**
  * Create a calendar widget in a containing div for a given date input.
  *
- * Returns a YAHOO.widget.Calendar rendered into the containing div
- * and linked to the given date input node. The input node will be updated
- * with widget interactions.
+ * Returns a Y.Calendar rendered into the containing div and linked to the
+ * given date input node. The input node will be updated with widget
+ * interactions.
  *
- * @method create_calendar_widget_for_input
+ * @method create_calendar
  * @param date_input_node {Y.Node} the input node with which the widget
  *     is associated.
  * @param containing_div_node {Y.Node} the div within which the calendar
  *     widget is rendered.
  */
-var create_calendar_widget_for_input = function(date_input_node,
-                                                containing_div_node) {
+var create_calendar = function(date_input_node, containing_div_node,
+                               include_time, overlay) {
     var initial_value = get_initial_value_for_input(date_input_node);
 
-    var calendar_widget = new YAHOO.widget.Calendar(
-        "calendar_widget", containing_div_node.get('id'), {
-            title:"Select a date",
-            close:true,
-            pagedate: initial_value,
-            selected: [
-                initial_value.getMonth() + 1,
-                initial_value.getDate(),
-                initial_value.getFullYear()].join("/")
-            });
-
-    // If this widget should also include entering time
-    // then add it in whenever the calendar is rendered.
-    var is_datetime_widget = date_input_node.hasClass('withtime');
-    var time_selector_node = null;
-    if (is_datetime_widget) {
-        calendar_widget.renderEvent.subscribe(function(type, args, obj) {
-            time_selector_node = create_time_selector_node(initial_value);
-            containing_div_node.appendChild(time_selector_node);
-
-            // Ensure that when the ok button is click, the calendar's
-            // selectEvent is fired and the calendar closed.
-            var ok_button = time_selector_node.one('.lazr-btn');
-            Y.on("click", function(e) {
-                calendar_widget.selectEvent.fire();
-                calendar_widget.hide();
-            }, ok_button);
+    var calendar = new Y.Calendar({
+        contentBox: containing_div_node,
+        showPrevMonth: true,
+        showNextMonth: true,
+        width: '300px',
+        date: initial_value}).render();
+
+    if (include_time) {
+        time_selector_node = create_time_selector_node(initial_value);
+        containing_div_node.appendChild(time_selector_node);
+        var ok_button = time_selector_node.one('.lazr-btn');
+        ok_button.on("click", function(e) {
+            var value = calendar._getSelectedDatesList();
+            if (value.length === 0) {
+                return;
+            }
+            calendar.fire('selectionChange', {newSelection: value});
+            calendar.hide();
+            overlay.hide();
         });
     }
 
-    // Handle the (YUI2) calendar select differently for date widgets
-    // and datetime widgets.
-    calendar_widget.selectEvent.subscribe(function(type, args, obj) {
-        // If this is not a datetime widget, we can close it when the
-        // user makes a selection.
-        if (!is_datetime_widget) {
-            calendar_widget.hide();
-        }
-
-        var selected_dates = calendar_widget.getSelectedDates();
-        var selected_date = selected_dates[0];
-
-        var value_string = [
-            selected_date.getFullYear(),
-            pad_with_zero(selected_date.getMonth() + 1),
-            pad_with_zero(selected_date.getDate())
-            ].join("-");
-
-        if (is_datetime_widget) {
+    calendar.on("selectionChange", function(e) {
+        var newDate = Y.Date.format(e.newSelection[0]);
+        if (include_time) {
             hours = pad_with_zero(
                 time_selector_node.one('.hours').get('value'));
             minutes = pad_with_zero(
                 time_selector_node.one('.minutes').get('value'));
-            value_string += " " + hours + ":" + minutes;
-        }
-
-        date_input_node.set('value', value_string);
-    }, calendar_widget, true);
-
-    calendar_widget.render();
-
-    return calendar_widget;
+            newDate += " " + hours + ":" + minutes;
+        }
+        date_input_node.set('value', newDate);
+        if (!include_time) {
+            calendar.hide();
+            overlay.hide();
+        }
+    });
+
+    return calendar;
 };
 
 
@@ -187,7 +164,7 @@
     }
 
     date_inputs.each(function(date_input) {
-        // Fore each date input, insert the Choose... link right after
+        // For each date input, insert the Choose... link right after
         // the date input node.
         // Has the calendar already been added?
         if (date_input.hasClass('calendar-added')) {
@@ -195,39 +172,38 @@
             }
         var parent_node = date_input.ancestor();
         var choose_link = Y.Node.create(
-            '<span>(<a class="js-action" href="#">' +
-            'Choose...</a>)</span>');
+            '<span>(<a class="js-action" href="#">Choose...</a>)</span>');
         parent_node.insertBefore(choose_link, date_input.next());
 
-        // Add a container div for the calendar right after the
-        // choose_link.
-        var containing_div_id = "calendar_container-" +
-            date_input.get('id');
-        var containing_div_node = Y.Node.create(
-            '<div id="' + containing_div_id +
-            '" style="position:absolute"></div>');
-        parent_node.insertBefore(
-            containing_div_node, choose_link.next());
-
-
         // Add a class to flag that this date-input is setup.
         date_input.addClass('calendar-added');
-        // Setup the on click event to display the calendar.
-        var calendar_widget = null;
+        // Setup the on click event to display the overlay.
         Y.on("click", function(e) {
-
-            // Just prevent the default link behaviour to avoid scrolling
-            // to the top of the page.
             e.preventDefault();
-
-            // Create the calendar widget if this is the first time
-            // the link has been clicked.
-            if (calendar_widget === null) {
-                calendar_widget = create_calendar_widget_for_input(
-                    date_input, containing_div_node);
+            var include_time = date_input.hasClass('withtime');
+            var container = Y.Node.create('<div class="yui3-g"></div>');
+            var calendar_div = Y.Node.create('<div></div>');
+            container.prepend(calendar_div);
+            var title = "Choose a date";
+            if (include_time) {
+                title = title + " and time";
             }
-
-            calendar_widget.show();
+            var header = Y.Node.create('<h2>' + title + '</h2>');
+            var overlay = new Y.lp.ui.PrettyOverlay({
+                headerContent: header,
+                bodyContent: container});
+            overlay.centered(choose_link);
+            overlay.render();
+            var calendar = create_calendar(
+                date_input, calendar_div, include_time, overlay);
+            overlay.on('cancel', function(e) {
+                calendar.hide();
+                calendar.destroy();
+                overlay.hide();
+                overlay.destroy();
+            });
+            overlay.show();
+            calendar.show();
         }, choose_link);
     });
 };
@@ -246,8 +222,5 @@
 };
 
 }, "0.1", {
-    'requires': [
-        'node', 'yui2-yahoo', 'yui2-event', 'yui2-dom', 'yui2-calendar',
-        'yui2-dom-event'
-    ]
+    'requires': ['date', 'node', 'calendar', 'lp.ui.overlay']
 });

=== modified file 'lib/lp/app/templates/launchpad-widget-macros.pt'
--- lib/lp/app/templates/launchpad-widget-macros.pt	2012-03-08 14:52:40 +0000
+++ lib/lp/app/templates/launchpad-widget-macros.pt	2013-04-22 05:04:28 +0000
@@ -88,22 +88,19 @@
         Javascript and CSS needed for using the yui2calendar-based
         Date and DateTime widgets.
     </tal:comment>
-    <tal:yui2resources
-      tal:define="yui2 string:${icingroot}/yui_2.7.0b/build;">
-
-      <script type="text/javascript">
-          LPJS.use('lang', 'node', 'lp.app.calendar', function(Y) {
-                  Y.lp.app.calendar.setup_calendar_widgets();
-              }
-          );
-      </script>
-
-      <link rel="stylesheet" type="text/css"
-          tal:attributes="href
-          string:${yui2}/calendar/assets/skins/sam/calendar.css" />
-    </tal:yui2resources>
-
+    <script type="text/javascript">
+        LPJS.use('lang', 'node', 'lp.app.calendar', function(Y) {
+                Y.lp.app.calendar.setup_calendar_widgets();
+            });
+    </script>
+    <link rel="stylesheet" type="text/css"
+        href="/+icing/yui/assets/skins/sam/calendar-base.css" />
+    <link rel="stylesheet" type="text/css"
+        href="/+icing/yui/assets/skins/sam/calendar.css" />
+    <link rel="stylesheet" type="text/css"
+        href="/+icing/yui/assets/skins/sam/calendarnavigator.css" />
+    <link rel="stylesheet" type="text/css"
+        href="/+icing/yui/cssgrids/cssgrids.css" />
 </metal:yui2calendar-dependencies>
 
 </tal:root>
-


Follow ups