<commit_before>(function() {
  'use strict';
  var relvis = window.relvis = window.relvis || {};

  relvis.textLayout = function textLayout(ctx, str, width) { //{{{1
    window.ctx = ctx;
    var spacing = ctx.measureText(' ').width;
    var words = str.split(' ');
    var lengths = words.map(function(word) {
      return ctx.measureText(word).width;
    });
    var lines = [];
    var line = [];
    var linePos = 0;
    for (var i = 0; i < words.length; ++i) {
      if (linePos > 0 && linePos + lengths[i] > width) {
        lines.push({
          str: line.join(' '),
          len: linePos
        });
        line = [];
        linePos = 0;
      }
      line.push(words[i]);
      linePos += lengths[i] + spacing;
    }
    lines.push({
      str: line.join(' '),
      len: linePos
    });
    return lines;
  };

  relvis.writeBox = function writeBox(ctx, str, x, y, w, h) { //{{{1
    var size = 60;
    var lines, i, maxLen;
    do {
      size = size * 0.9 | 0;
      ctx.font = size + 'px sans-serif';
      lines = relvis.textLayout(ctx, str, w);
      maxLen = 0;
      for (i = 0; i < lines.length; ++i) {
        maxLen = Math.max(maxLen, lines[i].len);
      }
    } while (size > 13 && (maxLen > w || lines.length * size > h));

    for (i = 0; i < lines.length; ++i) {
      if (size * (i + 1) < h) {
        ctx.fillText(lines[i].str, x, y + size * (i + 1));
      }
    }
  };

  relvis.drawGraph = function drawGraph(canvas, graph) { //{{{1
    var margin = 0.05;

    var ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'rgba(0,0,0,0.2)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    var visibleNodes = graph.nodes.filter(function(o) {
      return o.visible;
    });
    var boundaries = relvis.findBoundaries(visibleNodes, ['x', 'y']);

    visibleNodes.forEach(function(node) {
      var xy = boundaries.zeroOne(node);
      node.vx = (xy.x * (1 - 2 * margin) + margin) * canvas.width;
      node.vy = (xy.y * (1 - 2 * margin) + margin) * canvas.height;
    });

    relvis.nearestPoints(visibleNodes, 'vx', 'vy');

    var visibleEdges = graph.edges.filter(function(e) {
      return e.source.visible && e.target.visible;
    });

    visibleEdges.forEach(function(e) {
      relvis.drawEdge(ctx, e.source, e.target,
        e.source.vx, e.source.vy,
        e.target.vx, e.target.vy,
        window.devicePixelRatio || 1);
    });

    for (var i = 0; i < visibleNodes.length; ++i) {
      var node = visibleNodes[i];
      // size should be 1/2 distance to nearest (or if neares is smaller, a bit larger, which is why we make the size of the nearest node factor in)
      var size = node.nearestDist * 0.8 - 0.34 * node.nearestNode.nearestDist; // * Math.SQRT1_2;
      var w = size * 2;
      var x = node.vx - w / 2;
      var h = size * 2 / relvis.visualObjectRatio;
      var y = node.vy - h / 2;

      relvis.drawNode(ctx, node, x, y, w, h, window.devicePixelRatio || 1);
    }
  };
})();
<commit_msg>cached text metrics for better performance on firefox<commit_after>(function() {
  'use strict';
  var relvis = window.relvis = window.relvis || {};

  var measureCache = {};

  relvis.textLayout = function textLayout(ctx, str, width, size) { //{{{1
    window.ctx = ctx;
    function measure(str) {
      var t = size + ',' + str;
      return (measureCache[t] = (measureCache[t] || ctx.measureText(str).width));
    }
    var spacing = measure(' ');
    var words = str.split(' ');
    var lengths = words.map(measure);
    var lines = [];
    var line = [];
    var linePos = 0;
    for (var i = 0; i < words.length; ++i) {
      if (linePos > 0 && linePos + lengths[i] > width) {
        lines.push({
          str: line.join(' '),
          len: linePos
        });
        line = [];
        linePos = 0;
      }
      line.push(words[i]);
      linePos += lengths[i] + spacing;
    }
    lines.push({
      str: line.join(' '),
      len: linePos
    });
    return lines;
  };

  relvis.writeBox = function writeBox(ctx, str, x, y, w, h) { //{{{1
    var size = 60;
    var lines, i, maxLen;
    do {
      size = size * 0.9 | 0;
      ctx.font = size + 'px sans-serif';
      lines = relvis.textLayout(ctx, str, w, size);
      maxLen = 0;
      for (i = 0; i < lines.length; ++i) {
        maxLen = Math.max(maxLen, lines[i].len);
      }
    } while (size > 13 && (maxLen > w || lines.length * size > h));

    for (i = 0; i < lines.length; ++i) {
      if (size * (i + 1) < h) {
        ctx.fillText(lines[i].str, x, y + size * (i + 1));
      }
    }
  };

  relvis.drawGraph = function drawGraph(canvas, graph) { //{{{1
    var margin = 0.05;

    var ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'rgba(0,0,0,0.2)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    var visibleNodes = graph.nodes.filter(function(o) {
      return o.visible;
    });
    var boundaries = relvis.findBoundaries(visibleNodes, ['x', 'y']);

    visibleNodes.forEach(function(node) {
      var xy = boundaries.zeroOne(node);
      node.vx = (xy.x * (1 - 2 * margin) + margin) * canvas.width;
      node.vy = (xy.y * (1 - 2 * margin) + margin) * canvas.height;
    });

    relvis.nearestPoints(visibleNodes, 'vx', 'vy');

    var visibleEdges = graph.edges.filter(function(e) {
      return e.source.visible && e.target.visible;
    });

    visibleEdges.forEach(function(e) {
      relvis.drawEdge(ctx, e.source, e.target,
        e.source.vx, e.source.vy,
        e.target.vx, e.target.vy,
        window.devicePixelRatio || 1);
    });

    for (var i = 0; i < visibleNodes.length; ++i) {
      var node = visibleNodes[i];
      // size should be 1/2 distance to nearest (or if neares is smaller, a bit larger, which is why we make the size of the nearest node factor in)
      var size = node.nearestDist * 0.8 - 0.34 * node.nearestNode.nearestDist; // * Math.SQRT1_2;
      var w = size * 2;
      var x = node.vx - w / 2;
      var h = size * 2 / relvis.visualObjectRatio;
      var y = node.vy - h / 2;

      relvis.drawNode(ctx, node, x, y, w, h, window.devicePixelRatio || 1);
    }
  };
})();
<|endoftext|>


<commit_before>define([
	'goo/statemachine/actions/Action',
	'goo/math/Vector3'
],
/** @lends */
function(
	Action,
	Vector3
) {
	"use strict";

	function TweenMoveAction(/*id, settings*/) {
		Action.apply(this, arguments);
	}

	TweenMoveAction.prototype = Object.create(Action.prototype);
	TweenMoveAction.prototype.constructor = TweenMoveAction;

	TweenMoveAction.external = {
		name: 'Tween Move',
		description: 'Smoothly transitions between 2 locations',
		canTransition: true,
		parameters: [{
			name: 'Translation',
			key: 'to',
			type: 'position',
			description: 'Move',
			'default': [0, 0, 0]
		}, {
			name: 'Relative',
			key: 'relative',
			type: 'boolean',
			description: 'If true add, otherwise set',
			'default': true
		}, {
			name: 'Time',
			key: 'time',
			type: 'number',
			description: 'Time it takes for this movement to complete',
			'default': 1000
		}, {
			name: 'Easing 1',
			key: 'easing1',
			type: 'dropdown',
			description: 'Easing 1',
			'default': 'Linear',
			options: ['Linear', 'Quadratic', 'Exponential', 'Circular', 'Elastic', 'Back', 'Bounce']
		}, {
			name: 'Easing 2',
			key: 'easing2',
			type: 'dropdown',
			description: 'Easing 2',
			'default': 'In',
			options: ['In', 'Out', 'InOut']
		}],
		transitions: [{
			key: 'complete',
			name: 'On Completion',
			description: 'Event fired when the movement completes'
		}]
	};

	TweenMoveAction.prototype.configure = function(settings) {
		this.to = settings.to;
		this.relative = settings.relative;
		this.time = settings.time;
		if (settings.easing1 === 'Linear') {
			this.easing = window.TWEEN.Easing.Linear.None;
		} else {
			this.easing = window.TWEEN.Easing[settings.easing1][settings.easing2];
		}
		this.eventToEmit = { channel: settings.transitions.complete };
	};

	TweenMoveAction.prototype._setup = function() {
		this.tween = new window.TWEEN.Tween();
	};

	TweenMoveAction.prototype._run = function(fsm) {
		var entity = fsm.getOwnerEntity();
		var transformComponent = entity.transformComponent;
		var translation = transformComponent.transform.translation;
		var initialTranslation = new Vector3().copy(translation);

		var fakeFrom = { x: initialTranslation.x, y: initialTranslation.y, z: initialTranslation.z };
		var fakeTo;

		if (this.relative) {
			var to = Vector3.add(initialTranslation, this.to);
			fakeTo = { x: to.x, y: to.y, z: to.z };

			this.tween.from(fakeFrom).to(fakeTo, +this.time).easing(this.easing).onUpdate(function() {
				translation.setd(this.x, this.y, this.z);
				transformComponent.setUpdated();
			}).onComplete(function() {
				fsm.send(this.eventToEmit.channel);
			}.bind(this)).start();
		} else {
			fakeTo = { x: this.to[0], y: this.to[1], z: this.to[2] };

			this.tween.from(fakeFrom).to(fakeTo, +this.time).easing(this.easing).onUpdate(function() {
				translation.setd(this.x, this.y, this.z);
				transformComponent.setUpdated();
			}).onComplete(function() {
				fsm.send(this.eventToEmit.channel);
			}.bind(this)).start();
		}
	};

	return TweenMoveAction;
});<commit_msg>#451 MoveTween actions are not composable<commit_after>define([
	'goo/statemachine/actions/Action',
	'goo/math/Vector3'
],
/** @lends */
function(
	Action,
	Vector3
) {
	"use strict";

	function TweenMoveAction(/*id, settings*/) {
		Action.apply(this, arguments);
	}

	TweenMoveAction.prototype = Object.create(Action.prototype);
	TweenMoveAction.prototype.constructor = TweenMoveAction;

	TweenMoveAction.external = {
		name: 'Tween Move',
		description: 'Smoothly transitions between 2 locations',
		canTransition: true,
		parameters: [{
			name: 'Translation',
			key: 'to',
			type: 'position',
			description: 'Move',
			'default': [0, 0, 0]
		}, {
			name: 'Relative',
			key: 'relative',
			type: 'boolean',
			description: 'If true add, otherwise set',
			'default': true
		}, {
			name: 'Time',
			key: 'time',
			type: 'number',
			description: 'Time it takes for this movement to complete',
			'default': 1000
		}, {
			name: 'Easing 1',
			key: 'easing1',
			type: 'dropdown',
			description: 'Easing 1',
			'default': 'Linear',
			options: ['Linear', 'Quadratic', 'Exponential', 'Circular', 'Elastic', 'Back', 'Bounce']
		}, {
			name: 'Easing 2',
			key: 'easing2',
			type: 'dropdown',
			description: 'Easing 2',
			'default': 'In',
			options: ['In', 'Out', 'InOut']
		}],
		transitions: [{
			key: 'complete',
			name: 'On Completion',
			description: 'Event fired when the movement completes'
		}]
	};

	TweenMoveAction.prototype.configure = function(settings) {
		this.to = settings.to;
		this.relative = settings.relative;
		this.time = settings.time;
		if (settings.easing1 === 'Linear') {
			this.easing = window.TWEEN.Easing.Linear.None;
		} else {
			this.easing = window.TWEEN.Easing[settings.easing1][settings.easing2];
		}
		this.eventToEmit = { channel: settings.transitions.complete };
	};

	TweenMoveAction.prototype._setup = function() {
		this.tween = new window.TWEEN.Tween();
	};

	TweenMoveAction.prototype._run = function(fsm) {
		var entity = fsm.getOwnerEntity();
		var transformComponent = entity.transformComponent;
		var translation = transformComponent.transform.translation;
		var initialTranslation = new Vector3().copy(translation);

		var fakeFrom = { x: initialTranslation.x, y: initialTranslation.y, z: initialTranslation.z };
		var fakeTo;

		var old = { x: fakeFrom.x, y: fakeFrom.y, z: fakeFrom.z };

		if (this.relative) {
			var to = Vector3.add(initialTranslation, this.to);
			fakeTo = { x: to.x, y: to.y, z: to.z };

			this.tween.from(fakeFrom).to(fakeTo, +this.time).easing(this.easing).onUpdate(function() {
				translation.data[0] += this.x - old.x;
				translation.data[1] += this.y - old.y;
				translation.data[2] += this.z - old.z;

				old.x = this.x;
				old.y = this.y;
				old.z = this.z;

				transformComponent.setUpdated();
			}).onComplete(function() {
				fsm.send(this.eventToEmit.channel);
			}.bind(this)).start();
		} else {
			fakeTo = { x: this.to[0], y: this.to[1], z: this.to[2] };

			this.tween.from(fakeFrom).to(fakeTo, +this.time).easing(this.easing).onUpdate(function() {
				translation.data[0] += this.x - old.x;
				translation.data[1] += this.y - old.y;
				translation.data[2] += this.z - old.z;

				old.x = this.x;
				old.y = this.y;
				old.z = this.z;

				transformComponent.setUpdated();
			}).onComplete(function() {
				fsm.send(this.eventToEmit.channel);
			}.bind(this)).start();
		}
	};

	return TweenMoveAction;
});<|endoftext|>


