This module allows you to select a date and time and then renders a block to show the days, hours, mins and seconds decreasing until the event.

I have created it to allow non technical drupal users the ability to change the countdown labels, numbers and background colours in the block configuration. This allows them to style the block output to suit their existing template design.

The module uses simple javascript to allow it to work with as many browsers as possible

My project page can be found at Countdown event
My git repository is at: git clone http://git.drupal.org/sandbox/octoplod/2106065.git countdown_event

CommentFileSizeAuthor
Countdown_image.PNG2.79 KBoctoplod

Comments

tr33m4n’s picture

Status: Needs review » Needs work

Hello there,

Please fix the problems found by the automated review here http://pareview.sh/pareview/httpgitdrupalorgsandboxoctoplod2106065git , most of which are mainly Drupal coding standard issues.

You also need to move your git branch from master to a version specific one as described here https://drupal.org/empty-git-master

You also need to add a README.txt to your repo describing the module and installation instructions, more information can be found here https://drupal.org/node/161085

Could you also update this page with the drupal.org specific git repository rather than the drupalcode one, eg http://git.drupal.org/sandbox/octoplod/2106065.git

Will do another review once these problems have been fixed :)
Cheers

octoplod’s picture

thank you for reviewing my module, this is my first drupal submission and your comments are greatly appreciated. I will follow your advice and amend my module. cheers !

christianadamski’s picture

Hey,

my thoughts:

* Empty lines at end .module file.
* You have some switch() calls, with only one single "case" each. Maybe a simple if() would suffice? Unless you plan to later extend theses cases of course.
* You add your js file in your .info file. From my understanding, that will add it globally. Maybe use drupal_add_js instead, to only load it where needed? Line 138 seems to indicate you planed to do so? If not, the comment there is unnecessary.
* JavaScript looks fine to me.

octoplod’s picture

Hi, thanks very much for taking the time to look at my module, your comments and advice are greatly appreciated

octoplod’s picture

Hi, I have updated this module addressing the issues identified in the advice given to me and resubmitted it for reviewing

many thanks

octoplod

octoplod’s picture

Status: Needs work » Needs review

change status to needs review...

PA robot’s picture

We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)

Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).

I'm a robot and this is an automated message from Project Applications Scraper.

PA robot’s picture

Issue summary: View changes

updated the link to the git repository

octoplod’s picture

Issue summary: View changes

Update repository link

matrixlord’s picture

Status: Needs review » Needs work

Hello,

You may wish to check here for drupal coding standards related stuff.

I would also suggest you to add default values in countdown_event_block_configure when calling variable_get, because if left blank, the countdown digits are invisible.

I would add the js/css through the module file and not through the info one. Maybe someone would want to add the block on a single page and avoid loading the js/css on every other one. That's my opinion though, you may wish to keep it like this.

octoplod’s picture

Status: Needs work » Needs review

Hi,

thanks for your comments.. i have updated the module to provide default values if none are supplied by the user because as you correctly point out, the digits were initially invisible without them.

Also i have removed the js from the info to a drupal_add_js function in the module

octoplod

vijaycs85’s picture

Oh yeah,I came across few requirement of this module, but never tried to make it as 'module' :). Here is some of my reviews:

