<commit_before>angular.module('Aggie')
    .directive('clockVisualization', [
        'VisualizationDataFormatter',
        function(VisualizationDataFormatter) {
            return {
                restrict:'E',
                link: function($scope, element, attributes) {
                    var radians = 0.0174532925,
                        clockRadius = 200,
                        margin = 120,
                        width = (clockRadius+margin)*2,
                        height = (clockRadius+margin)*2,
                        minuteHandLength = clockRadius,
                        secondHandLength = clockRadius-12,
                        secondHandBalance = 30,
                        secondTickStart = clockRadius,
                    secondTickLength = -10,
                    secondLabelRadius = clockRadius + 16,
                    secondLabelYOffset = 5;

                    var graphDataStart = clockRadius + 25,
                        graphDatalength = 30,
                        minGraphStart = clockRadius - 100;

                    var minuteScale = secondScale = d3.scale.linear()
                        .range([0,354])
                        .domain([0,59]);

                    var handData = [
                        {
                            type:'minute',
                            value:0,
                            length:-minuteHandLength,
                            scale:minuteScale
                        },
                        {
                            type:'second',
                            value:0,
                            length:-secondHandLength,
                            scale:secondScale,
                            balance:secondHandBalance
                        }
                    ];

                    function drawClock(){ //create all the clock elements
                        updateData();	//draw them in the correct starting position
                        var svg = d3.select(element[0]).append("svg")
                            .attr("width", width)
                            .attr("height", height);

                        var face = svg.append('g')
                            .attr('id','clock-face')
                            .attr('transform','translate(' + (clockRadius + margin) + ',' + (clockRadius + margin) + ')');

                        //add marks for seconds
                        face.selectAll('.second-tick')
                            .data(d3.range(0,60)).enter()
                            .append('line')
                            .attr('class', 'second-tick')
                            .attr('x1',0)
                            .attr('x2',0)
                            .attr('y1',secondTickStart)
                            .attr('y2',secondTickStart + secondTickLength)
                            .attr('transform',function(d){
                                return 'rotate(' + secondScale(d) + ')';
                            });
                        //and labels

                        face.selectAll('.second-label')
                            .data(d3.range(5,61,5))
                            .enter()
                            .append('text')
                            .attr('class', 'second-label')
                            .attr('text-anchor','middle')
                            .attr('x',function(d){
                                return secondLabelRadius*Math.sin(secondScale(d)*radians);
                            })
                            .attr('y',function(d){
                                return -secondLabelRadius*Math.cos(secondScale(d)*radians) + secondLabelYOffset;
                            })
                            .text(function(d){
                                return d;
                            });

                        renderReportsGraph();

                        var hands = face.append('g').attr('id','clock-hands');

                        face.append('g').attr('id','face-overlay')
                            .append('circle').attr('class','hands-cover')
                            .attr('x',0)
                            .attr('y',0)
                            .attr('r',clockRadius/20);

                        hands.selectAll('line')
                            .data(handData)
                            .enter()
                            .append('line')
                            .attr('class', function(d){
                                return d.type + '-hand';
                            })
                            .attr('x1',0)
                            .attr('y1',function(d){
                                return d.balance ? d.balance : 0;
                            })
                            .attr('x2',0)
                            .attr('y2',function(d){
                                return d.length;
                            })
                            .attr('transform',function(d){
                                return 'rotate('+ d.scale(d.value) +')';
                            });
                    }

                    function moveHands(){
                        d3.select('#clock-hands').selectAll('line')
                            .data(handData)
                            .transition()
                            .attr('transform',function(d){
                                return 'rotate('+ d.scale(d.value) +')';
                            });
                    }

                    function updateData(){
                        var t = new Date();
                        handData[0].value = t.getMinutes();
                        handData[1].value = t.getSeconds();
                    }

                    drawClock();

                    setInterval(function(){
                        updateData();
                        moveHands();
                        renderReportsGraph();
                    }, 1000);

                    d3.select(self.frameElement).style("height", height + "px");

                    function renderReportsGraph() {
                        if(handData[1].value == 0 ){
                            //clear seconds data
                            d3.select('#clock-face').selectAll('.reports-data.sec').remove();
                            renderMinReportsGraph();
                        }
                        var secReportsData = formatData(getReportPerSecond(handData[1].value));

                        var graphScale = d3.scale.linear()
                            .range([0, graphDatalength])
                            .domain([0,( d3.max(secReportsData[0].data, function(d){
                                return d.value;
                            }))]);

                        var secReport = d3.select('#clock-face').selectAll('reports-data sec')
                            .data(secReportsData).enter()
                            .append('g')
                            .attr('class', 'reports-data sec')
                            .attr('x1', 0)
                            .attr('x2', 0)
                            .attr('y1', graphDataStart)
                            .attr('y2', graphDataStart + graphDatalength)
                            .attr('transform',function(report){
                                return 'rotate(' + (180 + (6 * (report.second - 1))) + ')';
                            });

                        secReport.selectAll('rect')
                            .data(function(d){ return d.data}).enter()
                            .append('rect')
                            .attr('width', 10)
                            .attr('x', -5)
                            .attr('class', function(d) {
                                switch (d.type) {
                                    case 'facebook':
                                        return 'facebook-source';
                                    case 'twitter':
                                        return 'twitter-source';
                                    case 'elmo':
                                        return 'elmo-source';
                                    case 'rss':
                                        return 'rss-source';
                                    default:
                                        return 'unknown-source';
                                }
                            })
                            .attr('y', function(d) {
                                return graphDataStart + graphScale(d.y0);
                            })
                            .attr("height", function(d) {
                                return (graphScale(d.y1) - graphScale(d.y0));
                            });

                    }

                    function renderMinReportsGraph() {
                        var minReportsData = formatData(getReportPerMinute(handData[0].value));

                        var graphScale = d3.scale.linear()
                            .range([graphDatalength, 0])
                            .domain([0,( d3.max(minReportsData[0].data, function(d){
                                return d.value;
                            }))]);

                        var minReport = d3.select('#clock-face').selectAll('reports-data min')
                            .data(minReportsData).enter()
                            .append('g')
                            .attr('class', 'reports-data min')
                            .attr('x1', 0)
                            .attr('x2', 0)
                            .attr('y1', minGraphStart)
                            .attr('y2', minGraphStart - graphDatalength)
                            .attr('transform',function(report){
                                return 'rotate(' + (180 + (6 * (report.minute - 1))) + ')';
                            });

                        minReport.selectAll('rect')
                            .data(function(d){ return d.data}).enter()
                            .append('rect')
                            .attr('width', 10)
                            .attr('x', -5)
                            .attr('class', function(d) {
                                switch (d.type) {
                                    case 'facebook':
                                        return 'facebook-source';
                                    case 'twitter':
                                        return 'twitter-source';
                                    case 'elmo':
                                        return 'elmo-source';
                                    case 'rss':
                                        return 'rss-source';
                                    default:
                                        return 'unknown-source';
                                }
                            })
                            .attr('y', function(d) {
                                return minGraphStart - graphScale(d.y0);
                            })
                            .attr("height", function(d) {
                                return -(graphScale(d.y1) - graphScale(d.y0));
                            });
                    }

                    function getReportPerSecond(second){

                        return [{
                            second: second,
                            minute: 0,
                            hour: 0,
                            data: [
                                {
                                    type: 'twitter',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'rss',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'elmo',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'facebook',
                                    value: Math.floor(Math.random() * 1000) + 1
                                }
                            ]
                        }]

                    }

                    function getReportPerMinute(minute){

                        return [{
                            second: 0,
                            minute: minute,
                            hour: 0,
                            data: [
                                {
                                    type: 'twitter',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'rss',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'elmo',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'facebook',
                                    value: Math.floor(Math.random() * 1000) + 1
                                }
                            ]
                        }]

                    }
                    function formatData(data){
                        data[0].data.sort(function(a, b) {
                            return a.value - b.value;
                        });

                        var y0 = 0;
                        data[0].data =  data[0].data.map(function(report) {
                            return {
                                type: report.type,
                                value: report.value,
                                y0: y0,
                                y1: y0 += report.value
                            }
                        });

                        return data;
                    }
                }
            }
    }]);<commit_msg>reset mins on 60 min mark<commit_after>angular.module('Aggie')
    .directive('clockVisualization', [
        'VisualizationDataFormatter',
        function(VisualizationDataFormatter) {
            return {
                restrict:'E',
                link: function($scope, element, attributes) {
                    var radians = 0.0174532925,
                        clockRadius = 200,
                        margin = 120,
                        width = (clockRadius+margin)*2,
                        height = (clockRadius+margin)*2,
                        minuteHandLength = clockRadius,
                        secondHandLength = clockRadius-12,
                        secondHandBalance = 30,
                        secondTickStart = clockRadius,
                    secondTickLength = -10,
                    secondLabelRadius = clockRadius + 16,
                    secondLabelYOffset = 5;

                    var graphDataStart = clockRadius + 25,
                        graphDatalength = 30,
                        minGraphStart = clockRadius - 100;

                    var minuteScale = secondScale = d3.scale.linear()
                        .range([0,354])
                        .domain([0,59]);

                    var handData = [
                        {
                            type:'minute',
                            value:0,
                            length:-minuteHandLength,
                            scale:minuteScale
                        },
                        {
                            type:'second',
                            value:0,
                            length:-secondHandLength,
                            scale:secondScale,
                            balance:secondHandBalance
                        }
                    ];

                    function drawClock(){ //create all the clock elements
                        updateData();	//draw them in the correct starting position
                        var svg = d3.select(element[0]).append("svg")
                            .attr("width", width)
                            .attr("height", height);

                        var face = svg.append('g')
                            .attr('id','clock-face')
                            .attr('transform','translate(' + (clockRadius + margin) + ',' + (clockRadius + margin) + ')');

                        //add marks for seconds
                        face.selectAll('.second-tick')
                            .data(d3.range(0,60)).enter()
                            .append('line')
                            .attr('class', 'second-tick')
                            .attr('x1',0)
                            .attr('x2',0)
                            .attr('y1',secondTickStart)
                            .attr('y2',secondTickStart + secondTickLength)
                            .attr('transform',function(d){
                                return 'rotate(' + secondScale(d) + ')';
                            });
                        //and labels

                        face.selectAll('.second-label')
                            .data(d3.range(5,61,5))
                            .enter()
                            .append('text')
                            .attr('class', 'second-label')
                            .attr('text-anchor','middle')
                            .attr('x',function(d){
                                return secondLabelRadius*Math.sin(secondScale(d)*radians);
                            })
                            .attr('y',function(d){
                                return -secondLabelRadius*Math.cos(secondScale(d)*radians) + secondLabelYOffset;
                            })
                            .text(function(d){
                                return d;
                            });

                        renderReportsGraph();

                        var hands = face.append('g').attr('id','clock-hands');

                        face.append('g').attr('id','face-overlay')
                            .append('circle').attr('class','hands-cover')
                            .attr('x',0)
                            .attr('y',0)
                            .attr('r',clockRadius/20);

                        hands.selectAll('line')
                            .data(handData)
                            .enter()
                            .append('line')
                            .attr('class', function(d){
                                return d.type + '-hand';
                            })
                            .attr('x1',0)
                            .attr('y1',function(d){
                                return d.balance ? d.balance : 0;
                            })
                            .attr('x2',0)
                            .attr('y2',function(d){
                                return d.length;
                            })
                            .attr('transform',function(d){
                                return 'rotate('+ d.scale(d.value) +')';
                            });
                    }

                    function moveHands(){
                        d3.select('#clock-hands').selectAll('line')
                            .data(handData)
                            .transition()
                            .attr('transform',function(d){
                                return 'rotate('+ d.scale(d.value) +')';
                            });
                    }

                    function updateData(){
                        var t = new Date();
                        handData[0].value = t.getMinutes();
                        handData[1].value = t.getSeconds();
                    }

                    drawClock();

                    setInterval(function(){
                        updateData();
                        moveHands();
                        renderReportsGraph();
                    }, 1000);

                    d3.select(self.frameElement).style("height", height + "px");

                    function renderReportsGraph() {
                        if(handData[1].value == 0 ){
                            //clear seconds data
                            d3.select('#clock-face').selectAll('.reports-data.sec').remove();
                            renderMinReportsGraph();
                        }
                        var secReportsData = formatData(getReportPerSecond(handData[1].value));

                        var graphScale = d3.scale.linear()
                            .range([0, graphDatalength])
                            .domain([0,( d3.max(secReportsData[0].data, function(d){
                                return d.value;
                            }))]);

                        var secReport = d3.select('#clock-face').selectAll('reports-data sec')
                            .data(secReportsData).enter()
                            .append('g')
                            .attr('class', 'reports-data sec')
                            .attr('x1', 0)
                            .attr('x2', 0)
                            .attr('y1', graphDataStart)
                            .attr('y2', graphDataStart + graphDatalength)
                            .attr('transform',function(report){
                                return 'rotate(' + (180 + (6 * (report.second - 1))) + ')';
                            });

                        secReport.selectAll('rect')
                            .data(function(d){ return d.data}).enter()
                            .append('rect')
                            .attr('width', 10)
                            .attr('x', -5)
                            .attr('class', function(d) {
                                switch (d.type) {
                                    case 'facebook':
                                        return 'facebook-source';
                                    case 'twitter':
                                        return 'twitter-source';
                                    case 'elmo':
                                        return 'elmo-source';
                                    case 'rss':
                                        return 'rss-source';
                                    default:
                                        return 'unknown-source';
                                }
                            })
                            .attr('y', function(d) {
                                return graphDataStart + graphScale(d.y0);
                            })
                            .attr("height", function(d) {
                                return (graphScale(d.y1) - graphScale(d.y0));
                            });

                    }                     s

                    function renderMinReportsGraph() {
                        if(handData[0].value == 0){
                            d3.select('#clock-face').selectAll('.reports-data.min').remove();
                        }
                        var minReportsData = formatData(getReportPerMinute(handData[0].value));

                        var graphScale = d3.scale.linear()
                            .range([graphDatalength, 0])
                            .domain([0,( d3.max(minReportsData[0].data, function(d){
                                return d.value;
                            }))]);

                        var minReport = d3.select('#clock-face').selectAll('reports-data min')
                            .data(minReportsData).enter()
                            .append('g')
                            .attr('class', 'reports-data min')
                            .attr('x1', 0)
                            .attr('x2', 0)
                            .attr('y1', minGraphStart)
                            .attr('y2', minGraphStart - graphDatalength)
                            .attr('transform',function(report){
                                return 'rotate(' + (180 + (6 * (report.minute - 1))) + ')';
                            });

                        minReport.selectAll('rect')
                            .data(function(d){ return d.data}).enter()
                            .append('rect')
                            .attr('width', 10)
                            .attr('x', -5)
                            .attr('class', function(d) {
                                switch (d.type) {
                                    case 'facebook':
                                        return 'facebook-source';
                                    case 'twitter':
                                        return 'twitter-source';
                                    case 'elmo':
                                        return 'elmo-source';
                                    case 'rss':
                                        return 'rss-source';
                                    default:
                                        return 'unknown-source';
                                }
                            })
                            .attr('y', function(d) {
                                return minGraphStart - graphScale(d.y0);
                            })
                            .attr("height", function(d) {
                                return -(graphScale(d.y1) - graphScale(d.y0));
                            });
                    }

                    function getReportPerSecond(second){

                        return [{
                            second: second,
                            minute: 0,
                            hour: 0,
                            data: [
                                {
                                    type: 'twitter',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'rss',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'elmo',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'facebook',
                                    value: Math.floor(Math.random() * 1000) + 1
                                }
                            ]
                        }]

                    }

                    function getReportPerMinute(minute){

                        return [{
                            second: 0,
                            minute: minute,
                            hour: 0,
                            data: [
                                {
                                    type: 'twitter',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'rss',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'elmo',
                                    value: Math.floor(Math.random() * 1000) + 1
                                },
                                {
                                    type: 'facebook',
                                    value: Math.floor(Math.random() * 1000) + 1
                                }
                            ]
                        }]

                    }
                    function formatData(data){
                        data[0].data.sort(function(a, b) {
                            return a.value - b.value;
                        });

                        var y0 = 0;
                        data[0].data =  data[0].data.map(function(report) {
                            return {
                                type: report.type,
                                value: report.value,
                                y0: y0,
                                y1: y0 += report.value
                            }
                        });

                        return data;
                    }
                }
            }
    }]);<|endoftext|>