<commit_before>'use strict';

Array.prototype.unique = function() {
  var newArray = [];
  for (var i = 0, l = this.length; i < l; i++) {
    if (newArray.indexOf(this[i]) === -1 && this[i] !== '') {
      newArray.push(this[i]);
    }
  }
  return newArray;
};

Array.prototype.intersect = function(array) {
  return this.filter((x) => array.indexOf(x) != -1);
};

var Index = class {

  readFile(path) {
    var promise = $.ajax({
      dataType: 'json',
      url: path,
    });
    return promise;
  }

  transformDocuments(original) {
    return original.map((itm) => itm.text.toLowerCase().replace(/[^a-zA-Z\s]/g, '').split(' '));
  }

  getTokens(transformedDocuments) {
    return transformedDocuments.reduce((prev, cur) => prev.concat(cur)).unique();
  }

  createIndex(documents) {
    var index = {};
    var myClass = this;
    return new Promise(function(resolve) {
      myClass.readFile(documents).then(function(readDocument) {
        var transformedDocuments = myClass.transformDocuments(readDocument);
        var tokens = myClass.getTokens(transformedDocuments);

        tokens.forEach(function(curToken) {
          index[curToken] = [];
          transformedDocuments.forEach(function(curDocument, documentIndex) {
            if (curDocument.indexOf(curToken) != -1) {
              index[curToken].push(documentIndex);
            }
          });
        });

        myClass.index = index;
        resolve(true);
      });
    });
  }

  searchIndex() {
    var result = [];
    var pos = 0;
    for (var itm of arguments) {
      if (Object.keys(this.index).indexOf(itm) === -1) {
        return [];
      }
      if (pos === 0) {
        result = result.concat(this.index[itm]);
        pos = 1;
      } else {
        result = result.intersect(this.index[itm]);
      }
    }
    return result;
  }

  getIndex() {
    return this.index;
  }
};
<commit_msg>refactored code<commit_after>'use strict';

Array.prototype.unique = function() {
  var newArray = [];
  for (var i = 0, l = this.length; i < l; i++) {
    if (newArray.indexOf(this[i]) === -1 && this[i] !== '') {
      newArray.push(this[i]);
    }
  }
  return newArray;
};

Array.prototype.intersect = function(array) {
  return this.filter((x) => array.indexOf(x) != -1);
};

var Index = class {

  readFile(path) {
    var promise = $.ajax({
      dataType: 'json',
      url: path,
    });
    return promise;
  }

  transformDocuments(original) {
    return original.map((itm) => itm.text.toLowerCase().replace(/[^a-zA-Z\s]/g, '').split(' '));
  }

  getTokens(transformedDocuments) {
    return transformedDocuments.reduce((prev, cur) => prev.concat(cur)).unique();
  }

  createIndex(documents) {
    var index = {};
    var myClass = this;
    return new Promise(function(resolve) {
      myClass.readFile(documents).then(function(readDocument) {
        var transformedDocuments = myClass.transformDocuments(readDocument);
        var tokens = myClass.getTokens(transformedDocuments);

        tokens.forEach(function(curToken) {
          index[curToken] = [];
          transformedDocuments.forEach(function(curDocument, documentIndex) {
            if (curDocument.indexOf(curToken) !== -1) {
              index[curToken].push(documentIndex);
            }
          });
        });

        myClass.index = index;
        resolve(true);
      });
    });
  }

  searchIndex() {
    var result = [];
    var pos = 0;
    for (var itm of arguments) {
      if (Object.keys(this.index).indexOf(itm) === -1) {
        return [];
      }
      if (pos === 0) {
        result = result.concat(this.index[itm]);
        pos = 1;
      } else {
        result = result.intersect(this.index[itm]);
      }
    }
    return result;
  }

  getIndex() {
    return this.index;
  }
};
<|endoftext|>


<commit_before>// 언어팩 선언.
$.lang = {};
$.lang.en = {
  img_manager_3: '../images/m-3@3x.png',
  img_manager_4: '../images/m-4@3x.png',
  img_manager_5: '../images/m-5@3x.png',
  locale: 'English',
  lang_item_1: '中文简体',
  lang_item_2: '中文繁体',
  lang_item_3: '한국어',
  txt_support: 'Support',
  txt_login: 'Login',
  title_apply: 'Be in control',
  btn_apply: 'APPLY NOW',
  txt_ems1: 'Easishare Management System',
  txt_ems2: 'Integrated fleet management platform',
  txt_ems_customer: 'CUSTOMER',
  txt_ems_driver: 'DRIVER',
  txt_ems_manager: 'MANAGER',
  txt_serve: 'Serve',
  txt_order: 'Order',
  txt_dispatch: 'Dispatch',
  title_ems_service: 'EMS Service',
  txt_customer_title: 'Customer Tool & APP',
  txt_customer_content: 'Create your customer\'s account to serve their order inputs.',
  txt_manager_title: 'Manager Tool',
  txt_manager_content: 'Manage booking. scheduling. dispatch and reservations all in one.',
  txt_driver_title: 'Driver APP',
  txt_driver_content: 'Dispatch rides and track ride progress real time.',
  title_benefits: 'Benefits',
  txt_survive_title: 'Survive!',
  txt_survive_content: 'Get more business with same fleet size by exchanging orders with other suppliers',
  txt_moreorder_title: 'More Order!',
  txt_moreorder_content: 'Get more order from other booking apps and OTAs connected to EMS',
  txt_ownit_title: 'Own it!',
  txt_ownit_content: 'Get manager tool, customer and driver mobile application with your brand on it',
  txt_win_title: 'Win!',
  txt_win_content: 'Going into bidding? Take secure cloud-based EMS with you to win',
  title_social_proof: 'Social Proof',
  txt_andashun: 'Andashun',
  txt_andashun_content: '“It’s easy and boost work efficiency. We no longer have to make multiple phone calls or search through documents to find an available driver.”',
  txt_rich: 'Rich Pacific International',
  txt_rich_content: '“We love how we can track where the drivers are to make sure they are in time for pickup. With this tool, we can provide better service.”',
  txt_manager: 'Manager',
  txt_apply_bottom_content: 'Eliminate trivial tasks with EMS to focus on things that matters most',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: 'Terms & Policy',
  txt_register_title: 'Apply Easishare Management System',
  txt_register_title_desc: 'Below are the basic information we need to get you started.
Our sales team will contract you for further guidance as soon as possible.',
  register_confirm_btn: 'Confirm',
  register_succeed: 'Thank you! We will be in touch shortly.'
};

$.lang.zh_rCN = {
  img_manager_3: '../images/m-3-tra@3x.png',
  img_manager_4: '../images/m-4-tra@3x.png',
  img_manager_5: '../images/m-5-tra@3x.png',
  locale: '中文简体',
  lang_item_1: '中文繁体',
  lang_item_2: 'English',
  lang_item_3: '한국어',
  txt_support: '支持',
  txt_login: '登录',
  title_apply: '连接你我',
  btn_apply: '立即申请',
  txt_ems1: '易智行车辆管理系统',
  txt_ems2: '为您整合业务资源',
  txt_ems_customer: '乘客',
  txt_ems_driver: '司机',
  txt_ems_manager: '调度',
  txt_serve: '服务',
  txt_order: '订单',
  txt_dispatch: '安排',
  title_ems_service: '易智行解决方案',
  txt_customer_title: '客户预订工具(含网页与app)',
  txt_customer_content: '为您的客户创建账户，客户下单后，您可以接收到订单。',
  txt_manager_title: '调度工具',
  txt_manager_content: '提供全流程一站式的服务，可为客户下单、行程安排、司机车辆调度等。',
  txt_driver_title: '司机app',
  txt_driver_content: '给司机安排行程并实时监控行程进度。',
  title_benefits: '优势与收益',
  txt_survive_title: '业务拓展！',
  txt_survive_content: '在同样规模的车辆下，通过与同行换单，获取更多的业务。',
  txt_moreorder_title: '更多订单！',
  txt_moreorder_content: '易智行接入了大量订车平台与在线旅行社，您可获得更多订单。',
  txt_ownit_title: '自有品牌',
  txt_ownit_content: '调度工具、客户端、司机端，将标识您提供的自有品牌。',
  txt_win_title: '商业机遇',
  txt_win_content: '需要投标？使用云端安全加密技术的易智行助您在投标中脱颖而出！',
  title_social_proof: '客户评价',
  txt_andashun: '深圳市安达顺汽车服务有限公司',
  txt_andashun_content: '“易智行系统使用方便，并提高了工作效率。我们不需要打多次电话或者查看安排表来确认是否有可安排的司机。”',
  txt_rich: '富邦国际发展有限公司',
  txt_rich_content: '“我们可以实时监控司机的位置，以确保司机准时接客。我们很喜欢这个实用的功能。通过易智行，我们能够提供更优质的服务。”',
  txt_manager: '调度',
  txt_apply_bottom_content: '通过易智行车辆管理系统，消除繁琐的工作流程，集中资源到最重要的业务上。',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: '政策条款',
  txt_register_title: 'EMS易智行车辆管理系统',
  txt_register_title_desc: '如需注册易智行车辆管理系统，请如实填写以下信息，谢谢！',
  register_confirm_btn: '提交',
  register_succeed: 'Thank you! We will be in touch shortly.'
};

