<commit_before>this.BlueMap = function(elementId, project){

	this.el = document.getElementById(elementId);

	this.projectApiUrl = '/projects/api/project/';

	this.CUSTOM_MAP_STYLE = '1pct'

	// Our favorite settings for Google Maps
	this.cfg = {
	  	mapTypeId: google.maps.MapTypeId.ROADMAP,
		zoom: 7,
	 	mapTypeControl: true,
	    zoomControl: true,
		panControl: false,
	    scaleControl: true,
	    streetViewControl: false,
	 	zoomControlOptions: {
		    style: google.maps.ZoomControlStyle.SMALL
		},
		mapTypeControlOptions: {
			mapTypeIds: [
					google.maps.MapTypeId.ROADMAP,
					google.maps.MapTypeId.TERRAIN,
					google.maps.MapTypeId.SATELLITE,
					google.maps.MapTypeId.HYBRID,
					this.CUSTOM_MAP_STYLE,
				]
		},
		overviewMapControl: true,
	};

	if (undefined != project) {
		var my = this;
		this.project = project;
		my.cfg.center =  new google.maps.LatLng(project.latitude, project.longitude);
	}

	this.projectFilters = 'limit=1000';

	// To store and clear markers
	this.markers = [];

	this.mapStyle = [
	  {
	    featureType: "administrative.country",
	    elementType: "geometry",
	    stylers: [
	      { color: "#FFFFFF" },
	      { weight: 1 },
	      { lightness: 1 },
	    ]
	  },{
	    elementType: "labels.text.stroke",
	    stylers: [
	      { color: "#FFFFFF" },
	      { weight: 2 },
	      { lightness: 1 }
	    ]
	  },{
	    elementType: "labels.text.fill",
	    stylers: [
	      { color: "#000000" },
	      { weight: 1 },
	      { lightness: 1 },
	    ]
	  },{
	    featureType: "road",
	    elementType: "geometry",
	    stylers: [
	      { color: "#333333" },
	      { lightness: 30 }
	    ]
	  },{
	    featureType: "poi",
	    elementType: "geometry.fill",
	    stylers: [
	      { color: "#00C051" }
	    ]
	  },{
	    featureType: "landscape",
	    elementType: "geometry.fill",
	    stylers: [
	      { color: "#00C051" }
	    ]
	  },{
	    featureType: "water",
	    stylers: [
	      { color: "#FEAAC7" },
	      { color: "#99EEBB" },
	    ]
	  },{
	  }
	];

	this.icons = {
		green: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_green.png',
		  new google.maps.Size(30, 30),
		  new google.maps.Point(0,0),
		  new google.maps.Point(7, 32)),
		pink: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_pink.png',
		  new google.maps.Size(30, 30),
		  new google.maps.Point(0,0),
		  new google.maps.Point(7, 32)),
		shadow: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_shadow.png',
		  new google.maps.Size(55, 30),
		  new google.maps.Point(0,0),
		  new google.maps.Point(7, 30))
	};

	this.getMap = function(cfg) {
		var my = this;
		if (undefined == my.map) {
			for (i in cfg) {
				my.cfg[i] = cfg[i];
			}
			my.map = new google.maps.Map(my.el, my.cfg);

			// Add our custom MapStyle
			my.addMapStyle('1pct', my.mapStyle, '1%COLORS');

		}
		return my.map;
	}

	this.addMapStyle = function(name, styles, title) {
		var my = this;
		if (undefined == title) {
			title = name;
		}

  	    var MyMapType = new google.maps.StyledMapType(styles, {name: title});

		my.map.mapTypes.set(my.CUSTOM_MAP_STYLE, MyMapType);
		my.map.setMapTypeId(my.CUSTOM_MAP_STYLE);
	}

	/**
	 * Load projects for the current viewport
	 * Extra filters can be given through 'filters'
	 * filters as objects {title_startswith: 'a'}
	 */
	this.loadProjects = function(filters) {

		if (undefined != filters) {
			this.projectFilters = filters;
		}
		var my = this;

		var coords = my.map.getBounds();
		var url = my.projectApiUrl;
		url += '?latitude__gte=' + coords.getSouthWest().lat();
		url += '&latitude__lte=' + coords.getNorthEast().lat();
		url += '&longitude__gte=' + coords.getSouthWest().lng();
		url += '&longitude__lte=' + coords.getNorthEast().lng();
		url += '&' + this.projectFilters;

		$('#maploading').show();
		$.getJSON(url, function(data){
			for (m in my.markers) {
				my.markers[m].setMap(null);
			}
			$('#maploading').hide();
			var projects = data.objects;
			for (i in projects) {
				var pos = new google.maps.LatLng(projects[i].latitude, projects[i].longitude);
				if (projects[i].slug == my.project.slug) {
					 var marker = new google.maps.Marker({
						 	position: pos,
							map: my.map,
							icon: my.icons.pink,
							shadow: my.icons.shadow
						});
				} else {
					 var marker = new google.maps.Marker({
						 	position: pos,
							map: my.map,
							icon: my.icons.green,
							shadow: my.icons.shadow
						});
				}
				my.markers.push(marker);
			}
		});

	};

	this.showProjects = function(filter) {
		var my = this;
		// Listen to map changes to load projects
		// Wait until map is dawn drawing
		// and then get all projects that are on this map...
		google.maps.event.addListener(my.map, 'idle', function() {
			my.loadProjects(filter);
		});
		return my;
	}

	// Get it going!
	this.map = this.getMap();

	return this;

};

<commit_msg>Cleaned up tabs and other code style errors in js<commit_after>this.BlueMap = function(elementId, project){

    this.el = document.getElementById(elementId);

    this.projectApiUrl = '/projects/api/project/';

    this.CUSTOM_MAP_STYLE = '1pct'

    // Our favorite settings for Google Maps
    this.cfg = {
          mapTypeId: google.maps.MapTypeId.ROADMAP,
        zoom: 7,
         mapTypeControl: true,
        zoomControl: true,
        panControl: false,
        scaleControl: true,
        streetViewControl: false,
         zoomControlOptions: {
            style: google.maps.ZoomControlStyle.SMALL
        },
        mapTypeControlOptions: {
            mapTypeIds: [
                    google.maps.MapTypeId.ROADMAP,
                    google.maps.MapTypeId.TERRAIN,
                    google.maps.MapTypeId.SATELLITE,
                    google.maps.MapTypeId.HYBRID,
                    this.CUSTOM_MAP_STYLE,
                ]
        },
        overviewMapControl: true,
    };

    if (undefined != project) {
        var my = this;
        this.project = project;
        my.cfg.center =  new google.maps.LatLng(project.latitude, project.longitude);
    };

    this.projectFilters = 'limit=1000';

    // To store and clear markers
    this.markers = [];

    this.mapStyle = [
      {
        featureType: "administrative.country",
        elementType: "geometry",
        stylers: [
          { color: "#FFFFFF" },
          { weight: 1 },
          { lightness: 1 },
        ]
      },{
        elementType: "labels.text.stroke",
        stylers: [
          { color: "#FFFFFF" },
          { weight: 2 },
          { lightness: 1 }
        ]
      },{
        elementType: "labels.text.fill",
        stylers: [
          { color: "#000000" },
          { weight: 1 },
          { lightness: 1 },
        ]
      },{
        featureType: "road",
        elementType: "geometry",
        stylers: [
          { color: "#333333" },
          { lightness: 30 }
        ]
      },{
        featureType: "poi",
        elementType: "geometry.fill",
        stylers: [
          { color: "#00C051" }
        ]
      },{
        featureType: "landscape",
        elementType: "geometry.fill",
        stylers: [
          { color: "#00C051" }
        ]
      },{
        featureType: "water",
        stylers: [
          { color: "#FEAAC7" },
          { color: "#99EEBB" },
        ]
      },{
      }
    ];

    this.icons = {
        green: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_green.png',
          new google.maps.Size(30, 30),
          new google.maps.Point(0,0),
          new google.maps.Point(7, 32)),
        pink: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_pink.png',
          new google.maps.Size(30, 30),
          new google.maps.Point(0,0),
          new google.maps.Point(7, 32)),
        shadow: new google.maps.MarkerImage('/static/assets/global/images/icons/1pct_pointer_shadow.png',
          new google.maps.Size(55, 30),
          new google.maps.Point(0,0),
          new google.maps.Point(7, 30))
    };

    this.getMap = function(cfg) {
        var my = this;
        if (undefined == my.map) {
            for (i in cfg) {
                my.cfg[i] = cfg[i];
            };
            my.map = new google.maps.Map(my.el, my.cfg);

            // Add our custom MapStyle
            my.addMapStyle('1pct', my.mapStyle, '1%COLORS');

        };
        return my.map;
    };

    this.addMapStyle = function(name, styles, title) {
        var my = this;
        if (undefined == title) {
            title = name;
        };

          var MyMapType = new google.maps.StyledMapType(styles, {name: title});

        my.map.mapTypes.set(my.CUSTOM_MAP_STYLE, MyMapType);
        my.map.setMapTypeId(my.CUSTOM_MAP_STYLE);
    };

    /**
     * Load projects for the current viewport
     * Extra filters can be given through 'filters'
     * filters as objects {title_startswith: 'a'}
     */
    this.loadProjects = function(filters) {

        if (undefined != filters) {
            this.projectFilters = filters;
        };
        var my = this;

        var coords = my.map.getBounds();
        var url = my.projectApiUrl;
        url += '?latitude__gte=' + coords.getSouthWest().lat();
        url += '&latitude__lte=' + coords.getNorthEast().lat();
        url += '&longitude__gte=' + coords.getSouthWest().lng();
        url += '&longitude__lte=' + coords.getNorthEast().lng();
        url += '&' + this.projectFilters;

        $('#maploading').show();
        $.getJSON(url, function(data){
            for (m in my.markers) {
                my.markers[m].setMap(null);
            };
            $('#maploading').hide();
            var projects = data.objects;
            for (i in projects) {
                var pos = new google.maps.LatLng(projects[i].latitude, projects[i].longitude);
                if (projects[i].slug == my.project.slug) {
                     var marker = new google.maps.Marker({
                             position: pos,
                            map: my.map,
                            icon: my.icons.pink,
                            shadow: my.icons.shadow
                        });
                } else {
                     var marker = new google.maps.Marker({
                             position: pos,
                            map: my.map,
                            icon: my.icons.green,
                            shadow: my.icons.shadow
                        });
                };
                my.markers.push(marker);
            };
        });

    };

    this.showProjects = function(filter) {
        var my = this;
        // Listen to map changes to load projects
        // Wait until map is dawn drawing
        // and then get all projects that are on this map...
        google.maps.event.addListener(my.map, 'idle', function() {
            my.loadProjects(filter);
        });
        return my;
    };

    // Get it going!
    this.map = this.getMap();

    return this;

};