<commit_before>define([
  'angular',
  'lodash',
  'app/core/utils/kbn',
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.services');

  module.service('templateValuesSrv', function($q, $rootScope, datasourceSrv, $location, templateSrv, timeSrv) {
    var self = this;

    function getNoneOption() { return { text: 'None', value: '', isNone: true }; }

    $rootScope.onAppEvent('time-range-changed', function()  {
      var variable = _.findWhere(self.variables, { type: 'interval' });
      if (variable) {
        self.updateAutoInterval(variable);
      }
    }, $rootScope);

    this.init = function(dashboard) {
      this.variables = dashboard.templating.list;
      templateSrv.init(this.variables);

      var queryParams = $location.search();
      var promises = [];

      //use promises to delay processing variables that
      //depend on other variables.
      this.variableLock = {};
      var self = this;
      _.forEach(this.variables, function(variable) {
        self.variableLock[variable.name] = $q.defer();
      });

      for (var i = 0; i < this.variables.length; i++) {
        var variable = this.variables[i];
        promises.push(this.processVariable(variable, queryParams));
      }

      return $q.all(promises);
    };

    this.processVariable = function(variable, queryParams) {
      var dependencies = [];
      var self = this;
      // determine our dependencies.
      if (variable.type === "query") {
        _.forEach(this.variables, function(v) {
          if (templateSrv.containsVariable(variable.query, v.name)) {
            dependencies.push(self.variableLock[v.name].promise);
          }
        });
      }
      return $q.all(dependencies).then(function() {
        var variableName = variable.name;
        var urlValue = queryParams['var-' + variable.name];
        if (urlValue !== void 0) {
          return self.setVariableFromUrl(variable, urlValue).then(function() {
            self.variableLock[variableName].resolve();
          });
        }
        else if (variable.refresh) {
          return self.updateOptions(variable).then(function() {
            if (_.isEmpty(variable.current) && variable.options.length) {
              console.log("setting current for %s", variable.name);
              self.setVariableValue(variable, variable.options[0], true);
            }
            self.variableLock[variableName].resolve();
          });
        }
        else if (variable.type === 'interval') {
          self.updateAutoInterval(variable);
          self.variableLock[variableName].resolve();
        } else {
          self.variableLock[variableName].resolve();
        }
      });
    };

    this.setVariableFromUrl = function(variable, urlValue) {
      if (variable.refresh) {
        var self = this;
        //refresh the list of options before setting the value
        return this.updateOptions(variable).then(function() {
          var option = _.findWhere(variable.options, { text: urlValue });
          option = option || { text: urlValue, value: urlValue };

          self.updateAutoInterval(variable);
          return self.setVariableValue(variable, option, true);
        });
      }
      var option = _.findWhere(variable.options, { text: urlValue });
      option = option || { text: urlValue, value: urlValue };

      this.updateAutoInterval(variable);
      return this.setVariableValue(variable, option, true);
    };

    this.updateAutoInterval = function(variable) {
      if (!variable.auto) { return; }

      // add auto option if missing
      if (variable.options.length && variable.options[0].text !== 'auto') {
        variable.options.unshift({ text: 'auto', value: '$__auto_interval' });
      }

      var interval = kbn.calculateInterval(timeSrv.timeRange(), variable.auto_count, (variable.auto_min ? ">"+variable.auto_min : null));
      templateSrv.setGrafanaVariable('$__auto_interval', interval);
    };

    this.setVariableValue = function(variable, option, firstLoad) {
      variable.current = angular.copy(option);

      if (_.isArray(variable.current.value)) {
        variable.current.text = variable.current.value.join(' + ');
      }

      self.selectOptionsForCurrentValue(variable);

      templateSrv.updateTemplateData();
      // on first load, variable loading is ordered to ensure
      // that parents are updated before children.
      if (firstLoad) {
        return $q.when();
      }
      return self.updateOptionsInChildVariables(variable);
    };

    this.variableUpdated = function(variable) {
      templateSrv.updateTemplateData();
      return this.updateOptionsInChildVariables(variable);
    };

    this.updateOptionsInChildVariables = function(updatedVariable) {
      var promises = _.map(self.variables, function(otherVariable) {
        if (otherVariable === updatedVariable) {
          return;
        }
        if (templateSrv.containsVariable(otherVariable.query, updatedVariable.name)) {
          return self.updateOptions(otherVariable);
        }
      });

      return $q.all(promises);
    };

    this._updateNonQueryVariable = function(variable) {
      // extract options in comma seperated string
      variable.options = _.map(variable.query.split(/[,]+/), function(text) {
        return { text: text.trim(), value: text.trim() };
      });

      if (variable.type === 'interval') {
        self.updateAutoInterval(variable);
      }

      if (variable.type === 'custom' && variable.includeAll) {
        self.addAllOption(variable);
      }
    };

    this.updateOptions = function(variable) {
      if (variable.type !== 'query') {
        self._updateNonQueryVariable(variable);
        self.setVariableValue(variable, variable.options[0]);
        return $q.when([]);
      }

      return datasourceSrv.get(variable.datasource)
        .then(_.partial(this.updateOptionsFromMetricFindQuery, variable))
        .then(_.partial(this.updateTags, variable));
    };

    this.selectOptionsForCurrentValue = function(variable) {
      var i, y, value, option;

      for (i = 0; i < variable.options.length; i++) {
        option = variable.options[i];
        option.selected = false;
        if (_.isArray(variable.current.value)) {
          for (y = 0; y < variable.current.value.length; y++) {
            value = variable.current.value[y];
            if (option.value === value) {
              option.selected = true;
            }
          }
        } else if (option.value === variable.current.value) {
          option.selected = true;
        }
      }
    };

    this.validateVariableSelectionState = function(variable) {
      if (!variable.current) {
        if (!variable.options.length) { return; }
        return self.setVariableValue(variable, variable.options[0]);
      }

      if (_.isArray(variable.current.value)) {
        self.selectOptionsForCurrentValue(variable);
      } else {
        var currentOption = _.findWhere(variable.options, { text: variable.current.text });
        if (currentOption) {
          return self.setVariableValue(variable, currentOption);
        } else {
          if (!variable.options.length) { return; }
          return self.setVariableValue(variable, variable.options[0]);
        }
      }
    };

    this.updateTags = function(variable, datasource) {
      if (variable.useTags) {
        return datasource.metricFindQuery(variable.tagsQuery).then(function (results) {
          variable.tags = [];
          for (var i = 0; i < results.length; i++) {
            variable.tags.push(results[i].text);
          }
          return datasource;
        });
      } else {
        delete variable.tags;
      }

      return datasource;
    };

    this.updateOptionsFromMetricFindQuery = function(variable, datasource) {
      return datasource.metricFindQuery(variable.query).then(function (results) {
        variable.options = self.metricNamesToVariableValues(variable, results);
        if (variable.includeAll) {
          self.addAllOption(variable);
        }
        if (!variable.options.length) {
          variable.options.push(getNoneOption());
        }
        return datasource;
      });
    };

    this.getValuesForTag = function(variable, tagKey) {
      return datasourceSrv.get(variable.datasource).then(function(datasource) {
        var query = variable.tagValuesQuery.replace('$tag', tagKey);
        return datasource.metricFindQuery(query).then(function (results) {
          return _.map(results, function(value) {
            return value.text;
          });
        });
      });
    };

    this.metricNamesToVariableValues = function(variable, metricNames) {
      var regex, options, i, matches;
      options = {}; // use object hash to remove duplicates

      if (variable.regex) {
        regex = kbn.stringToJsRegex(templateSrv.replace(variable.regex));
      }

      for (i = 0; i < metricNames.length; i++) {
        var value = metricNames[i].text;

        if (regex) {
          matches = regex.exec(value);
          if (!matches) { continue; }
          if (matches.length > 1) {
            value = matches[1];
          }
        }

        options[value] = value;
      }

      return _.map(_.keys(options).sort(), function(key) {
        var option = { text: key, value: key };
        return option;
      });
    };

    this.addAllOption = function(variable) {
      if (variable.allValue) {
        variable.options.unshift({text: 'All', value: variable.allValue});
        return;
      }

      variable.options.unshift({text: 'All', value: "$__all"});
    };

  });

});
<commit_msg>fix(templaing): refactoring PR #4283<commit_after>define([
  'angular',
  'lodash',
  'app/core/utils/kbn',
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.services');

  module.service('templateValuesSrv', function($q, $rootScope, datasourceSrv, $location, templateSrv, timeSrv) {
    var self = this;

    function getNoneOption() { return { text: 'None', value: '', isNone: true }; }

    $rootScope.onAppEvent('time-range-changed', function()  {
      var variable = _.findWhere(self.variables, { type: 'interval' });
      if (variable) {
        self.updateAutoInterval(variable);
      }
    }, $rootScope);

    this.init = function(dashboard) {
      this.variables = dashboard.templating.list;
      templateSrv.init(this.variables);

      var queryParams = $location.search();
      var promises = [];

      // use promises to delay processing variables that
      // depend on other variables.
      this.variableLock = {};
      _.forEach(this.variables, function(variable) {
        self.variableLock[variable.name] = $q.defer();
      });

      for (var i = 0; i < this.variables.length; i++) {
        var variable = this.variables[i];
        promises.push(this.processVariable(variable, queryParams));
      }

      return $q.all(promises);
    };

    this.processVariable = function(variable, queryParams) {
      var dependencies = [];
      var lock = self.variableLock[variable.name];

      // determine our dependencies.
      if (variable.type === "query") {
        _.forEach(this.variables, function(v) {
          if (templateSrv.containsVariable(variable.query, v.name)) {
            dependencies.push(self.variableLock[v.name].promise);
          }
        });
      }

      return $q.all(dependencies).then(function() {
        var urlValue = queryParams['var-' + variable.name];
        if (urlValue !== void 0) {
          return self.setVariableFromUrl(variable, urlValue).then(lock.resolve);
        }
        else if (variable.refresh) {
          return self.updateOptions(variable).then(function() {
            if (_.isEmpty(variable.current) && variable.options.length) {
              console.log("setting current for %s", variable.name);
              self.setVariableValue(variable, variable.options[0]);
            }
            lock.resolve();
          });
        }
        else if (variable.type === 'interval') {
          self.updateAutoInterval(variable);
          lock.resolve();
        } else {
          lock.resolve();
        }
      });
    };

    this.setVariableFromUrl = function(variable, urlValue) {
      var promise = $q.when(true);

      if (variable.refresh) {
        promise = this.updateOptions(variable);
      }

      return promise.then(function() {
        var option = _.findWhere(variable.options, { text: urlValue });
        option = option || { text: urlValue, value: urlValue };

        self.updateAutoInterval(variable);
        return self.setVariableValue(variable, option, true);
      });
    };

    this.updateAutoInterval = function(variable) {
      if (!variable.auto) { return; }

      // add auto option if missing
      if (variable.options.length && variable.options[0].text !== 'auto') {
        variable.options.unshift({ text: 'auto', value: '$__auto_interval' });
      }

      var interval = kbn.calculateInterval(timeSrv.timeRange(), variable.auto_count, (variable.auto_min ? ">"+variable.auto_min : null));
      templateSrv.setGrafanaVariable('$__auto_interval', interval);
    };

    this.setVariableValue = function(variable, option, initPhase) {
      variable.current = angular.copy(option);

      if (_.isArray(variable.current.value)) {
        variable.current.text = variable.current.value.join(' + ');
      }

      self.selectOptionsForCurrentValue(variable);
      templateSrv.updateTemplateData();

      // on first load, variable loading is ordered to ensure
      // that parents are updated before children.
      if (initPhase) {
        return $q.when();
      }

      return self.updateOptionsInChildVariables(variable);
    };

    this.variableUpdated = function(variable) {
      templateSrv.updateTemplateData();
      return this.updateOptionsInChildVariables(variable);
    };

    this.updateOptionsInChildVariables = function(updatedVariable) {
      var promises = _.map(self.variables, function(otherVariable) {
        if (otherVariable === updatedVariable) {
          return;
        }
        if (templateSrv.containsVariable(otherVariable.query, updatedVariable.name)) {
          return self.updateOptions(otherVariable);
        }
      });

      return $q.all(promises);
    };

    this._updateNonQueryVariable = function(variable) {
      // extract options in comma seperated string
      variable.options = _.map(variable.query.split(/[,]+/), function(text) {
        return { text: text.trim(), value: text.trim() };
      });

      if (variable.type === 'interval') {
        self.updateAutoInterval(variable);
      }

      if (variable.type === 'custom' && variable.includeAll) {
        self.addAllOption(variable);
      }
    };

    this.updateOptions = function(variable) {
      if (variable.type !== 'query') {
        self._updateNonQueryVariable(variable);
        self.setVariableValue(variable, variable.options[0]);
        return $q.when([]);
      }

      return datasourceSrv.get(variable.datasource)
        .then(_.partial(this.updateOptionsFromMetricFindQuery, variable))
        .then(_.partial(this.updateTags, variable))
        .then(_.partial(this.validateVariableSelectionState, variable));
    };

    this.selectOptionsForCurrentValue = function(variable) {
      var i, y, value, option;

      for (i = 0; i < variable.options.length; i++) {
        option = variable.options[i];
        option.selected = false;
        if (_.isArray(variable.current.value)) {
          for (y = 0; y < variable.current.value.length; y++) {
            value = variable.current.value[y];
            if (option.value === value) {
              option.selected = true;
            }
          }
        } else if (option.value === variable.current.value) {
          option.selected = true;
        }
      }
    };

    this.validateVariableSelectionState = function(variable) {
      if (!variable.current) {
        if (!variable.options.length) { return; }
        return self.setVariableValue(variable, variable.options[0], true);
      }

      if (_.isArray(variable.current.value)) {
        self.selectOptionsForCurrentValue(variable);
      } else {
        var currentOption = _.findWhere(variable.options, { text: variable.current.text });
        if (currentOption) {
          return self.setVariableValue(variable, currentOption, true);
        } else {
          if (!variable.options.length) { return; }
          return self.setVariableValue(variable, variable.options[0]);
        }
      }
    };

    this.updateTags = function(variable, datasource) {
      if (variable.useTags) {
        return datasource.metricFindQuery(variable.tagsQuery).then(function (results) {
          variable.tags = [];
          for (var i = 0; i < results.length; i++) {
            variable.tags.push(results[i].text);
          }
          return datasource;
        });
      } else {
        delete variable.tags;
      }

      return datasource;
    };

    this.updateOptionsFromMetricFindQuery = function(variable, datasource) {
      return datasource.metricFindQuery(variable.query).then(function (results) {
        variable.options = self.metricNamesToVariableValues(variable, results);
        if (variable.includeAll) {
          self.addAllOption(variable);
        }
        if (!variable.options.length) {
          variable.options.push(getNoneOption());
        }
        return datasource;
      });
    };

    this.getValuesForTag = function(variable, tagKey) {
      return datasourceSrv.get(variable.datasource).then(function(datasource) {
        var query = variable.tagValuesQuery.replace('$tag', tagKey);
        return datasource.metricFindQuery(query).then(function (results) {
          return _.map(results, function(value) {
            return value.text;
          });
        });
      });
    };

    this.metricNamesToVariableValues = function(variable, metricNames) {
      var regex, options, i, matches;
      options = {}; // use object hash to remove duplicates

      if (variable.regex) {
        regex = kbn.stringToJsRegex(templateSrv.replace(variable.regex));
      }

      for (i = 0; i < metricNames.length; i++) {
        var value = metricNames[i].text;

        if (regex) {
          matches = regex.exec(value);
          if (!matches) { continue; }
          if (matches.length > 1) {
            value = matches[1];
          }
        }

        options[value] = value;
      }

      return _.map(_.keys(options).sort(), function(key) {
        var option = { text: key, value: key };
        return option;
      });
    };

    this.addAllOption = function(variable) {
      if (variable.allValue) {
        variable.options.unshift({text: 'All', value: variable.allValue});
        return;
      }

      variable.options.unshift({text: 'All', value: "$__all"});
    };

  });

});
<|endoftext|>