$.lang.zh_rTW = {
  locale: '中文繁体',
  lang_item_1: '中文简体',
  lang_item_2: 'English',
  lang_item_3: '한국어',
  txt_support: '支持',
  txt_login: '登錄',
  title_apply: '連接你我',
  btn_apply: '立即申請',
  txt_ems1: '易智行車輛管理系統',
  txt_ems2: '為您整合業務資源',
  txt_ems_customer: '乘客',
  txt_ems_driver: '司機',
  txt_ems_manager: '調度',
  txt_serve: '服務',
  txt_order: '訂單',
  txt_dispatch: '安排',
  title_ems_service: '易智行解決方案',
  txt_customer_title: '客戶預訂工具（含網頁與app）',
  txt_customer_content: '為您的客戶創建賬戶，客戶下單後，您可以接收到訂單。',
  txt_manager_title: '調度工具',
  txt_manager_content: '提供全流程一站式的服務，可為客戶下單、行程安排、司機車輛調度等。',
  txt_driver_title: '司機app',
  txt_driver_content: '給司機安排行程並實時監控行程進度。',
  title_benefits: '優勢與收益',
  txt_survive_title: '業務拓展！',
  txt_survive_content: 'Get more business with same fleet size by exchanging orders with other suppliers',
  txt_moreorder_title: 'More Order!',
  txt_moreorder_content: 'Get more order from other booking apps and OTAs connected to EMS',
  txt_ownit_title: 'Own it!',
  txt_ownit_content: 'Get manager tool, customer and driver mobile application with your brand on it',
  txt_win_title: 'Win!',
  txt_win_content: 'Going into bidding? Take secure cloud-based EMS with you to win',
  title_social_proof: 'Social Proof',
  txt_andashun: 'Andashun',
  txt_andashun_content: '“It’s easy and boost work efficiency. We no longer have to make multiple phone calls or search through documents to find an available driver.”',
  txt_rich: 'Rich Pacific International',
  txt_rich_content: '“We love how we can track where the drivers are to make sure they are in time for pickup. With this tool, we can provide better service.”',
  txt_manager: 'Manager',
  txt_apply_bottom_content: 'Eliminate trivial tasks with EMS to focus on things that matters most',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: 'Terms & Policy',
  register_confirm_btn: 'Confirm',
  register_succeed: 'Thank you! We will be in touch shortly.'
};

$.lang.ko = {};

$.langtype = {};
$.langtype.en = {
  item1: 'zh_rCN',
  item2: 'zh_rTW',
  item3: 'ko'
};

$.langtype.zh_rCN = {
  item1: 'zh_rTW',
  item2: 'en',
  item3: 'ko'
};

$.langtype.zh_rTW = {
  item1: 'zh_rCN',
  item2: 'en',
  item3: 'ko'
};

$.langtype.ko = {
  item1: 'en',
  item2: 'zh_rCN',
  item3: 'zh_rTW'
};
<commit_msg>translations refactoring<commit_after>// 언어팩 선언.
$.lang = {};
$.lang.en = {
  img_manager_3: '../images/m-3@3x.png',
  img_manager_4: '../images/m-4@3x.png',
  img_manager_5: '../images/m-5@3x.png',
  locale: 'English',
  lang_item_1: '中文简体',
  lang_item_2: '中文繁体',
  lang_item_3: '한국어',
  txt_support: 'Support',
  txt_login: 'Login',
  title_apply: 'Be in control',
  btn_apply: 'APPLY NOW',
  txt_ems1: 'Easishare Management System',
  txt_ems2: 'Integrated fleet management platform',
  txt_ems_customer: 'CUSTOMER',
  txt_ems_driver: 'DRIVER',
  txt_ems_manager: 'MANAGER',
  txt_serve: 'Serve',
  txt_order: 'Order',
  txt_dispatch: 'Dispatch',
  title_ems_service: 'EMS Service',
  txt_customer_title: 'Customer Tool & APP',
  txt_customer_content: 'Create your customer\'s account to serve their order inputs.',
  txt_manager_title: 'Manager Tool',
  txt_manager_content: 'Manage booking. scheduling. dispatch and reservations all in one.',
  txt_driver_title: 'Driver APP',
  txt_driver_content: 'Dispatch rides and track ride progress real time.',
  title_benefits: 'Benefits',
  txt_survive_title: 'Survive!',
  txt_survive_content: 'Get more business with same fleet size by exchanging orders with other suppliers',
  txt_moreorder_title: 'More Order!',
  txt_moreorder_content: 'Get more order from other booking apps and OTAs connected to EMS',
  txt_ownit_title: 'Own it!',
  txt_ownit_content: 'Get manager tool, customer and driver mobile application with your brand on it',
  txt_win_title: 'Win!',
  txt_win_content: 'Going into bidding? Take secure cloud-based EMS with you to win',
  title_social_proof: 'Social Proof',
  txt_andashun: 'Andashun',
  txt_andashun_content: '“It’s easy and boost work efficiency. We no longer have to make multiple phone calls or search through documents to find an available driver.”',
  txt_rich: 'Rich Pacific International',
  txt_rich_content: '“We love how we can track where the drivers are to make sure they are in time for pickup. With this tool, we can provide better service.”',
  txt_manager: 'Manager',
  txt_apply_bottom_content: 'Eliminate trivial tasks with EMS to focus on things that matters most',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: 'Terms & Policy',
  txt_register_title: 'Apply Easishare Management System',
  txt_register_title_desc: 'Below are the basic information we need to get you started.
Our sales team will contract you for further guidance as soon as possible.',
  register_confirm_btn: 'Confirm',
  register_succeed: 'Thank you! We will be in touch shortly.',
};

$.lang.zh_rCN = {
  img_manager_3: '../images/m-3-tra@3x.png',
  img_manager_4: '../images/m-4-tra@3x.png',
  img_manager_5: '../images/m-5-tra@3x.png',
  locale: '中文简体',
  lang_item_1: '中文繁体',
  lang_item_2: 'English',
  lang_item_3: '한국어',
  txt_support: '支持',
  txt_login: '登录',
  title_apply: '连接你我',
  btn_apply: '立即申请',
  txt_ems1: '易智行车辆管理系统',
  txt_ems2: '为您整合业务资源',
  txt_ems_customer: '乘客',
  txt_ems_driver: '司机',
  txt_ems_manager: '调度',
  txt_serve: '服务',
  txt_order: '订单',
  txt_dispatch: '安排',
  title_ems_service: '易智行解决方案',
  txt_customer_title: '客户预订工具(含网页与app)',
  txt_customer_content: '为您的客户创建账户，客户下单后，您可以接收到订单。',
  txt_manager_title: '调度工具',
  txt_manager_content: '提供全流程一站式的服务，可为客户下单、行程安排、司机车辆调度等。',
  txt_driver_title: '司机app',
  txt_driver_content: '给司机安排行程并实时监控行程进度。',
  title_benefits: '优势与收益',
  txt_survive_title: '业务拓展！',
  txt_survive_content: '在同样规模的车辆下，通过与同行换单，获取更多的业务。',
  txt_moreorder_title: '更多订单！',
  txt_moreorder_content: '易智行接入了大量订车平台与在线旅行社，您可获得更多订单。',
  txt_ownit_title: '自有品牌',
  txt_ownit_content: '调度工具、客户端、司机端，将标识您提供的自有品牌。',
  txt_win_title: '商业机遇',
  txt_win_content: '需要投标？使用云端安全加密技术的易智行助您在投标中脱颖而出！',
  title_social_proof: '客户评价',
  txt_andashun: '深圳市安达顺汽车服务有限公司',
  txt_andashun_content: '“易智行系统使用方便，并提高了工作效率。我们不需要打多次电话或者查看安排表来确认是否有可安排的司机。”',
  txt_rich: '富邦国际发展有限公司',
  txt_rich_content: '“我们可以实时监控司机的位置，以确保司机准时接客。我们很喜欢这个实用的功能。通过易智行，我们能够提供更优质的服务。”',
  txt_manager: '调度',
  txt_apply_bottom_content: '通过易智行车辆管理系统，消除繁琐的工作流程，集中资源到最重要的业务上。',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: '政策条款',
  txt_register_title: 'EMS易智行车辆管理系统',
  txt_register_title_desc: '如需注册易智行车辆管理系统，请如实填写以下信息，谢谢！',
  register_confirm_btn: '提交',
  register_succeed: 'Thank you! We will be in touch shortly.',
};

$.lang.zh_rTW = {
  locale: '中文繁体',
  lang_item_1: '中文简体',
  lang_item_2: 'English',
  lang_item_3: '한국어',
  txt_support: '支持',
  txt_login: '登錄',
  title_apply: '連接你我',
  btn_apply: '立即申請',
  txt_ems1: '易智行車輛管理系統',
  txt_ems2: '為您整合業務資源',
  txt_ems_customer: '乘客',
  txt_ems_driver: '司機',
  txt_ems_manager: '調度',
  txt_serve: '服務',
  txt_order: '訂單',
  txt_dispatch: '安排',
  title_ems_service: '易智行解決方案',
  txt_customer_title: '客戶預訂工具（含網頁與app）',
  txt_customer_content: '為您的客戶創建賬戶，客戶下單後，您可以接收到訂單。',
  txt_manager_title: '調度工具',
  txt_manager_content: '提供全流程一站式的服務，可為客戶下單、行程安排、司機車輛調度等。',
  txt_driver_title: '司機app',
  txt_driver_content: '給司機安排行程並實時監控行程進度。',
  title_benefits: '優勢與收益',
  txt_survive_title: '業務拓展！',
  txt_survive_content: 'Get more business with same fleet size by exchanging orders with other suppliers',
  txt_moreorder_title: 'More Order!',
  txt_moreorder_content: 'Get more order from other booking apps and OTAs connected to EMS',
  txt_ownit_title: 'Own it!',
  txt_ownit_content: 'Get manager tool, customer and driver mobile application with your brand on it',
  txt_win_title: 'Win!',
  txt_win_content: 'Going into bidding? Take secure cloud-based EMS with you to win',
  title_social_proof: 'Social Proof',
  txt_andashun: 'Andashun',
  txt_andashun_content: '“It’s easy and boost work efficiency. We no longer have to make multiple phone calls or search through documents to find an available driver.”',
  txt_rich: 'Rich Pacific International',
  txt_rich_content: '“We love how we can track where the drivers are to make sure they are in time for pickup. With this tool, we can provide better service.”',
  txt_manager: 'Manager',
  txt_apply_bottom_content: 'Eliminate trivial tasks with EMS to focus on things that matters most',
  txt_icp: '粤ICP备17020336号粤公网安备 44030402000541号
© 2017 深圳易智顺顺科技有限公司 Easi6 Limited. All Rights Reserved.',
  txt_terms_policy: 'Terms & Policy',
  register_confirm_btn: 'Confirm',
  register_succeed: 'Thank you! We will be in touch shortly.',
};

