<commit_before>function mylog(v) { divStatsE.html(divStatsE.html() + v + "
"); }

function resetImgs() {
  idxSelect = -99;
  imgLeftE.attr( 'class', 'imgNormal');
  imgRightE.attr('class', 'imgNormal');
  voteAllowed = true;
}

function resetPool() { // Once all images have been shown, start over
  resetImgs();

   // Slice() forces copy by value (doesn't just create a reference)
  fnPool  = img_fn.slice();
  idxPool = img_idx.slice();

  if (myChartObj) { myChartObj.destroy(); }
}

function global_init() {
  // Don't use "var" in this function; we need to init global vars

  img_fn = [
    "blueMarinatedTurkey.jpg",
    "condimentSprays.jpg",
    "cornDogs.jpg",
    "cranberryCandles.jpg",
    "frozenShrimp.jpg",
    "frozenWhatAreThese.jpg",
    "heatedSoda.jpg",
    "jelloMayoTurkey.jpg",
    "pastaOnionsCandy.jpg",
    "whipcreamSoup.jpg",
    "good_cauliDog.jpg",
    "good_happyPyramid.jpg",
    "good_rawPyramid.jpg",
    "good_rawVeganPyramid.jpg",
    "good_vegPlate.jpg",
    "good_veganProteinPowde.jpg"
  ];
  // TODO: Add 4 more images

  // Tracks indices (of original array) of images that have been shown
  img_idx = [];
  for (var ii=0; ii < img_fn.length; ii++) { img_idx[ii] = ii; }

  imgDir = "./img/";

  imgLeftE  = $('#imgLeft');
  imgRightE = $('#imgRight');
  btnVoteE  = $('#btnVote');
  btnNewE   = $('#btnNew');
  divStatsE = $('#divStats');
  myChartE  = $('#myChart');

  ctx = myChartE[0].getContext("2d");
  myChartObj = 0;

  resetPool();

  imgLeftE.on( "click", function() { selectImg(imgLeftE ); } );
  imgRightE.on("click", function() { selectImg(imgRightE); } );

  btnVoteE.on("click", function() { recordVote(); } );
  btnNewE.on("click",  function() { newPair(); }    );
}

function getRandIntOnRange (a, b) {
  var r = Math.random();
  var t = a + Math.floor(r * (b-a+1));
  return t;
}

function removeFilename(idx, maxIdx) {
  // Remove img filename. ( Note: The code below is faster than splice(). )
  fnPool[idx] = fnPool[maxIdx];
  fnPool.pop();
  // Update indices list
  idxPool[idx]= idxPool[maxIdx];
  idxPool.pop();
}

function showRandImg(imgE) {
  var maxIdx = fnPool.length - 1;
  if (maxIdx < 1) {
    console.log("No images left in pool. Resetting pool.");
    resetPool();
    maxIdx = fnPool.length - 1;
  }

  var idx = getRandIntOnRange(0, maxIdx);
  imgE.attr('src', imgDir + fnPool[idx]);
   // Extend object to have an property that holds idx w.r.t. original fn array
  imgE.idxOrig = idxPool[idx];
mylog("idx = " + idx);
  removeFilename(idx, maxIdx);
}

function selectImg(el) {
  if (voteAllowed) {
    resetImgs();
    el.attr('class', 'imgPicked');
    idxSelect = el.idxOrig;
  }
}

function recordVote() {
  if (idxSelect > -1) {
    voteAllowed = false;
    btnVoteE.css("visibility", "hidden");
    showChart();
  }
}

function showChart() {
  // The charting code here is just a placeholder, and is NOT the best way to
  // show votes or relative popularity. Improve the code below to generate more
  // easily understandable charts.
  var fnL = img_fn[imgLeftE.idxOrig];
  var fnR = img_fn[imgRightE.idxOrig];
  var labelL = fnL.split(".")[0];
  var labelR = fnR.split(".")[0];

  var data = {
    labels: [labelL, labelR],
    datasets: [
      { label: "Raw votes",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [5, 2] // Bogus data -- use your vote counts instead
      },
      { label: "Percentage split",
        fillColor: "rgba(151,187,205,0.5)",
        strokeColor: "rgba(151,187,205,0.8)",
        highlightFill: "rgba(151,187,205,0.75)",
        highlightStroke: "rgba(151,187,205,1)",
        data: [5/(5+2), 2/(5+2)]
      }
    ]
  };

  // This call to create the chart does not include options as an arg. Modify
  // this to use options that make the labels, colors, etc.  match the look and
  // feel of the rest of your web page.
  //
  // Options (see www.chartjs.org/docs/) should look similar to this:
  //
  //  { //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
  //    scaleBeginAtZero : true,
  //
  //    //Boolean - Whether grid lines are shown across the chart
  //    scaleShowGridLines : true,
  //
  //    ... and so on...
  myChartObj = new Chart(ctx).Bar(data);

  /*** !! Insert code HERE to draw your chart and make it visible !! ***/

  btnNewE.css("display",    "inline");
  btnNewE.css("visibility", "visible");
}

function newPair() {
  btnNewE.css( "visibility", "hidden");
  btnVoteE.css("visibility", "visible");
  resetImgs();

  /*** !! Insert code HERE to hide your chart !! ***/

  // This seems to correctly free no-longer-used memory, but it doesn't wipe or
  // hide the graphic that is "cached" in your <canvas>
  if (myChartObj) { myChartObj.destroy(); }

  // TODO: If total img count is odd, handle case where only one filename is "left in the hat"
//console.log("fnPool.length = " + fnPool.length);
  showRandImg(imgLeftE);
//removeFilename(imgLeftE.idxOrig, fnPool.length-1);
  showRandImg(imgRightE);
}

$(document).ready(function() {
  global_init();
  showRandImg(imgLeftE);
  showRandImg(imgRightE);
});<commit_msg>Added some old debug stuff on weather JSON data<commit_after>var jsonStuff = {
  "coord": {"lon":-122.68, "lat":45.52},
  "weather":[ {"id":500,
               "main":"Rain",
               "description":"light rain",
               "icon":"10n"}
            ],
  "base":"cmc stations",
  "main":{"temp":279.638,
          "pressure":1001.55,
	  "humidity":97,
	  "temp_min":279.638,
	  "temp_max":279.638,
	  "sea_level":1036.48,
	  "grnd_level":1001.55},
  "wind":{"speed":3.76,
	  "deg":204},
  "rain":{"3h":0.52},
  "clouds":{"all":92},
  "dt":1447216221,
  "sys":{"message":0.0037,
	 "country":"US",
	 "sunrise":1447254260,
	 "sunset":1447289076},
  "id":5746545,
  "name":"Portland",
  "cod":200
  };

console.log(jsonStuff.name);

function mylog(v) { divStatsE.html(divStatsE.html() + v + "
"); }

function resetImgs() {
  idxSelect = -99;
  imgLeftE.attr( 'class', 'imgNormal');
  imgRightE.attr('class', 'imgNormal');
  voteAllowed = true;
}

function resetPool() { // Once all images have been shown, start over
  resetImgs();

   // Slice() forces copy by value (doesn't just create a reference)
  fnPool  = img_fn.slice();
  idxPool = img_idx.slice();

  if (myChartObj) { myChartObj.destroy(); }
}

function global_init() {
  // Don't use "var" in this function; we need to init global vars

  img_fn = [
    "blueMarinatedTurkey.jpg",
    "condimentSprays.jpg",
    "cornDogs.jpg",
    "cranberryCandles.jpg",
    "frozenShrimp.jpg",
    "frozenWhatAreThese.jpg",
    "heatedSoda.jpg",
    "jelloMayoTurkey.jpg",
    "pastaOnionsCandy.jpg",
    "whipcreamSoup.jpg",
    "good_cauliDog.jpg",
    "good_happyPyramid.jpg",
    "good_rawPyramid.jpg",
    "good_rawVeganPyramid.jpg",
    "good_vegPlate.jpg",
    "good_veganProteinPowde.jpg"
  ];
  // TODO: Add 4 more images

  // Tracks indices (of original array) of images that have been shown
  img_idx = [];
  for (var ii=0; ii < img_fn.length; ii++) { img_idx[ii] = ii; }

  imgDir = "./img/";

  imgLeftE  = $('#imgLeft');
  imgRightE = $('#imgRight');
  btnVoteE  = $('#btnVote');
  btnNewE   = $('#btnNew');
  divStatsE = $('#divStats');
  myChartE  = $('#myChart');

  ctx = myChartE[0].getContext("2d");
  myChartObj = 0;

  resetPool();

  imgLeftE.on( "click", function() { selectImg(imgLeftE ); } );
  imgRightE.on("click", function() { selectImg(imgRightE); } );

  btnVoteE.on("click", function() { recordVote(); } );
  btnNewE.on("click",  function() { newPair(); }    );
}

function getRandIntOnRange (a, b) {
  var r = Math.random();
  var t = a + Math.floor(r * (b-a+1));
  return t;
}

function removeFilename(idx, maxIdx) {
  // Remove img filename. ( Note: The code below is faster than splice(). )
  fnPool[idx] = fnPool[maxIdx];
  fnPool.pop();
  // Update indices list
  idxPool[idx]= idxPool[maxIdx];
  idxPool.pop();
}

function showRandImg(imgE) {
  var maxIdx = fnPool.length - 1;
  if (maxIdx < 1) {
    console.log("No images left in pool. Resetting pool.");
    resetPool();
    maxIdx = fnPool.length - 1;
  }

  var idx = getRandIntOnRange(0, maxIdx);
  imgE.attr('src', imgDir + fnPool[idx]);
   // Extend object to have an property that holds idx w.r.t. original fn array
  imgE.idxOrig = idxPool[idx];
mylog("idx = " + idx);
  removeFilename(idx, maxIdx);
}

function selectImg(el) {
  if (voteAllowed) {
    resetImgs();
    el.attr('class', 'imgPicked');
    idxSelect = el.idxOrig;
  }
}

function recordVote() {
  if (idxSelect > -1) {
    voteAllowed = false;
    btnVoteE.css("visibility", "hidden");
    showChart();
  }
}

function showChart() {
  // The charting code here is just a placeholder, and is NOT the best way to
  // show votes or relative popularity. Improve the code below to generate more
  // easily understandable charts.
  var fnL = img_fn[imgLeftE.idxOrig];
  var fnR = img_fn[imgRightE.idxOrig];
  var labelL = fnL.split(".")[0];
  var labelR = fnR.split(".")[0];

  var data = {
    labels: [labelL, labelR],
    datasets: [
      { label: "Raw votes",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [5, 2] // Bogus data -- use your vote counts instead
      },
      { label: "Percentage split",
        fillColor: "rgba(151,187,205,0.5)",
        strokeColor: "rgba(151,187,205,0.8)",
        highlightFill: "rgba(151,187,205,0.75)",
        highlightStroke: "rgba(151,187,205,1)",
        data: [5/(5+2), 2/(5+2)]
      }
    ]
  };

  // This call to create the chart does not include options as an arg. Modify
  // this to use options that make the labels, colors, etc.  match the look and
  // feel of the rest of your web page.
  //
  // Options (see www.chartjs.org/docs/) should look similar to this:
  //
  //  { //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
  //    scaleBeginAtZero : true,
  //
  //    //Boolean - Whether grid lines are shown across the chart
  //    scaleShowGridLines : true,
  //
  //    ... and so on...
  myChartObj = new Chart(ctx).Bar(data);

  /*** !! Insert code HERE to draw your chart and make it visible !! ***/

  btnNewE.css("display",    "inline");
  btnNewE.css("visibility", "visible");
}

function newPair() {
  btnNewE.css( "visibility", "hidden");
  btnVoteE.css("visibility", "visible");
  resetImgs();

  /*** !! Insert code HERE to hide your chart !! ***/

  // This seems to correctly free no-longer-used memory, but it doesn't wipe or
  // hide the graphic that is "cached" in your <canvas>
  if (myChartObj) { myChartObj.destroy(); }

  // TODO: If total img count is odd, handle case where only one filename is "left in the hat"
//console.log("fnPool.length = " + fnPool.length);
  showRandImg(imgLeftE);
//removeFilename(imgLeftE.idxOrig, fnPool.length-1);
  showRandImg(imgRightE);
}

$(document).ready(function() {
  global_init();
  showRandImg(imgLeftE);
  showRandImg(imgRightE);
});<|endoftext|>


<commit_before>(function Xcon () {

    "use strict";

    if (this !== console) {
        return false;
    }

    this.condition = function (text) {
        var type = typeof text;
        switch (type) {
            case 'number' || 'boolean' || 'function':
                text = text.toString();
                break;
            case 'object':
                type = text instanceof Array ? 'array' : 'object';
                type = text !== null ? type : 'null';
                text = JSON.stringify(text);
                break;
            case 'undefined':
                text = 'undefined';
                break;
        }
        type = type + ':';
        return {
            "type": type,
            "text": text
        };
    };

    this.out = function (rawText, opts) {
        opts = opts || {};
        var props = this.condition(rawText),
            type = props.type,
            text = props.text || '',
            typeColor = opts.color || 'gray';
        type = opts.error ? 'error' : type;
        type = opts.fnName ? opts.fnName + '(' +
            opts.fnArgs.toString() + ') returns ' + type : type;
        this.log("%c" + type, "color:" + typeColor + ";font-weight:bold;");
        this.log("%c" + text, "color:" + opts.color + ";font-weight:bold;");
        if (opts.console) {
            this.log(rawText);
        }
    };

    this.run = function (fn) {
        if (typeof fn === 'function') {
            var args = [], n, result;
            for (n = 1; n < arguments.length; n++) {
                args.push(arguments[n]);
            }
            try {
                result = fn.apply(this, args);
                this.out(result, {
                    "color": 'darkgreen',
                    "fnName": fn.name || 'anonymous function',
                    "fnArgs": args
                });
                return result;
            } catch (e) {
                this.out(e.message, {
                    "color": 'red',
                    "fnName": fn.name || 'anonymous function',
                    "fnArgs": args,
                    "error": true
                });
            }
        } else {
            this.out(arguments[0], arguments[1]);
        }
    };

    return this;

}).call(window.console);
<commit_msg>future-proof against additions to native console by browser vendors<commit_after>(function Xcon () {

    "use strict";

    // future-proof against vender expansions to browser console
    if (this.condition || this.out || this.run) {
        window.xcon = {};
        return Xcon.call(window.xcon);
    }

    this.condition = function (text) {
        var type = typeof text;
        switch (type) {
            case 'number' || 'boolean' || 'function':
                text = text.toString();
                break;
            case 'object':
                type = text instanceof Array ? 'array' : 'object';
                type = text !== null ? type : 'null';
                text = JSON.stringify(text);
                break;
            case 'undefined':
                text = 'undefined';
                break;
        }
        type = type + ':';
        return {
            "type": type,
            "text": text
        };
    };

    this.out = function (rawText, opts) {
        opts = opts || {};
        var props = this.condition(rawText),
            type = props.type,
            text = props.text || '',
            typeColor = opts.color || 'gray';
        type = opts.error ? 'error' : type;
        type = opts.fnName ? opts.fnName + '(' +
            opts.fnArgs.toString() + ') returns ' + type : type;
        console.log("%c" + type, "color:" + typeColor + ";font-weight:bold;");
        console.log("%c" + text, "color:" + opts.color + ";font-weight:bold;");
        if (opts.console) {
            console.log(rawText);
        }
    };

    this.run = function (fn) {
        if (typeof fn === 'function') {
            var args = [], n, result;
            for (n = 1; n < arguments.length; n++) {
                args.push(arguments[n]);
            }
            try {
                result = fn.apply(this, args);
                this.out(result, {
                    "color": 'darkgreen',
                    "fnName": fn.name || 'anonymous function',
                    "fnArgs": args
                });
                return result;
            } catch (e) {
                this.out(e.message, {
                    "color": 'red',
                    "fnName": fn.name || 'anonymous function',
                    "fnArgs": args,
                    "error": true
                });
            }
        } else {
            this.out(arguments[0], arguments[1]);
        }
    };

    return this;

}).call(window.console);
<|endoftext|>


<commit_before>import Utils from '../utils/utils';
import Geo from '../geo';

import parseCSSColor from 'csscolorparser';
import log from 'loglevel';

export var StyleParser = {};

// Style macros

StyleParser.expandMacros = function expandMacros (obj) {
    for (var p in obj) {
        var val = obj[p];

        // Loop through object properties
        if (typeof val === 'object') {
            obj[p] = expandMacros(val);
        }
        // Convert strings back into functions
        else if (typeof val === 'string') {
            for (var m in StyleParser.macros) {
                if (val.match(StyleParser.macros[m])) {
                    var f;
                    try {
                        /*jshint ignore:start */
                        eval('f = ' + val);
                        /*jshint ignore:end */
                        obj[p] = f;
                        log.trace(`expanded macro ${val} to ${f}`);
                        break;
                    }
                    catch (e) {
                        // fall-back to original value if parsing failed
                        obj[p] = val;
                        log.trace(`failed to expand macro ${val}`);
                    }
                }
            }
        }
    }

    return obj;
};

// List of macros
StyleParser.macros = [
    'Style.color.pseudoRandomColor',
    'Style.color.randomColor'
];

var Style = {};

Style.color = {
    // pseudo-random grayscale by geometry id
    pseudoRandomGrayscale() {
        var func = `function() {
            var c = Math.max((parseInt(feature.id, 16) % 100) / 100, 0.4);
            return [0.7 * c, 0.7 * c, 0.7 * c];
        }`;
        return func;
    },

    // pseudo-random color by geometry id
    pseudoRandomColor() {
        var func = `function() {
            return [
                0.7 * (parseInt(feature.id, 16) / 100 % 1),
                0.7 * (parseInt(feature.id, 16) / 10000 % 1),
                0.7 * (parseInt(feature.id, 16) / 1000000 % 1)
            ];
        }`;
        return func;
        // return `function() { return [0.7 * (parseInt(feature.id, 16) / 100 % 1), 0.7 * (parseInt(feature.id, 16) / 10000 % 1), 0.7 * (parseInt(feature.id, 16) / 1000000 % 1)]; }`;
    },

    // random color
    randomColor() {
        var func = `function() {
            return [0.7 * Math.random(), 0.7 * Math.random(), 0.7 * Math.random()];
        }`;
        return func;
    }
};

// Wraps style functions and provides a scope of commonly accessible data:
// - feature: the 'properties' of the feature, e.g. accessed as 'feature.name'
// - $zoom: the current map zoom level
// - $geometry: the type of geometry, 'point', 'line', or 'polygon'
// - $meters_per_pixel: conversion for meters/pixels at current map zoom
// - properties: user-defined properties on the style-rule object in the stylesheet
StyleParser.wrapFunction = function (func) {
    var f = `function(context) {
                var feature = context.feature.properties;
                var $zoom = context.zoom;
                var $geometry = context.geometry;
                var $meters_per_pixel = context.meters_per_pixel;
                var properties = context.properties;
                return (${func}());
            }`;
    return f;
};

// Style parsing

// Style defaults
StyleParser.defaults = {
    color: [1, 1, 1, 1],
    width: 1,
    size: 1,
    extrude: false,
    height: 20,
    min_height: 0,
    order: 0,
    z: 0,
    material: {
        ambient: 1,
        diffuse: 1
    }
};

// A context object that is passed to style parsing functions to provide a scope of commonly used values
StyleParser.getFeatureParseContext = function (feature, tile) {
    return {
        feature,
        tile,
        zoom: tile.style_zoom,
        geometry: Geo.geometryType(feature.geometry.type),
        meters_per_pixel: Geo.metersPerPixel(tile.coords.z),
        units_per_meter: Geo.units_per_meter[tile.coords.z]
    };
};

StyleParser.convertUnits = function(val, context, convert = 'meters') {
    if (typeof val === 'string') {
        var units = val.match(/([0-9.-]+)([a-z]+)/);
        if (units && units.length === 3) {
            val = parseFloat(units[1]);
            units = units[2];
        }

        // Convert to meters
        if (convert === 'meters') {
            // Convert from pixels
            if (units === 'px') {
                val *= Geo.metersPerPixel(context.zoom);
            }
            // Convert from kilometers
            else if (units === 'km') {
                val *= 1000;
            }
        }
    }
    else if (Array.isArray(val)) {
        // Array of arrays, e.g. zoom-interpolated stops
        if (Array.isArray(val[0])) {
            return val.map(v => { return [v[0], StyleParser.convertUnits(v[1], context, convert)]; });
        }
        // Array of values
        else {
            return val.map(v => { return StyleParser.convertUnits(v, context, convert); });
        }
    }
    return val;
};

// Takes a distance cache object and returns a distance value for this zoom
// (caching the result for future use)
// { value: original, zoom: { z: meters }, dynamic: function(){...} }
StyleParser.cacheDistance = function(val, context, convert = 'meters') {
    if (val.dynamic) {
        let v = val.dynamic(context);
        return v;
    }
    else if (val.zoom && val.zoom[convert] && val.zoom[convert][context.zoom]) {
        return val.zoom[convert][context.zoom];
    }
    else {
        // Dynamic function-based
        if (typeof val.value === 'function') {
            val.dynamic = val.value;
            let v = val.dynamic(context);
            return v;
        }
        // Array of zoom-interpolated stops, e.g. [zoom, value] pairs
        else {
            // Calculate value for current zoom
            val.zoom = val.zoom || {};
            let zunits = val.zoom[convert] = val.zoom[convert] || {};

            zunits[context.zoom] = StyleParser.convertUnits(val.value, context,
                convert === 'meters' && 'meters'); // convert to meters
            zunits[context.zoom] = Utils.interpolate(context.zoom, zunits[context.zoom]);

            return zunits[context.zoom];
        }
    }
};

// Cache previously parsed color strings
StyleParser.string_colors = {};
StyleParser.colorForString = function(string) {
    // Cached
    if (StyleParser.string_colors[string]) {
        return StyleParser.string_colors[string];
    }

    // Calculate and cache
    let color = parseCSSColor.parseCSSColor(string);
    if (color && color.length === 4) {
        color[0] /= 255;
        color[1] /= 255;
        color[2] /= 255;
        color[3] = 1;
    }
    else {
        color = StyleParser.defaults.color;
    }
    StyleParser.string_colors[string] = color;
    return color;
};

// Takes a color cache object and returns a color value for this zoom
// (caching the result for future use)
// { value: original, static: [r,g,b,a], zoom: { z: [r,g,b,a] }, dynamic: function(){...} }
StyleParser.cacheColor = function(val, context = {}) {
    if (val.dynamic) {
        let v = val.dynamic(context);
        v[3] = v[3] || 1; // default alpha
        return v;
    }
    else if (val.static) {
        return val.static;
    }
    else if (val.zoom && val.zoom[context.zoom]) {
        return val.zoom[context.zoom];
    }
    else {
        // Dynamic function-based color
        if (typeof val.value === 'function') {
            val.dynamic = val.value;
            let v = val.dynamic(context);
            v[3] = v[3] || 1; // default alpha
            return v;
        }
        // Single string color
        else if (typeof val.value === 'string') {
            val.static = StyleParser.colorForString(val.value);
            return val.static;
        }
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        else if (Array.isArray(val.value) && Array.isArray(val.value[0])) {
            if (!val.zoom) {
                val.zoom = {};
                // Parse any string colors inside stops
                for (let i=0; i < val.value.length; i++) {
                    let v = val.value[i];
                    if (typeof v[1] === 'string') {
                        v[1] = StyleParser.colorForString(v[1]);
                    }
                }
            }

            // Calculate color for current zoom
            val.zoom[context.zoom] = Utils.interpolate(context.zoom, val.value);
            val.zoom[context.zoom][3] = val.zoom[context.zoom][3] || 1; // default alpha
            return val.zoom[context.zoom];
        }
        // Single array color
        else {
            val.static = val.value;
            val.static[3] = val.static[3] || 1; // default alpha
            return val.static;
        }
    }
};

StyleParser.parseColor = function(val, context = {}) {
    if (typeof val === 'function') {
        val = val(context);
    }

    // Parse CSS-style colors
    // TODO: change all colors to use 0-255 range internally to avoid dividing and then re-multiplying in geom builder
    if (typeof val === 'string') {
        val = parseCSSColor.parseCSSColor(val);
        if (val && val.length === 4) {
            val[0] /= 255;
            val[1] /= 255;
            val[2] /= 255;
        }
        else {
            val = null;
        }
    }
    else if (Array.isArray(val) && Array.isArray(val[0])) {
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        for (let i=0; i < val.length; i++) {
            let v = val[i];
            if (typeof v[1] === 'string') {
                var vc = parseCSSColor.parseCSSColor(v[1]);
                if (vc && vc.length === 4) {
                    vc[0] /= 255;
                    vc[1] /= 255;
                    vc[2] /= 255;
                    v[1] = vc;
                }
            }
        }
    }

    if (context.zoom) {
        val = Utils.interpolate(context.zoom, val);
    }

    // Defaults
    if (val) {
        // alpha
        if (!val[3]) {
            val[3] = 1;
        }
    }
    else {
        val = [0, 0, 0, 1];
    }

    return val;
};

// Order is summed from top to bottom in the style hierarchy:
// each child order value is added to the parent order value
StyleParser.calculateOrder = function(order, context) {
    if (typeof order === 'function') {
        order = order(context);
    }
    else if (Array.isArray(order)) {
        order = order.reduce((sum, order) => {
            order = order || StyleParser.defaults.order;
            if (typeof order === 'function') {
                order = order(context);
            }
            else if (typeof order === 'string') {
                order = context.feature.properties[order];
            }
            else {
                order = parseFloat(order);
            }

            if (!order || isNaN(order)) {
                return sum;
            }
            return sum + order;
        }, 0);
    }
    else if (typeof order === 'string') {
        if (context.feature.properties[order]) {
            order = context.feature.properties[order];
        }
        else {
            order = parseFloat(order);
        }
    }

    return order;
};
<commit_msg>expose `$layer` property for JS filters/properties<commit_after>import Utils from '../utils/utils';
import Geo from '../geo';

import parseCSSColor from 'csscolorparser';
import log from 'loglevel';

export var StyleParser = {};

// Style macros

StyleParser.expandMacros = function expandMacros (obj) {
    for (var p in obj) {
        var val = obj[p];

        // Loop through object properties
        if (typeof val === 'object') {
            obj[p] = expandMacros(val);
        }
        // Convert strings back into functions
        else if (typeof val === 'string') {
            for (var m in StyleParser.macros) {
                if (val.match(StyleParser.macros[m])) {
                    var f;
                    try {
                        /*jshint ignore:start */
                        eval('f = ' + val);
                        /*jshint ignore:end */
                        obj[p] = f;
                        log.trace(`expanded macro ${val} to ${f}`);
                        break;
                    }
                    catch (e) {
                        // fall-back to original value if parsing failed
                        obj[p] = val;
                        log.trace(`failed to expand macro ${val}`);
                    }
                }
            }
        }
    }

    return obj;
};

// List of macros
StyleParser.macros = [
    'Style.color.pseudoRandomColor',
    'Style.color.randomColor'
];

var Style = {};

Style.color = {
    // pseudo-random grayscale by geometry id
    pseudoRandomGrayscale() {
        var func = `function() {
            var c = Math.max((parseInt(feature.id, 16) % 100) / 100, 0.4);
            return [0.7 * c, 0.7 * c, 0.7 * c];
        }`;
        return func;
    },

    // pseudo-random color by geometry id
    pseudoRandomColor() {
        var func = `function() {
            return [
                0.7 * (parseInt(feature.id, 16) / 100 % 1),
                0.7 * (parseInt(feature.id, 16) / 10000 % 1),
                0.7 * (parseInt(feature.id, 16) / 1000000 % 1)
            ];
        }`;
        return func;
        // return `function() { return [0.7 * (parseInt(feature.id, 16) / 100 % 1), 0.7 * (parseInt(feature.id, 16) / 10000 % 1), 0.7 * (parseInt(feature.id, 16) / 1000000 % 1)]; }`;
    },

    // random color
    randomColor() {
        var func = `function() {
            return [0.7 * Math.random(), 0.7 * Math.random(), 0.7 * Math.random()];
        }`;
        return func;
    }
};

// Wraps style functions and provides a scope of commonly accessible data:
// - feature: the 'properties' of the feature, e.g. accessed as 'feature.name'
// - $zoom: the current map zoom level
// - $geometry: the type of geometry, 'point', 'line', or 'polygon'
// - $meters_per_pixel: conversion for meters/pixels at current map zoom
// - properties: user-defined properties on the style-rule object in the stylesheet
StyleParser.wrapFunction = function (func) {
    var f = `function(context) {
                var feature = context.feature.properties;
                var $zoom = context.zoom;
                var $layer = context.layer;
                var $geometry = context.geometry;
                var $meters_per_pixel = context.meters_per_pixel;
                var properties = context.properties;
                return (${func}());
            }`;
    return f;
};

// Style parsing

// Style defaults
StyleParser.defaults = {
    color: [1, 1, 1, 1],
    width: 1,
    size: 1,
    extrude: false,
    height: 20,
    min_height: 0,
    order: 0,
    z: 0,
    material: {
        ambient: 1,
        diffuse: 1
    }
};

// A context object that is passed to style parsing functions to provide a scope of commonly used values
StyleParser.getFeatureParseContext = function (feature, tile) {
    return {
        feature,
        tile,
        zoom: tile.style_zoom,
        geometry: Geo.geometryType(feature.geometry.type),
        meters_per_pixel: Geo.metersPerPixel(tile.coords.z),
        units_per_meter: Geo.units_per_meter[tile.coords.z]
    };
};

StyleParser.convertUnits = function(val, context, convert = 'meters') {
    if (typeof val === 'string') {
        var units = val.match(/([0-9.-]+)([a-z]+)/);
        if (units && units.length === 3) {
            val = parseFloat(units[1]);
            units = units[2];
        }

        // Convert to meters
        if (convert === 'meters') {
            // Convert from pixels
            if (units === 'px') {
                val *= Geo.metersPerPixel(context.zoom);
            }
            // Convert from kilometers
            else if (units === 'km') {
                val *= 1000;
            }
        }
    }
    else if (Array.isArray(val)) {
        // Array of arrays, e.g. zoom-interpolated stops
        if (Array.isArray(val[0])) {
            return val.map(v => { return [v[0], StyleParser.convertUnits(v[1], context, convert)]; });
        }
        // Array of values
        else {
            return val.map(v => { return StyleParser.convertUnits(v, context, convert); });
        }
    }
    return val;
};

// Takes a distance cache object and returns a distance value for this zoom
// (caching the result for future use)
// { value: original, zoom: { z: meters }, dynamic: function(){...} }
StyleParser.cacheDistance = function(val, context, convert = 'meters') {
    if (val.dynamic) {
        let v = val.dynamic(context);
        return v;
    }
    else if (val.zoom && val.zoom[convert] && val.zoom[convert][context.zoom]) {
        return val.zoom[convert][context.zoom];
    }
    else {
        // Dynamic function-based
        if (typeof val.value === 'function') {
            val.dynamic = val.value;
            let v = val.dynamic(context);
            return v;
        }
        // Array of zoom-interpolated stops, e.g. [zoom, value] pairs
        else {
            // Calculate value for current zoom
            val.zoom = val.zoom || {};
            let zunits = val.zoom[convert] = val.zoom[convert] || {};

            zunits[context.zoom] = StyleParser.convertUnits(val.value, context,
                convert === 'meters' && 'meters'); // convert to meters
            zunits[context.zoom] = Utils.interpolate(context.zoom, zunits[context.zoom]);

            return zunits[context.zoom];
        }
    }
};

// Cache previously parsed color strings
StyleParser.string_colors = {};
StyleParser.colorForString = function(string) {
    // Cached
    if (StyleParser.string_colors[string]) {
        return StyleParser.string_colors[string];
    }

    // Calculate and cache
    let color = parseCSSColor.parseCSSColor(string);
    if (color && color.length === 4) {
        color[0] /= 255;
        color[1] /= 255;
        color[2] /= 255;
        color[3] = 1;
    }
    else {
        color = StyleParser.defaults.color;
    }
    StyleParser.string_colors[string] = color;
    return color;
};

// Takes a color cache object and returns a color value for this zoom
// (caching the result for future use)
// { value: original, static: [r,g,b,a], zoom: { z: [r,g,b,a] }, dynamic: function(){...} }
StyleParser.cacheColor = function(val, context = {}) {
    if (val.dynamic) {
        let v = val.dynamic(context);
        v[3] = v[3] || 1; // default alpha
        return v;
    }
    else if (val.static) {
        return val.static;
    }
    else if (val.zoom && val.zoom[context.zoom]) {
        return val.zoom[context.zoom];
    }
    else {
        // Dynamic function-based color
        if (typeof val.value === 'function') {
            val.dynamic = val.value;
            let v = val.dynamic(context);
            v[3] = v[3] || 1; // default alpha
            return v;
        }
        // Single string color
        else if (typeof val.value === 'string') {
            val.static = StyleParser.colorForString(val.value);
            return val.static;
        }
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        else if (Array.isArray(val.value) && Array.isArray(val.value[0])) {
            if (!val.zoom) {
                val.zoom = {};
                // Parse any string colors inside stops
                for (let i=0; i < val.value.length; i++) {
                    let v = val.value[i];
                    if (typeof v[1] === 'string') {
                        v[1] = StyleParser.colorForString(v[1]);
                    }
                }
            }

            // Calculate color for current zoom
            val.zoom[context.zoom] = Utils.interpolate(context.zoom, val.value);
            val.zoom[context.zoom][3] = val.zoom[context.zoom][3] || 1; // default alpha
            return val.zoom[context.zoom];
        }
        // Single array color
        else {
            val.static = val.value;
            val.static[3] = val.static[3] || 1; // default alpha
            return val.static;
        }
    }
};

StyleParser.parseColor = function(val, context = {}) {
    if (typeof val === 'function') {
        val = val(context);
    }

    // Parse CSS-style colors
    // TODO: change all colors to use 0-255 range internally to avoid dividing and then re-multiplying in geom builder
    if (typeof val === 'string') {
        val = parseCSSColor.parseCSSColor(val);
        if (val && val.length === 4) {
            val[0] /= 255;
            val[1] /= 255;
            val[2] /= 255;
        }
        else {
            val = null;
        }
    }
    else if (Array.isArray(val) && Array.isArray(val[0])) {
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        for (let i=0; i < val.length; i++) {
            let v = val[i];
            if (typeof v[1] === 'string') {
                var vc = parseCSSColor.parseCSSColor(v[1]);
                if (vc && vc.length === 4) {
                    vc[0] /= 255;
                    vc[1] /= 255;
                    vc[2] /= 255;
                    v[1] = vc;
                }
            }
        }
    }

    if (context.zoom) {
        val = Utils.interpolate(context.zoom, val);
    }

    // Defaults
    if (val) {
        // alpha
        if (!val[3]) {
            val[3] = 1;
        }
    }
    else {
        val = [0, 0, 0, 1];
    }

    return val;
};

// Order is summed from top to bottom in the style hierarchy:
// each child order value is added to the parent order value
StyleParser.calculateOrder = function(order, context) {
    if (typeof order === 'function') {
        order = order(context);
    }
    else if (Array.isArray(order)) {
        order = order.reduce((sum, order) => {
            order = order || StyleParser.defaults.order;
            if (typeof order === 'function') {
                order = order(context);
            }
            else if (typeof order === 'string') {
                order = context.feature.properties[order];
            }
            else {
                order = parseFloat(order);
            }

            if (!order || isNaN(order)) {
                return sum;
            }
            return sum + order;
        }, 0);
    }
    else if (typeof order === 'string') {
        if (context.feature.properties[order]) {
            order = context.feature.properties[order];
        }
        else {
            order = parseFloat(order);
        }
    }

    return order;
};
<|endoftext|>


<commit_before>import Utils from '../utils/utils';
import Geo from '../geo';

import parseCSSColor from 'csscolorparser';
import log from 'loglevel';

export var StyleParser = {};

// Style macros

StyleParser.expandMacros = function expandMacros (obj) {
    for (var p in obj) {
        var val = obj[p];

        // Loop through object properties
        if (typeof val === 'object') {
            obj[p] = expandMacros(val);
        }
        // Convert strings back into functions
        else if (typeof val === 'string') {
            for (var m in StyleParser.macros) {
                if (val.match(StyleParser.macros[m])) {
                    var f;
                    try {
                        /*jshint ignore:start */
                        eval('f = ' + val);
                        /*jshint ignore:end */
                        obj[p] = f;
                        log.trace(`expanded macro ${val} to ${f}`);
                        break;
                    }
                    catch (e) {
                        // fall-back to original value if parsing failed
                        obj[p] = val;
                        log.trace(`failed to expand macro ${val}`);
                    }
                }
            }
        }
    }

    return obj;
};

// List of macros
StyleParser.macros = [
    'Style.color.pseudoRandomColor',
    'Style.color.randomColor',
    'Style.pixels'
];

var Style = {};

Style.color = {
    // pseudo-random grayscale by geometry id
    pseudoRandomGrayscale() {
        var func = `function() {
            var c = Math.max((parseInt(feature.osm_id, 16) % 100) / 100, 0.4);
            return [0.7 * c, 0.7 * c, 0.7 * c];
        }`;
        return func;
    },

    // pseudo-random color by geometry id
    pseudoRandomColor() {
        var func = `function() {
            return [
                0.7 * (parseInt(feature.osm_id, 16) / 100 % 1),
                0.7 * (parseInt(feature.osm_id, 16) / 10000 % 1),
                0.7 * (parseInt(feature.osm_id, 16) / 1000000 % 1)
            ];
        }`;
        return func;
        // return `function() { return [0.7 * (parseInt(feature.osm_id, 16) / 100 % 1), 0.7 * (parseInt(feature.osm_id, 16) / 10000 % 1), 0.7 * (parseInt(feature.osm_id, 16) / 1000000 % 1)]; }`;
    },

    // random color
    randomColor() {
        var func = `function() {
            return [0.7 * Math.random(), 0.7 * Math.random(), 0.7 * Math.random()];
        }`;
        return func;
    }
};

// Returns a function (that can be used as a dynamic style) that converts pixels to meters for the current zoom level.
// The provided pixel value ('p') can itself be a function, in which case it is wrapped by this one.
Style.pixels = function (p) {
    var f;
    f = 'function() { return ' + (typeof p === 'function' ? '(' + (p.toString() + '())') : p) + ' * $meters_per_pixel; }';
    return f;
};

// Wraps style functions and provides a scope of commonly accessible data:
// - feature: the 'properties' of the feature, e.g. accessed as 'feature.name'
// - $zoom: the current map zoom level
// - $geometry: the type of geometry, 'point', 'line', or 'polygon'
// - $meters_per_pixel: conversion for meters/pixels at current map zoom
// - properties: user-defined properties on the style-rule object in the stylesheet
StyleParser.wrapFunction = function (func) {
    var f = `function(context) {
                var feature = context.feature.properties;
                var $zoom = context.zoom;
                var $geometry = context.geometry;
                var $meters_per_pixel = context.meters_per_pixel;
                var properties = context.properties;
                return (${func}());
            }`;
    return f;
};

// Style parsing

// Style defaults
StyleParser.defaults = {
    color: [1.0, 0, 0],
    width: 1,
    size: 1,
    extrude: false,
    height: 20,
    min_height: 0,
    order: 0,
    z: 0,
    material: {
        ambient: 1,
        diffuse: 1
    }
};

// A context object that is passed to style parsing functions to provide a scope of commonly used values
StyleParser.getFeatureParseContext = function (feature, tile) {
    return {
        feature,
        tile,
        zoom: tile.coords.z,
        geometry: Geo.geometryType(feature.geometry.type),
        meters_per_pixel: Geo.metersPerPixel(tile.coords.z),
        units_per_meter: Geo.units_per_meter[tile.coords.z]
    };
};

StyleParser.convertUnits = function(val, context, convert = true) {
    if (typeof val === 'string') {
        var units = val.match(/([0-9.-]+)([a-z]+)/);
        if (units && units.length === 3) {
            val = parseFloat(units[1]);
            units = units[2];
        }

        if (convert) {
            // Convert from pixels
            if (units === 'px') {
                val *= Geo.metersPerPixel(context.zoom);
            }
            // Convert from kilometers
            else if (units === 'km') {
                val *= 1000;
            }
        }
    }
    else if (Array.isArray(val)) {
        // Array of arrays, e.g. zoom-interpolated stops
        if (val.every(v => { return Array.isArray(v); })) {
            return val.map(v => { return [v[0], StyleParser.convertUnits(v[1], context, convert)]; });
        }
        // Array of values
        else {
            return val.map(v => { return StyleParser.convertUnits(v, context, convert); });
        }
    }
    return val;
};

StyleParser.parseDistance = function(val, context, convert = true) {
    if (typeof val === 'function') {
        val = val(context);
    }
    val = StyleParser.convertUnits(val, context, convert);
    val = Utils.interpolate(context.zoom, val);

    if (convert) {
        if (typeof val === 'number') {
            val *= context.units_per_meter;
        }
        else if (Array.isArray(val)) {
            val.forEach((v, i) => val[i] *= context.units_per_meter);
        }
    }
    return val;
};

StyleParser.parseColor = function(val, context = {}) {
    if (typeof val === 'function') {
        val = val(context);
    }

    // Parse CSS-style colors
    // TODO: change all colors to use 0-255 range internally to avoid dividing and then re-multiplying in geom builder
    if (typeof val === 'string') {
        val = parseCSSColor.parseCSSColor(val);
        if (val && val.length === 4) {
            val = val.slice(0, 3).map(c => { return c / 255; });
        }
        else {
            val = null;
        }
    }
    else if (Array.isArray(val) && val.every(v => { return Array.isArray(v); })) {
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        val = val.map(v => {
            if (typeof v[1] === 'string') {
                var vc = parseCSSColor.parseCSSColor(v[1]);
                if (vc && vc.length === 4) {
                    vc = vc.slice(0, 3).map(c => { return c / 255; });
                }
                return [v[0], vc];
            }
            return v;
        });
    }

    if (context.zoom) {
        val = Utils.interpolate(context.zoom, val);
    }

    // Defaults
    if (val) {
        // alpha
        if (!val[3]) {
            val[3] = 1;
        }
    }
    else {
        val = [0, 0, 0, 1];
    }

    return val;
};

// Order is summed from top to bottom in the style hierarchy:
// each child order value is added to the parent order value
StyleParser.calculateOrder = function(order, context) {
    if (typeof order === 'function') {
        order = order(context);
    }
    else if (Array.isArray(order)) {
        order = order.reduce((sum, order) => {
            order = order || StyleParser.defaults.order;
            if (typeof order === 'function') {
                order = order(context);
            }
            else if (typeof order === 'string') {
                order = context.feature.properties[order];
            }
            else {
                order = parseFloat(order);
            }

            if (!order || isNaN(order)) {
                return sum;
            }
            return sum + order;
        }, 0);
    }
    else if (typeof order === 'string') {
        order = context.feature.properties[order];
    }
    else {
        order = parseFloat(order);
    }

    return order;
};
<commit_msg>temporary fix for osm_id (until tile data is normalized)<commit_after>import Utils from '../utils/utils';
import Geo from '../geo';

import parseCSSColor from 'csscolorparser';
import log from 'loglevel';

export var StyleParser = {};

// Style macros

StyleParser.expandMacros = function expandMacros (obj) {
    for (var p in obj) {
        var val = obj[p];

        // Loop through object properties
        if (typeof val === 'object') {
            obj[p] = expandMacros(val);
        }
        // Convert strings back into functions
        else if (typeof val === 'string') {
            for (var m in StyleParser.macros) {
                if (val.match(StyleParser.macros[m])) {
                    var f;
                    try {
                        /*jshint ignore:start */
                        eval('f = ' + val);
                        /*jshint ignore:end */
                        obj[p] = f;
                        log.trace(`expanded macro ${val} to ${f}`);
                        break;
                    }
                    catch (e) {
                        // fall-back to original value if parsing failed
                        obj[p] = val;
                        log.trace(`failed to expand macro ${val}`);
                    }
                }
            }
        }
    }

    return obj;
};

// List of macros
StyleParser.macros = [
    'Style.color.pseudoRandomColor',
    'Style.color.randomColor',
    'Style.pixels'
];

var Style = {};

Style.color = {
    // pseudo-random grayscale by geometry id
    pseudoRandomGrayscale() {
        var func = `function() {
            var c = Math.max((parseInt(feature.osm_id, 16) % 100) / 100, 0.4);
            return [0.7 * c, 0.7 * c, 0.7 * c];
        }`;
        return func;
    },

    // pseudo-random color by geometry id
    pseudoRandomColor() {
        var func = `function() {
            return [
                0.7 * (parseInt(feature.osm_id, 16) / 100 % 1),
                0.7 * (parseInt(feature.osm_id, 16) / 10000 % 1),
                0.7 * (parseInt(feature.osm_id, 16) / 1000000 % 1)
            ];
        }`;
        return func;
        // return `function() { return [0.7 * (parseInt(feature.osm_id, 16) / 100 % 1), 0.7 * (parseInt(feature.osm_id, 16) / 10000 % 1), 0.7 * (parseInt(feature.osm_id, 16) / 1000000 % 1)]; }`;
    },

    // random color
    randomColor() {
        var func = `function() {
            return [0.7 * Math.random(), 0.7 * Math.random(), 0.7 * Math.random()];
        }`;
        return func;
    }
};

// Returns a function (that can be used as a dynamic style) that converts pixels to meters for the current zoom level.
// The provided pixel value ('p') can itself be a function, in which case it is wrapped by this one.
Style.pixels = function (p) {
    var f;
    f = 'function() { return ' + (typeof p === 'function' ? '(' + (p.toString() + '())') : p) + ' * $meters_per_pixel; }';
    return f;
};

// Wraps style functions and provides a scope of commonly accessible data:
// - feature: the 'properties' of the feature, e.g. accessed as 'feature.name'
// - $zoom: the current map zoom level
// - $geometry: the type of geometry, 'point', 'line', or 'polygon'
// - $meters_per_pixel: conversion for meters/pixels at current map zoom
// - properties: user-defined properties on the style-rule object in the stylesheet
StyleParser.wrapFunction = function (func) {
    var f = `function(context) {
                var feature = context.feature.properties;
                var $zoom = context.zoom;
                var $geometry = context.geometry;
                var $meters_per_pixel = context.meters_per_pixel;
                var properties = context.properties;

                // TODO: remove once tile feature ids are normalized
                feature.osm_id = feature.osm_id || feature.uid || context.feature.id;

                return (${func}());
            }`;
    return f;
};

// Style parsing

// Style defaults
StyleParser.defaults = {
    color: [1.0, 0, 0],
    width: 1,
    size: 1,
    extrude: false,
    height: 20,
    min_height: 0,
    order: 0,
    z: 0,
    material: {
        ambient: 1,
        diffuse: 1
    }
};

// A context object that is passed to style parsing functions to provide a scope of commonly used values
StyleParser.getFeatureParseContext = function (feature, tile) {
    return {
        feature,
        tile,
        zoom: tile.coords.z,
        geometry: Geo.geometryType(feature.geometry.type),
        meters_per_pixel: Geo.metersPerPixel(tile.coords.z),
        units_per_meter: Geo.units_per_meter[tile.coords.z]
    };
};

StyleParser.convertUnits = function(val, context, convert = true) {
    if (typeof val === 'string') {
        var units = val.match(/([0-9.-]+)([a-z]+)/);
        if (units && units.length === 3) {
            val = parseFloat(units[1]);
            units = units[2];
        }

        if (convert) {
            // Convert from pixels
            if (units === 'px') {
                val *= Geo.metersPerPixel(context.zoom);
            }
            // Convert from kilometers
            else if (units === 'km') {
                val *= 1000;
            }
        }
    }
    else if (Array.isArray(val)) {
        // Array of arrays, e.g. zoom-interpolated stops
        if (val.every(v => { return Array.isArray(v); })) {
            return val.map(v => { return [v[0], StyleParser.convertUnits(v[1], context, convert)]; });
        }
        // Array of values
        else {
            return val.map(v => { return StyleParser.convertUnits(v, context, convert); });
        }
    }
    return val;
};

StyleParser.parseDistance = function(val, context, convert = true) {
    if (typeof val === 'function') {
        val = val(context);
    }
    val = StyleParser.convertUnits(val, context, convert);
    val = Utils.interpolate(context.zoom, val);

    if (convert) {
        if (typeof val === 'number') {
            val *= context.units_per_meter;
        }
        else if (Array.isArray(val)) {
            val.forEach((v, i) => val[i] *= context.units_per_meter);
        }
    }
    return val;
};

StyleParser.parseColor = function(val, context = {}) {
    if (typeof val === 'function') {
        val = val(context);
    }

    // Parse CSS-style colors
    // TODO: change all colors to use 0-255 range internally to avoid dividing and then re-multiplying in geom builder
    if (typeof val === 'string') {
        val = parseCSSColor.parseCSSColor(val);
        if (val && val.length === 4) {
            val = val.slice(0, 3).map(c => { return c / 255; });
        }
        else {
            val = null;
        }
    }
    else if (Array.isArray(val) && val.every(v => { return Array.isArray(v); })) {
        // Array of zoom-interpolated stops, e.g. [zoom, color] pairs
        val = val.map(v => {
            if (typeof v[1] === 'string') {
                var vc = parseCSSColor.parseCSSColor(v[1]);
                if (vc && vc.length === 4) {
                    vc = vc.slice(0, 3).map(c => { return c / 255; });
                }
                return [v[0], vc];
            }
            return v;
        });
    }

    if (context.zoom) {
        val = Utils.interpolate(context.zoom, val);
    }

    // Defaults
    if (val) {
        // alpha
        if (!val[3]) {
            val[3] = 1;
        }
    }
    else {
        val = [0, 0, 0, 1];
    }

    return val;
};

// Order is summed from top to bottom in the style hierarchy:
// each child order value is added to the parent order value
StyleParser.calculateOrder = function(order, context) {
    if (typeof order === 'function') {
        order = order(context);
    }
    else if (Array.isArray(order)) {
        order = order.reduce((sum, order) => {
            order = order || StyleParser.defaults.order;
            if (typeof order === 'function') {
                order = order(context);
            }
            else if (typeof order === 'string') {
                order = context.feature.properties[order];
            }
            else {
                order = parseFloat(order);
            }

            if (!order || isNaN(order)) {
                return sum;
            }
            return sum + order;
        }, 0);
    }
    else if (typeof order === 'string') {
        order = context.feature.properties[order];
    }
    else {
        order = parseFloat(order);
    }

    return order;
};
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.config');

const serverConfig = () => {
  return {
    output: {
      path: path.resolve('.cache/ssr-build'), // Don't bloat `public` dir
			libraryTarget: 'commonjs2' // Use module.exports
    },
    target: 'node', // Load chunks using require
    plugins: [
      new webpack.DefinePlugin({
        'process.env.PRERENDER': true // In app.js don't call ReactDOM.render
      }),
    ],
    optimization: {
      removeAvailableModules: false,
      removeEmptyChunks: false,
      splitChunks: false,
      minimize: false // Faster build, easier debugging
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: 'null-loader'
        },
        // This does weird things to document
        {
          test: /novnc-core\/.*\.js/,
          use: 'null-loader'
        }
      ]
    },
    resolve: {
      alias: {
        // This stops prerender from hanging in `yarn build:client`
        'd3-timer': 'theme-patternfly-org/helpers/d3-timer',
        // The maintainer will not allow his bundle to be required from a node context
        // https://github.com/xtermjs/xterm.js/pull/3134
        'xterm':  'theme-patternfly-org/helpers/xterm',
        'xterm-addon-fit':  'theme-patternfly-org/helpers/xterm-addon-fit',
      },
    },
    // Load in prerender.js instead
    externals: ['react', 'react-dom', '@reach/router']
  };
}

module.exports = (env = {}, argv) => merge(
  baseConfig(env, argv),
  serverConfig(env, argv)
);
<commit_msg>handle @novnc/novnc (#2301)<commit_after>const path = require('path');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.config');

const serverConfig = () => {
  return {
    output: {
      path: path.resolve('.cache/ssr-build'), // Don't bloat `public` dir
			libraryTarget: 'commonjs2' // Use module.exports
    },
    target: 'node', // Load chunks using require
    plugins: [
      new webpack.DefinePlugin({
        'process.env.PRERENDER': true // In app.js don't call ReactDOM.render
      }),
    ],
    optimization: {
      removeAvailableModules: false,
      removeEmptyChunks: false,
      splitChunks: false,
      minimize: false // Faster build, easier debugging
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: 'null-loader'
        },
        // This does weird things to document
        {
          test: /(novnc-core|@novnc\/novnc)\/.*\.js/,
          use: 'null-loader'
        }
      ]
    },
    resolve: {
      alias: {
        // This stops prerender from hanging in `yarn build:client`
        'd3-timer': 'theme-patternfly-org/helpers/d3-timer',
        // The maintainer will not allow his bundle to be required from a node context
        // https://github.com/xtermjs/xterm.js/pull/3134
        'xterm':  'theme-patternfly-org/helpers/xterm',
        'xterm-addon-fit':  'theme-patternfly-org/helpers/xterm-addon-fit',
      },
    },
    // Load in prerender.js instead
    externals: ['react', 'react-dom', '@reach/router']
  };
}

module.exports = (env = {}, argv) => merge(
  baseConfig(env, argv),
  serverConfig(env, argv)
);
<|endoftext|>


<commit_before>import EmberObject from '@ember/object';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { timeout } from 'ember-concurrency';
import { render, click, waitFor } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import DS from 'ember-data';

let model;

module('Integration | Component | cs version control', function(hooks) {
  setupRenderingTest(hooks);

  hooks.beforeEach(function() {
    // We need a valid model here because the component will go
    // looking for its metadata, and ember-resource-metadata works
    // through ember-data's identity map.
    this.owner.register('model:thing', DS.Model.extend());
    model = EmberObject.create({
      id: 1,
      type: 'thing',
      serialize() {
        return {
          id: '1',
          type: 'things',
          data: {
            attributes: {}
          }
        }
      }
    });
    this.set('model', model);
    this.meta = this.owner.lookup('service:resource-metadata');
    this.get('meta').write(model, { branch: 'master' });
    this.owner.register('config:enviroment', {
      cardstack: { defaultBranch: 'master' }
    });
    this.owner.lookup('router:main').setupRouter();
  });

  test('render with saved content', async function(assert) {
    model.set('hasDirtyFields', false);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control--button.disabled').hasText('Save');
  });

  test('render with dirty content', async function(assert) {
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control--button.disabled').doesNotExist('no disabled button');
    assert.dom('.cs-version-control--button-save.enabled').hasText('Save');
  });

  test('clicking update on dirty model triggers save', async function(assert) {
    assert.expect(1);
    model.set('save', function() {
      assert.ok(true);
    });
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--button-save.enabled');
  });

  test('clicking update shows loading spinner', async function(assert) {
    assert.expect(2);
    model.set('save', async () => await timeout(5));
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    assert.notOk(this.$('.cs-version-control--loading').length, 'Does not display loading before click');
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    click('.cs-version-control--button-save');
    await waitFor('.cs-version-control--loading');
    assert.ok(this.$('.cs-version-control--loading').length, 'Displays loading after click');
  });

  test('clicking update on clean model does nothing', async function(assert) {
    assert.expect(0);
    model.set('save', function() {
      throw new Error("should not happen");
    });
    model.set('hasDirtyFields', false);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--button-save');
  });

  test('clicking delete triggers deleteRecord', async function(assert) {
    assert.expect(1);
    model.set('destroyRecord', function() {
      assert.ok(true);
    });
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--delete-button');
  });
});
<commit_msg>Add tests for current status in cs-version-control<commit_after>import EmberObject from '@ember/object';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { timeout } from 'ember-concurrency';
import { render, click, waitFor } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import DS from 'ember-data';

let model;

module('Integration | Component | cs version control', function(hooks) {
  setupRenderingTest(hooks);

  hooks.beforeEach(function() {
    // We need a valid model here because the component will go
    // looking for its metadata, and ember-resource-metadata works
    // through ember-data's identity map.
    this.owner.register('model:thing', DS.Model.extend());
    model = EmberObject.create({
      id: 1,
      type: 'thing',
      serialize() {
        return {
          id: '1',
          type: 'things',
          data: {
            attributes: {}
          }
        }
      }
    });
    this.set('model', model);
    this.meta = this.owner.lookup('service:resource-metadata');
    this.get('meta').write(model, { branch: 'master' });
    this.owner.register('config:enviroment', {
      cardstack: { defaultBranch: 'master' }
    });
    this.owner.lookup('router:main').setupRouter();
  });

  test('render with saved content', async function(assert) {
    model.set('hasDirtyFields', false);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control--button.disabled').hasText('Save');
  });

  test('render with dirty content', async function(assert) {
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control--button.disabled').doesNotExist('no disabled button');
    assert.dom('.cs-version-control--button-save.enabled').hasText('Save');
  });

  test('clicking update on dirty model triggers save', async function(assert) {
    assert.expect(1);
    model.set('save', function() {
      assert.ok(true);
    });
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--button-save.enabled');
  });

  test('clicking update shows loading spinner', async function(assert) {
    assert.expect(2);
    model.set('save', async () => await timeout(5));
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    assert.notOk(this.$('.cs-version-control--loading').length, 'Does not display loading before click');
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    click('.cs-version-control--button-save');
    await waitFor('.cs-version-control--loading');
    assert.ok(this.$('.cs-version-control--loading').length, 'Displays loading after click');
  });

  test('clicking update on clean model does nothing', async function(assert) {
    assert.expect(0);
    model.set('save', function() {
      throw new Error("should not happen");
    });
    model.set('hasDirtyFields', false);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--button-save');
  });

  test('clicking delete triggers deleteRecord', async function(assert) {
    assert.expect(1);
    model.set('destroyRecord', function() {
      assert.ok(true);
    });
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    await click('.cs-version-control--delete-button');
  });

  test('"draft" status is displayed for new model', async function (assert) {
    model.set('isNew', true);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control-dropdown-option--status').hasText('draft');
  });

  test('"published" status is displayed for clean model', async function (assert) {
    model.set('hasDirtyFields', false);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control-dropdown-option--status').hasText('published');
  });

  test('"edited" status is displayed for dirty model', async function (assert) {
    model.set('hasDirtyFields', true);
    model.set('isNew', false);
    await render(hbs`{{cs-version-control model=model enabled=true}}`);
    assert.dom('.cs-version-control-dropdown-option--status').hasText('edited');
  });
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var scss = require('gulp-sass');
var uglify = require('gulp-uglify');
var webpack = require('gulp-webpack');

gulp.task('default', function () {
    console.log('Hello,gulp!');
});

gulp.task('scss', function () {
    gulp.src('scss/**/*.scss')
        .pipe(scss())
        .pipe(gulp.dest('css'));
});

gulp.task('scss:watch', function () {
    gulp.watch('scss/**/*.scss', ['scss']);
});

gulp.task('jscompile', function () {
    gulp.src('js/**/twitter.js')
        .pipe(webpack({
            output: {
                filename: 'twitter.min.js'
            }
        }))
        .pipe(uglify())
        .pipe(gulp.dest('../../../../target/classes/static/js'));
});

gulp.task('jswatch', function () {
    gulp.watch('js/**/*.js', ['jscompile']);
});<commit_msg>cssとjsのコンパイル先を修正<commit_after>var gulp = require('gulp');
var scss = require('gulp-sass');
var uglify = require('gulp-uglify');
var webpack = require('gulp-webpack');
var TARGET_PATH = '../../../../target/classes/static/';

gulp.task('default', function () {
    console.log('Hello,gulp!');
});

gulp.task('scss', function () {
    gulp.src('scss/**/*.scss')
        .pipe(scss())
        .pipe(gulp.dest(TARGET_PATH + 'css'));
});

gulp.task('scss:watch', function () {
    gulp.watch('scss/**/*.scss', ['scss']);
});

gulp.task('jscompile', function () {
    gulp.src('js/**/twitter.js')
        .pipe(webpack({
            output: {
                filename: 'twitter.min.js'
            }
        }))
        .pipe(uglify())
        .pipe(gulp.dest(TARGET_PATH + 'js'));
});

gulp.task('jswatch', function () {
    gulp.watch('js/**/*.js', ['jscompile']);
});<|endoftext|>


<commit_before>angular.module('hello', ['ui.bootstrap'])
    .controller('home', function ($scope, $http) {
        $scope.activities = [];
        $scope.activeFilter = "";
        $scope.errorMessage;
        $scope.hideCompleted = false;

        $scope.priorities = {
            prioOne: "A",
            prioTwo: "B",
            prioThree: "C",
            prioFour: "D",
            prioFive: "E",
            prioSix: "F"
        }

        $http.get('/initialize').then(function (response) {
                $scope.loadActivities();
            },
            function (errorResponse) {
                $scope.errorMessage = 'error initializing application';
            });

        $scope.getErrorMessage = function () {
            return errorMessage;
        }

        $scope.toggleHideCompleted = function () {
            $scope.hideCompleted = !$scope.hideCompleted;
        }

        $scope.getHideCompleted = function () {
            return $scope.hideCompleted;
        }

        $scope.loadActivities = function () {
            $scope.activities.length = 0;
            $http.get('/getActivities').then(function (response) {
                    console.log(response);
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities';
                });
        };

        $scope.loadActivtiesByTag = function (tag) {
            $scope.activeFilter = tag;
            $scope.activities.length = 0;
            $scope.toggleFilterVisibility();
            $http.post('/getActivitiesByTag', tag).then(function (response) {
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities by tag';
                });
        }

        $scope.loadActivtiesByProject = function (project) {
            $scope.activeFilter = project;
            $scope.activities = [];
            $scope.toggleFilterVisibility();
            $http.post('/getActivitiesByProject', project).then(function (response) {
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities by project';
                });
        }

        $scope.clearFilter = function () {
            $scope.activeFilter = "";
            $scope.toggleFilterVisibility();
            $scope.activities = [];
            $scope.loadActivities();
        }

        $scope.toggleFilterVisibility = function () {
            var div = document.getElementById("filterDisplay");
            div.style.display = div.style.display == "none" ? "block" : "none";
        }

        $scope.getDone = function (isDone) {
            if (isDone == true) {
                return 'fa fa-calendar-check-o';
            } else {
                return 'fa fa-calendar-times-o';
            }
        };

        $scope.getTodoToggleText = function (isDone) {
            if (isDone == true) {
                return "Didn't do it";
            } else {
                return "I did it!";
            }
        }

        $scope.getHeaderTemplate = function (isDone) {
            if (isDone == true) {
                return "color: #4cae4c;";
            } else {
                return "";
            }
        }

        $scope.save = function (name) {
            for (i in $scope.activities) {
                if ($scope.activities[i].name == name) {
                    let activity = $scope.activities[i];
                    if (activity.deadline == undefined) {
                        delete activity.deadline;
                    }
                    if (activity.completionDate == undefined) {
                        delete activity.completionDate;
                    }
                    if (activity.projects == undefined || activity.projects.length < 1) {
                        delete activity.projects;
                    }
                    if (activity.tags == undefined || activity.tags.length < 1) {
                        delete activity.tags;
                    }

                    $http.post('/save', activity).then(function (response) {
                            $scope.loadActivities();
                            return;
                        },
                        function (response) {
                            $scope.errorMessage = "Error while saving activity";
                        });

                }
            }
        };

        $scope.delete = function (name) {
            for (i in $scope.activities) {
                if ($scope.activities[i].name == name) {
                    let activity = $scope.activities[i];
                    if (activity.deadline == undefined) {
                        delete activity.deadline;
                    }
                    if (activity.completionDate == undefined) {
                        delete activity.completionDate;
                    }
                    if (activity.projects.length < 1) {
                        delete activity.projects;
                    }

                    $http.post('/delete', activity);
                    $scope.activities.splice(i, 1);
                    return;
                }
            }
        };

        $scope.getPanelStyle = function (name) {
            if ($scope.isUrgent(name)) {
                return 'panel-danger';
            } else {
                return 'panel-default';
            }
        }

        $scope.isUrgent = function (name) {
            var today = new Date();
            for (i in $scope.activities) {
                if ($scope.activities[i].name == name) {
                    let activity = $scope.activities[i];
                    if (activity.deadline != undefined) {
                        var deadlineDate = new Date(activity.deadline);
                        var warningDate = new Date(deadlineDate.getFullYear(), deadlineDate.getMonth(), deadlineDate.getDay() - 1);
                        if (today >= warningDate && !activity.completed) {
                            return true;
                        } else {
                            return false;
                        }
                    }
                }
            }
            return false;
        }

        $scope.addActivity = function () {

            var activity = {
                name: $scope.name,
                completed: false,
                deadline: $scope.deadline,
                priority: $scope.selectedPriority,
                tags: [],
                projects: []
            };
            if ($scope.tags) {
                let tagList = $scope.tags.split(",");
                if (tagList.length > 0) {
                    activity.tags = tagList;
                }
            }

            if ($scope.projects) {
                let projectList = $scope.projects.split(",");
                if (projectList.length > 0) {
                    activity.projects = projectList;
                }
            }

            $scope.activities.push(activity);
            $scope.save(activity.name);
        }

        $scope.togglediv = function (id) {
            var div = document.getElementById(id);
            div.style.display = div.style.display == "none" ? "block" : "none";
        }

        $scope.today = function () {
            $scope.dt = new Date();
        };
        $scope.today();

        $scope.clear = function () {
            $scope.dt = null;
        };

        $scope.inlineOptions = {
            customClass: getDayClass,
            minDate: new Date(),
            showWeeks: true
        };

        $scope.dateOptions = {
            dateDisabled: disabled,
            formatYear: 'yy',
            maxDate: new Date(2020, 5, 22),
            minDate: new Date(),
            startingDay: 1
        };

        // Disable weekend selection
        function disabled(data) {
            var date = data.date,
                mode = data.mode;
            //return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
            return false;
        }

        $scope.toggleMin = function () {
            $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date();
            $scope.dateOptions.minDate = $scope.inlineOptions.minDate;
        };

        $scope.toggleMin();

        $scope.open1 = function () {
            $scope.popup1.opened = true;
        };

        $scope.open2 = function () {
            $scope.popup2.opened = true;
        };

        $scope.setDate = function (year, month, day) {
            $scope.dt = new Date(year, month, day);
        };

        $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.format = $scope.formats[0];
        $scope.altInputFormats = ['M!/d!/yyyy'];

        $scope.popup1 = {
            opened: false
        };

        $scope.popup2 = {
            opened: false
        };

        var tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        var afterTomorrow = new Date();
        afterTomorrow.setDate(tomorrow.getDate() + 1);
        $scope.events = [
            {
                date: tomorrow,
                status: 'full'
            },
            {
                date: afterTomorrow,
                status: 'partially'
            }
        ];

        function getDayClass(data) {
            var date = data.date,
                mode = data.mode;
            if (mode === 'day') {
                var dayToCheck = new Date(date).setHours(0, 0, 0, 0);

                for (var i = 0; i < $scope.events.length; i++) {
                    var currentDay = new Date($scope.events[i].date).setHours(0, 0, 0, 0);

                    if (dayToCheck === currentDay) {
                        return $scope.events[i].status;
                    }
                }
            }

            return '';
        }
    });<commit_msg>Fix the bug for real this time<commit_after>angular.module('hello', ['ui.bootstrap'])
    .controller('home', function ($scope, $http) {
        $scope.activities = [];
        $scope.activeFilter = "";
        $scope.errorMessage;
        $scope.hideCompleted = false;

        $scope.priorities = {
            prioOne: "A",
            prioTwo: "B",
            prioThree: "C",
            prioFour: "D",
            prioFive: "E",
            prioSix: "F"
        }

        $http.get('/initialize').then(function (response) {
                $scope.loadActivities();
            },
            function (errorResponse) {
                $scope.errorMessage = 'error initializing application';
            });

        $scope.getErrorMessage = function () {
            return errorMessage;
        }

        $scope.toggleHideCompleted = function () {
            $scope.hideCompleted = !$scope.hideCompleted;
        }

        $scope.getHideCompleted = function () {
            return $scope.hideCompleted;
        }

        $scope.loadActivities = function () {
            $scope.activities.length = 0;
            $http.get('/getActivities').then(function (response) {
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities';
                });
        };

        $scope.loadActivtiesByTag = function (tag) {
            $scope.activeFilter = tag;
            $scope.activities.length = 0;
            $scope.toggleFilterVisibility();
            $http.post('/getActivitiesByTag', tag).then(function (response) {
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities by tag';
                });
        }

        $scope.loadActivtiesByProject = function (project) {
            $scope.activeFilter = project;
            $scope.activities = [];
            $scope.toggleFilterVisibility();
            $http.post('/getActivitiesByProject', project).then(function (response) {
                    $scope.activities = response.data;
                },
                function (errResponse) {
                    $scope.errorMessage = 'error getting activities by project';
                });
        }

        $scope.clearFilter = function () {
            $scope.activeFilter = "";
            $scope.toggleFilterVisibility();
            $scope.activities = [];
            $scope.loadActivities();
        }

        $scope.toggleFilterVisibility = function () {
            var div = document.getElementById("filterDisplay");
            div.style.display = div.style.display == "none" ? "block" : "none";
        }

        $scope.getDone = function (isDone) {
            if (isDone == true) {
                return 'fa fa-calendar-check-o';
            } else {
                return 'fa fa-calendar-times-o';
            }
        };

        $scope.getTodoToggleText = function (isDone) {
            if (isDone == true) {
                return "Didn't do it";
            } else {
                return "I did it!";
            }
        }

        $scope.getHeaderTemplate = function (isDone) {
            if (isDone == true) {
                return "color: #4cae4c;";
            } else {
                return "";
            }
        }

        $scope.save = function (name) {
            for (i in $scope.activities) {
                if ($scope.activities[i].name == name) {
                    let activity = $scope.activities[i];
                    if (activity.deadline == undefined) {
                        delete activity.deadline;
                    }
                    if (activity.completionDate == undefined) {
                        delete activity.completionDate;
                    }
                    if (activity.projects == undefined || activity.projects.length < 1) {
                        delete activity.projects;
                    }
                    if (activity.tags == undefined || activity.tags.length < 1) {
                        delete activity.tags;
                    }

                    $http.post('/save', activity).then(function (response) {
                            return true;
                        },
                        function (response) {
                            $scope.errorMessage = "Error while saving activity";
                        });

                }
            }
        };

        $scope.delete = function (name) {
            $http.get('/getActivities').then(function (response) {
                    $scope.activities = response.data;
                    for (i in $scope.activities) {
                        if ($scope.activities[i].name == name) {
                            let activity = $scope.activities[i];
                            if (activity.deadline == undefined) {
                                delete activity.deadline;
                            }
                            if (activity.completionDate == undefined) {
                                delete activity.completionDate;
                            }
                            if (activity.projects.length < 1) {
                                delete activity.projects;
                            }

                            $http.post('/delete', activity);
                            $scope.activities.splice(i, 1);
                            return;
                        }
                    }
                },
                function (errResponse) {
                    $scope.errorMessage = 'error deleting activities';
                });
        };

        $scope.getPanelStyle = function (name) {
            if ($scope.isUrgent(name)) {
                return 'panel-danger';
            } else {
                return 'panel-default';
            }
        }

        $scope.isUrgent = function (name) {
            var today = new Date();
            for (i in $scope.activities) {
                if ($scope.activities[i].name == name) {
                    let activity = $scope.activities[i];
                    if (activity.deadline != undefined) {
                        var deadlineDate = new Date(activity.deadline);
                        var warningDate = new Date(deadlineDate.getFullYear(), deadlineDate.getMonth(), deadlineDate.getDay() - 1);
                        if (today >= warningDate && !activity.completed) {
                            return true;
                        } else {
                            return false;
                        }
                    }
                }
            }
            return false;
        }

        $scope.addActivity = function () {

            var activity = {
                name: $scope.name,
                completed: false,
                deadline: $scope.deadline,
                priority: $scope.selectedPriority,
                tags: [],
                projects: []
            };
            if ($scope.tags) {
                let tagList = $scope.tags.split(",");
                if (tagList.length > 0) {
                    activity.tags = tagList;
                }
            }

            if ($scope.projects) {
                let projectList = $scope.projects.split(",");
                if (projectList.length > 0) {
                    activity.projects = projectList;
                }
            }

            $scope.activities.push(activity);
            $scope.save(activity.name);
        }

        $scope.togglediv = function (id) {
            var div = document.getElementById(id);
            div.style.display = div.style.display == "none" ? "block" : "none";
        }

        $scope.today = function () {
            $scope.dt = new Date();
        };
        $scope.today();

        $scope.clear = function () {
            $scope.dt = null;
        };

        $scope.inlineOptions = {
            customClass: getDayClass,
            minDate: new Date(),
            showWeeks: true
        };

        $scope.dateOptions = {
            dateDisabled: disabled,
            formatYear: 'yy',
            maxDate: new Date(2020, 5, 22),
            minDate: new Date(),
            startingDay: 1
        };

        // Disable weekend selection
        function disabled(data) {
            var date = data.date,
                mode = data.mode;
            //return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
            return false;
        }

        $scope.toggleMin = function () {
            $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date();
            $scope.dateOptions.minDate = $scope.inlineOptions.minDate;
        };

        $scope.toggleMin();

        $scope.open1 = function () {
            $scope.popup1.opened = true;
        };

        $scope.open2 = function () {
            $scope.popup2.opened = true;
        };

        $scope.setDate = function (year, month, day) {
            $scope.dt = new Date(year, month, day);
        };

        $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
        $scope.format = $scope.formats[0];
        $scope.altInputFormats = ['M!/d!/yyyy'];

        $scope.popup1 = {
            opened: false
        };

        $scope.popup2 = {
            opened: false
        };

        var tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        var afterTomorrow = new Date();
        afterTomorrow.setDate(tomorrow.getDate() + 1);
        $scope.events = [
            {
                date: tomorrow,
                status: 'full'
            },
            {
                date: afterTomorrow,
                status: 'partially'
            }
        ];

        function getDayClass(data) {
            var date = data.date,
                mode = data.mode;
            if (mode === 'day') {
                var dayToCheck = new Date(date).setHours(0, 0, 0, 0);

                for (var i = 0; i < $scope.events.length; i++) {
                    var currentDay = new Date($scope.events[i].date).setHours(0, 0, 0, 0);

                    if (dayToCheck === currentDay) {
                        return $scope.events[i].status;
                    }
                }
            }

            return '';
        }
    });<|endoftext|>


<commit_before>$(document).ready(function() {

	jQuery.fn.extend({
		updateEntity : function(id) {
			// populate template; for new entry received id is 0.
			url = (id != 0 ? "/" + id : "");
			$.ajax({url: "/users" + url, contentType : "text/plain" , success: function(result){
					$("#dialog-form").html(result);
			}});
			$('#dialog-form').dialog('open');
		 }
	});

	var table = $('table#users').DataTable({
		'ajax' : '/data/users',
		'serverSide' : true,
		"search": {
		    "caseSensitive": false
		 },
		columns : [ {
			data : 'id'
		}, {
			data : 'name'
		}, {
			data : 'email'
		}, {
			data : 'role'
		}, {
			data : 'status'

			// columns not persisted on the server-side
		}, {
			data : 'edit',
			orderable : false,
			searchable : false,
			render : function(data, type, row) {
				return "";
			}
		}, {
			data : 'deactivate',
			orderable : false,
			searchable : false,
			render : function(data, type, row) {
				if (row.status == "ACTIVE") {
					return ""
					+ " ";
				} else {
					return ""
					+ " ";
				}
			}
		}
		]
	});

	// load create-users template
	$.ajax({url: "/users", success: function(result){
	        $("#create-user").html(result);
    }});
});<commit_msg>fix datatype for edit requests<commit_after>$(document).ready(function() {

	jQuery.fn.extend({
		updateEntity : function(id) {
			// populate template; for new entry received id is 0.
			url = (id != 0 ? "/" + id : "");
			$.ajax({url: "/users" + url, accepts:"text/plain, charset=utf-8", dataType: "text/plain", success: function(result){
					$("#dialog-form").html(result);
			}});
			$('#dialog-form').dialog('open');
		 }
	});

	var table = $('table#users').DataTable({
		'ajax' : '/data/users',
		'serverSide' : true,
		"search": {
		    "caseSensitive": false
		 },
		columns : [ {
			data : 'id'
		}, {
			data : 'name'
		}, {
			data : 'email'
		}, {
			data : 'role'
		}, {
			data : 'status'

			// columns not persisted on the server-side
		}, {
			data : 'edit',
			orderable : false,
			searchable : false,
			render : function(data, type, row) {
				return "";
			}
		}, {
			data : 'deactivate',
			orderable : false,
			searchable : false,
			render : function(data, type, row) {
				if (row.status == "ACTIVE") {
					return ""
					+ " ";
				} else {
					return ""
					+ " ";
				}
			}
		}
		]
	});

	// load create-users template
	$.ajax({url: "/users", success: function(result){
	        $("#create-user").html(result);
    }});
});<|endoftext|>


<commit_before>import React from 'react';
import Helmet from 'react-helmet';
import Footer from '../pages/components/footer.js';
import classifier_img from '../pages/classifier_test.png';
// import '../css/blog-post.css'; // make it pretty!

export default function Template({
  data // this prop will be injected by the GraphQL query we'll write in a bit
}) {
  const { markdownRemark: post } = data; // data.markdownRemark holds our post data
  return (

      <Helmet title={`${post.frontmatter.title}`} />

          {post.frontmatter.title}

  );
}
export const pageQuery = graphql`
  query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
      }
    }
  }
`
;
<commit_msg>Update blog-post.js<commit_after>import React from 'react';
import Helmet from 'react-helmet';
import Footer from '../pages/components/footer.js';
import classifier_img from '../pages/classifier_test.png';
// import '../css/blog-post.css'; // make it pretty!

export default function Template({
  data // this prop will be injected by the GraphQL query we'll write in a bit
}) {
  const { markdownRemark: post } = data; // data.markdownRemark holds our post data
  return (

      <Helmet title={`${post.frontmatter.title}`} />

          {post.frontmatter.title}

 using github for development.. danger!

  );
}
export const pageQuery = graphql`
  query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
      }
    }
  }
`
;
<|endoftext|>