<commit_before>// ta in json
// instansiera vårt objekt
//

var info = {
	name: "BarChart",
	description: "A barchart by the team"
};

function BarChart(){
	var atom;
	var data;

	// default properties for the Atom
	var defaults = {
		title: "Barchart",
		chart:{
			background: "white",
			foreground: "#333"
		},
		fills: [
			"#69D2E7",
			"#A7DBD8",
			"#E0E4CC",
			"#F38630",
			"#FA6900",
			"#3FB8AF",
			"#7FC7AF",
			"#DAD8A7",
			"#FF9E9D",
			"#FF3D7F"
		],
		getFill: function (index) {
			return this.fills[index % this.fills.length]
		},
		lines:{},
		highest:{
			color:"red"
		},
		barWidth: 50,
		barMargin: 30,
		topMargin: 120,
		labelSize: 14
	};

	// called by library
	// onRecieveJSON
	var init = function (json, options, callback){

		data = json;

		if(options){
			//recursively merge defaults with options
			$.extend(true, defaults, options);
		};

		if(callback){
			callback();
		};
	};

	var draw = function (paper) {

		var paperHeight = parseInt(paper.attr('height'));
		var paperWidth = parseInt(paper.attr('width'));

		var highest = 0;
		data.forEach(function (d) {
			if(d.value > highest) {
				highest = d.value
			};
		});

		var scale = (paperHeight - defaults.topMargin) / highest;
		var xOffsetLeft = defaults.barMargin;

		var barWidth = (paperWidth / data.length) - defaults.barMargin - (defaults.barMargin/data.length);

		//  frame
		paper.append('rect')
			.attr('width', paperWidth)
			.attr('height', paperHeight)
			.attr('fill', "#fafafa")
			.attr('stroke', "rgba(0,0,0,0.4)")

		var bars = paper.selectAll('g')
			.data(data)

		// main bars
		bars.enter()
			.append('rect')
				.attr('width', barWidth)
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin);
				})
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"rgba(0,0,0,0.2)")
				// .attr('stroke-width',"2")
				// .attr('stroke-alignment',"inner")
				.attr('y', paperHeight- defaults.labelSize*2)
				.delay()
				.transition()
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2;
				})
				.attr('height', function (d) {
					return d.value * scale;
				})
				// .transition()

		shadowSize = (barWidth - barWidth / 1.618);

		//shadows
		bars.enter()
			.append('rect')
				.attr('width', shadowSize)
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth- shadowSize;
				})
				.attr('fill', 'rgba(0,0,0,0.08)')

				.attr('y', paperHeight- defaults.labelSize*2)
				.delay()
				.transition()
				.attr('height', function (d) {
					return d.value * scale;
				})
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2;
				});

		// labels
		bars.enter()
			.append('text')
				.text(function (d) {
					return d.label;
				})
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth /2;
				})
				.attr('y', function (d) {
					return paperHeight - defaults.labelSize + 5;
				})
				.attr('width', barWidth)
				.attr('stroke-width', ".05")
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"black")
				.attr('font-family', "avenir")
				.attr('text-anchor', "middle")
				// .attr('style', "text-transform: uppercase;")
				.attr('font-size', "12")
				.attr('font-weight', "600")

		// bars.values
		bars.enter()
			.append('text')
				.text(function (d) {
					return d.value;
				})
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth /2;
				})
				.attr('width', barWidth)
				.attr('stroke-width', ".05")
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"black")
				.attr('font-family', "avenir")
				.attr('text-anchor', "middle")
				// .attr('style', "text-transform: uppercase;")
				.attr('font-size', barWidth /3)
				.attr('font-weight', "600")
				.attr('y', paperHeight- defaults.labelSize*2)
				.delay()
				.transition()
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2 - defaults.labelSize;
				})

		if(defaults.title){
			bars.enter()
				.append('text')
					.text(defaults.title)
					.attr('x', 10)
					.attr('y', defaults.barMargin  + 5)
					.attr('fill', "#999")
					.attr('font-family', "avenir")
					.attr('font-size', defaults.barMargin*0.9)
		};

	};

		// init:init
	return Object.freeze({
		init: init,
		draw: draw,
		getDefaults: function(){return defaults;}
	});
};

Molecule.registerAtom(BarChart, info);

<commit_msg>remove delay<commit_after>// ta in json
// instansiera vårt objekt
//

var info = {
	name: "BarChart",
	description: "A barchart by the team"
};

function BarChart(){
	var atom;
	var data;

	// default properties for the Atom
	var defaults = {
		title: "Barchart",
		chart:{
			background: "white",
			foreground: "#333"
		},
		fills: [
			"#69D2E7",
			"#A7DBD8",
			"#E0E4CC",
			"#F38630",
			"#FA6900",
			"#3FB8AF",
			"#7FC7AF",
			"#DAD8A7",
			"#FF9E9D",
			"#FF3D7F"
		],
		getFill: function (index) {
			return this.fills[index % this.fills.length]
		},
		lines:{},
		highest:{
			color:"red"
		},
		barWidth: 50,
		barMargin: 30,
		topMargin: 120,
		labelSize: 14
	};

	// called by library
	// onRecieveJSON
	var init = function (json, options, callback){

		data = json;

		if(options){
			//recursively merge defaults with options
			$.extend(true, defaults, options);
		};

		if(callback){
			callback();
		};
	};

	var draw = function (paper) {

		var paperHeight = parseInt(paper.attr('height'));
		var paperWidth = parseInt(paper.attr('width'));

		var highest = 0;
		data.forEach(function (d) {
			if(d.value > highest) {
				highest = d.value
			};
		});

		var scale = (paperHeight - defaults.topMargin) / highest;
		var xOffsetLeft = defaults.barMargin;

		var barWidth = (paperWidth / data.length) - defaults.barMargin - (defaults.barMargin/data.length);

		//  frame
		paper.append('rect')
			.attr('width', paperWidth)
			.attr('height', paperHeight)
			.attr('fill', "#fafafa")
			.attr('stroke', "rgba(0,0,0,0.4)")

		var bars = paper.selectAll('g')
			.data(data)

		// main bars
		bars.enter()
			.append('rect')
				.attr('width', barWidth)
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin);
				})
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"rgba(0,0,0,0.2)")
				// .attr('stroke-width',"2")
				// .attr('stroke-alignment',"inner")
				.attr('y', paperHeight- defaults.labelSize*2)

				.transition()
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2;
				})
				.attr('height', function (d) {
					return d.value * scale;
				})
				// .transition()

		shadowSize = (barWidth - barWidth / 1.618);

		//shadows
		bars.enter()
			.append('rect')
				.attr('width', shadowSize)
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth- shadowSize;
				})
				.attr('fill', 'rgba(0,0,0,0.08)')

				.attr('y', paperHeight- defaults.labelSize*2)

				.transition()
				.attr('height', function (d) {
					return d.value * scale;
				})
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2;
				});

		// labels
		bars.enter()
			.append('text')
				.text(function (d) {
					return d.label;
				})
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth /2;
				})
				.attr('y', function (d) {
					return paperHeight - defaults.labelSize + 5;
				})
				.attr('width', barWidth)
				.attr('stroke-width', ".05")
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"black")
				.attr('font-family', "avenir")
				.attr('text-anchor', "middle")
				// .attr('style', "text-transform: uppercase;")
				.attr('font-size', "12")
				.attr('font-weight', "600")

		// bars.values
		bars.enter()
			.append('text')
				.text(function (d) {
					return d.value;
				})
				.attr('x', function (d,i) {
					return xOffsetLeft + i * (barWidth + defaults.barMargin) + barWidth /2;
				})
				.attr('width', barWidth)
				.attr('stroke-width', ".05")
				.attr('fill', function (d,i) {
					return defaults.getFill(i);
				})
				.attr('stroke',"black")
				.attr('font-family', "avenir")
				.attr('text-anchor', "middle")
				// .attr('style', "text-transform: uppercase;")
				.attr('font-size', barWidth /3)
				.attr('font-weight', "600")
				.attr('y', paperHeight- defaults.labelSize*2)

				.transition()
				.attr('y', function (d) {
					return paperHeight - (d.value * scale) - defaults.labelSize*2 - defaults.labelSize;
				})

		if(defaults.title){
			bars.enter()
				.append('text')
					.text(defaults.title)
					.attr('x', 10)
					.attr('y', defaults.barMargin  + 5)
					.attr('fill', "#999")
					.attr('font-family', "avenir")
					.attr('font-size', defaults.barMargin*0.9)
		};

	};

		// init:init
	return Object.freeze({
		init: init,
		draw: draw,
		getDefaults: function(){return defaults;}
	});
};

Molecule.registerAtom(BarChart, info);

<|endoftext|>


