<commit_before>(function($){
    $.fn.socialfeed = function(options)
    {
        var defaults = {
            plugin_folder: '', // a folder in which the plugin is located (with a slash in the end)
            // VK.com
            vk_limit: 3, // amount of vkontakte posts to show
            //vk_username: "vk_username", // ID of a VK page which stream will be shown
            // Twitter.com
            tw_limit: 3, // amount of twitter posts to show
            //tw_username: "tw_username", // ID of a twitter page which stream will be shown
            // Facebook.com
            fb_limit: 3, // amount of facebook posts to show
            //fb_username: "fb_username", // ID of a Facebook page which stream will be shown
            // General
            cookies: false, //if true then twitter results will be saved in cookies, to fetch them if 150 requests/hour is over.
            //currently works only for saving sets of tweets under 10
            length: 500 // maximum length of post message shown
        };
        //---------------------------------------------------------------------------------
        var options = $.extend(defaults, options),
        container = $(this);
        container.empty().css('display', 'inline-block');
        //---------------------------------------------------------------------------------
        // Initiate function
        return getAllData();
        //---------------------------------------------------------------------------------
        //This function performs consequent data loading from all of the sources by calling corresponding functions
        function getAllData(){
            if (options.fb_username != undefined) {
                //Facebook requires an access_token for fetching the feed.
                $.get(options.plugin_folder + 'php/get_access_token.php', function(data) {
                    getFacebookData(data);
                });
            }
            if (options.tw_username != undefined) {
                getTwitterData();
            }
            if (options.vk_username != undefined) {
                getVkontakteData();
            }
        }
        function getFacebookData(access_token){
            var limit = 'limit=' + options.fb_limit,
              query_extention = '&access_token=' + access_token + '',
              fb_graph = 'https://graph.facebook.com/',
              feed_json = fb_graph + options.fb_username + '/feed?' + limit + query_extention;
            $.get(feed_json,function(json){
                $.each(json.data,function(){
                    var element = this,
                      text,
                      url,
                      post = {};
                    if (element.message != undefined || element.story != undefined){
                        if (element.message != undefined)
                            text = element.message;
                        else
                            text = element.story;
                        if (element.link!=undefined)
                            url = element.link;
                        else
                            url = 'http://facebook.com/' + element.from.id;
                        post.dt_create = dateToSeconds(convertDate(element.created_time));
                        post.author_link = 'http://facebook.com/' + element.from.id;
                        post.author_picture = fb_graph + element.from.id + '/picture';
                        post.post_url = url;
                        post.author_name = element.from.name;
                        post.message = text;
                        post.description = '';
                        post.link = url;
                        if (element.description != undefined)
                            post.description = element.description;
                        post.social_network = 'fb';
                        getTemplate(post);
                    }
                });
            },'json');

        }
        function getVkontakteData(){
            var vk_json = 'https://api.vk.com/method/wall.get?owner_id='+options.vk_username+'&filter=owner&count='+options.vk_limit+'&callback=?',
              vk_user_json = 'https://api.vk.com/method/users.get?fields=first_name,%20last_name,%20screen_name,%20photo&uid=',
              vk_group_json = 'https://api.vk.com/method/groups.getById?fields=first_name,%20last_name,%20screen_name,%20photo&gid=';
            $.get(vk_json,function(json){

                $.each(json.response, function(){
                    if (this != parseInt(this)){
                        var element = this,
                          post = {};
                        post.dt_create = dateToSeconds(new Date(element.date*1000));
                        post.description = ' ';
                        post.message = stripHTML(element.text);
                        post.social_network='vk';
                        //if the post is created by user
                        if (element.from_id > 0){
                            vk_user_json += element.from_id + '&callback=?';
                            $.get(vk_user_json,function(user_json){
                                post.author_name = user_json.response[0].first_name + ' ' + user_json.response[0].last_name;
                                post.author_picture = user_json.response[0].photo;
                                post.author_link = 'http://vk.com/' + user_json.response[0].screen_name;
                                post.link = 'http://vk.com/' + user_json.response[0].screen_name + '?w=wall' + user_json.response[0].uid + '_' + element.id + '%2Fall';
                                getTemplate(post);
                            },'json');
                        //if the post is created by group
                        }else{
                            vk_group_json += (-1) * element.from_id + '&callback=?';
                            $.get(vk_group_json,function(user_json){
                                post.author_name = user_json.response[0].name;
                                post.author_picture = user_json.response[0].photo;
                                post.author_link = 'http://vk.com/' + user_json.response[0].screen_name;
                                post.link = 'http://vk.com/' + user_json.response[0].screen_name + '?w=wall-' + user_json.response[0].gid  + '_' + element.id;
                                getTemplate(post);

                            },'json');
                        }
                    }
                });

            },'json');
        }

        function getTwitterData(){
            var tw_json = 'http://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=' + options.tw_username + '&count=' + options.tw_limit + '&callback=?';
            $.ajax({
                url:tw_json,
                dataType:'json',
                timeout:1000,
                success:function(json){
                    $.each(json, function(i) {
                        var post = {},
                          element = this;
                        post.dt_create = dateToSeconds(convertDate(fixTwitterDate(element.created_at)));
                        post.author_link = 'http://twitter.com/'+element.user.screen_name;
                        post.author_picture = element.user.profile_image_url;
                        post.post_url = post.author_link + '/status/' + element.id_str;
                        post.author_name = element.user.name;
                        post.message = element.text;
                        post.description = '';
                        post.social_network = 'tw';
                        post.link = 'http://twitter.com/' + element.user.screen_name + '/status/' + element.id_str;
                        if (options.cookies)
                            $.cookie('social-feed-twitter' + i,JSON.stringify(post));
                        getTemplate(post);
                    });
                },
                error:function(e){
                    if (options.cookies){
                        //if can not fetch data from Twitter (because of the 150 responses / hour limit) get them from cookies
                        for (var i = 0, limit = options.tw_limit; i < limit && $.cookie('social-feed-twitter' + i) != null; i++){
                            var data = JSON.parse($.cookie('social-feed-twitter' + i));
                            data.dt_create = convertDate(data.dt_create);
                            getTemplate(data);
                        }
                    }
                }
            });
        }
        //---------------------------------------------------------------------------------
        //Render functions
        //---------------------------------------------------------------------------------
        function getTemplate(data){
            var content = data;

            content.time_ago = timeAgo(data.dt_create);
            content.text = escapeHtml(wrapLinks(shorten(data.message + ' ' + data.description)));
            content.social_icon = options.plugin_folder + 'img/' + data.social_network + '-icon-24.png';
            $.post(options.plugin_folder + 'php/template.php', content,function(template){
                placeTemplate(template,data);
            });
        }
        function placeTemplate(template,data){
            if (container.children().length == 0){
                container.append(template);
            }else{
                var i = 0,
                  insert_index = -1;

                $.each(container.children(), function(){
                    if ($(this).attr('dt_create') > data.dt_create){
                        insert_index = i;
                        return false;
                    }
                    i++;
                });
                container.append(template);
                if (insert_index >= 0){
                    insert_index++;
                    var before = container.children('div:nth-child('+insert_index+')'),
                      current = container.children('div:last-child');
                    $(current).insertBefore(before);
                }
            }
        }
        //---------------------------------------------------------------------------------
        //Utility functions
        //---------------------------------------------------------------------------------
        function wrapLinkTemplate(string){
            return '<a target="_blank" href="' + string + '">' + string + '<\/a>';
        }
        function wrapLinks(string){
            return string.replace(/\bhttp[^ ]+/ig, wrapLinkTemplate);
        }
        function convertDate(string){
            string = string.replace('+0000', 'Z');
            var time = ('' + string).replace(/-/g, "/").replace(/[TZ]/g, " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
            if(time.substr(time.length - 4, 1) == ".") time = time.substr(0,time.length - 4);
            return new Date(time);
        }
        function shorten(string){
            string = $.trim(string);
            if (string.length > options.length)
            {
                var cut = string.substring(0, options.length),
                  link_start_position = cut.lastIndexOf('http');
                if (link_start_position > 0){
                    var link_end_position = string.indexOf(' ',link_start_position);
                    if (link_end_position > options.length && string != string.substring(0,link_end_position))
                        return string.substring(0,link_end_position) + " ..";
                    else
                        return string;
                }else{
                    return cut + "..";
                }
            //return string.substring(0,options.length) + "..";
            }else
                return string;
        }
        function dateToSeconds(time){
            return (new Date - time) / 1000;
        }
        function stripHTML(string){
            if (typeof string === "undefined" || string === null)
                return '';
            return string.replace(/(<([^>]+)>)|nbsp;|\s{2,}|/ig,"");
        }
        function escapeHtml(string) {
            if (typeof string==="undefined" || string===null)
                return;
            return string
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
        }
        function fixTwitterDate(created_at) {
            var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
              pattern = /\s/,
              day_of_week,day,month_pos,month,year,time;
            created_at = created_at.split(pattern);
            for (var i = 0; i < created_at.length; i++){
                day_of_week = created_at[0];
                day = created_at[2];
                month_pos = created_at[1];
                month = 0 + months.indexOf(month_pos) + 1; // add 1 because array starts from zero
                year = created_at[5];
                time = created_at[3];
            }
            created_at = year + '-' + month + '-' + day + 'T' + time + 'Z';

            if(created_at !== undefined)
                return created_at;
        }
        function timeAgo(seconds){
            //the function is taken from https://github.com/iatek/jquery-socialist
            var time_formats = [
            [60, 'just now', '1'],
            [120, '1 minute ago', '1 minute from now'],
            [3600, 'minutes', 60],
            [7200, '1 hour ago', '1 hour from now'],
            [86400, 'hours', 3600],
            [172800, 'yesterday', 'tomorrow'],
            [604800, 'days', 86400],
            [1209600, 'last week', 'next week'],
            [2419200, 'weeks', 604800],
            [4838400, 'last month', 'next month'],
            [29030400, 'months', 2419200],
            [58060800, 'last year', 'next year'],
            [2903040000, 'years', 29030400],
            [5806080000, 'last century', 'next century'],
            [58060800000, 'centuries', 2903040000]
            ];
            var token = 'ago', list_choice = 1;
            if (seconds < 0) {
                seconds = Math.abs(seconds);
                token = 'from now';
                list_choice = 2;
            }
            var i = 0, format;
            while (format = time_formats[i++])
                if (seconds < format[0]) {
                    if (typeof format[2] == 'string')
                        return format[list_choice];
                    else
                        return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;
                }
            return seconds;
        }
    //---------------------------------------------------------------------------------
    };

})(jQuery);
<commit_msg>Issue: css clean up bug fixes, container fix;<commit_after>(function($){
    $.fn.socialfeed = function(options)
    {
        var defaults = {
            plugin_folder: '', // a folder in which the plugin is located (with a slash in the end)
            // VK.com
            vk_limit: 3, // amount of vkontakte posts to show
            //vk_username: "vk_username", // ID of a VK page which stream will be shown
            // Twitter.com
            tw_limit: 3, // amount of twitter posts to show
            //tw_username: "tw_username", // ID of a twitter page which stream will be shown
            // Facebook.com
            fb_limit: 3, // amount of facebook posts to show
            //fb_username: "fb_username", // ID of a Facebook page which stream will be shown
            // General
            cookies: false, //if true then twitter results will be saved in cookies, to fetch them if 150 requests/hour is over.
            //currently works only for saving sets of tweets under 10
            length: 500 // maximum length of post message shown
        };
        //---------------------------------------------------------------------------------
        var options = $.extend(defaults, options),
        container = $(this);
        container.empty().css('display', 'inline-block');
        //---------------------------------------------------------------------------------
        // Initiate function
        return getAllData();
        //---------------------------------------------------------------------------------
        //This function performs consequent data loading from all of the sources by calling corresponding functions
        function getAllData(){
            if (options.fb_username != undefined) {
                //Facebook requires an access_token for fetching the feed.
                $.get(options.plugin_folder + 'php/get_access_token.php', function(data) {
                    getFacebookData(data);
                });
            }
            if (options.tw_username != undefined) {
                getTwitterData();
            }
            if (options.vk_username != undefined) {
                getVkontakteData();
            }
        }
        function getFacebookData(access_token){
            var limit = 'limit=' + options.fb_limit,
              query_extention = '&access_token=' + access_token + '',
              fb_graph = 'https://graph.facebook.com/',
              feed_json = fb_graph + options.fb_username + '/feed?' + limit + query_extention;
            $.get(feed_json,function(json){
                $.each(json.data,function(){
                    var element = this,
                      post = {};
                    if (element.message != undefined || element.story != undefined){
                        var text = element.story;,
                          url = 'http://facebook.com/' + element.from.id
                        if (element.message != undefined)
                            text = element.message;
                        if (element.link!=undefined)
                            url = element.link;
                        post.dt_create = dateToSeconds(convertDate(element.created_time));
                        post.author_link = 'http://facebook.com/' + element.from.id;
                        post.author_picture = fb_graph + element.from.id + '/picture';
                        post.post_url = url;
                        post.author_name = element.from.name;
                        post.message = text;
                        post.description = (element.description != undefined) ? element.description : '';
                        post.link = url;
                        post.social_network = 'fb';
                        getTemplate(post);
                    }
                });
            },'json');

        }
        function getVkontakteData(){
            var vk_json = 'https://api.vk.com/method/wall.get?owner_id='+options.vk_username+'&filter=owner&count='+options.vk_limit+'&callback=?',
              vk_user_json = 'https://api.vk.com/method/users.get?fields=first_name,%20last_name,%20screen_name,%20photo&uid=',
              vk_group_json = 'https://api.vk.com/method/groups.getById?fields=first_name,%20last_name,%20screen_name,%20photo&gid=';
            $.get(vk_json,function(json){

                $.each(json.response, function(){
                    if (this != parseInt(this)){
                        var element = this,
                          post = {};
                        post.dt_create = dateToSeconds(new Date(element.date*1000));
                        post.description = ' ';
                        post.message = stripHTML(element.text);
                        post.social_network='vk';
                        //if the post is created by user
                        if (element.from_id > 0){
                            vk_user_json += element.from_id + '&callback=?';
                            $.get(vk_user_json,function(user_json){
                                post.author_name = user_json.response[0].first_name + ' ' + user_json.response[0].last_name;
                                post.author_picture = user_json.response[0].photo;
                                post.author_link = 'http://vk.com/' + user_json.response[0].screen_name;
                                post.link = 'http://vk.com/' + user_json.response[0].screen_name + '?w=wall' + user_json.response[0].uid + '_' + element.id + '%2Fall';
                                getTemplate(post);
                            },'json');
                        //if the post is created by group
                        }else{
                            vk_group_json += (-1) * element.from_id + '&callback=?';
                            $.get(vk_group_json,function(user_json){
                                post.author_name = user_json.response[0].name;
                                post.author_picture = user_json.response[0].photo;
                                post.author_link = 'http://vk.com/' + user_json.response[0].screen_name;
                                post.link = 'http://vk.com/' + user_json.response[0].screen_name + '?w=wall-' + user_json.response[0].gid  + '_' + element.id;
                                getTemplate(post);

                            },'json');
                        }
                    }
                });

            },'json');
        }

        function getTwitterData(){
            var tw_json = 'http://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=' + options.tw_username + '&count=' + options.tw_limit + '&callback=?';
            $.ajax({
                url:tw_json,
                dataType:'json',
                timeout:1000,
                success:function(json){
                    $.each(json, function(i) {
                        var post = {},
                          element = this;
                        post.dt_create = dateToSeconds(convertDate(fixTwitterDate(element.created_at)));
                        post.author_link = 'http://twitter.com/'+element.user.screen_name;
                        post.author_picture = element.user.profile_image_url;
                        post.post_url = post.author_link + '/status/' + element.id_str;
                        post.author_name = element.user.name;
                        post.message = element.text;
                        post.description = '';
                        post.social_network = 'tw';
                        post.link = 'http://twitter.com/' + element.user.screen_name + '/status/' + element.id_str;
                        if (options.cookies)
                            $.cookie('social-feed-twitter' + i,JSON.stringify(post));
                        getTemplate(post);
                    });
                },
                error:function(e){
                    if (options.cookies){
                        //if can not fetch data from Twitter (because of the 150 responses / hour limit) get them from cookies
                        for (var i = 0, limit = options.tw_limit; i < limit && $.cookie('social-feed-twitter' + i) != null; i++){
                            var data = JSON.parse($.cookie('social-feed-twitter' + i));
                            data.dt_create = convertDate(data.dt_create);
                            getTemplate(data);
                        }
                    }
                }
            });
        }
        //---------------------------------------------------------------------------------
        //Render functions
        //---------------------------------------------------------------------------------
        function getTemplate(data){
            var content = data;
            content.time_ago = timeAgo(data.dt_create);
            content.text = escapeHtml(wrapLinks(shorten(data.message + ' ' + data.description)));
            content.social_icon = options.plugin_folder + 'img/' + data.social_network + '-icon-24.png';
            $.post(options.plugin_folder + 'php/template.php', content,function(template){
                placeTemplate(template,data);
            });
        }
        function placeTemplate(template,data){
            if ($(container).children().length == 0){
                $(container).append(template);
            }else{
                var i = 0,
                  insert_index = -1;
                $.each($(container).children(), function(){
                    if ($(this).attr('dt_create') > data.dt_create){
                        insert_index = i;
                        return false;
                    }
                    i++;
                });
                $(container).append(template);
                if (insert_index >= 0){
                    insert_index++;
                    var before = $(container).children('div:nth-child('+insert_index+')'),
                      current = $(container).children('div:last-child');
                    $(current).insertBefore(before);
                }
                else{
                }

            }
        }
        //---------------------------------------------------------------------------------
        //Utility functions
        //---------------------------------------------------------------------------------
        function wrapLinkTemplate(string){
            return '<a target="_blank" href="' + string + '">' + string + '<\/a>';
        }
        function wrapLinks(string){
            return string.replace(/\bhttp[^ ]+/ig, wrapLinkTemplate);
        }
        function convertDate(string){
            string = string.replace('+0000', 'Z');
            var time = ('' + string).replace(/-/g, "/").replace(/[TZ]/g, " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
            if(time.substr(time.length - 4, 1) == ".") time = time.substr(0,time.length - 4);
            return new Date(time);
        }
        function shorten(string){
            string = $.trim(string);
            if (string.length > options.length)
            {
                var cut = string.substring(0, options.length),
                  link_start_position = cut.lastIndexOf('http');
                if (link_start_position > 0){
                    var link_end_position = string.indexOf(' ',link_start_position);
                    if (link_end_position > options.length && string != string.substring(0,link_end_position))
                        return string.substring(0,link_end_position) + " ..";
                    else
                        return string;
                }else{
                    return cut + "..";
                }
            //return string.substring(0,options.length) + "..";
            }else
                return string;
        }
        function dateToSeconds(time){
            return (new Date - time) / 1000;
        }
        function stripHTML(string){
            if (typeof string === "undefined" || string === null)
                return '';
            return string.replace(/(<([^>]+)>)|nbsp;|\s{2,}|/ig,"");
        }
        function escapeHtml(string) {
            if (typeof string==="undefined" || string===null)
                return;
            return string
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
        }
        function fixTwitterDate(created_at) {
            var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
              pattern = /\s/,
              day_of_week,day,month_pos,month,year,time;
            created_at = created_at.split(pattern);
            for (var i = 0; i < created_at.length; i++){
                day_of_week = created_at[0];
                day = created_at[2];
                month_pos = created_at[1];
                month = 0 + months.indexOf(month_pos) + 1; // add 1 because array starts from zero
                year = created_at[5];
                time = created_at[3];
            }
            created_at = year + '-' + month + '-' + day + 'T' + time + 'Z';

            if(created_at !== undefined)
                return created_at;
        }
        function timeAgo(seconds){
            //the function is taken from https://github.com/iatek/jquery-socialist
            var time_formats = [
            [60, 'just now', '1'],
            [120, '1 minute ago', '1 minute from now'],
            [3600, 'minutes', 60],
            [7200, '1 hour ago', '1 hour from now'],
            [86400, 'hours', 3600],
            [172800, 'yesterday', 'tomorrow'],
            [604800, 'days', 86400],
            [1209600, 'last week', 'next week'],
            [2419200, 'weeks', 604800],
            [4838400, 'last month', 'next month'],
            [29030400, 'months', 2419200],
            [58060800, 'last year', 'next year'],
            [2903040000, 'years', 29030400],
            [5806080000, 'last century', 'next century'],
            [58060800000, 'centuries', 2903040000]
            ];
            var token = 'ago', list_choice = 1;
            if (seconds < 0) {
                seconds = Math.abs(seconds);
                token = 'from now';
                list_choice = 2;
            }
            var i = 0, format;
            while (format = time_formats[i++])
                if (seconds < format[0]) {
                    if (typeof format[2] == 'string')
                        return format[list_choice];
                    else
                        return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;
                }
            return seconds;
        }
    //---------------------------------------------------------------------------------
    };

})(jQuery); <|endoftext|>


<commit_before>(function (widget) {
    // Roughly following http://bl.ocks.org/mbostock/4063269
    var diameter = 600,
        className = "averageJobBuildTime";

    var buildRuntimeAsBubbles = function (pipeline) {
        return Object.keys(pipeline)
            .filter(function (jobName) {
                return pipeline[jobName].averageRuntime;
            })
            .map(function (jobName) {
                var avgRuntime = pipeline[jobName].averageRuntime;
                return {
                    name: jobName,
                    title: jobName + ': ' + avgRuntime,
                    value: avgRuntime
                };
            });
    };

    var svg = widget.create("Average Job Build Time","Color: jobGroup, Diameter: avg. Runtime")
            .svg(diameter)
            .attr("class", className);

    var bubble = d3.layout.pack()
            .sort(null)
            .size([diameter, diameter])
            .padding(1.5),
        noGrouping = function (bubbleNodes) {
            return bubbleNodes.filter(function(d) { return !d.children; });
        };

    var color = d3.scale.category20c();

    d3.json('/jobs', function (_, root) {
        var node = svg.selectAll("g")
                .data(noGrouping(bubble.nodes({children: buildRuntimeAsBubbles(root)})))
                .enter()
                .append("g")
                .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });;

        node.append("title")
            .text(function(d) { return d.title; });

        node.append("circle")
            .attr("r", function (d) { return d.r; })
            .style("fill", function(d) {
                var jobGroup = d.name.split(' ')[0];
                return color(jobGroup);
            });

        node.append("text")
            .style("text-anchor", "middle")
            .each(function (d) {
                widget.textWithLineBreaks(this, d.name.split(' '));
            });
    });
}(widget));
<commit_msg>Show properly formated duration in avg build time graph<commit_after>(function (widget) {
    // Roughly following http://bl.ocks.org/mbostock/4063269
    var diameter = 600,
        className = "averageJobBuildTime";

    var padZero = function (value) {
        if (value < 10) {
            return '0' + value;
        } else {
            return '' + value;
        }
    };

    var formatTimeInMs = function (timeInMs) {
        var hours = Math.floor(timeInMs / (60 * 60 * 1000)),
            minutes = Math.floor(timeInMs % (60 * 60 * 1000) / (60 * 1000)),
            seconds = Math.round(timeInMs % (60 * 1000) / 1000);

        return hours + ':' + padZero(minutes) + ':' + padZero(seconds);
    };

    var buildRuntimeAsBubbles = function (pipeline) {
        return Object.keys(pipeline)
            .filter(function (jobName) {
                return pipeline[jobName].averageRuntime;
            })
            .map(function (jobName) {
                var averageRuntime = pipeline[jobName].averageRuntime,
                    runtime = averageRuntime ? ' (' + formatTimeInMs(averageRuntime) + ')' : '';

                return {
                    name: jobName,
                    title: jobName + ': ' + runtime,
                    value: averageRuntime
                };
            });
    };

    var svg = widget.create("Average Job Build Time","Color: jobGroup, Diameter: avg. Runtime")
            .svg(diameter)
            .attr("class", className);

    var bubble = d3.layout.pack()
            .sort(null)
            .size([diameter, diameter])
            .padding(1.5),
        noGrouping = function (bubbleNodes) {
            return bubbleNodes.filter(function(d) { return !d.children; });
        };

    var color = d3.scale.category20c();

    d3.json('/jobs', function (_, root) {
        var node = svg.selectAll("g")
                .data(noGrouping(bubble.nodes({children: buildRuntimeAsBubbles(root)})))
                .enter()
                .append("g")
                .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });;

        node.append("title")
            .text(function(d) { return d.title; });

        node.append("circle")
            .attr("r", function (d) { return d.r; })
            .style("fill", function(d) {
                var jobGroup = d.name.split(' ')[0];
                return color(jobGroup);
            });

        node.append("text")
            .style("text-anchor", "middle")
            .each(function (d) {
                widget.textWithLineBreaks(this, d.name.split(' '));
            });
    });
}(widget));
<|endoftext|>


