<commit_before>/* Atlassian M.E.A.T.
 * Authors: Adam Ahmed, Martin Jopson, Stephen Russell, Robert Smart
 * (c) 2011 Atlassian Pty Ltd.
 * Atlassian M.E.A.T. may be freely distributed under the MIT license.
 */

var GlobalEvents = (function() {
	var eventNamespace = ".meatevent";
	return {
		trigger : function(a,b) {
			$(window).trigger(a + eventNamespace, b);
		},
		bind : function(a,b,c) {
			var newA;
			$(window).bind(a + eventNamespace, b, c);
		},
		unbind : function(a,b) {
			$(window).unbind(a + eventNamespace, b);
		}
	};
})();

var ParameterParser = new (function() {
	this.parse = function() {
		var hashTag = window.location.hash.substr(1),
			qsParams = window.location.search.substr(1),
			vars = hashTag.split('&').concat(qsParams.split('&')),
			params = {};

		for(var i = 0, l = vars.length; i < l; i++) {
			var nameVal = vars[i].split('=');
			if(nameVal[0]) {
				params[decodeURIComponent(nameVal[0])] = nameVal.length > 1 ? decodeURIComponent(nameVal[1]) : true;
			}
		}

		return params;
	};

	return this;
})();

var Logger = (function(){
	var vars = ParameterParser.parse();

	return {
		log: function(msg, errObj) {
			msg && console.log(msg);
			throw errObj;
		}
	};
})();

var ActivityMonitor = (function() {
	var timeouts = [],
		timeoutIndex = 0,
		lastActivityTime = new Date(),
		idleTimeoutHandle = null,
		nextTimeoutHandle = 0;

	function recordActivity() {
        try {
            lastActivityTime = new Date();
            timeoutIndex = 0;
            idleCallback();
        } catch (e) {
            Logger.log("Error in idle recording.", e)
        }
	}
	function idleCallback() {
		var now = new Date(),
			idleTimeMs = msBetween(lastActivityTime, now);

		if(idleTimeoutHandle) {
			clearTimeout(idleTimeoutHandle);
			idleTimeoutHandle = null;
		}

		for (var t = timeouts.length; timeoutIndex < t; timeoutIndex++) {
			var timeout = timeouts[timeoutIndex];
			if (timeout.idleMs <= idleTimeMs) {
				try { timeout.handler(); } catch(e) {}
			} else {
				var timeoutAgainIn = timeout.idleMs - msBetween(lastActivityTime, new Date());
				idleTimeoutHandle = setTimeout(idleCallback, timeoutAgainIn > 0 ? timeoutAgainIn : 1);
				break;
			}
		}
	}
	function msBetween(dateA, dateB) {
		return (dateB - dateA);
	}

	$(document)
		.mousemove(recordActivity)
		.click(recordActivity)
		.bind('touchstart', recordActivity)
		.bind('touchmove', recordActivity)
		.bind('touchend', recordActivity);

	return {
		setIdleHandler : function(idleMs, handler) {
			var i = 0,
				l = timeouts.length;
			while (i < l) {
				if(idleMs < timeouts[i].idleMs) {
					timeouts.splice(i, 0, {
						idleMs: idleMs,
						handler: handler,
						timeoutHandle: nextTimeoutHandle
					});
					break;
				}
				i++;
			}
			if (i == l) {
				timeouts.push({
						idleMs: idleMs,
						handler: handler,
						timeoutHandle: nextTimeoutHandle
					});
			}
			idleCallback();

			return nextTimeoutHandle++;
		},
		clearIdleHandler : function(idleTimeoutHandle) {
			for (var i = 0, l = timeouts.length; i < l; i++) {
				if(idleTimeoutHandle == timeouts[i].timeoutHandle) {
					if (i < timeoutIndex) timeoutIndex--;
					timeouts.splice(i, 1);
					break;
				}
			}
		}
	};
})();

var DebugSettings = (function(){
	var vars = ParameterParser.parse(),
		offsetFromServerTime;

	if (false && EventManagerConfig.timeServerJSONPUrl) {
		$.ajax(EventManagerConfig.timeServerJSONPUrl, {
			dataType: "jsonp",
			async: false,
			timeout: 10000
		}).done(function(data) {
			if (data && data.datetime) {
				var serverDate = new Date(data.datetime);
				if (!isNaN(+serverDate)) { // valid date
					offsetFromServerTime = serverDate - new Date();
				}
			}
		}).fail(function(xhr, textStatus, errorThrown) {
			console.log("Error while contacting time server: " + textStatus);
		});
	}

	return {
		now : vars.debug ?
				function() { return new Date(2011, 6, 1, 15, 25, 0); } :
				function() {
					return offsetFromServerTime == null ? new Date() : new Date((+new Date()) + offsetFromServerTime);
				}
	};
})();<commit_msg>Remove time server url debug code<commit_after>/* Atlassian M.E.A.T.
 * Authors: Adam Ahmed, Martin Jopson, Stephen Russell, Robert Smart
 * (c) 2011 Atlassian Pty Ltd.
 * Atlassian M.E.A.T. may be freely distributed under the MIT license.
 */

var GlobalEvents = (function() {
	var eventNamespace = ".meatevent";
	return {
		trigger : function(a,b) {
			$(window).trigger(a + eventNamespace, b);
		},
		bind : function(a,b,c) {
			var newA;
			$(window).bind(a + eventNamespace, b, c);
		},
		unbind : function(a,b) {
			$(window).unbind(a + eventNamespace, b);
		}
	};
})();

var ParameterParser = new (function() {
	this.parse = function() {
		var hashTag = window.location.hash.substr(1),
			qsParams = window.location.search.substr(1),
			vars = hashTag.split('&').concat(qsParams.split('&')),
			params = {};

		for(var i = 0, l = vars.length; i < l; i++) {
			var nameVal = vars[i].split('=');
			if(nameVal[0]) {
				params[decodeURIComponent(nameVal[0])] = nameVal.length > 1 ? decodeURIComponent(nameVal[1]) : true;
			}
		}

		return params;
	};

	return this;
})();

var Logger = (function(){
	var vars = ParameterParser.parse();

	return {
		log: function(msg, errObj) {
			msg && console.log(msg);
			throw errObj;
		}
	};
})();

var ActivityMonitor = (function() {
	var timeouts = [],
		timeoutIndex = 0,
		lastActivityTime = new Date(),
		idleTimeoutHandle = null,
		nextTimeoutHandle = 0;

	function recordActivity() {
        try {
            lastActivityTime = new Date();
            timeoutIndex = 0;
            idleCallback();
        } catch (e) {
            Logger.log("Error in idle recording.", e)
        }
	}
	function idleCallback() {
		var now = new Date(),
			idleTimeMs = msBetween(lastActivityTime, now);

		if(idleTimeoutHandle) {
			clearTimeout(idleTimeoutHandle);
			idleTimeoutHandle = null;
		}

		for (var t = timeouts.length; timeoutIndex < t; timeoutIndex++) {
			var timeout = timeouts[timeoutIndex];
			if (timeout.idleMs <= idleTimeMs) {
				try { timeout.handler(); } catch(e) {}
			} else {
				var timeoutAgainIn = timeout.idleMs - msBetween(lastActivityTime, new Date());
				idleTimeoutHandle = setTimeout(idleCallback, timeoutAgainIn > 0 ? timeoutAgainIn : 1);
				break;
			}
		}
	}
	function msBetween(dateA, dateB) {
		return (dateB - dateA);
	}

	$(document)
		.mousemove(recordActivity)
		.click(recordActivity)
		.bind('touchstart', recordActivity)
		.bind('touchmove', recordActivity)
		.bind('touchend', recordActivity);

	return {
		setIdleHandler : function(idleMs, handler) {
			var i = 0,
				l = timeouts.length;
			while (i < l) {
				if(idleMs < timeouts[i].idleMs) {
					timeouts.splice(i, 0, {
						idleMs: idleMs,
						handler: handler,
						timeoutHandle: nextTimeoutHandle
					});
					break;
				}
				i++;
			}
			if (i == l) {
				timeouts.push({
						idleMs: idleMs,
						handler: handler,
						timeoutHandle: nextTimeoutHandle
					});
			}
			idleCallback();

			return nextTimeoutHandle++;
		},
		clearIdleHandler : function(idleTimeoutHandle) {
			for (var i = 0, l = timeouts.length; i < l; i++) {
				if(idleTimeoutHandle == timeouts[i].timeoutHandle) {
					if (i < timeoutIndex) timeoutIndex--;
					timeouts.splice(i, 1);
					break;
				}
			}
		}
	};
})();

var DebugSettings = (function(){
	var vars = ParameterParser.parse(),
		offsetFromServerTime;

	if (EventManagerConfig.timeServerJSONPUrl) {
		$.ajax(EventManagerConfig.timeServerJSONPUrl, {
			dataType: "jsonp",
			async: false,
			timeout: 10000
		}).done(function(data) {
			if (data && data.datetime) {
				var serverDate = new Date(data.datetime);
				if (!isNaN(+serverDate)) { // valid date
					offsetFromServerTime = serverDate - new Date();
				}
			}
		}).fail(function(xhr, textStatus, errorThrown) {
			console.log("Error while contacting time server: " + textStatus);
		});
	}

	return {
		now : vars.debug ?
				function() { return new Date(2011, 6, 1, 15, 25, 0); } :
				function() {
					return offsetFromServerTime == null ? new Date() : new Date((+new Date()) + offsetFromServerTime);
				}
	};
})();<|endoftext|>