<commit_before>/**
 *  Poppy Pagination
 *  Generate page options/results using pre-existing content
 *
 *  Copyright 2012-2015, Marc S. Brooks (http://mbrooks.info)
 *  Licensed under the MIT license:
 *  http://www.opensource.org/licenses/mit-license.php
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('5(!D.s||(D.s&&D.s.G.1f<\'1.8.3\')){1g H 1h(\'1i-1j 1k s 1.8.3 1l 1m.\');}(7($){4 j={};4 k={"I":7(a,b){4 c=$(l);a=$.1n(J,{K:0,L:10,M:1,N:{O:\'1o P\',Q:\'1p P\',R:\'%v - %z 1q %m 1r\',S:\'1s\'}},a);j=a.N;4 d=T(a);5(d.m>0){4 e=c.1t(\'w.U\');5(e[0]){e.1u()}4 f=$(\'<w></w>\').p(\'U\');4 g=V(d,b),W=X(d,b);f.6(W,g);c.1v(f);4 h=f.1w(J);h.6(h.Y().1x().1y());c.6(h)}},"1z":7(){$(l).1A()}};$.G.Z=7(a){5(k[a]){q k[a].11(l,1B.1C.1D.1E(12,1))}x 5(1F a===\'1G\'||!a){q k.I.11(l,12)}x{$.1H(\'1I \'+a+\' 1J 1K 1L 13 s.Z\')}};7 V(a,b){4 c=$(\'<n></n>\').6(y(j.R,a));4 d=$(\'<14></14>\');5(a.m>10&&a.9>1){4 e=$(\'<15></15>\').6(y(j.S,a));d.6(e);4 f=$(\'-\'),r=$(\'<r></r>\').6(f);4 g=[10,20,1M,1N,1O];$.1P(g,7(){5(l<=a.m){f=$(\'\'+l+\'\').1Q(\'16\',l);r.6(f);5(l==a.9){r.1R=l}}});5($.17(b)){r.B(\'1S\',7(){a.9=1T(l.16);b(a)})}d.6(r)}q $(\'<w></w>\').p(\'1U\').6(c,d)}7 X(c,d){4 e=$(\'<18></18>\').p(\'t\');4 f=$(\'\').p(\'1V\');7 C(a){a.1W();c.o=a.1X;5($.17(d)){d(c)}}(7(){4 a=10,19=(c.v/c.9)-(a/2),1a=(c.z/c.9)+(a/2);1b(4 i=1;i<=c.t;i++){5(19>i)1c;5(1a<i)1c;4 b=E;5(c.o!=i){b=$(\'\'+i+\'\').B(\'F\',i,C)}x{b=$(\'<n>\'+i+\'</n>\')}f.6(b)}})();(7(){5(c.m>0){4 a=$(\'\').p(\'z\');4 b=E;5(c.o>1){b=$(\'\').B(\'F\',(c.o-1),C)}x{b=$(\'<n></n>\')}b.6(y(j.O,c));a.6(b);e.6(a)}})();5(f.Y()){e.6(f);5(c.t==1){f.1Y(\'1Z\',\'21\')}}(7(){5(c.m>1){4 a=$(\'\').p(\'22\');4 b=E;5(c.t!=c.o){b=$(\'\').B(\'F\',(c.o+1),C)}x{b=$(\'<n></n>\')}b.6(y(j.Q,c));a.6(b);e.6(a)}})();5(c.t==1){e.p(\'23\')}q e}7 T(a){4 b={};b.m=a.K;b.9=a.L;b.o=a.M||1;b.t=1d(b.m,b.9);b.v=b.o*b.9+1-b.9;b.z=((b.v+b.9-1)<b.m)?(b.v+b.9-1):b.m;q b}7 1d(a,b){4 c=24.25(a/b);5((c*b)<a){c++}q c}7 y(a,b){1b(4 c 13 b){5(b[c]){4 d=c,1e=H 26(\'%\'+d,\'i\');a=a.27(1e,b[c])}}q a}})(s);',62,132,'||||var|if|append|function||limit||||||||||||this|total|span|start|addClass|return|select|jQuery|pages|li|first|div|else|replaceTokens|last|option|on|onClickEvent|window|null|click|fn|new|init|true|totalResults|perPage|startPage|uiText|LAST_PAGE|Page|NEXT_PAGE|RESULTS|VIEWING|calcPageResults|poppy_pagination|createResultElm|block2|createPagerElm|children|PoppyPagination||apply|arguments|in|form|label|value|isFunction|ul|first_link|last_link|for|continue|getTotalRows|regex|jquery|throw|Error|Poppy|Pagination|requires|or|greater|extend|Last|Next|of|results|Viewing|find|remove|prepend|clone|get|reverse|destroy|removeData|Array|prototype|slice|call|typeof|object|error|Method|does|not|exist|30|40|50|each|attr|selectedIndex|change|parseInt|options|crumbs|preventDefault|data|css|visibility||hidden|next|disabled|Math|round|RegExp|replace'.split('|'),0,{}));
<commit_msg>Packed new release<commit_after>/**
 *  Poppy Pagination
 *  Generate page options/results using pre-existing content
 *
 *  Copyright 2012-2015, Marc S. Brooks (http://mbrooks.info)
 *  Licensed under the MIT license:
 *  http://www.opensource.org/licenses/mit-license.php
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('5(!H.s||(H.s&&H.s.L.1j<\'1.8.3\')){1k M 1l(\'1m-1n 1o s 1.8.3 1p 1q.\');}(7($){4 j={"N":7(a,b){4 c=$(k),9=c.9();a=$.1r(O,{P:0,Q:10,R:1,I:{S:\'1s T\',U:\'1t T\',V:\'%x - %D 1u %m 1v\',W:\'1w\'}},a);5($.1x(9)){c.9({t:a})}n c.u(\'X\',b)},"1y":7(){$(k).1z()},"X":7(a){4 b=$(k),y=b.1A();4 c=b.u(\'Y\');5(c.m>0){4 d=y.1B(\'z.Z\');5(d[0]){d.1C()}4 e=$(\'<z></z>\').q(\'Z\');4 f=b.u(\'11\',c,a),12=b.u(\'13\',c,a);e.6(12,f);y.1D(e);4 g=e.1E(O);g.6(g.14().1F().1G());y.6(g)}n y},"11":7(a,b){4 c=$(k),9=c.9(),v=9.t.I;4 d=$(\'<o></o>\').6(A(v.V,a));4 e=$(\'<15></15>\');5(a.m>10&&a.l>1){4 f=$(\'<16></16>\').6(A(v.W,a));e.6(f);4 g=$(\'<E>-</E>\'),r=$(\'<r></r>\').6(g);4 h=[10,20,1H,1I,1J];$.1K(h,7(){5(k<=a.m){g=$(\'<E>\'+k+\'</E>\').1L(\'17\',k);r.6(g);5(k==a.l){r.1M=k}}});5($.18(b)){r.F(\'1N\',7(){a.l=1O(k.17);b(a)})}e.6(r)}n $(\'<z></z>\').q(\'1P\').6(d,e)},"13":7(c,d){4 e=$(k),9=e.9(),v=9.t.I;4 f=$(\'<19></19>\').q(\'B\');4 g=$(\'<w></w>\').q(\'1Q\');7 G(a){a.1R();c.p=a.9;5($.18(d)){d(c)}}(7(){4 a=10,1a=(c.x/c.l)-(a/2),1b=(c.D/c.l)+(a/2);1c(4 i=1;i<=c.B;i++){5(1a>i)1d;5(1b<i)1d;4 b=J;5(c.p!=i){b=$(\'\'+i+\'\').F(\'K\',i,G)}C{b=$(\'<o>\'+i+\'</o>\')}g.6(b)}})();(7(){5(c.m>0){4 a=$(\'<w></w>\').q(\'D\');4 b=J;5(c.p>1){b=$(\'\').F(\'K\',(c.p-1),G)}C{b=$(\'<o></o>\')}b.6(A(v.S,c));a.6(b);f.6(a)}})();5(g.14()){f.6(g)}(7(){5(c.m>1){4 a=$(\'<w></w>\').q(\'1S\');4 b=J;5(c.B!=c.p){b=$(\'\').F(\'K\',(c.p+1),G)}C{b=$(\'<o></o>\')}b.6(A(v.U,c));a.6(b);f.6(a)}})();5(c.B==1){f.q(\'1T\')}n f},"Y":7(){4 a=$(k),9=a.9();4 b={};b.m=9.t.P;b.l=9.t.Q;b.p=9.t.R||1;b.B=1e(b.m,b.l);b.x=b.p*b.l+1-b.l;b.D=((b.x+b.l-1)<b.m)?(b.x+b.l-1):b.m;n b}};$.L.u=7(a){5(j[a]){n j[a].1f(k,1U.1V.1W.1X(1g,1))}C 5(1Y a===\'1Z\'||!a){n j.N.1f(k,1g)}C{$.21(\'22 \'+a+\' 23 24 25 1h s.u\')}};7 1e(a,b){4 c=26.27(a/b);5((c*b)<a){c++}n c}7 A(a,b){1c(4 c 1h b){5(b[c]){4 d=c,1i=M 28(\'%\'+d,\'i\');a=a.29(1i,b[c])}}n a}})(s);',62,134,'||||var|if|append|function||data|||||||||||this|limit|total|return|span|start|addClass|select|jQuery|config|PoppyPagination|lang|li|first|block|div|replaceTokens|pages|else|last|option|on|onClickEvent|window|uiText|null|click|fn|new|init|true|totalResults|perPage|startPage|LAST_PAGE|Page|NEXT_PAGE|RESULTS|VIEWING|_createPageResults|_calcPageResults|poppy_pagination||_createResultElm|elm2|_createPagerElm|children|form|label|value|isFunction|ul|first_link|last_link|for|continue|getTotalRows|apply|arguments|in|regex|jquery|throw|Error|Poppy|Pagination|requires|or|greater|extend|Last|Next|of|results|Viewing|isEmptyObject|destroy|removeData|parent|find|remove|prepend|clone|get|reverse|30|40|50|each|attr|selectedIndex|change|parseInt|options|crumbs|preventDefault|next|disabled|Array|prototype|slice|call|typeof|object||error|Method|does|not|exist|Math|round|RegExp|replace'.split('|'),0,{}));
<|endoftext|>


<commit_before>/**
 * @file
 * Js behavior for the mailing forms.
 */

(function($) {

  /**
   * Attach the behavior.
   */
  Drupal.behaviors.culturefeed_mailing = {
    attach: function (context, settings) {

      // If a userlocation is known, set the default zip value.
      var userLocationJson = $.cookie('Drupal.visitor.uitid.userLocation');
      if (typeof userLocationJson !== 'undefined') {
        var userLocation = jQuery.parseJSON(userLocationJson);
        if ($('.zip-field').length && userLocation.hasOwnProperty('postal')) {
          $('.zip-field').val(userLocation.postal);
        }
      }

    }
  };

})(jQuery);
<commit_msg>UIV-1630 Added extra condition for empty user location-cookie<commit_after>/**
 * @file
 * Js behavior for the mailing forms.
 */

(function($) {

  /**
   * Attach the behavior.
   */
  Drupal.behaviors.culturefeed_mailing = {
    attach: function (context, settings) {

      // If a userlocation is known, set the default zip value.
      var userLocationJson = $.cookie('Drupal.visitor.uitid.userLocation');
      if (typeof userLocationJson !== 'undefined') {
        var userLocation = jQuery.parseJSON(userLocationJson);
        if (userLocation) {
          if ($('.zip-field').length && userLocation.hasOwnProperty('postal')) {
            $('.zip-field').val(userLocation.postal);
          }
        }
      }

    }
  };

})(jQuery);
<|endoftext|>


<commit_before>/**
 * Copyright 2020 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  Action,
  StateProperty,
} from '../../../extensions/amp-story/1.0/amp-story-store-service';
import {CSS} from '../../../build/amp-story-panning-media-0.1.css';
import {CommonSignals} from '../../../src/common-signals';
import {Layout} from '../../../src/layout';
import {Services} from '../../../src/services';
import {closest, whenUpgradedToCustomElement} from '../../../src/dom';
import {deepEquals} from '../../../src/json';
import {dev, user} from '../../../src/log';
import {setImportantStyles} from '../../../src/style';

/** @const {string} */
const TAG = 'AMP_STORY_PANNING_MEDIA';

/** @const {string}  */
const DURATION_MS = 1000;

/**
 * Position values used to animate between components.
 * x: (optional) Percentage between [-50; 50]
 * y: (optional) Percentage between [-50; 50]
 * zoom: 0 is not visible. 1 fills the viewport vertically.
 * @typedef {{
 *   x: float,
 *   y: float,
 *   zoom: float,
 * }}
 */
export let panningMediaPositionDef;

export class AmpStoryPanningMedia extends AMP.BaseElement {
  /** @param {!AmpElement} element */
  constructor(element) {
    super(element);

    /** @private {?Element} */
    this.element_ = element;

    /** @private {?Element} The element that is transitioned. */
    this.ampImgEl_ = null;

    /** @private {?panningMediaPositionDef} Position to animate to. */
    this.animateTo_ = {};

    /** @private {?panningMediaPositionDef} Current animation state. */
    this.animationState_ = {};

    /** @private {?../../../extensions/amp-story/1.0/amp-story-store-service.AmpStoryStoreService} */
    this.storeService_ = null;

    /** @private {?string} */
    this.pageId_ = null;

    /** @private {boolean} */
    this.isOnActivePage_ = false;

    /** @private {?number} Distance from active page. */
    this.distance_ = null;

    /** @private {?string} */
    this.groupId_ = null;
  }