<commit_before>var satchmo = satchmo || {};

satchmo.use_sale_prices = true;

// Get the current selected product price.
satchmo.get_current_price = function(detail, qty, use_sale) {
    var taxed = satchmo.default_view_tax,
        k, prices;

    if (use_sale) {
        k = taxed ? "TAXED_SALE" : "SALE";
    }
    else {
        k = taxed ? "TAXED" : "PRICE";
    }

    var prices = detail[k];
    if (prices) {
        var best = prices['1'];
        if (qty > 1) {
            for (var pricekey in prices) {
                var priceqty = parseInt(pricekey);
                if (priceqty > qty) {
                    break;
                }
                best = prices[pricekey];
            }
        }
        return best;
    }
    else {
        return ""
    }
};

satchmo.make_optionkey = function() {
    var work = Array(satchmo.option_ids.length);
    for (var ix=0; ix<satchmo.option_ids.length; ix++) {
        var k = "#" + satchmo.option_ids[ix];
        var v = $(k).fieldValue()[0];
        work[ix] = v;
    }
    return work.join('::');
};

// used for sorting numerically
satchmo.numeric_compare = function(a, b) {
    return a-b;
};

satchmo.option_ids = "";

// Update the product name
satchmo.set_name = function(name) {
    $("#productname").attr('value', name);
};