1. Still few left to fix at http://pareview.sh/pareview/httpgitdrupalorgsandboxoctoplod2106065git
2. stylesheets[all][] = countdown_event.css - Can't we include this css only on pages where we need it?
3. window.onload = function() { in countdown_event.js may work bit different in drupal modules as behaviour. Have a look at https://drupal.org/node/304258
4. hook_init - Can be removed and including that js file can be part of countdown_event_attach() with drupal_add_js(). it may cause multiple call only when we have multiple blocks on same page. But I guess that's better than having this js in all pages?
5. We may need a .install file with hook_install all variables that we are creating.

Some future thoughts:
1. Currently this module support one counter. However it is doing it in a proper way by altering block configuration and adding it's own content. In future, we can alter the block form to provide an select box say 'Block type' => 'Countdown'. So that we can add any number of countdown blocks. But we can't use variables in that case. We need to have a table for all details.

octoplod’s picture

Status: Needs review » Needs work

hi vijaycs85,

thanks for the reference to #304258: JavaScript API overview that's just the article i needed but couldn't find ! I will update the module accordingly.

I hadn't considered that anyone would try to use more than one countdown block per page but it's worth further thought.

thanks again for your time

octoplod’s picture

Status: Needs work » Needs review

Hi,

Please review my module. In response to the very useful comments in have received, I have modified the module as follows...

I have moved the css from the info file and it is now called from the countdown_event.module.
I have rewritten the javascript to remove the window.onload function and replaced it with drupal.behaviours. The hook_init has also been removed as it is now unnecessary.
I've checked the module against the code sniffer and it hasn't returned any coding issues.

As yet, I don't envisage this module being used more than once per site but in a future update I may allow this.

vijaycs85’s picture

Awesome!!! I will have a look at it again. Thanks for the updates @octoplod.

vijaycs85’s picture

Issue summary: View changes

repository link changed

octoplod’s picture

Issue summary: View changes

tidying page - add 'git clone' to link

R2-D8’s picture

I reviewed this project, but didn't get far...

But first two points we do not need working code for:

(1) I don't see any need for further countdown modules. There are already some existing. But maybe you can provide more information what benefits of your module would offer in comparison.

(2) You should rename the project: Remove the word 'module'. Git cloning links take this name for the module folder what then will break naming convention (functions name not like module name). OR rename all functions (appending '_module').

Ignoring those points, talking about code, I can provide the following hints:

(3) You need an install file ('countdown_event.install'). Insert a custom 'hook_uninstall' function in order to remove variables your module creates.
Additionally you could set messages upon un-/installation.
Here's an example:

<?php

/**
 * @file
 * Install and uninstall functions.
 */

/**
 * Implements hook_install().
 */
function countdown_event_install() {
  // make translations available on un-/install.
  $t = get_t();
  // Set custom status message on installation.
  drupal_set_message($t("'countdown_event' has been succesfully installed."));
}

/**
 * Implements hook_uninstall().
 */
function countdown_event_uninstall() {
  // Delete module variables
  variable_del("countdown_event_date");
  variable_del("countdown_event_label_msg");
  variable_del("countdown_event_label_color");
  variable_del("countdown_event_background_color");
  variable_del("countdown_event_text_color");
  // make translations available on un-/install.
  $t = get_t();
  // Set custom message after uninstallation.
  drupal_set_message($t("'countdown_event' has been succesfully uninstalled."));
}

(4) Then on line 13 in the js file I found the bug preventing the module from running. The closing bracket and semicolon are missing. But then another error appears about an object not being a function.

(5) So I rewrote your JS file according to my script template. Now no errors appear. Here's the whole file:

/**
 * @file
 * This file provides the javascript for the countdown event module
 *
 * Author: Mark Collins
 */
(function($) {
  function countdown_event(context, settings) {
    $(document).ready(function() {

      // event date/time from the countdown module with timezone offset correction
      var countdownDate = (Drupal.settings.countdown_event.countdown_event_date * 1000);
      var labelMsg = (Drupal.settings.countdown_event.countdown_event_label_msg);
      var labelColor = (Drupal.settings.countdown_event.countdown_event_label_color);
      var textColor = (Drupal.settings.countdown_event.countdown_event_text_color);
      var backgroundColor = (Drupal.settings.countdown_event.countdown_event_background_color);

      // set defaults if no user preferences
      if(labelMsg === '' || labelMsg === null){
        labelMsg = 'COUNTDOWN:';
      }
      if(labelColor === '' || labelColor === null){
        labelColor = '#000000';
      }
      if(backgroundColor === ''){
        backgroundColor = '#444444';
      }
      if(textColor === '' || textColor === null){
        textColor = '#fff';
      }

      // add the custom message
      document.getElementById('label_msg').innerHTML = labelMsg;

      // add the custom label color
      var label = document.getElementById('clock_holder');
      label.style.color = labelColor;
      var units = ['countdownDays', 'countdownHrs', 'countdownMins', 'countdownSecs'];

      // add the custom background color and text color
      function customStyle(units, bgColor, txtColor) {
        for (var element in units) {
          var styledDiv = document.getElementById(units[element]);
          styledDiv.style.backgroundColor = bgColor;
          styledDiv.style.color = txtColor;
          //add class style

          //For IE
          styledDiv.setAttribute("class", 'countdownDigitBk');
          //For Most Browsers
          styledDiv.setAttribute("className", 'countdownDigitBk');
        }
      };

      //apply styling by calling function
      customStyle(units, backgroundColor, textColor);
      setInterval(function() {

        // get todays date / time
        var nowDateTime = new Date();

        // ascertain the difference between today the countdown event date / time
        var totalMilSecs = nowDateTime - countdownDate;

        // round the number down and make it positive
        var totalSecs = Math.floor(((totalMilSecs / 1000)) * -1);

        // time units expressed in secs
        var singleDay = 60 * 60 * 24;
        var singleHour = 60 * 60;
        var singleMinute = 60;
        var singleSec = 1;

        // calculte days
        var dayDiffDays = Math.floor(totalSecs / singleDay);

        // calculte hours
        var hourDiffHours = Math.floor((totalSecs / singleHour) - (dayDiffDays * 24));

        // calculte mins
        var minDiffMins = Math.floor((totalSecs / singleMinute) - ((hourDiffHours * 60) + (dayDiffDays * 24 * 60)));

        // calculte secs
        var secDiffSecs = Math.floor((totalSecs / singleSec) - ((minDiffMins * 60) + (hourDiffHours * 60 * 60) + (dayDiffDays * 60 * 60 * 24)));

        // function to add leading zero to tidy display
        var addLeadZero = function (number) {

            return ((number < 10) ? ('0' + number) : number);
        };

        var hourDiffHours = addLeadZero(hourDiffHours);
        var minDiffMins = addLeadZero(minDiffMins);
        var secDiffSecs = addLeadZero(secDiffSecs);

        var nodes = new Array();
        nodes[0] = document.getElementById('countdownDays');
        nodes[1] = document.getElementById('countdownHrs');
        nodes[2] = document.getElementById('countdownMins');
        nodes[3] = document.getElementById('countdownSecs');

        // remove existing countdown if present
        if (nodes[0].firstChild) {
            var removeNode = function (nodeName) {
                nodeName.removeChild(nodeName.childNodes[0]);
            };

            for (i = 0; i < nodes.length; i++) {
                removeNode(nodes[i]);
            }
        } //end if

        // update countdown
        var updateCountdown = function(node, timeUnit, elementId) {

            // add to dom tree
            var textNode = document.createTextNode(timeUnit);
            node.appendChild(textNode);
        };

        updateCountdown(nodes[0], dayDiffDays, 'countdownDays');
        updateCountdown(nodes[1], hourDiffHours, 'countdownHrs');
        updateCountdown(nodes[2], minDiffMins, 'countdownMins');
        updateCountdown(nodes[3], secDiffSecs, 'countdownSecs');

      //repeat every second
      }, 1000);
    });
  }

  Drupal.behaviors.countdown_event = {
    attach: function(context, settings) {
      countdown_event(context, settings);
    }
  }
})(jQuery);

At last some points I was wondering about:

(6) Since the module's block is getting it's data through PHP/JS and not HTML I don't see any problem in caching the block. So I'd alter the cache value in 'countdown_event_block_info()' from 'DRUPAL_NO_CACHE' to 'DRUPAL_CACHE_GLOBAL'.

(7) I don't see why a block title should be driven by variables. It's a fixed value. Also this would be one more variable to think about on unistallation. I didn't take this variable into the install file example.

(8) The default values added lately should be synced across the module file and the javascript file. Maybe it's even better only providing them in the module.

(9) I'm wondering why you are attaching the whole settings array to each data variable in 'countdown_event_attach()'? One of both should be enough: either attaching the array into one variable, or taking each single variable out of the array.

(10) When javascript is disabled the block is still shown. I'd think about whether to add noscript tags or (maybe better) to add the div (at least the visual part) totally by script.

(11) Last but not urgent. You should sync your project page, README.txt and 'hook_help'.

So this was my review, hope this helps you.
I will come back by time and check the progress.
Feel free to contact me if you got questions/ideas.

R2-D8’s picture

Issue summary: View changes
Status: Needs review » Needs work
octoplod’s picture

Hi R2-D8

Thank you for taking the time to review my module.

The reason I created this module was because I needed a countdown timer for a website I was working on (http://80.168.34.25/gear) and those already available didn't suit my requirements.

For example JQuery countdown timer (https://drupal.org/project/jquery_countdown_timer) only goes up to 99 days. Countdown (https://drupal.org/project/countdown) would not work in internet explorer 8.

Above all else, I wanted to create a countdown timer that could be styled by non technical users to fit their own website color scheme without having to change any (css) code. I believe that too many drupal modules are written with developers in mind rather than end users.

Thanks for spotting my javascript error, I accidently removed the ); when I was tidying the code ... oops!

I will look at your other suggestions this week.

thanks again

Octoplod

vijaycs85’s picture

Cool, @octoplod update the related module details that you have mentioned in #16 in your module page (https://drupal.org/sandbox/octoplod/2106065) for future reference(can add a section called 'Similar projects' with details).

octoplod’s picture

Hi vijaycs85,

Thanks, that's a good idea. I will do that tomorrow.

Octoplod

octoplod’s picture

Hi,

I have looked at the points raised by R2-D8 and I have implemented the following changes:

1. I have updated the module to include the install file with the hook_install and hook_uninstall as suggested by R2-D8.

2. I have corrected the js file (added the missing ');' and removed an unnecessary drupal.setting ref so that the javascript runs error free.

3. The DRUPAL_NO_CACHE is now set to DRUPAL_CACHE_GLOBAL.

4. The block title is no longer a variable.

5. I removed the settings array to each data variable in 'countdown_event_attach()' as it was unecessary.

Thanks again to R2-D8 for such a detailed review and helping to improve this module

Octoplod

octoplod’s picture

Hi,

I've updated my project to show how my module differs from similar projects ie -

Similar projects

https://drupal.org/project/jquery_countdown_timer - this modules only goes upto 99 days.

https://drupal.org/project/countdown - this modules countdown only refreshes when the page reloads.

https://drupal.org/project/jquery_countdown - this module doesn't allow for color styling and doesn't work in earlier IE browsers

octoplod’s picture

Status: Needs work » Needs review

Changed Status to needs review

octoplod’s picture

that's strange ... I've updated this project's status to 'needs review' but it shows as 'needs work' in the project list
https://drupal.org/project/issues/projectapplications?text=&status=All&p...

tr33m4n’s picture

Showing as 'needs review' for me. Drupal.org has recently been update to D7 so probably something to do with that, think they're still working out some bugs

octoplod’s picture

Hi,

thanks for looking tr33m4n, it seems that the status shows as 'needs review' in firefox 25 and IE 10 but 'needs work' in chrome Version 30.0.1599.101.
Could you confirm which browser you are using please.

octoplod

tr33m4n’s picture

Chrome version 30.0.1599.114... Try clearing your cache?

R2-D8’s picture

Nice, good progress.

I've reviewed this project and am nearly satisfied.

From the points I've mentioned 10 should be adressed next, as this is fundamentaly in your scenario and could be causing trouble/confusion. The rest is more on the extreme side (optimisation, documentation and so on).

Here some small things I can provide you snippets today:

(12) Provide a config link
In your .info file we could set the configuration link for your block:

configure = admin/structure/block/manage/countdown_event/countdown_event/configure

This way the configuration can be reached directly from the module page (when installed & enabled).

 

(13) Config link in install message
That configuration link could also be part of the recently added installation message:

drupal_set_message($t("'countdown_event' has been successfully installed. You may now <a href=\"/admin/structure/block/manage/custom/main/configure\">configure the countdown event block</a>."));

Now we don't even need to scroll after installation.

 

(14) hook_help() and README.txt
Providing a README.txt file is recommended for many reasons. Syncing this file with hook_help and the project page can be painful. So i recommend you to read the content from README.txt into hook_help:

/**
 * Implements hook_help().
 */
function countdown_event_help($path, $arg) {
  if ($path == 'admin/help#countdown_event') {
    // Return content of the module README.txt.
    return check_markup(file_get_contents(dirname(__FILE__) . "/README.txt"));
  }
}

 


Finally i'd say octoplod has prooven himself as motivated and capable. So I suggest to grant otcopold full project release permissions. But since I'm also not granted yet with that permission I'm not changing the project status yet. Maybe in a few days.
octoplod’s picture

Hi,

10. I have now added noscript tags to the .tpl.php file to display a warning if javascript is not available.

12, 13, 14. Implemented as recommended :-)

Thanks again to R2-D8 for taking the time to review this module. I've been very pleased to implement these recommendations as they are excellent little touches that make this module more user friendly and that always a good thing.
I particularly like 14. I've never thought of doing that before, what a great way of syncing those two files ... pure genius !

Octoplod

octoplod’s picture

Status changed to needs review

perignon’s picture

Status: Needs review » Reviewed & tested by the community

Handy little module. I could see a lot of uses for this. I installed and configured this on a very "heavy" drupal site that has over 100 modules. It installed via Drush with no issues. Looking through the code it was clean and appeared to have all proper formatting and documentation.

I'll be keeping this in my "back pocket" for the future.

kscheirer’s picture

Status: Reviewed & tested by the community » Fixed

No problems found, I agree with R2-D8.

Thanks for your contribution, octoplod!

I updated your account to let you promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and get involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

----
Top Shelf Modules - Crafted, Curated, Contributed.

octoplod’s picture

hi Kscheirer,

thanks for the positive comments and the account update :-)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

octoplod’s picture

Issue summary: View changes