  /** @override */
  buildCallback() {
    this.animateTo_ = {
      x: parseFloat(this.element_.getAttribute('x')) || 0,
      y: parseFloat(this.element_.getAttribute('y')) || 0,
      zoom: parseFloat(this.element_.getAttribute('zoom')) || 1,
    };
    return Services.storyStoreServiceForOrNull(this.win).then(
      (storeService) => {
        this.storeService_ = storeService;
      }
    );
  }

  /** @override */
  layoutCallback() {
    this.ampImgEl_ = dev().assertElement(
      this.element_.querySelector('amp-img')
    );
    this.groupId_ =
      this.element_.getAttribute('group-id') ||
      this.ampImgEl_.getAttribute('src');

    this.initializeListeners_();
    return whenUpgradedToCustomElement(this.ampImgEl_)
      .then(() => this.ampImgEl_.signals().whenSignal(CommonSignals.LOAD_END))
      .then(() => {
        const imgEl = dev().assertElement(this.element_.querySelector('img'));
        // Remove layout="fill" classes so image is not clipped.
        imgEl.classList = '';
        // Centers the amp-img horizontally. The image does not load if this is done in CSS.
        // TODO(#31515): Handle base zoom of aspect ratio wider than image
        setImportantStyles(this.ampImgEl_, {
          left: 'auto',
          right: 'auto',
        });
      })
      .catch(() => user().error(TAG, 'Failed to load the amp-img.'));
  }

  /** @private */
  initializeListeners_() {
    this.storeService_.subscribe(
      StateProperty.CURRENT_PAGE_ID,
      (currPageId) => {
        this.isOnActivePage_ = currPageId === this.getPageId_();
        this.onPageNavigation_();
      },
      true /** callToInitialize */
    );
    this.storeService_.subscribe(
      StateProperty.PANNING_MEDIA_STATE,
      (panningMediaState) => this.onPanningMediaStateChange_(panningMediaState),
      true /** callToInitialize */
    );
    // Mutation observer for distance attribute
    const config = {attributes: true, attributeFilter: ['distance']};
    const callback = (mutationsList) => {
      this.distance_ = parseInt(
        mutationsList[0].target.getAttribute('distance'),
        10
      );
    };
    const observer = new MutationObserver(callback);
    this.getPage_() && observer.observe(this.getPage_(), config);
  }

  /** @private */
  onPageNavigation_() {
    if (this.isOnActivePage_) {
      this.animate_();
    }
  }

  /**
   * Animates from current position to active components position.
   * @private
   */
  animate_() {
    const startPos =
      this.storeService_.get(StateProperty.PANNING_MEDIA_STATE)[
        this.groupId_
      ] || this.animateTo_;

    const easeInOutQuad = (val) =>
      val < 0.5 ? 2 * val * val : 1 - Math.pow(-2 * val + 2, 2) / 2;

    let startTime;
    const nextFrame = (currTime) => {
      if (!startTime) {
        startTime = currTime;
      }
      const elapsedTime = currTime - startTime;
      if (elapsedTime < DURATION_MS) {
        const {x, y, zoom} = this.animateTo_;
        const easing = easeInOutQuad(elapsedTime / DURATION_MS);
        this.storeService_.dispatch(Action.ADD_PANNING_MEDIA_STATE, {
          [this.groupId_]: {
            x: startPos.x + (x - startPos.x) * easing,
            y: startPos.y + (y - startPos.y) * easing,
            zoom: startPos.zoom + (zoom - startPos.zoom) * easing,
          },
        });
        // Only call loop again if on active page.
        if (this.isOnActivePage_) {
          requestAnimationFrame(nextFrame);
        }
      } else {
        this.storeService_.dispatch(Action.ADD_PANNING_MEDIA_STATE, {
          [this.groupId_]: this.animateTo_,
        });
      }
    };
    requestAnimationFrame(nextFrame);
  }

  /**
   * @private
   * @param {!Object<string, string>} panningMediaState
   */
  onPanningMediaStateChange_(panningMediaState) {
    if (
      this.distance_ <= 1 &&
      panningMediaState[this.groupId_] &&
      // Prevent update if value is same as previous value.
      // This happens when 2 or more components are on the same page.
      !deepEquals(this.animationState_, panningMediaState[this.groupId_])
    ) {
      this.animationState_ = panningMediaState[this.groupId_];
      this.updateTransform_();
    }
  }

  /**
   * @private
   * @return {!Promise}
   */
  updateTransform_() {
    const {x, y, zoom} = this.animationState_;
    return this.mutateElement(() => {
      setImportantStyles(this.ampImgEl_, {
        transform: `translate3d(${x}%, ${y}%, ${(zoom - 1) / zoom}px)`,
      });
    });
  }

  /**
   * @private
   * @return {string} the page id
   */
  getPageId_() {
    if (this.pageId_ == null) {
      this.pageId_ = this.getPage_().getAttribute('id');
    }
    return this.pageId_;
  }

  /**
   * @private
   * @return {?Element} the parent amp-story-page
   */
  getPage_() {
    return closest(
      dev().assertElement(this.element),
      (el) => el.tagName.toLowerCase() === 'amp-story-page'
    );
  }

  /** @override */
  isLayoutSupported(layout) {
    return layout == Layout.FILL;
  }
}

AMP.extension('amp-story-panning-media', '0.1', (AMP) => {
  AMP.registerElement('amp-story-panning-media', AmpStoryPanningMedia, CSS);
});
<commit_msg>Early return to not animate (#32368)<commit_after>/**
 * Copyright 2020 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  Action,
  StateProperty,
} from '../../../extensions/amp-story/1.0/amp-story-store-service';
import {CSS} from '../../../build/amp-story-panning-media-0.1.css';
import {CommonSignals} from '../../../src/common-signals';
import {Layout} from '../../../src/layout';
import {Services} from '../../../src/services';
import {closest, whenUpgradedToCustomElement} from '../../../src/dom';
import {deepEquals} from '../../../src/json';
import {dev, user} from '../../../src/log';
import {setImportantStyles} from '../../../src/style';

/** @const {string} */
const TAG = 'AMP_STORY_PANNING_MEDIA';

/** @const {string}  */
const DURATION_MS = 1000;

/**
 * Position values used to animate between components.
 * x: (optional) Percentage between [-50; 50]
 * y: (optional) Percentage between [-50; 50]
 * zoom: 0 is not visible. 1 fills the viewport vertically.
 * @typedef {{
 *   x: float,
 *   y: float,
 *   zoom: float,
 * }}
 */
export let panningMediaPositionDef;

export class AmpStoryPanningMedia extends AMP.BaseElement {
  /** @param {!AmpElement} element */
  constructor(element) {
    super(element);

    /** @private {?Element} */
    this.element_ = element;

    /** @private {?Element} The element that is transitioned. */
    this.ampImgEl_ = null;

    /** @private {?panningMediaPositionDef} Position to animate to. */
    this.animateTo_ = {};

    /** @private {?panningMediaPositionDef} Current animation state. */
    this.animationState_ = {};

    /** @private {?../../../extensions/amp-story/1.0/amp-story-store-service.AmpStoryStoreService} */
    this.storeService_ = null;

    /** @private {?string} */
    this.pageId_ = null;

    /** @private {boolean} */
    this.isOnActivePage_ = false;

    /** @private {?number} Distance from active page. */
    this.distance_ = null;

    /** @private {?string} */
    this.groupId_ = null;
  }

  /** @override */
  buildCallback() {
    this.animateTo_ = {
      x: parseFloat(this.element_.getAttribute('x')) || 0,
      y: parseFloat(this.element_.getAttribute('y')) || 0,
      zoom: parseFloat(this.element_.getAttribute('zoom')) || 1,
    };
    return Services.storyStoreServiceForOrNull(this.win).then(
      (storeService) => {
        this.storeService_ = storeService;
      }
    );
  }

  /** @override */
  layoutCallback() {
    this.ampImgEl_ = dev().assertElement(
      this.element_.querySelector('amp-img')
    );
    this.groupId_ =
      this.element_.getAttribute('group-id') ||
      this.ampImgEl_.getAttribute('src');

    this.initializeListeners_();
    return whenUpgradedToCustomElement(this.ampImgEl_)
      .then(() => this.ampImgEl_.signals().whenSignal(CommonSignals.LOAD_END))
      .then(() => {
        const imgEl = dev().assertElement(this.element_.querySelector('img'));
        // Remove layout="fill" classes so image is not clipped.
        imgEl.classList = '';
        // Centers the amp-img horizontally. The image does not load if this is done in CSS.
        // TODO(#31515): Handle base zoom of aspect ratio wider than image
        setImportantStyles(this.ampImgEl_, {
          left: 'auto',
          right: 'auto',
        });
      })
      .catch(() => user().error(TAG, 'Failed to load the amp-img.'));
  }

  /** @private */
  initializeListeners_() {
    this.storeService_.subscribe(
      StateProperty.CURRENT_PAGE_ID,
      (currPageId) => {
        this.isOnActivePage_ = currPageId === this.getPageId_();
        this.onPageNavigation_();
      },
      true /** callToInitialize */
    );
    this.storeService_.subscribe(
      StateProperty.PANNING_MEDIA_STATE,
      (panningMediaState) => this.onPanningMediaStateChange_(panningMediaState),
      true /** callToInitialize */
    );
    // Mutation observer for distance attribute
    const config = {attributes: true, attributeFilter: ['distance']};
    const callback = (mutationsList) => {
      this.distance_ = parseInt(
        mutationsList[0].target.getAttribute('distance'),
        10
      );
    };
    const observer = new MutationObserver(callback);
    this.getPage_() && observer.observe(this.getPage_(), config);
  }

  /** @private */
  onPageNavigation_() {
    if (this.isOnActivePage_) {
      this.animate_();
    }
  }

  /**
   * Animates from current position to active components position.
   * @private
   */
  animate_() {
    const startPos = this.storeService_.get(StateProperty.PANNING_MEDIA_STATE)[
      this.groupId_
    ];

    // Don't animate if first instance of group or prefers-reduced-motion.
    if (!startPos || this.prefersReducedMotion_()) {
      this.storeService_.dispatch(Action.ADD_PANNING_MEDIA_STATE, {
        [this.groupId_]: this.animateTo_,
      });
      return;
    }

    const easeInOutQuad = (val) =>
      val < 0.5 ? 2 * val * val : 1 - Math.pow(-2 * val + 2, 2) / 2;

    let startTime;
    const nextFrame = (currTime) => {
      if (!startTime) {
        startTime = currTime;
      }
      const elapsedTime = currTime - startTime;
      if (elapsedTime < DURATION_MS) {
        const {x, y, zoom} = this.animateTo_;
        const easing = easeInOutQuad(elapsedTime / DURATION_MS);
        this.storeService_.dispatch(Action.ADD_PANNING_MEDIA_STATE, {
          [this.groupId_]: {
            x: startPos.x + (x - startPos.x) * easing,
            y: startPos.y + (y - startPos.y) * easing,
            zoom: startPos.zoom + (zoom - startPos.zoom) * easing,
          },
        });
        // Only call loop again if on active page.
        if (this.isOnActivePage_) {
          requestAnimationFrame(nextFrame);
        }
      } else {
        this.storeService_.dispatch(Action.ADD_PANNING_MEDIA_STATE, {
          [this.groupId_]: this.animateTo_,
        });
      }
    };
    requestAnimationFrame(nextFrame);
  }