satchmo.set_option_ids = function(arr) {
    arr.sort(satchmo.numeric_compare);
    satchmo.option_ids = arr;
};

// Update the product price
satchmo.set_price = function(price) {
    $("#price").text(price);
};

satchmo.show_error = function(msg) {
    var section = $('#js_error');
    if (section.length == 0) {
        if (msg != "") {
            $('form#options').before("
" + msg + "
");
        }
    }
    else {
        section.text(msg);
        if (msg == "") {
            section.hide();
        }
    }
    var disabled = (msg != "");
    $('#addcart').attr('disabled', disabled);
};

// update name and price based on the current selections
satchmo.update_price = function() {
    var key = satchmo.make_optionkey(),
        detail = satchmo.variations[key],
        msg = "",
        use_sale, sale_price, full_price;

    if (detail) {
        var qty = parseInt($('#quantity').fieldValue()[0]);
        satchmo.set_name(detail['SLUG']);

        if (!satchmo.variations['SALE']) {
            use_sale = false;
        }
        else {
            use_sale = satchmo.use_sale_prices;
        }

        if (use_sale) {
            full_price = satchmo.get_current_price(detail, qty, false);
            $('#fullprice').text(full_price);

            sale_price = satchmo.get_current_price(detail, qty, true);
        }
        else {
            sale_price = satchmo.get_current_price(detail, qty, false);
            $('#fullprice').hide();
        }

        satchmo.set_price(sale_price);

        if (qty && qty > detail['QTY']) {
            if (detail['QTY'] == -1) {
                msg = "Sorry, we are out of stock on that combination.";
             }
             else {
                 msg = "Sorry, we only have " + detail['QTY'] + " available in that combination.";
             }
        }
    }
    else {
        msg = "Sorry, we don't have any of that combination available.";
    }
    satchmo.show_error(msg);
};
<commit_msg>Fix a bug in the javascript where the error message could get hidden. Also changes language for out of stock products so it makes a little more sense. Closes #784<commit_after>var satchmo = satchmo || {};

satchmo.use_sale_prices = true;

// Get the current selected product price.
satchmo.get_current_price = function(detail, qty, use_sale) {
    var taxed = satchmo.default_view_tax,
        k, prices;

    if (use_sale) {
        k = taxed ? "TAXED_SALE" : "SALE";
    }
    else {
        k = taxed ? "TAXED" : "PRICE";
    }

    var prices = detail[k];
    if (prices) {
        var best = prices['1'];
        if (qty > 1) {
            for (var pricekey in prices) {
                var priceqty = parseInt(pricekey);
                if (priceqty > qty) {
                    break;
                }
                best = prices[pricekey];
            }
        }
        return best;
    }
    else {
        return ""
    }
};

satchmo.make_optionkey = function() {
    var work = Array(satchmo.option_ids.length);
    for (var ix=0; ix<satchmo.option_ids.length; ix++) {
        var k = "#" + satchmo.option_ids[ix];
        var v = $(k).fieldValue()[0];
        work[ix] = v;
    }
    return work.join('::');
};

// used for sorting numerically
satchmo.numeric_compare = function(a, b) {
    return a-b;
};

satchmo.option_ids = "";

// Update the product name
satchmo.set_name = function(name) {
    $("#productname").attr('value', name);
};

satchmo.set_option_ids = function(arr) {
    arr.sort(satchmo.numeric_compare);
    satchmo.option_ids = arr;
};

// Update the product price
satchmo.set_price = function(price) {
    $("#price").text(price);
};

satchmo.show_error = function(msg) {
    var section = $('#js_error');
    if (section.length == 0) {
        if (msg != "") {
            $('form#options').before("
" + msg + "
");
        }
    }
    else {
        section.text(msg);
        if (msg == "") {
            section.hide();
        } else {
            section.show();
        }
    }
    var disabled = (msg != "");
    $('#addcart').attr('disabled', disabled);
};

// update name and price based on the current selections
satchmo.update_price = function() {
    var key = satchmo.make_optionkey(),
        detail = satchmo.variations[key],
        msg = "",
        use_sale, sale_price, full_price;

    if (detail) {
        var qty = parseInt($('#quantity').fieldValue()[0]);
        satchmo.set_name(detail['SLUG']);

        if (!satchmo.variations['SALE']) {
            use_sale = false;
        }
        else {
            use_sale = satchmo.use_sale_prices;
        }

        if (use_sale) {
            full_price = satchmo.get_current_price(detail, qty, false);
            $('#fullprice').text(full_price);

            sale_price = satchmo.get_current_price(detail, qty, true);
        }
        else {
            sale_price = satchmo.get_current_price(detail, qty, false);
            $('#fullprice').hide();
        }

        satchmo.set_price(sale_price);

        if (qty && qty > detail['QTY']) {
            if (detail['QTY'] <= 0) {
                msg = "Sorry, we are out of stock on that combination.";
             }
             else {
                 msg = "Sorry, we only have " + detail['QTY'] + " available in that combination.";
             }
        }
    }
    else {
        msg = "Sorry, we don't have any of that combination available.";
    }
    satchmo.show_error(msg);
};
<|endoftext|>


<commit_before>$(function() {
	if(window.location.protocol === "https:") {
		location.href = "http://mywebservice.info/beauty/";
	}

	var url = "http://mywebservice.info/beautyUniversity/data_out/school/university";

	$( '.swipebox' ).swipebox();
	$( '.swipebox' ).click(function() {
		$(".slide img").attr("data-caption", "This test data-caption");
	});

	jsonGet(url);
	$(window).on('ajaxComplete', function() {
  		setTimeout(function() {
  			$(window).lazyLoadXT();
  		}, 50);
	});

	$("#go-top").click(function(event) {
		event.preventDefault();
		$("html, body").animate({ scrollTop: 0 }, "slow");
	});

	$("#go-school-btn").click(function(event) {
		event.preventDefault();
		$("#img-contents").html("");
		if($("#fans-page-name").text() === "表特大學") {
			$("#go-school-btn").text("表特大學");
			$("#fans-page-name").text("表特輔仁");
			url = "http://mywebservice.info/beautyUniversity/data_out/school/FJU";
		}
		else {
			$("#go-school-btn").text("表特輔仁");
			$("#fans-page-name").text("表特大學");
			url = "http://mywebservice.info/beautyUniversity/data_out/school/university";
		}
		jsonGet(url);
	});

	 $('img.caption').captionjs({
        'class_name'      : 'captionjs', // Class name for each

        'schema'          : true,        // Use schema.org markup (i.e., itemtype, itemprop)
        'mode'            : 'default',   // default | stacked | animated | hide
        'debug_mode'      : false,       // Output debug info to the JS console
        'force_dimensions': true,        // Force the dimensions in case they cannot be detected (e.g., image is not yet painted to viewport)
        'is_responsive'   : false,       // Ensure the figure and image change size when in responsive layout. Requires a container to control responsiveness!
        'inherit_styles'  : false        // Have the caption.js container inherit box-model properties from the original image
    });

	/*
	$("#highchart-btn").click(function(event) {
		event.preventDefault();
		var str = "";
		if($("#fans-page-name").text() === "表特輔仁") {
			str = "FJU";
		}
		else {
			str = "university";
		}
		$("#img-contents").html("");
		$("#chart-container").html("");

		//using high chart

		 $('#chart-container').highcharts({
			chart: {
				plotBackgroundColor: null,
				plotBorderWidth: null,
				plotShadow: false,
				type: 'pie'
			},
			title: {
				text: 'Browser market shares January, 2015 to May, 2015'
			},
			tooltip: {
				pointFormat: '{series.name}: {point.percentage:.1f}%'
			},
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    format: '{point.name}: {point.percentage:.1f} %',
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    }
                }
            }
        },
        series: [{
            name: 'Brands',
            colorByPoint: true,
            data: [{
                name: 'Microsoft Internet Explorer',
                y: 56.33
            }, {
                name: 'Chrome',
                y: 24.03,
                sliced: true,
                selected: true
            }, {
                name: 'Firefox',
                y: 10.38
            }, {
                name: 'Safari',
                y: 4.77
            }, {
                name: 'Opera',
                y: 0.91
            }, {
                name: 'Proprietary or Undetectable',
                y: 0.2
            }]
        }]
    });
	});
	*/
});

function jsonGet(url) {
	$.getJSON(url, function(data) {
		var str = "";
		var j = 0;
		if(url.indexOf("university") !== -1) {
			for (var i = data.length - 1; i >= 0; i--) {
				if(data[i]["message"] === "" || data[i]["object_id"] === "") {
					continue;
				}

				str += "";
				str += "";
				str += "";
				j++;
			}
		}
		else {
			for (var i = 0; i < data.length; i++) {
				if(data[i]["message"] === "" || data[i]["object_id"] === "") {
					continue;
				}

				str += "";
				str += "";
				str += "";
				j++;
			}
		}
		console.log(j);
		$("#img-contents").append(str);
	 });
}

function getAnalytic(url) {

}<commit_msg>modify swipebox slide caption<commit_after>$(function() {
	if(window.location.protocol === "https:") {
		location.href = "http://mywebservice.info/beauty/";
	}

	var url = "http://mywebservice.info/beautyUniversity/data_out/school/university";

	$( '.swipebox' ).swipebox();
	$( '.swipebox' ).click(function() {
		$("div.slide > img").attr("data-caption", "This test data-caption");
	});

	jsonGet(url);
	$(window).on('ajaxComplete', function() {
  		setTimeout(function() {
  			$(window).lazyLoadXT();
  		}, 50);
	});

	$("#go-top").click(function(event) {
		event.preventDefault();
		$("html, body").animate({ scrollTop: 0 }, "slow");
	});

	$("#go-school-btn").click(function(event) {
		event.preventDefault();
		$("#img-contents").html("");
		if($("#fans-page-name").text() === "表特大學") {
			$("#go-school-btn").text("表特大學");
			$("#fans-page-name").text("表特輔仁");
			url = "http://mywebservice.info/beautyUniversity/data_out/school/FJU";
		}
		else {
			$("#go-school-btn").text("表特輔仁");
			$("#fans-page-name").text("表特大學");
			url = "http://mywebservice.info/beautyUniversity/data_out/school/university";
		}
		jsonGet(url);
	});

	 $('img.caption').captionjs({
        'class_name'      : 'captionjs', // Class name for each

        'schema'          : true,        // Use schema.org markup (i.e., itemtype, itemprop)
        'mode'            : 'default',   // default | stacked | animated | hide
        'debug_mode'      : false,       // Output debug info to the JS console
        'force_dimensions': true,        // Force the dimensions in case they cannot be detected (e.g., image is not yet painted to viewport)
        'is_responsive'   : false,       // Ensure the figure and image change size when in responsive layout. Requires a container to control responsiveness!
        'inherit_styles'  : false        // Have the caption.js container inherit box-model properties from the original image
    });

	/*
	$("#highchart-btn").click(function(event) {
		event.preventDefault();
		var str = "";
		if($("#fans-page-name").text() === "表特輔仁") {
			str = "FJU";
		}
		else {
			str = "university";
		}
		$("#img-contents").html("");
		$("#chart-container").html("");

		//using high chart

		 $('#chart-container').highcharts({
			chart: {
				plotBackgroundColor: null,
				plotBorderWidth: null,
				plotShadow: false,
				type: 'pie'
			},
			title: {
				text: 'Browser market shares January, 2015 to May, 2015'
			},
			tooltip: {
				pointFormat: '{series.name}: {point.percentage:.1f}%'
			},
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    format: '{point.name}: {point.percentage:.1f} %',
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    }
                }
            }
        },
        series: [{
            name: 'Brands',
            colorByPoint: true,
            data: [{
                name: 'Microsoft Internet Explorer',
                y: 56.33
            }, {
                name: 'Chrome',
                y: 24.03,
                sliced: true,
                selected: true
            }, {
                name: 'Firefox',
                y: 10.38
            }, {
                name: 'Safari',
                y: 4.77
            }, {
                name: 'Opera',
                y: 0.91
            }, {
                name: 'Proprietary or Undetectable',
                y: 0.2
            }]
        }]
    });
	});
	*/
});

function jsonGet(url) {
	$.getJSON(url, function(data) {
		var str = "";
		var j = 0;
		if(url.indexOf("university") !== -1) {
			for (var i = data.length - 1; i >= 0; i--) {
				if(data[i]["message"] === "" || data[i]["object_id"] === "") {
					continue;
				}

				str += "";
				str += "";
				str += "";
				j++;
			}
		}
		else {
			for (var i = 0; i < data.length; i++) {
				if(data[i]["message"] === "" || data[i]["object_id"] === "") {
					continue;
				}

				str += "";
				str += "";
				str += "";
				j++;
			}
		}
		console.log(j);
		$("#img-contents").append(str);
	 });
}

function getAnalytic(url) {

}<|endoftext|>


<commit_before>$(function() {
	$.getJSON("https://mywebservice.info/beautyUniversity/data_out.php", function(data) {
		var str = "";
		for (var i = data.length - 1; i >= 0; i--) {
			if(data[i]["message"] === "" || data[i]["object_id"] === "") {
				continue;
			}

			str += "<a name='lightbox'  class='swipebox' href='" + "https://graph.facebook.com/" + data[i]["object_id"] + "/picture?type=normal" +"'";
			str += "";
			str += "";
		}

		$("#main-content").append(str);
	 });

	$(window).on('ajaxComplete', function() {
  		setTimeout(function() {
  			$( '.swipebox' ).swipebox();
  			$(window).lazyLoadXT();
  		}, 50);
	});
});<commit_msg>change bind swipebox position<commit_after>$(function() {
	$( '.swipebox' ).swipebox();
	$.getJSON("https://mywebservice.info/beautyUniversity/data_out.php", function(data) {
		var str = "";
		for (var i = data.length - 1; i >= 0; i--) {
			if(data[i]["message"] === "" || data[i]["object_id"] === "") {
				continue;
			}

			str += "<a name='lightbox'  class='swipebox' href='" + "https://graph.facebook.com/" + data[i]["object_id"] + "/picture?type=normal" +"'";
			str += "";
			str += "";
		}

		$("#main-content").append(str);
	 });

	$(window).on('ajaxComplete', function() {
  		setTimeout(function() {
  			$(window).lazyLoadXT();
  		}, 50);
	});
});<|endoftext|>


<commit_before>import StageButton       from '../objects/LevelButton';
import MenuOptionButton  from '../objects/MenuOptionButton';
import BackgroundPattern from '../objects/BackgroundPattern';

export default class Levels extends Phaser.State {

  init () {
    this.game.transitions.registerTransition('fade-from-black');
  }

  create () {
    this.game.transitions.doTransition();

    this.add.existing(new BackgroundPattern(this.game));
    this.add.image(0, 0, 'background-level-select');

    this.add.image(0, 32, 'labels', 'label-level-select');

    this.add.existing(new MenuOptionButton(this.game));

    this.game.storage.getItem('levels', this._addStageButtons, this);
  }

  // --------------------------------------------------------------------------

  _addStageButtons (err, unlockedLevels) {
    for (var len = unlockedLevels.length, i = 0; i < len; ++i) {
      var { name, buttonFace, locked } = unlockedLevels[i];
      var x = 48 + 32 * (i % 5);
      var y = 64 + 32 * Math.floor(i / 5);

      this.add.existing(
        this._makeStageButton(x, y, name, buttonFace, locked));
    }
  }

  _makeStageButton (x, y, level, buttonFace, locked) {
    return new StageButton(this.game, x, y, level, locked);
  }

}
<commit_msg>Level selection 'Back' button transition<commit_after>import StageButton       from '../objects/LevelButton';
import MenuOptionButton  from '../objects/MenuOptionButton';
import BackgroundPattern from '../objects/BackgroundPattern';

export default class Levels extends Phaser.State {

  init () {
    this.game.transitions.registerTransition('fade-from-black');
  }

  create () {
    this.game.transitions.doTransition();

    this.add.existing(new BackgroundPattern(this.game));
    this.add.image(0, 0, 'background-level-select');

    this.add.image(0, 32, 'labels', 'label-level-select');

    let backButton = new MenuOptionButton(this.game, 0, 0);
    backButton.onInputUp.addOnce(() => this._doTransition('Title'));
    this.add.existing(backButton);

    this.game.storage.getItem('levels', this._addStageButtons, this);
  }

  // --------------------------------------------------------------------------

  _addStageButtons (err, unlockedLevels) {
    for (var len = unlockedLevels.length, i = 0; i < len; ++i) {
      var { name, buttonFace, locked } = unlockedLevels[i];
      var x = 48 + 32 * (i % 5);
      var y = 64 + 32 * Math.floor(i / 5);

      this.add.existing(
        this._makeStageButton(x, y, name, buttonFace, locked));
    }
  }

  _makeStageButton (x, y, level, buttonFace, locked) {
    return new StageButton(this.game, x, y, level, locked);
  }

  _doTransition (stateName, ... params) {
    this.game.transitions.registerTransition('fade-to-black');
    this.game.transitions.registerTransitionCallback(
      () => this._goToState(stateName, ... params));
    this.game.transitions.doTransition();
  }

  _goToState (stateName, ... params) {
    this.game.state.start(stateName, true, false, ... params);
  }

}
<|endoftext|>


<commit_before>Elm.Native = Elm.Native || {};
Elm.Native.Rails = {};
Elm.Native.Rails.make = function(localRuntime) {
    localRuntime.Native = localRuntime.Native || {};
    localRuntime.Native.Rails = localRuntime.Native.Rails || {};
    if (localRuntime.Native.Rails.values)
    {
        return localRuntime.Native.Rails.values;
    }

    var $Maybe = Elm.Maybe.make(localRuntime);

    var csrfTokenNode = document.querySelector('meta[name="csrf-token"]');
    var csrfToken = (function() {
        return (csrfTokenNode === null || tyepof csrfTokenNode.content === "undefined") ? $Maybe.Nothing : $Maybe.Just(csrfTokenNode.content);
    })();

    return localRuntime.Native.Rails.values = {
        csrfToken : csrfToken
    };
}
<commit_msg>Use querySelector alternative.<commit_after>Elm.Native = Elm.Native || {};
Elm.Native.Rails = {};
Elm.Native.Rails.make = function(localRuntime) {
    localRuntime.Native = localRuntime.Native || {};
    localRuntime.Native.Rails = localRuntime.Native.Rails || {};
    if (localRuntime.Native.Rails.values)
    {
        return localRuntime.Native.Rails.values;
    }

    var $Maybe = Elm.Maybe.make(localRuntime);

    var csrfTokenName = "csrf-token"
    var csrfToken = $Maybe.Nothing;
    var potentialMetaNodes = document.head.childNodes;

    // Use this instead of document.querySelector() for pre-ES5 compatibility.
    for (var index in potentialMetaNodes) {
        var potentialMetaNode = potentialMetaNodes[index];

        if (potentialMetaNode.tagName === "META"
            && potentialMetaNode.name === csrfTokenName
            && (typeof potentialMetaNode.content) === "string")
        {
            csrfToken = $Maybe.Just(potentialMetaNode.content);;
            break;
        }
    }

    return localRuntime.Native.Rails.values = {
        csrfToken : csrfToken
    };
}
<|endoftext|>


<commit_before>import React      from 'react/addons';
import Hammer     from 'hammerjs';
import immutable  from 'immutable';
import TweenState from 'react-tween-state';
import markdown   from 'markdown';

import gridify   from '../utils/gridify';
import doubletap from '../utils/doubletap';

import Ticket       from '../models/ticket';
import Board        from '../models/board';
import TicketAction from '../actions/ticket';

import DraggableMixin   from '../mixins/draggable';
import EditTicketDialog from '../components/dialog/edit-ticket';

/**
 *
 */
export default React.createClass({
	mixins: [ DraggableMixin, TweenState.Mixin ],

	propTypes: {
		ticket: (props) => {
			if(!props.ticket instanceof Ticket) throw new Error();
		},
		board: (props) => {
			if(!props.board instanceof Board) throw new Error();
		},
		snap:  React.PropTypes.bool
	},

	getDefaultProps() {
		return { snap: false }
	},

	getInitialState() {
		return {
			x: this.props.ticket.position.x,
			y: this.props.ticket.position.y,
			showEditDialog: false
		}
	},

	shouldComponentUpdate(nextProps, nextState) {
		let prevProps = this.props;
		let prevState = this.state;

		let hasStateChanged = (
			prevState.x                 !== nextState.x              ||
			prevState.y                 !== nextState.y              ||
			prevState.showEditDialog    !== nextState.showEditDialog
		);

		let havePropsChanged = (
			prevProps.snap  !== nextProps.snap                ||
			prevProps.board.id !== nextProps.board.id               ||
			!immutable.is(prevProps.ticket, nextProps.ticket)
		);

		let isTweening = nextState.tweenQueue.length > 0;

		return hasStateChanged || havePropsChanged || isTweening;
	},

	componentDidMount() {
		this.hammer = doubletap(this.getDOMNode());
		this.hammer.on('doubletap', this.toggleEditDialog);

		this.draggable.on('dragEnd', () => {
			if(this.draggable && !this.props.ticket.id.startsWith('dirty_')) {
				let position = this.draggable.position;

				if (this.state.x === position.x && this.state.y === position.y) {
					return;
				}

				// Snap the position if necessary...
				position = this.props.snap ? gridify(position) : position;

				// If we are snapping the ticket, we 'tween' the position to the
				// end value, else we just set the state directly.
				if (this.props.snap) {
					this.tween(position, this.draggable.position, 100);
				}
				else this.setState({ x: position.x, y: position.y });

				TicketAction.update({ id: this.props.board.id }, {
					id: this.props.ticket.id,
					position: { x: this.state.x, y: this.state.y }
				});
			}
		});

	},

	componentWillUnmount() {
		this.hammer.destroy();
		this.hammer = null;
	},

	componentWillReceiveProps(next) {
		// Prevent tweening, if there is a 'drag' currently going on.
		if(this.state.isDragging) return null;

		// Prevent unnecessary tweening.
		if(this.state.x !== next.ticket.position.x ||
				this.state.y !== next.ticket.position.y) {
			return this.tween(next.ticket.position);
		}
	},

	toggleEditDialog() {
		if(!this.props.ticket.id.startsWith('dirty_')) {
			this.setState({ showEditDialog: !this.state.showEditDialog });
		}
	},

	tween(to, from, duration) {
		[ 'x', 'y' ].map((axis) => {
			let tweeningOpts = {
				duration:   duration || 500,
				endValue:   to[axis],
				beginValue: from ? from[axis] : null
			}
			return this.tweenState(axis, tweeningOpts);
		});
	},

	render() {
		let style = {
			ticket: {
				top:    this.getTweeningValue('y'),
				left:   this.getTweeningValue('x'),
				zIndex: this.props.ticket.position.z
			},
			color: {
				backgroundColor: this.props.ticket.color
			}
		}
		let editTicketDialog = !this.state.showEditDialog ? null : (
			<EditTicketDialog board={this.props.board}
				ticket={this.props.ticket}
				onDismiss={this.toggleEditDialog} />
		);

		let markupContent = markdown.markdown.toHTML(this.props.ticket.content);

		// Add target="_blank" attribute to links
		if (markupContent.includes('<a href=')) {
			markupContent = markupContent.replace(/<a href="/g, '<a target="_blank" href="');
		}

		let commentCount = null;

		if (this.props.ticket.comments.size < 100) {
			commentCount = this.props.ticket.comments.size
		} else {
			commentCount = '99+';
		}

		return (

					{this.props.ticket.heading}

							{commentCount}

				{editTicketDialog}

		);
	}
});
<commit_msg>removed some meaningless work i did<commit_after>import React      from 'react/addons';
import Hammer     from 'hammerjs';
import immutable  from 'immutable';
import TweenState from 'react-tween-state';
import markdown   from 'markdown';

import gridify   from '../utils/gridify';
import doubletap from '../utils/doubletap';

import Ticket       from '../models/ticket';
import Board        from '../models/board';
import TicketAction from '../actions/ticket';

import DraggableMixin   from '../mixins/draggable';
import EditTicketDialog from '../components/dialog/edit-ticket';

/**
 *
 */
export default React.createClass({
	mixins: [ DraggableMixin, TweenState.Mixin ],

	propTypes: {
		ticket: (props) => {
			if(!props.ticket instanceof Ticket) throw new Error();
		},
		board: (props) => {
			if(!props.board instanceof Board) throw new Error();
		},
		snap:  React.PropTypes.bool
	},

	getDefaultProps() {
		return { snap: false }
	},

	getInitialState() {
		return {
			x: this.props.ticket.position.x,
			y: this.props.ticket.position.y,
			showEditDialog: false
		}
	},

	shouldComponentUpdate(nextProps, nextState) {
		let prevProps = this.props;
		let prevState = this.state;

		let hasStateChanged = (
			prevState.x                 !== nextState.x              ||
			prevState.y                 !== nextState.y              ||
			prevState.showEditDialog    !== nextState.showEditDialog
		);

		let havePropsChanged = (
			prevProps.snap  !== nextProps.snap                ||
			prevProps.board.id !== nextProps.board.id               ||
			!immutable.is(prevProps.ticket, nextProps.ticket)
		);

		let isTweening = nextState.tweenQueue.length > 0;

		return hasStateChanged || havePropsChanged || isTweening;
	},

	componentDidMount() {
		this.hammer = doubletap(this.getDOMNode());
		this.hammer.on('doubletap', this.toggleEditDialog);

		this.draggable.on('dragEnd', () => {
			if(this.draggable && !this.props.ticket.id.startsWith('dirty_')) {
				let position = this.draggable.position;

				if (this.state.x === position.x && this.state.y === position.y) {
					return;
				}

				// Snap the position if necessary...
				position = this.props.snap ? gridify(position) : position;

				// If we are snapping the ticket, we 'tween' the position to the
				// end value, else we just set the state directly.
				if (this.props.snap) {
					this.tween(position, this.draggable.position, 100);
				}
				else this.setState({ x: position.x, y: position.y });

				TicketAction.update({ id: this.props.board.id }, {
					id: this.props.ticket.id,
					position: { x: this.state.x, y: this.state.y }
				});
			}
		});

	},

	componentWillUnmount() {
		this.hammer.destroy();
		this.hammer = null;
	},

	componentWillReceiveProps(next) {
		// Prevent tweening, if there is a 'drag' currently going on.
		if(this.state.isDragging) return null;

		// Prevent unnecessary tweening.
		if(this.state.x !== next.ticket.position.x ||
				this.state.y !== next.ticket.position.y) {
			return this.tween(next.ticket.position);
		}
	},

	toggleEditDialog() {
		if(!this.props.ticket.id.startsWith('dirty_')) {
			this.setState({ showEditDialog: !this.state.showEditDialog });
		}
	},

	tween(to, from, duration) {
		[ 'x', 'y' ].map((axis) => {
			let tweeningOpts = {
				duration:   duration || 500,
				endValue:   to[axis],
				beginValue: from ? from[axis] : null
			}
			return this.tweenState(axis, tweeningOpts);
		});
	},

	render() {
		let style = {
			ticket: {
				top:    this.getTweeningValue('y'),
				left:   this.getTweeningValue('x'),
				zIndex: this.props.ticket.position.z
			},
			color: {
				backgroundColor: this.props.ticket.color
			}
		}
		let editTicketDialog = !this.state.showEditDialog ? null : (
			<EditTicketDialog board={this.props.board}
				ticket={this.props.ticket}
				onDismiss={this.toggleEditDialog} />
		);

		let markupContent = markdown.markdown.toHTML(this.props.ticket.content);

		// Add target="_blank" attribute to links
		if (markupContent.includes('<a href=')) {
			markupContent = markupContent.replace(/<a href="/g, '<a target="_blank" href="');
		}

		let commentCount = null;

		this.props.ticket.comments.size < 100 ? commentCount = this.props.ticket.comments.size : commentCount = "99+";

		return (

					{this.props.ticket.heading}

							{commentCount}

				{editTicketDialog}

		);
	}
});
<|endoftext|>


<commit_before>Elm.Native = Elm.Native || {};
Elm.Native.Utils = {};
Elm.Native.Utils.make = function(localRuntime) {
	localRuntime.Native = localRuntime.Native || {};
	localRuntime.Native.Utils = localRuntime.Native.Utils || {};
	if (localRuntime.Native.Utils.values)
	{
		return localRuntime.Native.Utils.values;
	}

	function eq(l, r)
	{
		var stack = [{'x': l, 'y': r}];
		while (stack.length > 0)
		{
			var front = stack.pop();
			var x = front.x;
			var y = front.y;
			if (x === y)
			{
				continue;
			}
			if (typeof x === 'object')
			{
				var c = 0;
				for (var i in x)
				{
					++c;
					if (i in y)
					{
						if (i !== 'ctor')
						{
							stack.push({ 'x': x[i], 'y': y[i] });
						}
					}
					else
					{
						return false;
					}
				}
				if ('ctor' in x)
				{
					stack.push({'x': x.ctor, 'y': y.ctor});
				}
				if (c !== Object.keys(y).length)
				{
					return false;
				}
			}
			else if (typeof x === 'function')
			{
				throw new Error('Equality error: general function equality is ' +
								'undecidable, and therefore, unsupported');
			}
			else
			{
				return false;
			}
		}
		return true;
	}

	// code in Generate/JavaScript.hs depends on the particular
	// integer values assigned to LT, EQ, and GT
	var LT = -1, EQ = 0, GT = 1, ord = ['LT', 'EQ', 'GT'];

	function compare(x, y)
	{
		return {
			ctor: ord[cmp(x, y) + 1]
		};
	}

	function cmp(x, y) {
		var ord;
		if (typeof x !== 'object')
		{
			return x === y ? EQ : x < y ? LT : GT;
		}
		else if (x.isChar)
		{
			var a = x.toString();
			var b = y.toString();
			return a === b
				? EQ
				: a < b
					? LT
					: GT;
		}
		else if (x.ctor === '::' || x.ctor === '[]')
		{
			while (true)
			{
				if (x.ctor === '[]' && y.ctor === '[]')
				{
					return EQ;
				}
				if (x.ctor !== y.ctor)
				{
					return x.ctor === '[]' ? LT : GT;
				}
				ord = cmp(x._0, y._0);
				if (ord !== EQ)
				{
					return ord;
				}
				x = x._1;
				y = y._1;
			}
		}
		else if (x.ctor.slice(0, 6) === '_Tuple')
		{
			var n = x.ctor.slice(6) - 0;
			var err = 'cannot compare tuples with more than 6 elements.';
			if (n === 0) return EQ;
			if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
			if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
			if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
			if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
			if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
			if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
			if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
			return EQ;
		}
		else
		{
			throw new Error('Comparison error: comparison is only defined on ints, ' +
							'floats, times, chars, strings, lists of comparable values, ' +
							'and tuples of comparable values.');
		}
	}

	var Tuple0 = {
		ctor: '_Tuple0'
	};

	function Tuple2(x, y)
	{
		return {
			ctor: '_Tuple2',
			_0: x,
			_1: y
		};
	}

	function chr(c)
	{
		var x = new String(c);
		x.isChar = true;
		return x;
	}

	function txt(str)
	{
		var t = new String(str);
		t.text = true;
		return t;
	}

	var count = 0;
	function guid(_)
	{
		return count++;
	}

	function copy(oldRecord)
	{
		var newRecord = {};
		for (var key in oldRecord)
		{
			var value = key === '_'
				? copy(oldRecord._)
				: oldRecord[key];
			newRecord[key] = value;
		}
		return newRecord;
	}

	function remove(key, oldRecord)
	{
		var record = copy(oldRecord);
		if (key in record._)
		{
			record[key] = record._[key][0];
			record._[key] = record._[key].slice(1);
			if (record._[key].length === 0)
			{
				delete record._[key];
			}
		}
		else
		{
			delete record[key];
		}
		return record;
	}

	function replace(keyValuePairs, oldRecord)
	{
		var record = copy(oldRecord);
		for (var i = keyValuePairs.length; i--; )
		{
			var pair = keyValuePairs[i];
			record[pair[0]] = pair[1];
		}
		return record;
	}

	function insert(key, value, oldRecord)
	{
		var newRecord = copy(oldRecord);
		if (key in newRecord)
		{
			var values = newRecord._[key];
			var copiedValues = values ? values.slice(0) : [];
			newRecord._[key] = [newRecord[key]].concat(copiedValues);
		}
		newRecord[key] = value;
		return newRecord;
	}

	function getXY(e)
	{
		var posx = 0;
		var posy = 0;
		if (e.pageX || e.pageY)
		{
			posx = e.pageX;
			posy = e.pageY;
		}
		else if (e.clientX || e.clientY)
		{
			posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}

		if (localRuntime.isEmbed())
		{
			var rect = localRuntime.node.getBoundingClientRect();
			var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
			var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
			// TODO: figure out if there is a way to avoid rounding here
			posx = posx - Math.round(relx) - localRuntime.node.clientLeft;
			posy = posy - Math.round(rely) - localRuntime.node.clientTop;
		}
		return Tuple2(posx, posy);
	}

	//// LIST STUFF ////

	var Nil = { ctor: '[]' };

	function Cons(hd, tl)
	{
		return {
			ctor: '::',
			_0: hd,
			_1: tl
		};
	}

	function append(xs, ys)
	{
		// append Strings
		if (typeof xs === 'string')
		{
			return xs + ys;
		}

		// append Text
		if (xs.ctor.slice(0, 5) === 'Text:')
		{
			return {
				ctor: 'Text:Append',
				_0: xs,
				_1: ys
			};
		}

		// append Lists
		if (xs.ctor === '[]')
		{
			return ys;
		}
		var root = Cons(xs._0, Nil);
		var curr = root;
		xs = xs._1;
		while (xs.ctor !== '[]')
		{
			curr._1 = Cons(xs._0, Nil);
			xs = xs._1;
			curr = curr._1;
		}
		curr._1 = ys;
		return root;
	}

	//// RUNTIME ERRORS ////

	function indent(lines)
	{
		return '\n' + lines.join('\n');
	}

	function badCase(moduleName, span)
	{
		var msg = indent([
			'Non-exhaustive pattern match in case-expression.',
			'Make sure your patterns cover every case!'
		]);
		throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
	}

	function badIf(moduleName, span)
	{
		var msg = indent([
			'Non-exhaustive pattern match in multi-way-if expression.',
			'It is best to use \'otherwise\' as the last branch of multi-way-if.'
		]);
		throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
	}

	function formatValue(value)
	{
		// Explicity format undefined values as "undefined"
		// because JSON.stringify(undefined) unhelpfully returns ""
		return (value === undefined) ? "undefined" : JSON.stringify(value);
	}

	function badPort(expected, received)
	{
		var msg = indent([
			'Expecting ' + expected + ' but was given ',
			formatValue(received)
		]);
		throw new Error('Runtime error when sending values through a port.' + msg);
	}

	return localRuntime.Native.Utils.values = {
		eq: eq,
		cmp: cmp,
		compare: F2(compare),
		Tuple0: Tuple0,
		Tuple2: Tuple2,
		chr: chr,
		txt: txt,
		copy: copy,
		remove: remove,
		replace: replace,
		insert: insert,
		guid: guid,
		getXY: getXY,

		Nil: Nil,
		Cons: Cons,
		append: F2(append),

		badCase: badCase,
		badIf: badIf,
		badPort: badPort
	};
};
<commit_msg>Simplify record update logic<commit_after>Elm.Native = Elm.Native || {};
Elm.Native.Utils = {};
Elm.Native.Utils.make = function(localRuntime) {
	localRuntime.Native = localRuntime.Native || {};
	localRuntime.Native.Utils = localRuntime.Native.Utils || {};
	if (localRuntime.Native.Utils.values)
	{
		return localRuntime.Native.Utils.values;
	}

	// COMPARISONS

	function eq(l, r)
	{
		var stack = [{'x': l, 'y': r}];
		while (stack.length > 0)
		{
			var front = stack.pop();
			var x = front.x;
			var y = front.y;
			if (x === y)
			{
				continue;
			}
			if (typeof x === 'object')
			{
				var c = 0;
				for (var i in x)
				{
					++c;
					if (i in y)
					{
						if (i !== 'ctor')
						{
							stack.push({ 'x': x[i], 'y': y[i] });
						}
					}
					else
					{
						return false;
					}
				}
				if ('ctor' in x)
				{
					stack.push({'x': x.ctor, 'y': y.ctor});
				}
				if (c !== Object.keys(y).length)
				{
					return false;
				}
			}
			else if (typeof x === 'function')
			{
				throw new Error('Equality error: general function equality is ' +
								'undecidable, and therefore, unsupported');
			}
			else
			{
				return false;
			}
		}
		return true;
	}

	// code in Generate/JavaScript.hs depends on the particular
	// integer values assigned to LT, EQ, and GT
	var LT = -1, EQ = 0, GT = 1, ord = ['LT', 'EQ', 'GT'];

	function compare(x, y)
	{
		return {
			ctor: ord[cmp(x, y) + 1]
		};
	}

	function cmp(x, y) {
		var ord;
		if (typeof x !== 'object')
		{
			return x === y ? EQ : x < y ? LT : GT;
		}
		else if (x.isChar)
		{
			var a = x.toString();
			var b = y.toString();
			return a === b
				? EQ
				: a < b
					? LT
					: GT;
		}
		else if (x.ctor === '::' || x.ctor === '[]')
		{
			while (true)
			{
				if (x.ctor === '[]' && y.ctor === '[]')
				{
					return EQ;
				}
				if (x.ctor !== y.ctor)
				{
					return x.ctor === '[]' ? LT : GT;
				}
				ord = cmp(x._0, y._0);
				if (ord !== EQ)
				{
					return ord;
				}
				x = x._1;
				y = y._1;
			}
		}
		else if (x.ctor.slice(0, 6) === '_Tuple')
		{
			var n = x.ctor.slice(6) - 0;
			var err = 'cannot compare tuples with more than 6 elements.';
			if (n === 0) return EQ;
			if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
			if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
			if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
			if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
			if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
			if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
			if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
			return EQ;
		}
		else
		{
			throw new Error('Comparison error: comparison is only defined on ints, ' +
							'floats, times, chars, strings, lists of comparable values, ' +
							'and tuples of comparable values.');
		}
	}

	// TUPLES

	var Tuple0 = {
		ctor: '_Tuple0'
	};

	function Tuple2(x, y)
	{
		return {
			ctor: '_Tuple2',
			_0: x,
			_1: y
		};
	}

	// LITERALS

	function chr(c)
	{
		var x = new String(c);
		x.isChar = true;
		return x;
	}

	function txt(str)
	{
		var t = new String(str);
		t.text = true;
		return t;
	}

	// GUID

	var count = 0;
	function guid(_)
	{
		return count++;
	}

	// RECORDS

	function update(oldRecord, updatedFields)
	{
		var newRecord = {};
		for (var key in oldRecord)
		{
			var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key];
			newRecord[key] = value;
		}
		return newRecord;
	}

	// MOUSE COORDINATES

	function getXY(e)
	{
		var posx = 0;
		var posy = 0;
		if (e.pageX || e.pageY)
		{
			posx = e.pageX;
			posy = e.pageY;
		}
		else if (e.clientX || e.clientY)
		{
			posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}

		if (localRuntime.isEmbed())
		{
			var rect = localRuntime.node.getBoundingClientRect();
			var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
			var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
			// TODO: figure out if there is a way to avoid rounding here
			posx = posx - Math.round(relx) - localRuntime.node.clientLeft;
			posy = posy - Math.round(rely) - localRuntime.node.clientTop;
		}
		return Tuple2(posx, posy);
	}

	//// LIST STUFF ////

	var Nil = { ctor: '[]' };

	function Cons(hd, tl)
	{
		return {
			ctor: '::',
			_0: hd,
			_1: tl
		};
	}

	function append(xs, ys)
	{
		// append Strings
		if (typeof xs === 'string')
		{
			return xs + ys;
		}

		// append Text
		if (xs.ctor.slice(0, 5) === 'Text:')
		{
			return {
				ctor: 'Text:Append',
				_0: xs,
				_1: ys
			};
		}

		// append Lists
		if (xs.ctor === '[]')
		{
			return ys;
		}
		var root = Cons(xs._0, Nil);
		var curr = root;
		xs = xs._1;
		while (xs.ctor !== '[]')
		{
			curr._1 = Cons(xs._0, Nil);
			xs = xs._1;
			curr = curr._1;
		}
		curr._1 = ys;
		return root;
	}

	//// RUNTIME ERRORS ////

	function indent(lines)
	{
		return '\n' + lines.join('\n');
	}

	function badCase(moduleName, span)
	{
		var msg = indent([
			'Non-exhaustive pattern match in case-expression.',
			'Make sure your patterns cover every case!'
		]);
		throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
	}

	function badIf(moduleName, span)
	{
		var msg = indent([
			'Non-exhaustive pattern match in multi-way-if expression.',
			'It is best to use \'otherwise\' as the last branch of multi-way-if.'
		]);
		throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
	}

	function formatValue(value)
	{
		// Explicity format undefined values as "undefined"
		// because JSON.stringify(undefined) unhelpfully returns ""
		return (value === undefined) ? "undefined" : JSON.stringify(value);
	}

	function badPort(expected, received)
	{
		var msg = indent([
			'Expecting ' + expected + ' but was given ',
			formatValue(received)
		]);
		throw new Error('Runtime error when sending values through a port.' + msg);
	}

	return localRuntime.Native.Utils.values = {
		eq: eq,
		cmp: cmp,
		compare: F2(compare),
		Tuple0: Tuple0,
		Tuple2: Tuple2,
		chr: chr,
		txt: txt,
		update: update,
		guid: guid,
		getXY: getXY,

		Nil: Nil,
		Cons: Cons,
		append: F2(append),

		badCase: badCase,
		badIf: badIf,
		badPort: badPort
	};
};
<|endoftext|>


<commit_before>'use strict';
(function(module) {
  try {
    module = angular.module('tink.formathelper');
  } catch (e) {
    module = angular.module('tink.formathelper', ['tink.datehelper','tink.safeApply']);
  }
  module.directive('tinkFormatInput', ['dateCalculator', '$window', 'safeApply', function(dateCalculator, $window, safeApply) {
    return {
      restrict: 'EA',
      replace: true,
      priority:99,
      controller:'tinkFormatController',
      controllerAs:'ctrl',
      scope:{
        minDate:'=?',
        maxDate:'=?',
        isDisabled:'='
      },
      require:['tinkFormatInput','ngModel','?^form'],
      template: function() {
        var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
        var isTouch = ('createTouch' in $window.document) && isNative;
        if (isTouch) {
          return '
<input id="input" class="faux-input" type="date"/>
';
        } else {
          return '

{{placeholder}}

';
        }
      },
      compile: function(template) {
        template.prop('type', 'date');
        return {
          pre: function() {
          },
          post: function(scope, elem, attr, ctrl) {
            // -- check if we are using a touch device  --/
            var isDateSupported = function() {
              var i = document.createElement('input');
              i.setAttribute('type', 'date');
              return i.type !== 'text';
            };

            var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
            var isTouch = ('createTouch' in $window.document) && isNative && isDateSupported();
        //variable
        var config = {
          format: '00/00/0000',
          placeholder: 'dd/mm/jjjj'
        };
        var dateformat;
        if(isTouch){
          dateformat = 'yyyy-mm-dd';
        }else{
          dateformat = 'dd/mm/yyyy';
        }

        var element = elem.find('#input');
        var ngControl = ctrl[1];
        var controller = ctrl[0];
        var form = ctrl[2];

        var prefix = '';
        if(angular.isDefined(attr.validName)){
          setTimeout(function(){
            if(form && attr.name && typeof attr.name === 'string' && attr.name !== ''){
            safeApply(scope,function(){
              prefix = attr.validName;
              form.$removeControl(ngControl);
              ngControl.$name = prefix+attr.name;
              form.$addControl(ngControl);
            });
          }
          }, 1);
        }else{
          setTimeout(function(){
            safeApply(scope,function(){
              if(form){
                form.$addControl(ngControl);
              }
            });
          }, 1);
        }

        function validFormat(date,format){
          var dateObject;
          if(angular.isDefined(date) && date !== null){

            if(typeof date === 'string'){
              if(date.length !== 10){ return false; }

              if(!isTouch && !/^(?:(?:31(\/)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/.test(date)){return false;}

              dateObject = dateCalculator.getDate(date, format);
            }else if(angular.isDate(date)){
              dateObject = date;
            }else if(typeof date === 'function'){
              return validFormat(date(),format);
            }else {
              return false;
            }

            return dateObject.toString()!=='Invalid Date';
          }
        }

        var isRequired = (function(){
          if(attr.require === 'true'){
            return true;
          }else{
            return false;
          }
        })();
        var noErrorClass = 'hide-error';
        var errorElem = $(elem.find('.faux-input')[0]);

        function checkValidity(value){
          var stringValue;
          if(value != 'Invalid Date' && angular.isDate(value)){
            stringValue = dateCalculator.format(value,dateformat);
          }else{
            stringValue = value;
          }

          safeApply(scope,function(){

            if(angular.isDate(scope.minDate)){
              if(dateCalculator.dateBeforeOther(value,scope.minDate)){
                ngControl.$setValidity('date-min',true);
                errorElem.addClass(noErrorClass);
              }else{
                ngControl.$setValidity('date-min',false);
                errorElem.removeClass(noErrorClass);
              }

            }
            if(angular.isDate(scope.maxDate)){
              if(dateCalculator.dateBeforeOther(scope.maxDate,value)){
                ngControl.$setValidity('date-max',true);
                errorElem.addClass(noErrorClass);
              }else{
                ngControl.$setValidity('date-max',false);
                errorElem.removeClass(noErrorClass);
              }
            }

            if(validFormat(stringValue,dateformat)){
              ngControl.$setValidity('date',true);
              errorElem.addClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',true);
                errorElem.addClass(noErrorClass);
              }
            }else if(stringValue !== config.placeholder && stringValue !== null){
              ngControl.$setValidity('date',false);
              ngControl.$setValidity('date-min',true);
              ngControl.$setValidity('date-max',true);
              errorElem.removeClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',true);
              }
            }else{
              ngControl.$setValidity('date',true);
              ngControl.$setValidity('date-min',true);
              ngControl.$setValidity('date-max',true);
              errorElem.addClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',false);
                errorElem.removeClass(noErrorClass);
              }
            }

          });
        }
        var myWatch = 0;
 //format text going to user (model to view)
        scope.$watch('$parent.'+ attr.ngModel, function(newVal,oldval) {
          if(myWatch === 0){
            if(!isTouch || isTouch && newVal !== ''){
              if(newVal != 'Invalid Date' && angular.isDate(newVal)){
                var date = dateCalculator.format(newVal,dateformat);
                controller.setValue(date,null,isTouch);
                checkValidity(newVal);
              }else{
                controller.setValue(null,null,isTouch);
              }
            }else{
               controller.setValue('',null,isTouch);
            }
            checkValidity(newVal);
          }else{
            myWatch = 0;
          }
        }, true);

        controller.init(element,config,form,ngControl);

         /* ngControl.$formatters.push(function(modelValue) {

          });
*/

          //format text from the user (view to model)
          ngControl.$parsers.unshift(function(value) {

              if(isTouch && value === ''){
                value = element.val();
              }

            if(value === null || value === ''){
              return value;
            }else if(typeof value === 'string'){
              controller.setValue(value,null,isTouch);
              return dateCalculator.getDate(value,dateformat);
            }else{
              return null;
            }
          });
          element.unbind('input').unbind('change');

          //on blur update the model.
          element.on('blur', function() {
            safeApply(scope,function(){
              var value;
              if(isTouch){
                value = element.val();
              }else{
                value = controller.getValue();
              }
              if(value === config.placeholder){
                checkValidity(value);
                ngControl.$setViewValue(null);
              }else{
                var date = dateCalculator.getDate(value,dateformat);
                if(date === null){
                  checkValidity(value);
                }else{
                  checkValidity(date);
                }
                ngControl.$setViewValue(value);
                ngControl.$setDirty();
                ngControl.$render();
              }
              var date = $(elem.html()).contents().contents().unwrap()[0].wholeText;
                  if(!validFormat(date,dateformat)){
                    myWatch = 1;
                    controller.setValue(date);
                  }
            });
          });
      }
    };

  }
};
}]);
})();<commit_msg>fix for firing 2 watches<commit_after>'use strict';
(function(module) {
  try {
    module = angular.module('tink.formathelper');
  } catch (e) {
    module = angular.module('tink.formathelper', ['tink.datehelper','tink.safeApply']);
  }
  module.directive('tinkFormatInput', ['dateCalculator', '$window', 'safeApply', function(dateCalculator, $window, safeApply) {
    return {
      restrict: 'EA',
      replace: true,
      priority:99,
      controller:'tinkFormatController',
      controllerAs:'ctrl',
      scope:{
        minDate:'=?',
        maxDate:'=?',
        isDisabled:'='
      },
      require:['tinkFormatInput','ngModel','?^form'],
      template: function() {
        var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
        var isTouch = ('createTouch' in $window.document) && isNative;
        if (isTouch) {
          return '
<input id="input" class="faux-input" type="date"/>
';
        } else {
          return '

{{placeholder}}

';
        }
      },
      compile: function(template) {
        template.prop('type', 'date');
        return {
          pre: function() {
          },
          post: function(scope, elem, attr, ctrl) {
            // -- check if we are using a touch device  --/
            var isDateSupported = function() {
              var i = document.createElement('input');
              i.setAttribute('type', 'date');
              return i.type !== 'text';
            };

            var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
            var isTouch = ('createTouch' in $window.document) && isNative && isDateSupported();
        //variable
        var config = {
          format: '00/00/0000',
          placeholder: 'dd/mm/jjjj'
        };
        var dateformat;
        if(isTouch){
          dateformat = 'yyyy-mm-dd';
        }else{
          dateformat = 'dd/mm/yyyy';
        }

        var element = elem.find('#input');
        var ngControl = ctrl[1];
        var controller = ctrl[0];
        var form = ctrl[2];

        var prefix = '';
        if(angular.isDefined(attr.validName)){
          setTimeout(function(){
            if(form && attr.name && typeof attr.name === 'string' && attr.name !== ''){
            safeApply(scope,function(){
              prefix = attr.validName;
              form.$removeControl(ngControl);
              ngControl.$name = prefix+attr.name;
              form.$addControl(ngControl);
            });
          }
          }, 1);
        }else{
          setTimeout(function(){
            safeApply(scope,function(){
              if(form){
                form.$addControl(ngControl);
              }
            });
          }, 1);
        }

        function validFormat(date,format){
          var dateObject;
          if(angular.isDefined(date) && date !== null){

            if(typeof date === 'string'){
              if(date.length !== 10){ return false; }

              if(!isTouch && !/^(?:(?:31(\/)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/.test(date)){return false;}

              dateObject = dateCalculator.getDate(date, format);
            }else if(angular.isDate(date)){
              dateObject = date;
            }else if(typeof date === 'function'){
              return validFormat(date(),format);
            }else {
              return false;
            }

            return dateObject.toString()!=='Invalid Date';
          }
        }

        var isRequired = (function(){
          if(attr.require === 'true'){
            return true;
          }else{
            return false;
          }
        })();
        var noErrorClass = 'hide-error';
        var errorElem = $(elem.find('.faux-input')[0]);

        function checkValidity(value){
          var stringValue;
          if(value != 'Invalid Date' && angular.isDate(value)){
            stringValue = dateCalculator.format(value,dateformat);
          }else{
            stringValue = value;
          }

          safeApply(scope,function(){

            if(angular.isDate(scope.minDate)){
              if(dateCalculator.dateBeforeOther(value,scope.minDate)){
                ngControl.$setValidity('date-min',true);
                errorElem.addClass(noErrorClass);
              }else{
                ngControl.$setValidity('date-min',false);
                errorElem.removeClass(noErrorClass);
              }

            }
            if(angular.isDate(scope.maxDate)){
              if(dateCalculator.dateBeforeOther(scope.maxDate,value)){
                ngControl.$setValidity('date-max',true);
                errorElem.addClass(noErrorClass);
              }else{
                ngControl.$setValidity('date-max',false);
                errorElem.removeClass(noErrorClass);
              }
            }

            if(validFormat(stringValue,dateformat)){
              ngControl.$setValidity('date',true);
              errorElem.addClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',true);
                errorElem.addClass(noErrorClass);
              }
            }else if(stringValue !== config.placeholder && stringValue !== null){
              ngControl.$setValidity('date',false);
              ngControl.$setValidity('date-min',true);
              ngControl.$setValidity('date-max',true);
              errorElem.removeClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',true);
              }
            }else{
              ngControl.$setValidity('date',true);
              ngControl.$setValidity('date-min',true);
              ngControl.$setValidity('date-max',true);
              errorElem.addClass(noErrorClass);
              if(isRequired){
                ngControl.$setValidity('date-required',false);
                errorElem.removeClass(noErrorClass);
              }
            }

          });
        }
        var myWatch = 0;
 //format text going to user (model to view)
        scope.$watch('$parent.'+ attr.ngModel, function(newVal,oldval) {
          if(myWatch === 0){
            if(!isTouch || isTouch && newVal !== ''){
              if(newVal != 'Invalid Date' && angular.isDate(newVal)){
                var date = dateCalculator.format(newVal,dateformat);
                controller.setValue(date,null,isTouch);
                checkValidity(newVal);
              }else{
                controller.setValue(null,null,isTouch);
              }
            }else{
               controller.setValue('',null,isTouch);
            }
            checkValidity(newVal);
          }else{
            myWatch = 0;
          }
        }, true);

        controller.init(element,config,form,ngControl);

         /* ngControl.$formatters.push(function(modelValue) {

          });
*/

          //format text from the user (view to model)
          ngControl.$parsers.unshift(function(value) {

              if(isTouch && value === ''){
                value = element.val();
              }

            if(value === null || value === ''){
              return value;
            }else if(typeof value === 'string'){
              controller.setValue(value,null,isTouch);
              return dateCalculator.getDate(value,dateformat);
            }else{
              return null;
            }
          });
          element.unbind('input').unbind('change');

          //on blur update the model.
          element.on('blur', function() {
            safeApply(scope,function(){
              var value;
              if(isTouch){
                value = element.val();
              }else{
                value = controller.getValue();
              }
              if(value === config.placeholder){
                checkValidity(value);
                ngControl.$setViewValue(null);
              }else{
                var date = dateCalculator.getDate(value,dateformat);
                if(date === null){
                  checkValidity(value);
                }else{
                  checkValidity(date);
                }
                //fires 2 watches !
                //ngControl.$setViewValue(value);
                ngControl.$setDirty();
                ngControl.$render();
              }
              var date = $(elem.html()).contents().contents().unwrap()[0].wholeText;
                  if(!validFormat(date,dateformat)){
                    myWatch = 1;
                    controller.setValue(date);
                  }
            });
          });
      }
    };

  }
};
}]);
})();<|endoftext|>