mpuria mpuria - 12 days ago 5
CSS Question

Fill css progressbar value/width when reaching a set time/date

I am trying to make a css progress bar whose width would be defined by a date and time.

The purpose is to create a progress bar when reaching a specific predefined date and time set.

For Example: The Progressbar reaches 100% when the date is December 25, 2014.
The calculation method i think should be: [(date&time_defined) - (date&time_today)] = Value of the width percentage, so when [(date&time_defined)==(date&time_today)] width percentage should be 100%.

This is the progressbar css code that i use

<html>
<body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script>
$(function() {
$(".meter > span").each(function() {
$(this)
.data("origWidth", $(this).width())
.width(0)
.animate({
width: $(this).data("origWidth")
}, 1200);
});
});
</script>

<style>
.meter {
height: 20px; /* Can be anything */
position: relative;
margin: 60px 0 20px 0; /* Just for demo spacing */
background: #555;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
border-radius: 25px;
padding: 10px;
-webkit-box-shadow: inset 0 -1px 1px rgba(255,255,255,0.3);
-moz-box-shadow : inset 0 -1px 1px rgba(255,255,255,0.3);
box-shadow : inset 0 -1px 1px rgba(255,255,255,0.3);
}
.meter > span {
display: block;
height: 100%;
-webkit-border-top-right-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
-moz-border-radius-topright: 8px;
-moz-border-radius-bottomright: 8px;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
-webkit-border-top-left-radius: 20px;
-webkit-border-bottom-left-radius: 20px;
-moz-border-radius-topleft: 20px;
-moz-border-radius-bottomleft: 20px;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
background-color: rgb(43,194,83);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0, rgb(43,194,83)),
color-stop(1, rgb(84,240,84))
);
background-image: -moz-linear-gradient(
center bottom,
rgb(43,194,83) 37%,
rgb(84,240,84) 69%
);
-webkit-box-shadow:
inset 0 2px 9px rgba(255,255,255,0.3),
inset 0 -2px 6px rgba(0,0,0,0.4);
-moz-box-shadow:
inset 0 2px 9px rgba(255,255,255,0.3),
inset 0 -2px 6px rgba(0,0,0,0.4);
box-shadow:
inset 0 2px 9px rgba(255,255,255,0.3),
inset 0 -2px 6px rgba(0,0,0,0.4);
position: relative;
overflow: hidden;
}
.meter > span:after, .animate > span > span {
content: "";
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
background-image:
-webkit-gradient(linear, 0 0, 100% 100%,
color-stop(.25, rgba(255, 255, 255, .2)),
color-stop(.25, transparent), color-stop(.5, transparent),
color-stop(.5, rgba(255, 255, 255, .2)),
color-stop(.75, rgba(255, 255, 255, .2)),
color-stop(.75, transparent), to(transparent)
);
background-image:
-moz-linear-gradient(
-45deg,
rgba(255, 255, 255, .2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, .2) 50%,
rgba(255, 255, 255, .2) 75%,
transparent 75%,
transparent
);
z-index: 1;
-webkit-background-size: 50px 50px;
-moz-background-size: 50px 50px;
-webkit-animation: move 2s linear infinite;
-webkit-border-top-right-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
-moz-border-radius-topright: 8px;
-moz-border-radius-bottomright: 8px;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
-webkit-border-top-left-radius: 20px;
-webkit-border-bottom-left-radius: 20px;
-moz-border-radius-topleft: 20px;
-moz-border-radius-bottomleft: 20px;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
overflow: hidden;
}

.animate > span:after {
display: none;
}

@-webkit-keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: 50px 50px;
}
}

.orange > span {
background-color: #f1a165;
background-image: -moz-linear-gradient(top, #f1a165, #f36d0a);
background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f1a165),color-stop(1, #f36d0a));
background-image: -webkit-linear-gradient(#f1a165, #f36d0a);
}

.red > span {
background-color: #f0a3a3;
background-image: -moz-linear-gradient(top, #f0a3a3, #f42323);
background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f0a3a3),color-stop(1, #f42323));
background-image: -webkit-linear-gradient(#f0a3a3, #f42323);
}

.nostripes > span > span, .nostripes > span:after {
-webkit-animation: none;
background-image: none;
}
</style>


<div class="meter">
<span style="width: PERCENTAGE%"></span>
</div>
</body>
</html>


If possible do show me the needed code to use inside the above code because I'm not familiar much with CSS and javascript or whatsoever. I'm just trying to start :)

EDIT: I just need a modification to the code above so it would work when i insert a date $ time(e.g. december, 25, 2014 14:08) into wherever provided.. instead of a fixed width

Answer

You need a valid way to convert the dates into numbers (the easiest way is to use milliseconds). You also need a reference point to use for calculations (let's use the start of the year).

Once you have these things, the formula is straightforward. Here is the pseudo code:

(difference of current from start date / difference of final date from start date) * 100

In JS:

var targetDate = new Date("12/25/2014");
var beginDate = new Date("01/01/2014");
var totalTime = (targetDate - beginDate);
var dateProgress = new Date(data.Date) - beginDate;
var completionPercentage = (Math.round((dateProgress / totalTime) * 100));

Then it becomes a matter of code structure. I like to use custom events in JQuery to keep the code DRY so below is how I solved it:

var targetDate = new Date("12/25/2014");
var beginDate = new Date("01/01/2014");
var totalTime = (targetDate - beginDate);
$(function () {

    //Create a custom event on the span to handle incoming data for animation.
    $(".meter > span").bind("progress-event", function (e, data) {
        $(this)
            .width($(this).prop("width"))
            .data("origWidth", data.Complete)
            .animate({
            width: $(this).data("origWidth") + "%"
        }, 1200);
        $(this).prop("title",($(this).data("origWidth") + "%"));
    });
    //Initial animation on page load.
    $(".meter > span").each(function () {
        $(document).trigger("date-changed", {
            Date: new Date() // today's date
        });
    });

    //Apply the datepicker with an event handler for a selected date
    $("#date-input").datepicker({
        onSelect: function (selectedDate, obj) {
            $(document).trigger("date-changed", {
                Date: selectedDate
            });
        } // end onSelect function
    });
});

//Custom event to handle a date being picked from the datepicker
$(document).bind("date-changed", function (e, data) {
    var dateProgress = new Date(data.Date) - beginDate;
    var completionPercentage = (Math.round((dateProgress / totalTime) * 100));
    if(completionPercentage > 100) {  //Make sure we don't go past 100
        completionPercentage = 100;
    } // end if
    $(".meter > span").trigger("progress-event", {
        Date: data.Date,
        Complete: completionPercentage
    });
});

Here, I have created two custom events: date-changed and progress-event. The date-changed event I have for demo purposes and is triggered when a date is selected from the date picker on the text box. This feeds the "selected" date to the progress-event after performing some calculations. The responsibility of the progress-event is simply to populate the data of and animate the progress bar.

The important part is in the $(document).trigger(...... sections where I give the name of the event I've triggered, and I build a JavaScript object that contains the data each method needs (in your case, a date object).

Here is a JsFiddle: http://jsfiddle.net/xDaevax/pzgxuoj9/

Notice that I used JQuery UI, and a newer version of JQuery than you. JQuery UI is not necessary (unless you want to use that for picking dates) and this code should work with your version of JQuery (you may have to substitute where I used the prop method with calls to attr). Also important to note is that I put this code in the HEAD section of the HTML, not the body.

Comments