  /**
   * @private
   * @param {!Object<string, string>} panningMediaState
   */
  onPanningMediaStateChange_(panningMediaState) {
    if (
      this.distance_ <= 1 &&
      panningMediaState[this.groupId_] &&
      // Prevent update if value is same as previous value.
      // This happens when 2 or more components are on the same page.
      !deepEquals(this.animationState_, panningMediaState[this.groupId_])
    ) {
      this.animationState_ = panningMediaState[this.groupId_];
      this.updateTransform_();
    }
  }

  /**
   * @private
   * @return {!Promise}
   */
  updateTransform_() {
    const {x, y, zoom} = this.animationState_;
    return this.mutateElement(() => {
      setImportantStyles(this.ampImgEl_, {
        transform: `translate3d(${x}%, ${y}%, ${(zoom - 1) / zoom}px)`,
      });
    });
  }

  /**
   * @private
   * @return {string} the page id
   */
  getPageId_() {
    if (this.pageId_ == null) {
      this.pageId_ = this.getPage_().getAttribute('id');
    }
    return this.pageId_;
  }

  /**
   * @private
   * @return {?Element} the parent amp-story-page
   */
  getPage_() {
    return closest(
      dev().assertElement(this.element),
      (el) => el.tagName.toLowerCase() === 'amp-story-page'
    );
  }

  /**
   * Whether the device opted in prefers-reduced-motion.
   * @return {boolean}
   * @private
   */
  prefersReducedMotion_() {
    return this.win.matchMedia('(prefers-reduced-motion: reduce)').matches;
  }

  /** @override */
  isLayoutSupported(layout) {
    return layout == Layout.FILL;
  }
}

AMP.extension('amp-story-panning-media', '0.1', (AMP) => {
  AMP.registerElement('amp-story-panning-media', AmpStoryPanningMedia, CSS);
});
<|endoftext|>


<commit_before>let path = require('path'),
  glob = require('glob');

const shaders = glob.sync(path.join(__dirname, 'src', 'renderers', 'webgl', 'shaders', '*.glsl'));

const entry = {};

shaders.forEach(function (p) {
  entry[path.basename(p, '.glsl')] = p;
});

module.exports = {
  mode: 'production',
  entry,
  output: {
    path: path.join(__dirname, 'renderers', 'webgl', 'shaders'),
    filename: '[name].glsl',
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.glsl$/,
        exclude: /node_modules/,
        loader: 'raw-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
    ],
  },
};
<commit_msg>Dropping useless rule<commit_after>let path = require('path'),
  glob = require('glob');

const shaders = glob.sync(path.join(__dirname, 'src', 'renderers', 'webgl', 'shaders', '*.glsl'));

const entry = {};

shaders.forEach(function (p) {
  entry[path.basename(p, '.glsl')] = p;
});

module.exports = {
  mode: 'production',
  entry,
  output: {
    path: path.join(__dirname, 'renderers', 'webgl', 'shaders'),
    filename: '[name].glsl',
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.glsl$/,
        exclude: /node_modules/,
        loader: 'raw-loader',
      },
    ],
  },
};
<|endoftext|>