<commit_before>// @flow

import qs from 'query-string'

import {IS_PRODUCTION} from '@frogpond/constants'

let root: string

export function setApiRoot(url: string) {
	root = url
}

export const API = (path: string, query: ?unknown = null) => {
	if (!IS_PRODUCTION) {
		if (!path.startsWith('/')) {
			throw new Error('invalid path requested from the api!')
		}
	}

	let url = root + path

	if (query) {
		url += `?${qs.stringify(query)}`
	}

	return url
}
<commit_msg>m/api: Remove // @flow annotation<commit_after>import qs from 'query-string'

import {IS_PRODUCTION} from '@frogpond/constants'

let root: string

export function setApiRoot(url: string) {
	root = url
}

export const API = (path: string, query: ?unknown = null) => {
	if (!IS_PRODUCTION) {
		if (!path.startsWith('/')) {
			throw new Error('invalid path requested from the api!')
		}
	}

	let url = root + path

	if (query) {
		url += `?${qs.stringify(query)}`
	}

	return url
}
<|endoftext|>


<commit_before>/*
 * Lunchpad user provider
 *
 * @author Markus Riegel <riegel.markius@googlemail.com>
 */

var db = require('./module.dbase.js').dBase,
	hash = require('password-hash');
	cn = 'user';

var UserProvider = function(){
	db.gc(cn, function(collection){

		collection.ensureIndex('mail',{unique:true},function(error,indexName){
			if(error) console.log(error);
		});

	},function(error){ console.log(error); });
};