<|endoftext|>


<commit_before>$(document).ready(function () {
  var days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ];
  var data = JSON.parse(blocks);
  var i;
  var date = new Date();
  var render;
  if (date.getDay() === 1) {
    render = data.articulation;
    for (i = 0; i < render.length; i++) {
      if (!render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      } else if (render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      }
    }
  } else if (date.getDay() === 2 || date.getDate() === 3 || date.getDate() === 4 || date.getDate() === 5) {
    render = data.regular;
    for (i = 0; i < render.length; i++) {
      if (!render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
        document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
      } else if (render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      }
    }
    document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
  } else if (date.getDay() === 0 || date.getDay() === 6) {
    document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
    $('#text').text("No school today, it's " + days[date.getDay()] + "!");
  }
});

var timeUpdate = setInterval(function () {
  $('#time').text('The time is ' + new Date().toLocaleTimeString());
}, 500);
<commit_msg>Update schedule.js<commit_after>$(document).ready(function () {
  var days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ];
  var data = JSON.parse(blocks);
  var i;
  var date = new Date();
  var render;
  if (date.getDay() === 1) {
    render = data.articulation;
    for (i = 0; i < render.length; i++) {
      if (!render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      } else if (render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      }
    }
    document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
  } else if (date.getDay() === 2 || date.getDate() === 3 || date.getDate() === 4 || date.getDate() === 5) {
    render = data.regular;
    for (i = 0; i < render.length; i++) {
      if (!render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      } else if (render[i].bold) {
        $('#display').append('
' + render[i].name + ':	' + render[i].start + '-' + render[i].end + '
');
      }
    }
    document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
  } else if (date.getDay() === 0 || date.getDay() === 6) {
    document.getElementsByTagName('title')[0].innerHTML += ': ' + days[date.getDay()];
    $('#text').text("No school today, it's " + days[date.getDay()] + "!");
  }
});

var timeUpdate = setInterval(function () {
  $('#time').text('The time is ' + new Date().toLocaleTimeString());
}, 500);
<|endoftext|>


<commit_before>var assert = require('chai').assert;
var expect = require('chai').expect;
var sinon = require('sinon');
var moment = require('moment');
var _ = require('lodash');
var Qs = require('qs');
var TestHelpers = require('../../support/TestHelpers');
var ExplorerActions = require('../../../client/js/app/actions/ExplorerActions');
var FilterUtils = require('../../../client/js/app/utils/FilterUtils');
var ValidationUtils = require('../../../client/js/app/utils/ValidationUtils');
var ExplorerValidations = require('../../../client/js/app/validations/ExplorerValidations');
var ExplorerUtils = require('../../../client/js/app/utils/ExplorerUtils');