<commit_before>;(function ($, document, window) {
    'use strict';

    /**
     * Chart initializer.
     */
    function Chart(chart)
    {
        this.id = chart.options.element;
        this.type = chart.chart;
        this.options = chart.options;
        this.ajax = chart.ajax;

        this.init();

        return this;
    }

    Chart.prototype = {

        /**
         * Initialize method.
         *
         * @return {undefined}
         */
        init: function () {
            if (0 < this.options.data.length) {
                this.draw();
            } else {
                this.getData();
            }
        },

        /**
         * Draw method.
         *
         * @return {undefined}
         */
        draw: function () {
            var that = this;

            switch (this.type) {
                case 'barChart':
                    Morris.Bar(this.options);
                    break;
                case 'lineChart':
                    Morris.Line(this.options);
                    break;
                case 'donutChart':
                    Morris.Donut(this.options);
                    break;
                case 'knobChart':
                    $('.knob-graph').knob({
                        'width': 85,
                        'height': 85,
                        'linecap': 'round',
                        'thickness': '.2',
                        'readOnly': true,
                        'cursor': false,
                        'draw': function () {
                            var colorGradients = [
                                '#05497d', '#043b64', '#032c4c', //blue
                                '#1e3302', '#2c4c03', '#3b6404', '#497d05', '#579606', '#66ae07', '#74c708', //green
                                '#a7a60e', '#bfbd0f', '#d6d411', //yellow
                                '#a70e0f', '#bf0f11', '#d61113', '#ec1517', //red
                            ];
                            var randomColor = Math.floor(Math.random() * colorGradients.length);
                            this.o.fgColor = colorGradients[randomColor];
                        }
                    });
                    break;
                case 'funnelChart':
                    this.options.data.sort(function (a, b) {
                        return (a.value < b.value) ? 1 : ((b.value < a.value) ? -1 : 0);
                    });

                    var d3chart = new D3Funnel('#' + this.id);
                    d3chart.draw(this.options.data, {
                        block: {
                            dynamicHeight: true
                        }
                    });
                    break;
            }
        },

        getData: function () {
            var that = this;

            if (!this.ajax) {
                console.log('No ajax information, cannot fetch chart data.');

                return;
            }

            var placeholder = this.getPlaceholder();
            // add loading placeholder
            $('#' + this.id).append(placeholder.element);

            $.ajax({
                url: this.ajax.url,
                method: 'GET',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    Authorization: 'Bearer ' + this.ajax.token
                },
                success: function (data, textStatus, jqXHR) {
                    // remove placeholder
                    $('#' + placeholder.id).remove();

                    var chartData = that.normalizeData(data.data);

                    that.options.data = chartData;

                    that.draw();
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                }
            });
        },

        normalizeData: function (data) {
            var that = this;

            switch (this.type) {
                case 'funnelChart':
                case 'donutChart':
                    data.forEach(function (v, k) {
                        var label = data[k][that.options.xkey[0]];
                        var value = data[k][that.options.ykeys[0]];
                        data[k].label = $('
').html(label).text();
                        data[k].value = parseInt(value);
                    });
                    break;
                case 'barChart':
                    data.forEach(function (v, k) {
                        var key = that.options.xkey[0];
                        var value = data[k][key];
                        data[k][key] = $('
').html(value).text();
                    });
                    break;
            }

            return data;
        },

        getPlaceholder: function () {
            var result = {};

            // random id
            result.id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
            result.element = $('
', {id: result.id, style: 'height:350px;padding-top:160px;'});
            result.element.html(
                '
 Processing...
'
            );

            return result;
        }
    };

    if (!window.chartsData) {
        console.log('No charts to initialize');

        return;
    }

    var charts = [];
    window.chartsData.forEach(function (data) {
        if ( typeof data.options == 'undefined') {
            return;
        }
        var id = data.options.element;
        var isVisible = (!$('a[href="#' + id + '"]').data('toggle') || $('#' + id).hasClass('active'));

        // initialize visible charts
        if (isVisible) {
            // init chart
            new Chart(data);
            charts.push('#' + data.options.element);
        }
    });

    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        var chartId = $(e.target).attr('href');

        // chart already initialized
        if (-1 !== charts.indexOf(chartId)) {
            return;
        }

        // get chart data
        var data = $.grep(window.chartsData, function (v) {
            return '#' + v.options.element === chartId;
        });

        if (!data.length) {
            return;
        }

        data = data[0];
        // init chart
        new Chart(data);
        charts.push('#' + data.options.element);
    });

})(jQuery, document, window);
<commit_msg>HTML escape graph data (task #8668)<commit_after>;(function ($, document, window) {
    'use strict';

    /**
     * Chart initializer.
     */
    function Chart(chart)
    {
        this.id = chart.options.element;
        this.type = chart.chart;
        this.options = chart.options;
        this.ajax = chart.ajax;

        this.init();

        return this;
    }

    Chart.prototype = {

        /**
         * Initialize method.
         *
         * @return {undefined}
         */
        init: function () {
            if (0 < this.options.data.length) {
                this.options.data = this.escapeData(this.options.data);
                this.draw();
            } else {
                this.getData();
            }
        },

        escapeData: function (data) {
            var that = this;

            let label = '';
            switch (this.type) {
                case 'funnelChart':
                case 'donutChart':
                    label = 'label';
                    break;
                case 'barChart':
                    label = that.options.xkey[0];
                    break;
            }

            data.forEach(function (item) {
                const doc = new DOMParser().parseFromString(item[label], 'text/html');
                // strip html tags
                let value = doc.body.textContent || '';
                // strip   html entities
                value = value.replace(/\u00a0/g, '');
                value = value ? value : 'N/A';
                item[label] = value;
            });

            return data;
        },

        /**
         * Draw method.
         *
         * @return {undefined}
         */
        draw: function () {
            var that = this;

            switch (this.type) {
                case 'barChart':
                    Morris.Bar(this.options);
                    break;
                case 'lineChart':
                    Morris.Line(this.options);
                    break;
                case 'donutChart':
                    Morris.Donut(this.options);
                    break;
                case 'knobChart':
                    $('.knob-graph').knob({
                        'width': 85,
                        'height': 85,
                        'linecap': 'round',
                        'thickness': '.2',
                        'readOnly': true,
                        'cursor': false,
                        'draw': function () {
                            var colorGradients = [
                                '#05497d', '#043b64', '#032c4c', //blue
                                '#1e3302', '#2c4c03', '#3b6404', '#497d05', '#579606', '#66ae07', '#74c708', //green
                                '#a7a60e', '#bfbd0f', '#d6d411', //yellow
                                '#a70e0f', '#bf0f11', '#d61113', '#ec1517', //red
                            ];
                            var randomColor = Math.floor(Math.random() * colorGradients.length);
                            this.o.fgColor = colorGradients[randomColor];
                        }
                    });
                    break;
                case 'funnelChart':
                    this.options.data.sort(function (a, b) {
                        return (a.value < b.value) ? 1 : ((b.value < a.value) ? -1 : 0);
                    });

                    var d3chart = new D3Funnel('#' + this.id);
                    d3chart.draw(this.options.data, {
                        block: {
                            dynamicHeight: true
                        }
                    });
                    break;
            }
        },

        getData: function () {
            var that = this;

            if (!this.ajax) {
                console.log('No ajax information, cannot fetch chart data.');

                return;
            }

            var placeholder = this.getPlaceholder();
            // add loading placeholder
            $('#' + this.id).append(placeholder.element);

            $.ajax({
                url: this.ajax.url,
                method: 'GET',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    Authorization: 'Bearer ' + this.ajax.token
                },
                success: function (data, textStatus, jqXHR) {
                    // remove placeholder
                    $('#' + placeholder.id).remove();

                    var chartData = that.normalizeData(data.data);

                    that.options.data = chartData;

                    that.draw();
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                }
            });
        },

        normalizeData: function (data) {
            var that = this;

            switch (this.type) {
                case 'funnelChart':
                case 'donutChart':
                    data.forEach(function (v, k) {
                        var label = data[k][that.options.xkey[0]];
                        var value = data[k][that.options.ykeys[0]];
                        data[k].label = $('
').html(label).text();
                        data[k].value = parseInt(value);
                    });
                    break;
                case 'barChart':
                    data.forEach(function (v, k) {
                        var key = that.options.xkey[0];
                        var value = data[k][key];
                        data[k][key] = $('
').html(value).text();
                    });
                    break;
            }

            return data;
        },

        getPlaceholder: function () {
            var result = {};

            // random id
            result.id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
            result.element = $('
', {id: result.id, style: 'height:350px;padding-top:160px;'});
            result.element.html(
                '
 Processing...
'
            );

            return result;
        }
    };

    if (!window.chartsData) {
        console.log('No charts to initialize');

        return;
    }

    var charts = [];
    window.chartsData.forEach(function (data) {
        if ( typeof data.options == 'undefined') {
            return;
        }
        var id = data.options.element;
        var isVisible = (!$('a[href="#' + id + '"]').data('toggle') || $('#' + id).hasClass('active'));

        // initialize visible charts
        if (isVisible) {
            // init chart
            new Chart(data);
            charts.push('#' + data.options.element);
        }
    });

    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        var chartId = $(e.target).attr('href');

        // chart already initialized
        if (-1 !== charts.indexOf(chartId)) {
            return;
        }

        // get chart data
        var data = $.grep(window.chartsData, function (v) {
            return '#' + v.options.element === chartId;
        });

        if (!data.length) {
            return;
        }

        data = data[0];
        // init chart
        new Chart(data);
        charts.push('#' + data.options.element);
    });

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


<commit_before>YUI.add('text-annotation', function (Y) {

    var Range = function (start, end) {
        this.start = start;
        this.end = end;
    };
    var Name = function (namespace, localName) {
        this.namespace = namespace;
        this.localName = localName;
    };
    var Text = function (id, type, contentLength, range, content) {
        this.id = id;
        this.type = type;
        this.contentLength = contentLength;
        this.range = range || new Range(0, contentLength);
        this.content = content || "";
    };
    var TextTarget = function (text, range) {
        this.text = text;
        this.range = range;
    };

    var UNKNOWN_NAME = new Name(null, "");
    var Annotation = function (name, data, targets) {
        this.name = name || UNKNOWN_NAME;
        this.data = data || {};
        this.targets = targets || [];
    };
    Y.extend(Annotation, Object, {
        targetIn: function(text) {
            return Y.Array.find(this.targets, function(t) {
                return (t.text === text);
            });
        }
    });

    Y.extend(Text, Object, {
        partition: function () {
            var offsets = [];
            Y.Array.each(this.annotations, function (a) {
                Y.Array.each(a.targets, function(t) {
                    if (t.text == this) {
                        var range = t.range;
                        if (offsets.indexOf(range.start) < 0) offsets.push(range.start);
                        if (offsets.indexOf(range.end) < 0) offsets.push(range.end);
                    }
                }, this);
            }, this);
            offsets.sort(function (a, b) {
                return a - b;
            });

            if (offsets.length == 0 || offsets[0] > this.range.start) offsets.unshift(this.range.start);
            if (offsets.length == 1 || offsets[offsets.length - 1] < this.range.end) offsets.push(this.range.end);

            var partitions = [];
            var start = -1;
            Y.Array.each(offsets, function (end) {
                if (start >= 0) partitions.push(new Range(start, end));
                start = end;
            });
            return partitions;
        },
        find: function(range) {
            var result = [];
            this._searchRange(this.rangeIndex._root, range, result);
            return result;
        },
        _searchRange: function(node, range, result) {
            // Don't search nodes that don't exist
            if (node === null) {
                return;
            }

            // If range is to the right of the rightmost point of any interval
            // in this node and all children, there won't be any matches.
            if (range.start >= node.maxEnd) {
                return;
            }

            // Search left children
            if (node.left !== null) {
                this._searchRange(node.left, range, result);
            }

            // Check this node
            if (node.key.overlapsWith(range)) {
                Y.Array.each(node.values, function(v) {
                    result.push(v);
                });
            }

            // If range is to the left of the start of this interval,
            // then it can't be in any child to the right.
            if (range.end <= node.key.start) {
                return;
            }

            // Otherwise, search right children
            if (node.right !== null) {
                this._searchRange(node.right, range, result);
            }
        }
    }, {
        create: function (data) {
            var text = new Text(data.text.id, data.text.t, data.text.l, data.textRange, data.textContent), names = {};
            Y.Object.each(data.names, function (v, k) {
                names[k] = new Name(v[0], v[1]);
            });
            text.annotations = Y.Array.map(data.annotations, function (a) {
                return new Annotation(names[a.n], a.d, Y.Array.map(a.t, function (target) {
                    return new TextTarget((target[2] == text.id ? text : target[2]), new Range(target[0], target[1]));
                }));
            });
            text.rangeIndex = new Y.Faust.RBTree(Range.sort, function(a) {
                return a.targetIn(text).range;
            });
            Y.Array.each(text.annotations, function(a) {
                text.rangeIndex.insert(a);
            });
            (function(treeNode) {
                if (treeNode === null) {
                    return 0;
                } else {
                    treeNode.maxEnd = Math.max(treeNode.key.end, arguments.callee(treeNode.left), arguments.callee(treeNode.right));
                    return treeNode.maxEnd;
                }
            })(text.rangeIndex._root);
            return text;
        }
    });
    Y.extend(Name, Object, {
        toString: function () {
            return (this.namespace == null ? "" : "{" + this.namespace + "}") + this.localName;
        },
        fromString: function (str) {
            var firstBrace = str.indexOf("{");
            if (firstBrace < 0) {
                return new NS.Name(null, str);
            }
            var secondBrace = str.indexOf("}");
            if (secondBrace < firstBrace || secondBrace >= (str.length - 1)) {
                Y.error("Invalid Name", str, { throwFail: true });
            }

            return new NS.Name(str.substring(firstBrace + 1, secondBrace), str.substring(secondBrace + 1))
        }
    });
    Y.extend(Range, Object, {
        length: function () {
            return (this.end - this.start);
        },
        precedes: function (other) {
            return (this.end <= other.start);
        },
        overlapsWith: function (other) {
            return (this.start < other.end) && (this.end > other.start);
        },
        of: function (text) {
            return text.substring(this.start, this.end);
        },
        equalsStartOf: function (other) {
            return  (this.start == other.start) && (this.end == other.start);
        },
        amountOfOverlapWith: function (other) {
            return (Math.min(this.end, other.end) - Math.max(this.start, other.start));
        },
        fromId: function (str) {
            var components = str.replace("r", "").split("-");
            return new Range(parseInt(components[0]), parseInt(components[1]));
        },
        toId: function () {
            return "r" + this.start.toString() + "-" + this.end.toString();
        },
        toString: function () {
            return "[" + this.start + ", " + this.end + "]";
        }
    }, {
        sort: function (ra, rb) {
            return (ra.start == rb.start ? (rb.end - ra.end) : (ra.start - rb.start));
        }
    });

    Y.mix(Y.namespace("Faust"), {
        Text: Text,
        Name: Name,
        Range: Range,
        TextTarget: TextTarget,
        Annotation: Annotation
    });
}, '0.0', {
    requires: ["text-index", "base", "substitute", "array-extras", "io", "json"]
});<commit_msg>bug fix for empty ranges<commit_after>YUI.add('text-annotation', function (Y) {

    var Range = function (start, end) {
        this.start = start;
        this.end = end;
    };
    var Name = function (namespace, localName) {
        this.namespace = namespace;
        this.localName = localName;
    };
    var Text = function (id, type, contentLength, range, content) {
        this.id = id;
        this.type = type;
        this.contentLength = contentLength;
        this.range = range || new Range(0, contentLength);
        this.content = content || "";
    };
    var TextTarget = function (text, range) {
        this.text = text;
        this.range = range;
    };

    var UNKNOWN_NAME = new Name(null, "");
    var Annotation = function (name, data, targets) {
        this.name = name || UNKNOWN_NAME;
        this.data = data || {};
        this.targets = targets || [];
    };
    Y.extend(Annotation, Object, {
        targetIn: function(text) {
            return Y.Array.find(this.targets, function(t) {
                return (t.text === text);
            });
        }
    });

    Y.extend(Text, Object, {
        partition: function () {
            var offsets = [];
            Y.Array.each(this.annotations, function (a) {
                Y.Array.each(a.targets, function(t) {
                    if (t.text == this) {
                        var range = t.range;
                        if (offsets.indexOf(range.start) < 0) offsets.push(range.start);
                        if (offsets.indexOf(range.end) < 0) offsets.push(range.end);
                    }
                }, this);
            }, this);
            offsets.sort(function (a, b) {
                return a - b;
            });

            if (offsets.length == 0 || offsets[0] > this.range.start) offsets.unshift(this.range.start);
            if (offsets.length == 1 || offsets[offsets.length - 1] < this.range.end) offsets.push(this.range.end);

            var partitions = [];
            var start = -1;
            Y.Array.each(offsets, function (end) {
                if (start >= 0) partitions.push(new Range(start, end));
                start = end;
            });
            return partitions;
        },
        find: function(range) {
            var result = [];
            this._searchRange(this.rangeIndex._root, range, result);
            return result;
        },
        _searchRange: function(node, range, result) {
            // Don't search nodes that don't exist
            if (node === null) {
                return;
            }

            // If range is to the right of the rightmost point of any interval
            // in this node and all children, there won't be any matches.
            if (range.start > node.maxEnd) {
                return;
            }

            // Search left children
            if (node.left !== null) {
                this._searchRange(node.left, range, result);
            }

            // Check this node
            if (node.key.overlapsWith(range) || range.includes(node.key)) {
                Y.Array.each(node.values, function(v) {
                    result.push(v);
                });
            }

            // If range is to the left of the start of this interval,
            // then it can't be in any child to the right.
            if (range.end < node.key.start) {
                return;
            }

            // Otherwise, search right children
            if (node.right !== null) {
                this._searchRange(node.right, range, result);
            }
        }
    }, {
        create: function (data) {
            var text = new Text(data.text.id, data.text.t, data.text.l, data.textRange, data.textContent), names = {};
            Y.Object.each(data.names, function (v, k) {
                names[k] = new Name(v[0], v[1]);
            });
            text.annotations = Y.Array.map(data.annotations, function (a) {
                return new Annotation(names[a.n], a.d, Y.Array.map(a.t, function (target) {
                    return new TextTarget((target[2] == text.id ? text : target[2]), new Range(target[0], target[1]));
                }));
            });
            text.rangeIndex = new Y.Faust.RBTree(Range.sort, function(a) {
                return a.targetIn(text).range;
            });
            Y.Array.each(text.annotations, function(a) {
                text.rangeIndex.insert(a);
            });
            (function(treeNode) {
                if (treeNode === null) {
                    return 0;
                } else {
                    treeNode.maxEnd = Math.max(treeNode.key.end, arguments.callee(treeNode.left), arguments.callee(treeNode.right));
                    return treeNode.maxEnd;
                }
            })(text.rangeIndex._root);
            return text;
        }
    });
    Y.extend(Name, Object, {
        toString: function () {
            return (this.namespace == null ? "" : "{" + this.namespace + "}") + this.localName;
        },
        fromString: function (str) {
            var firstBrace = str.indexOf("{");
            if (firstBrace < 0) {
                return new NS.Name(null, str);
            }
            var secondBrace = str.indexOf("}");
            if (secondBrace < firstBrace || secondBrace >= (str.length - 1)) {
                Y.error("Invalid Name", str, { throwFail: true });
            }

            return new NS.Name(str.substring(firstBrace + 1, secondBrace), str.substring(secondBrace + 1))
        }
    });
    Y.extend(Range, Object, {
        length: function () {
            return (this.end - this.start);
        },
        precedes: function (other) {
            return (this.end <= other.start);
        },
        overlapsWith: function (other) {
            return ((this.start < other.end) && (this.end > other.start));
        },
        includes: function(other) {
            return (this.start <= other.start && this.end >= other.end);
        },
        of: function (text) {
            return text.substring(this.start, this.end);
        },
        equalsStartOf: function (other) {
            return  (this.start == other.start) && (this.end == other.start);
        },
        amountOfOverlapWith: function (other) {
            return (Math.min(this.end, other.end) - Math.max(this.start, other.start));
        },
        fromId: function (str) {
            var components = str.replace("r", "").split("-");
            return new Range(parseInt(components[0]), parseInt(components[1]));
        },
        toId: function () {
            return "r" + this.start.toString() + "-" + this.end.toString();
        },
        toString: function () {
            return "[" + this.start + ", " + this.end + "]";
        }
    }, {
        sort: function (ra, rb) {
            return (ra.start == rb.start ? (rb.end - ra.end) : (ra.start - rb.start));
        }
    });

    Y.mix(Y.namespace("Faust"), {
        Text: Text,
        Name: Name,
        Range: Range,
        TextTarget: TextTarget,
        Annotation: Annotation
    });
}, '0.0', {
    requires: ["text-index", "base", "substitute", "array-extras", "io", "json"]
});<|endoftext|>


<commit_before>//= require leaflet/routing-machine
//= require leaflet/lrm-mapzen
//= require map/map
//= require map/route
//= require map/form
//= require map/summary

const MapObj = new Map();
const RouteObj = new Route();
let FormObj;

/**************** REGISTERING EVENTS ****************/
// This function is triggered when a route is successfully calculated
MapObj.control.on('routesfound', function(e) {

  console.debug("Routes found");

  // enable autoRoute
  MapObj.control.options.autoRoute = true;

  // hides the route form
  FormObj.form.fadeOut();

  // waits 1 sec to get the route instructions and load it
  // into the sidebar
  setTimeout(function() {

    let summary = new Summary();

    // set route information
    $('#mode_icon').removeClass().addClass(summary.mode.icon);
    $('#mode_text').text(summary.mode.text);
    $('#distance').text(summary.distance);
    $('#time').text(summary.time);

    // get every route instruction
    var itinerary = $('.leaflet-routing-alt').find('tbody').find('tr');

    // load it into the sidebar table
    var $itinerarySidebar = $('#itinerary').find('table').find('tbody');
    $itinerarySidebar.html(itinerary);
    // get routes translations
    $itinerarySidebar.find('tr').each(function(index, instructionRow) {
      var $instruction = $(instructionRow).find('td').eq(1);

      $instruction.text(translateRoute($instruction.text()));

    });

    $('#itinerary').fadeIn();

  }, 300);

});

MapObj.control.on('routingerror', function() {
  // TODO Show message when it's not possible to calculate routes

});

/**************** POSITION ****************/

// get the user's current position
function getLocation(point) {
  try {
    navigator.geolocation.getCurrentPosition(function(position){
      positionSuccess(position, point);
    }, );
  } catch (error) {
    console.warn(error);
    alert("Recurso não disponível no seu browser.");
  }
}

// process the user's current position to create the route
function positionSuccess(position, point) {
  var location = {
    latlng: {
      lat: position.coords.latitude,
      lng: position.coords.longitude
    }
  }
  var inside_bounds = map.getBounds().contains(location.latlng);
  if(inside_bounds){
    if(point == 'origin'){
      routesFromHere(location);
    } else {
      routesToHere(location);
    }
  } else {
    alert("Ops... Parece que você não está no campus.");
  }

}

/**************** FORM ****************/

// loads the routes form into the sidebar
function loadRouteForm(data) {

  $("#sidebar").load("/map/routes", function() {

    $('.btn-reverse-route').on('click', function(e) {
      reverseRoute(e);
    });

    // instantiate route form elements when the page is loaded
    FormObj = new Form();

    fillFormRouteLocations(data);

    // when user clicks the button to use the current location in origin input
    FormObj.origin.parent().find('button').on('click', function() {
      getLocation('origin');
    });

    // when user clicks the button to use the current location in destination input
    FormObj.destination.parent().find('button').on('click', function() {
      getLocation('destination');
    });

    // calculate route when user clicks submit button
    FormObj.submit.on('click', function(e) {
      console.debug('Clicked submit button');
      // prevent default behavior
      e.preventDefault();

      // get route mode from the form and set into the control
      MapObj.control.options.router.options.costing = FormObj.mode.parent('.btn.active').find('input').val();

      var origin_latlng = FormObj.origin.val().split(',');
      var destination_latlng = FormObj.destination.val().split(',');

      console.info(origin_latlng);
      console.info(destination_latlng);

      if (origin_latlng != null && destination_latlng != null) {

        MapObj.control.spliceWaypoints(0, 1, origin_latlng);
        MapObj.control.spliceWaypoints(MapObj.control.getWaypoints().length - 1, 1, destination_latlng);

        // TODO refactor
        if (RouteObj.origin.marker == null) {
          MapObj.createMarker(Routeobj.origin, origin_latlng);
        } else {
          RouteObj.origin.marker.setLatLng(origin_latlng);
        }

        // TODO refactor
        if (RouteObj.destination.marker == null) {
          MapObj.createMarker(destination, destination_latlng);
        } else {
          RouteObj.destination.marker.setLatLng(destination_latlng);
        }

        console.debug("Calculate route!");
        MapObj.control.route();
      }

    });

    sidebar.show();
  });
}

/**************** ROUTES ****************/

function unLoadRoute() {
  sidebar.hide();

  // remove markers from map
  MapObj.removeMarker(RouteObj.origin);
  MapObj.removeMarker(RouteObj.destination);

  // removes route from map
  MapObj.control.spliceWaypoints(0, 2);

  // disable auto route
  MapObj.control.options.autoRoute = false;
}

// set values to location in the route form
// when sidebar is already loaded
function fillFormRouteLocations(data) {
  if ('origin' in data) {
    FormObj.origin.val(data.origin);
  }
  if ('destination' in data) {
    FormObj.destination.val(data.destination);
  }
}

function setRouteLocation(e, waypoint) {
  var lat = e.latlng.lat;
  var lng = e.latlng.lng;

  var data = {};
  data[waypoint.title] = lat + ", " + lng;

  if (sidebar.isVisible()) {
    fillFormRouteLocations(data);
  } else {
    loadRouteForm(data);
  }
  if (waypoint.marker == null) {
    MapObj.createMarker(waypoint, e.latlng);
  } else {
    waypoint.marker.setLatLng(e.latlng);
  }
};

// this is performed when user clicks "Rotas a partir daqui"
function routesFromHere(e) {
  setRouteLocation(e, RouteObj.origin);
  MapObj.control.spliceWaypoints(0, 1, e.latlng);
}

// this is performed when user clicks "Rotas para cá"
function routesToHere(e) {
  setRouteLocation(e, RouteObj.destination);
  MapObj.control.spliceWaypoints(MapObj.control.getWaypoints().length - 1, 1, e.latlng);
}

function reverseRoute(e) {
  e.preventDefault();

  // reverse waypoints to route
  var waypoints = MapObj.control.getWaypoints();
  MapObj.control.setWaypoints(waypoints.reverse());

  // NOTE reverse markers was so hard to figure out
  if (RouteObj.origin.marker != null && RouteObj.destination.marker == null) {
    console.log('Destination in blank.');
    MapObj.createMarker(RouteObj.destination, RouteObj.origin.marker.getLatLng());
    MapObj.removeMarker(RouteObj.origin);
  } else if (RouteObj.destination.marker != null && RouteObj.origin.marker == null) {
    console.log('Origin in blank');
    MapObj.createMarker(RouteObj.origin, RouteObj.destination.marker.getLatLng());
    MapObj.removeMarker(RouteObj.destination);
  }

  if (RouteObj.origin.marker != null && RouteObj.destination.marker != null) {
    var latlng = RouteObj.origin.marker.getLatLng();
    RouteObj.origin.marker.setLatLng(RouteObj.destination.marker.getLatLng());
    RouteObj.destination.marker.setLatLng(latlng);
  }

  var origin_latlng = FormObj.origin.val();
  var destination_latlng = FormObj.destination.val();

  // swap values in form
  FormObj.origin.val(destination_latlng);
  FormObj.destination.val(origin_latlng);

}
// TODO Require to fill out origin and destination in the form, before calculate route
// TODO Add button to create a new route
// TODO Suggest locations on whe form
// TODO Suggest locations on whe form
<commit_msg>Fixing lint errors on routes file.<commit_after>//= require leaflet/routing-machine
//= require leaflet/lrm-mapzen
//= require map/map
//= require map/route
//= require map/form
//= require map/summary

const MapObj = new Map();
const RouteObj = new Route();
let FormObj;

/**************** REGISTERING EVENTS ****************/
// This function is triggered when a route is successfully calculated
MapObj.control.on('routesfound', function(e) {

  console.debug("Routes found");

  // enable autoRoute
  MapObj.control.options.autoRoute = true;

  // hides the route form
  FormObj.form.fadeOut();

  // waits 1 sec to get the route instructions and load it
  // into the sidebar
  setTimeout(function() {

    let summary = new Summary();

    // set route information
    $('#mode_icon').removeClass().addClass(summary.mode.icon);
    $('#mode_text').text(summary.mode.text);
    $('#distance').text(summary.distance);
    $('#time').text(summary.time);

    // get every route instruction
    var itinerary = $('.leaflet-routing-alt').find('tbody').find('tr');

    // load it into the sidebar table
    var $itinerarySidebar = $('#itinerary').find('table').find('tbody');
    $itinerarySidebar.html(itinerary);
    // get routes translations
    $itinerarySidebar.find('tr').each(function(index, instructionRow) {
      var $instruction = $(instructionRow).find('td').eq(1);

      $instruction.text(translateRoute($instruction.text()));

    });

    $('#itinerary').fadeIn();

  }, 300);

});

MapObj.control.on('routingerror', function() {
  // TODO Show message when it's not possible to calculate routes

});

/**************** POSITION ****************/

// get the user's current position
function getLocation(point) {
  try {
    navigator.geolocation.getCurrentPosition(function(position){
      positionSuccess(position, point);
    }, );
  } catch (error) {
    console.warn(error);
    alert("Recurso não disponível no seu browser.");
  }
}

// process the user's current position to create the route
function positionSuccess(position, point) {
  var location = {
    latlng: {
      lat: position.coords.latitude,
      lng: position.coords.longitude
    }
  };
  var inside_bounds = map.getBounds().contains(location.latlng);
  if(inside_bounds){
    if(point == 'origin'){
      routesFromHere(location);
    } else {
      routesToHere(location);
    }
  } else {
    alert("Ops... Parece que você não está no campus.");
  }

}

/**************** FORM ****************/

// loads the routes form into the sidebar
function loadRouteForm(data) {

  $("#sidebar").load("/map/routes", function() {

    $('.btn-reverse-route').on('click', function(e) {
      reverseRoute(e);
    });

    // instantiate route form elements when the page is loaded
    FormObj = new Form();

    fillFormRouteLocations(data);

    // when user clicks the button to use the current location in origin input
    FormObj.origin.parent().find('button').on('click', function() {
      getLocation('origin');
    });

    // when user clicks the button to use the current location in destination input
    FormObj.destination.parent().find('button').on('click', function() {
      getLocation('destination');
    });

    // calculate route when user clicks submit button
    FormObj.submit.on('click', function(e) {
      console.debug('Clicked submit button');
      // prevent default behavior
      e.preventDefault();

      // get route mode from the form and set into the control
      MapObj.control.options.router.options.costing = FormObj.mode.parent('.btn.active').find('input').val();

      var origin_latlng = FormObj.origin.val().split(',');
      var destination_latlng = FormObj.destination.val().split(',');

      console.info(origin_latlng);
      console.info(destination_latlng);

      if (origin_latlng != null && destination_latlng != null) {

        MapObj.control.spliceWaypoints(0, 1, origin_latlng);
        MapObj.control.spliceWaypoints(MapObj.control.getWaypoints().length - 1, 1, destination_latlng);

        // TODO refactor
        if (RouteObj.origin.marker === null) {
          MapObj.createMarker(Routeobj.origin, origin_latlng);
        } else {
          RouteObj.origin.marker.setLatLng(origin_latlng);
        }

        // TODO refactor
        if (RouteObj.destination.marker === null) {
          MapObj.createMarker(destination, destination_latlng);
        } else {
          RouteObj.destination.marker.setLatLng(destination_latlng);
        }

        console.debug("Calculate route!");
        MapObj.control.route();
      }

    });

    sidebar.show();
  });
}

/**************** ROUTES ****************/

function unLoadRoute() {
  sidebar.hide();

  // remove markers from map
  MapObj.removeMarker(RouteObj.origin);
  MapObj.removeMarker(RouteObj.destination);

  // removes route from map
  MapObj.control.spliceWaypoints(0, 2);

  // disable auto route
  MapObj.control.options.autoRoute = false;
}

// set values to location in the route form
// when sidebar is already loaded
function fillFormRouteLocations(data) {
  if ('origin' in data) {
    FormObj.origin.val(data.origin);
  }
  if ('destination' in data) {
    FormObj.destination.val(data.destination);
  }
}

function setRouteLocation(e, waypoint) {
  var lat = e.latlng.lat;
  var lng = e.latlng.lng;

  var data = {};
  data[waypoint.title] = lat + ", " + lng;

  if (sidebar.isVisible()) {
    fillFormRouteLocations(data);
  } else {
    loadRouteForm(data);
  }
  if (waypoint.marker === null) {
    MapObj.createMarker(waypoint, e.latlng);
  } else {
    waypoint.marker.setLatLng(e.latlng);
  }
}

// this is performed when user clicks "Rotas a partir daqui"
function routesFromHere(e) {
  setRouteLocation(e, RouteObj.origin);
  MapObj.control.spliceWaypoints(0, 1, e.latlng);
}

// this is performed when user clicks "Rotas para cá"
function routesToHere(e) {
  setRouteLocation(e, RouteObj.destination);
  MapObj.control.spliceWaypoints(MapObj.control.getWaypoints().length - 1, 1, e.latlng);
}

function reverseRoute(e) {
  e.preventDefault();

  // reverse waypoints to route
  var waypoints = MapObj.control.getWaypoints();
  MapObj.control.setWaypoints(waypoints.reverse());

  // NOTE reverse markers was so hard to figure out
  if (RouteObj.origin.marker !== null && RouteObj.destination.marker === null) {
    console.log('Destination in blank.');
    MapObj.createMarker(RouteObj.destination, RouteObj.origin.marker.getLatLng());
    MapObj.removeMarker(RouteObj.origin);
  } else if (RouteObj.destination.marker !== null && RouteObj.origin.marker === null) {
    console.log('Origin in blank');
    MapObj.createMarker(RouteObj.origin, RouteObj.destination.marker.getLatLng());
    MapObj.removeMarker(RouteObj.destination);
  }

  if (RouteObj.origin.marker !== null && RouteObj.destination.marker !== null) {
    var latlng = RouteObj.origin.marker.getLatLng();
    RouteObj.origin.marker.setLatLng(RouteObj.destination.marker.getLatLng());
    RouteObj.destination.marker.setLatLng(latlng);
  }

  var origin_latlng = FormObj.origin.val();
  var destination_latlng = FormObj.destination.val();

  // swap values in form
  FormObj.origin.val(destination_latlng);
  FormObj.destination.val(origin_latlng);

}
// TODO Require to fill out origin and destination in the form, before calculate route
// TODO Add button to create a new route
// TODO Suggest locations on whe form
// TODO Suggest locations on whe form
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var PublishView = require('../../../../../../javascripts/cartodb/new_common/dialogs/publish/publish_view');

var sharedTests = function() {
  it('should have no leaks', function() {
    expect(this.view).toHaveNoLeaks();
  });

  it('should render fine', function() {
    expect(this.innerHTML()).toContain('Publish your map');
  });

  it('should render the options', function() {
    expect(this.innerHTML()).toContain('OptionCard');
    expect(this.view.$el.find('.OptionCard').length).toEqual(3);
  });
};

describe('new_common/dialogs/publish/publish_view', function() {
  beforeEach(function() {
    this.user = jasmine.createSpy('user');
    this.vis = new cdb.admin.Visualization({
      id: 'abc-123',
      privacy: 'PRIVATE'
    });
    spyOn(this.vis, 'embedURL').and.returnValue('http://cartodb.com/user/pepe/viz/abc-123/embed_map');
    spyOn(this.vis, 'vizjsonURL').and.returnValue('https://cartodb.com/user/pepe/api/v2/viz/abc-123/viz.json');
    spyOn(this.vis, 'publicURL').and.returnValue('https://cartodb.com/user/pepe/api/v2/viz/abc-123/public_map');

    var self = this;
    this.urlShortener = jasmine.createSpyObj('UrlShortener', ['fetch']);
    cdb.editor = {
      UrlShortener: function() {
        return self.urlShortener;
      }
    };
    this.view = new PublishView({
      model: this.vis,
      user: this.user,
      clean_on_hide: true
    });
    this.view.render();
  });

  describe('when map is private', function() {
    sharedTests.call(this);

    it('should not try to shorten the public URL', function() {
      expect(this.urlShortener.fetch).not.toHaveBeenCalled();
    });

    it('should render alternative views for map and embed options', function() {
      expect(this.innerHTML()).toContain('is private');
      expect(this.innerHTML()).toContain('js-change-privacy');
    });

    describe('when clicking any change privacy link', function() {
      beforeEach(function() {
        var self = this;
        this.privacyModal = jasmine.createSpyObj('PrivacyDialog', ['appendToBody', 'bind', 'clean']);
        cdb.editor.ChangePrivacyView = function() {
          return self.privacyModal;
        };
        spyOn(this.view, 'hide');
        spyOn(this.view, 'show');
        spyOn(this.view, 'clean');
        this.view.$el.find('.js-change-privacy').click();
      });

      it('should hide the publish modal but not clean it', function() {
        expect(this.view.hide).toHaveBeenCalled();
        expect(this.view.clean).not.toHaveBeenCalled();
        expect(this.view.options.clean_on_hide).toBeFalsy();
      });

      it('should show the privacy modal instead', function() {
        expect(this.privacyModal.appendToBody).toHaveBeenCalled();
      });

      it('should listen to hide event on the privacy modal', function() {
        expect(this.privacyModal.bind).toHaveBeenCalled();
        expect(this.privacyModal.bind.calls.argsFor(0)[0]).toEqual('hide');
      });

      describe('when privacy modal finishs', function() {
        beforeEach(function() {
          this.privacyModal.bind.calls.argsFor(0)[1].call(this.view);
        });

        it('should restore clean_on_hide value', function() {
          expect(this.view.options.clean_on_hide).toBeTruthy();
        });

        it('should show publish modal again', function() {
          expect(this.view.show).toHaveBeenCalled();
        });

        it('should clean the privacy modal', function() {
          // clean_on_hide: true on the creation of the privacy modal made the publish modal also to be removed :/
          expect(this.privacyModal.clean).toHaveBeenCalled();
        });
      });
    });
  });

  describe('when map is not private', function() {
    sharedTests.call(this);

    beforeEach(function() {
      this.vis.set('privacy', 'LINK');
    });

    it('should render the embed option', function() {
      expect(this.innerHTML()).toContain('<iframe width="100%" height="520" frameborder="0" src="http://cartodb.com/user/pepe/viz/abc-123/embed_map" allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen></iframe>');
    });

    it('should render the dev cartodb.js option', function() {
      expect(this.innerHTML()).toContain('https://cartodb.com/user/pepe/api/v2/viz/abc-123/viz.json');
    });

    it('should get shorter public URL', function() {
      expect(this.urlShortener.fetch).toHaveBeenCalledWith(
        'https://cartodb.com/user/pepe/api/v2/viz/abc-123/public_map',
        jasmine.objectContaining({
          success: jasmine.any(Function),
          error: jasmine.any(Function)
        }
      ));
    });

    describe('when url shortening succeeds', function() {
      beforeEach(function() {
        this.urlShortener.fetch.calls.argsFor(0)[1].success('cdb.io/abc123');
      });

      it('should set shorter url as new copyable content', function() {
        expect(this.innerHTML()).toContain('cdb.io/abc123');
      });
    });

    describe('when shorter URL could not be retrieved', function() {
      beforeEach(function() {
        this.urlShortener.fetch.calls.argsFor(0)[1].error('/viz/abc-123/public_map');
      });

      it('should render the original public URL', function() {
        expect(this.innerHTML()).toContain('/public_map');
      });
    });
  });
});
<commit_msg>Relax test case<commit_after>var cdb = require('cartodb.js');
var PublishView = require('../../../../../../javascripts/cartodb/new_common/dialogs/publish/publish_view');

var sharedTests = function() {
  it('should have no leaks', function() {
    expect(this.view).toHaveNoLeaks();
  });

  it('should render fine', function() {
    expect(this.innerHTML()).toContain('Publish your map');
  });

  it('should render the options', function() {
    expect(this.innerHTML()).toContain('OptionCard');
    expect(this.view.$el.find('.OptionCard').length).toEqual(3);
  });
};

describe('new_common/dialogs/publish/publish_view', function() {
  beforeEach(function() {
    this.user = jasmine.createSpy('user');
    this.vis = new cdb.admin.Visualization({
      id: 'abc-123',
      privacy: 'PRIVATE'
    });
    spyOn(this.vis, 'embedURL').and.returnValue('http://cartodb.com/user/pepe/viz/abc-123/embed_map');
    spyOn(this.vis, 'vizjsonURL').and.returnValue('https://cartodb.com/user/pepe/api/v2/viz/abc-123/viz.json');
    spyOn(this.vis, 'publicURL').and.returnValue('https://cartodb.com/user/pepe/api/v2/viz/abc-123/public_map');

    var self = this;
    this.urlShortener = jasmine.createSpyObj('UrlShortener', ['fetch']);
    cdb.editor = {
      UrlShortener: function() {
        return self.urlShortener;
      }
    };
    this.view = new PublishView({
      model: this.vis,
      user: this.user,
      clean_on_hide: true
    });
    this.view.render();
  });

  describe('when map is private', function() {
    sharedTests.call(this);

    it('should not try to shorten the public URL', function() {
      expect(this.urlShortener.fetch).not.toHaveBeenCalled();
    });

    it('should render alternative views for map and embed options', function() {
      expect(this.innerHTML()).toContain('is private');
      expect(this.innerHTML()).toContain('js-change-privacy');
    });

    describe('when clicking any change privacy link', function() {
      beforeEach(function() {
        var self = this;
        this.privacyModal = jasmine.createSpyObj('PrivacyDialog', ['appendToBody', 'bind', 'clean']);
        cdb.editor.ChangePrivacyView = function() {
          return self.privacyModal;
        };
        spyOn(this.view, 'hide');
        spyOn(this.view, 'show');
        spyOn(this.view, 'clean');
        this.view.$el.find('.js-change-privacy').click();
      });

      it('should hide the publish modal but not clean it', function() {
        expect(this.view.hide).toHaveBeenCalled();
        expect(this.view.clean).not.toHaveBeenCalled();
        expect(this.view.options.clean_on_hide).toBeFalsy();
      });

      it('should show the privacy modal instead', function() {
        expect(this.privacyModal.appendToBody).toHaveBeenCalled();
      });

      it('should listen to hide event on the privacy modal', function() {
        expect(this.privacyModal.bind).toHaveBeenCalled();
        expect(this.privacyModal.bind.calls.argsFor(0)[0]).toEqual('hide');
      });

      describe('when privacy modal finishs', function() {
        beforeEach(function() {
          this.privacyModal.bind.calls.argsFor(0)[1].call(this.view);
        });

        it('should restore clean_on_hide value', function() {
          expect(this.view.options.clean_on_hide).toBeTruthy();
        });

        it('should show publish modal again', function() {
          expect(this.view.show).toHaveBeenCalled();
        });

        it('should clean the privacy modal', function() {
          // clean_on_hide: true on the creation of the privacy modal made the publish modal also to be removed :/
          expect(this.privacyModal.clean).toHaveBeenCalled();
        });
      });
    });
  });

  describe('when map is not private', function() {
    sharedTests.call(this);

    beforeEach(function() {
      this.vis.set('privacy', 'LINK');
    });

    it('should render the embed option', function() {
      expect(this.innerHTML()).toContain('iframe width="100%" height="520" frameborder="0" src="http://cartodb.com/user/pepe/viz/abc-123/embed_map" allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen');
    });

    it('should render the dev cartodb.js option', function() {
      expect(this.innerHTML()).toContain('https://cartodb.com/user/pepe/api/v2/viz/abc-123/viz.json');
    });

    it('should get shorter public URL', function() {
      expect(this.urlShortener.fetch).toHaveBeenCalledWith(
        'https://cartodb.com/user/pepe/api/v2/viz/abc-123/public_map',
        jasmine.objectContaining({
          success: jasmine.any(Function),
          error: jasmine.any(Function)
        }
      ));
    });

    describe('when url shortening succeeds', function() {
      beforeEach(function() {
        this.urlShortener.fetch.calls.argsFor(0)[1].success('cdb.io/abc123');
      });

      it('should set shorter url as new copyable content', function() {
        expect(this.innerHTML()).toContain('cdb.io/abc123');
      });
    });

    describe('when shorter URL could not be retrieved', function() {
      beforeEach(function() {
        this.urlShortener.fetch.calls.argsFor(0)[1].error('/viz/abc-123/public_map');
      });

      it('should render the original public URL', function() {
        expect(this.innerHTML()).toContain('/public_map');
      });
    });
  });
});
<|endoftext|>


<commit_before>// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();
// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject() {
	// will store the reference to the XMLHttpRequest object
	var xmlHttp;
	// if running Internet Explorer
	if(window.ActiveXObject) {
		try {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (e) {
			xmlHttp = false;
		}
	}
	// if running Mozilla or other browsers
	else {
		try {
			xmlHttp = new XMLHttpRequest();
		}
		catch (e) {
			xmlHttp = false;
		}
	}

	// return the created object or display an error message
	if (!xmlHttp)
		alert("Error creating the XMLHttpRequest object.");
	else
		return xmlHttp;
}

function dragStart(event) {
	event.dataTransfer.effectAllowed = 'move';
	event.dataTransfer.setData("Text", event.target.getAttribute('id'));
}

function dragOver(event) {
	return false;
}

function drop(event) {
	var from = event.dataTransfer.getData("Text");
	console.log(from);
	var to = event.target.getAttribute('id');
	var piece = document.getElementById(from).innerHTML;
	var txt = from+"-"+to;
	event.preventDefault(); // Consider using `event.preventDefault` instead
	var text = document.createTextNode(from+"-"+to);
	// we can add the code for the piece and send it to the server.
	// proceed only if the xmlHttp object isn't busy
	if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0) {
		// retrieve the name typed by the user on the form
		text = encodeURIComponent(txt);
		xmlHttp.open("GET", "move/"+txt, true);
		//	$.post("/move",{ str: text },function( data ){
		//	},"json" );
		// define the method to handle server responses
		xmlHttp.onreadystatechange = handleServerResponse;
		// make the server request
		xmlHttp.send(null);
	}
	return false;
}
// executed automatically when a message is received from the server
function handleServerResponse()	{
	// move forward only if the transaction has completed
	if (xmlHttp.readyState == 4) {
	// status of 200 indicates the transaction completed successfully
		if (xmlHttp.status == 200) {
			// extract the XML retrieved from the server
			xmlDoc = xmlHttp.responseXML;
			// obtain the document element (the root element) of the XML structure
			console.log(xmlDoc);
			// get the text message, which is in the first child of game.php
			// obtain the document element (the root element) of the XML structure
			xmlDocumentElement = xmlDoc.documentElement;
			// get the text message, which is in the first child of
			// the the document element
			move = xmlDocumentElement.firstChild.data;

			var errormsg =  {
									 "201" : "It's not your turn."
									,"202" : "This move is against the game rules."
									,"203" : "Another piece in the way"
									,"204" : "You can not move there."
									,"205" : "King can't move into chess."
									};
			if (move > 200) {
				msg =  errormsg[move];
				document.getElementById("error").innerHTML = msg;
				$('#error').hide().fadeIn("slow");
				$('#error').fadeOut(3000);
			}
			else {
				// update the client display using the data received
				document.getElementById("moves").innerHTML +=  move + "
";
				var from = move.substring(0,2);
				var to = move.substring(3,5);
				var element = document.getElementById(from);
				var target = document.getElementById(to);
				target.innerHTML = element.innerHTML; // Moving piece to new cell
				element.innerHTML = ""; // Clearing old cell
			}
		}
		// a HTTP status different than 200 signals an error
		else {
			alert("There was a problem accessing the server: " +
			xmlHttp.statusText);
		}
	}
}
<commit_msg>crowning<commit_after>// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();
// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject() {
	// will store the reference to the XMLHttpRequest object
	var xmlHttp;
	// if running Internet Explorer
	if(window.ActiveXObject) {
		try {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (e) {
			xmlHttp = false;
		}
	}
	// if running Mozilla or other browsers
	else {
		try {
			xmlHttp = new XMLHttpRequest();
		}
		catch (e) {
			xmlHttp = false;
		}
	}

	// return the created object or display an error message
	if (!xmlHttp)
		alert("Error creating the XMLHttpRequest object.");
	else
		return xmlHttp;
}