/*
 *
 */

UserProvider.prototype.findAll = function(onSuccess, onError){
	b.gc(cn, function(collection){

		collection.find({},{
			fields: {
				_id:1,
				mail:1,
				nick:1,
				ava:1,
				item:1,
				role:1
			}
		}).toArray(function(error,users){
			if(error) onError(error);
			else onSuccess(users);
		});

	},onError);
}

/*
 * Find user by mongo id
 */

UserProvider.prototype.findUser = function(id, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.findOne({
			_id: db.oID(id)
		},{},function(error,result){
			if(error) onError(error);
			else if(!result) onError('user not found!');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Find user by mail.
 */

UserProvider.prototype.findUserByMail = function(mail, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.findOne({
			mail: mail
		},{
			fields:{
				mail:1,
				nick:1,
				pass:1
			}
		},function(error,result){
			if(error) onError(error);
			else if(!result) onError('user not found!');
			else onSuccess(result);
		});

	},onError);
}

/*
* Find users who want to be reminded, but have not listed themselves yet.
*/

UserProvider.prototype.findUsersForReminder = function(exludeIds, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.find({
			_id: { $nin: exludeIds },
			'noti.remind': true
		},{
			fields:{
				mail: 1,
				nick: 1
			}
		}).toArray(function(error,result){
			if(error) onError(error);
			else onSuccess(result);
		});

	},onError);
}

