Changeset 113803 in spip-zone


Ignore:
Timestamp:
Feb 7, 2019, 4:55:54 PM (10 days ago)
Author:
root
Message:

report de r113802 (=> https://contrib.spip.net/timecircles-plugin-spip#comment499242 )

Location:
_plugins_/timecircles/branches/v1.5.3
Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/timecircles/branches/v1.5.3/js/timecircles.js

    r112655 r113803  
    11/**
    2         * TimeCircles v1.5.3.15 / SPIP 3.1+
    3         * by Wim Barelds - https://wimbarelds.nl/
    4         * brought to SPIP by Loiseau2nuit (2018)
    5         * https://contrib.spip.net/Loiseau2nuit
    6         * Licence: MIT
    7         *
    8         * Calling functions brought by lib/timecircles.js
    9         * with some little default settings.
    10         * Copy this file in your own '/squelettes/js'
    11         * directory to tweak countdowns & timers
    12         *
    13         * See & tweak for yourself custom examples:
    14         * http://git.wimbarelds.nl/TimeCircles/
    15         **/
    16 jQuery(document).ready(function(){
    17         $(".DateCountdown").TimeCircles();
    18         $(".CountDownTimer").TimeCircles({ time: { Days: { show: false }, Hours: { show: false } }});
    19         $(".PageOpenTimer").TimeCircles();
    20        
    21         var updateTime = function(){
    22                 var date = $("#date").val();
    23                 var time = $("#time").val();
    24                 var datetime = date + ' ' + time + ':00';
    25                 $(".DateCountdown").data('date', datetime).TimeCircles().start();
    26         }
    27         $("#date").change(updateTime).keyup(updateTime);
    28         $("#time").change(updateTime).keyup(updateTime);
    29        
    30         // Start and stop are methods applied on the public TimeCircles instance
    31         $(".startTimer").click(function() {
    32                 $(".CountDownTimer").TimeCircles().start();
    33         });
    34         $(".stopTimer").click(function() {
    35                 $(".CountDownTimer").TimeCircles().stop();
    36         });
    37        
    38         // Fade in and fade out are examples of how chaining can be done with TimeCircles
    39         $(".fadeIn").click(function() {
    40                 $(".PageOpenTimer").fadeIn();
    41         });
    42         $(".fadeOut").click(function() {
    43                 $(".PageOpenTimer").fadeOut();
    44         });
    45 
    46         $(window).on('resize', function(){
    47                 $('.DateCountdown').TimeCircles().rebuild();
    48                 $('.CountDownTimer').TimeCircles().rebuild();
    49                 $('.PageOpenTimer').TimeCircles().rebuild();
    50         });
    51 
    52 });
     2 * Basic structure: TC_Class is the public class that is returned upon being called
     3 *
     4 * So, if you do
     5 *      var tc = $(".timer").TimeCircles();
     6 *     
     7 * tc will contain an instance of the public TimeCircles class. It is important to
     8 * note that TimeCircles is not chained in the conventional way, check the
     9 * documentation for more info on how TimeCircles can be chained.
     10 *
     11 * After being called/created, the public TimerCircles class will then- for each element
     12 * within it's collection, either fetch or create an instance of the private class.
     13 * Each function called upon the public class will be forwarded to each instance
     14 * of the private classes within the relevant element collection
     15 **/
     16(function($) {
     17
     18    var useWindow = window;
     19   
     20    // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
     21    if (!Object.keys) {
     22        Object.keys = (function() {
     23            'use strict';
     24            var hasOwnProperty = Object.prototype.hasOwnProperty,
     25                    hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
     26                    dontEnums = [
     27                        'toString',
     28                        'toLocaleString',
     29                        'valueOf',
     30                        'hasOwnProperty',
     31                        'isPrototypeOf',
     32                        'propertyIsEnumerable',
     33                        'constructor'
     34                    ],
     35                    dontEnumsLength = dontEnums.length;
     36
     37            return function(obj) {
     38                if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
     39                    throw new TypeError('Object.keys called on non-object');
     40                }
     41
     42                var result = [], prop, i;
     43
     44                for (prop in obj) {
     45                    if (hasOwnProperty.call(obj, prop)) {
     46                        result.push(prop);
     47                    }
     48                }
     49
     50                if (hasDontEnumBug) {
     51                    for (i = 0; i < dontEnumsLength; i++) {
     52                        if (hasOwnProperty.call(obj, dontEnums[i])) {
     53                            result.push(dontEnums[i]);
     54                        }
     55                    }
     56                }
     57                return result;
     58            };
     59        }());
     60    }
     61   
     62    // Used to disable some features on IE8
     63    var limited_mode = false;
     64    var tick_duration = 200; // in ms
     65   
     66    var debug = (location.hash === "#debug");
     67    function debug_log(msg) {
     68        if (debug) {
     69            console.log(msg);
     70        }
     71    }
     72
     73    var allUnits = ["Days", "Hours", "Minutes", "Seconds"];
     74    var nextUnits = {
     75        Seconds: "Minutes",
     76        Minutes: "Hours",
     77        Hours: "Days",
     78        Days: "Years"
     79    };
     80    var secondsIn = {
     81        Seconds: 1,
     82        Minutes: 60,
     83        Hours: 3600,
     84        Days: 86400,
     85        Months: 2678400,
     86        Years: 31536000
     87    };
     88
     89    /**
     90     * Converts hex color code into object containing integer values for the r,g,b use
     91     * This function (hexToRgb) originates from:
     92     * http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
     93     * @param {string} hex color code
     94     */
     95    function hexToRgb(hex) {
     96        // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
     97        var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
     98        hex = hex.replace(shorthandRegex, function(m, r, g, b) {
     99            return r + r + g + g + b + b;
     100        });
     101
     102        var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
     103        return result ? {
     104            r: parseInt(result[1], 16),
     105            g: parseInt(result[2], 16),
     106            b: parseInt(result[3], 16)
     107        } : null;
     108    }
     109   
     110    function isCanvasSupported() {
     111        var elem = document.createElement('canvas');
     112        return !!(elem.getContext && elem.getContext('2d'));
     113    }
     114
     115    /**
     116     * Function s4() and guid() originate from:
     117     * http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
     118     */
     119    function s4() {
     120        return Math.floor((1 + Math.random()) * 0x10000)
     121                .toString(16)
     122                .substring(1);
     123    }
     124
     125    /**
     126     * Creates a unique id
     127     * @returns {String}
     128     */
     129    function guid() {
     130        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
     131                s4() + '-' + s4() + s4() + s4();
     132    }
     133
     134    /**
     135     * Array.prototype.indexOf fallback for IE8
     136     * @param {Mixed} mixed
     137     * @returns {Number}
     138     */
     139    if (!Array.prototype.indexOf) {
     140        Array.prototype.indexOf = function(elt /*, from*/)
     141        {
     142            var len = this.length >>> 0;
     143
     144            var from = Number(arguments[1]) || 0;
     145            from = (from < 0)
     146                    ? Math.ceil(from)
     147                    : Math.floor(from);
     148            if (from < 0)
     149                from += len;
     150
     151            for (; from < len; from++)
     152            {
     153                if (from in this &&
     154                        this[from] === elt)
     155                    return from;
     156            }
     157            return -1;
     158        };
     159    }
     160
     161    function parse_date(str) {
     162        var match = str.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{1,2}:[0-9]{2}:[0-9]{2}$/);
     163        if (match !== null && match.length > 0) {
     164            var parts = str.split(" ");
     165            var date = parts[0].split("-");
     166            var time = parts[1].split(":");
     167            return new Date(date[0], date[1] - 1, date[2], time[0], time[1], time[2]);
     168        }
     169        // Fallback for different date formats
     170        var d = Date.parse(str);
     171        if (!isNaN(d))
     172            return d;
     173        d = Date.parse(str.replace(/-/g, '/').replace('T', ' '));
     174        if (!isNaN(d))
     175            return d;
     176        // Cant find anything
     177        return new Date();
     178    }
     179
     180    function parse_times(diff, old_diff, total_duration, units, floor) {
     181        var raw_time = {};
     182        var raw_old_time = {};
     183        var time = {};
     184        var pct = {};
     185        var old_pct = {};
     186        var old_time = {};
     187
     188        var greater_unit = null;
     189        for(var i = 0; i < units.length; i++) {
     190            var unit = units[i];
     191            var maxUnits;
     192
     193            if (greater_unit === null) {
     194                maxUnits = total_duration / secondsIn[unit];
     195            }
     196            else {
     197                maxUnits = secondsIn[greater_unit] / secondsIn[unit];
     198            }
     199
     200            var curUnits = (diff / secondsIn[unit]);
     201            var oldUnits = (old_diff / secondsIn[unit]);
     202           
     203            if(floor) {
     204                if(curUnits > 0) curUnits = Math.floor(curUnits);
     205                else curUnits = Math.ceil(curUnits);
     206                if(oldUnits > 0) oldUnits = Math.floor(oldUnits);
     207                else oldUnits = Math.ceil(oldUnits);
     208            }
     209           
     210            if (unit !== "Days") {
     211                curUnits = curUnits % maxUnits;
     212                oldUnits = oldUnits % maxUnits;
     213            }
     214
     215            raw_time[unit] = curUnits;
     216            time[unit] = Math.abs(curUnits);
     217            raw_old_time[unit] = oldUnits;
     218            old_time[unit] = Math.abs(oldUnits);
     219            pct[unit] = Math.abs(curUnits) / maxUnits;
     220            old_pct[unit] = Math.abs(oldUnits) / maxUnits;
     221
     222            greater_unit = unit;
     223        }
     224
     225        return {
     226            raw_time: raw_time,
     227            raw_old_time: raw_old_time,
     228            time: time,
     229            old_time: old_time,
     230            pct: pct,
     231            old_pct: old_pct
     232        };
     233    }
     234
     235    var TC_Instance_List = {};
     236    function updateUsedWindow() {
     237        if(typeof useWindow.TC_Instance_List !== "undefined") {
     238            TC_Instance_List = useWindow.TC_Instance_List;
     239        }
     240        else {
     241            useWindow.TC_Instance_List = TC_Instance_List;
     242        }
     243        initializeAnimationFrameHandler(useWindow);
     244    };
     245   
     246    function initializeAnimationFrameHandler(w) {
     247        var vendors = ['webkit', 'moz'];
     248        for (var x = 0; x < vendors.length && !w.requestAnimationFrame; ++x) {
     249            w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame'];
     250            w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame'];
     251        }
     252
     253        if (!w.requestAnimationFrame || !w.cancelAnimationFrame) {
     254            w.requestAnimationFrame = function(callback, element, instance) {
     255                if (typeof instance === "undefined")
     256                    instance = {data: {last_frame: 0}};
     257                var currTime = new Date().getTime();
     258                var timeToCall = Math.max(0, 16 - (currTime - instance.data.last_frame));
     259                var id = w.setTimeout(function() {
     260                    callback(currTime + timeToCall);
     261                }, timeToCall);
     262                instance.data.last_frame = currTime + timeToCall;
     263                return id;
     264            };
     265            w.cancelAnimationFrame = function(id) {
     266                clearTimeout(id);
     267            };
     268        }
     269    };
     270   
     271
     272    var TC_Instance = function(element, options) {
     273        this.element = element;
     274        this.container;
     275        this.listeners = null;
     276        this.data = {
     277            paused: false,
     278            last_frame: 0,
     279            animation_frame: null,
     280            interval_fallback: null,
     281            timer: false,
     282            total_duration: null,
     283            prev_time: null,
     284            drawn_units: [],
     285            text_elements: {
     286                Days: null,
     287                Hours: null,
     288                Minutes: null,
     289                Seconds: null
     290            },
     291            attributes: {
     292                canvas: null,
     293                context: null,
     294                item_size: null,
     295                line_width: null,
     296                radius: null,
     297                outer_radius: null
     298            },
     299            state: {
     300                fading: {
     301                    Days: false,
     302                    Hours: false,
     303                    Minutes: false,
     304                    Seconds: false
     305                }
     306            }
     307        };
     308
     309        this.config = null;
     310        this.setOptions(options);
     311        this.initialize();
     312    };
     313
     314    TC_Instance.prototype.clearListeners = function() {
     315        this.listeners = { all: [], visible: [] };
     316    };
     317   
     318    TC_Instance.prototype.addTime = function(seconds_to_add) {
     319        if(this.data.attributes.ref_date instanceof Date) {
     320            var d = this.data.attributes.ref_date;
     321            d.setSeconds(d.getSeconds() + seconds_to_add);
     322        }
     323        else if(!isNaN(this.data.attributes.ref_date)) {
     324            this.data.attributes.ref_date += (seconds_to_add * 1000);
     325        }
     326    };
     327   
     328    TC_Instance.prototype.initialize = function(clear_listeners) {
     329        // Initialize drawn units
     330        this.data.drawn_units = [];
     331        for(var i = 0; i < Object.keys(this.config.time).length; i++) {
     332            var unit = Object.keys(this.config.time)[i];
     333            if (this.config.time[unit].show) {
     334                this.data.drawn_units.push(unit);
     335            }
     336        }
     337
     338        // Avoid stacking
     339        $(this.element).children('div.time_circles').remove();
     340
     341        if (typeof clear_listeners === "undefined")
     342            clear_listeners = true;
     343        if (clear_listeners || this.listeners === null) {
     344            this.clearListeners();
     345        }
     346        this.container = $("<div>");
     347        this.container.addClass('time_circles');
     348        this.container.appendTo(this.element);
     349       
     350        // Determine the needed width and height of TimeCircles
     351        var height = this.element.offsetHeight;
     352        var width = this.element.offsetWidth;
     353        if (height === 0)
     354            height = $(this.element).height();
     355        if (width === 0)
     356            width = $(this.element).width();
     357
     358        if (height === 0 && width > 0)
     359            height = width / this.data.drawn_units.length;
     360        else if (width === 0 && height > 0)
     361            width = height * this.data.drawn_units.length;
     362       
     363        // Create our canvas and set it to the appropriate size
     364        var canvasElement = document.createElement('canvas');
     365        canvasElement.width = width;
     366        canvasElement.height = height;
     367       
     368        // Add canvas elements
     369        this.data.attributes.canvas = $(canvasElement);
     370        this.data.attributes.canvas.appendTo(this.container);
     371       
     372        // Check if the browser has browser support
     373        var canvasSupported = isCanvasSupported();
     374        // If the browser doesn't have browser support, check if explorer canvas is loaded
     375        // (A javascript library that adds canvas support to browsers that don't have it)
     376        if(!canvasSupported && typeof G_vmlCanvasManager !== "undefined") {
     377            G_vmlCanvasManager.initElement(canvasElement);
     378            limited_mode = true;
     379            canvasSupported = true;
     380        }
     381        if(canvasSupported) {
     382            this.data.attributes.context = canvasElement.getContext('2d');
     383        }
     384
     385        this.data.attributes.item_size = Math.min(width / this.data.drawn_units.length, height);
     386        this.data.attributes.line_width = this.data.attributes.item_size * this.config.fg_width;
     387        this.data.attributes.radius = ((this.data.attributes.item_size * 0.8) - this.data.attributes.line_width) / 2;
     388        this.data.attributes.outer_radius = this.data.attributes.radius + 0.5 * Math.max(this.data.attributes.line_width, this.data.attributes.line_width * this.config.bg_width);
     389
     390        // Prepare Time Elements
     391        var i = 0;
     392        for (var key in this.data.text_elements) {
     393            if (!this.config.time[key].show)
     394                continue;
     395
     396            var textElement = $("<div>");
     397            textElement.addClass('textDiv_' + key);
     398            textElement.css("top", Math.round(0.35 * this.data.attributes.item_size));
     399            textElement.css("left", Math.round(i++ * this.data.attributes.item_size));
     400            textElement.css("width", this.data.attributes.item_size);
     401            textElement.appendTo(this.container);
     402
     403            var headerElement = $("<h4>");
     404            headerElement.text(this.config.time[key].text); // Options
     405            headerElement.css("font-size", Math.round(this.config.text_size * this.data.attributes.item_size));
     406            headerElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px");
     407            headerElement.appendTo(textElement);
     408
     409            var numberElement = $("<span>");
     410            numberElement.css("font-size", Math.round(3 * this.config.text_size * this.data.attributes.item_size));
     411            numberElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px");
     412            numberElement.appendTo(textElement);
     413
     414            this.data.text_elements[key] = numberElement;
     415        }
     416
     417        this.start();
     418        if (!this.config.start) {
     419            this.data.paused = true;
     420        }
     421       
     422        // Set up interval fallback
     423        var _this = this;
     424        this.data.interval_fallback = useWindow.setInterval(function(){
     425            _this.update.call(_this, true);
     426        }, 100);
     427    };
     428
     429    TC_Instance.prototype.update = function(nodraw) {
     430        if(typeof nodraw === "undefined") {
     431            nodraw = false;
     432        }
     433        else if(nodraw && this.data.paused) {
     434            return;
     435        }
     436       
     437        if(limited_mode) {
     438            //Per unit clearing doesn't work in IE8 using explorer canvas, so do it in one time. The downside is that radial fade cant be used
     439            this.data.attributes.context.clearRect(0, 0, this.data.attributes.canvas[0].width, this.data.attributes.canvas[0].hright);
     440        }
     441        var diff, old_diff;
     442
     443        var prevDate = this.data.prev_time;
     444        var curDate = new Date();
     445        this.data.prev_time = curDate;
     446
     447        if (prevDate === null)
     448            prevDate = curDate;
     449
     450        // If not counting past zero, and time < 0, then simply draw the zero point once, and call stop
     451        if (!this.config.count_past_zero) {
     452            if (curDate > this.data.attributes.ref_date) {
     453                for(var i = 0; i < this.data.drawn_units.length; i++) {
     454                    var key = this.data.drawn_units[i];
     455
     456                    // Set the text value
     457                    this.data.text_elements[key].text("0");
     458                    var x = (i * this.data.attributes.item_size) + (this.data.attributes.item_size / 2);
     459                    var y = this.data.attributes.item_size / 2;
     460                    var color = this.config.time[key].color;
     461                    this.drawArc(x, y, color, 0);
     462                }
     463                this.stop();
     464                return;
     465            }
     466        }
     467
     468        // Compare current time with reference
     469        diff = (this.data.attributes.ref_date - curDate) / 1000;
     470        old_diff = (this.data.attributes.ref_date - prevDate) / 1000;
     471
     472        var floor = this.config.animation !== "smooth";
     473
     474        var visible_times = parse_times(diff, old_diff, this.data.total_duration, this.data.drawn_units, floor);
     475        var all_times = parse_times(diff, old_diff, secondsIn["Years"], allUnits, floor);
     476
     477        var i = 0;
     478        var j = 0;
     479        var lastKey = null;
     480
     481        var cur_shown = this.data.drawn_units.slice();
     482        for (var i in allUnits) {
     483            var key = allUnits[i];
     484
     485            // Notify (all) listeners
     486            if (Math.floor(all_times.raw_time[key]) !== Math.floor(all_times.raw_old_time[key])) {
     487                this.notifyListeners(key, Math.floor(all_times.time[key]), Math.floor(diff), "all");
     488            }
     489
     490            if (cur_shown.indexOf(key) < 0)
     491                continue;
     492
     493            // Notify (visible) listeners
     494            if (Math.floor(visible_times.raw_time[key]) !== Math.floor(visible_times.raw_old_time[key])) {
     495                this.notifyListeners(key, Math.floor(visible_times.time[key]), Math.floor(diff), "visible");
     496            }
     497           
     498            if(!nodraw) {
     499                // Set the text value
     500                this.data.text_elements[key].text(Math.floor(Math.abs(visible_times.time[key])));
     501
     502                var x = (j * this.data.attributes.item_size) + (this.data.attributes.item_size / 2);
     503                var y = this.data.attributes.item_size / 2;
     504                var color = this.config.time[key].color;
     505
     506                if (this.config.animation === "smooth") {
     507                    if (lastKey !== null && !limited_mode) {
     508                        if (Math.floor(visible_times.time[lastKey]) > Math.floor(visible_times.old_time[lastKey])) {
     509                            this.radialFade(x, y, color, 1, key);
     510                            this.data.state.fading[key] = true;
     511                        }
     512                        else if (Math.floor(visible_times.time[lastKey]) < Math.floor(visible_times.old_time[lastKey])) {
     513                            this.radialFade(x, y, color, 0, key);
     514                            this.data.state.fading[key] = true;
     515                        }
     516                    }
     517                    if (!this.data.state.fading[key]) {
     518                        this.drawArc(x, y, color, visible_times.pct[key]);
     519                    }
     520                }
     521                else {
     522                    this.animateArc(x, y, color, visible_times.pct[key], visible_times.old_pct[key], (new Date()).getTime() + tick_duration);
     523                }
     524            }
     525            lastKey = key;
     526            j++;
     527        }
     528
     529        // Dont request another update if we should be paused
     530        if(this.data.paused || nodraw) {
     531            return;
     532        }
     533       
     534        // We need this for our next frame either way
     535        var _this = this;
     536        var update = function() {
     537            _this.update.call(_this);
     538        };
     539
     540        // Either call next update immediately, or in a second
     541        if (this.config.animation === "smooth") {
     542            // Smooth animation, Queue up the next frame
     543            this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);
     544        }
     545        else {
     546            // Tick animation, Don't queue until very slightly after the next second happens
     547            var delay = (diff % 1) * 1000;
     548            if (delay < 0)
     549                delay = 1000 + delay;
     550            delay += 50;
     551
     552            _this.data.animation_frame = useWindow.setTimeout(function() {
     553                _this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this);
     554            }, delay);
     555        }
     556    };
     557
     558    TC_Instance.prototype.animateArc = function(x, y, color, target_pct, cur_pct, animation_end) {
     559        if (this.data.attributes.context === null)
     560            return;
     561
     562        var diff = cur_pct - target_pct;
     563        if (Math.abs(diff) > 0.5) {
     564            if (target_pct === 0) {
     565                this.radialFade(x, y, color, 1);
     566            }
     567            else {
     568                this.radialFade(x, y, color, 0);
     569            }
     570        }
     571        else {
     572            var progress = (tick_duration - (animation_end - (new Date()).getTime())) / tick_duration;
     573            if (progress > 1)
     574                progress = 1;
     575
     576            var pct = (cur_pct * (1 - progress)) + (target_pct * progress);
     577            this.drawArc(x, y, color, pct);
     578
     579            //var show_pct =
     580            if (progress >= 1)
     581                return;
     582            var _this = this;
     583            useWindow.requestAnimationFrame(function() {
     584                _this.animateArc(x, y, color, target_pct, cur_pct, animation_end);
     585            }, this.element);
     586        }
     587    };
     588
     589    TC_Instance.prototype.drawArc = function(x, y, color, pct) {
     590        if (this.data.attributes.context === null)
     591            return;
     592
     593        var clear_radius = Math.max(this.data.attributes.outer_radius, this.data.attributes.item_size / 2);
     594        if(!limited_mode) {
     595            this.data.attributes.context.clearRect(
     596                    x - clear_radius,
     597                    y - clear_radius,
     598                    clear_radius * 2,
     599                    clear_radius * 2
     600                    );
     601        }
     602       
     603        if (this.config.use_background) {
     604            this.data.attributes.context.beginPath();
     605            this.data.attributes.context.arc(x, y, this.data.attributes.radius, 0, 2 * Math.PI, false);
     606            this.data.attributes.context.lineWidth = this.data.attributes.line_width * this.config.bg_width;
     607
     608            // line color
     609            this.data.attributes.context.strokeStyle = this.config.circle_bg_color;
     610            this.data.attributes.context.stroke();
     611        }
     612
     613        // Direction
     614        var startAngle, endAngle, counterClockwise;
     615        var defaultOffset = (-0.5 * Math.PI);
     616        var fullCircle = 2 * Math.PI;
     617        startAngle = defaultOffset + (this.config.start_angle / 360 * fullCircle);
     618        var offset = (2 * pct * Math.PI);
     619
     620        if (this.config.direction === "Both") {
     621            counterClockwise = false;
     622            startAngle -= (offset / 2);
     623            endAngle = startAngle + offset;
     624        }
     625        else {
     626            if (this.config.direction === "Clockwise") {
     627                counterClockwise = false;
     628                endAngle = startAngle + offset;
     629            }
     630            else {
     631                counterClockwise = true;
     632                endAngle = startAngle - offset;
     633            }
     634        }
     635
     636        this.data.attributes.context.beginPath();
     637        this.data.attributes.context.arc(x, y, this.data.attributes.radius, startAngle, endAngle, counterClockwise);
     638        this.data.attributes.context.lineWidth = this.data.attributes.line_width;
     639
     640        // line color
     641        this.data.attributes.context.strokeStyle = color;
     642        this.data.attributes.context.stroke();
     643    };
     644
     645    TC_Instance.prototype.radialFade = function(x, y, color, from, key) {
     646        // TODO: Make fade_time option
     647        var rgb = hexToRgb(color);
     648        var _this = this; // We have a few inner scopes here that will need access to our instance
     649
     650        var step = 0.2 * ((from === 1) ? -1 : 1);
     651        var i;
     652        for (i = 0; from <= 1 && from >= 0; i++) {
     653            // Create inner scope so our variables are not changed by the time the Timeout triggers
     654            (function() {
     655                var delay = 50 * i;
     656                var rgba = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + (Math.round(from * 10) / 10) + ")";
     657                useWindow.setTimeout(function() {
     658                    _this.drawArc(x, y, rgba, 1);
     659                }, delay);
     660            }());
     661            from += step;
     662        }
     663        if (typeof key !== undefined) {
     664            useWindow.setTimeout(function() {
     665                _this.data.state.fading[key] = false;
     666            }, 50 * i);
     667        }
     668    };
     669
     670    TC_Instance.prototype.timeLeft = function() {
     671        if (this.data.paused && typeof this.data.timer === "number") {
     672            return this.data.timer;
     673        }
     674        var now = new Date();
     675        return ((this.data.attributes.ref_date - now) / 1000);
     676    };
     677
     678    TC_Instance.prototype.start = function() {
     679        useWindow.cancelAnimationFrame(this.data.animation_frame);
     680        useWindow.clearTimeout(this.data.animation_frame)
     681
     682        // Check if a date was passed in html attribute or jquery data
     683        var attr_data_date = $(this.element).data('date');
     684        if (typeof attr_data_date === "undefined") {
     685            attr_data_date = $(this.element).attr('data-date');
     686        }
     687        if (typeof attr_data_date === "string") {
     688            this.data.attributes.ref_date = parse_date(attr_data_date);
     689        }
     690        // Check if this is an unpause of a timer
     691        else if (typeof this.data.timer === "number") {
     692            if (this.data.paused) {
     693                this.data.attributes.ref_date = (new Date()).getTime() + (this.data.timer * 1000);
     694            }
     695        }
     696        else {
     697            // Try to get data-timer
     698            var attr_data_timer = $(this.element).data('timer');
     699            if (typeof attr_data_timer === "undefined") {
     700                attr_data_timer = $(this.element).attr('data-timer');
     701            }
     702            if (typeof attr_data_timer === "string") {
     703                attr_data_timer = parseFloat(attr_data_timer);
     704            }
     705            if (typeof attr_data_timer === "number") {
     706                this.data.timer = attr_data_timer;
     707                this.data.attributes.ref_date = (new Date()).getTime() + (attr_data_timer * 1000);
     708            }
     709            else {
     710                // data-timer and data-date were both not set
     711                // use config date
     712                this.data.attributes.ref_date = this.config.ref_date;
     713            }
     714        }
     715
     716        // Start running
     717        this.data.paused = false;
     718        this.update.call(this);
     719    };
     720
     721    TC_Instance.prototype.restart = function() {
     722        this.data.timer = false;
     723        this.start();
     724    };
     725
     726    TC_Instance.prototype.stop = function() {
     727        if (typeof this.data.timer === "number") {
     728            this.data.timer = this.timeLeft(this);
     729        }
     730        // Stop running
     731        this.data.paused = true;
     732        useWindow.cancelAnimationFrame(this.data.animation_frame);
     733    };
     734
     735    TC_Instance.prototype.destroy = function() {
     736        this.clearListeners();
     737        this.stop();
     738        useWindow.clearInterval(this.data.interval_fallback);
     739        this.data.interval_fallback = null;
     740       
     741        this.container.remove();
     742        $(this.element).removeAttr('data-tc-id');
     743        $(this.element).removeData('tc-id');
     744    };
     745
     746    TC_Instance.prototype.setOptions = function(options) {
     747        if (this.config === null) {
     748            this.default_options.ref_date = new Date();
     749            this.config = $.extend(true, {}, this.default_options);
     750        }
     751        $.extend(true, this.config, options);
     752
     753        // Use window.top if use_top_frame is true
     754        if(this.config.use_top_frame) {
     755            useWindow = window.top;
     756        }
     757        else {
     758            useWindow = window;
     759        }
     760        updateUsedWindow();
     761       
     762        this.data.total_duration = this.config.total_duration;
     763        if (typeof this.data.total_duration === "string") {
     764            if (typeof secondsIn[this.data.total_duration] !== "undefined") {
     765                // If set to Years, Months, Days, Hours or Minutes, fetch the secondsIn value for that
     766                this.data.total_duration = secondsIn[this.data.total_duration];
     767            }
     768            else if (this.data.total_duration === "Auto") {
     769                // If set to auto, total_duration is the size of 1 unit, of the unit type bigger than the largest shown
     770                for(var i = 0; i < Object.keys(this.config.time).length; i++) {
     771                    var unit = Object.keys(this.config.time)[i];
     772                    if (this.config.time[unit].show) {
     773                        this.data.total_duration = secondsIn[nextUnits[unit]];
     774                        break;
     775                    }
     776                }
     777            }
     778            else {
     779                // If it's a string, but neither of the above, user screwed up.
     780                this.data.total_duration = secondsIn["Years"];
     781                console.error("Valid values for TimeCircles config.total_duration are either numeric, or (string) Years, Months, Days, Hours, Minutes, Auto");
     782            }
     783        }
     784    };
     785
     786    TC_Instance.prototype.addListener = function(f, context, type) {
     787        if (typeof f !== "function")
     788            return;
     789        if (typeof type === "undefined")
     790            type = "visible";
     791        this.listeners[type].push({func: f, scope: context});
     792    };
     793
     794    TC_Instance.prototype.notifyListeners = function(unit, value, total, type) {
     795        for (var i = 0; i < this.listeners[type].length; i++) {
     796            var listener = this.listeners[type][i];
     797            listener.func.apply(listener.scope, [unit, value, total]);
     798        }
     799    };
     800
     801    TC_Instance.prototype.default_options = {
     802        ref_date: new Date(),
     803        start: true,
     804        animation: "smooth",
     805        count_past_zero: true,
     806        circle_bg_color: "#60686F",
     807        use_background: true,
     808        fg_width: 0.1,
     809        bg_width: 1.2,
     810        text_size: 0.07,
     811        total_duration: "Auto",
     812        direction: "Clockwise",
     813        use_top_frame: false,
     814        start_angle: 0,
     815        time: {
     816            Days: {
     817                show: true,
     818                text: "Days",
     819                color: "#FC6"
     820            },
     821            Hours: {
     822                show: true,
     823                text: "Hours",
     824                color: "#9CF"
     825            },
     826            Minutes: {
     827                show: true,
     828                text: "Minutes",
     829                color: "#BFB"
     830            },
     831            Seconds: {
     832                show: true,
     833                text: "Seconds",
     834                color: "#F99"
     835            }
     836        }
     837    };
     838
     839    // Time circle class
     840    var TC_Class = function(elements, options) {
     841        this.elements = elements;
     842        this.options = options;
     843        this.foreach();
     844    };
     845
     846    TC_Class.prototype.getInstance = function(element) {
     847        var instance;
     848
     849        var cur_id = $(element).data("tc-id");
     850        if (typeof cur_id === "undefined") {
     851            cur_id = guid();
     852            $(element).attr("data-tc-id", cur_id);
     853        }
     854        if (typeof TC_Instance_List[cur_id] === "undefined") {
     855            var options = this.options;
     856            var element_options = $(element).data('options');
     857            if (typeof element_options === "string") {
     858                element_options = JSON.parse(element_options);
     859            }
     860            if (typeof element_options === "object") {
     861                options = $.extend(true, {}, this.options, element_options);
     862            }
     863            instance = new TC_Instance(element, options);
     864            TC_Instance_List[cur_id] = instance;
     865        }
     866        else {
     867            instance = TC_Instance_List[cur_id];
     868            if (typeof this.options !== "undefined") {
     869                instance.setOptions(this.options);
     870            }
     871        }
     872        return instance;
     873    };
     874
     875    TC_Class.prototype.addTime = function(seconds_to_add) {
     876        this.foreach(function(instance) {
     877            instance.addTime(seconds_to_add);
     878        });
     879    };
     880   
     881    TC_Class.prototype.foreach = function(callback) {
     882        var _this = this;
     883        this.elements.each(function() {
     884            var instance = _this.getInstance(this);
     885            if (typeof callback === "function") {
     886                callback(instance);
     887            }
     888        });
     889        return this;
     890    };
     891
     892    TC_Class.prototype.start = function() {
     893        this.foreach(function(instance) {
     894            instance.start();
     895        });
     896        return this;
     897    };
     898
     899    TC_Class.prototype.stop = function() {
     900        this.foreach(function(instance) {
     901            instance.stop();
     902        });
     903        return this;
     904    };
     905
     906    TC_Class.prototype.restart = function() {
     907        this.foreach(function(instance) {
     908            instance.restart();
     909        });
     910        return this;
     911    };
     912
     913    TC_Class.prototype.rebuild = function() {
     914        this.foreach(function(instance) {
     915            instance.initialize(false);
     916        });
     917        return this;
     918    };
     919
     920    TC_Class.prototype.getTime = function() {
     921        return this.getInstance(this.elements[0]).timeLeft();
     922    };
     923
     924    TC_Class.prototype.addListener = function(f, type) {
     925        if (typeof type === "undefined")
     926            type = "visible";
     927        var _this = this;
     928        this.foreach(function(instance) {
     929            instance.addListener(f, _this.elements, type);
     930        });
     931        return this;
     932    };
     933
     934    TC_Class.prototype.destroy = function() {
     935        this.foreach(function(instance) {
     936            instance.destroy();
     937        });
     938        return this;
     939    };
     940
     941    TC_Class.prototype.end = function() {
     942        return this.elements;
     943    };
     944
     945    $.fn.TimeCircles = function(options) {
     946        return new TC_Class(this, options);
     947    };
     948}(jQuery));
  • _plugins_/timecircles/branches/v1.5.3/paquet.xml

    r112669 r113803  
    22        prefix="timecircles"
    33        categorie="squelette"
    4         version="1.5.3.22"
     4        version="1.5.3.23"
    55        etat="test"
    66        compatibilite="[3.1.0;3.3.*]"
  • _plugins_/timecircles/branches/v1.5.3/timecircles_pipelines.php

    r112669 r113803  
    3333 **/
    3434function timecircles_insert_head($flux){
    35         $flux .= '<script src="'.generer_url_public('lib/timecircles.js').'" type="text/javascript"></script>'
    36         . '<script src="'.find_in_path('js/timecircles.js').'" type="text/javascript"></script>';
     35        $flux .= '<script src="'.find_in_path('js/timecircles.js').'" type="text/javascript"></script>'
     36        .<<<EOF
     37<script type="text/javascript">
     38<!--
     39jQuery(document).ready(function(){
     40        $(".DateCountdown").TimeCircles();
     41        $(".CountDownTimer").TimeCircles({ time: { Days: { show: false }, Hours: { show: false } }});
     42        $(".PageOpenTimer").TimeCircles();
     43        var updateTime = function(){
     44                var date = $("#date").val();
     45                var time = $("#time").val();
     46                var datetime = date + ' ' + time + ':00';
     47                $(".DateCountdown").data('date', datetime).TimeCircles().start();
     48        }
     49        $("#date").change(updateTime).keyup(updateTime);
     50        $("#time").change(updateTime).keyup(updateTime);
     51        /* Start and stop are methods applied on the public TimeCircles instance */
     52        $(".startTimer").click(function() {
     53                $(".CountDownTimer").TimeCircles().start();
     54        });
     55        $(".stopTimer").click(function() {
     56                $(".CountDownTimer").TimeCircles().stop();
     57        });
     58        /* Fade in and fade out are examples of how chaining can be done with TimeCircles */
     59        $(".fadeIn").click(function() {
     60                $(".PageOpenTimer").fadeIn();
     61        });
     62        $(".fadeOut").click(function() {
     63                $(".PageOpenTimer").fadeOut();
     64        });
     65        $(window).on('resize', function(){
     66    $('.DateCountdown').TimeCircles().rebuild();
     67                $('.CountDownTimer').TimeCircles().rebuild();
     68                $('.PageOpenTimer').TimeCircles().rebuild();
     69        });
     70});
     71-->             
     72</script>
     73EOF;
     74
    3775        return $flux;
    3876}
Note: See TracChangeset for help on using the changeset viewer.