function dragStart(event) {
	event.dataTransfer.effectAllowed = 'move';
	event.dataTransfer.setData("Text", event.target.getAttribute('id'));
}

function dragOver(event) {
	return false;
}

function drop(event) {
	var from = event.dataTransfer.getData("Text");
	console.log(from);
	var to = event.target.getAttribute('id');
	var piece = document.getElementById(from).innerHTML;
	var txt = from+"-"+to;
	event.preventDefault(); // Consider using `event.preventDefault` instead
	var text = document.createTextNode(from+"-"+to);
	// we can add the code for the piece and send it to the server.
	// proceed only if the xmlHttp object isn't busy
	if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0) {
		// retrieve the name typed by the user on the form
		text = encodeURIComponent(txt);
		xmlHttp.open("GET", "move/"+txt, true);
		//	$.post("/move",{ str: text },function( data ){
		//	},"json" );
		// define the method to handle server responses
		xmlHttp.onreadystatechange = handleServerResponse;
		// make the server request
		xmlHttp.send(null);
	}
	return false;
}
// executed automatically when a message is received from the server
function handleServerResponse()	{
	// move forward only if the transaction has completed
	if (xmlHttp.readyState == 4) {
	// status of 200 indicates the transaction completed successfully
		if (xmlHttp.status == 200) {
			// extract the XML retrieved from the server
			xmlDoc = xmlHttp.responseXML;
			// obtain the document element (the root element) of the XML structure
			console.log(xmlDoc);
			// get the text message, which is in the first child of game.php
			// obtain the document element (the root element) of the XML structure
			xmlDocumentElement = xmlDoc.documentElement;
			// get the text message, which is in the first child of
			// the the document element
			move = xmlDocumentElement.firstChild.data;

			var errormsg =  {
									 "201" : "It's not your turn."
									,"202" : "This move is against the game rules."
									,"203" : "Another piece in the way"
									,"204" : "You can not move there."
									,"205" : "King can't move into chess."
									};
			if (move > 200) {
				msg =  errormsg[move];
				document.getElementById("error").innerHTML = msg;
				$('#error').hide().fadeIn("slow");
				$('#error').fadeOut(3000);
			} else if (move == 101) {
				var from = txt.substring(0,2);
				var to = txt.substring(3,5);
				var element = document.getElementById(from);
				var target = document.getElementById(to);
				target.innerHTML = "♚"; // Make it a Queen
				element.innerHTML = ""; // Clearing old cell
			}
			else {
				// update the client display using the data received
				document.getElementById("moves").innerHTML +=  move + "
";
				var from = move.substring(0,2);
				var to = move.substring(3,5);
				var element = document.getElementById(from);
				var target = document.getElementById(to);
				target.innerHTML = element.innerHTML; // Moving piece to new cell
				element.innerHTML = ""; // Clearing old cell
			}
		}
		// a HTTP status different than 200 signals an error
		else {
			alert("There was a problem accessing the server: " +
			xmlHttp.statusText);
		}
	}
}
<|endoftext|>