/*
* Find users who want to get overview emails
*/

UserProvider.prototype.findUsersForOverview = function(onSuccess, onError){
	db.gc(cn, function(collection){

		collection.find({
			'noti.overv': true
		},{
			fields:{
				mail: 1,
				nick: 1
			}
		}).toArray(function(error,result){
			if(error) onError(error);
			else onSuccess(result);
		});

	},onError);
}

/*
 * Change the password
 */

UserProvider.prototype.updatePass = function(id, pass, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				pass: hash.generate( pass )
			}
		},{
			safe:true,
			multi:false
		},function(error,updates){
			if(error) onError(error);
			else if(!updates) onError('user not found.');
			else onSuccess(updates);
		});

	},onError);
}

/*
 * Add an item to the inventory list.
 */
/*
UserProvider.prototype.saveItemToInventory = function(id, item, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$push:{
				inv: item
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}
*/

/*
 * Update the inventory of a user
 */
UserProvider.prototype.updateInventoryById = function(id, inv, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				inv: inv
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Remove an item from all inventories.
 */

UserProvider.prototype.removeItemFromInventories = function(iid, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			inv:iid
		},{
			$pull:{
				inv:iid
			}
		},{
			multi:true, //only true so that in case of an error multiple entries will be removed
			save:true
		},function(error,updates){
			if(error) onError(error);
			else onSuccess(updates);
		});

	},onError);
}

/*
 * Make item active.
 */

UserProvider.prototype.updateAktiveItem = function(id, item, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({},{
			$pull:{
				inv: _id
			}
		},{
			safe:true,
			multi:true
		},function(error,results){
			if(error) onError(error);
			else onSuccess(results);
		});

	},onError);
}

/*
 * Adjust notification settings
 */

UserProvider.prototype.updateNoti = function(id, noti, onSuccess, onError){
	db.gc(cn, function(collection){

		if( noti.remind === undefined ||
			noti.overv === undefined){
			callback('params invalid');
			return null;
		}

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				noti: noti
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Ajust stats
 */

UserProvider.prototype.updateStats = function(id, stats, onSuccess, onError){
	db.gc(cn, function(collection){

		if( !stats.cihs ||
			!stats.cis){
			callback('params invalid');
			return null;
		}

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				stats: stats
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Delete user
 */

UserProvider.prototype.deleteUser = function(id, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.remove({
			_id: id
		},{
			safe: true
		},function(error,numRemoved){
			if(error) onError(error);
			else{
				console.log('User removed: '+numRemoved);
				onSuccess(numRemoved);
			}
		});

	},onError);
}

/*
 * Save a new row
 *
 * @param user { mail, nick, pass, ava }
 */

UserProvider.prototype.save = function(users, onSuccess, onError){
	db.gc(cn, function(collection){

		var i,
			user;

		if(users.length === undefined) users = [users];

		// expected values

		for(i=0;i<users.length;i++){

			user = users[i];

			if( !user.mail ||
				!user.nick ||
				!user.role ||
				!user.pass ||
				!user.ava ){
				onError('data incomplete');
				return;
			}

			// hash passwort
			user.pass = hash.generate( user.pass );
			console.log('generated hash');

			// add missing standard values
			user.item = null; // active item
			user.inv = []; // inventory (all items)

			user.noti = {
				remind: true,
				overv: true
			};
			user.stats = {
				cihs: 0,
				cis: 0
			};

		}

		console.log('for queue completed. users.lenth: '+users.length);

		collection.insert(users, function(error,results) {
			if(error) onError(error);
			else{
				console.log('User created: '+users.length);
				onSuccess(results);
			}
		});

	},onError);
}

exports.userProvider = new UserProvider();
<commit_msg>bug fix<commit_after>/*
 * Lunchpad user provider
 *
 * @author Markus Riegel <riegel.markius@googlemail.com>
 */

var db = require('./module.dbase.js').dBase,
	hash = require('password-hash');
	cn = 'user';

var UserProvider = function(){
	db.gc(cn, function(collection){

		collection.ensureIndex('mail',{unique:true},function(error,indexName){
			if(error) console.log(error);
		});

	},function(error){ console.log(error); });
};

/*
 *
 */

UserProvider.prototype.findAll = function(onSuccess, onError){
	db.gc(cn, function(collection){

		collection.find({},{
			fields: {
				_id:1,
				mail:1,
				nick:1,
				ava:1,
				item:1,
				role:1
			}
		}).toArray(function(error,users){
			if(error) onError(error);
			else onSuccess(users);
		});

	},onError);
}

/*
 * Find user by mongo id
 */

UserProvider.prototype.findUser = function(id, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.findOne({
			_id: db.oID(id)
		},{},function(error,result){
			if(error) onError(error);
			else if(!result) onError('user not found!');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Find user by mail.
 */

UserProvider.prototype.findUserByMail = function(mail, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.findOne({
			mail: mail
		},{
			fields:{
				mail:1,
				nick:1,
				pass:1
			}
		},function(error,result){
			if(error) onError(error);
			else if(!result) onError('user not found!');
			else onSuccess(result);
		});

	},onError);
}

/*
* Find users who want to be reminded, but have not listed themselves yet.
*/

UserProvider.prototype.findUsersForReminder = function(exludeIds, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.find({
			_id: { $nin: exludeIds },
			'noti.remind': true
		},{
			fields:{
				mail: 1,
				nick: 1
			}
		}).toArray(function(error,result){
			if(error) onError(error);
			else onSuccess(result);
		});

	},onError);
}

/*
* Find users who want to get overview emails
*/

UserProvider.prototype.findUsersForOverview = function(onSuccess, onError){
	db.gc(cn, function(collection){

		collection.find({
			'noti.overv': true
		},{
			fields:{
				mail: 1,
				nick: 1
			}
		}).toArray(function(error,result){
			if(error) onError(error);
			else onSuccess(result);
		});

	},onError);
}

/*
 * Change the password
 */

UserProvider.prototype.updatePass = function(id, pass, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				pass: hash.generate( pass )
			}
		},{
			safe:true,
			multi:false
		},function(error,updates){
			if(error) onError(error);
			else if(!updates) onError('user not found.');
			else onSuccess(updates);
		});

	},onError);
}

/*
 * Add an item to the inventory list.
 */
/*
UserProvider.prototype.saveItemToInventory = function(id, item, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$push:{
				inv: item
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}
*/

/*
 * Update the inventory of a user
 */
UserProvider.prototype.updateInventoryById = function(id, inv, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				inv: inv
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Remove an item from all inventories.
 */

UserProvider.prototype.removeItemFromInventories = function(iid, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({
			inv:iid
		},{
			$pull:{
				inv:iid
			}
		},{
			multi:true, //only true so that in case of an error multiple entries will be removed
			save:true
		},function(error,updates){
			if(error) onError(error);
			else onSuccess(updates);
		});

	},onError);
}

/*
 * Make item active.
 */

UserProvider.prototype.updateAktiveItem = function(id, item, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.update({},{
			$pull:{
				inv: _id
			}
		},{
			safe:true,
			multi:true
		},function(error,results){
			if(error) onError(error);
			else onSuccess(results);
		});

	},onError);
}

/*
 * Adjust notification settings
 */