$.lang.ko = {};

$.langtype = {};
$.langtype.en = {
  item1: 'zh_rCN',
  item2: 'zh_rTW',
  item3: 'ko',
};

$.langtype.zh_rCN = {
  item1: 'zh_rTW',
  item2: 'en',
  item3: 'ko',
};

$.langtype.zh_rTW = {
  item1: 'zh_rCN',
  item2: 'en',
  item3: 'ko',
};

$.langtype.ko = {
  item1: 'en',
  item2: 'zh_rCN',
  item3: 'zh_rTW',
};
<|endoftext|>


<commit_before>/**
 * Utility-class with several static functions to simplify validation, merging and other standard operations on
 * javascript-Objects.
 */
export default class ObjectManager {
    /**
     * Checks that given object is not null and not undefined. Also checks the same inwards in provided nested keys
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": ""}}, false, true, "foo", "bar");
     *  // check is now false. key "foo" is found, key "bar" is found, but "bar" is emptyString, and params specify to check for them
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": {}}}, true, false, "foo", "bar");
     *  // check is now false. key "foo" is found, key "bar" is found, but "bar" is {}, and params specify to check for emptyObject.
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": {}}}, false, false, "foo", "bar");
     *  // check is now true. key "foo" is found, key "bar" is found, so no requested values are null or undefined.
     *
     *  NOTE: Other functions in this file lets you ignore the boolean params - so just use them :)
     *
     * @param givenObject   The object to validate
     * @param emptyObject   if true - keys mapped to empty object {} will also give false
     * @param emptyString   if true - keys mapped to empty string "" will also give false
     * @param args          nested keys to look for, so to validate myObject.foo.bar call this._hasOwnValue(myObject, false, false, "foo". "bar")
     * @returns {boolean}   true if validation passes, false if not.
     */
    static _hasOwnValue(givenObject, emptyObject, emptyString, ...args) {
        function checkValue(value) {
            return (value != undefined && value != null && (!emptyObject || value != {}) && (!emptyString || value != ""));
        }

        if (!checkValue(givenObject)) {
            return false;
        }

        for (let key of args) {
            if (!(key in givenObject) || !checkValue(givenObject[key])) {
                return false;
            }
            givenObject = givenObject[key];
        }

        return true;
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty string "".
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined or ""
     */
    static validateAllowEmptyObject(givenObject, ...args) {
        return this._hasOwnValue(givenObject, false, true, ...args);
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty object {}.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined or {}
     */
    static validateAllowEmptyString(givenObject, ...args) {
        return this._hasOwnValue(givenObject, true, false, ...args);
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty string "" or empty object {}.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined, {} or ""
     */
    static validate(givenObject, ...args) {
        return this._hasOwnValue(givenObject, true, true, ...args);
    }

    /**
     * Validate that an object and nested keys are not null or undefined.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null or undefined.
     */
    static validateAllowEmptyStringAndEmptyObject(givenObject, ...args) {
        return this._hasOwnValue(givenObject, false, false, ...args);
    }

    /**
     * uses {@link validate} to lookup given args in given objectToBeValidated.
     * This ensures the lookup is not null, undefined, empty object, or empty string.
     * If this test fails, given fallbackValue is returned.
     *
     * @example
     *  // to validate myObject.foo.bar, and get "helloworld" back as default if it is empty:
     *  validateOrFallback("helloworld", myObject, "foo", "bar")
     *
     * @param fallbackValue         what to return if empty
     * @param objectToBeValidated   object to do lookup in
     * @param args                  indices used for lookup in object
     * @returns {*}                 lookup in objectToBeValidated if validation succeeded, fallbackValue if not.
     */
    static validateOrFallback(fallbackValue, objectToBeValidated, ...args) {
        if (!this.validate(objectToBeValidated, ...args)) {
            return fallbackValue;
        }
        for (let arg of args) {
            objectToBeValidated = objectToBeValidated[arg];
        }
        return objectToBeValidated;
    }

    /**
     * Utilityfunction to simplify validation! uses {@link validateOrFallback} for validation, and executes
     * given callback (and returns returnvalue from it) if validation fails.
     *
     * @param callback              Function to be executed if validation fails
     * @param objectToBeValidated   The object to do validation-lookup in
     * @param args                  indices used for lookup in objectToBeValidated
     * @returns {*}                 lookup in objectToBeValidated if validation succeeded, returnvalue from callback if not.
     */
    static validateOrCallback(callback, objectToBeValidated, ...args) {
        const validatedValue = this.validateOrFallback(null, objectToBeValidated, ...args);
        if (validatedValue == null) {
            return callback();
        }
        return validatedValue;
    }

    /**
     * Utilityfunction to simplify validation! uses {@link validateOrCallback} for validation, and passes
     * a callback that simply thrown an Error if validation fails.
     *
     * @param errorMessage          the message to use in new Error(errorMessage)
     * @param objectToBeValidated   the object to validate args in
     * @param args                  args for lookup. see {@link validateOrFallback}
     * @returns {*}                 the looked-up value from objectToBeValidated if it exists
     */
    static validateOrError(errorMessage, objectToBeValidated, ...args) {
        return this.validateOrCallback(()=>{throw new Error(errorMessage);}, objectToBeValidated, ...args);
    }

    static _recursiveMerge(mergedValues, overrides) {
    for (let key in overrides) {
        if ((key in mergedValues) && overrides[key] != null && overrides[key].constructor == Object) {
          mergedValues[key] = this._recursiveMerge(mergedValues[key], overrides[key]);
        } else {
          mergedValues[key] = overrides[key];
        }
      }
      return mergedValues;
  }

  /**
   * Deep copy all values from overrides to givenObject.
   *
   * All keys in passed overrides-object will be cloned to passed givenObject. This happens deeply, so all
   * nested objects will also be iterated (NOTE: lists are not iterated, only objects).
   *
   * Note that objects are passed by-reference, so if you do not want givenObject to be modified directly make sure
   * you pass false as third param
   *
   * @param givenObject             The object to override values in
   * @param overrides               The object to copy all values from
   * @param overrideValuesInGiven   if true givenObjects will be overwritten directly, if false a new object
   *                                will be created to merge both given objects into.
   * @returns {*}                   The result from deep-merging
   */
  static _merge(givenObject, overrides, overrideValuesInGiven) {
    if (overrideValuesInGiven) {
      return this._recursiveMerge(givenObject, overrides);
    }

    let mergedValues = {};
    mergedValues = this._recursiveMerge(mergedValues, givenObject);
    return this._recursiveMerge(mergedValues, overrides);
  }

    /**
     * Merges all values from overrideObject into originalObject.
     * This happens in place (as objects are passed-by-reference), so originalObject is modified.
     *
     * This is a deep-merge (unlike Object.assign).
     *
     * @example
Simple example

     * let originalObject = {
     *      foo: "bar",
     *      person: {
     *          name: "Sandy claws",
     *          age: 42
     *      }
     * }
     *
     * let overrideObject = {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678
     *      }
     *  }
     *
     *  ObjectManager.mergeInPlace(originalObject, overrideObject);
     *
     *  // originalObject will now be:
     *  originalObject == {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678,
     *          name: "Sandy claws"
     *      }
     *  }
     *
     * @param originalObject    the object to modify
     * @param overrideObject    the object to copy values from
     */
  static mergeInPlace(originalObject, overrideObject) {
      this._merge(originalObject, overrideObject, true);
  }

    /**
     * Merges all values from originalObject and overrideObject into a new object that is returned.
     *
     * This is a deep-merge (unlike Object.assign).
     *
     * First, all values from originalObject are merged into a new object.
     * Then all values from overrideObject are merged into the same object, overriding any corresponding keys from
     * originalObject.
     *
     * @example
Simple example

     * let originalObject = {
     *      foo: "bar",
     *      person: {
     *          name: "Sandy claws",
     *          age: 42
     *      }
     * }
     *
     * let overrideObject = {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678
     *      }
     *  }
     *
     *  let mergedObject = ObjectManager.mergeAndCopy(originalObject, overrideObject);
     *
     *  // mergedObject will now be:
     *  mergedObject == {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678,
     *          name: "Sandy claws"
     *      }
     *  }
     *
     * @param originalObject    initial values for new object
     * @param overrideObject    object to override values from original object with
     * @returns {{}}            new object containing values from originalObject overridden by overrideObject (see example)
     */
  static mergeAndClone(originalObject, overrideObject) {
      return this._merge(originalObject, overrideObject, false);
  }
}
<commit_msg>jsbase...ObjectManager: Add missing clone method.<commit_after>/**
 * Utility-class with several static functions to simplify validation, merging and other standard operations on
 * javascript-Objects.
 */
export default class ObjectManager {
    /**
     * Checks that given object is not null and not undefined. Also checks the same inwards in provided nested keys
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": ""}}, false, true, "foo", "bar");
     *  // check is now false. key "foo" is found, key "bar" is found, but "bar" is emptyString, and params specify to check for them
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": {}}}, true, false, "foo", "bar");
     *  // check is now false. key "foo" is found, key "bar" is found, but "bar" is {}, and params specify to check for emptyObject.
     *
     * @example
     *  let check = this._hasOwnValue({"foo": {"bar": {}}}, false, false, "foo", "bar");
     *  // check is now true. key "foo" is found, key "bar" is found, so no requested values are null or undefined.
     *
     *  NOTE: Other functions in this file lets you ignore the boolean params - so just use them :)
     *
     * @param givenObject   The object to validate
     * @param emptyObject   if true - keys mapped to empty object {} will also give false
     * @param emptyString   if true - keys mapped to empty string "" will also give false
     * @param args          nested keys to look for, so to validate myObject.foo.bar call this._hasOwnValue(myObject, false, false, "foo". "bar")
     * @returns {boolean}   true if validation passes, false if not.
     */
    static _hasOwnValue(givenObject, emptyObject, emptyString, ...args) {
        function checkValue(value) {
            return (value != undefined && value != null && (!emptyObject || value != {}) && (!emptyString || value != ""));
        }

        if (!checkValue(givenObject)) {
            return false;
        }

        for (let key of args) {
            if (!(key in givenObject) || !checkValue(givenObject[key])) {
                return false;
            }
            givenObject = givenObject[key];
        }

        return true;
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty string "".
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined or ""
     */
    static validateAllowEmptyObject(givenObject, ...args) {
        return this._hasOwnValue(givenObject, false, true, ...args);
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty object {}.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined or {}
     */
    static validateAllowEmptyString(givenObject, ...args) {
        return this._hasOwnValue(givenObject, true, false, ...args);
    }

    /**
     * Validate that an object and nested keys are not null, undefined or empty string "" or empty object {}.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null, undefined, {} or ""
     */
    static validate(givenObject, ...args) {
        return this._hasOwnValue(givenObject, true, true, ...args);
    }

    /**
     * Validate that an object and nested keys are not null or undefined.
     *
     * @example
     * // check that myObject.foo.bar exists:
     * validateAllowEmptyObject(myObject, "foo", "bar")
     *
     * @param givenObject   the object to validate
     * @param args          nested keys to check
     * @returns {boolean}   true if neither the object or any provided nested key is null or undefined.
     */
    static validateAllowEmptyStringAndEmptyObject(givenObject, ...args) {
        return this._hasOwnValue(givenObject, false, false, ...args);
    }

    /**
     * uses {@link validate} to lookup given args in given objectToBeValidated.
     * This ensures the lookup is not null, undefined, empty object, or empty string.
     * If this test fails, given fallbackValue is returned.
     *
     * @example
     *  // to validate myObject.foo.bar, and get "helloworld" back as default if it is empty:
     *  validateOrFallback("helloworld", myObject, "foo", "bar")
     *
     * @param fallbackValue         what to return if empty
     * @param objectToBeValidated   object to do lookup in
     * @param args                  indices used for lookup in object
     * @returns {*}                 lookup in objectToBeValidated if validation succeeded, fallbackValue if not.
     */
    static validateOrFallback(fallbackValue, objectToBeValidated, ...args) {
        if (!this.validate(objectToBeValidated, ...args)) {
            return fallbackValue;
        }
        for (let arg of args) {
            objectToBeValidated = objectToBeValidated[arg];
        }
        return objectToBeValidated;
    }

    /**
     * Utilityfunction to simplify validation! uses {@link validateOrFallback} for validation, and executes
     * given callback (and returns returnvalue from it) if validation fails.
     *
     * @param callback              Function to be executed if validation fails
     * @param objectToBeValidated   The object to do validation-lookup in
     * @param args                  indices used for lookup in objectToBeValidated
     * @returns {*}                 lookup in objectToBeValidated if validation succeeded, returnvalue from callback if not.
     */
    static validateOrCallback(callback, objectToBeValidated, ...args) {
        const validatedValue = this.validateOrFallback(null, objectToBeValidated, ...args);
        if (validatedValue == null) {
            return callback();
        }
        return validatedValue;
    }

    /**
     * Utilityfunction to simplify validation! uses {@link validateOrCallback} for validation, and passes
     * a callback that simply thrown an Error if validation fails.
     *
     * @param errorMessage          the message to use in new Error(errorMessage)
     * @param objectToBeValidated   the object to validate args in
     * @param args                  args for lookup. see {@link validateOrFallback}
     * @returns {*}                 the looked-up value from objectToBeValidated if it exists
     */
    static validateOrError(errorMessage, objectToBeValidated, ...args) {
        return this.validateOrCallback(()=>{throw new Error(errorMessage);}, objectToBeValidated, ...args);
    }

    static _recursiveMerge(mergedValues, overrides) {
    for (let key in overrides) {
        if ((key in mergedValues) && overrides[key] != null && overrides[key].constructor == Object) {
          mergedValues[key] = this._recursiveMerge(mergedValues[key], overrides[key]);
        } else {
          mergedValues[key] = overrides[key];
        }
      }
      return mergedValues;
  }

  /**
   * Deep copy all values from overrides to givenObject.
   *
   * All keys in passed overrides-object will be cloned to passed givenObject. This happens deeply, so all
   * nested objects will also be iterated (NOTE: lists are not iterated, only objects).
   *
   * Note that objects are passed by-reference, so if you do not want givenObject to be modified directly make sure
   * you pass false as third param
   *
   * @param givenObject             The object to override values in
   * @param overrides               The object to copy all values from
   * @param overrideValuesInGiven   if true givenObjects will be overwritten directly, if false a new object
   *                                will be created to merge both given objects into.
   * @returns {*}                   The result from deep-merging
   */
  static _merge(givenObject, overrides, overrideValuesInGiven) {
    if (overrideValuesInGiven) {
      return this._recursiveMerge(givenObject, overrides);
    }

    let mergedValues = {};
    mergedValues = this._recursiveMerge(mergedValues, givenObject);
    return this._recursiveMerge(mergedValues, overrides);
  }

    /**
     * Merges all values from overrideObject into originalObject.
     * This happens in place (as objects are passed-by-reference), so originalObject is modified.
     *
     * This is a deep-merge (unlike Object.assign).
     *
     * @example
Simple example

     * let originalObject = {
     *      foo: "bar",
     *      person: {
     *          name: "Sandy claws",
     *          age: 42
     *      }
     * }
     *
     * let overrideObject = {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678
     *      }
     *  }
     *
     *  ObjectManager.mergeInPlace(originalObject, overrideObject);
     *
     *  // originalObject will now be:
     *  originalObject == {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678,
     *          name: "Sandy claws"
     *      }
     *  }
     *
     * @param originalObject    the object to modify
     * @param overrideObject    the object to copy values from
     */
  static mergeInPlace(originalObject, overrideObject) {
      this._merge(originalObject, overrideObject, true);
  }

    /**
     * Merges all values from originalObject and overrideObject into a new object that is returned.
     *
     * This is a deep-merge (unlike Object.assign).
     *
     * First, all values from originalObject are merged into a new object.
     * Then all values from overrideObject are merged into the same object, overriding any corresponding keys from
     * originalObject.
     *
     * @example
Simple example

     * let originalObject = {
     *      foo: "bar",
     *      person: {
     *          name: "Sandy claws",
     *          age: 42
     *      }
     * }
     *
     * let overrideObject = {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678
     *      }
     *  }
     *
     *  let mergedObject = ObjectManager.mergeAndCopy(originalObject, overrideObject);
     *
     *  // mergedObject will now be:
     *  mergedObject == {
     *      foo: "baz",
     *      person: {
     *          age: 23,
     *          phone: 12345678,
     *          name: "Sandy claws"
     *      }
     *  }
     *
     * @param originalObject    initial values for new object
     * @param overrideObject    object to override values from original object with
     * @returns {{}}            new object containing values from originalObject overridden by overrideObject (see example)
     */
  static mergeAndClone(originalObject, overrideObject) {
      return this._merge(originalObject, overrideObject, false);
  }

  static clone(object) {
      return this.mergeAndClone({}, object);
  }
}
<|endoftext|>


<commit_before>'use strict';

window.game = {};
window.game.path = document.querySelector('link[rel=template]').href.split("/template.js")[0];
window.game.level = 1;

var Game = require("./controllers/game");

var container = document.querySelector(".container");

var button = document.querySelector(".btn")

button.onclick = function(){
	var gameScreen = new Game(container);
}

<commit_msg>template.js url got rewritten , spliting before hash<commit_after>'use strict';

window.game = {};
window.game.path = document.querySelector('link[rel=template]').href.split("/template")[0];
window.game.level = 1;

var Game = require("./controllers/game");

var container = document.querySelector(".container");

var button = document.querySelector(".btn")

button.onclick = function(){
	var gameScreen = new Game(container);
}

<|endoftext|>


<commit_before>import env from '../shared/Env';

const Author = 'Pablo Magaz';
const SiteTitle = Author;
const SiteDescription = `Sitio web de ${ Author }`;
const BlogTitle = 'El Blog Isomórfico';
const BlogDescription = `${ BlogTitle }: JavaScript, JavaScript y más JavaScript.`;
const KeyWords = 'javascript, react, redux, rxjs, immutable, angular, angularjs, webpack, es6, observables, programación reactiva, blog, rxjs, vue, serviceworker, ecma 2018, pwa, progressive web app';
const numPosts = 10;
const blogImage = 'assets/images/postcover/blog.svg';
const blogTitleImage = 'assets/images/share/ElBlogIsomorfico.png';
const brandTitleImage = 'assets/images/share/PabloMagaz.png';
const postOpeningChars = 46;
const codeHighlightDelay = 750;
const postOpeningSplitChar = '
';
const addThisUrl = 'http://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-59c0d1b1697ac737';
const socialLinks = {
  linkedIn: 'https://es.linkedin.com/in/pablo-magaz-05b46763',
  twitter: 'https://twitter.com/pablo_magaz',
  gmail: 'magazpablo@gmail.com',
  github: 'https://github.com/pmagaz'
};

let HostName;
let ServerUrl;
let SiteUrl;
let BlogUrl;
let GhostUrl;
let ImageUrl;
let BaseApiUrl;
let PostsApiUrl;
let clientSecret;
let PostApiUrl;
let PostsApi;
let PostApi;
let ContentPath;
let Ssl;
let Protocol;
let uniqueImagePath;
let GoogleAnaliticsId;
let DisqusSettings;

if (env === 'development') {
  Ssl = false;
  Protocol = Ssl ? 'https://' : 'http://';
  HostName = 'localhost:8000';
  ServerUrl = `http://${ HostName }`;
  SiteUrl = `${ ServerUrl }`;
  clientSecret = '285ee4eda6c3';
  BlogUrl = `${ SiteUrl }/blog`;
  GhostUrl = 'http://pablomagaz.com/';
  ImageUrl = GhostUrl;
  ContentPath = '/Users/Pablo/js/ghost/content';
  BaseApiUrl = `${ GhostUrl }/ghost/api/v0.1/`;
  PostApiUrl = 'https://pablomagaz.com/api/post/';
  PostsApiUrl = 'https://pablomagaz.com/api/posts/';
  PostsApi = `${ BaseApiUrl }posts/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags&fields=id,uuid,title,slug,html,image,feature_image,tags,updated_at,updated_at,published_at&order=published_at desc`;
  PostApi = `${ BaseApiUrl }posts/slug/:slug/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags`;
  GoogleAnaliticsId = 'UA-104300440-3';
  DisqusSettings = {
    shortName: 'el-blog-isomorfico',
    identifier: 'el-blog-isomofico-dev'
  };
} else {
  Ssl = true;
  Protocol = Ssl ? 'https://' : 'http://';
  HostName = 'pablomagaz.com';
  ServerUrl = `${ Protocol }${ HostName }`;
  SiteUrl = `${ ServerUrl }`;
  clientSecret = '113542417eed';
  BlogUrl = `${ SiteUrl }/blog`;
  GhostUrl = 'http://localhost:2369';
  ImageUrl = `${ Protocol }${ HostName }`;
  ContentPath = '/var/www/ghost/content';
  BaseApiUrl = `${ GhostUrl }/ghost/api/v0.1/`;
  PostApiUrl = `${ Protocol }${ HostName }/api/post/`;
  PostsApiUrl = `${ Protocol }${ HostName }/api/posts/`;
  PostsApi = `${ BaseApiUrl }posts/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags&fields=id,uuid,title,slug,html,image,feature_image,tags,updated_at,updated_at,published_at&order=published_at desc`;
  PostApi = `${ BaseApiUrl }posts/slug/:slug/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags`;
  uniqueImagePath = '/assets/images/postcovers';
  GoogleAnaliticsId = 'UA-104300440-2';
  DisqusSettings = {
    shortName: 'el-blog-isomorfico',
    identifier: 'el-blog-isomofico'
  };
}

export const SiteConf = {
  ServerUrl,
  Author,
  SiteTitle,
  SiteUrl,
  numPosts,
  BlogDescription,
  KeyWords,
  BlogTitle,
  BlogUrl,
  blogImage,
  blogTitleImage,
  brandTitleImage,
  SiteDescription,
  ImageUrl,
  ContentPath,
  PostApi,
  PostsApi,
  PostApiUrl,
  PostsApiUrl,
  postOpeningChars,
  postOpeningSplitChar,
  codeHighlightDelay,
  GoogleAnaliticsId,
  Ssl,
  uniqueImagePath,
  socialLinks,
  DisqusSettings,
  addThisUrl
};
<commit_msg>Set absolute url to blog logo<commit_after>import env from '../shared/Env';

const Author = 'Pablo Magaz';
const SiteTitle = Author;
const SiteDescription = `Sitio web de ${ Author }`;
const BlogTitle = 'El Blog Isomórfico';
const BlogDescription = `${ BlogTitle }: JavaScript, JavaScript y más JavaScript.`;
const KeyWords = 'javascript, react, redux, rxjs, immutable, angular, angularjs, webpack, es6, observables, programación reactiva, blog, rxjs, vue, serviceworker, ecma 2018, pwa, progressive web app';
const numPosts = 10;
const blogImage = 'https://pablomagaz.com/assets/images/postcover/blog.svg';
const blogTitleImage = 'assets/images/share/ElBlogIsomorfico.png';
const brandTitleImage = 'assets/images/share/PabloMagaz.png';
const postOpeningChars = 46;
const codeHighlightDelay = 750;
const postOpeningSplitChar = '
';
const addThisUrl = 'http://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-59c0d1b1697ac737';
const socialLinks = {
  linkedIn: 'https://es.linkedin.com/in/pablo-magaz-05b46763',
  twitter: 'https://twitter.com/pablo_magaz',
  gmail: 'magazpablo@gmail.com',
  github: 'https://github.com/pmagaz'
};

let HostName;
let ServerUrl;
let SiteUrl;
let BlogUrl;
let GhostUrl;
let ImageUrl;
let BaseApiUrl;
let PostsApiUrl;
let clientSecret;
let PostApiUrl;
let PostsApi;
let PostApi;
let ContentPath;
let Ssl;
let Protocol;
let uniqueImagePath;
let GoogleAnaliticsId;
let DisqusSettings;

if (env === 'development') {
  Ssl = false;
  Protocol = Ssl ? 'https://' : 'http://';
  HostName = 'localhost:8000';
  ServerUrl = `http://${ HostName }`;
  SiteUrl = `${ ServerUrl }`;
  clientSecret = '285ee4eda6c3';
  BlogUrl = `${ SiteUrl }/blog`;
  GhostUrl = 'http://pablomagaz.com/';
  ImageUrl = GhostUrl;
  ContentPath = '/Users/Pablo/js/ghost/content';
  BaseApiUrl = `${ GhostUrl }/ghost/api/v0.1/`;
  PostApiUrl = 'https://pablomagaz.com/api/post/';
  PostsApiUrl = 'https://pablomagaz.com/api/posts/';
  PostsApi = `${ BaseApiUrl }posts/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags&fields=id,uuid,title,slug,html,image,feature_image,tags,updated_at,updated_at,published_at&order=published_at desc`;
  PostApi = `${ BaseApiUrl }posts/slug/:slug/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags`;
  GoogleAnaliticsId = 'UA-104300440-3';
  DisqusSettings = {
    shortName: 'el-blog-isomorfico',
    identifier: 'el-blog-isomofico-dev'
  };
} else {
  Ssl = true;
  Protocol = Ssl ? 'https://' : 'http://';
  HostName = 'pablomagaz.com';
  ServerUrl = `${ Protocol }${ HostName }`;
  SiteUrl = `${ ServerUrl }`;
  clientSecret = '113542417eed';
  BlogUrl = `${ SiteUrl }/blog`;
  GhostUrl = 'http://localhost:2369';
  ImageUrl = `${ Protocol }${ HostName }`;
  ContentPath = '/var/www/ghost/content';
  BaseApiUrl = `${ GhostUrl }/ghost/api/v0.1/`;
  PostApiUrl = `${ Protocol }${ HostName }/api/post/`;
  PostsApiUrl = `${ Protocol }${ HostName }/api/posts/`;
  PostsApi = `${ BaseApiUrl }posts/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags&fields=id,uuid,title,slug,html,image,feature_image,tags,updated_at,updated_at,published_at&order=published_at desc`;
  PostApi = `${ BaseApiUrl }posts/slug/:slug/?client_id=ghost-frontend&client_secret=${ clientSecret }&include=tags`;
  uniqueImagePath = '/assets/images/postcovers';
  GoogleAnaliticsId = 'UA-104300440-2';
  DisqusSettings = {
    shortName: 'el-blog-isomorfico',
    identifier: 'el-blog-isomofico'
  };
}

export const SiteConf = {
  ServerUrl,
  Author,
  SiteTitle,
  SiteUrl,
  numPosts,
  BlogDescription,
  KeyWords,
  BlogTitle,
  BlogUrl,
  blogImage,
  blogTitleImage,
  brandTitleImage,
  SiteDescription,
  ImageUrl,
  ContentPath,
  PostApi,
  PostsApi,
  PostApiUrl,
  PostsApiUrl,
  postOpeningChars,
  postOpeningSplitChar,
  codeHighlightDelay,
  GoogleAnaliticsId,
  Ssl,
  uniqueImagePath,
  socialLinks,
  DisqusSettings,
  addThisUrl
};
<|endoftext|>


<commit_before>angular
    .module('horizon.dashboard.project.vitrage')
    .directive('hzEntitiesGraph', hzEntitiesGraph);

function hzEntitiesGraph() {
    var directive = {
        link: link,
        scope: {
            data: '=',
            selected: '=',
            itemSelected: '&',
            search: '='
        },
        templateUrl: STATIC_URL + 'dashboard/project/entities/graph/entities-graph.html',
        restrict: 'E'
    };
    return directive;

    function link(scope, element, attrs) {

        var minZoom = 0.3,
            maxZoom = 4,
            linkWidth = 1.5,
            circleRadius = 14,
            circlePadding = 1,
            pinned = horizon.cookies.get('pinned') || [],
            zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]),
            graphCreated,
            node,
            link,
            content;

        scope.$watch('data.ts', function(newVal, oldVal) {
            if (newVal) {
                prepareData();

                if (!graphCreated) {
                    createGraph();
                } else {
                    drawGraph();
                }
            }
        });

        scope.isEmpty = function() {
          return scope.data && scope.data.nodes && scope.data.nodes.length === 0;
        };

        var svg = d3.select(element[0]).select('svg')
            .style('cursor', 'move')
            .attr('width', '100%')
            .attr('pointer-events', 'all');
            //.on('click', selectNone);

        svg.call(zoom);

        var svg_g = svg.append('g')
            .attr('width', '100%')
            .attr('height', '100%')

        link = svg_g.selectAll('.link');

        node = svg_g.selectAll('.node');

        var force = d3.layout.force()
            .gravity(0.05)
            .distance(100)
            .charge(-100)
            //.friction(0.8)
            .linkDistance(function(d) {
                if (d.relationship_type === 'on') {
                    return 80;
                }
                return 160;
            })
            .linkStrength(function(d) {
                if (d.relationship_type === 'on') {
                    return 2;
                }
                return 0.5;
            });

        var drag = force.drag()
            .on('dragend', nodeDragend);
            //.on('dragstart', nodeDragstart);

        resize();
        d3.select(window).on('resize', resize);

        function resize() {
            svg.attr('height', window.innerHeight - 168 + 'px')
            force.size([angular.element(svg[0]).width(),
                angular.element(svg[0]).height()])
                .resume();
        }

        function prepareData() {
            _.each(pinned, function(pin) {
                var node = _.find(scope.data.nodes, function(node) {
                    return pin.id === node.id;
                });

                if (node) {
                    node.fixed = true;
                    node.x = pin.x;
                    node.y = pin.y;
                }
            })
        }

        function createGraph() {

            graphCreated = true;

            function collide(alpha) {
                var quadtree = d3.geom.quadtree(scope.data.nodes);
                return function(d) {
                    var rb = 2 * circleRadius + circlePadding,
                        nx1 = d.x - rb,
                        nx2 = d.x + rb,
                        ny1 = d.y - rb,
                        ny2 = d.y + rb;
                    quadtree.visit(function(quad, x1, y1, x2, y2) {
                        if (quad.point && (quad.point !== d)) {
                            var x = d.x - quad.point.x,
                                y = d.y - quad.point.y,
                                l = Math.sqrt(x * x + y * y);
                            if (l < rb) {
                                l = (l - rb) / l * alpha;
                                d.x -= x *= l;
                                d.y -= y *= l;
                                quad.point.x += x;
                                quad.point.y += y;
                            }
                        }
                        return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
                    });
                };
            }

            force.nodes(scope.data.nodes)
                .links(scope.data.links);

            force.on('tick', function() {
                link.attr('x1', function(d) { return d.source.x; })
                    .attr('y1', function(d) { return d.source.y; })
                    .attr('x2', function(d) { return d.target.x; })
                    .attr('y2', function(d) { return d.target.y; });

                node.attr('transform', function(d) {
                    return 'translate(' + d.x + ',' + d.y + ')';
                });

                node.each(collide(0.5));
            });

            zoom.on('zoom', function() {
                var strokeWidth = linkWidth / zoom.scale();
                if (strokeWidth > linkWidth) {
                    strokeWidth = linkWidth;
                }

                link.style('stroke-width', strokeWidth);

                var scale = 1 / (zoom.scale() / 1.2);
                if (scale > 1) {
                    scale = 1;
                }
                //content.attr('transform', 'scale(' + scale + ')');
                svg_g.selectAll('.node-content').attr('transform', 'scale(' + scale + ')');

                svg_g.attr('transform', 'translate(' + d3.event.translate + ')scale(' + d3.event.scale + ')');

            });

            drawGraph();
        }

        window.drawGraph = drawGraph;

        function drawGraph() {
            link = link.data(force.links(), function(d) { return d.source.id + '-' + d.target.id; });
            link
                .enter().append('line')
                .attr('class', 'link')
            link.exit().remove();

            node = node.data(force.nodes(), function(d) { return d.id;});
            content = node
                .enter().append('g')
                .attr('class', 'node')
                .classed('pinned', function(d) { return d.fixed; })
                .call(force.drag)
                .on('click', nodeClick)
                .on('mousedown', function(d) { d3.event.stopPropagation() })
                .on('dblclick', pinNode)
                .call(drag)
                .append('g')
                .classed('node-content', true);

            //Only for updates
            /*content
                .attr('transform', 'scale(0)')
                .transition(750)
                .attr('transform', 'scale(1)');*/

            node.exit()
                .select('.node-content')
                .transition()
                .duration(750)
                .attr('transform', 'scale(0)')

            node.exit()
                .transition()
                .duration(750)
                .remove();

            content.append('circle')
                .attr('r', circleRadius + 'px');

            content.append('text')
                .attr('text-anchor', 'middle')
                .attr('dominant-baseline', 'central')
                .attr('transform', 'scale(1)')
                .attr('class', function(d) {
                    var cls = '';
                    var severity = d.operational_severity;
                    if (severity) {
                        switch (severity.toLowerCase()) {
                            case 'critical':
                                cls = 'red';
                                break;
                            case 'severe':
                                cls = 'orange';
                                break;
                            case 'warning':
                                cls = 'yellow';
                                break;
                            case 'ok':
                                cls = 'green';
                                break;
                            case 'n/a':
                                cls = 'gray';
                                break;
                            default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
                                cls = 'gray';
                                break;
                        }
                    }
                    return cls;
                })
                .style('font-size', function(d) {
                    var category = d.category || 'no_category',
                        icon_size;

                    if (category && category.toLowerCase() === 'alarm') {
                        icon_size = '18px';
                    } else {
                        var type = d.type || 'no_type';
                        switch(type.toLowerCase()) {
                            case 'nova.instance':
                            case 'nova.host':
                            case 'nova.zone':
                            case 'neutron.port':
                                icon_size = '16px'; //fa-external-link-square
                                break;
                            case 'openstack.cluster':
                                icon_size = '18px'; //fa-cloud
                                break;
                            case 'cinder.volume':
                                icon_size = '22px';
                                break;
                            case 'neutron.network':
                            default:
                                icon_size = '20px';
                                break;
                        }
                    }

                    return icon_size;
                })
                .style('stroke', function(d) {
                    var category = d.category;
                    if (category && category.toLowerCase() === 'alarm') {
                        return '18px'
                    }
                    return '20px'
                })
                .classed('icon', true)
                .classed('fill-only', function(d) {
                    var type = (d.type || '').toLowerCase();
                    if (type && type === 'nova.host' || type === 'cinder.volume') {
                        return true;
                    }
                })
                .text(function(d) {
                    var category = d.category,
                        icon;

                    if (category && category.toLowerCase() === 'alarm') {
                        icon = '\uf0f3'; //\uf0a2'; //bell-o
                    } else {
                        var type = d.type || 'no_type';
                        switch(type.toLowerCase()) {
                            case 'nova.instance':
                                icon = '\uf108'; //fa-desktop
                                break;
                            case 'nova.host':
                                icon = '\uf233'; //fa-server
                                break;
                            case 'nova.zone':
                                icon = '\uf279'; //fa-map
                                break;
                            case 'neutron.network':
                                icon = '\uf0ac'; //fa-globe
                                break;
                            case 'neutron.port':
                                icon = '\uf14c'; //fa-external-link-square
                                break;
                            case 'cinder.volume':
                                icon = '\uf0a0'; //fa-hdd-o
                                break;
                            case 'openstack.cluster':
                                icon = '\uf0c2'; //fa-cloud
                                break;
                            default:
                                icon = '\uf013'; //fa-cog
                                break;
                        }
                    }
                    return icon
                });

            content.append('text')
                .classed('pin', true)
                .attr('dx', '-18px')
                .attr('dy', '-12px')
                .text('\uf08d')
                .on('click', pinNode)

            content.append('text')
                .classed('.label', true)
                .attr('dx', 18)
                .attr('dy', '.35em')
                .text(function(d) { return d.name });

            force.start();
        }

        function nodeClick(d) {
            scope.selected = d;
            //scope.itemSelected(scope.selected);

            d3.event.stopImmediatePropagation();
            d3.event.preventDefault();

            scope.$emit('graphItemClicked', d);

            svg_g.selectAll('.node')
                .classed('selected', false);

            if ($(this).is('.node')) {
                d3.select(this).classed('selected', true);
            }
        }

        function selectNone(d) {
            nodeClick(null);
        }

        function pinNode(d) {
            var node;

            if ($(this).is('.node')) {
                node = d3.select(this);
            } else if ($(this).is('.pin')) {
                node = d3.select(this.parentNode.parentNode);
            }

            if (node) {
                node.classed('pinned', d.fixed = (d.fixed ? false : true));

                updatePinnedCookie(d);
            }

            d3.event.stopImmediatePropagation();
            d3.event.preventDefault();

            //fixing some bug with unpinning
            setTimeout(function() {
                force.resume()
            }, 100)
        }

        function updatePinnedCookie(d) {
            var pinIndex = -1;
            pinned.forEach(function(pin, i) {
                if (pin.id === d.id) {
                    pinIndex = i
                }
            })

            if (pinIndex > -1) {
                pinned.splice(pinIndex, 1);
            }

            if (d.fixed) {
                pinned.push({id: d.id, x: d.x, y: d.y});
            }

            horizon.cookies.put('pinned', pinned);
        }

        function nodeDragend(d) {
            if (d.fixed) {
                updatePinnedCookie(d);
            }
        }

        /*function nodeDragstart(d) {
            d3.select(this).classed('pinned', d.fixed = true);
        }*/

    }
}
<commit_msg>entity graph ellipsis and better gravity<commit_after>angular
    .module('horizon.dashboard.project.vitrage')
    .directive('hzEntitiesGraph', hzEntitiesGraph);

function hzEntitiesGraph() {
    var directive = {
        link: link,
        scope: {
            data: '=',
            selected: '=',
            itemSelected: '&',
            search: '='
        },
        templateUrl: STATIC_URL + 'dashboard/project/entities/graph/entities-graph.html',
        restrict: 'E'
    };
    return directive;

    function link(scope, element, attrs) {

        var minZoom = 0.3,
            maxZoom = 4,
            linkWidth = 1.5,
            circleRadius = 14,
            circlePadding = 1,
            pinned = horizon.cookies.get('pinned') || [],
            zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]),
            ellipsisChars = 15,
            graphCreated,
            node,
            link,
            content;

        scope.$watch('data.ts', function(newVal, oldVal) {
            if (newVal) {
                prepareData();

                if (!graphCreated) {
                    createGraph();
                } else {
                    drawGraph();
                }
            }
        });

        scope.isEmpty = function() {
          return scope.data && scope.data.nodes && scope.data.nodes.length === 0;
        };

        var svg = d3.select(element[0]).select('svg')
            .style('cursor', 'move')
            .attr('width', '100%')
            .attr('pointer-events', 'all');
            //.on('click', selectNone);

        svg.call(zoom);

        var svg_g = svg.append('g')
            .attr('width', '100%')
            .attr('height', '100%')

        link = svg_g.selectAll('.link');

        node = svg_g.selectAll('.node');

        var force = d3.layout.force()
            .gravity(0.05)
            .distance(200)
            .charge(-1000)
            //.friction(0.8)
            .linkDistance(function(d) {
                if (d.relationship_type === 'on') {
                    return 80;
                }
                return 160;
            })
            .linkStrength(function(d) {
                if (d.relationship_type === 'on') {
                    return 2;
                }
                return 0.5;
            });

        var drag = force.drag()
            .on('dragend', nodeDragend);
            //.on('dragstart', nodeDragstart);

        resize();
        d3.select(window).on('resize', resize);

        function resize() {
            svg.attr('height', window.innerHeight - 168 + 'px')
            force.size([angular.element(svg[0]).width(),
                angular.element(svg[0]).height()])
                .resume();
        }

        function prepareData() {
            _.each(pinned, function(pin) {
                var node = _.find(scope.data.nodes, function(node) {
                    return pin.id === node.id;
                });

                if (node) {
                    node.fixed = true;
                    node.x = pin.x;
                    node.y = pin.y;
                }
            })
        }

        function createGraph() {

            graphCreated = true;

            function collide(alpha) {
                var quadtree = d3.geom.quadtree(scope.data.nodes);
                return function(d) {
                    var rb = 2 * circleRadius + circlePadding,
                        nx1 = d.x - rb,
                        nx2 = d.x + rb,
                        ny1 = d.y - rb,
                        ny2 = d.y + rb;
                    quadtree.visit(function(quad, x1, y1, x2, y2) {
                        if (quad.point && (quad.point !== d)) {
                            var x = d.x - quad.point.x,
                                y = d.y - quad.point.y,
                                l = Math.sqrt(x * x + y * y);
                            if (l < rb) {
                                l = (l - rb) / l * alpha;
                                d.x -= x *= l;
                                d.y -= y *= l;
                                quad.point.x += x;
                                quad.point.y += y;
                            }
                        }
                        return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
                    });
                };
            }

            force.nodes(scope.data.nodes)
                .links(scope.data.links);

            force.on('tick', function() {
                link.attr('x1', function(d) { return d.source.x; })
                    .attr('y1', function(d) { return d.source.y; })
                    .attr('x2', function(d) { return d.target.x; })
                    .attr('y2', function(d) { return d.target.y; });

                node.attr('transform', function(d) {
                    return 'translate(' + d.x + ',' + d.y + ')';
                });

                node.each(collide(0.5));
            });

            zoom.on('zoom', function() {
                var strokeWidth = linkWidth / zoom.scale();
                if (strokeWidth > linkWidth) {
                    strokeWidth = linkWidth;
                }

                link.style('stroke-width', strokeWidth);

                var scale = 1 / (zoom.scale() / 1.2);
                if (scale > 1) {
                    scale = 1;
                }
                //content.attr('transform', 'scale(' + scale + ')');
                svg_g.selectAll('.node-content').attr('transform', 'scale(' + scale + ')');

                svg_g.attr('transform', 'translate(' + d3.event.translate + ')scale(' + d3.event.scale + ')');

            });

            drawGraph();
        }

        window.drawGraph = drawGraph;

        function drawGraph() {
            link = link.data(force.links(), function(d) { return d.source.id + '-' + d.target.id; });
            link
                .enter().append('line')
                .attr('class', 'link')
            link.exit().remove();

            node = node.data(force.nodes(), function(d) { return d.id;});
            content = node
                .enter().append('g')
                .attr('class', 'node')
                .classed('pinned', function(d) { return d.fixed; })
                .call(force.drag)
                .on('click', nodeClick)
                .on('mousedown', function(d) { d3.event.stopPropagation() })
                .on('dblclick', pinNode)
                .call(drag)
                .append('g')
                .classed('node-content', true);

            //Only for updates
            /*content
                .attr('transform', 'scale(0)')
                .transition(750)
                .attr('transform', 'scale(1)');*/

            node.exit()
                .select('.node-content')
                .transition()
                .duration(750)
                .attr('transform', 'scale(0)')

            node.exit()
                .transition()
                .duration(750)
                .remove();

            content.append('circle')
                .attr('r', circleRadius + 'px');

            content.append('text')
                .attr('text-anchor', 'middle')
                .attr('dominant-baseline', 'central')
                .attr('transform', 'scale(1)')
                .attr('class', function(d) {
                    var cls = '';
                    var severity = d.operational_severity;
                    if (severity) {
                        switch (severity.toLowerCase()) {
                            case 'critical':
                                cls = 'red';
                                break;
                            case 'severe':
                                cls = 'orange';
                                break;
                            case 'warning':
                                cls = 'yellow';
                                break;
                            case 'ok':
                                cls = 'green';
                                break;
                            case 'n/a':
                                cls = 'gray';
                                break;
                            default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
                                cls = 'gray';
                                break;
                        }
                    }
                    return cls;
                })
                .style('font-size', function(d) {
                    var category = d.category || 'no_category',
                        icon_size;

                    if (category && category.toLowerCase() === 'alarm') {
                        icon_size = '18px';
                    } else {
                        var type = d.type || 'no_type';
                        switch(type.toLowerCase()) {
                            case 'nova.instance':
                            case 'nova.host':
                            case 'nova.zone':
                            case 'neutron.port':
                                icon_size = '16px'; //fa-external-link-square
                                break;
                            case 'openstack.cluster':
                                icon_size = '18px'; //fa-cloud
                                break;
                            case 'cinder.volume':
                                icon_size = '22px';
                                break;
                            case 'neutron.network':
                            default:
                                icon_size = '20px';
                                break;
                        }
                    }

                    return icon_size;
                })
                .style('stroke', function(d) {
                    var category = d.category;
                    if (category && category.toLowerCase() === 'alarm') {
                        return '18px'
                    }
                    return '20px'
                })
                .classed('icon', true)
                .classed('fill-only', function(d) {
                    var type = (d.type || '').toLowerCase();
                    if (type && type === 'nova.host' || type === 'cinder.volume') {
                        return true;
                    }
                })
                .text(function(d) {
                    var category = d.category,
                        icon;

                    if (category && category.toLowerCase() === 'alarm') {
                        icon = '\uf0f3'; //\uf0a2'; //bell-o
                    } else {
                        var type = d.type || 'no_type';
                        switch(type.toLowerCase()) {
                            case 'nova.instance':
                                icon = '\uf108'; //fa-desktop
                                break;
                            case 'nova.host':
                                icon = '\uf233'; //fa-server
                                break;
                            case 'nova.zone':
                                icon = '\uf279'; //fa-map
                                break;
                            case 'neutron.network':
                                icon = '\uf0ac'; //fa-globe
                                break;
                            case 'neutron.port':
                                icon = '\uf14c'; //fa-external-link-square
                                break;
                            case 'cinder.volume':
                                icon = '\uf0a0'; //fa-hdd-o
                                break;
                            case 'openstack.cluster':
                                icon = '\uf0c2'; //fa-cloud
                                break;
                            default:
                                icon = '\uf013'; //fa-cog
                                break;
                        }
                    }
                    return icon
                });

            content.append('text')
                .classed('pin', true)
                .attr('dx', '-18px')
                .attr('dy', '-12px')
                .text('\uf08d')
                .on('click', pinNode)

            content.append('text')
                .classed('.label', true)
                .attr('dx', 18)
                .attr('dy', '.35em')
                .text(function(d) {
                    if(d.name.length > ellipsisChars) {
                        return d.name.substring(0, ellipsisChars) + '...';
                    } else {
                        return d.name;
                    }
                })
                .append('title')
                .text(function(d) { return d.name; });

            force.start();
        }

        function nodeClick(d) {
            scope.selected = d;
            //scope.itemSelected(scope.selected);

            d3.event.stopImmediatePropagation();
            d3.event.preventDefault();

            scope.$emit('graphItemClicked', d);

            svg_g.selectAll('.node')
                .classed('selected', false);

            if ($(this).is('.node')) {
                d3.select(this).classed('selected', true);
            }
        }

        function selectNone(d) {
            nodeClick(null);
        }

        function pinNode(d) {
            var node;

            if ($(this).is('.node')) {
                node = d3.select(this);
            } else if ($(this).is('.pin')) {
                node = d3.select(this.parentNode.parentNode);
            }

            if (node) {
                node.classed('pinned', d.fixed = (d.fixed ? false : true));

                updatePinnedCookie(d);
            }

            d3.event.stopImmediatePropagation();
            d3.event.preventDefault();

            //fixing some bug with unpinning
            setTimeout(function() {
                force.resume()
            }, 100)
        }

        function updatePinnedCookie(d) {
            var pinIndex = -1;
            pinned.forEach(function(pin, i) {
                if (pin.id === d.id) {
                    pinIndex = i
                }
            })

            if (pinIndex > -1) {
                pinned.splice(pinIndex, 1);
            }

            if (d.fixed) {
                pinned.push({id: d.id, x: d.x, y: d.y});
            }

            horizon.cookies.put('pinned', pinned);
        }

        function nodeDragend(d) {
            if (d.fixed) {
                updatePinnedCookie(d);
            }
        }

        /*function nodeDragstart(d) {
            d3.select(this).classed('pinned', d.fixed = true);
        }*/

    }
}
<|endoftext|>


<commit_before>ngDefine('camunda.common.directives.notificationsPanel', [
  'angular',
  'jquery',
  'module:ngSanitize'
], function(module, angular, $) {

  var notificationsTemplate =
'
' +
'
' +
'    <button type="button" class="close" ng-click="removeNotification(notification)">×</button>' +
'    {{ notification.status }}: ' +
'
' +
'
';

  module.directive('notificationsPanel', function(Notifications, $filter) {
    return {
      restrict: 'EAC',
      scope: {
        filter: '=notificationsFilter'
      },
      template: notificationsTemplate,
      link: function(scope, element, attrs, $destroy) {

        var filter = scope.filter;

        function matchesFilter(notification) {
          if (!filter) {
            return true;
          }

          return !!$filter('filter')([ notification ], filter).length;
        };

        var notifications = scope.notifications = [];

        var consumer = {
          add: function(notification) {
            if (matchesFilter(notification)) {
              notifications.push(notification);
              return true;
            } else {
              return false;
            }
          },
          remove: function(notification) {
            var idx = notifications.indexOf(notification);
            if (idx != -1) {
              notifications.splice(idx, 1);
            }
          }
        };

        Notifications.registerConsumer(consumer);

        scope.removeNotification = function(notification) {
          notifications.splice(notifications.indexOf(notification), 1);
        };

        scope.notificationClass = function(notification) {
          var classes = [ 'error', 'success', 'warning', 'information' ];

          var type = 'information';

          if (classes.indexOf(notification.type) != -1) {
            type = notification.type;
          }

          return 'alert-' + type;
        };

        scope.$on($destroy, function() {
          Notifications.unregisterConsumer(consumer);
        });
      }
    };
  });
});
<commit_msg>fix(webapps/notificationsPanel): fix panels not being removed<commit_after>ngDefine('camunda.common.directives.notificationsPanel', [
  'angular',
  'jquery',
  'module:ngSanitize'
], function(module, angular, $) {

  var notificationsTemplate =
'
' +
'
' +
'    <button type="button" class="close" ng-click="removeNotification(notification)">×</button>' +
'    {{ notification.status }}: ' +
'
' +
'
';

  module.directive('notificationsPanel', function(Notifications, $filter) {
    return {
      restrict: 'EAC',
      scope: {
        filter: '=notificationsFilter'
      },
      template: notificationsTemplate,
      link: function(scope, element, attrs, $destroy) {

        var filter = scope.filter;

        function matchesFilter(notification) {
          if (!filter) {
            return true;
          }

          return !!$filter('filter')([ notification ], filter).length;
        };

        var notifications = scope.notifications = [];

        var consumer = {
          add: function(notification) {
            if (matchesFilter(notification)) {
              notifications.push(notification);
              return true;
            } else {
              return false;
            }
          },
          remove: function(notification) {
            var idx = notifications.indexOf(notification);
            if (idx != -1) {
              notifications.splice(idx, 1);
            }
          }
        };

        Notifications.registerConsumer(consumer);

        scope.removeNotification = function(notification) {
          notifications.splice(notifications.indexOf(notification), 1);
        };

        scope.notificationClass = function(notification) {
          var classes = [ 'error', 'success', 'warning', 'information' ];

          var type = 'information';

          if (classes.indexOf(notification.type) != -1) {
            type = notification.type;
          }

          return 'alert-' + type;
        };

        scope.$on('$destroy', function() {
          Notifications.unregisterConsumer(consumer);
        });
      }
    };
  });
});
<|endoftext|>


<commit_before>Application.Directives.directive("homeSampleDetails", homeSampleDetailsDirective);
function homeSampleDetailsDirective() {
    return {
        restrict: "AE",
        scope: true,
        controller: 'homeSampleDetailsController',
        replace: true,
        templateUrl: "application/core/projects/project/home/directives/home-sample-details.html"
    };
}

Application.Controllers.controller("homeSampleDetailsController",
    ["$scope", "current", "Project",
        homeSampleDetailsController]);

function homeSampleDetailsController($scope, current, Project) {
    console.log($scope.sample);
    console.log(current.project());
    //currently we have a single note for a sample. This could change at the time of sample rework
    var notes = Project.getSpecificNotes(current.project(), $scope.sample.id, 'sample');
    $scope.note = notes[0];
}
<commit_msg>removed console  statements<commit_after>Application.Directives.directive("homeSampleDetails", homeSampleDetailsDirective);
function homeSampleDetailsDirective() {
    return {
        restrict: "AE",
        scope: true,
        controller: 'homeSampleDetailsController',
        replace: true,
        templateUrl: "application/core/projects/project/home/directives/home-sample-details.html"
    };
}

Application.Controllers.controller("homeSampleDetailsController",
    ["$scope", "current", "Project",
        homeSampleDetailsController]);

function homeSampleDetailsController($scope, current, Project) {
    //currently we have a single note for a sample. This could change at the time of sample rework
    var notes = Project.getSpecificNotes(current.project(), $scope.sample.id, 'sample');
    $scope.note = notes[0];
}
<|endoftext|>