<commit_before>(function () {
  "use strict";

jQuery(function($) {
  var reclineDatasetInfo = $.extend({}, true, VIZDATA.resources[0]);
  if (VIZDATA.resources[0].schema && VIZDATA.resources[0].schema.fields) {
    reclineDatasetInfo.fields = VIZDATA.resources[0].schema.fields;
  }
  var dataset = new recline.Model.Dataset(reclineDatasetInfo);
  var timemapper = new TimeMapperView({
    model: dataset,
    datapackage: VIZDATA,
    el: $('.data-views')
  });
  // TODO: move this stuff into a proper view
  $('.js-embed').on('click', function(e) {
    e.preventDefault();
    var url = window.location.href.replace(/#.*$/, "") + '?embed=1'; // for now, just remove any fragment id
    var val = '';
    $('.embed-modal textarea').val(val);
    $('.embed-modal').modal();
  });
});

var TimeMapperView = Backbone.View.extend({
  events: {
    'click .controls .js-show-toolbox': '_onShowToolbox',
    'submit .toolbox form': '_onSearch'
  },

  initialize: function(options) {
    var self = this;
    this._setupOnHashChange();

    this.datapackage = options.datapackage;
    // fix up for datapackage without right structure
    if (!this.datapackage.tmconfig) {
      this.datapackage.tmconfig = {};
    }
    this.timelineState = _.extend({}, this.datapackage.tmconfig.timeline, {
      nonUSDates: this.datapackage.tmconfig.dayfirst,
      timelineJSOptions: _.extend({}, this.datapackage.tmconfig.timelineJSOptions, {
        "hash_bookmark": true
      })
    });
    this._setupTwitter();

    // now load the data
    this.model.fetch().done(function() {
      self.model.query({size: self.model.recordCount})
      .done(function() {
        self._dataChanges();
        self._setStartPosition();
        self._onDataLoaded();
      });
    });
  },

  _setStartPosition: function() {
    var startAtSlide = 0;
    switch (this.datapackage.tmconfig.startfrom) {
      case 'start':
        // done
        break;
      case 'end':
        startAtSlide = this.model.recordCount - 1;
        break;
      case 'today':
        var dateToday = new Date();
        this.model.records.each(function(rec, i) {
          if (rec.get('startParsed') < dateToday) {
            startAtSlide = i;
          }
        });
        break;
    }
    this.timelineState.timelineJSOptions = _.extend(this.timelineState.timelineJSOptions, {
        "start_at_slide": startAtSlide
      }
    );
  },

  _onDataLoaded: function() {
    $('.js-loading').hide();

    // Note: We *have* to postpone setup until now as otherwise timeline
    // might try to navigate to a non-existent marker
    if (this.datapackage.tmconfig.viewtype === 'timeline') {
      // timeline only
      $('body').addClass('viewtype-timeline');
      // fix height of timeline to be window height minus navbar and footer
      $('.timeline-pane').height($(window).height() - 42 - 41);
      this._setupTimeline();
    } else if (this.datapackage.tmconfig.viewtype === 'map') {
      $('body').addClass('viewtype-map');
      this._setupMap();
    } else {
      $('body').addClass('viewtype-timemap');
      this._setupTimeline();
      this._setupMap();
    }

    // Nasty hack. Timeline ignores hashchange events unless is_moving ==
    // True. However, once it's True, it can never become false again. The
    // callback associated with the UPDATE event sets it to True, but is
    // otherwise a no-op.
    $("div.slider").trigger("UPDATE");
  },

  _setupTwitter: function(e) {
    !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
  },

  _dataChanges: function() {
    var self = this;
    this.model.records.each(function(record) {
      // normalize date field names
      if (record.get('startdate') && !record.get('start')) {
        record.set({
          start: record.get('startdate'),
          end: record.get('enddate')
        }, {silent: true}
        );
      }
      var startDate = VMM.Date.parse(normalizeDate(record.get("start"), self.datapackage.tmconfig.dayfirst));
      var data = {
        // VMM.Date.parse is the timelinejs date parser
        startParsed: startDate,
        title: record.get('title') || record.get('headline'),
        description: record.get('description') || record.get('text') || '',
        url: record.get('url') || record.get('webpage'),
        media: record.get('image') || record.get('media'),
        mediacaption: record.get('caption') || record.get('mediacaption') || record.get('imagecaption'),
        mediacredit: record.get('imagecredit') || record.get('mediacredit'),
      };
      if (record.get('size') || record.get('size') === 0) {
        data.size = parseFloat(record.get('size'));
      }
      record.set(data, { silent: true });
    });

    var starts = this.model.records.pluck('startParsed')
      , minDate = _.min(starts)
      , maxDate =  _.max(starts)
      , dateRange = maxDate - minDate
      , sizes = this.model.records.pluck('size')
      , maxSize = _.max(sizes)
      ;
    // set opacity - we compute opacity between 0.1 and 1 based on distance from most recent date
    var minOpacity = 0.3
      , opacityRange = 1.0 - minOpacity
      ;
    this.model.records.each(function(rec) {
      var temporalRangeLocation = (rec.get('startParsed') - minDate) / dateRange;
      rec.set({
        temporalRangeLocation: temporalRangeLocation,
        opacity: minOpacity + (opacityRange * temporalRangeLocation),
        relativeSize: parseFloat(rec.get('size')) / maxSize
      });
    });

    // Timeline will sort the entries by timestamp, and we need the order to be
    // the same for the map which runs off the model
    this.model.records.comparator = function (a, b) {
      return a.get('startParsed') - b.get('startParsed');
    };
    this.model.records.sort();
  },

  _setupOnHashChange: function() {
    var self = this;
    // listen for hashchange to update map
    $(window).on("hashchange", function () {
      var hash = window.location.hash.substring(1);
      if (parseInt(hash, 10)) {
        var record = self.model.records.at(hash);
        if (record && record.marker) {
          record.marker.openPopup();
        }
      }
    });
  },

  _onShowToolbox: function(e) {
    e.preventDefault();
    if (this.$el.find('.toolbox').hasClass('hideme')) {
      this.$el.find('.toolbox').removeClass('hideme');
    } else {
      this.$el.find('.toolbox').addClass('hideme');
    }
  },

  _onSearch: function(e) {
    e.preventDefault();
    var query = this.$el.find('.text-query input').val();
    this.model.query({q: query});
  },

  _setupTimeline: function() {
    this.timeline = new recline.View.Timeline({
      model: this.model,
      el: this.$el.find('.timeline'),
      state: this.timelineState
    });

    // convert the record to a structure suitable for timeline.js
    this.timeline.convertRecord = function(record, fields) {
      if (record.get('startParsed') == 'Invalid Date') {
        if (typeof console !== "undefined" && console.warn) {
          console.warn('Failed to extract date from record');
          console.warn(record.toJSON());
        }
        return null;
      }
      try {
        var out = this._convertRecord(record, fields);
      } catch (e) {
        out = null;
      }
      if (!out) {
        if (typeof console !== "undefined" && console.warn) {
          console.warn('Failed to extract timeline entry from record');
          console.warn(record.toJSON());
        }
        return null;
      }
      if (record.get('media')) {
        out.asset = {
          media: record.get('media'),
          caption: record.get('mediacaption'),
          credit: record.get('mediacredit'),
          thumbnail: record.get('icon')
        };
      }
      out.headline = record.get('title');
      if (record.get('url')) {
        out.headline = '%headline '
          .replace(/%url/g, record.get('url'))
          .replace(/%headline/g, out.headline)
          ;
      }
      out.text = record.get('description');
      if (record.get('source') || record.get('sourceurl')) {
        var s = record.get('source') || record.get('sourceurl');
        if (record.get('sourceurl')) {
          s = '' + s + '';
        }
        out.text += '
Source: ' + s + '
';
      }

      return out;
    };
    this.timeline.render();
  },

  initMap: function(){
      var datapackage = this.model.datapackage;
      var overlayers = {};
      var mapUrl = "//otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
      var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of MapQuest ';
      var bg = new L.TileLayer(mapUrl, {maxZoom: 18, attribution: osmAttribution ,subdomains: '1234'});
      this.map.addLayer(bg);

      for(var i=0;i<datapackage.tmconfig.maplayer_available.length;i++){
        var mapid = datapackage.tmconfig.maplayer_available[i];
        if(!L.RCHSS[mapid])
           console.log(mapid);
        var layer = new L.RCHSS[mapid]({opacity:0.35});
        if(mapid == datapackage.tmconfig.maplayer){
          this.map.addLayer(layer);
        }
        overlayers[layer.name] = layer;
      }
      this.map.addControl(new L.Control.Layers({'OSM': bg}, overlayers));
  },

  _setupMap: function() {
    this.model.datapackage = this.datapackage
    this.map = new recline.View.Map({
      model: this.model
    });
    this.map.initMap = this.initMap;
    this.$el.find('.map').append(this.map.el);

    // customize with icon column
    this.map.infobox = function(record) {
      if (record.icon !== undefined) {
        return ' ' + record.get('title');
      }
      return record.get('title');
    };

    this.map.geoJsonLayerOptions.pointToLayer = function(feature, latlng) {
      var record = this.model.records.get(feature.properties.cid);
      var recordAttr = record.toJSON();
      var maxSize = 400;
      var radius = parseInt(Math.sqrt(maxSize * recordAttr.relativeSize));
      if (radius) {
        var marker = new L.CircleMarker(latlng, {
          radius: radius,
          fillcolor: '#fe9131',
          color: '#fe9131',
          opacity: recordAttr.opacity,
          fillOpacity: recordAttr.opacity * 0.9
        });
      } else {
        var marker = new L.Marker(latlng, {
          opacity: recordAttr.opacity
        });
      }
      var label = recordAttr.title + '
Date: ' + recordAttr.start;
      if (recordAttr.size) {
        label += '
Size: ' + recordAttr.size;
      }
      marker.bindLabel(label);

      // customize with icon column
      if (recordAttr.icon !== undefined) {
        var eventIcon = L.icon({
            iconUrl: recordAttr.icon,
            iconSize:     [100, 20], // size of the icon
            iconAnchor:   [22, 94], // point of the icon which will correspond to marker's location
            shadowAnchor: [4, 62],  // the same for the shadow
            popupAnchor:  [-3, -76] // point from which the popup should open relative to the iconAnchor
        });
        marker.setIcon(eventIcon);
      }

      // this is for cluster case
      // this.markers.addLayer(marker);

      // When a marker is clicked, update the fragment id, which will in turn update the timeline
      marker.on("click", function (e) {
        var i = _.indexOf(record.collection.models, record);
        window.location.hash = "#" + i.toString();
      });

      // Stored so that we can get from record to marker in hashchange callback
      record.marker = marker;

      return marker;
    };
    this.map.render();
  }
});

// convert dates into a format TimelineJS will handle
// TimelineJS does not document this at all so combo of read the code +
// trial and error
// Summary (AFAICt):
// Preferred: [-]yyyy[,mm,dd,hh,mm,ss]
// Supported: mm/dd/yyyy
var normalizeDate = function(date, dayfirst) {
  if (!date) {
    return '';
  }
  var out = $.trim(date);
  // HACK: support people who put '2013-08-20 in gdocs (to force gdocs to
  // not attempt to parse the date)
  if (out.length && out[0] === "'") {
    out = out.slice(1);
  }
  out = out.replace(/(\d)th/g, '$1');
  out = out.replace(/(\d)st/g, '$1');
  out = $.trim(out);
  if (out.match(/\d\d\d\d-\d\d-\d\d(T.*)?/)) {
    out = out.replace(/-/g, ',').replace('T', ',').replace(':',',');
  }
  if (out.match(/\d\d-\d\d-\d\d.*/)) {
    out = out.replace(/-/g, '/');
  }
  if (dayfirst) {
    var parts = out.match(/(\d\d)\/(\d\d)\/(\d\d.*)/);
    if (parts) {
      out = [parts[2], parts[1], parts[3]].join('/');
    }
  }
  return out;
}

})();
<commit_msg>update overlap opacity.<commit_after>(function () {
  "use strict";

jQuery(function($) {
  var reclineDatasetInfo = $.extend({}, true, VIZDATA.resources[0]);
  if (VIZDATA.resources[0].schema && VIZDATA.resources[0].schema.fields) {
    reclineDatasetInfo.fields = VIZDATA.resources[0].schema.fields;
  }
  var dataset = new recline.Model.Dataset(reclineDatasetInfo);
  var timemapper = new TimeMapperView({
    model: dataset,
    datapackage: VIZDATA,
    el: $('.data-views')
  });
  // TODO: move this stuff into a proper view
  $('.js-embed').on('click', function(e) {
    e.preventDefault();
    var url = window.location.href.replace(/#.*$/, "") + '?embed=1'; // for now, just remove any fragment id
    var val = '';
    $('.embed-modal textarea').val(val);
    $('.embed-modal').modal();
  });
});

var TimeMapperView = Backbone.View.extend({
  events: {
    'click .controls .js-show-toolbox': '_onShowToolbox',
    'submit .toolbox form': '_onSearch'
  },

  initialize: function(options) {
    var self = this;
    this._setupOnHashChange();

    this.datapackage = options.datapackage;
    // fix up for datapackage without right structure
    if (!this.datapackage.tmconfig) {
      this.datapackage.tmconfig = {};
    }
    this.timelineState = _.extend({}, this.datapackage.tmconfig.timeline, {
      nonUSDates: this.datapackage.tmconfig.dayfirst,
      timelineJSOptions: _.extend({}, this.datapackage.tmconfig.timelineJSOptions, {
        "hash_bookmark": true
      })
    });
    this._setupTwitter();

    // now load the data
    this.model.fetch().done(function() {
      self.model.query({size: self.model.recordCount})
      .done(function() {
        self._dataChanges();
        self._setStartPosition();
        self._onDataLoaded();
      });
    });
  },

  _setStartPosition: function() {
    var startAtSlide = 0;
    switch (this.datapackage.tmconfig.startfrom) {
      case 'start':
        // done
        break;
      case 'end':
        startAtSlide = this.model.recordCount - 1;
        break;
      case 'today':
        var dateToday = new Date();
        this.model.records.each(function(rec, i) {
          if (rec.get('startParsed') < dateToday) {
            startAtSlide = i;
          }
        });
        break;
    }
    this.timelineState.timelineJSOptions = _.extend(this.timelineState.timelineJSOptions, {
        "start_at_slide": startAtSlide
      }
    );
  },

  _onDataLoaded: function() {
    $('.js-loading').hide();

    // Note: We *have* to postpone setup until now as otherwise timeline
    // might try to navigate to a non-existent marker
    if (this.datapackage.tmconfig.viewtype === 'timeline') {
      // timeline only
      $('body').addClass('viewtype-timeline');
      // fix height of timeline to be window height minus navbar and footer
      $('.timeline-pane').height($(window).height() - 42 - 41);
      this._setupTimeline();
    } else if (this.datapackage.tmconfig.viewtype === 'map') {
      $('body').addClass('viewtype-map');
      this._setupMap();
    } else {
      $('body').addClass('viewtype-timemap');
      this._setupTimeline();
      this._setupMap();
    }

    // Nasty hack. Timeline ignores hashchange events unless is_moving ==
    // True. However, once it's True, it can never become false again. The
    // callback associated with the UPDATE event sets it to True, but is
    // otherwise a no-op.
    $("div.slider").trigger("UPDATE");
  },

  _setupTwitter: function(e) {
    !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
  },

  _dataChanges: function() {
    var self = this;
    this.model.records.each(function(record) {
      // normalize date field names
      if (record.get('startdate') && !record.get('start')) {
        record.set({
          start: record.get('startdate'),
          end: record.get('enddate')
        }, {silent: true}
        );
      }
      var startDate = VMM.Date.parse(normalizeDate(record.get("start"), self.datapackage.tmconfig.dayfirst));
      var data = {
        // VMM.Date.parse is the timelinejs date parser
        startParsed: startDate,
        title: record.get('title') || record.get('headline'),
        description: record.get('description') || record.get('text') || '',
        url: record.get('url') || record.get('webpage'),
        media: record.get('image') || record.get('media'),
        mediacaption: record.get('caption') || record.get('mediacaption') || record.get('imagecaption'),
        mediacredit: record.get('imagecredit') || record.get('mediacredit'),
      };
      if (record.get('size') || record.get('size') === 0) {
        data.size = parseFloat(record.get('size'));
      }
      record.set(data, { silent: true });
    });

    var starts = this.model.records.pluck('startParsed')
      , minDate = _.min(starts)
      , maxDate =  _.max(starts)
      , dateRange = maxDate - minDate
      , sizes = this.model.records.pluck('size')
      , maxSize = _.max(sizes)
      ;
    // set opacity - we compute opacity between 0.1 and 1 based on distance from most recent date
    var minOpacity = 0.3
      , opacityRange = 1.0 - minOpacity
      ;
    this.model.records.each(function(rec) {
      var temporalRangeLocation = (rec.get('startParsed') - minDate) / dateRange;
      rec.set({
        temporalRangeLocation: temporalRangeLocation,
        opacity: minOpacity + (opacityRange * temporalRangeLocation),
        relativeSize: parseFloat(rec.get('size')) / maxSize
      });
    });

    // Timeline will sort the entries by timestamp, and we need the order to be
    // the same for the map which runs off the model
    this.model.records.comparator = function (a, b) {
      return a.get('startParsed') - b.get('startParsed');
    };
    this.model.records.sort();
  },

  _setupOnHashChange: function() {
    var self = this;
    // listen for hashchange to update map
    $(window).on("hashchange", function () {
      var hash = window.location.hash.substring(1);
      if (parseInt(hash, 10)) {
        var record = self.model.records.at(hash);
        if (record && record.marker) {
          record.marker.openPopup();
        }
      }
    });
  },

  _onShowToolbox: function(e) {
    e.preventDefault();
    if (this.$el.find('.toolbox').hasClass('hideme')) {
      this.$el.find('.toolbox').removeClass('hideme');
    } else {
      this.$el.find('.toolbox').addClass('hideme');
    }
  },

  _onSearch: function(e) {
    e.preventDefault();
    var query = this.$el.find('.text-query input').val();
    this.model.query({q: query});
  },

  _setupTimeline: function() {
    this.timeline = new recline.View.Timeline({
      model: this.model,
      el: this.$el.find('.timeline'),
      state: this.timelineState
    });

    // convert the record to a structure suitable for timeline.js
    this.timeline.convertRecord = function(record, fields) {
      if (record.get('startParsed') == 'Invalid Date') {
        if (typeof console !== "undefined" && console.warn) {
          console.warn('Failed to extract date from record');
          console.warn(record.toJSON());
        }
        return null;
      }
      try {
        var out = this._convertRecord(record, fields);
      } catch (e) {
        out = null;
      }
      if (!out) {
        if (typeof console !== "undefined" && console.warn) {
          console.warn('Failed to extract timeline entry from record');
          console.warn(record.toJSON());
        }
        return null;
      }
      if (record.get('media')) {
        out.asset = {
          media: record.get('media'),
          caption: record.get('mediacaption'),
          credit: record.get('mediacredit'),
          thumbnail: record.get('icon')
        };
      }
      out.headline = record.get('title');
      if (record.get('url')) {
        out.headline = '%headline '
          .replace(/%url/g, record.get('url'))
          .replace(/%headline/g, out.headline)
          ;
      }
      out.text = record.get('description');
      if (record.get('source') || record.get('sourceurl')) {
        var s = record.get('source') || record.get('sourceurl');
        if (record.get('sourceurl')) {
          s = '' + s + '';
        }
        out.text += '
Source: ' + s + '
';
      }

      return out;
    };
    this.timeline.render();
  },

  initMap: function(){
      var datapackage = this.model.datapackage;
      var overlayers = {};
      var mapUrl = "//otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
      var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of MapQuest ';
      var bg = new L.TileLayer(mapUrl, {maxZoom: 18, attribution: osmAttribution ,subdomains: '1234'});
      this.map.addLayer(bg);

      for(var i=0;i<datapackage.tmconfig.maplayer_available.length;i++){
        var mapid = datapackage.tmconfig.maplayer_available[i];
        if(!L.RCHSS[mapid])
           console.log(mapid);
        var layer = new L.RCHSS[mapid]({opacity:0.75});
        if(mapid == datapackage.tmconfig.maplayer){
          this.map.addLayer(layer);
        }
        overlayers[layer.name] = layer;
      }
      this.map.addControl(new L.Control.Layers({'OSM': bg}, overlayers));
  },

  _setupMap: function() {
    this.model.datapackage = this.datapackage
    this.map = new recline.View.Map({
      model: this.model
    });
    this.map.initMap = this.initMap;
    this.$el.find('.map').append(this.map.el);

    // customize with icon column
    this.map.infobox = function(record) {
      if (record.icon !== undefined) {
        return ' ' + record.get('title');
      }
      return record.get('title');
    };

    this.map.geoJsonLayerOptions.pointToLayer = function(feature, latlng) {
      var record = this.model.records.get(feature.properties.cid);
      var recordAttr = record.toJSON();
      var maxSize = 400;
      var radius = parseInt(Math.sqrt(maxSize * recordAttr.relativeSize));
      if (radius) {
        var marker = new L.CircleMarker(latlng, {
          radius: radius,
          fillcolor: '#fe9131',
          color: '#fe9131',
          opacity: recordAttr.opacity,
          fillOpacity: recordAttr.opacity * 0.9
        });
      } else {
        var marker = new L.Marker(latlng, {
          opacity: recordAttr.opacity
        });
      }
      var label = recordAttr.title + '
Date: ' + recordAttr.start;
      if (recordAttr.size) {
        label += '
Size: ' + recordAttr.size;
      }
      marker.bindLabel(label);

      // customize with icon column
      if (recordAttr.icon !== undefined) {
        var eventIcon = L.icon({
            iconUrl: recordAttr.icon,
            iconSize:     [100, 20], // size of the icon
            iconAnchor:   [22, 94], // point of the icon which will correspond to marker's location
            shadowAnchor: [4, 62],  // the same for the shadow
            popupAnchor:  [-3, -76] // point from which the popup should open relative to the iconAnchor
        });
        marker.setIcon(eventIcon);
      }

      // this is for cluster case
      // this.markers.addLayer(marker);

      // When a marker is clicked, update the fragment id, which will in turn update the timeline
      marker.on("click", function (e) {
        var i = _.indexOf(record.collection.models, record);
        window.location.hash = "#" + i.toString();
      });

      // Stored so that we can get from record to marker in hashchange callback
      record.marker = marker;

      return marker;
    };
    this.map.render();
  }
});

// convert dates into a format TimelineJS will handle
// TimelineJS does not document this at all so combo of read the code +
// trial and error
// Summary (AFAICt):
// Preferred: [-]yyyy[,mm,dd,hh,mm,ss]
// Supported: mm/dd/yyyy
var normalizeDate = function(date, dayfirst) {
  if (!date) {
    return '';
  }
  var out = $.trim(date);
  // HACK: support people who put '2013-08-20 in gdocs (to force gdocs to
  // not attempt to parse the date)
  if (out.length && out[0] === "'") {
    out = out.slice(1);
  }
  out = out.replace(/(\d)th/g, '$1');
  out = out.replace(/(\d)st/g, '$1');
  out = $.trim(out);
  if (out.match(/\d\d\d\d-\d\d-\d\d(T.*)?/)) {
    out = out.replace(/-/g, ',').replace('T', ',').replace(':',',');
  }
  if (out.match(/\d\d-\d\d-\d\d.*/)) {
    out = out.replace(/-/g, '/');
  }
  if (dayfirst) {
    var parts = out.match(/(\d\d)\/(\d\d)\/(\d\d.*)/);
    if (parts) {
      out = [parts[2], parts[1], parts[3]].join('/');
    }
  }
  return out;
}

})();
<|endoftext|>


<commit_before>
//Defino funcion constructora wikiController para crear objeto y seleccionar los elementos
function WikiController(tapiz, guardar, editar){

    this.tapiz = document.getElementById(tapiz);

    this.guardar = document.getElementById(guardar);

    this.editar = document.getElementById(editar);

}

//Defino funcion constructora Wiki para crear ojetos de su subtipo
//@id id de la wiki.
//@styles estilos de la wiki
//@sitax sintasis de la wiki
function Wiki(id, styles, sintax){

    this.id = id;

    this.styles = {
        'width': '100%',
        'height': '400px',
        'border': '1px solid blue'
    };

    //Array con sintaxis de la Wiki para comparar con los strings recogidos del textarea
    this.sintax = [
        sections = "=",
        articles = "-",
        divs     = "#",
        back     = "*",
        linksInit = "[",
        linksFin = "]",
        linksToInit  = "(",
        linksToFin   = ""
    ];

    //metodo de insertar textarea en el tapiz para el modo edicion.
    //@id identificador de la wiki a editar (ya lo tenemos al crear el objeto).
    this.insertarTextarea = function(id){
        var textarea = document.createElement("textarea");
        textarea.id = "area1";
        textarea.rows = 20;
        textarea.cols = 100;
        //aplicarEstilos(textarea, estilos);
        tapiz.appendChild(textarea);

        // return ...el return ha de colocar el cursor en el textarea directamente e incluir en el textarea el contenido guardado.
    };

    //Metodo para recoger datos de la wiki
    //@id identificador de la wiki de la que hay que recoger los datos.
    this.recogerWiki = function(id){};

    //Metodo de guardar en JSON las cadenas de texto recogidas en el textarea.
    //@id identificador a guardar (ya lo tenemos al crear el objeto)
    this.guardarTextarea = function(id){
        var area = document.getElementById('area1');
        console.log(area);
        //var areaText = area.nodeValue; //da element input no el nodo de texto.
        //var childrenTextarea = area.childNodes; //da 0 nodos hijos??
        var text = new String(area.value); //variable de tipo string, nos interesa objeto ??
        //alert(text);
        var textString = area.value;
        console.log(textString);
        console.log(text);

        var sections = splitSections(text, "===");

        //Metodo que convertirá el textarea y compara los simbolos de la sintaxis de la wiki para formatear la vista de la wiki.
        function splitSections(string, caracter){
            var arraySections = new Array();
            var count = 0;
            var lastCount;

            //Recorro el string para detectar las secciones
            for (var i = 0; i< string.length; i++) {

                var t = i + 2;
                //creo un objeto por cada section y los atributos id, numero de inicio y el fin de la misma.
                if(string[i] == "=" && string[i++] == "=" && string[t] == "="){
                    lastCount = count;
                    console.log(lastCount);
                    count = count+1;

                    //TODO: creo que crea objetos fuera de la matriz pero dentro del objeto, con lo que no se podra recorrer. comprobar
                    arraySections[count] = {};
                    arraySections[count].id = count;
                    arraySections[count].inicio = i;

                    //Si he detectado otra seccion, como no es la ultima le establezco el fin de la anterior
                    if(count > 1){
                        arraySections[lastCount].fin = i -1;
                    }
                }
            }

            // Y cuando salgo del for le agrego al ultimo objeto su fin que sera el fin del String
            arraySections[count].fin = string.length;

            //Extraigo los titulos y guardo los strings de cada section en su objeto
            for (var i = 0; i < arraySections.length; i++){
                console.log(arraySections[i]);

            }

            console.log(arraySections);
            //var strings = string.split(caracter);
            return arraySections;
        };

        //console.log(sections);

       // return el return ha de llamar a convertirTextarea para guardarla en formato convertido
       return sections;
    };

    //Metodo que aplica una lista de estilos a un elemento.
    //@element elemento a aplicar los estilos
    //@listaEstilos estilos a aplicar al elemento.
    this.aplicarEstilos = function (elemento, listaEstilos){
        for (var estilo in listaEstilos ){
            elemento.style[estilo] = listaEstilos[estilo];
        }
    };

};

function crearObjWiki(id){
    //TODO:consultar previamente el id correspondiente
    var wiki = new Wiki(id);
    return wiki;

};

var wikiCtl = new WikiController("tapiz", "guardar", "editar" );
var wiki = new Wiki(1, {}, []);

//window.onload = ;
editar.onclick = wiki.insertarTextarea;
guardar.onclick = wiki.guardarTextarea;
<commit_msg>Conseguido guardar los titulos de cada section substrayendolos del string<commit_after>
//Defino funcion constructora wikiController para crear objeto y seleccionar los elementos
function WikiController(tapiz, guardar, editar){

    this.tapiz = document.getElementById(tapiz);

    this.guardar = document.getElementById(guardar);

    this.editar = document.getElementById(editar);

}

//Defino funcion constructora Wiki para crear ojetos de su subtipo
//@id id de la wiki.
//@styles estilos de la wiki
//@sitax sintasis de la wiki
function Wiki(id, styles, sintax){

    this.id = id;

    this.styles = {
        'width': '100%',
        'height': '400px',
        'border': '1px solid blue'
    };

    //Array con sintaxis de la Wiki para comparar con los strings recogidos del textarea
    this.sintax = [
        sections = "=",
        articles = "-",
        divs     = "#",
        back     = "*",
        linksInit = "[",
        linksFin = "]",
        linksToInit  = "(",
        linksToFin   = ""
    ];

    //metodo de insertar textarea en el tapiz para el modo edicion.
    //@id identificador de la wiki a editar (ya lo tenemos al crear el objeto).
    this.insertarTextarea = function(id){
        var textarea = document.createElement("textarea");
        textarea.id = "area1";
        textarea.rows = 20;
        textarea.cols = 100;
        //aplicarEstilos(textarea, estilos);
        tapiz.appendChild(textarea);

        // return ...el return ha de colocar el cursor en el textarea directamente e incluir en el textarea el contenido guardado.
    };

    //Metodo para recoger datos de la wiki
    //@id identificador de la wiki de la que hay que recoger los datos.
    this.recogerWiki = function(id){};

    //Metodo de guardar en JSON las cadenas de texto recogidas en el textarea.
    //@id identificador a guardar (ya lo tenemos al crear el objeto)
    this.guardarTextarea = function(id){
        var area = document.getElementById('area1');
        console.log(area);
        //var areaText = area.nodeValue; //da element input no el nodo de texto.
        //var childrenTextarea = area.childNodes; //da 0 nodos hijos??
        var text = new String(area.value); //variable de tipo string, nos interesa objeto ??

        //Pruebas de atributos de area
        var textString = area.value;
        console.log(textString);
        console.log(text);

        var sections = splitSections(text);

        //Metodo que convertirá el textarea y compara los simbolos de la sintaxis de la wiki para formatear la vista de la wiki.
        function splitSections(string){
            var arraySections = new Array();
            var count = 0;
            var lastCount;

            //Recorro el string para detectar las secciones
            for (var i = 0; i< string.length; i++) {
                var t = i + 2;

                //Cuando tengo 3 = seguidos, estoy en una section...
                if(string[i] == "=" && string[i++] == "=" && string[t] == "="){
                    lastCount = count;
                    count = count+1;

                    //Creo un objeto en el array, en el indice numerico en el que estoy
                    arraySections[count] = {};
                    //El id será igual al inidice del array
                    arraySections[count].id = count;
                    //El inicio de la section es en el que estoy ahora mismo.
                    arraySections[count].inicio = i;

                    console.log(i);
                    //Localizo el salto de líne posterior al lugar en el que estoy.
                    var nextSalto = string.indexOf("\n",i);

                    console.log(nextSalto);

                    //Guardo el título en el objeto de section
                    arraySections[count].titulo = string.substring(i+3, nextSalto);

                    //Si he detectado otra seccion, como no es la ultima le establezco el fin de la anterior
                    if(count > 1){
                        arraySections[lastCount].fin = i -1;
                    }
                }
            }

            // Y cuando salgo del for le agrego al ultimo objeto su fin que sera el fin del String
            arraySections[count].fin = string.length;

            console.log(arraySections);
            //var strings = string.split(caracter);
            return arraySections;
        };

        //console.log(sections);

       // return el return ha de llamar a convertirTextarea para guardarla en formato convertido
       return sections;
    };

    //Metodo que aplica una lista de estilos a un elemento.
    //@element elemento a aplicar los estilos
    //@listaEstilos estilos a aplicar al elemento.
    this.aplicarEstilos = function (elemento, listaEstilos){
        for (var estilo in listaEstilos ){
            elemento.style[estilo] = listaEstilos[estilo];
        }
    };

};

function crearObjWiki(id){
    //TODO:consultar previamente el id correspondiente
    var wiki = new Wiki(id);
    return wiki;

};

var wikiCtl = new WikiController("tapiz", "guardar", "editar" );
var wiki = new Wiki(1, {}, []);

//window.onload = ;
editar.onclick = wiki.insertarTextarea;
guardar.onclick = wiki.guardarTextarea;
<|endoftext|>


<commit_before>(function(global){

const oriMapViewBox = document.querySelector('#mapcanvas').getAttribute('viewBox');

// update info when clicking on a node in the graph visualization
document.querySelector('#content').addEventListener('click', function(event){
    // click could happen on .node or an element inside of .node
    if (event.target.mozMatchesSelector('.node, .node *')){
        var node = event.target;
        while(node.mozMatchesSelector('.node *')){
            node = node.parentElement;
        }
        // console.log('svg node: %o, name: %s, data node: %s', node, node.getAttribute('data-name'), aggregate.nodeForKey(node.getAttribute('data-name')));
        updateInfo(node.getAttribute('data-name'));
    }else{
        //console.log('does not match .node: %o', event.target);
    }
},false);

// get server info from http://freegeoip.net
function getServerInfo(nodeName, callback){
    var info = parseUri(nodeName); // uses Steven Levithan's parseUri 1.2.2
    var jsonURL = "http://freegeoip.net/json/" + info.host;
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", jsonURL, false );
    xmlHttp.send( null );
    callback( (xmlHttp.status == 200) ? JSON.parse(xmlHttp.responseText) : false );
}

// reset map
function resetMap(){
    var preHighlight = document.querySelectorAll(".highlight-country");
    if (preHighlight){
        toArray(preHighlight).forEach(function(element){
            element.classList.remove("highlight-country");
        });
    }
    document.querySelector("#mapcanvas").setAttribute("viewBox", oriMapViewBox);
}

// update map
function updateMap(countryCode){
    var countryOnMap = d3.select("#mapcanvas").select("#" + countryCode.toLowerCase());
    countryOnMap.classed("highlight-country", true);
    countryOnMap.selectAll("*").classed("highlight-country", true);

    // position the highlighted country in center
    var svgViewBox = document.querySelector("#mapcanvas").getAttribute("viewBox").split(" ");
    var worldDimen = document.querySelector("#mapcanvas").getClientRects()[0];
    var countryDimen = document.querySelector("#"+countryCode).getClientRects()[0];

    var ratio = svgViewBox[2] / worldDimen.width;
    var worldCenter = {
        x: 0.5*worldDimen.width + worldDimen.left,
        y: 0.5*worldDimen.height + worldDimen.top
    };
    var countryCenter = {
        x: 0.5*countryDimen.width + countryDimen.left,
        y: 0.5*countryDimen.height + countryDimen.top
    };

    var newViewBox = {
        x: (countryCenter.x-worldCenter.x) * ratio,
        y: (countryCenter.y-worldCenter.y) * ratio,
        w: svgViewBox[2],
        h: svgViewBox[3]
    };
    setZoom(newViewBox,'mapcanvas');
}

// updates info on the right info bar
function updateInfo(nodeName){

    // update content in the side bar
    getServerInfo(nodeName, function(data){
        document.querySelector(".holder .title").innerHTML = nodeName;
        //document.querySelector(".holder .url").innerHTML = nodeName;

        if ( data == false || data.country_name === "Reserved" ){
            document.querySelector("#country").innerHTML = "(Unable to find server location)";
            resetMap();
        }else{
            // update country info only when it is different from the current one
            if ( data.country_name !==  document.querySelector("#country").innerHTML ){
                resetMap();
                document.querySelector("#country").innerHTML = data.country_name;
                var countryOnMap = document.querySelectorAll("svg #" + data.country_code.toLowerCase());
                if ( countryOnMap ){ updateMap(data.country_code.toLowerCase()); }
            }
        }

        // update the connections list
        var nodeList = aggregate.nodeForKey(nodeName);
        var htmlList = "";
        for ( var key in nodeList ){
            if ( key != nodeName ){
                htmlList = htmlList + "
" + key + "
";
            }
        }
        document.querySelector(".connections-list").querySelector(".blue-text").innerHTML = Object.keys(nodeList).length-1 + " connections from current site";
        document.querySelector(".connections-list ul").innerHTML = htmlList;

        document.querySelector("#content").classList.add("showinfo");
    });

}

/*
// FIX THIS!!! applying translation causes the map to fracture
// the svg map uses Robinson projection
d3.select("#mapcanvas").attr("cursor","-moz-grab").call(
    d3.behavior.zoom()
        .translate ([0, 0])
        .scale (1.0)
        .scaleExtent([1.0, 4.0])
        .on("zoom", function(){
            d3.selectAll("#mapcanvas > *")
                .attr("transform","translate(" + d3.event.translate.join(",") + ")" +
                      " scale(" +  d3.event.scale + ")");
        })
);
*/

})(this);

<commit_msg>changed text on UI<commit_after>(function(global){

const oriMapViewBox = document.querySelector('#mapcanvas').getAttribute('viewBox');

// update info when clicking on a node in the graph visualization
document.querySelector('#content').addEventListener('click', function(event){
    // click could happen on .node or an element inside of .node
    if (event.target.mozMatchesSelector('.node, .node *')){
        var node = event.target;
        while(node.mozMatchesSelector('.node *')){
            node = node.parentElement;
        }
        // console.log('svg node: %o, name: %s, data node: %s', node, node.getAttribute('data-name'), aggregate.nodeForKey(node.getAttribute('data-name')));
        updateInfo(node.getAttribute('data-name'));
    }else{
        //console.log('does not match .node: %o', event.target);
    }
},false);

// get server info from http://freegeoip.net
function getServerInfo(nodeName, callback){
    var info = parseUri(nodeName); // uses Steven Levithan's parseUri 1.2.2
    var jsonURL = "http://freegeoip.net/json/" + info.host;
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", jsonURL, false );
    xmlHttp.send( null );
    callback( (xmlHttp.status == 200) ? JSON.parse(xmlHttp.responseText) : false );
}

// reset map
function resetMap(){
    var preHighlight = document.querySelectorAll(".highlight-country");
    if (preHighlight){
        toArray(preHighlight).forEach(function(element){
            element.classList.remove("highlight-country");
        });
    }
    document.querySelector("#mapcanvas").setAttribute("viewBox", oriMapViewBox);
}

// update map
function updateMap(countryCode){
    var countryOnMap = d3.select("#mapcanvas").select("#" + countryCode.toLowerCase());
    countryOnMap.classed("highlight-country", true);
    countryOnMap.selectAll("*").classed("highlight-country", true);

    // position the highlighted country in center
    var svgViewBox = document.querySelector("#mapcanvas").getAttribute("viewBox").split(" ");
    var worldDimen = document.querySelector("#mapcanvas").getClientRects()[0];
    var countryDimen = document.querySelector("#"+countryCode).getClientRects()[0];

    var ratio = svgViewBox[2] / worldDimen.width;
    var worldCenter = {
        x: 0.5*worldDimen.width + worldDimen.left,
        y: 0.5*worldDimen.height + worldDimen.top
    };
    var countryCenter = {
        x: 0.5*countryDimen.width + countryDimen.left,
        y: 0.5*countryDimen.height + countryDimen.top
    };

    var newViewBox = {
        x: (countryCenter.x-worldCenter.x) * ratio,
        y: (countryCenter.y-worldCenter.y) * ratio,
        w: svgViewBox[2],
        h: svgViewBox[3]
    };
    setZoom(newViewBox,'mapcanvas');
}

// updates info on the right info bar
function updateInfo(nodeName){

    // update content in the side bar
    getServerInfo(nodeName, function(data){
        document.querySelector(".holder .title").innerHTML = nodeName;
        //document.querySelector(".holder .url").innerHTML = nodeName;

        if ( data == false || data.country_name === "Reserved" ){
            document.querySelector("#country").innerHTML = "(Unable to find server location)";
            resetMap();
        }else{
            // update country info only when it is different from the current one
            if ( data.country_name !==  document.querySelector("#country").innerHTML ){
                resetMap();
                document.querySelector("#country").innerHTML = data.country_name;
                var countryOnMap = document.querySelectorAll("svg #" + data.country_code.toLowerCase());
                if ( countryOnMap ){ updateMap(data.country_code.toLowerCase()); }
            }
        }

        // update the connections list
        var nodeList = aggregate.nodeForKey(nodeName);
        var htmlList = "";
        for ( var key in nodeList ){
            if ( key != nodeName ){
                htmlList = htmlList + "
" + key + "
";
            }
        }
        document.querySelector(".connections-list").querySelector(".blue-text").innerHTML = Object.keys(nodeList).length-1 + " sites have connections to/from current site";
        document.querySelector(".connections-list ul").innerHTML = htmlList;

        document.querySelector("#content").classList.add("showinfo");
    });

}

/*
// FIX THIS!!! applying translation causes the map to fracture
// the svg map uses Robinson projection
d3.select("#mapcanvas").attr("cursor","-moz-grab").call(
    d3.behavior.zoom()
        .translate ([0, 0])
        .scale (1.0)
        .scaleExtent([1.0, 4.0])
        .on("zoom", function(){
            d3.selectAll("#mapcanvas > *")
                .attr("transform","translate(" + d3.event.translate.join(",") + ")" +
                      " scale(" +  d3.event.scale + ")");
        })
);
*/

})(this);

<|endoftext|>


<commit_before>var selectorGraphs = Selector()
    .callback(function(d){
        $('#'+selectorGraphs.type()).html(d.name);
        $('#dimensions input[name='+selectorGraphs.type()+']').val(d.id).trigger('change');
        $('#modal-selector').modal('hide');
    });

function select_dimension_graph(id) {
  d3.select("#modal-selector-content").call(selectorGraphs.type(id));
  $('#modal-selector').modal('show');
}

function deactivate_dimension_graph(id) {
  $(id).siblings("button").html('Select');
  $(id).siblings("input").val("all").trigger('change');
}

$('.dropdown-select').on( 'click', '.dropdown-menu li a', function() {
   var target = $(this).html();

   //Adds active class to selected item
   $(this).parents('.dropdown-menu').find('li').removeClass('active');
   $(this).parent('li').addClass('active');

   //Displays selected text on dropdown-toggle button
   $(this).parents('.dropdown-select').find('.dropdown-toggle').html(target);
});

dataviva.requireAttrs(['datasets'], function() {

    for (dataset in dataviva.datasets) {
        $('#datasets').append( $('<option value="'+dataset+'">'+dataviva.dictionary[dataset]+'</option>'));
    }

    $('#datasets').on('change', function() {
        $('#datasets #dataset-empty-option').remove();
        var dataset = this.value;

        $('#dimensions').empty();
        dataviva.datasets[dataset].dimensions.forEach(function(dimension, index) {
                var div = $("

").addClass("form-group"),
                label = $("").attr("for", dimension.id).addClass("control-label"),
                deactivate_button = $("<button></button>").attr("for", dimension.id).addClass("btn btn-xs btn-link pull-right")
                                        .html(dataviva.dictionary['deactivate'])
                                        .attr("onclick", "deactivate_dimension_graph(this)"),
                selector_button = $("<button></button>").attr("id", dimension.id).addClass("btn btn-block btn-outline btn-primary")
                                        .attr("onclick", "select_dimension_graph(id);")
                                        .html(dataviva.dictionary['select']);

                filter = $("<input></input>").attr("type", "hidden").attr("name", dimension.id).attr("id", 'filter'+index).val('all');

                label.html(dataviva.dictionary[dimension.id]);

                filter.change(function() {
                      $.ajax({
                            method: "GET",
                            url: "/" + lang + "/build_graph/views/" + dataset +"/" +
                                $('#dimensions #filter0').val() + "/" +
                                ($('#dimensions #filter1').val() == 'all' ? 'all' : $('#dimensions #filter1')[0].name) + "/" +
                                ($('#dimensions #filter2').val() == 'all' ? 'all' : $('#dimensions #filter2')[0].name),
                            data: {
                                    filter1: $('#dimensions #filter1').val(),
                                    filter2: $('#dimensions #filter2').val()
                                },
                            success: function (result) {
                                //('#titles').empty()

                                window.buildGraphViews = result.views;

                                if(result.views){

                                    $('#views').empty()

                                    var div = $("

").addClass("form-group");
                                        select = $("<select></select>").addClass("form-control"),
                                        label = $("").attr("for", "titles").addClass("control-label"),

                                    label.html(dataviva.dictionary["views"]);

                                    for(view in result.views){
                                        option = $('<option value="'+view+'">'+view+'</option>')
                                        select.append(option);
                                    }

                                    select.on('change', function() {
                                        $('#graphs').empty()

                                        for (graph in buildGraphViews[this.value]) {
                                            var name = buildGraphViews[this.value][graph].name,
                                                url = buildGraphViews[this.value][graph].url
                                            graphButton = $('').addClass('btn btn-primary')
                                                            .attr('href', "/" + dataviva.language + '/embed/' + url)
                                                            .attr('target', "graphs-frame-build-graphs")
                                                            .html(name);
                                            $('#graphs').append(graphButton);
                                        }
                                    });

                                    div.append(label).append(select);

                                    $('#views').append(div);
                            }
                        }
                    });

                });

                if (dimension.name == 'School') {
                    div.append(filter)
                } else {
                    div.append(filter).append(label).append(deactivate_button).append(selector_button)
                }

                $('#dimensions').append(div);
        });
    });
});

<commit_msg>Adds build a graph controller better structure<commit_after>var selectorGraphs = Selector()
    .callback(function(d){
        $('#'+selectorGraphs.type()).html(d.name);
        $('#dimensions input[name='+selectorGraphs.type()+']').val(d.id).trigger('change');
        $('#modal-selector').modal('hide');
    });

function select_dimension_graph(id) {
  d3.select("#modal-selector-content").call(selectorGraphs.type(id));
  $('#modal-selector').modal('show');
}

var buildGraph = (function () {

    return {
        dataset: dataset,
        views: views,
        init: init
    }

    var views, dataset;

    function buildDimensions(dataset) {
        $('#dimensions').empty();
        dataviva.datasets[dataset].dimensions.forEach(function(dimension, index) {
            var div = $('

').addClass('form-group'),
            label = $('').attr('for', dimension.id).addClass('control-label'),
            deactivate_button = $('<button></button>').attr('for', dimension.id).addClass('btn btn-xs btn-link pull-right')
                                    .html(dataviva.dictionary['deactivate'])
                                    .attr('onclick', 'deactivate_dimension_graph(this)'),
            selector_button = $('<button></button>').attr('id', dimension.id).addClass('btn btn-block btn-outline btn-primary')
                                    .html(dataviva.dictionary['select'])
                                    .attr('onclick', 'select_dimension_graph(id);');

            filter = $('<input></input>').attr('type', 'hidden').attr('name', dimension.id).attr('id', 'filter'+index).val('all');

            label.html(dataviva.dictionary[dimension.id]);

            if (dimension.name == 'School') {
                div.append(filter);
            } else {
                div.append(filter).append(label).append(deactivate_button).append(selector_button);
            }

            $('#dimensions').append(div);
        });
    }

    function buildViews(views) {
        $('#views').empty()

        var div = $('

').addClass('form-group');
            select = $('<select></select>').addClass('form-control'),
            label = $('').attr('for', 'titles').addClass('control-label'),

        label.html(dataviva.dictionary['views']);

        for(view in views){
            option = $('<option value="'+view+'">'+view+'</option>')
            select.append(option);
        }

        div.append(label).append(select);
        $('#views').append(div);
    }

    function buildGraphs(graphs) {
        $('#graphs').empty()

        var div = $('

').attr('class', 'dropdown dropdown-select');
            graphButton = $('<button data-toggle="dropdown" aria-expanded="true"></button>')
                            .attr('id', 'graph-button')
                            .attr('class', 'btn btn-outline btn-block dropdown-toggle'),
            dropDownMenu = $('

')
                            .attr('class', 'dropdown-menu'),
            label = $('').attr('for', 'graph-button').addClass('control-label');

        label.html(dataviva.dictionary['graphs']);

        for(graph in graphs){
            option = $('<option value="'+graph+'">'+graph+'</option>')
            select.append(option);
        }

        div.on( 'click', '.dropdown-menu li a', function() {
           var target = $(this).html();

           //Adds active class to selected item
           $(this).parents('.dropdown-menu').find('li').removeClass('active');
           $(this).parent('li').addClass('active');

           //Displays selected text on dropdown-toggle button
           $(this).parents('.dropdown-select').find('.dropdown-toggle').html(target);
        });

        div.append(label).append(select);
        $('#graphs').append(div);
    }

    function updateViews() {
        $.ajax({
            method: "GET",
            url: "/" + lang + "/build_graph/views/" + dataset +"/" +
                $('#dimensions #filter0').val() + "/" +
                ($('#dimensions #filter1').val() == 'all' ? 'all' : $('#dimensions #filter1')[0].name) + "/" +
                ($('#dimensions #filter2').val() == 'all' ? 'all' : $('#dimensions #filter2')[0].name),
            data: {
                    filter1: $('#dimensions #filter1').val(),
                    filter2: $('#dimensions #filter2').val()
                },
            success: function (result) {
                console.log(result.views);
            }
        });
    }

    function changeDataSet() {
        buildGraph.dataset = this.value;
        buildDimensions(this.value);
        updateViews();
    }

    function init() {
        for (dataset in dataviva.datasets) {
            $('#datasets').append( $('<option value="'+dataset+'">'+dataviva.dictionary[dataset]+'</option>'));
        }

        $('#datasets').on('change', changeDataSet);
    }
})();

function deactivate_dimension_graph(id) {
  $(id).siblings('button').html('Select');
  $(id).siblings('input').val('all').trigger('change');
}

$(document).ready(function () {
    dataviva.requireAttrs(['datasets'], function() {
        buildGraph.init();
    });
});

<|endoftext|>


<commit_before><commit_msg>Remove flash message on login.<commit_after><|endoftext|>


<commit_before>module.exports = {
  description: '',
  normalizeEntityName: function () {},

  /**
    Installs specified packages at the root level of the application.
    Triggered by 'ember install <addon name>'.
    @returns {Promise} package names and versions
  */
  afterInstall: function () {
    return this.addAddonsToProject({
      packages: [
        {name: 'ember-frost-core', target: '>=0.29.0 <2.0.0'}
      ]
    })
  }
}
<commit_msg>update blueprint<commit_after>module.exports = {
  description: '',
  normalizeEntityName: function () {},

  /**
    Installs specified packages at the root level of the application.
    Triggered by 'ember install <addon name>'.
    @returns {Promise} package names and versions
  */
  afterInstall: function () {
    return this.addAddonsToProject({
      packages: [
        {name: 'ember-frost-core', target: '>=0.29.0 <2.0.0'},
        {name: 'ember-hook', target: '~1.3.1'}
      ]
    })
  }
}
<|endoftext|>


<commit_before>import { checkPropTypes } from './check-props';
import { getDisplayName } from './devtools/custom';
import { options } from 'preact';
import { ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE } from './constants';

function getClosestDomNodeParent(parent) {
	if (!parent) return null;
	if (typeof parent.type === 'function') {
		return getClosestDomNodeParent(parent._parent);
	}
	return parent.type;
}

export function initDebug() {
	/* eslint-disable no-console */
	let oldBeforeDiff = options._diff;
	let oldDiffed = options.diffed;
	let oldVnode = options.vnode;
	const warnedComponents = { useEffect: {}, useLayoutEffect: {}, lazyPropTypes: {} };

	options._catchError = (error, vnode) => {
		let component = vnode && vnode._component;
		if (component && typeof error.then === 'function') {
			error = new Error('Missing Suspense. The throwing component was: ' + (component.displayName || component.name));
		}
	};

	options._root = (vnode, parentNode) => {
		if (!parentNode) {
			throw new Error('Undefined parent passed to render(), this is the second argument.\nCheck if the element is available in the DOM/has the correct id.');
		}
		let isValid;
		switch (parentNode.nodeType) {
			case ELEMENT_NODE:
			case DOCUMENT_FRAGMENT_NODE:
			case DOCUMENT_NODE: isValid = true; break;
			default: isValid = false;
		}
		if (!isValid) throw new Error(`
			Expected a valid HTML node as a second argument to render.
			Received ${parentNode} instead: render(<${vnode.type.name || vnode.type} />, ${parentNode});
		`);
	};

	options._diff = vnode => {
		if (vnode == null) { return; }

		let { type, _parent: parent } = vnode;
		let parentType = getClosestDomNodeParent(parent);

		if (type===undefined) {
			throw new Error('Undefined component passed to createElement()\n\n'+
			'You likely forgot to export your component or might have mixed up default and named imports'+
			serializeVNode(vnode));
		}
		else if (type!=null && typeof type==='object') {
			if (type._lastDomChild!==undefined && type._dom!==undefined) {
				let info = 'Did you accidentally pass a JSX literal as JSX twice?\n\n'+
				'  let My'+getDisplayName(type)+' = '+serializeVNode(type)+';\n'+
				'  let vnode = <My'+getDisplayName(type)+' />;\n\n'+
				'This usually happens when you export a JSX literal and not the component.';
				throw new Error('Invalid type passed to createElement(): '+type+'\n\n'+info+'\n');
			}

			throw new Error('Invalid type passed to createElement(): '+(Array.isArray(type) ? 'array' : type));
		}

		if ((type==='thead' || type==='tfoot' || type==='thead') && parentType!=='table') {
			console.error(
				'Improper nesting of table.' +
				'Your <thead/tbody/tfoot> should have a <table> parent.'
				+ serializeVNode(vnode)
			);
		}
		else if (type==='tr' && (parentType!=='thead' && parentType!=='tfoot' && parentType!=='tbody')) {
			console.error(
				'Improper nesting of table.' +
				'Your <tr> should have a <thead/tbody/tfoot> parent.'
				+ serializeVNode(vnode)
			);
		}
		else if (type==='td') {
			if (parentType!=='tr') {
				console.error(
					'Improper nesting of table.' +
					'Your <td> should have a <tr> parent.'
					+ serializeVNode(vnode)
				);
			} else if (parent._parent.type === 'thead') {
				console.error(
					'Improper nesting of table.' +
					'Your <thead> should use <th> instead of <td>.'
					+ serializeVNode(vnode)
				);
			}
		}
		else if (type==='th' && parentType!=='tr') {
			console.error(
				'Improper nesting of table.' +
				'Your <th> should have a <tr> parent with a <thead> parent.'
				+ serializeVNode(vnode)
			);
		}

		if (
			vnode.ref!==undefined &&
			typeof vnode.ref!=='function' &&
			typeof vnode.ref!=='object' &&
			!('$$typeof' in vnode)  // allow string refs when preact-compat is installed
		) {
			throw new Error(
				`Component's "ref" property should be a function, or an object created ` +
				`by createRef(), but got [${typeof vnode.ref}] instead\n` +
				serializeVNode(vnode)
			);
		}

		if (typeof vnode.type==='string') {
			for (const key in vnode.props) {
				if (key[0]==='o' && key[1]==='n' && typeof vnode.props[key]!=='function' && vnode.props[key]!=null) {
					throw new Error(
						`Component's "${key}" property should be a function, ` +
						`but got [${typeof vnode.props[key]}] instead\n` +
						serializeVNode(vnode)
					);
				}
			}
		}

		// Check prop-types if available
		if (typeof vnode.type==='function' && vnode.type.propTypes) {
			if (vnode.type.displayName === 'Lazy' && !warnedComponents.lazyPropTypes[vnode.type]) {
				const m = 'PropTypes are not supported on lazy(). Use propTypes on the wrapped component itself. ';
				try {
					const lazyVNode = vnode.type();
					warnedComponents.lazyPropTypes[vnode.type] = true;
					console.warn(m + 'Component wrapped in lazy() is ' + (lazyVNode.type.displayName || lazyVNode.type.name));
				}
				catch (promise) {
					console.warn(m + 'We will log the wrapped component\'s name once it is loaded.');
				}
			}
			checkPropTypes(vnode.type.propTypes, vnode.props, getDisplayName(vnode), serializeVNode(vnode));
		}

		if (oldBeforeDiff) oldBeforeDiff(vnode);
	};

	options._hook = (comp) => {
		if (!comp) {
			throw new Error('Hook can only be invoked from render methods.');
		}
	};

	const warn = (property, err) => ({
		get() {
			throw new Error(`getting vnode.${property} is deprecated, ${err}`);
		},
		set() {
			throw new Error(`setting vnode.${property} is not allowed, ${err}`);
		}
	});

	const deprecatedAttributes = {
		nodeName: warn('nodeName', 'use vnode.type'),
		attributes: warn('attributes', 'use vnode.props'),
		children: warn('children', 'use vnode.props.children')
	};

	options.vnode = (vnode) => {
		let source, self;
		if (vnode.props && vnode.props.__source) {
			source = vnode.props.__source;
			delete vnode.props.__source;
		}
		if (vnode.props && vnode.props.__self) {
			self = vnode.props.__self;
			delete vnode.props.__self;
		}
		vnode.__self = self;
		vnode.__source = source;
		Object.defineProperties(vnode, deprecatedAttributes);
		if (oldVnode) oldVnode(vnode);
	};

	options.diffed = (vnode) => {
		if (vnode == null) { return; }

		if (vnode._component && vnode._component.__hooks) {
			let hooks = vnode._component.__hooks;
			hooks._list.forEach(hook => {
				if (hook._callback && (!hook._args || !Array.isArray(hook._args))) {
					/* istanbul ignore next */
					console.warn(
						`In ${vnode.type.name || vnode.type} you are calling useMemo/useCallback without passing arguments.\n` +
						`This is a noop since it will not be able to memoize, it will execute it every render.`
					);
				}
			});
			if (hooks._pendingEffects.length > 0) {
				hooks._pendingEffects.forEach((effect) => {
					if ((!effect._args || !Array.isArray(effect._args)) && !warnedComponents.useEffect[vnode.type]) {
						warnedComponents.useEffect[vnode.type] = true;
						/* istanbul ignore next */
						console.warn('You should provide an array of arguments as the second argument to the "useEffect" hook.\n\n' +
							'Not doing so will invoke this effect on every render.\n\n' +
							'This effect can be found in the render of ' + (vnode.type.name || vnode.type) + '.');
					}
				});
			}
			if (hooks._pendingLayoutEffects.length > 0) {
				hooks._pendingLayoutEffects.forEach((layoutEffect) => {
					if ((!layoutEffect._args || !Array.isArray(layoutEffect._args)) && !warnedComponents.useLayoutEffect[vnode.type]) {
						warnedComponents.useLayoutEffect[vnode.type] = true;
						/* istanbul ignore next */
						console.warn('You should provide an array of arguments as the second argument to the "useLayoutEffect" hook.\n\n' +
							'Not doing so will invoke this effect on every render.\n\n' +
							'This effect can be found in the render of ' + (vnode.type.name || vnode.type) + '.');
					}
				});
			}
		}

		if (vnode._children != null) {
			const keys = [];
			for (let i = 0; i < vnode._children.length; i++) {
				const child = vnode._children[i];
				if (!child || child.key==null) continue;

				const key = child.key;
				if (keys.indexOf(key) !== -1) {
					console.error(
						'Following component has two or more children with the ' +
						`same key attribute: "${key}". This may cause glitches and misbehavior ` +
						'in rendering process. Component: \n\n' +
						serializeVNode(vnode)
					);

					// Break early to not spam the console
					break;
				}

				keys.push(key);
			}
		}

		if (oldDiffed) oldDiffed(vnode);
	};
}

/**
 * Serialize a vnode tree to a string
 * @param {import('./internal').VNode} vnode
 * @returns {string}
 */
export function serializeVNode(vnode) {
	let { props } = vnode;
	let name = getDisplayName(vnode);

	let attrs = '';
	if (props) {
		for (let prop in props) {
			if (props.hasOwnProperty(prop) && prop!=='children') {
				let value = props[prop];

				// If it is an object but doesn't have toString(), use Object.toString
				if (typeof value==='function') {
					value = `function ${value.displayName || value.name}() {}`;
				}

				value = Object(value) === value && !value.toString
					? Object.prototype.toString.call(value)
					: value + '';

				attrs += ` ${prop}=${JSON.stringify(value)}`;
			}
		}
	}

	let children = props.children;
	return `<${name}${attrs}${children && children.length
		? '>..</'+name+'>'
		: ' />'}`;
}
<commit_msg>fix: solve lint error<commit_after>import { checkPropTypes } from './check-props';
import { getDisplayName } from './devtools/custom';
import { options } from 'preact';
import { ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE } from './constants';

function getClosestDomNodeParent(parent) {
	if (!parent) return null;
	if (typeof parent.type === 'function') {
		return getClosestDomNodeParent(parent._parent);
	}
	return parent.type;
}

export function initDebug() {
	/* eslint-disable no-console */
	let oldBeforeDiff = options._diff;
	let oldDiffed = options.diffed;
	let oldVnode = options.vnode;
	const warnedComponents = { useEffect: {}, useLayoutEffect: {}, lazyPropTypes: {} };

	options._catchError = (error, vnode) => {
		let component = vnode && vnode._component;
		if (component && typeof error.then === 'function') {
			error = new Error('Missing Suspense. The throwing component was: ' + (component.displayName || component.name));
		}
	};

	options._root = (vnode, parentNode) => {
		if (!parentNode) {
			throw new Error('Undefined parent passed to render(), this is the second argument.\nCheck if the element is available in the DOM/has the correct id.');
		}
		let isValid;
		switch (parentNode.nodeType) {
			case ELEMENT_NODE:
			case DOCUMENT_FRAGMENT_NODE:
			case DOCUMENT_NODE: isValid = true; break;
			default: isValid = false;
		}
		if (!isValid) throw new Error(`
			Expected a valid HTML node as a second argument to render.
			Received ${parentNode} instead: render(<${vnode.type.name || vnode.type} />, ${parentNode});
		`);
	};

	options._diff = vnode => {
		if (vnode == null) { return; }

		let { type, _parent: parent } = vnode;
		let parentType = getClosestDomNodeParent(parent);

		if (type===undefined) {
			throw new Error('Undefined component passed to createElement()\n\n'+
			'You likely forgot to export your component or might have mixed up default and named imports'+
			serializeVNode(vnode));
		}
		else if (type!=null && typeof type==='object') {
			if (type._lastDomChild!==undefined && type._dom!==undefined) {
				let info = 'Did you accidentally pass a JSX literal as JSX twice?\n\n'+
				'  let My'+getDisplayName(type)+' = '+serializeVNode(type)+';\n'+
				'  let vnode = <My'+getDisplayName(type)+' />;\n\n'+
				'This usually happens when you export a JSX literal and not the component.';
				throw new Error('Invalid type passed to createElement(): '+type+'\n\n'+info+'\n');
			}

			throw new Error('Invalid type passed to createElement(): '+(Array.isArray(type) ? 'array' : type));
		}

		if ((type==='thead' || type==='tfoot' || type==='thead') && parentType!=='table') {
			console.error(
				'Improper nesting of table.' +
				'Your <thead/tbody/tfoot> should have a <table> parent.'
				+ serializeVNode(vnode)
			);
		}
		else if (type==='tr' && (parentType!=='thead' && parentType!=='tfoot' && parentType!=='tbody')) {
			console.error(
				'Improper nesting of table.' +
				'Your <tr> should have a <thead/tbody/tfoot> parent.'
				+ serializeVNode(vnode)
			);
		}
		else if (type==='td') {
			if (parentType!=='tr') {
				console.error(
					'Improper nesting of table.' +
					'Your <td> should have a <tr> parent.'
					+ serializeVNode(vnode)
				);
			}
			else if (parent._parent.type === 'thead') {
				console.error(
					'Improper nesting of table.' +
					'Your <thead> should use <th> instead of <td>.'
					+ serializeVNode(vnode)
				);
			}
		}
		else if (type==='th' && parentType!=='tr') {
			console.error(
				'Improper nesting of table.' +
				'Your <th> should have a <tr> parent with a <thead> parent.'
				+ serializeVNode(vnode)
			);
		}

		if (
			vnode.ref!==undefined &&
			typeof vnode.ref!=='function' &&
			typeof vnode.ref!=='object' &&
			!('$$typeof' in vnode)  // allow string refs when preact-compat is installed
		) {
			throw new Error(
				`Component's "ref" property should be a function, or an object created ` +
				`by createRef(), but got [${typeof vnode.ref}] instead\n` +
				serializeVNode(vnode)
			);
		}

		if (typeof vnode.type==='string') {
			for (const key in vnode.props) {
				if (key[0]==='o' && key[1]==='n' && typeof vnode.props[key]!=='function' && vnode.props[key]!=null) {
					throw new Error(
						`Component's "${key}" property should be a function, ` +
						`but got [${typeof vnode.props[key]}] instead\n` +
						serializeVNode(vnode)
					);
				}
			}
		}

		// Check prop-types if available
		if (typeof vnode.type==='function' && vnode.type.propTypes) {
			if (vnode.type.displayName === 'Lazy' && !warnedComponents.lazyPropTypes[vnode.type]) {
				const m = 'PropTypes are not supported on lazy(). Use propTypes on the wrapped component itself. ';
				try {
					const lazyVNode = vnode.type();
					warnedComponents.lazyPropTypes[vnode.type] = true;
					console.warn(m + 'Component wrapped in lazy() is ' + (lazyVNode.type.displayName || lazyVNode.type.name));
				}
				catch (promise) {
					console.warn(m + 'We will log the wrapped component\'s name once it is loaded.');
				}
			}
			checkPropTypes(vnode.type.propTypes, vnode.props, getDisplayName(vnode), serializeVNode(vnode));
		}

		if (oldBeforeDiff) oldBeforeDiff(vnode);
	};

	options._hook = (comp) => {
		if (!comp) {
			throw new Error('Hook can only be invoked from render methods.');
		}
	};

	const warn = (property, err) => ({
		get() {
			throw new Error(`getting vnode.${property} is deprecated, ${err}`);
		},
		set() {
			throw new Error(`setting vnode.${property} is not allowed, ${err}`);
		}
	});

	const deprecatedAttributes = {
		nodeName: warn('nodeName', 'use vnode.type'),
		attributes: warn('attributes', 'use vnode.props'),
		children: warn('children', 'use vnode.props.children')
	};

	options.vnode = (vnode) => {
		let source, self;
		if (vnode.props && vnode.props.__source) {
			source = vnode.props.__source;
			delete vnode.props.__source;
		}
		if (vnode.props && vnode.props.__self) {
			self = vnode.props.__self;
			delete vnode.props.__self;
		}
		vnode.__self = self;
		vnode.__source = source;
		Object.defineProperties(vnode, deprecatedAttributes);
		if (oldVnode) oldVnode(vnode);
	};

	options.diffed = (vnode) => {
		if (vnode == null) { return; }

		if (vnode._component && vnode._component.__hooks) {
			let hooks = vnode._component.__hooks;
			hooks._list.forEach(hook => {
				if (hook._callback && (!hook._args || !Array.isArray(hook._args))) {
					/* istanbul ignore next */
					console.warn(
						`In ${vnode.type.name || vnode.type} you are calling useMemo/useCallback without passing arguments.\n` +
						`This is a noop since it will not be able to memoize, it will execute it every render.`
					);
				}
			});
			if (hooks._pendingEffects.length > 0) {
				hooks._pendingEffects.forEach((effect) => {
					if ((!effect._args || !Array.isArray(effect._args)) && !warnedComponents.useEffect[vnode.type]) {
						warnedComponents.useEffect[vnode.type] = true;
						/* istanbul ignore next */
						console.warn('You should provide an array of arguments as the second argument to the "useEffect" hook.\n\n' +
							'Not doing so will invoke this effect on every render.\n\n' +
							'This effect can be found in the render of ' + (vnode.type.name || vnode.type) + '.');
					}
				});
			}
			if (hooks._pendingLayoutEffects.length > 0) {
				hooks._pendingLayoutEffects.forEach((layoutEffect) => {
					if ((!layoutEffect._args || !Array.isArray(layoutEffect._args)) && !warnedComponents.useLayoutEffect[vnode.type]) {
						warnedComponents.useLayoutEffect[vnode.type] = true;
						/* istanbul ignore next */
						console.warn('You should provide an array of arguments as the second argument to the "useLayoutEffect" hook.\n\n' +
							'Not doing so will invoke this effect on every render.\n\n' +
							'This effect can be found in the render of ' + (vnode.type.name || vnode.type) + '.');
					}
				});
			}
		}

		if (vnode._children != null) {
			const keys = [];
			for (let i = 0; i < vnode._children.length; i++) {
				const child = vnode._children[i];
				if (!child || child.key==null) continue;

				const key = child.key;
				if (keys.indexOf(key) !== -1) {
					console.error(
						'Following component has two or more children with the ' +
						`same key attribute: "${key}". This may cause glitches and misbehavior ` +
						'in rendering process. Component: \n\n' +
						serializeVNode(vnode)
					);

					// Break early to not spam the console
					break;
				}

				keys.push(key);
			}
		}

		if (oldDiffed) oldDiffed(vnode);
	};
}

/**
 * Serialize a vnode tree to a string
 * @param {import('./internal').VNode} vnode
 * @returns {string}
 */
export function serializeVNode(vnode) {
	let { props } = vnode;
	let name = getDisplayName(vnode);

	let attrs = '';
	if (props) {
		for (let prop in props) {
			if (props.hasOwnProperty(prop) && prop!=='children') {
				let value = props[prop];

				// If it is an object but doesn't have toString(), use Object.toString
				if (typeof value==='function') {
					value = `function ${value.displayName || value.name}() {}`;
				}

				value = Object(value) === value && !value.toString
					? Object.prototype.toString.call(value)
					: value + '';

				attrs += ` ${prop}=${JSON.stringify(value)}`;
			}
		}
	}

	let children = props.children;
	return `<${name}${attrs}${children && children.length
		? '>..</'+name+'>'
		: ' />'}`;
}
<|endoftext|>


<commit_before>
$(function(){

  window.mavutil = {};
  window.mavutil.heartbeat = {};
  /* Constants: */
  /* MAV_MODE_FLAG: bitfield for base_mode. */
  var MAV_MODE_FLAG_CUSTOM_MODE_ENABLED =  1;
  var MAV_MODE_FLAG_TEST_ENABLED =  2;
  var MAV_MODE_FLAG_AUTO_ENABLED =  4;
  var MAV_MODE_FLAG_GUIDED_ENABLED =  8;
  var MAV_MODE_FLAG_STABILIZE_ENABLED =  16;
  var MAV_MODE_FLAG_HIL_ENABLED =  32;
  var MAV_MODE_FLAG_MANUAL_INPUT_ENABLED =  64;
  var MAV_MODE_FLAG_SAFETY_ARMED =  128;

  var MAV_TYPE_FIXED_WING = 1;
  var MAV_TYPE_QUADROTOR = 2;

  /* Flight mode lookup tables: */
  var arduPlaneFlightModes = {
    0: 'MANUAL',
    1: 'CIRCLE',
    2: 'STABILIZE',
    5: 'FBWA',
    6: 'FBWB',
    7: 'FBWC',
    10: 'AUTO',
    11: 'RTL',
    12: 'LOITER',
    13: 'TAKEOFF',
    14: 'LAND',
    15: 'GUIDED',
    16: 'INITIALIZING'
  };

  var arduCopterFlightModes = {
    0: 'STABILIZE',
    1: 'ACRO',
    2: 'ALT_HOLD',
    3: 'AUTO',
    4: 'GUIDED',
    5: 'LOITER',
    6: 'RTL',
    7: 'CIRCLE',
    8: 'POSITION',
    9: 'LAND',
    10: 'OF_LOITER',
    11: 'APPROACH'
  };

  window.mavutil.heartbeat.modestring = function (msg) {
    var base_mode = msg.get('base_mode');
    var type = msg.get('type');
    var custom_mode = msg.get('custom_mode');

    if (base_mode === null || type === null || custom_mode === null) {
      return;
    }

    if (!base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
      return ('BaseMode('+ base_mode + ')');
    } else if (type == MAV_TYPE_QUADROTOR &&
               custom_mode in arduCopterFlightModes) {
      return arduCopterFlightModes[custom_mode];
    } else if (type == MAV_TYPE_FIXED_WING &&
               custom_mode in arduPlaneFlightModes) {
      return arduPlaneFlightModes[custom_mode];
    }
    return ('CustomMode(' + custom_mode + ')');
  };

  window.mavutil.heartbeat.armed = function (msg) {
    base_mode = msg.get('base_mode');
    if (base_mode == null) return null;
    if (base_mode & MAV_MODE_FLAG_SAFETY_ARMED) {
      return true;
    }
    return false;

  };

});
<commit_msg>mavutil: export flight mode arrays and mavtype detection function<commit_after>
$(function(){

  window.mavutil = {};
  window.mavutil.heartbeat = {};
  /* Constants: */
  /* MAV_MODE_FLAG: bitfield for base_mode. */
  var MAV_MODE_FLAG_CUSTOM_MODE_ENABLED =  1;
  var MAV_MODE_FLAG_TEST_ENABLED =  2;
  var MAV_MODE_FLAG_AUTO_ENABLED =  4;
  var MAV_MODE_FLAG_GUIDED_ENABLED =  8;
  var MAV_MODE_FLAG_STABILIZE_ENABLED =  16;
  var MAV_MODE_FLAG_HIL_ENABLED =  32;
  var MAV_MODE_FLAG_MANUAL_INPUT_ENABLED =  64;
  var MAV_MODE_FLAG_SAFETY_ARMED =  128;

  var MAV_TYPE_FIXED_WING = 1;
  var MAV_TYPE_QUADROTOR = 2;

  /* Flight mode lookup tables: */
  var arduPlaneFlightModes = {
    0: 'MANUAL',
    1: 'CIRCLE',
    2: 'STABILIZE',
    5: 'FBWA',
    6: 'FBWB',
    7: 'FBWC',
    10: 'AUTO',
    11: 'RTL',
    12: 'LOITER',
    13: 'TAKEOFF',
    14: 'LAND',
    15: 'GUIDED',
    16: 'INITIALIZING'
  };
  window.mavutil.arduPlaneFlightModes = arduPlaneFlightModes;

  var arduCopterFlightModes = {
    0: 'STABILIZE',
    1: 'ACRO',
    2: 'ALT_HOLD',
    3: 'AUTO',
    4: 'GUIDED',
    5: 'LOITER',
    6: 'RTL',
    7: 'CIRCLE',
    8: 'POSITION',
    9: 'LAND',
    10: 'OF_LOITER',
    11: 'APPROACH'
  };
  window.mavutil.arduCopterFlightModes = arduCopterFlightModes;

  window.mavutil.heartbeat.mavtype = function (msg) {
    var type = msg.get('type');
    if (type == MAV_TYPE_QUADROTOR) return "ArduCopter";
    if (type == MAV_TYPE_FIXED_WING) return "ArduPlane";
    return "unknown";
  }

  window.mavutil.heartbeat.modestring = function (msg) {
    var base_mode = msg.get('base_mode');
    var type = msg.get('type');
    var custom_mode = msg.get('custom_mode');

    if (base_mode === null || type === null || custom_mode === null) {
      return;
    }

    if (!base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
      return ('BaseMode('+ base_mode + ')');
    } else if (type == MAV_TYPE_QUADROTOR &&
               custom_mode in arduCopterFlightModes) {
      return arduCopterFlightModes[custom_mode];
    } else if (type == MAV_TYPE_FIXED_WING &&
               custom_mode in arduPlaneFlightModes) {
      return arduPlaneFlightModes[custom_mode];
    }
    return ('CustomMode(' + custom_mode + ')');
  };

  window.mavutil.heartbeat.armed = function (msg) {
    base_mode = msg.get('base_mode');
    if (base_mode == null) return null;
    if (base_mode & MAV_MODE_FLAG_SAFETY_ARMED) {
      return true;
    }
    return false;

  };

});
<|endoftext|>


<commit_before>/**
 * Connect Request event
 * @module peer/events/connect-request
 */
const uuid = require('uuid');
const NError = require('nerror');

/**
 * Connect Request event class
 */
class ConnectRequest {
    /**
     * Create service
     * @param {App} app                             The application
     * @param {object} config                       Configuration
     * @param {Logger} logger                       Logger service
     * @param {Crypter} crypter                     Crypter service
     */
    constructor(app, config, logger, crypter) {
        this._app = app;
        this._config = config;
        this._logger = logger;
        this._crypter = crypter;
    }

    /**
     * Service name is 'modules.peer.events.connectRequest'
     * @type {string}
     */
    static get provides() {
        return 'modules.peer.events.connectRequest';
    }

    /**
     * Dependencies as constructor arguments
     * @type {string[]}
     */
    static get requires() {
        return [ 'app', 'config', 'logger', 'crypter' ];
    }

    /**
     * Event handler
     * @param {string} sessionId                Session ID
     * @param {object} message                  The message
     */
    handle(sessionId, message) {
        let session = this.peer.sessions.get(sessionId);
        if (!session)
            return;

        if (session.name && session.name !== message.connectRequest.connectionName)
            return;

        let connection = this.peer.connections.get(message.connectRequest.connectionName);
        if (!connection)
            return;

        if (!session.name) {
            session.name = connection.name;
            connection.sessionIds.add(sessionId);
            let cryptSession = this._crypter.sessions.get(sessionId);
            if (cryptSession)
                cryptSession.connection = connection.name;
        }

        this._crypter.verify(
                sessionId,
                connection.tracker,
                message.connectRequest.identity,
                message.connectRequest.publicKey,
                message.connectRequest.signature,
                connection.fixed
            )
            .then(result => {
                session.verified = result.verified;

                if (session.verified) {
                    let cryptSession = this._crypter.sessions.get(sessionId);
                    cryptSession.peerKey = new Uint8Array(Buffer.from(message.connectRequest.publicKey, 'base64'));
                    cryptSession.peerName = result.name;
                    this._logger.info(
                        `Peer of ${message.connectRequest.connectionName} authenticated as ${result.name} (${session.socket.address().address}:${session.socket.address().port})`
                    );
                } else {
                    if (result.name && connection.fixed && connection.peers.indexOf(result.name) === -1) {
                        this._logger.info(
                            `Peer of ${message.connectRequest.connectionName} is not in the fixed list (${result.name}) and rejected (${session.socket.address().address}:${session.socket.address().port})`
                        );
                    } else {
                        this._logger.info(
                            `Peer of ${message.connectRequest.connectionName} is ${result.name ? 'not ' + result.name : 'unknown'} and rejected (${session.socket.address().address}:${session.socket.address().port})`
                        );
                    }
                }

                let response = this.peer.ConnectResponse.create({
                    response: session.verified ? this.peer.ConnectResponse.Result.ACCEPTED : this.peer.ConnectResponse.Result.REJECTED,
                });
                let reply = this.peer.OuterMessage.create({
                    type: this.peer.OuterMessage.Type.CONNECT_RESPONSE,
                    connectResponse: response,
                });
                let buffer = this.peer.OuterMessage.encode(reply).finish();

                this._logger.debug('connect-request', session.verified ? 'Sending ACCEPT' : 'Sending REJECT');
                this.peer.send(sessionId, buffer);

                if (session.verified) {
                    if (session.accepted && !session.established) {
                        session.established = true;
                        this.peer.emit('established', sessionId);
                    } else if (connection.server) {
                        this.peer.sendConnectRequest(sessionId);
                    }
                }
            })
            .catch(error => {
                this._logger.error(new NError(error, `ConnectRequest.handle()`));
            });
    }

    /**
     * Retrieve tracker server
     * @return {Tracker}
     */
    get tracker() {
        if (this._tracker)
            return this._tracker;
        this._tracker = this._app.get('servers').get('tracker');
        return this._tracker;
    }

    /**
     * Retrieve peer server
     * @return {Peer}
     */
    get peer() {
        if (this._peer)
            return this._peer;
        this._peer = this._app.get('servers').get('peer');
        return this._peer;
    }

    /**
     * Retrieve front server
     * @return {Front}
     */
    get front() {
        if (this._front)
            return this._front;
        this._front = this._app.get('servers').get('front');
        return this._front;
    }
}

module.exports = ConnectRequest;<commit_msg>Better log<commit_after>/**
 * Connect Request event
 * @module peer/events/connect-request
 */
const uuid = require('uuid');
const NError = require('nerror');

/**
 * Connect Request event class
 */
class ConnectRequest {
    /**
     * Create service
     * @param {App} app                             The application
     * @param {object} config                       Configuration
     * @param {Logger} logger                       Logger service
     * @param {Crypter} crypter                     Crypter service
     */
    constructor(app, config, logger, crypter) {
        this._app = app;
        this._config = config;
        this._logger = logger;
        this._crypter = crypter;
    }

    /**
     * Service name is 'modules.peer.events.connectRequest'
     * @type {string}
     */
    static get provides() {
        return 'modules.peer.events.connectRequest';
    }

    /**
     * Dependencies as constructor arguments
     * @type {string[]}
     */
    static get requires() {
        return [ 'app', 'config', 'logger', 'crypter' ];
    }

    /**
     * Event handler
     * @param {string} sessionId                Session ID
     * @param {object} message                  The message
     */
    handle(sessionId, message) {
        let session = this.peer.sessions.get(sessionId);
        if (!session)
            return;

        if (session.name && session.name !== message.connectRequest.connectionName)
            return;

        let connection = this.peer.connections.get(message.connectRequest.connectionName);
        if (!connection)
            return;

        if (!session.name) {
            session.name = connection.name;
            connection.sessionIds.add(sessionId);
            let cryptSession = this._crypter.sessions.get(sessionId);
            if (cryptSession)
                cryptSession.connection = connection.name;
        }

        this._crypter.verify(
                sessionId,
                connection.tracker,
                message.connectRequest.identity,
                message.connectRequest.publicKey,
                message.connectRequest.signature,
                connection.fixed
            )
            .then(result => {
                session.verified = result.verified;

                if (session.verified) {
                    let cryptSession = this._crypter.sessions.get(sessionId);
                    cryptSession.peerKey = new Uint8Array(Buffer.from(message.connectRequest.publicKey, 'base64'));
                    cryptSession.peerName = result.name;
                    this._logger.info(
                        `Peer ${result.name} of ${message.connectRequest.connectionName} passed identity check (${session.socket.address().address}:${session.socket.address().port})`
                    );
                } else {
                    if (result.name && connection.fixed && connection.peers.indexOf(result.name) === -1) {
                        this._logger.error(
                            `Peer ${result.name} of ${message.connectRequest.connectionName} is not in the fixed list and rejected (${session.socket.address().address}:${session.socket.address().port})`
                        );
                    } else {
                        this._logger.error(
                            `Peer ${result.name ? result.name : 'unknown'} of ${message.connectRequest.connectionName} failed identity check (${session.socket.address().address}:${session.socket.address().port})`
                        );
                    }
                }

                let response = this.peer.ConnectResponse.create({
                    response: session.verified ? this.peer.ConnectResponse.Result.ACCEPTED : this.peer.ConnectResponse.Result.REJECTED,
                });
                let reply = this.peer.OuterMessage.create({
                    type: this.peer.OuterMessage.Type.CONNECT_RESPONSE,
                    connectResponse: response,
                });
                let buffer = this.peer.OuterMessage.encode(reply).finish();

                this._logger.debug('connect-request', session.verified ? 'Sending ACCEPT' : 'Sending REJECT');
                this.peer.send(sessionId, buffer);

                if (session.verified) {
                    if (session.accepted && !session.established) {
                        session.established = true;
                        this.peer.emit('established', sessionId);
                    } else if (connection.server) {
                        this.peer.sendConnectRequest(sessionId);
                    }
                }
            })
            .catch(error => {
                this._logger.error(new NError(error, `ConnectRequest.handle()`));
            });
    }

    /**
     * Retrieve tracker server
     * @return {Tracker}
     */
    get tracker() {
        if (this._tracker)
            return this._tracker;
        this._tracker = this._app.get('servers').get('tracker');
        return this._tracker;
    }

    /**
     * Retrieve peer server
     * @return {Peer}
     */
    get peer() {
        if (this._peer)
            return this._peer;
        this._peer = this._app.get('servers').get('peer');
        return this._peer;
    }

    /**
     * Retrieve front server
     * @return {Front}
     */
    get front() {
        if (this._front)
            return this._front;
        this._front = this._app.get('servers').get('front');
        return this._front;
    }
}

module.exports = ConnectRequest;<|endoftext|>