UserProvider.prototype.updateNoti = function(id, noti, onSuccess, onError){
	db.gc(cn, function(collection){

		if( noti.remind === undefined ||
			noti.overv === undefined){
			callback('params invalid');
			return null;
		}

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				noti: noti
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Ajust stats
 */

UserProvider.prototype.updateStats = function(id, stats, onSuccess, onError){
	db.gc(cn, function(collection){

		if( !stats.cihs ||
			!stats.cis){
			callback('params invalid');
			return null;
		}

		collection.update({
			_id: db.oID(id)
		},{
			$set:{
				stats: stats
			}
		},{
			safe:true,
			multi:false
		},function(error,result){
			if(error) onError(error);
			if(!result) onError('nothing updated, user not found');
			else onSuccess(result);
		});

	},onError);
}

/*
 * Delete user
 */

UserProvider.prototype.deleteUser = function(id, onSuccess, onError){
	db.gc(cn, function(collection){

		collection.remove({
			_id: id
		},{
			safe: true
		},function(error,numRemoved){
			if(error) onError(error);
			else{
				console.log('User removed: '+numRemoved);
				onSuccess(numRemoved);
			}
		});

	},onError);
}

/*
 * Save a new row
 *
 * @param user { mail, nick, pass, ava }
 */

UserProvider.prototype.save = function(users, onSuccess, onError){
	db.gc(cn, function(collection){

		var i,
			user;

		if(users.length === undefined) users = [users];

		// expected values

		for(i=0;i<users.length;i++){

			user = users[i];

			if( !user.mail ||
				!user.nick ||
				!user.role ||
				!user.pass ||
				!user.ava ){
				onError('data incomplete');
				return;
			}

			// hash passwort
			user.pass = hash.generate( user.pass );
			console.log('generated hash');

			// add missing standard values
			user.item = null; // active item
			user.inv = []; // inventory (all items)

			user.noti = {
				remind: true,
				overv: true
			};
			user.stats = {
				cihs: 0,
				cis: 0
			};

		}

		console.log('for queue completed. users.lenth: '+users.length);

		collection.insert(users, function(error,results) {
			if(error) onError(error);
			else{
				console.log('User created: '+users.length);
				onSuccess(results);
			}
		});

	},onError);
}

exports.userProvider = new UserProvider();
<|endoftext|>


<commit_before>walk(document.body);

function walk(node)
{
	// I stole this function from here:
	// http://is.gd/mwZp7E

	var child, next;

	switch ( node.nodeType )
	{
		case 1:  // Element
		case 9:  // Document
		case 11: // Document fragment
			child = node.firstChild;
			while ( child )
			{
				next = child.nextSibling;
				walk(child);
				child = next;
			}
			break;

		case 3: // Text node
			handleText(node);
			break;
	}
}

function handleText(textNode)
{
	var v = textNode.nodeValue;

	v = v.replace(/\bSamia\b/g, "Queen");
	v = v.replace(/\bsamia\b/g, "queen");
	v = v.replace(/\batheist\b/g, "idiot");
	v = v.replace(/\bAtheist\b/g, "Idiot");
  v = v.replace(/\bFedora\b/g, "Cock Sleeve");
  v = v.replace(/\bfedora\b/g, "cock sleeve");
	textNode.nodeValue = v;
}
<commit_msg>Update content_script.js<commit_after>walk(document.body);

function walk(node)
{
	// I stole this function from here:
	// http://is.gd/mwZp7E

	var child, next;

	switch ( node.nodeType )
	{
		case 1:  // Element
		case 9:  // Document
		case 11: // Document fragment
			child = node.firstChild;
			while ( child )
			{
				next = child.nextSibling;
				walk(child);
				child = next;
			}
			break;

		case 3: // Text node
			handleText(node);
			break;
	}
}

function handleText(textNode)
{
	var v = textNode.nodeValue;

	v = v.replace(/\bSamia\b/g, "Queen");
	v = v.replace(/\bsamia\b/g, "queen");
	v = v.replace(/\batheist\b/g, "idiot");
	v = v.replace(/\bAtheist\b/g, "Idiot");
	v = v.replace(/\bFedora\b/g, "Cock Sleeve");
  	v = v.replace(/\bfedora\b/g, "cock sleeve");
    	v = v.replace(/\bfedora\b/g, "cock sleeve");
    	v = v.replace(/\bfedoras\b/g, "cock sleeves");
    	v = v.replace(/\bfedoras\b/g, "Cock Sleeves");
	textNode.nodeValue = v;
}
<|endoftext|>


<commit_before>(function (window, angular, undefined) {
    'use strict';

    angular
        .module('MainPage')
        .directive('sgBlick', sgBlick);

    sgBlick.$inject = ['$timeout', '$interval'];

    function sgBlick($timeout, $interval) {

        return {
            restrict: 'A',
            link
        };

        function link(scope, elm, attrs) {
            var delay = attrs.delay || 0;
            var speed = attrs.speed || 200;         // blick speed in pxs per second
            var interval = attrs.interval || 10;    // blick every 10s
            var random = attrs.random
                ? (attrs.random === '' ? 1 : attrs.random)
                : 0;
            var duration;

            // random interval = interval (in s) +/- random value < random attr (in s)
            // converted to ms
            var rndInterval = (interval + random * (Math.random() * 2 - 1)) * 1000;

            // set blick time depending on speed param and element length
            scope.$watch(
                ()=> elm.width(),
                (newWidth, oldWidth)=> {
                    if (newWidth && newWidth !== oldWidth) {
                        duration = newWidth / speed;
                        elm.css('transition-duration', duration + "s");
                    }
                });

            $timeout($interval(cbBlick, rndInterval), delay);

            function cbBlick() {
                // set style to 'hovered' for
                elm.toggleClass('hovered');
                setTimeout(()=> {
                    elm.toggleClass('hovered')
                }, Number(duration * 1000));
            }
        }
    }

})(window, window.angular);<commit_msg>SG-152 Профилирование директив<commit_after>(function (window, angular, undefined) {
    'use strict';

    angular
        .module('MainPage')
        .directive('sgBlick', sgBlick);

    sgBlick.$inject = ['$window', '$timeout', '$interval'];

    function sgBlick($window, $timeout, $interval) {

        return {
            restrict: 'A',
            link
        };

        function link(scope, elm, attrs) {
            var delay = attrs.delay || 0;
            var speed = attrs.speed || 200;         // blick speed in pxs per second
            var interval = attrs.interval || 10;    // blick every 10s
            var random = attrs.random
                ? (attrs.random === '' ? 1 : attrs.random)
                : 0;
            var duration;

            var elmWidth = 0;

            angular.element($window).on('load resize', ()=> {
                elmWidth = elm.width();
            });

            // random interval = interval (in s) +/- random value < random attr (in s)
            // converted to ms
            var rndInterval = (interval + random * (Math.random() * 2 - 1)) * 1000;

            // set blick time depending on speed param and element length
            scope.$watch(
                ()=> {
                    return elmWidth;
                },
                (newWidth, oldWidth)=> {
                    if (newWidth && newWidth !== oldWidth) {
                        duration = newWidth / speed;
                        elm.css('transition-duration', duration + "s");
                    }
                });

            $timeout($interval(cbBlick, rndInterval), delay);

            function cbBlick() {
                // set style to 'hovered' for
                elm.toggleClass('hovered');
                setTimeout(()=> {
                    elm.toggleClass('hovered')
                }, Number(duration * 1000));
            }
        }
    }

})(window, window.angular);<|endoftext|>


<commit_before>/* eslint-env node, browser */

import React from 'react';
import PropTypes from 'prop-types';

/* eslint-disable import/extensions, import/no-unresolved, import/no-extraneous-dependencies */
import {
  Checkbox,
  CheckboxGroup,
  Input,
  RadioGroup,
  Row,
  Select,
  File,
  Textarea,
  Form,
} from 'formsy-react-components';
/* eslint-enable */

const Playground = props => {
  const {
    disabledChoice,
    layoutChoice,
    validateOnSubmitChoice,
    validatePristineChoice,
  } = props;

  let myform = null;

  const resetForm = () => {
    console.log('Reset called'); // eslint-disable-line no-console
    const {formsyForm} = myform;
    formsyForm.reset();
  };

  const submitForm = data => {
    console.log(data); // eslint-disable-line no-console
  };

  const radioOptions = [
    {value: 'a', label: 'Option A'},
    {value: 'b', label: 'Option B'},
    {value: 'c', label: 'Option C'},
  ];

  const radioOptionsDisabled = [
    {value: 'a', label: 'Option A'},
    {value: 'b', label: 'Option B', disabled: true},
    {value: 'c', label: 'Option C'},
  ];

  const optionY = {
    value: 'y',
    label: 'Option Y (yellow css class)',
    className: 'yellow',
  };
  optionY['data-note'] = 'This is a data attribute.';

  const selectOptions = [
    {value: 'a', label: 'Option A'},
    {value: 'a', label: 'Option A (again)'},
    {value: 'b', label: 'Option B'},
    {
      value: 'c',
      label: 'Option C',
      title: 'This is a title attribute for Option C',
    },
    {value: 'd', label: 'Option D', disabled: true},
    optionY,
    {value: 'e1', label: 'Option E-1', group: 'Option group E'},
    {value: 'e2', label: 'Option E-2', group: 'Option group E'},
  ];

  const singleSelectOptions = [
    {value: '', label: 'Please select…'},
    ...selectOptions,
  ];

  const refCallback = form => {
    myform = form;
  };

  return (
    <Form
      onSubmit={submitForm}
      layout={layoutChoice}
      className="custom-classname-is-rendered"
      validateOnSubmit={validateOnSubmitChoice}
      validatePristine={validatePristineChoice}
      disabled={disabledChoice}
      ref={refCallback}>
      <fieldset>
        <legend>Input types</legend>
        <Input name="secret" value="I'm hidden!" type="hidden" />
        <Input
          name="text1"
          id="artisanCraftedBespokeId"
          value=""
          label="Text"
          type="text"
          placeholder="Here is a text input."
          help="This is a required text input."
          required
        />
        <Input
          name="date[0]"
          value=""
          label="Date"
          type="date"
          placeholder="This is a date input."
          required
        />
        <Input
          name="email"
          value=""
          label="Email"
          type="email"
          autoComplete="off"
          placeholder="This is an email input."
          help="This email field should not autocomplete."
          validations="isEmail"
          validationErrors={{
            isEmail: 'This doesn’t look like a valid email address.',
          }}
          required
        />
        <Input
          name="password1"
          value=""
          label="Password"
          type="password"
          validations="minLength:8"
          validationError="Your password must be at least 8 characters long."
          placeholder="Choose a password"
        />
        <Input
          name="password2"
          value=""
          label="Confirm password"
          type="password"
          validations="equalsField:password1"
          validationErrors={{
            equalsField: 'Passwords must match.',
          }}
          placeholder="Retype password"
        />
        <Input
          type="color"
          name="colour1"
          label="Colour input"
          value="#000000"
          validations="equals:#000000"
          validationError="You can have any color, as long as it's black."
        />
        <Input
          type="range"
          name="range1"
          label="Range input"
          min={0}
          max={10}
          step={2}
        />
        <File
          name="file1"
          label="File picker"
          help="This returns a HTML5 FileList."
          multiple
        />
      </fieldset>
      <fieldset>
        <legend>Textarea</legend>
        <Textarea
          rows={3}
          cols={40}
          name="txtArea1"
          label="Textarea"
          placeholder="This field requires 10 characters."
          help="This is some help text for the textarea."
          validations="minLength:10"
          validationErrors={{
            minLength: 'Please provide at least 10 characters.',
          }}
        />
      </fieldset>
      <fieldset>
        <legend>Select</legend>
        <Select
          name="select1"
          label="Select"
          help="This is a required select element."
          options={singleSelectOptions}
          required
        />
        <Select
          name="select2"
          value={['a', 'c']}
          label="Select (multiple)"
          help="Here, “Option A” and “Option C” are initially selected."
          options={selectOptions}
          multiple
        />
      </fieldset>
      <fieldset>
        <legend>Checkboxes</legend>
        <Checkbox
          name="checkbox1"
          value
          label="Checkbox (single)"
          valueLabel="Check me out"
        />
        <CheckboxGroup
          name="checkboxGrp1"
          value={['a', 'c']}
          label="Checkbox group (stacked)"
          help="Here, “Option A” and “Option C” are initially selected."
          options={radioOptions}
        />
      </fieldset>
      <fieldset>
        <legend>Radio group</legend>
        <RadioGroup
          name="radioGrp1"
          value="b"
          label="Radio group (stacked)"
          help="Here, “Option B” is initially selected."
          options={radioOptions}
        />
        <RadioGroup
          name="radioGrp2"
          type="inline"
          label="Radio group (inline)"
          help="This is a required radio group."
          options={radioOptions}
          required
        />
        <RadioGroup
          name="radioGrp3"
          type="inline"
          label="Radio group (disabled)"
          help="Here, “Option B” is disabled."
          options={radioOptionsDisabled}
        />
      </fieldset>
      <fieldset>
        <legend>Layout tweaks</legend>
        <Input
          name="cssRowTweak"
          value=""
          label="This row is yellow"
          type="text"
          placeholder="the rowClassName property is ‘yellow’"
          rowClassName="yellow"
          help="You can modify the class name for the row."
        />
        <Input
          name="cssWrapperTweaks"
          value=""
          label="Label and element wrapper"
          type="text"
          placeholder="Label is ‘col-sm-5’, element-wrapper is ‘col-sm-7’"
          labelClassName={[{'col-sm-3': false}, 'col-sm-5']}
          elementWrapperClassName={[{'col-sm-9': false}, 'col-sm-7']}
          help="The label and element-wrapper classes can be changed."
        />
      </fieldset>
      <fieldset>
        <legend>Disabled</legend>
        <Input
          name="disabled"
          value="This field is always disabled."
          label="Disabled"
          type="text"
          disabled
          help="The disabled prop on this component is set to true."
        />
      </fieldset>
      <fieldset>
        <legend>Input groups</legend>
        <Input
          name="addon-before"
          value=""
          label="Add-on before"
          type="text"
          addonBefore={}
        />
        <Input
          name="addon-after"
          value=""
          label="Add-on after"
          type="text"
          addonAfter={}
        />
        <Input
          name="button-before"
          value=""
          label="Button before"
          type="text"
          buttonBefore={
            <button className="btn btn-light" type="button">
              Go!
            </button>
          }
        />
        <Input
          name="button-after"
          value=""
          label="Button after"
          type="text"
          buttonAfter={
            <button className="btn btn-light" type="button">
              Go!
            </button>
          }
        />
      </fieldset>
      <fieldset>
        <Row layout={layoutChoice}>
          <input
            className="btn btn-secondary"
            onClick={resetForm}
            type="reset"
            defaultValue="Reset"
          />{' '}
          <input
            className="btn btn-primary"
            formNoValidate
            type="submit"
            defaultValue="Submit"
          />
        </Row>
      </fieldset>
    </Form>
  );
};

Playground.propTypes = {
  disabledChoice: PropTypes.bool.isRequired,
  layoutChoice: PropTypes.oneOf(['horizontal', 'vertical', 'elementOnly'])
    .isRequired,
  validateOnSubmitChoice: PropTypes.bool.isRequired,
  validatePristineChoice: PropTypes.bool.isRequired,
};

export default Playground;
<commit_msg>Update playground examples.<commit_after>/* eslint-env node, browser */

import React from 'react';
import PropTypes from 'prop-types';

/* eslint-disable import/extensions, import/no-unresolved, import/no-extraneous-dependencies */
import {
  Checkbox,
  CheckboxGroup,
  Input,
  RadioGroup,
  Row,
  Select,
  File,
  Textarea,
  Form,
} from 'formsy-react-components';
/* eslint-enable */

const Playground = props => {
  const {
    disabledChoice,
    layoutChoice,
    validateOnSubmitChoice,
    validatePristineChoice,
  } = props;

  let myform = null;

  const resetForm = () => {
    console.log('Reset called'); // eslint-disable-line no-console
    const {formsyForm} = myform;
    formsyForm.reset();
  };

  const submitForm = data => {
    console.log(data); // eslint-disable-line no-console
  };

  const radioOptions = [
    {value: 'a', label: 'Option A'},
    {value: 'b', label: 'Option B'},
    {value: 'c', label: 'Option C'},
  ];

  const radioOptionsDisabled = [
    {value: 'a', label: 'Option A'},
    {value: 'b', label: 'Option B', disabled: true},
    {value: 'c', label: 'Option C'},
  ];

  const optionY = {
    value: 'y',
    label: 'Option Y (yellow css class)',
    className: 'yellow',
  };
  optionY['data-note'] = 'This is a data attribute.';

  const selectOptions = [
    {value: 'a', label: 'Option A'},
    {value: 'a', label: 'Option A (again)'},
    {value: 'b', label: 'Option B'},
    {
      value: 'c',
      label: 'Option C',
      title: 'This is a title attribute for Option C',
    },
    {value: 'd', label: 'Option D', disabled: true},
    optionY,
    {value: 'e1', label: 'Option E-1', group: 'Option group E'},
    {value: 'e2', label: 'Option E-2', group: 'Option group E'},
  ];

  const singleSelectOptions = [
    {value: '', label: 'Please select…'},
    ...selectOptions,
  ];

  const refCallback = form => {
    myform = form;
  };

  return (
    <Form
      onSubmit={submitForm}
      layout={layoutChoice}
      className="custom-classname-is-rendered"
      validateOnSubmit={validateOnSubmitChoice}
      validatePristine={validatePristineChoice}
      disabled={disabledChoice}
      ref={refCallback}>
      <fieldset>
        <legend>Input types</legend>
        <Input name="secret" value="I'm hidden!" type="hidden" />
        <Input
          name="text1"
          id="artisanCraftedBespokeId"
          value=""
          label="Text"
          type="text"
          placeholder="Here is a text input."
          help="This is a required text input."
          required
        />
        <Input
          name="date[0]"
          value=""
          label="Date"
          type="date"
          placeholder="This is a date input."
          required
        />
        <Input
          name="email"
          value=""
          label="Email"
          type="email"
          autoComplete="off"
          placeholder="This is an email input."
          help="This email field should not autocomplete."
          validations="isEmail"
          validationErrors={{
            isEmail: 'This doesn’t look like a valid email address.',
          }}
          required
        />
        <Input
          name="password1"
          value=""
          label="Password"
          type="password"
          validations="minLength:8"
          validationError="Your password must be at least 8 characters long."
          placeholder="Choose a password"
        />
        <Input
          name="password2"
          value=""
          label="Confirm password"
          type="password"
          validations="equalsField:password1"
          validationErrors={{
            equalsField: 'Passwords must match.',
          }}
          placeholder="Retype password"
        />
        <Input
          type="color"
          name="colour1"
          label="Colour input"
          value="#000000"
          validations="equals:#000000"
          validationError="You can have any color, as long as it's black."
        />
        <Input
          type="range"
          name="range1"
          label="Range input"
          min={0}
          max={10}
          step={2}
        />
        <File
          name="file1"
          label="File picker"
          help="This returns a HTML5 FileList."
          multiple
        />
      </fieldset>
      <fieldset>
        <legend>Textarea</legend>
        <Textarea
          rows={3}
          cols={40}
          name="txtArea1"
          label="Textarea"
          placeholder="This field requires 10 characters."
          help="This is some help text for the textarea."
          validations="minLength:10"
          validationErrors={{
            minLength: 'Please provide at least 10 characters.',
          }}
        />
      </fieldset>
      <fieldset>
        <legend>Select</legend>
        <Select
          name="select1"
          label="Select"
          help="This is a required select element."
          options={singleSelectOptions}
          required
        />
        <Select
          name="select2"
          value={['a', 'c']}
          label="Select (multiple)"
          help="Here, “Option A” and “Option C” are initially selected."
          options={selectOptions}
          multiple
        />
      </fieldset>
      <fieldset>
        <legend>Checkboxes</legend>
        <Checkbox
          name="checkbox1"
          value
          label="Checkbox (single)"
          valueLabel="Check me out"
        />
        <CheckboxGroup
          name="checkboxGrp1"
          value={['a', 'c']}
          label="Checkbox group (stacked)"
          help="Here, “Option A” and “Option C” are initially selected."
          options={radioOptions}
        />
        <CheckboxGroup
          name="checkboxGrp1"
          type="inline"
          label="Checkbox group (inline)"
          options={radioOptions}
        />
      </fieldset>
      <fieldset>
        <legend>Radio group</legend>
        <RadioGroup
          name="radioGrp1"
          value="b"
          label="Radio group (stacked)"
          help="Here, “Option B” is initially selected."
          options={radioOptions}
        />
        <RadioGroup
          name="radioGrp2"
          type="inline"
          label="Radio group (inline)"
          help="This is a required radio group."
          options={radioOptions}
          required
        />
        <RadioGroup
          name="radioGrp3"
          type="inline"
          label="Radio group (disabled)"
          help="Here, “Option B” is disabled."
          options={radioOptionsDisabled}
        />
      </fieldset>
      <fieldset>
        <legend>Layout tweaks</legend>
        <Input
          name="cssRowTweak"
          value=""
          label="This row is yellow"
          type="text"
          placeholder="the rowClassName property is ‘yellow’"
          rowClassName="yellow"
          help="You can modify the class name for the row."
        />
        <Input
          name="cssWrapperTweaks"
          value=""
          label="Label and element wrapper"
          type="text"
          placeholder="Label is ‘col-sm-5’, element-wrapper is ‘col-sm-7’"
          labelClassName={[{'col-sm-3': false}, 'col-sm-5']}
          elementWrapperClassName={[{'col-sm-9': false}, 'col-sm-7']}
          help="The label and element-wrapper classes can be changed."
        />
      </fieldset>
      <fieldset>
        <legend>Disabled</legend>
        <Input
          name="disabled"
          value="This field is always disabled."
          label="Disabled"
          type="text"
          disabled
          help="The disabled prop on this component is set to true."
        />
      </fieldset>
      <fieldset>
        <legend>Input groups</legend>
        <Input
          name="addon-before"
          value=""
          label="Add-on before"
          type="text"
          addonBefore={@}
        />
        <Input
          name="addon-after"
          value=""
          label="Add-on after"
          type="text"
          addonAfter={@example.com}
        />
        <Input
          name="button-before"
          value=""
          label="Button before"
          type="text"
          buttonBefore={
            <button className="btn btn-secondary" type="button">
              Go!
            </button>
          }
        />
        <Input
          name="button-after"
          value=""
          label="Button after"
          type="text"
          buttonAfter={
            <button className="btn btn-secondary" type="button">
              Go!
            </button>
          }
        />
      </fieldset>
      <fieldset>
        <Row layout={layoutChoice}>
          <input
            className="btn btn-secondary"
            onClick={resetForm}
            type="reset"
            defaultValue="Reset"
          />{' '}
          <input
            className="btn btn-primary"
            formNoValidate
            type="submit"
            defaultValue="Submit"
          />
        </Row>
      </fieldset>
    </Form>
  );
};

Playground.propTypes = {
  disabledChoice: PropTypes.bool.isRequired,
  layoutChoice: PropTypes.oneOf(['horizontal', 'vertical', 'elementOnly'])
    .isRequired,
  validateOnSubmitChoice: PropTypes.bool.isRequired,
  validatePristineChoice: PropTypes.bool.isRequired,
};

export default Playground;
<|endoftext|>


<commit_before>import Mapper from "url-mapper"

import { assoc } from "./fp"

export const HomePage = "HomePage"
export const LoginPage = "LoginPage"
export const RegisterPage = "RegisterPage"
export const ArticleDetailPage = "ArticleDetailPage"
export const ArticleCreatePage = "ArticleCreatePage"
export const ArticleEditPage = "ArticleEditPage"
export const SettingsPage = "SettingsPage"
export const ProfilePage = "ProfilePage"
export const ProfileFavoritesPage = "ProfileFavoritesPage"

const prefix = "#"

const routeMappings = {
  "/": () => ({ pageId: HomePage, articles: null }),
  "/login": () => ({ pageId: LoginPage, login: {} }),
  "/register": () => ({ pageId: RegisterPage, register: {} }),
  "/article/:slug": () => ({ pageId: ArticleDetailPage, article: null }),
  "/editor/:slug": () => ({ pageId: ArticleEditPage, article: null }),
  "/editor": () => ({ pageId: ArticleCreatePage,
    article: { title: "", description: "", body: "", tags: "" }
  }),
  "/settings": () => ({ pageId: SettingsPage }),
  "/profile/:username": () => ({ pageId: ProfilePage, profile: null }),
  "/profile/:username/favorites": () => ({ pageId: ProfileFavoritesPage, profile: null })
}

const urlMapper = Mapper({ query: true })

const routeLookup = Object.keys(routeMappings).reduce((result, key) =>
  assoc(routeMappings[key]().pageId, key, result), {})

export const parseUrl = (url = document.location.hash || "#/") => {
  const mapped = urlMapper.map(url.substring(1), routeMappings)
  if (mapped) {
    const patch = mapped.match
    return Object.assign({}, patch(), { url, params: mapped.values })
  }
}

export const getUrl = (id, params = {}) => {
  const route = routeLookup[id] || "/"
  const result = urlMapper.stringify(route, params)
  return prefix + result
}

export const navigateTo = (id, params) => parseUrl(getUrl(id, params))

export const listenToRouteChanges = update =>
  window.onpopstate = () => update(parseUrl())
<commit_msg>Working on realworld example.<commit_after>import Mapper from "url-mapper"

import { assoc } from "./fp"

export const HomePage = "HomePage"
export const LoginPage = "LoginPage"
export const RegisterPage = "RegisterPage"
export const ArticleDetailPage = "ArticleDetailPage"
export const ArticleCreatePage = "ArticleCreatePage"
export const ArticleEditPage = "ArticleEditPage"
export const SettingsPage = "SettingsPage"
export const ProfilePage = "ProfilePage"
export const ProfileFavoritesPage = "ProfileFavoritesPage"

const prefix = "#"

const routeMappings = {
  "/": () => ({ pageId: HomePage, articles: null }),
  "/login": () => ({ pageId: LoginPage, login: {} }),
  "/register": () => ({ pageId: RegisterPage, register: {} }),
  "/article/:slug": () => ({ pageId: ArticleDetailPage, article: null }),
  "/editor/:slug": () => ({ pageId: ArticleEditPage, article: null }),
  "/editor": () => ({ pageId: ArticleCreatePage,
    article: { title: "", description: "", body: "", tags: "" }
  }),
  "/settings": () => ({ pageId: SettingsPage }),
  "/profile/:username": () => ({ pageId: ProfilePage, profile: null, feed: false }),
  "/profile/:username/favorites": () => ({ pageId: ProfileFavoritesPage, profile: null, feed: false })
}

const urlMapper = Mapper({ query: true })

const routeLookup = Object.keys(routeMappings).reduce((result, key) =>
  assoc(routeMappings[key]().pageId, key, result), {})

export const parseUrl = (url = document.location.hash || "#/") => {
  const mapped = urlMapper.map(url.substring(1), routeMappings)
  if (mapped) {
    const patch = mapped.match
    return Object.assign({}, patch(), { url, params: mapped.values })
  }
}

export const getUrl = (id, params = {}) => {
  const route = routeLookup[id] || "/"
  const result = urlMapper.stringify(route, params)
  return prefix + result
}

export const navigateTo = (id, params) => parseUrl(getUrl(id, params))

export const listenToRouteChanges = update =>
  window.onpopstate = () => update(parseUrl())
<|endoftext|>