describe('utils/ExplorerUtils', function() {
  describe('extraction event limit', function () {
    it('should be 100', function () {
      assert.strictEqual(ExplorerUtils.EXRACTION_EVENT_LIMIT, 100);
    });
  });

  describe('queryJSON', function () {
    it('should remove values that are not part of the query params that get sent to Keen', function () {
      var explorer = {
        query: {
          someVal: 'shouldBeRemoved',
          someOtherVal: 'shouldAlsoBeRemoved',
          event_collection: 'sholdRemain',
          analysis_type: 'shouldRemain'
        }
      };
      assert.deepEqual(ExplorerUtils.queryJSON(explorer), {
        event_collection: 'sholdRemain',
        analysis_type: 'shouldRemain'
      });
    });
    it('should remove the timezone if the timeframe_type is absolute', function () {
      var explorer = {
        timeframe_type: 'absolute',
        query: {
          timezone: 'US/Mountain',
          time: {
            start: new Date("Jan 1, 2015 1:00 PM"),
            end: new Date("Jan 2, 2015 1:00 PM")
          }
        }
      };
      assert.notDeepProperty(ExplorerUtils.queryJSON(explorer), 'timezone');
    });
    it('should remove values that are not valid query values', function () {
      var explorer = {
        query: {
          event_collection: undefined,
          analysis_type: 'shouldRemain',
          filters: []
        }
      };
      assert.deepEqual(ExplorerUtils.queryJSON(explorer), {
        analysis_type: 'shouldRemain'
      });
    });
    it('should call FilterUtils.queryJSON for every filter', function () {
      var explorer = { query: { filters: [{}, {}, {}] } };
      var stub = sinon.stub(FilterUtils, 'queryJSON');
      ExplorerUtils.queryJSON(explorer);
      assert.lengthOf(stub.getCalls(), 3);
      FilterUtils.queryJSON.restore();
    });
    it('should remove empty filters', function () {
      var explorer = {
        query: {
          filters: [
            {
              property_name: 'click',
              operator: 'eq',
              property_value: 'button',
              coercion_type: 'String'
            },
            {},
            {}
          ]
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.lengthOf(json.filters, 1);
    });
    it('should remove the fitlers key if it is empty after getting their queryJSON verisons', function () {
      var explorer = {
        query: {
          event_collection: 'click',
          analysis_type: 'count',
          filters: [
            {  property_name: 'click' },
            {},
            {}
          ]
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.isUndefined(json.filters);
    });
    it('should set the timeframe if there is one', function () {
      var explorer = {
        timeframe_type: 'relative',
        query: {
          event_collection: 'click',
          analysis_type: 'count',
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.deepEqual(json, {
        event_collection: 'click',
        analysis_type: 'count',
        timeframe: 'this_1_days'
      });
    });
  });

  describe('runQuery', function () {
    it('should create a Keen.Query', function () {
      var client = { run: sinon.spy() };
      var query = {
        analysis_type: 'count',
        event_collection: 'click'
      };
      ExplorerUtils.runQuery({
        client: client,
        query: query,
        success: function(){},
        error: function(){},
        complete: function(){}
      });
      assert.strictEqual(client.run.getCall(0).args[0].analysis, 'count');
      assert.deepEqual(client.run.getCall(0).args[0].params, {
        event_collection: 'click',
        timezone: (((new Date().getTimezoneOffset())/60)*60*60)*-1
      });
    });
  });

  describe('mergeResponseWithExplorer', function () {
    it('should keep all explorer attributes', function () {
      var explorer = {
        id: 'TEMP-ABC',
        name: 'SOME NAME',
        active: false,
        saving: false,
        error: null,
        result: null,
        loading: false,
        isValid: true,
        timeframe_type: 'relative',
        query: {
          event_collection: null,
          analysis_type: null,
          target_property: null,
          percentile: null,
          group_by: null,
          interval: null,
          timezone: 'UTC',
          filters: null,
          email: null,
          latest: null,
          filters: [],
          time: {
            relativity: 'this',
            amount: 1,
            sub_timeframe: 'weeks'
          }
        },
        visualization: {
          chart_type: null
        }
      };
      var response = {
        id: 'ACTUAL-ID',
        project_id: '10',
        query: {
          event_collection: 'clicks',
          analysis_type: 'count',
        },
        visualization: {
          chart_type: 'metric'
        }
      };
      assert.deepEqual(ExplorerUtils.mergeResponseWithExplorer(explorer, response), {
        id: 'ACTUAL-ID',
        project_id: '10',
        name: 'SOME NAME',
        active: false,
        saving: false,
        error: null,
        result: null,
        loading: false,
        isValid: true,
        timeframe_type: 'relative',
        query: {
          event_collection: 'clicks',
          analysis_type: 'count',
          target_property: null,
          percentile: null,
          group_by: null,
          interval: null,
          timezone: 'UTC',
          filters: null,
          email: null,
          latest: null,
          filters: [],
          time: {
            relativity: 'this',
            amount: 1,
            sub_timeframe: 'weeks'
          }
        },
        visualization: {
          chart_type: 'metric'
        }
      });
    });
  });

  describe('getTimeframe', function () {
    it('should call the right timeframe builder for absolute timeframes', function () {
      var explorer = {
        timeframe_type: 'absolute'
      };
      var stub = sinon.stub(ExplorerUtils.timeframeBuilders, 'absolute_timeframe');
      ExplorerUtils.getTimeframe(explorer);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.timeframeBuilders.absolute_timeframe.restore();
    });
    it('should call the right timeframe builder for relative timeframes', function () {
      var explorer = {
        timeframe_type: 'relative'
      };
      var stub = sinon.stub(ExplorerUtils.timeframeBuilders, 'relative_timeframe');
      ExplorerUtils.getTimeframe(explorer);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.timeframeBuilders.relative_timeframe.restore();
    });
  });

  describe('timeframeBuilders', function () {
    describe('absolute_timeframe', function () {
      it('should properly build a timeframe object', function () {
        var explorer = {
          timeframe_type: 'absolute',
          query: {
            timezone: 'US/Hawaii',
            time: {
              start: new Date(moment().subtract(1, 'days').startOf('day').format()),
              end: new Date(moment().startOf('day').format())
            }
          }
        };
        var timeframe = ExplorerUtils.getTimeframe(explorer);
        var expectedFormat = 'YYYY-MM-DDTHH:mm:ss.SSS';
        var expectedTimezone = '-10:00'
        var expectedStart = moment(new Date(explorer.query.time.start)).format(expectedFormat) + expectedTimezone;
        var expectedEnd = moment(new Date(explorer.query.time.end)).format(expectedFormat) + expectedTimezone;

        assert.deepEqual(timeframe, {
          start: expectedStart,
          end: expectedEnd
        });
      });
    });
    describe('relative_timeframe', function () {
      var explorer = {
        timeframe_type: 'relative',
        query: {
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        }
      };
      var timeframe = ExplorerUtils.getTimeframe(explorer);
      assert.deepEqual(timeframe, 'this_1_days');
    });
  });

  describe('unpackTimeframeParam', function () {
    it('properly unpacks an absolute timeframe', function () {
      var query = {
        timeframe: {
          start: moment(new Date("June 7, 2015 1:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')+"-10:00",
          end: moment(new Date("June 8, 2015 2:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')+"-10:00"
        }
      };
      assert.deepEqual(ExplorerUtils.unpackTimeframeParam(query), {
        timeframe_type: 'absolute',
        timezone: 'US/Hawaii',
        time: {
          start: ExplorerUtils.convertDateToUTC(new Date(moment(new Date("June 7, 2015 1:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS'))),
          end: ExplorerUtils.convertDateToUTC(new Date(moment(new Date("June 8, 2015 2:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')))
        }
      });
    });
    it('properly unpacks a relative timeframe', function () {
      var query = { timeframe: 'this_8_days' };
      var unpacked = ExplorerUtils.unpackTimeframeParam(query);
      assert.deepEqual(unpacked, {
        timeframe_type: 'relative',
        time: {
          relativity: 'this',
          amount: '8',
          sub_timeframe: 'days'
        }
      });
    });
  });
  describe('formatQueryParams', function () {
    it('should call unpackTimeframeParam if there is a timeframe', function () {
      var params = {
        query: {
          timeframe: 'this_1_days'
        }
      };
      var stub = sinon.stub(ExplorerUtils, 'unpackTimeframeParam').returns({
        time: {
          relativity: 'this',
          amount: '1',
          sub_timeframe: 'days'
        },
        timeframe_type: 'relative'
      });
      var formatted = ExplorerUtils.formatQueryParams(params);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.unpackTimeframeParam.restore();
    });
    it('should call FilterUtils.initList for list filters', function () {
      var stub = sinon.stub(FilterUtils, 'initList');
      var params = {
        query: {
          filters: [
            {
              coercion_type: 'List',
              property_name: 'items',
              operator: 'eq',
              property_value: 'a list of items'
            }
          ]
        }
      };
      ExplorerUtils.formatQueryParams(params);
      assert.isTrue(stub.calledOnce);
      FilterUtils.initList.restore();
    });
    it('should call FilterUtils.getCoercedValue for every filter', function () {
      var stub = sinon.stub(FilterUtils, 'getCoercedValue');
      var params = {
        query: {
          filters: [{}, {}, {}]
        }
      };
      ExplorerUtils.formatQueryParams(params);
      assert.strictEqual(stub.callCount, 3);
      FilterUtils.getCoercedValue.restore();
    });
  });

  describe('getApiQueryUrl', function(){
    beforeEach(function(){
      this.explorer = _.assign({}, TestHelpers.createExplorerModel(), {
        timeframe_type: 'relative',
        query: {
          analysis_type: 'count',
          event_collection: 'clicks',
          filters: [
            {
              property_name: 'author.id',
              operator: 'eq',
              property_value: 'abc123',
              coercion_type: 'String'
            },
            {
              property_name: 'org_project_count',
              operator: 'gte',
              property_value: 10,
              coercion_type: 'Number'
            },
          ],
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        },
        visualization: {
          chart_type: 'metric'
        }
      });
      this.client = TestHelpers.createClient();
    });

    describe('removes unneeded attributes from the URL string', function(){
      it('analysis_type', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('analysis_type=');
        assert.isNull(found);
      });
      it('chart_type', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('chart_type=');
        assert.isNull(found);
      });
    });

    describe('it constructs the URL correctly', function(){
      it('has the timeframe attribute', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('timeframe=this_1_days');
        assert.lengthOf(found, 1);
      });

      describe('filters', function () {
        it('has the expected filters attribute', function () {
          assert.include(ExplorerUtils.getApiQueryUrl(this.client, this.explorer), "filters=%5B%7B%22property_name%22%3A%22author.id%22%2C%22operator%22%3A%22eq%22%2C%22property_value%22%3A%22abc123%22%7D%2C%7B%22property_name%22%3A%22org_project_count%22%2C%22operator%22%3A%22gte%22%2C%22property_value%22%3A10%7D%5D");
        });
        it('does not have the coercion_type property', function () {
          assert.notInclude(ExplorerUtils.getApiQueryUrl(this.client, this.explorer), "coercion_type");
        });
      });
    });
  });

  describe('getSdkExample', function(){

    beforeEach(function () {
      this.explorer = TestHelpers.createExplorerModel();
      this.client = TestHelpers.createClient();
    });

    describe('removes unneeded attributes from the URL string', function(){
      beforeEach(function(){
        this.explorer.query = {
          analysis_type: 'count',
          event_collection: 'clicks',
          timeframe: 'this_1_days',
          visualization: {
            chart_type: 'metric'
          }
        };
      });

      it('analysis_type', function(){
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('analysis_type');
        assert.isNull(found)
      });

      it('chart_type', function(){
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('chart_type');
        assert.isNull(found)
      });

    });

    describe('it constructs the example correctly', function(){

      it('has the timeframe attribute', function(){
        this.explorer = {
          timeframe_type: 'relative',
          query: {
            analysis_type: 'count',
            event_collection: 'clicks',
            timeframe: 'this_1_days',
            time: {
              relativity: 'this',
              amount: '1',
              sub_timeframe: 'days'
            }
          },
          visualization: {
            chart_type: 'metric'
          }
        };
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('timeframe: "this_1_days"');
        assert.lengthOf(found, 1);
      });

    })

  });
});<commit_msg>Fixing tests.<commit_after>var assert = require('chai').assert;
var expect = require('chai').expect;
var sinon = require('sinon');
var moment = require('moment');
var _ = require('lodash');
var Qs = require('qs');
var TestHelpers = require('../../support/TestHelpers');
var ExplorerActions = require('../../../client/js/app/actions/ExplorerActions');
var FilterUtils = require('../../../client/js/app/utils/FilterUtils');
var ValidationUtils = require('../../../client/js/app/utils/ValidationUtils');
var ExplorerValidations = require('../../../client/js/app/validations/ExplorerValidations');
var ExplorerUtils = require('../../../client/js/app/utils/ExplorerUtils');

describe('utils/ExplorerUtils', function() {
  describe('extraction event limit', function () {
    it('should be 100', function () {
      assert.strictEqual(ExplorerUtils.EXRACTION_EVENT_LIMIT, 100);
    });
  });

  describe('queryJSON', function () {
    it('should remove values that are not part of the query params that get sent to Keen', function () {
      var explorer = {
        query: {
          someVal: 'shouldBeRemoved',
          someOtherVal: 'shouldAlsoBeRemoved',
          event_collection: 'sholdRemain',
          analysis_type: 'shouldRemain'
        }
      };
      assert.deepEqual(ExplorerUtils.queryJSON(explorer), {
        event_collection: 'sholdRemain',
        analysis_type: 'shouldRemain'
      });
    });
    it('should remove the timezone if the timeframe_type is absolute', function () {
      var explorer = {
        timeframe_type: 'absolute',
        query: {
          timezone: 'US/Mountain',
          time: {
            start: new Date("Jan 1, 2015 1:00 PM"),
            end: new Date("Jan 2, 2015 1:00 PM")
          }
        }
      };
      assert.notDeepProperty(ExplorerUtils.queryJSON(explorer), 'timezone');
    });
    it('should remove values that are not valid query values', function () {
      var explorer = {
        query: {
          event_collection: undefined,
          analysis_type: 'shouldRemain',
          filters: []
        }
      };
      assert.deepEqual(ExplorerUtils.queryJSON(explorer), {
        analysis_type: 'shouldRemain'
      });
    });
    it('should call FilterUtils.queryJSON for every filter', function () {
      var explorer = { query: { filters: [{}, {}, {}] } };
      var stub = sinon.stub(FilterUtils, 'queryJSON');
      ExplorerUtils.queryJSON(explorer);
      assert.lengthOf(stub.getCalls(), 3);
      FilterUtils.queryJSON.restore();
    });
    it('should remove empty filters', function () {
      var explorer = {
        query: {
          filters: [
            {
              property_name: 'click',
              operator: 'eq',
              property_value: 'button',
              coercion_type: 'String'
            },
            {},
            {}
          ]
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.lengthOf(json.filters, 1);
    });
    it('should remove the fitlers key if it is empty after getting their queryJSON verisons', function () {
      var explorer = {
        query: {
          event_collection: 'click',
          analysis_type: 'count',
          filters: [
            {  property_name: 'click' },
            {},
            {}
          ]
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.isUndefined(json.filters);
    });
    it('should set the timeframe if there is one', function () {
      var explorer = {
        timeframe_type: 'relative',
        query: {
          event_collection: 'click',
          analysis_type: 'count',
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        }
      };
      var json = ExplorerUtils.queryJSON(explorer);
      assert.deepEqual(json, {
        event_collection: 'click',
        analysis_type: 'count',
        timeframe: 'this_1_days'
      });
    });
  });

  describe('runQuery', function () {
    it('should create a Keen.Query', function () {
      var client = { run: sinon.spy() };
      var query = {
        analysis_type: 'count',
        event_collection: 'click'
      };
      ExplorerUtils.runQuery({
        client: client,
        query: query,
        success: function(){},
        error: function(){},
        complete: function(){}
      });
      assert.strictEqual(client.run.getCall(0).args[0].analysis, 'count');
      assert.deepEqual(client.run.getCall(0).args[0].params, {
        event_collection: 'click',
        timezone: (((new Date().getTimezoneOffset())/60)*60*60)*-1
      });
    });
  });

  describe('mergeResponseWithExplorer', function () {
    it('should keep all explorer attributes', function () {
      var explorer = {
        id: 'TEMP-ABC',
        name: 'SOME NAME',
        active: false,
        saving: false,
        error: null,
        result: null,
        loading: false,
        isValid: true,
        timeframe_type: 'relative',
        query: {
          event_collection: null,
          analysis_type: null,
          target_property: null,
          percentile: null,
          group_by: null,
          interval: null,
          timezone: 'UTC',
          filters: null,
          email: null,
          latest: null,
          filters: [],
          time: {
            relativity: 'this',
            amount: 1,
            sub_timeframe: 'weeks'
          }
        },
        visualization: {
          chart_type: null
        }
      };
      var response = {
        id: 'ACTUAL-ID',
        project_id: '10',
        query: {
          event_collection: 'clicks',
          analysis_type: 'count',
        },
        visualization: {
          chart_type: 'metric'
        }
      };
      var expectedExplorer = {
        id: 'ACTUAL-ID',
        project_id: '10',
        name: 'SOME NAME',
        active: false,
        saving: false,
        error: null,
        result: null,
        loading: false,
        isValid: true,
        timeframe_type: 'relative',
        query: {
          event_collection: 'clicks',
          analysis_type: 'count',
          target_property: null,
          percentile: null,
          group_by: null,
          interval: null,
          timezone: 'UTC',
          filters: null,
          email: null,
          latest: null,
          filters: [],
          time: {
            relativity: 'this',
            amount: 1,
            sub_timeframe: 'weeks'
          }
        },
        visualization: {
          chart_type: 'metric'
        }
      };
      expectedExplorer.originalModel = _.cloneDeep(expectedExplorer);
      assert.deepEqual(ExplorerUtils.mergeResponseWithExplorer(explorer, response), expectedExplorer);
    });
  });

  describe('getTimeframe', function () {
    it('should call the right timeframe builder for absolute timeframes', function () {
      var explorer = {
        timeframe_type: 'absolute'
      };
      var stub = sinon.stub(ExplorerUtils.timeframeBuilders, 'absolute_timeframe');
      ExplorerUtils.getTimeframe(explorer);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.timeframeBuilders.absolute_timeframe.restore();
    });
    it('should call the right timeframe builder for relative timeframes', function () {
      var explorer = {
        timeframe_type: 'relative'
      };
      var stub = sinon.stub(ExplorerUtils.timeframeBuilders, 'relative_timeframe');
      ExplorerUtils.getTimeframe(explorer);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.timeframeBuilders.relative_timeframe.restore();
    });
  });

  describe('timeframeBuilders', function () {
    describe('absolute_timeframe', function () {
      it('should properly build a timeframe object', function () {
        var explorer = {
          timeframe_type: 'absolute',
          query: {
            timezone: 'US/Hawaii',
            time: {
              start: new Date(moment().subtract(1, 'days').startOf('day').format()),
              end: new Date(moment().startOf('day').format())
            }
          }
        };
        var timeframe = ExplorerUtils.getTimeframe(explorer);
        var expectedFormat = 'YYYY-MM-DDTHH:mm:ss.SSS';
        var expectedTimezone = '-10:00'
        var expectedStart = moment(new Date(explorer.query.time.start)).format(expectedFormat) + expectedTimezone;
        var expectedEnd = moment(new Date(explorer.query.time.end)).format(expectedFormat) + expectedTimezone;

        assert.deepEqual(timeframe, {
          start: expectedStart,
          end: expectedEnd
        });
      });
    });
    describe('relative_timeframe', function () {
      var explorer = {
        timeframe_type: 'relative',
        query: {
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        }
      };
      var timeframe = ExplorerUtils.getTimeframe(explorer);
      assert.deepEqual(timeframe, 'this_1_days');
    });
  });

  describe('unpackTimeframeParam', function () {
    it('properly unpacks an absolute timeframe', function () {
      var query = {
        timeframe: {
          start: moment(new Date("June 7, 2015 1:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')+"-10:00",
          end: moment(new Date("June 8, 2015 2:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')+"-10:00"
        }
      };
      assert.deepEqual(ExplorerUtils.unpackTimeframeParam(query), {
        timeframe_type: 'absolute',
        timezone: 'US/Hawaii',
        time: {
          start: ExplorerUtils.convertDateToUTC(new Date(moment(new Date("June 7, 2015 1:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS'))),
          end: ExplorerUtils.convertDateToUTC(new Date(moment(new Date("June 8, 2015 2:00 PM")).format('YYYY-MM-DDTHH:mm:ss.SSS')))
        }
      });
    });
    it('properly unpacks a relative timeframe', function () {
      var query = { timeframe: 'this_8_days' };
      var unpacked = ExplorerUtils.unpackTimeframeParam(query);
      assert.deepEqual(unpacked, {
        timeframe_type: 'relative',
        time: {
          relativity: 'this',
          amount: '8',
          sub_timeframe: 'days'
        }
      });
    });
  });
  describe('formatQueryParams', function () {
    it('should call unpackTimeframeParam if there is a timeframe', function () {
      var params = {
        query: {
          timeframe: 'this_1_days'
        }
      };
      var stub = sinon.stub(ExplorerUtils, 'unpackTimeframeParam').returns({
        time: {
          relativity: 'this',
          amount: '1',
          sub_timeframe: 'days'
        },
        timeframe_type: 'relative'
      });
      var formatted = ExplorerUtils.formatQueryParams(params);
      assert.isTrue(stub.calledOnce);
      ExplorerUtils.unpackTimeframeParam.restore();
    });
    it('should call FilterUtils.initList for list filters', function () {
      var stub = sinon.stub(FilterUtils, 'initList');
      var params = {
        query: {
          filters: [
            {
              coercion_type: 'List',
              property_name: 'items',
              operator: 'eq',
              property_value: 'a list of items'
            }
          ]
        }
      };
      ExplorerUtils.formatQueryParams(params);
      assert.isTrue(stub.calledOnce);
      FilterUtils.initList.restore();
    });
    it('should call FilterUtils.getCoercedValue for every filter', function () {
      var stub = sinon.stub(FilterUtils, 'getCoercedValue');
      var params = {
        query: {
          filters: [{}, {}, {}]
        }
      };
      ExplorerUtils.formatQueryParams(params);
      assert.strictEqual(stub.callCount, 3);
      FilterUtils.getCoercedValue.restore();
    });
  });

  describe('getApiQueryUrl', function(){
    beforeEach(function(){
      this.explorer = _.assign({}, TestHelpers.createExplorerModel(), {
        timeframe_type: 'relative',
        query: {
          analysis_type: 'count',
          event_collection: 'clicks',
          filters: [
            {
              property_name: 'author.id',
              operator: 'eq',
              property_value: 'abc123',
              coercion_type: 'String'
            },
            {
              property_name: 'org_project_count',
              operator: 'gte',
              property_value: 10,
              coercion_type: 'Number'
            },
          ],
          time: {
            relativity: 'this',
            amount: '1',
            sub_timeframe: 'days'
          }
        },
        visualization: {
          chart_type: 'metric'
        }
      });
      this.client = TestHelpers.createClient();
    });

    describe('removes unneeded attributes from the URL string', function(){
      it('analysis_type', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('analysis_type=');
        assert.isNull(found);
      });
      it('chart_type', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('chart_type=');
        assert.isNull(found);
      });
    });

    describe('it constructs the URL correctly', function(){
      it('has the timeframe attribute', function(){
        var found = ExplorerUtils.getApiQueryUrl(this.client, this.explorer).match('timeframe=this_1_days');
        assert.lengthOf(found, 1);
      });

      describe('filters', function () {
        it('has the expected filters attribute', function () {
          assert.include(ExplorerUtils.getApiQueryUrl(this.client, this.explorer), "filters=%5B%7B%22property_name%22%3A%22author.id%22%2C%22operator%22%3A%22eq%22%2C%22property_value%22%3A%22abc123%22%7D%2C%7B%22property_name%22%3A%22org_project_count%22%2C%22operator%22%3A%22gte%22%2C%22property_value%22%3A10%7D%5D");
        });
        it('does not have the coercion_type property', function () {
          assert.notInclude(ExplorerUtils.getApiQueryUrl(this.client, this.explorer), "coercion_type");
        });
      });
    });
  });

  describe('getSdkExample', function(){

    beforeEach(function () {
      this.explorer = TestHelpers.createExplorerModel();
      this.client = TestHelpers.createClient();
    });

    describe('removes unneeded attributes from the URL string', function(){
      beforeEach(function(){
        this.explorer.query = {
          analysis_type: 'count',
          event_collection: 'clicks',
          timeframe: 'this_1_days',
          visualization: {
            chart_type: 'metric'
          }
        };
      });

      it('analysis_type', function(){
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('analysis_type');
        assert.isNull(found)
      });

      it('chart_type', function(){
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('chart_type');
        assert.isNull(found)
      });

    });

    describe('it constructs the example correctly', function(){

      it('has the timeframe attribute', function(){
        this.explorer = {
          timeframe_type: 'relative',
          query: {
            analysis_type: 'count',
            event_collection: 'clicks',
            timeframe: 'this_1_days',
            time: {
              relativity: 'this',
              amount: '1',
              sub_timeframe: 'days'
            }
          },
          visualization: {
            chart_type: 'metric'
          }
        };
        var found = ExplorerUtils.getSdkExample(this.explorer, this.client).match('timeframe: "this_1_days"');
        assert.lengthOf(found, 1);
      });

    })

  });
});<|endoftext|>


<commit_before>'use-strict';

// This object defines the player.
function Player (name, image, score) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
  this.score = score || 0;
}

//Example to add new instance.
// var playerOne = new Player('Michael', 'michael.jpg', 0);
// console.log(playerOne);

// This object defines the historical figure.
function HistoricalFigure (comments) {
  this.comments = comments || []; // Sets default values if necessary.
}

// This object defines the enemy.
function Enemy (name, image) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
}

// This object defines the location (level).
function Location (name, image) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
}

// This object defines the questions and answers.
function Question (question, answerChoices, correctAnswer, incorrectAnswerResponse) {
  this.question = question || ''; // Sets default values if necessary.
  this.answerChoices = answerChoices || [];
  this.correctAnswer = correctAnswer || 0;
  this.incorrectAnswerResponse = incorrectAnswerResponse || '';
}
<commit_msg>Fixed use-strict<commit_after>'use strict';

// This object defines the player.
function Player (name, image, score) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
  this.score = score || 0;
}

//Example to add new instance.
// var playerOne = new Player('Michael', 'michael.jpg', 0);
// console.log(playerOne);

// This object defines the historical figure.
function HistoricalFigure (comments) {
  this.comments = comments || []; // Sets default values if necessary.
}

// This object defines the enemy.
function Enemy (name, image) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
}

// This object defines the location (level).
function Location (name, image) {
  this.name = name || ''; // Sets default values if necessary.
  this.image = image || '';
}

// This object defines the questions and answers.
function Question (question, answerChoices, correctAnswer, incorrectAnswerResponse) {
  this.question = question || ''; // Sets default values if necessary.
  this.answerChoices = answerChoices || [];
  this.correctAnswer = correctAnswer || 0;
  this.incorrectAnswerResponse = incorrectAnswerResponse || '';
}
<|endoftext|>


<commit_before>const { app, BrowserWindow } = require('electron')
const path = require('path')

const preferencesWindow = new BrowserWindow({
  width: 640,
  height: 480,
  show: false,
  webPreferences: {
    blinkFeatures: 'OverlayScrollbars'
  }
})

preferencesWindow.loadURL('file://' + path.join(__dirname, '/preferences.html'))

preferencesWindow.webContents.on('new-window', e => {
  e.preventDefault()
})

preferencesWindow.on('close', e => {
  e.preventDefault()
  preferencesWindow.hide()
})

app.on('before-quit', e => {
  preferencesWindow.removeAllListeners()
})

module.exports = preferencesWindow
<commit_msg>Hide PreferencesWindow when blur<commit_after>const { app, BrowserWindow } = require('electron')
const path = require('path')

const preferencesWindow = new BrowserWindow({
  width: 640,
  height: 480,
  show: false,
  webPreferences: {
    blinkFeatures: 'OverlayScrollbars'
  }
})

preferencesWindow.loadURL('file://' + path.join(__dirname, '/preferences.html'))

preferencesWindow.webContents.on('new-window', e => {
  e.preventDefault()
})

preferencesWindow.on('close', e => {
  e.preventDefault()
  preferencesWindow.hide()
})

preferencesWindow.on('blur', e => {
  preferencesWindow.hide()
})

app.on('before-quit', e => {
  preferencesWindow.removeAllListeners()
})

module.exports = preferencesWindow
<|endoftext|>


<commit_before>/*
	InputMagic v0.1.0
	https://github.com/ideasmashup/input-magic

	By William ANGER, ISC License, July 2014
*/

(function($, window, document, undefined){

	var $input = null;
	var firstpress = -1, lastpress = +new Date(), count = 0;

	// @bobince, stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript/3561711
	function noregex(str) {
		return str ? str.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') : '';
	}

	function trim(str, pattern) {
		return str.replace(pattern || /^\s+|\s+$/g, '');
	}

	function inputMagic(element, options) {
		this.options = $.extend({}, this.defaults, options);
		this.element = element;
		this.init();
	}

	inputMagic.prototype = {
		defaults : {
			// not yet defined...
		},

		init : function() {
			var $elt = $(this.element);
			var enable_autocomplete = false;
			var im = this;

			$elt.keydown(function(e){
				var keycode = (e.keyCode ? e.keyCode : e.which);
				var now = +new Date();

				// typing text
				if (count++ == 0) firstpress = now;
				lastpress = now;

				// codes ref : http://www.quirksmode.org/js/keys.html
				console.log("pressing "+ keycode);

				if (keycode == 13) {
					// enter pressed : submit value (?)
					log.console('enter pressed... submit?');

					$elt.data('hint', '');
					enable_autocomplete = false;
				}
				else if (keycode == 8 || keycode == 46) {
					// backspace or suppr : show hint again
					enable_autocomplete = false;
				}
				else if (keycode < 32) {
					// non-printable character : clear hint
					$elt.data('hint', '');
					enable_autocomplete = false;
				}
				else if (keycode >= 33 && keycode <= 40) {
					// arrows keys (home, end, pgup, pgdwn, etc) : clear hint
					$elt.data('hint', '');
					enable_autocomplete = true;
				}
				else {
					// printable characters : typing text so stop checking
					enable_autocomplete = true;
				}

				if (enable_autocomplete) {
					// do autocomplete
					setTimeout(function(){im.email_hints($elt)}, 10);
					enable_autocomplete = false;
				}
			});
		},

		range : function($input, start, end) {
			var input = $input[0];

			if (input.createTextRange) {
				var range = input.createTextRange();
				range.collapse(true);
				range.moveStart('character', start);
				range.moveEnd('character', end);
				range.select();
			}
			else if (input.setSelectionRange) {
				input.setSelectionRange(start, end);
			}
		},

		append_hint : function($input, hint) {
			var input = $input.get();
			var text = trim($input.val(), noregex(hint));

			$input.val(text + hint);
			$input.data('hint', hint);
			this.range($input, text.length, text.length + hint.length);
		},

		seek_hint : function(str, suggest_arr, max_results, offset, suffix) {
			var results = [];
			if (max_results === undefined) max_results = 1;
			if (suffix === undefined) suffix = '';

			for (var i=0; i<suggest_arr.length; i++) {
				if (results < max_results) {
					if (suggest_arr[i].substring(0, str.length) == str) {
						results.push(offset? suggest_arr[i].substr(str.length) + suffix : suggest_arr[i] + suffix);
					}
				}
				else break;
			}

			// return array or single value
			if (results.length == 0) {
				// no match found
				return (max_results == 1) ? suffix : [suffix];
			}
			else {
				// found a match (or more)
				return (max_results == 1) ? results[0] : results;
			}
		},

		email_hints : function($input) {
			var value = $input.val();
			var text = trim(value, noregex($input.data('hint')));
			var len = text.length;
			var hint = '';
			var completeness = Math.min(text.length / 14, 1);

			var ADJS = ['amazing','blithesome','charismatic','decisive','excellent','fantastical','great','heroic','incredible','jolly','kickstarter','light','magical','nice','outstanding','perfect','quality','remarkable','smart','thrilling','ultimate','vibrant','wondrous','xylophone','yes_we_can','zippy'];
			var DOMS = ['hotmail','live','yahoo','gmail','orange','aol','free','numericable'];
			var EXTS = ['com','fr','eu','org','us','net','io'];

			console.log('input='+ text +' ( '+ (completeness*100) +'% )');

			if (text.length < 2) {
				// no completion yet...
				this.trigger('state','incomplete');
			}

			// complete with "best guesses" (or "motivationnal" words)
			if (text.indexOf('@') == -1) {
				if (text.length > 0) {
					hint = this.seek_hint(text, ADJS, 1, true, '@');
				}
			}
			else {
				if (text.charAt(text.length - 1) != '@') {
					var parts = text.split('@', 2);
					var bef = parts[0];
					var aft = parts[1];

					if (aft.indexOf('.') == -1) {
						hint = this.seek_hint(aft, DOMS, 1, true, '.');
						this.trigger('state', 'incomplete');
					}
					else {
						var tmp = aft.split('.', 2);
						var host = tmp[0];
						var ext = tmp[1];

						if (aft.charAt(aft.length - 1) !== '.') {
							if (ext.length > 2) {
								this.trigger('state', 'complete');
							}
							else {
								hint = this.seek_hint(ext, EXTS, 1, true);
								this.trigger('state', 'partial');
							}
						}
						else {
							// no hint
						}

						// no hint
					}
				}
				else {
					// no hint
				}
			}

			if (hint.length > 0) {
				// only suggest non-empty strings
				this.append_hint($input, hint);
			}
			else {
				$input.data('hint', '');
			}
		},

		trigger : function(eventtype, data) {
			$(this.element).trigger('input'+ eventtype, data);
		}
	};

	$.fn.inputMagic = function(options) {
		return this.each(function() {
			if (!$.data(this, 'inputMagic')) {
				$.data(this, 'inputMagic', new inputMagic(this, options));
			}
		});
	}

})(jQuery, window, document);
<commit_msg>replaced global $input by plugin property this.$<commit_after>/*
	InputMagic v0.1.0
	https://github.com/ideasmashup/input-magic

	By William ANGER, ISC License, July 2014
*/

(function($, window, document, undefined){

	var firstpress = -1, lastpress = +new Date(), count = 0;

	// @bobince, stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript/3561711
	function noregex(str) {
		return str ? str.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') : '';
	}

	function trim(str, pattern) {
		return str.replace(pattern || /^\s+|\s+$/g, '');
	}

	function inputMagic(element, options) {
		this.options = $.extend({}, this.defaults, options);
		this.element = element;
		this.$ = $(element);
		this.init();
	}

	inputMagic.prototype = {
		defaults : {
			// not yet defined...
		},

		init : function() {
			var enable_autocomplete = false;
			var im = this;

			this.$.keydown(function(e){
				var keycode = (e.keyCode ? e.keyCode : e.which);
				var now = +new Date();

				// typing text
				if (count++ == 0) firstpress = now;
				lastpress = now;

				// codes ref : http://www.quirksmode.org/js/keys.html
				console.log("pressing "+ keycode);

				if (keycode == 13) {
					// enter pressed : submit value (?)
					log.console('enter pressed... submit?');

					this.data('hint', '');
					enable_autocomplete = false;
				}
				else if (keycode == 8 || keycode == 46) {
					// backspace or suppr : show hint again
					enable_autocomplete = false;
				}
				else if (keycode < 32) {
					// non-printable character : clear hint
					this.data('hint', '');
					enable_autocomplete = false;
				}
				else if (keycode >= 33 && keycode <= 40) {
					// arrows keys (home, end, pgup, pgdwn, etc) : clear hint
					this.data('hint', '');
					enable_autocomplete = true;
				}
				else {
					// printable characters : typing text so stop checking
					enable_autocomplete = true;
				}

				if (enable_autocomplete) {
					// do autocomplete
					setTimeout(function(){im.email_hints(this)}, 10);
					enable_autocomplete = false;
				}
			});
		},

		range : function(start, end) {
			if (this.element.createTextRange) {
				var range = this.element.createTextRange();
				range.collapse(true);
				range.moveStart('character', start);
				range.moveEnd('character', end);
				range.select();
			}
			else if (this.element.setSelectionRange) {
				this.element.setSelectionRange(start, end);
			}
		},

		append_hint : function(hint) {
			var text = trim(this.element.value, noregex(hint));

			this.$.val(text + hint);
			this.$.data('hint', hint);
			this.range(text.length, text.length + hint.length);
		},

		seek_hint : function(str, suggest_arr, max_results, offset, suffix) {
			var results = [];
			if (max_results === undefined) max_results = 1;
			if (suffix === undefined) suffix = '';

			for (var i=0; i<suggest_arr.length; i++) {
				if (results < max_results) {
					if (suggest_arr[i].substring(0, str.length) == str) {
						results.push(offset? suggest_arr[i].substr(str.length) + suffix : suggest_arr[i] + suffix);
					}
				}
				else break;
			}

			// return array or single value
			if (results.length == 0) {
				// no match found
				return (max_results == 1) ? suffix : [suffix];
			}
			else {
				// found a match (or more)
				return (max_results == 1) ? results[0] : results;
			}
		},

		email_hints : function() {
			var value = this.$.val();
			var text = trim(value, noregex(this.$.data('hint')));
			var len = text.length;
			var hint = '';
			var completeness = Math.min(text.length / 14, 1);

			var ADJS = ['amazing','blithesome','charismatic','decisive','excellent','fantastical','great','heroic','incredible','jolly','kickstarter','light','magical','nice','outstanding','perfect','quality','remarkable','smart','thrilling','ultimate','vibrant','wondrous','xylophone','yes_we_can','zippy'];
			var DOMS = ['hotmail','live','yahoo','gmail','orange','aol','free','numericable'];
			var EXTS = ['com','fr','eu','org','us','net','io'];

			console.log('input='+ text +' ( '+ (completeness*100) +'% )');

			if (text.length < 2) {
				// no completion yet...
				this.trigger('state','incomplete');
			}

			// complete with "best guesses" (or "motivationnal" words)
			if (text.indexOf('@') == -1) {
				if (text.length > 0) {
					hint = this.seek_hint(text, ADJS, 1, true, '@');
				}
			}
			else {
				if (text.charAt(text.length - 1) != '@') {
					var parts = text.split('@', 2);
					var bef = parts[0];
					var aft = parts[1];

					if (aft.indexOf('.') == -1) {
						hint = this.seek_hint(aft, DOMS, 1, true, '.');
						this.trigger('state', 'incomplete');
					}
					else {
						var tmp = aft.split('.', 2);
						var host = tmp[0];
						var ext = tmp[1];

						if (aft.charAt(aft.length - 1) !== '.') {
							if (ext.length > 2) {
								this.trigger('state', 'complete');
							}
							else {
								hint = this.seek_hint(ext, EXTS, 1, true);
								this.trigger('state', 'partial');
							}
						}
						else {
							// no hint
						}

						// no hint
					}
				}
				else {
					// no hint
				}
			}

			if (hint.length > 0) {
				// only suggest non-empty strings
				this.append_hint(hint);
			}
			else {
				this.$.data('hint', '');
			}
		},

		trigger : function(eventtype, data) {
			$(this.element).trigger('input'+ eventtype, data);
		}
	};

	$.fn.inputMagic = function(options) {
		return this.each(function() {
			if (!$.data(this, 'inputMagic')) {
				$.data(this, 'inputMagic', new inputMagic(this, options));
			}
		});
	}

})(jQuery, window, document);
<|endoftext|>


<commit_before>// @flow
import { parse } from "messageformat-parser"
import { isString } from "../essentials"

// [Tokens] -> (CTX -> String)
function processTokens(tokens, octothorpe = {}): Function => string {
  if (!tokens.filter(token => !isString(token)).length) {
    return tokens.join("")
  }

  return ctx =>
    tokens.map(token => {
      if (isString(token)) {
        return token

        // # in plural case
      } else if (token.type === "octothorpe") {
        const { name, offset = 0 } = octothorpe
        return ctx(name) - offset

        // simple argument
      } else if (token.type === "argument") {
        return ctx(token.arg)

        // argument with custom format (date, number)
      } else if (token.type === "function") {
        return ctx(token.arg, token.key, token.params[0])
      }

      const offset = token.offset ? parseInt(token.offset) : undefined

      // complex argument with cases
      const formatProps = {}
      token.cases.forEach(item => {
        formatProps[item.key] = processTokens(item.tokens, {
          name: token.arg,
          offset
        })
      })

      return ctx(token.arg, token.type, {
        offset,
        ...formatProps
      })
    })
}

// Message -> (Params -> String)
export default function compile(message: string): Function | string {
  try {
    return processTokens(parse(message))
  } catch (e) {
    console.error(`Message cannot be parsed due to syntax erorrs: ${message}`)
    return message
  }
}
<commit_msg>docs: fix typo in dev/compile.js (#518)<commit_after>// @flow
import { parse } from "messageformat-parser"
import { isString } from "../essentials"

// [Tokens] -> (CTX -> String)
function processTokens(tokens, octothorpe = {}): Function => string {
  if (!tokens.filter(token => !isString(token)).length) {
    return tokens.join("")
  }

  return ctx =>
    tokens.map(token => {
      if (isString(token)) {
        return token

        // # in plural case
      } else if (token.type === "octothorpe") {
        const { name, offset = 0 } = octothorpe
        return ctx(name) - offset

        // simple argument
      } else if (token.type === "argument") {
        return ctx(token.arg)

        // argument with custom format (date, number)
      } else if (token.type === "function") {
        return ctx(token.arg, token.key, token.params[0])
      }

      const offset = token.offset ? parseInt(token.offset) : undefined

      // complex argument with cases
      const formatProps = {}
      token.cases.forEach(item => {
        formatProps[item.key] = processTokens(item.tokens, {
          name: token.arg,
          offset
        })
      })

      return ctx(token.arg, token.type, {
        offset,
        ...formatProps
      })
    })
}

// Message -> (Params -> String)
export default function compile(message: string): Function | string {
  try {
    return processTokens(parse(message))
  } catch (e) {
    console.error(`Message cannot be parsed due to syntax errors: ${message}`)
    return message
  }
}
<|endoftext|>


<commit_before>/* jshint maxdepth: 5, maxparams: 6 */

(function(W, U) {
	'use strict';

	var reg = {
			tags: /{{\s*(?:([#\/])([^#{\|\n\s]+)\s*(\|[^{\n]+)?|else)\s*}}/g,
			partial: /{{\s*> (.+?)}}/g,
			pair: /{{#(.+?)(?:|\|?([^}]*))}}([\s\S]*?){{\/\1}}/g,
			single: /{{(.+?)}}/g,
			ext: /(.[^\(]+)(?:\((.*)\))?/,
			str: /^\\?("|')/,
			args: /(\\?['"][^'"]+\\?['"]|[^,]+)/g
		},
		_isEmpty = function(val) {
			return val === '' ||
				val === false ||
				val == null ||
				(typeof val == 'object' && ! Object.keys(val).length);
		},
		helpers = {
			is: function(val) {
				return this.val === val;
			},
			not: function(val) {
				return this.val !== val;
			},
			isEmpty: function() {
				return this.empty;
			},
			notEmpty: function() {
				return ! this.empty;
			}
		},
		partials = {},
		esc;

	W.app = {
		/**
		 * Create an application
		 *
		 * @param {string} name
		 * @param {object} [options] - application configuration
		 */
		make: function(name, options) {
			var views = W.$(options.view).map(function(el) {
					return [el, el.outerHTML];
				}),
				fn = function(data) {
					views.forEach(function(view) {
						W.view.diff(view[0], W.view.render(view[1], data));
					});
				};

			W.app[name] = W._make(name, {}, false, options.model);
			W[name] = new W.app[name]();

			fn(options.model);

			W[name].$observe('*', fn);
		}
	};

	W.fn.make('view', {
		/**
		 * Parse data into template string
		 *
		 * @param {string} template
		 * @param {object} data
		 * @returns {string}
		 */
		render: function(template, data) {
			return this.$private.render(template, W.$extend(data));
		},

		/**
		 * Add conditional template handler or tag data modifier
		 *
		 * @param {string} name
		 * @param {function} fn
		 */
		addHelper: function(name, fn) {
			W._extend(helpers, name, fn);
		},

		/**
		 * Make partial available for injection into other templates
		 *
		 * @param {string} name
		 * @param {string} value
		 */
		addPartial: function(name, value) {
			W._extend(partials, name, value);
		}
	}, {
		/**
		 * Render template string
		 *
		 * @param {string} temp
		 * @param {object} data
		 * @returns {string}
		 */
		render: function(temp, data) {
			var tags = [],
				depth = [];

			// Make partial replacements and match tag pairs
			temp = temp.replace(reg.partial, function(match, tag) {
				var partial = partials[tag.trim()];

				return partial ? (
					W.$isFunction(partial) ?
						partial() :
						partial
				) : '';
			}).replace(reg.tags, function(m, pre, tag, helper) {
				var resp = '{{';

				if (pre) {
					var segs = tag.split('('),
						root = segs[0],
						exists = tags.hasOwnProperty(tag);
					resp += pre + root + '%';

					if (pre == '#') {
						depth.push(root);

						if (exists) {
							tags[root].i++;
							tags[root].o.push(tags[root].i);
						} else {
							tags[root] = {
								i: 1,
								o: [1]
							};
						}

						if (segs.length > 1) {
							helper = '(' + segs.slice(1).join('(');
						}

						resp += tags[root].i + (helper || '');
					} else if (exists) {
						resp += tags[root].o.pop();
					}
				} else {
					tag = depth.pop();
					resp += ':' + tag + '%' + tags[tag].i;
				}

				return resp + '}}';
			});

			// Parse template tags
			temp = this.parse(temp, data, {}, data, 0);

			// Reconstitute replacements
			return esc ?
				temp.replace(/{~/g, '{{')
					.replace(/~}/g, '}}')
					.replace(/%\d+/g, '') :
				temp;
		},

		/**
		 * Parse template string
		 *
		 * @param {string} temp
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @param {int} index
		 * @returns {string}
		 */
		parse: function(temp, data, prev, init, index) {
			var scope = this;

			return temp.replace(reg.pair, function(m, t, helper, inner) {
				var tag = t.replace(/%\d+/, '');

				// Escape child template tags
				if (tag == '!') {
					esc = true;

					return inner.replace(/{{:[^{\s]+}}/g, '{{ else }}')
						.replace(/{{/g, '{~ ')
						.replace(/}}/g, ' ~}');
				}

				var cond = inner.split('{{:' + t + '}}');
				inner = cond[0];
				esc = false;

				var val = scope.get(data, prev, tag, U, init, index),
					empty = _isEmpty(val),
					help = [],
					each;

				// Parse helpers
				if (helper || empty) {
					var meth = helper ? helper.split('|') : [],
						sec = cond.length > 1 ? cond[1] : '',
						agg = [];

					// Check for root helpers
					if (empty) {
						var arg = meth[0] && meth[0][0] == '(';
						meth.unshift(tag + (arg ? meth[0] : '()'));

						if (arg) {
							meth.splice(1, 1);
						}
					}

					// Capture available aggregates and helpers
					meth.forEach(function(el) {
						var arr = el.match(reg.ext),
							name = arr[1].trim();

						// Check for each helper
						if (name == 'each') {
							each = true;
						} else if (helpers[name]) {
							el = [helpers[name], arr[2]];
							each ? help.push(el) : agg.push(el);
						}
					});

					// Process aggregates
					if (agg.length) {
						if (! agg.every(function(f) {
								var rv = f[0].apply({
									val: val,
									data: data,
									root: init,
									tag: tag,
									empty: empty,
									index: index
								}, scope.parseArgs(f[1], val));

								if (rv === false) {
									return rv;
								}

								if (rv !== true) {
									val = rv;
									empty = _isEmpty(val);
								}

								return true;
							})) {
							return sec;
						}
					} else if (empty) {
						return sec;
					}
				}

				var isObject = typeof val == 'object';

				if (! each) {
					if (! isObject) {
						val = W.$extend({}, data, {
							'.': val,
							'#': 0,
							'##': 1
						});
					}

					return scope.parse(inner, val, data, init, index);
				}

				if (! empty) {
					// Loop through objects and arrays
					if (isObject) {
						var isPlainObject = W.$isObject(val),
							resp = '',
							i = 0;

						for (var key in val) {
							if (val.hasOwnProperty(key)) {
								// Merge default properties
								var el = val[key];
								empty = _isEmpty(el);

								// Process helpers
								if (! help.length ||
									help.every(function(f) {
										var rv = f[0].apply({
											val: el,
											data: data,
											root: init,
											tag: tag,
											empty: empty,
											index: i
										}, scope.parseArgs(f[1], val));

										if (rv === false) {
											return rv;
										}

										if (rv !== true) {
											el = rv;
										}

										return true;
									})) {
									var item = W.$extend({}, W.$isObject(el) ?
										el :
										(isPlainObject ? val : {}),
									{
										$key: key,
										'.': el,
										'#': i,
										'##': i + 1
									});

									i++;

									resp += scope.parse(inner, item, data, init, i);
								}
							}
						}

						return resp;
					}

					return inner;
				}
			}).replace(reg.single, function(m, set) {
				var split = set.split('||'),
					fb = split[1],
					segs = split[0].split('|'),
					tag = segs[0].trim(),
					val = scope.get(data, prev, tag, fb, init, index),
					helps = segs.length > 1 ? segs.slice(1) : segs;

				// Return empty string if output isn't available
				if (val === U || typeof val == 'object') {
					val = '';
				}

				// Process helpers
				helps.forEach(function(el, i) {
					var arr = el.match(reg.ext);
					helps[i] = el.trim();

					if (arr) {
						var helper = helpers[arr[1].trim()];

						if (helper) {
							val = helper.apply({
								val: val,
								data: data,
								root: init,
								tag: tag,
								index: index,
								fallback: fb
							}, scope.parseArgs(arr[2], data));
						}
					}
				});

				// Encode output by default
				if (val === U) {
					val = '';
				} else if (typeof val == 'string') {
					if (helps.indexOf('raw') < 0) {
						val = val.replace(/&/g, '&')
							.replace(/&/g, '&')
							.replace(/</g, '<')
							.replace(/>/g, '>')
							.replace(/"/g, '"');
					}
				}

				return val;
			});
		},

		/**
		 * Get specific object value
		 *
		 * @param {object} data
		 * @param {object} prev
		 * @param {string} key
		 * @param {string} fb
		 * @param {object} init
		 * @param {int} x
		 * @returns {*}
		 */
		get: function(data, prev, key, fb, init, x) {
			key = key.trim();

			// Alter context
			if (key.substr(0, 6) == '$root.') {
				key = key.substr(6);
				data = init;
			} else if (key.substr(0, 3) == '../') {
				key = key.substr(3);
				data = prev;
			}

			var segs = key == '.' ? ['.'] : key.split('.'),
				orig = data,
				len = segs.length - 1,
				i = 0;

			// Loop through object segments
			for (; i <= len; i++) {
				key = segs[i];

				if (data && data.hasOwnProperty(key)) {
					data = data[key];

					// Return value on last segment
					if (i === len) {
						return data;
					}
				} else {
					break;
				}
			}

			if (key == '.') {
				return data;
			}

			// Process fallback value
			if (fb && fb !== '') {
				fb = fb.trim();
				var match = fb.match(reg.str);

				if (match) {
					return fb.replace(reg.str, '')
						.replace(new RegExp(match[0] + '$'), '');
				}

				return this.get(orig, prev, fb, '', init, x);
			}

			return fb;
		},

		/**
		 * Parse helper arguments
		 *
		 * @param {string} str
		 * @returns {*}
		 */
		parseArgs: function(str, data) {
			var args = str !== U ? str.match(reg.args) || [] : [];

			return args.map(function(arg) {
				arg = arg.trim();

				if (data && data.hasOwnProperty(arg) && isNaN(arg)) {
					return data[arg];
				} else {
					var match = arg.match(reg.str);

					if (match) {
						return arg.replace(reg.str, '')
							.replace(new RegExp(match[0] + '$'), '');
					}
				}

				return arg == 'true' ? true :
					arg == 'false' ? false :
					arg == 'null' ? null :
					parseInt(arg).toString() == arg ? parseInt(arg) :
					'';
			});
		}
	});
})(Wee, undefined);<commit_msg>Implement collision prevention logic for model keys and helpers<commit_after>/* jshint maxdepth: 5, maxparams: 6 */

(function(W, U) {
	'use strict';

	var reg = {
			tags: /{{\s*(?:([#\/])([^#{\|\n\s]+)\s*(\|[^{\n]+)?|else)\s*}}/g,
			partial: /{{\s*> (.+?)}}/g,
			pair: /{{#(.+?)(?:|\|?([^}]*))}}([\s\S]*?){{\/\1}}/g,
			single: /{{(.+?)}}/g,
			ext: /(.[^\(]+)(?:\((.*)\))?/,
			str: /^\\?("|')/,
			args: /(\\?['"][^'"]+\\?['"]|[^,]+)/g
		},
		_isEmpty = function(val) {
			return val === '' ||
				val === false ||
				val == null ||
				(typeof val == 'object' && ! Object.keys(val).length);
		},
		helpers = {
			is: function(val) {
				return this.val === val;
			},
			not: function(val) {
				return this.val !== val;
			},
			isEmpty: function() {
				return this.empty;
			},
			notEmpty: function() {
				return ! this.empty;
			}
		},
		partials = {},
		esc;

	W.app = {
		/**
		 * Create an application
		 *
		 * @param {string} name
		 * @param {object} [options] - application configuration
		 */
		make: function(name, options) {
			var views = W.$(options.view).map(function(el) {
					return [el, el.outerHTML];
				}),
				fn = function(data) {
					views.forEach(function(view) {
						W.view.diff(view[0], W.view.render(view[1], data));
					});
				};

			W.app[name] = W._make(name, {}, false, options.model);
			W[name] = new W.app[name]();

			fn(options.model);

			W[name].$observe('*', fn);
		}
	};

	W.fn.make('view', {
		/**
		 * Parse data into template string
		 *
		 * @param {string} template
		 * @param {object} data
		 * @returns {string}
		 */
		render: function(template, data) {
			return this.$private.render(template, W.$extend(data));
		},

		/**
		 * Add conditional template handler or tag data modifier
		 *
		 * @param {string} name
		 * @param {function} fn
		 */
		addHelper: function(name, fn) {
			W._extend(helpers, name, fn);
		},

		/**
		 * Make partial available for injection into other templates
		 *
		 * @param {string} name
		 * @param {string} value
		 */
		addPartial: function(name, value) {
			W._extend(partials, name, value);
		}
	}, {
		/**
		 * Render template string
		 *
		 * @param {string} temp
		 * @param {object} data
		 * @returns {string}
		 */
		render: function(temp, data) {
			var tags = [],
				depth = [];

			// Make partial replacements and match tag pairs
			temp = temp.replace(reg.partial, function(match, tag) {
				var partial = partials[tag.trim()];

				return partial ? (
					W.$isFunction(partial) ?
						partial() :
						partial
				) : '';
			}).replace(reg.tags, function(m, pre, tag, helper) {
				var resp = '{{';

				if (pre) {
					var segs = tag.split('('),
						root = segs[0],
						exists = tags.hasOwnProperty(tag);
					resp += pre + root + '%';

					if (pre == '#') {
						depth.push(root);

						if (exists) {
							tags[root].i++;
							tags[root].o.push(tags[root].i);
						} else {
							tags[root] = {
								i: 1,
								o: [1]
							};
						}

						if (segs.length > 1) {
							helper = '(' + segs.slice(1).join('(');
						}

						resp += tags[root].i + (helper || '');
					} else if (exists) {
						resp += tags[root].o.pop();
					}
				} else {
					tag = depth.pop();
					resp += ':' + tag + '%' + tags[tag].i;
				}

				return resp + '}}';
			});

			// Parse template tags
			temp = this.parse(temp, data, {}, data, 0);

			// Reconstitute replacements
			return esc ?
				temp.replace(/{~/g, '{{')
					.replace(/~}/g, '}}')
					.replace(/%\d+/g, '') :
				temp;
		},

		/**
		 * Parse template string
		 *
		 * @param {string} temp
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @param {int} index
		 * @returns {string}
		 */
		parse: function(temp, data, prev, init, index) {
			var scope = this;

			return temp.replace(reg.pair, function(m, t, helper, inner) {
				var tag = t.replace(/%\d+/, '');

				// Escape child template tags
				if (tag == '!') {
					esc = true;

					return inner.replace(/{{:[^{\s]+}}/g, '{{ else }}')
						.replace(/{{/g, '{~ ')
						.replace(/}}/g, ' ~}');
				}

				var cond = inner.split('{{:' + t + '}}');
				inner = cond[0];
				esc = false;

				var val = scope.get(data, prev, tag, U, init, index),
					empty = _isEmpty(val),
					help = [],
					each;

				// Parse helpers
				if (helper || empty) {
					var meth = helper ? helper.split('|') : [],
						sec = cond.length > 1 ? cond[1] : '',
						agg = [];

					// Check for root helpers
					if (empty) {
						var arg = meth[0] && meth[0][0] == '(';
						meth.unshift(tag + (arg ? meth[0] : '()'));

						if (arg) {
							meth.splice(1, 1);
						}
					}

					// Capture available aggregates and helpers
					meth.forEach(function(el) {
						var arr = el.match(reg.ext),
							name = arr[1].trim();

						// Check for each helper
						if (name == 'each') {
							each = true;
						} else if (helpers[name]) {
							el = [helpers[name], arr[2]];
							each ? help.push(el) : agg.push(el);
						}
					});

					// Process aggregates
					if (agg.length) {
						if (! agg.every(function(f) {
								var rv = f[0].apply({
									val: val,
									data: data,
									root: init,
									tag: tag,
									empty: empty,
									index: index
								}, scope.parseArgs(f[1], val));

								if (rv === false) {
									return rv;
								}

								if (rv !== true) {
									val = rv;
									empty = _isEmpty(val);
								}

								return true;
							})) {
							return sec;
						}
					} else if (empty) {
						return sec;
					}
				}

				var isObject = typeof val == 'object';

				if (! each) {
					if (! isObject) {
						val = W.$extend({}, data, {
							'.': val,
							'#': 0,
							'##': 1
						});
					}

					return scope.parse(inner, val, data, init, index);
				}

				if (! empty) {
					// Loop through objects and arrays
					if (isObject) {
						var isPlainObject = W.$isObject(val),
							resp = '',
							i = 0;

						for (var key in val) {
							if (val.hasOwnProperty(key)) {
								// Merge default properties
								var el = val[key];
								empty = _isEmpty(el);

								// Process helpers
								if (! help.length ||
									help.every(function(f) {
										var rv = f[0].apply({
											val: el,
											data: data,
											root: init,
											tag: tag,
											empty: empty,
											index: i
										}, scope.parseArgs(f[1], val));

										if (rv === false) {
											return rv;
										}

										if (rv !== true) {
											el = rv;
										}

										return true;
									})) {
									var item = W.$extend({}, W.$isObject(el) ?
										el :
										(isPlainObject ? val : {}),
									{
										$key: key,
										'.': el,
										'#': i,
										'##': i + 1
									});

									i++;

									resp += scope.parse(inner, item, data, init, i);
								}
							}
						}

						return resp;
					}

					return inner;
				}
			}).replace(reg.single, function(m, set) {
				var split = set.split('||'),
					fb = split[1],
					segs = split[0].split('|'),
					tag = segs[0].trim(),
					val = scope.get(data, prev, tag, fb, init, index),
					helps = segs.length > 1 ? segs.slice(1) : segs;

				// Return empty string if output isn't available
				if (val === U || typeof val == 'object') {
					val = '';
				}

				// Process helpers
				helps.forEach(function(el, i) {
					var arr = el.match(reg.ext);
					helps[i] = el.trim();

					if (arr) {
						var helper = helpers[arr[1].trim()];

						if (helper && segs.length > 1 ||
							! data.hasOwnProperty(tag)) {
							val = helper.apply({
								val: val,
								data: data,
								root: init,
								tag: tag,
								index: index,
								fallback: fb
							}, scope.parseArgs(arr[2], data));
						}
					}
				});

				// Encode output by default
				if (val === U) {
					val = '';
				} else if (typeof val == 'string') {
					if (helps.indexOf('raw') < 0) {
						val = val.replace(/&/g, '&')
							.replace(/&/g, '&')
							.replace(/</g, '<')
							.replace(/>/g, '>')
							.replace(/"/g, '"');
					}
				}

				return val;
			});
		},

		/**
		 * Get specific object value
		 *
		 * @param {object} data
		 * @param {object} prev
		 * @param {string} key
		 * @param {string} fb
		 * @param {object} init
		 * @param {int} x
		 * @returns {*}
		 */
		get: function(data, prev, key, fb, init, x) {
			key = key.trim();

			// Alter context
			if (key.substr(0, 6) == '$root.') {
				key = key.substr(6);
				data = init;
			} else if (key.substr(0, 3) == '../') {
				key = key.substr(3);
				data = prev;
			}

			var segs = key == '.' ? ['.'] : key.split('.'),
				orig = data,
				len = segs.length - 1,
				i = 0;

			// Loop through object segments
			for (; i <= len; i++) {
				key = segs[i];

				if (data && data.hasOwnProperty(key)) {
					data = data[key];

					// Return value on last segment
					if (i === len) {
						return data;
					}
				} else {
					break;
				}
			}

			if (key == '.') {
				return data;
			}

			// Process fallback value
			if (fb && fb !== '') {
				fb = fb.trim();
				var match = fb.match(reg.str);

				if (match) {
					return fb.replace(reg.str, '')
						.replace(new RegExp(match[0] + '$'), '');
				}

				return this.get(orig, prev, fb, '', init, x);
			}

			return fb;
		},

		/**
		 * Parse helper arguments
		 *
		 * @param {string} str
		 * @returns {*}
		 */
		parseArgs: function(str, data) {
			var args = str !== U ? str.match(reg.args) || [] : [];

			return args.map(function(arg) {
				arg = arg.trim();

				if (data && data.hasOwnProperty(arg) && isNaN(arg)) {
					return data[arg];
				} else {
					var match = arg.match(reg.str);

					if (match) {
						return arg.replace(reg.str, '')
							.replace(new RegExp(match[0] + '$'), '');
					}
				}

				return arg == 'true' ? true :
					arg == 'false' ? false :
					arg == 'null' ? null :
					parseInt(arg).toString() == arg ? parseInt(arg) :
					'';
			});
		}
	});
})(Wee, undefined);<|endoftext|>