<commit_before>/**
 * Adds a date and price as a tuple to a targetSeries
 * @param {HighChart.series} targetSeries reference
 * @param {int} date UTC formatted time
 * @param {int} price currency price
 */
var addDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], false);
  // tities
};

// Adds a live data point to a series, differs from "addDataPointToSeries"
//    because it defaults to true for redrawing the chart, hence a "live"
//    addPoint functionality
var addLiveDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], true);
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addCandlestickDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i].date * 1000;
    var price = candlestick[i].close;
    console.log('adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addBacktestDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i][0] * 1000;
    var price = candlestick[i][1];
    console.log('backtest: adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addBenchMarkDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i][0] * 1000;
    var price = candlestick[i][1];
    console.log('benchmark: adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {array[][]} chartData
 */
var addIndicatorDatasetToSeries = function (targetSeries, chartData) {
  for (var i = 0; i < chartData.length; i++) {
    var date = chartData[i][0] * 1000;
    var price = chartData[i][1];
    //console.log('date:', date, 'price:', price);
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
var createCandlestickSeries = function (highchart, name) {
  var seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
var createIndicatorSeries = function (highchart, name, spline) {
  var seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  if (spline == true) {
    seriesObj.type = 'spline';
  }
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

var createFlagSeries = function (highchart) {
  var seriesObj = {};
  seriesObj.id = 'flags';
  seriesObj.type = 'flags';
  seriesObj.data = [];
  seriesObj.onSeries = '10-Day Moving Average';
  seriesObj.shape = 'circlepin';
  seriesObj.width = 20;

  highchart.addSeries(seriesObj);
};

/**
 * Every flag consists of x, title and text. The attribute "x" must be set to
 * the point where the flag should appear. The attribute "title" is the text
 * which is displayed inside the flag on the chart. The attribute "text" contains
 * the text which will appear when the mouse hover above the flag.
 */
var addFlagToSeries = function (highchart, timeStamp, order) {
  var flagObj = {};
  console.log('inside addFlagToSeries:', timeStamp, order);
  flagObj.x = timeStamp;
  flagObj.title = order;
  flagObj.text = 'Make a trade here.';

  highchart.get('flags').addPoint(flagObj);
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
var loadStrategyTrades = function (highchart) {
  var socket = io.connect('http://localhost:3000');
  console.log('CONNECTION RECEIVED. SERVER RUNNING AT http://localhost:3000');

  highchart.showLoading('');

  // INITALIZE CHART WITH HISTORICAL DATA
  socket.on('initializedChartData', function (chartData) {

    // setTimeout(function () {
    //   highchart.hideLoading();
    // }, 2000);

    console.log('### initializedChartData received...');
    console.log('### creating series...');

    createCandlestickSeries(highchart, 'Closing Price');
    createIndicatorSeries(highchart, '10-Day Moving Average');
    createIndicatorSeries(highchart, '20-Day Moving Average');

    /* Creating candlestick chart lines */
    var candlestickData = chartData.candlestickData;
    var targetSeries = highchart.get("Closing Price");
    addCandlestickDatasetToSeries(targetSeries, candlestickData);

    /* Adding indicators */
    var SMA10 = chartData.indicators.SMA10;
    var targetSMA10 = highchart.get('10-Day Moving Average');
    console.log('### adding SMA10 to chart');
    addIndicatorDatasetToSeries(targetSMA10, SMA10);

    var SMA20 = chartData.indicators.SMA20;
    var targetSMA20 = highchart.get('20-Day Moving Average');
    console.log('### adding SMA20 to chart');
    addIndicatorDatasetToSeries(targetSMA20, SMA20);

    /* Adding order flags */
    createFlagSeries(highchart);
    for (var i = 0; i < chartData.flags.length; i++) {
      console.log('flag added');
      var timeStamp = chartData.flags[i].timestamp * 1000;
      var orderLongShort = chartData.flags[i].longShort;
      addFlagToSeries(highchart, timeStamp, orderLongShort);
    }

    highchart.hideLoading();

  });

  // UPDATE CHART WITH LIVE DATA
  socket.on('updatedChartData', function (chartData) {
    console.log("### CLIENT: Live Data Point Received");
    var date = chartData.time;
    var price = parseFloat(chartData.mostRecentTickerPrice);
    var targetSeries = highchart.get('Closing Price');
    addLiveDataPointToSeries(targetSeries, date, price);
  });
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
var loadPortfolioPerformance = function (highchart) {
  var socket = io.connect('http://localhost:3000');
  console.log('CONNECTION RECEIVED. SERVER RUNNING AT http://localhost:3000');
  highchart.showLoading('');

  // INITALIZE CHART WITH HISTORICAL DATA
  socket.on('backtest', function (chartData) {

    console.log('### Portfolio: initializedChartData received...');
    console.log('### Portfolio: creating series...');

    /* Creating candlestick chart lines */
    createIndicatorSeries(highchart, 'Backtest', false);
    var bt = chartData.backtest;
    //console.log(chartData);
    console.log('bt', bt);
    var btarget = highchart.get('Backtest');
    addBacktestDatasetToSeries(btarget, bt);

    /* Creating candlestick benchmark chart lines */
    createIndicatorSeries(highchart, 'Benchmark', false);
    var bm = chartData.benchmark;
    var bmtarget = highchart.get('Benchmark');
    addBenchMarkDatasetToSeries(bmtarget, bm);

    /* This line needs to be here for some reason, or else chart won't render properly... */
    createFlagSeries(highchart);

    highchart.hideLoading();
  });
};

$(document).ready(function () {
  $('#hcharts-strategy').highcharts('StockChart', {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: false,
          groupPixelWidth: 5
        }
      }
    },
    // loading: {
    //     labelStyle: {
    //         fontStyle: 'italic'
    //     }
    // },
    rangeSelector: {
      buttons: [{
        type: 'month',
        count: 1,
        text: '1m'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },

    title: {
      text: 'Moving Avg. Crossover Trades'
    },
    subtitle: {
      text: '+ Indicators (BTC/USD)'
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    // yAxis:
    //   [{
    //     title: {
    //       text: 'Ticker',
    //     },
    //     opposite: false
    //   }
    // ],
    chart: {
      events: {
        load: function () {
          var self = this;
          loadStrategyTrades(self);
        }
      },
    },
    series: []
  });

  $('#hcharts-portfolio').highcharts('StockChart', {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: false,
          groupPixelWidth: 15
        }
      }
    },
    rangeSelector: {
      buttons: [{
        type: 'month',
        count: 1,
        text: '1m'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },

    title: {
      text: 'Portfolio Performance'
    },
    subtitle: {
      text: 'Moving Average Crossover Strategy'
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    // yAxis:
    //   [{
    //     title: {
    //       text: 'Value',
    //     },
    //     opposite: false
    //   }
    // ],
    chart: {
      events: {
        load: function () {
          var self = this;
          loadPortfolioPerformance(self);
        }
      },
    },
    series: []
  });
});
<commit_msg>reordered createIndicator functions so benchmark is same color at ticker data chart<commit_after>/**
 * Adds a date and price as a tuple to a targetSeries
 * @param {HighChart.series} targetSeries reference
 * @param {int} date UTC formatted time
 * @param {int} price currency price
 */
var addDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], false);
  // tities
};

// Adds a live data point to a series, differs from "addDataPointToSeries"
//    because it defaults to true for redrawing the chart, hence a "live"
//    addPoint functionality
var addLiveDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], true);
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addCandlestickDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i].date * 1000;
    var price = candlestick[i].close;
    console.log('adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addBacktestDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i][0] * 1000;
    var price = candlestick[i][1];
    console.log('backtest: adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
var addBenchMarkDatasetToSeries = function (targetSeries, candlestick) {
  for (var i = 0; i < candlestick.length; i++) {
    var date = candlestick[i][0] * 1000;
    var price = candlestick[i][1];
    console.log('benchmark: adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {array[][]} chartData
 */
var addIndicatorDatasetToSeries = function (targetSeries, chartData) {
  for (var i = 0; i < chartData.length; i++) {
    var date = chartData[i][0] * 1000;
    var price = chartData[i][1];
    //console.log('date:', date, 'price:', price);
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
var createCandlestickSeries = function (highchart, name) {
  var seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
var createIndicatorSeries = function (highchart, name, spline) {
  var seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  if (spline == true) {
    seriesObj.type = 'spline';
  }
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

var createFlagSeries = function (highchart) {
  var seriesObj = {};
  seriesObj.id = 'flags';
  seriesObj.type = 'flags';
  seriesObj.data = [];
  seriesObj.onSeries = '10-Day Moving Average';
  seriesObj.shape = 'circlepin';
  seriesObj.width = 20;

  highchart.addSeries(seriesObj);
};

/**
 * Every flag consists of x, title and text. The attribute "x" must be set to
 * the point where the flag should appear. The attribute "title" is the text
 * which is displayed inside the flag on the chart. The attribute "text" contains
 * the text which will appear when the mouse hover above the flag.
 */
var addFlagToSeries = function (highchart, timeStamp, order) {
  var flagObj = {};
  console.log('inside addFlagToSeries:', timeStamp, order);
  flagObj.x = timeStamp;
  flagObj.title = order;
  flagObj.text = 'Make a trade here.';

  highchart.get('flags').addPoint(flagObj);
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
var loadStrategyTrades = function (highchart) {
  var socket = io.connect('http://localhost:3000');
  console.log('CONNECTION RECEIVED. SERVER RUNNING AT http://localhost:3000');

  highchart.showLoading('');

  // INITALIZE CHART WITH HISTORICAL DATA
  socket.on('initializedChartData', function (chartData) {

    // setTimeout(function () {
    //   highchart.hideLoading();
    // }, 2000);

    console.log('### initializedChartData received...');
    console.log('### creating series...');

    createCandlestickSeries(highchart, 'Closing Price');
    createIndicatorSeries(highchart, '10-Day Moving Average');
    createIndicatorSeries(highchart, '20-Day Moving Average');

    /* Creating candlestick chart lines */
    var candlestickData = chartData.candlestickData;
    var targetSeries = highchart.get("Closing Price");
    addCandlestickDatasetToSeries(targetSeries, candlestickData);

    /* Adding indicators */
    var SMA10 = chartData.indicators.SMA10;
    var targetSMA10 = highchart.get('10-Day Moving Average');
    console.log('### adding SMA10 to chart');
    addIndicatorDatasetToSeries(targetSMA10, SMA10);

    var SMA20 = chartData.indicators.SMA20;
    var targetSMA20 = highchart.get('20-Day Moving Average');
    console.log('### adding SMA20 to chart');
    addIndicatorDatasetToSeries(targetSMA20, SMA20);

    /* Adding order flags */
    createFlagSeries(highchart);
    for (var i = 0; i < chartData.flags.length; i++) {
      console.log('flag added');
      var timeStamp = chartData.flags[i].timestamp * 1000;
      var orderLongShort = chartData.flags[i].longShort;
      addFlagToSeries(highchart, timeStamp, orderLongShort);
    }

    highchart.hideLoading();

  });

  // UPDATE CHART WITH LIVE DATA
  socket.on('updatedChartData', function (chartData) {
    console.log("### CLIENT: Live Data Point Received");
    var date = chartData.time;
    var price = parseFloat(chartData.mostRecentTickerPrice);
    var targetSeries = highchart.get('Closing Price');
    addLiveDataPointToSeries(targetSeries, date, price);
  });
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
var loadPortfolioPerformance = function (highchart) {
  var socket = io.connect('http://localhost:3000');
  console.log('CONNECTION RECEIVED. SERVER RUNNING AT http://localhost:3000');
  highchart.showLoading('');

  // INITALIZE CHART WITH HISTORICAL DATA
  socket.on('backtest', function (chartData) {

    console.log('### Portfolio: initializedChartData received...');
    console.log('### Portfolio: creating series...');

    /* Creating candlestick benchmark chart lines */
    createIndicatorSeries(highchart, 'Benchmark', false);
    var bm = chartData.benchmark;
    var bmtarget = highchart.get('Benchmark');
    addBenchMarkDatasetToSeries(bmtarget, bm);

    /* Creating candlestick chart lines */
    createIndicatorSeries(highchart, 'Backtest', false);
    var bt = chartData.backtest;
    //console.log(chartData);
    console.log('bt', bt);
    var btarget = highchart.get('Backtest');
    addBacktestDatasetToSeries(btarget, bt);

    /* This line needs to be here for some reason, or else chart won't render properly... */
    createFlagSeries(highchart);

    highchart.hideLoading();
  });
};

$(document).ready(function () {
  $('#hcharts-strategy').highcharts('StockChart', {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: false,
          groupPixelWidth: 5
        }
      }
    },
    // loading: {
    //     labelStyle: {
    //         fontStyle: 'italic'
    //     }
    // },
    rangeSelector: {
      buttons: [{
        type: 'month',
        count: 1,
        text: '1m'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },

    title: {
      text: 'Moving Avg. Crossover Trades'
    },
    subtitle: {
      text: '+ Indicators (BTC/USD)'
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    // yAxis:
    //   [{
    //     title: {
    //       text: 'Ticker',
    //     },
    //     opposite: false
    //   }
    // ],
    chart: {
      events: {
        load: function () {
          var self = this;
          loadStrategyTrades(self);
        }
      },
    },
    series: []
  });

  $('#hcharts-portfolio').highcharts('StockChart', {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: false,
          groupPixelWidth: 15
        }
      }
    },
    rangeSelector: {
      buttons: [{
        type: 'month',
        count: 1,
        text: '1m'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },

    title: {
      text: 'Portfolio Performance'
    },
    subtitle: {
      text: 'Moving Average Crossover Strategy'
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    // yAxis:
    //   [{
    //     title: {
    //       text: 'Value',
    //     },
    //     opposite: false
    //   }
    // ],
    chart: {
      events: {
        load: function () {
          var self = this;
          loadPortfolioPerformance(self);
        }
      },
    },
    series: []
  });
});
<|endoftext|>


<commit_before>/*
*  Created by Thibaud Rohmer on 2010-12-23.
*/

/* 	refresh_img
*	loads given image url in the fullscreen (fs) and display (display_img) divs
*	and updates exif panel
*/

function refresh_img(url){
	if(url=="" || url==undefined){
		$('#display_img').html("");
		$('#exifdiv .content').html("");
		$('#commentsdiv .content').html("");
		$("#fblike").html("");
		return false;
	}

	$('#display_img').html('');

	$('#fs_img').html('');

	$("#fblike").html('');

	$('#exifdiv .content').load('exif.php',{ img: url });
	$("#exif").show();

	$('#admindiv .content').load('admin.php',{ img: url });

	$('#commentsdiv .content').load("infos.php",{ file: url });

	$('#display_img a').click(function(){
		change_display();
		return false;
	});

	location.hash=encodeURI(url);

}

/* show_select
* Brings focus to selected image
*
*/
function show_select(direction){
	if(typeof($(".select").attr("class")) != 'undefined'){
		var number=($(window).width()-$("leftcolumn").width())/3;
		item=$('.select');
		for(i=0;i<number;i=i+$(".img_contain").first().width()){
			if(typeof($(item).prev().attr("class")) != 'undefined'){
				item=$(item).prev();
			}
		}
		$('#projcontent').scrollTo($(item));
	}
}

/* select_thumb(thumb)
* selects the thumb
*/
function select_thumb(thumb){
	if($(thumb).attr("class") != "list_item") return false;
	$(".select").removeClass("select");
	thumb.addClass("select");
	return true;
}

/* 	preload_next
*	loads next image in memory for future viewing
*
*/
function preload_next(){
	if(typeof($(".select").prev().attr("class")) != 'undefined'){
		if($(".select").next().attr("class") != 'list_item'){
			$('.end').trigger('click');
		}

		nextImage = new Image();
		nextImage.src = $(".select").next().children("a").attr("title");
	}
}

/* 	preload_prev
*	loads previous image in memory for future viewing
*
*/
function preload_prev(){
	if(typeof($(".select").prev().attr("class")) != 'undefined'){
		nextImage = new Image();
		nextImage.src = $(".select").prev().children("a").attr("title");
	}
}

/* 	select_next
*	selects and displays next image
*	and preloads the next one
*/
function select_next(){
	if(typeof($(".select").attr("class")) == 'undefined'){
		$("#projcontent ul li").first().addClass("select");
		refresh_img($(".select a").attr('title'));
	}else{
		if(typeof($(".select").next().attr("class")) != 'undefined'){
			if( ! select_thumb($(".select").next())){
				$(".select").next().trigger("click");
			}
			refresh_img($(".select a").attr('title'));
		}
	}
	show_select("right");
	preload_next();
}

/* 	select_prev
*	selects and displays previous image
*	and preloads the one even before
*/
function select_prev() {
	if(typeof($(".select").attr("class")) == 'undefined'){
		$("#projcontent ul li").last().addClass("select");
		refresh_img($(".select a").attr('title'));
	}else{
		if(typeof($(".select").prev().attr("class")) != 'undefined'){
			var act=$(".select");
			$(".select").prev().addClass("select");
			act.removeClass("select");
			refresh_img($(".select a").attr('title'));
		}
	}
	show_select("left");
	preload_prev();
}

/* 	del_select_next
*	deletes current image, then selects and displays next image
*	and preloads the next one
*/
function del_select_next(){
	current=$(".select");
	select_next();
	current.hide();
}

/* Diaporama */

var diapo=0;
var diapoId=0;

function diaporama(){
	if(diapo==1){
		$("#fs").show();
		diapoId = setInterval(select_next,3000);
	}else{
		$("#fs").hide();
		clearInterval(diapoId);
		diapoId=0;
	}
}

function pause_diaporama(){
	if(diapo==1){
		if (diapoId==0){
			diapoId = setInterval(select_next,3000);
		}else{
			clearInterval(diapoId);
			diapoId=0;
		}
	}
}

/* remove_keyboard
* removes keyboard shortcuts
*/
function remove_keyboard(){
	$(window).unbind("keydown");
}

/* setup_keyboard
* setups keyboard shortcuts
*/
function setup_keyboard(){
	remove_keyboard();

	$(window).keydown(function(event) {

		if (event.keyCode == '39') { // arrow right
			select_next();
	   	}
		if (event.keyCode == '37') { // arrow left
				select_prev();
		}
		if (event.keyCode == '40') { //arrow down
			var number=($(window).width()-360)/170;
			for(i=0;i<number;i++){
				select_next();
			}
	   	}
		if (event.keyCode == '38') { //arrow up
			var number=($(window).width()-360)/170;
			for(i=0;i<number;i++){
				select_prev();
			}
	   	}
	  	if (event.keyCode == '70') { // f
			if(diapo!=1){
				$("#fs").toggle();
			}
	   	}
	  	if (event.keyCode == '72') { // h
			$('#wtf .content').load('help.txt');
			if($("#wtf").is(":visible")){
				$("#wtf").fadeOut("slow");
			}else{
				$("#wtf").fadeIn("slow");
			}
	   	}
	  	if (event.keyCode == '69') { // e
			if($("#exifdiv").is(":visible")){
				$("#exifdiv").fadeOut("slow");
			}else{
				$("#exifdiv").fadeIn("slow");
			}
	   	}
	  	if (event.keyCode == '13') { // enter
			change_display();
	   	}

	  	if (event.keyCode == '27') { // escape
			if($("#fs").is(":visible")) {
				$("#fs").hide();
				if(diapo==1){
					diapo=0;
					diaporama();
				}
			}else{
				if($("#projcontent").hasClass("inline")) {
					change_display();
				}else{
					$(".select").removeClass("select");
   				}
			}
		}

	  	if (event.keyCode == '68') { // d
			diapo=1-diapo;
			diaporama();
		}

		if (event.keyCode == '32') { // space
			pause_diaporama();
		}

		if (event.keyCode == '79') { // o

		}

	});
}

/* 	change_display
*	toggles display_div visibility along with many other things...
*/
function change_display(val){

	//if(val!="init" && $("#display2").css("display")=="none"){
	if(val!="init" && $("#projcontent").hasClass("fullpage")){
		$("#projcontent").removeClass("fullpage").addClass("inline");
		$("#menubar").show().removeClass("menubar-fullpage").addClass("menubar-inline");
		$("#display2").fadeIn();
		$('#display_img a').unbind();
		$('#display_img a').click(function(){
			change_display();
			return false;
		});

		$(window).bind('mousewheel', function(event,delta){
		 	if (delta > 0) {
				$("#projcontent").scrollTo('-='+10*delta+'px',0);
		 	} else {
				$("#projcontent").scrollTo('+='+(-10*delta)+'px',0);
		 	}
		});

	}else{
		$('#display_img a').unbind();
		$("#display2").fadeOut();
		$("#projcontent").removeClass("inline").addClass("fullpage");
		$("#menubar").hide().removeClass("menubar-inline").addClass("menubar-fullpage");
	}
	init_thumbs();
	show_select();
};

/* 	num_selected
*	returns the number of items selected
*
*/
function num_selected(){
	return $(".select a").size();
};

/* 	list_selected
*	returns a list of selected items
*/
function list_selected(){
	var mylist=new Array();
	$(".select a").each(function(){
		mylist[mylist.length] = ($(this).attr("href"));
	});
	return mylist;
};

/* 	list_selected_as_php
*	returns a php list of selected items in a string
*/
function list_selected_as_php(){
	var mylist="?";
	$(".select a").each(function(){
		mylist=mylist+"mylist[]="+($(this).attr("href"))+"&";
	});
	return mylist;
};

/* display_more
* Displays next thumbnails
*
*/
function display_more(page,limit,size_dir){
	morebutton="
More...
";

	$.post('files.php', {action:'go_on', page: page} ,function(data){
		$(data).appendTo('#album_contents');
		page++;

		if((page)*limit + 2 < size_dir)
		$(morebutton).appendTo('#album_contents');

		$('.end').click(function(){
			$(this).remove();
			if((page)*limit + 2 < size_dir)
			{
				display_more(page,limit,size_dir);
			}
		});

		init_thumbs();

	});
}

function init_thumbs(){
	if($("#projcontent").hasClass("fullpage"))
	{
		$('#projcontent a').unbind();

		$('#projcontent a').click(function(){
			$('.select').removeClass('select');
			$(this).parent().addClass('select');
			refresh_img(this.title);
			change_display();
			return false;
		});

	}else{
		$('#projcontent a').unbind();

		$('#projcontent a').click(function(){
			if ($(this).parent().hasClass("select")) return false;
			$(".select").removeClass("select");
			$(this).parent().addClass("select");
			refresh_img(this.title);
			return false;
		});

		$('#projcontent a').dblclick(function(){
			change_display();
			return false;
		});

	}
}

$(document).ready(function() {

/* Left menu */

	accordionCache = $('div#accordion');
  	$('.year', accordionCache).click( function () {

		$("#projcontent").load('files.php', { album: $(this).attr("title"), action: "album" });
		$('div.albums', accordionCache).removeClass('open');
		$('.year').removeClass('menu_selected');
		$('#leftcolumn li').removeClass('menu_selected');
		$('#logindiv').hide();
		location.hash=encodeURI($(this).attr("title"));
		$(this).addClass('menu_selected');
		$(this).next().addClass('open').slideDown('slow');
		$('div.albums:not(.open)', accordionCache).slideUp();
  	} );

	$("#leftcolumn li").click(function() {
		myclass=$(this).attr("class");
		if (myclass.indexOf(" ") > 1) {
			myclass=myclass.substr(0,myclass.indexOf(" "));
		}
		$("#projcontent").load('files.php', { album: $(this).attr("title"), action: "album" });
		$('#exif').hide();
		$('#logindiv').hide();
		$('#exifdiv').fadeOut("slow");
		if(myclass=="album")	location.hash=encodeURI($(this).attr("title"));
		else location.hash=encodeURI(myclass+"_"+$(this).attr("title"));
		$("#leftcolumn li").removeClass('menu_selected');
		$(this).addClass('menu_selected');
	});

/* Menubar */

	$("#next a").click(function(){
		select_next();
	});

	$("#previous a").click(function(){
		select_prev();
	});

	$("#help a").click(function(){
		$('#wtf .content').load('help.txt');
		if(!$("#wtf").is(":visible")){
			$("#wtf").fadeIn("slow",function(){
				$("body").click(function(){
					if($("#wtf").is(":visible")) {
						$("#wtf").fadeOut("slow");
						$("body").unbind("click");
					}
				});
			});

		}
	});

	$(".menubar_button").click(function(){
		var name="#"+$(this).attr("id")+"div";
		if($(name).is(":visible")){
			$(name).fadeOut("slow");
		}else{
			$(name).fadeIn("slow");
		}
		$(name).draggable();
	});

/* Keyboard events */
	setup_keyboard();

// Anchor
	parse_my_hash_dude();

});

/* parse_my_hash_dude
* hash parsing made easy... or not
*/

function parse_my_hash_dude(){
	if(location.hash.length>2){
		var hash=decodeURI(location.hash.substr(1));
		$('#exif').hide();
		$('#exifdiv').hide();
		$("#menubar").show();

	lastslash = hash.lastIndexOf("/");

	if( lastslash < 0 )
	{
		var myaction=hash.substr(0,hash.lastIndexOf("_"));
		var myalbum=hash.substr(hash.lastIndexOf("_")+1);
		$("#projcontent").load('files.php', { album: myalbum, action: myaction });
	}
	else
	{
		if( lastslash < hash.lastIndexOf( "." ) ){
			// IMAGE
			var myalbum = hash.substr(0,hash.lastIndexOf("/")+1);

			$("#projcontent").load('files.php', { album: myalbum, action: "album" },function(){
				refresh_img(hash);
				change_display();
			});
		}else{
			// FOLDER
			$("#projcontent").load('files.php', { album: hash, action: "album" },function(){
				change_display("init");
			});
		}
	}
}
}
<commit_msg>Displaying of album name in page title<commit_after>/*
*  Created by Thibaud Rohmer on 2010-12-23.
*/

/* 	refresh_img
*	loads given image url in the fullscreen (fs) and display (display_img) divs
*	and updates exif panel
*/

function refresh_img(url){
	if(url=="" || url==undefined){
		$('#display_img').html("");
		$('#exifdiv .content').html("");
		$('#commentsdiv .content').html("");
		$("#fblike").html("");
		return false;
	}

	$('#display_img').html('');

	$('#fs_img').html('');

	$("#fblike").html('');

	$('#exifdiv .content').load('exif.php',{ img: url });
	$("#exif").show();

	$('#admindiv .content').load('admin.php',{ img: url });

	$('#commentsdiv .content').load("infos.php",{ file: url });

	$('#display_img a').click(function(){
		change_display();
		return false;
	});

	location.hash=encodeURI(url);

}

function update_title(title){
	document.title = title;
}

/* show_select
* Brings focus to selected image
*
*/
function show_select(direction){
	if(typeof($(".select").attr("class")) != 'undefined'){
		var number=($(window).width()-$("leftcolumn").width())/3;
		item=$('.select');
		for(i=0;i<number;i=i+$(".img_contain").first().width()){
			if(typeof($(item).prev().attr("class")) != 'undefined'){
				item=$(item).prev();
			}
		}
		$('#projcontent').scrollTo($(item));
	}
}

/* select_thumb(thumb)
* selects the thumb
*/
function select_thumb(thumb){
	if($(thumb).attr("class") != "list_item") return false;
	$(".select").removeClass("select");
	thumb.addClass("select");
	return true;
}

/* 	preload_next
*	loads next image in memory for future viewing
*
*/
function preload_next(){
	if(typeof($(".select").prev().attr("class")) != 'undefined'){
		if($(".select").next().attr("class") != 'list_item'){
			$('.end').trigger('click');
		}

		nextImage = new Image();
		nextImage.src = $(".select").next().children("a").attr("title");
	}
}

/* 	preload_prev
*	loads previous image in memory for future viewing
*
*/
function preload_prev(){
	if(typeof($(".select").prev().attr("class")) != 'undefined'){
		nextImage = new Image();
		nextImage.src = $(".select").prev().children("a").attr("title");
	}
}

/* 	select_next
*	selects and displays next image
*	and preloads the next one
*/
function select_next(){
	if(typeof($(".select").attr("class")) == 'undefined'){
		$("#projcontent ul li").first().addClass("select");
		refresh_img($(".select a").attr('title'));
	}else{
		if(typeof($(".select").next().attr("class")) != 'undefined'){
			if( ! select_thumb($(".select").next())){
				$(".select").next().trigger("click");
			}
			refresh_img($(".select a").attr('title'));
		}
	}
	show_select("right");
	preload_next();
}

/* 	select_prev
*	selects and displays previous image
*	and preloads the one even before
*/
function select_prev() {
	if(typeof($(".select").attr("class")) == 'undefined'){
		$("#projcontent ul li").last().addClass("select");
		refresh_img($(".select a").attr('title'));
	}else{
		if(typeof($(".select").prev().attr("class")) != 'undefined'){
			var act=$(".select");
			$(".select").prev().addClass("select");
			act.removeClass("select");
			refresh_img($(".select a").attr('title'));
		}
	}
	show_select("left");
	preload_prev();
}

/* 	del_select_next
*	deletes current image, then selects and displays next image
*	and preloads the next one
*/
function del_select_next(){
	current=$(".select");
	select_next();
	current.hide();
}

/* Diaporama */

var diapo=0;
var diapoId=0;

function diaporama(){
	if(diapo==1){
		$("#fs").show();
		diapoId = setInterval(select_next,3000);
	}else{
		$("#fs").hide();
		clearInterval(diapoId);
		diapoId=0;
	}
}

function pause_diaporama(){
	if(diapo==1){
		if (diapoId==0){
			diapoId = setInterval(select_next,3000);
		}else{
			clearInterval(diapoId);
			diapoId=0;
		}
	}
}

/* remove_keyboard
* removes keyboard shortcuts
*/
function remove_keyboard(){
	$(window).unbind("keydown");
}

/* setup_keyboard
* setups keyboard shortcuts
*/
function setup_keyboard(){
	remove_keyboard();

	$(window).keydown(function(event) {

		if (event.keyCode == '39') { // arrow right
			select_next();
	   	}
		if (event.keyCode == '37') { // arrow left
				select_prev();
		}
		if (event.keyCode == '40') { //arrow down
			var number=($(window).width()-360)/170;
			for(i=0;i<number;i++){
				select_next();
			}
	   	}
		if (event.keyCode == '38') { //arrow up
			var number=($(window).width()-360)/170;
			for(i=0;i<number;i++){
				select_prev();
			}
	   	}
	  	if (event.keyCode == '70') { // f
			if(diapo!=1){
				$("#fs").toggle();
			}
	   	}
	  	if (event.keyCode == '72') { // h
			$('#wtf .content').load('help.txt');
			if($("#wtf").is(":visible")){
				$("#wtf").fadeOut("slow");
			}else{
				$("#wtf").fadeIn("slow");
			}
	   	}
	  	if (event.keyCode == '69') { // e
			if($("#exifdiv").is(":visible")){
				$("#exifdiv").fadeOut("slow");
			}else{
				$("#exifdiv").fadeIn("slow");
			}
	   	}
	  	if (event.keyCode == '13') { // enter
			change_display();
	   	}

	  	if (event.keyCode == '27') { // escape
			if($("#fs").is(":visible")) {
				$("#fs").hide();
				if(diapo==1){
					diapo=0;
					diaporama();
				}
			}else{
				if($("#projcontent").hasClass("inline")) {
					change_display();
				}else{
					$(".select").removeClass("select");
   				}
			}
		}

	  	if (event.keyCode == '68') { // d
			diapo=1-diapo;
			diaporama();
		}

		if (event.keyCode == '32') { // space
			pause_diaporama();
		}

		if (event.keyCode == '79') { // o

		}

	});
}

/* 	change_display
*	toggles display_div visibility along with many other things...
*/
function change_display(val){

	//if(val!="init" && $("#display2").css("display")=="none"){
	if(val!="init" && $("#projcontent").hasClass("fullpage")){
		$("#projcontent").removeClass("fullpage").addClass("inline");
		$("#menubar").show().removeClass("menubar-fullpage").addClass("menubar-inline");
		$("#display2").fadeIn();
		$('#display_img a').unbind();
		$('#display_img a').click(function(){
			change_display();
			return false;
		});

		$(window).bind('mousewheel', function(event,delta){
		 	if (delta > 0) {
				$("#projcontent").scrollTo('-='+10*delta+'px',0);
		 	} else {
				$("#projcontent").scrollTo('+='+(-10*delta)+'px',0);
		 	}
		});

	}else{
		$('#display_img a').unbind();
		$("#display2").fadeOut();
		$("#projcontent").removeClass("inline").addClass("fullpage");
		$("#menubar").hide().removeClass("menubar-inline").addClass("menubar-fullpage");
	}
	init_thumbs();
	show_select();
};

/* 	num_selected
*	returns the number of items selected
*
*/
function num_selected(){
	return $(".select a").size();
};

/* 	list_selected
*	returns a list of selected items
*/
function list_selected(){
	var mylist=new Array();
	$(".select a").each(function(){
		mylist[mylist.length] = ($(this).attr("href"));
	});
	return mylist;
};

/* 	list_selected_as_php
*	returns a php list of selected items in a string
*/
function list_selected_as_php(){
	var mylist="?";
	$(".select a").each(function(){
		mylist=mylist+"mylist[]="+($(this).attr("href"))+"&";
	});
	return mylist;
};

/* display_more
* Displays next thumbnails
*
*/
function display_more(page,limit,size_dir){
	morebutton="
More...
";

	$.post('files.php', {action:'go_on', page: page} ,function(data){
		$(data).appendTo('#album_contents');
		page++;

		if((page)*limit + 2 < size_dir)
		$(morebutton).appendTo('#album_contents');

		$('.end').click(function(){
			$(this).remove();
			if((page)*limit + 2 < size_dir)
			{
				display_more(page,limit,size_dir);
			}
		});

		init_thumbs();

	});
}

function init_thumbs(){
	if($("#projcontent").hasClass("fullpage"))
	{
		$('#projcontent a').unbind();

		$('#projcontent a').click(function(){
			$('.select').removeClass('select');
			$(this).parent().addClass('select');
			refresh_img(this.title);
			change_display();
			return false;
		});

	}else{
		$('#projcontent a').unbind();

		$('#projcontent a').click(function(){
			if ($(this).parent().hasClass("select")) return false;
			$(".select").removeClass("select");
			$(this).parent().addClass("select");
			refresh_img(this.title);
			return false;
		});

		$('#projcontent a').dblclick(function(){
			change_display();
			return false;
		});

	}
}

$(document).ready(function() {

/* Left menu */

	accordionCache = $('div#accordion');
  	$('.year', accordionCache).click( function () {

		$("#projcontent").load('files.php', { album: $(this).attr("title"), action: "album" });
		$('div.albums', accordionCache).removeClass('open');
		$('.year').removeClass('menu_selected');
		$('#leftcolumn li').removeClass('menu_selected');
		$('#logindiv').hide();
		location.hash=encodeURI($(this).attr("title"));
		$(this).addClass('menu_selected');
		$(this).next().addClass('open').slideDown('slow');
		$('div.albums:not(.open)', accordionCache).slideUp();
  	} );

	$("#leftcolumn li").click(function() {
		myclass=$(this).attr("class");
		if (myclass.indexOf(" ") > 1) {
			myclass=myclass.substr(0,myclass.indexOf(" "));
		}
		$("#projcontent").load('files.php', { album: $(this).attr("title"), action: "album" });
		$('#exif').hide();
		$('#logindiv').hide();
		$('#exifdiv').fadeOut("slow");
		if(myclass=="album")	location.hash=encodeURI($(this).attr("title"));
		else location.hash=encodeURI(myclass+"_"+$(this).attr("title"));
		$("#leftcolumn li").removeClass('menu_selected');
		$(this).addClass('menu_selected');
	});

/* Menubar */

	$("#next a").click(function(){
		select_next();
	});

	$("#previous a").click(function(){
		select_prev();
	});

	$("#help a").click(function(){
		$('#wtf .content').load('help.txt');
		if(!$("#wtf").is(":visible")){
			$("#wtf").fadeIn("slow",function(){
				$("body").click(function(){
					if($("#wtf").is(":visible")) {
						$("#wtf").fadeOut("slow");
						$("body").unbind("click");
					}
				});
			});

		}
	});

	$(".menubar_button").click(function(){
		var name="#"+$(this).attr("id")+"div";
		if($(name).is(":visible")){
			$(name).fadeOut("slow");
		}else{
			$(name).fadeIn("slow");
		}
		$(name).draggable();
	});

/* Keyboard events */
	setup_keyboard();

// Anchor
	parse_my_hash_dude();

});

/* parse_my_hash_dude
* hash parsing made easy... or not
*/

function parse_my_hash_dude(){
	if(location.hash.length>2){
		var hash=decodeURI(location.hash.substr(1));
		$('#exif').hide();
		$('#exifdiv').hide();
		$("#menubar").show();

	lastslash = hash.lastIndexOf("/");

	if( lastslash < 0 )
	{
		var myaction=hash.substr(0,hash.lastIndexOf("_"));
		var myalbum=hash.substr(hash.lastIndexOf("_")+1);
		$("#projcontent").load('files.php', { album: myalbum, action: myaction });
	}
	else
	{
		if( lastslash < hash.lastIndexOf( "." ) ){
			// IMAGE
			var myalbum = hash.substr(0,hash.lastIndexOf("/")+1);

			$("#projcontent").load('files.php', { album: myalbum, action: "album" },function(){
				refresh_img(hash);
				change_display();
			});
		}else{
			// FOLDER
			$("#projcontent").load('files.php', { album: hash, action: "album" },function(){
				change_display("init");
			});
		}
	}
}
}
<|endoftext|>


<commit_before>'use strict';
var config = require('../intialize/config');
var accessKey = config.accessKey;
var accessSecret = config.accessSecret;

var chai = require('chai');
var expect = chai.expect;

var amazonMws = require('../../lib/amazon-mws')(accessKey, accessSecret);

describe('Products', function () {

    before(function () {
        expect(accessKey).to.be.a('string');
        expect(accessSecret).to.be.a('string');
    });

    it('It should get offers using GetLowestPricedOffersForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'ListMatchingProducts',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'Query': 'k'
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');

        var response = await amazonMws.products.searchFor(options);

        expect(response).to.be.a('object');
        expect(response).to.have.property('Products').to.be.a('object');
        expect(response).to.have.property('Products').to.have.property('Product');
        expect(response).to.have.property('ResponseMetadata').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
        expect(response).to.have.property('Headers').to.be.a('object');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
        expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
    });

    it('It should get offers using GetLowestPricedOffersForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetLowestPricedOffersForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASIN': config.ASIN,
            'ItemCondition': 'New'
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options.ASIN).to.be.a('string');

        var response = await amazonMws.products.searchFor(options);

        expect(response).to.be.a('object');
        expect(response).to.have.property('status').to.be.a('string');
        expect(response).to.have.property('Summary').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
        expect(response).to.have.property('Headers').to.be.a('object');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
        expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
    });

    it('It should get my price for ASIN using getMyPriceForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetMyPriceForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': config.ASIN
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options['ASINList.ASIN.1']).to.be.a('string');

        var response = await amazonMws.products.searchFor(options);

        expect(response).to.be.a('object');
        expect(response).to.have.property('ASIN').to.be.a('string');
        expect(response).to.have.property('status').to.be.a('string');
        expect(response).to.have.property('Product').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
        expect(response).to.have.property('Headers').to.be.a('object');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
        expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
    });

    it('It should NOT get my price for INVALID ASIN using GetMyPriceForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetMyPriceForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': undefined
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');

        try {
            var response = await amazonMws.products.searchFor(options);
            expect(response).to.be.a('object');
            expect(response).to.have.property('ASIN').to.be.a('string');
            expect(response).to.have.property('status').to.be.a('string');
            expect(response).to.have.property('Product').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
            expect(response).to.have.property('Headers').to.be.a('object');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
        } catch (error) {
            console.log('error ', error);
            expect(error).to.be.a('object');
            expect(error).to.have.property('Type').to.be.a('string');
            expect(error).to.have.property('Message').to.be.a('string');
            expect(error).to.have.property('Detail').to.be.a('object');
            expect(error).to.have.property('StatusCode').to.be.a('number');
            expect(error).to.have.property('RequestId').to.be.a('string');
            expect(error).to.have.property('Headers').to.be.a('object');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(error).to.have.property('Headers').to.have.property('x-mws-timestamp');
        }

    });

    it('It should get my price for ASIN using GetCompetitivePricingForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetCompetitivePricingForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': config.ASIN
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options['ASINList.ASIN.1']).to.be.a('string');

        try {
            var response = await amazonMws.products.searchFor(options);
            expect(response).to.be.a('object');
            expect(response).to.have.property('ASIN').to.be.a('string');
            expect(response).to.have.property('status').to.be.a('string');
            expect(response).to.have.property('Product').to.be.a('object');
            expect(response).to.have.property('Product').to.have.property('CompetitivePricing');
            expect(response).to.have.property('Product').to.have.property('CompetitivePricing').to.have.property('NumberOfOfferListings');
            expect(response).to.have.property('Product').to.have.property('CompetitivePricing').to.have.property('NumberOfOfferListings').to.have.property('OfferListingCount').to.be.a('array');
            expect(response.Product.CompetitivePricing.NumberOfOfferListings.OfferListingCount[0]).to.have.property('condition');
            expect(response.Product.CompetitivePricing.NumberOfOfferListings.OfferListingCount[0]).to.have.property('Value');
            expect(response).to.have.property('ResponseMetadata').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
            expect(response).to.have.property('Headers').to.be.a('object');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
        } catch (error) {
            console.log('error ', error);
            expect(error).to.be.undefined;
        }
    });

});<commit_msg>correct test cases<commit_after>'use strict';
var config = require('../intialize/config');
var accessKey = config.accessKey;
var accessSecret = config.accessSecret;

var chai = require('chai');
var expect = chai.expect;

var amazonMws = require('../../lib/amazon-mws')(accessKey, accessSecret);

describe('Products', function () {

    before(function () {
        expect(accessKey).to.be.a('string');
        expect(accessSecret).to.be.a('string');
    });

    it('It should get offers using GetLowestPricedOffersForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'ListMatchingProducts',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'Query': 'k'
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');

        var response = await amazonMws.products.searchFor(options);

        expect(response).to.be.a('object');
        expect(response).to.have.property('Products').to.be.a('object');
        expect(response).to.have.property('Products').to.have.property('Product');
        expect(response).to.have.property('ResponseMetadata').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
        expect(response).to.have.property('Headers').to.be.a('object');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
        expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
    });

    it('It should get offers using GetLowestPricedOffersForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetLowestPricedOffersForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASIN': config.ASIN,
            'ItemCondition': 'New'
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options.ASIN).to.be.a('string');

        var response = await amazonMws.products.searchFor(options);

        expect(response).to.be.a('object');
        expect(response).to.have.property('status').to.be.a('string');
        expect(response).to.have.property('Summary').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.be.a('object');
        expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
        expect(response).to.have.property('Headers').to.be.a('object');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
        expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
        expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
    });

    it('It should get my price for ASIN using getMyPriceForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetMyPriceForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': config.ASIN
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options['ASINList.ASIN.1']).to.be.a('string');

        try {
            var response = await amazonMws.products.searchFor(options);
            expect(response).to.be.a('object');
            expect(response).to.have.property('ASIN').to.be.a('string');
            expect(response).to.have.property('status').to.be.a('string');
            expect(response).to.have.property('Product').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
            expect(response).to.have.property('Headers').to.be.a('object');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
        } catch (error) {
            console.log('error ', error);
            expect(error).to.be.undefined;
        }
    });

    it('It should NOT get my price for INVALID ASIN using GetMyPriceForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetMyPriceForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': undefined
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');

        try {
            var response = await amazonMws.products.searchFor(options);
            expect(response).to.be.a('object');
            expect(response).to.have.property('ASIN').to.be.a('string');
            expect(response).to.have.property('status').to.be.a('string');
            expect(response).to.have.property('Product').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
            expect(response).to.have.property('Headers').to.be.a('object');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
        } catch (error) {
            console.log('error ', error);
            expect(error).to.be.a('object');
            expect(error).to.have.property('Type').to.be.a('string');
            expect(error).to.have.property('Message').to.be.a('string');
            // expect(error).to.have.property('Detail').to.be.a('object');
            expect(error).to.have.property('StatusCode').to.be.a('number');
            expect(error).to.have.property('RequestId').to.be.a('string');
            expect(error).to.have.property('Headers').to.be.a('object');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(error).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(error).to.have.property('Headers').to.have.property('x-mws-timestamp');
        }

    });

    it('It should get my price for ASIN using GetCompetitivePricingForASIN Action', async function () {
        var options = {
            'Version': '2011-10-01',
            'Action': 'GetCompetitivePricingForASIN',
            'SellerId': config.SellerId,
            'MWSAuthToken': config.MWSAuthToken,
            'MarketplaceId': config.MarketplaceId,
            'ASINList.ASIN.1': config.ASIN
        };
        expect(options.SellerId).to.be.a('string');
        expect(options.MWSAuthToken).to.be.a('string');
        expect(options.MarketplaceId).to.be.a('string');
        expect(options['ASINList.ASIN.1']).to.be.a('string');

        try {
            var response = await amazonMws.products.searchFor(options);
            expect(response).to.be.a('object');
            expect(response).to.have.property('ASIN').to.be.a('string');
            expect(response).to.have.property('status').to.be.a('string');
            expect(response).to.have.property('Product').to.be.a('object');
            expect(response).to.have.property('Product').to.have.property('CompetitivePricing');
            if (response.Product.CompetitivePricing.NumberOfOfferListings.OfferListingCount) {
                expect(response).to.have.property('Product').to.have.property('CompetitivePricing').to.have.property('NumberOfOfferListings');
                expect(response).to.have.property('Product').to.have.property('CompetitivePricing').to.have.property('NumberOfOfferListings').to.have.property('OfferListingCount').to.be.a('array');
                expect(response.Product.CompetitivePricing.NumberOfOfferListings.OfferListingCount[0]).to.have.property('condition');
                expect(response.Product.CompetitivePricing.NumberOfOfferListings.OfferListingCount[0]).to.have.property('Value');
            }
            expect(response).to.have.property('ResponseMetadata').to.be.a('object');
            expect(response).to.have.property('ResponseMetadata').to.have.property('RequestId');
            expect(response).to.have.property('Headers').to.be.a('object');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-max');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-remaining');
            expect(response).to.have.property('Headers').to.have.property('x-mws-quota-resetson');
            expect(response).to.have.property('Headers').to.have.property('x-mws-timestamp');
        } catch (error) {
            console.log('error ', error);
            expect(error).to.be.undefined;
        }
    });

});<|endoftext|>


<commit_before>/**
 * Test case for mysqlcrudTable.
 * Runs with nodeunit.
 */

var MysqlcrudTable = require('../lib/mysqlcrud_table.js'),
    async = require('async');

var testDbConfig = require('../ci/configs/test_db_config'),
    mysql = require('mysql'),
    extend = require('extend'),
    setupTestDb = require('../ci/helpers/setup_test_db');

var connection;
exports.setUp = function (done) {
    setupTestDb(function (err) {
        connection = mysql.createConnection(extend({}, testDbConfig, {
            database: 'crudmysql_test'
        }));
        connection.connect(function () {
            done();
        });
    });
};
exports.tearDown = function (done) {
    connection.end(function () {
        done();
    });
};

exports['Mysqlcrud table'] = function (test) {
    var table = new MysqlcrudTable('TEST_PERSON', {
        connection: connection,
        idKey: 'id'
    });
    var insertId, insertId2;
    async.series([
        function (callback) {
            table.create({
                last_name: 'foo',
                first_name: 'baz'
            }, function (err, result) {
                test.ifError(err);
                test.ok(result);
                insertId = result.insertId;
                callback(err, result);
            });
        },
        function (callback) {
            table.create({
                last_name: 'foo2',
                first_name: 'baz2'
            }, function (err, result) {
                test.ifError(err);
                test.ok(result);
                insertId2 = result.insertId;
                callback(err, result);
            });
        },
        function (callback) {
            table.one(insertId, function (err, data) {
                test.equal(data.id, insertId);
                test.equal(data.last_name, 'foo');
                test.ifError(err);
                callback(err, data);
            });
        },
        function (callback) {
            table.count({}, function (err, count) {
                test.ifError(err);
                test.ok(count);
                callback(err)
            });
        },
        function (callback) {
            table.count({
                order: ['last_name']
            }, function (err, count) {
                test.ifError(err);
                test.ok(count);
                callback(err)
            });
        },
        function (callback) {
            table.list({}, function (err, data) {
                test.ifError(err);
                test.ok(data.length);
                callback(err)
            });
        },
        function (callback) {
            table.list({
                order: [{'last_name': false}],
                limit: 1,
                offset: 1
            }, function (err, data) {
                test.ifError(err);
                test.ok(data.length);
                callback(err)
            });
        },
        function (callback) {
            table.update(insertId, {
                last_name: 'foo2'
            }, function (err, data) {
                test.ifError(err);
                test.ok(data);
                callback(err);
            });
        },
        function (callback) {
            table.destroy(insertId, function (err, data) {
                test.ifError(err);
                test.ok(data);
                callback(err);
            });
        }
    ], function (err) {
        test.ifError(err);
        test.done();
    });
};

exports['Do ref.'] = function (test) {
    var shopTable = new MysqlcrudTable('TEST_SHOP', {
        connection: connection,
        idKey: 'id'
    });
    var productTable = new MysqlcrudTable('TEST_PRODUCT', {
        connection: connection,
        idKey: 'id'
    });
    var shopId, productId;
    async.series([
        function (callback) {
            shopTable.create({
                article: 20,
                dealer: 'oo',
                price: 100
            }, function (err, result) {
                test.ifError(err);
                shopId = result.insertId;
                callback(err);
            })
        },
        function (callback) {
            productTable.create({
                shop_id: shopId
            }, function (err, result) {
                test.ifError(err);
                productId = result.insertId;
                callback(err);
            })
        },
        function (callback) {
            productTable.list({
                ref: {
                    'shop_id': 'test_shop.id'
                }
            }, function (err, result) {
                test.ok(result[0]);
                test.ok(result[0]['test_shop']);
                test.ifError(err);
                callback(err);
            });
        },
        function (callback) {
            productTable.one(productId, {
                ref: {
                    'shop_id': 'test_shop.id'
                }
            }, function (err, result) {
                test.ok(result);
                test.ok(result['test_shop']);
                test.ifError(err);
                callback(err);
            });
        }
    ], function (err) {
        test.ifError(err);
        test.done();
    });

};<commit_msg>Modify tes<commit_after>/**
 * Test case for mysqlcrudTable.
 * Runs with nodeunit.
 */

var MysqlcrudTable = require('../lib/mysqlcrud_table.js'),
    async = require('async');

var testDbConfig = require('../ci/configs/test_db_config'),
    mysql = require('mysql'),
    extend = require('extend'),
    setupTestDb = require('../ci/helpers/setup_test_db');

var connection;
exports.setUp = function (done) {
    setupTestDb(function (err) {
        connection = mysql.createConnection(extend({}, testDbConfig, {
            database: 'crudmysql_test'
        }));
        connection.connect(function () {
            done();
        });
    });
};
exports.tearDown = function (done) {
    connection.end(function () {
        done();
    });
};

exports['Mysqlcrud table'] = function (test) {
    var table = new MysqlcrudTable('TEST_PERSON', {
        connection: connection,
        idKey: 'id'
    });
    var insertId, insertId2;
    async.series([
        function (callback) {
            table.create({
                last_name: 'foo',
                first_name: 'baz'
            }, function (err, result) {
                test.ifError(err);
                test.ok(result);
                insertId = result.insertId;
                callback(err, result);
            });
        },
        function (callback) {
            table.create({
                last_name: 'foo2',
                first_name: 'baz2'
            }, function (err, result) {
                test.ifError(err);
                test.ok(result);
                insertId2 = result.insertId;
                callback(err, result);
            });
        },
        function (callback) {
            table.one(insertId, function (err, data) {
                test.equal(data.id, insertId);
                test.equal(data.last_name, 'foo');
                test.ifError(err);
                callback(err, data);
            });
        },
        function (callback) {
            table.count({}, function (err, count) {
                test.ifError(err);
                test.ok(count);
                callback(err)
            });
        },
        function (callback) {
            table.count({
                order: ['last_name']
            }, function (err, count) {
                test.ifError(err);
                test.ok(count);
                callback(err)
            });
        },
        function (callback) {
            table.list({}, function (err, data) {
                test.ifError(err);
                test.ok(data.length);
                callback(err)
            });
        },
        function (callback) {
            table.list({
                order: [{'last_name': false}],
                limit: 1,
                offset: 1
            }, function (err, data) {
                test.ifError(err);
                test.ok(data.length);
                callback(err)
            });
        },
        function (callback) {
            table.update(insertId, {
                last_name: 'foo2'
            }, function (err, data) {
                test.ifError(err);
                test.ok(data);
                callback(err);
            });
        },
        function (callback) {
            table.destroy(insertId, function (err, data) {
                test.ifError(err);
                test.ok(data);
                callback(err);
            });
        }
    ], function (err) {
        test.ifError(err);
        test.done();
    });
};

exports['Do ref.'] = function (test) {
    var shopTable = new MysqlcrudTable('TEST_SHOP', {
        connection: connection,
        idKey: 'id'
    });
    var productTable = new MysqlcrudTable('TEST_PRODUCT', {
        connection: connection,
        idKey: 'id'
    });
    var shopId, productId;
    async.series([
        function (callback) {
            shopTable.create({
                article: 20,
                dealer: 'oo',
                price: 100
            }, function (err, result) {
                test.ifError(err);
                shopId = result.insertId;
                callback(err);
            })
        },
        function (callback) {
            productTable.create({
                shop_id: shopId
            }, function (err, result) {
                test.ifError(err);
                productId = result.insertId;
                callback(err);
            })
        },
        //function (callback) {
        //    productTable.list({
        //        ref: {
        //            'shop_id': 'test_shop.id'
        //        }
        //    }, function (err, result) {
        //        test.ok(result[0]);
        //        test.ok(result[0]['test_shop']);
        //        test.ifError(err);
        //        callback(err);
        //    });
        //},
        //function (callback) {
        //    productTable.one(productId, {
        //        ref: {
        //            'shop_id': 'test_shop.id'
        //        }
        //    }, function (err, result) {
        //        test.ok(result);
        //        test.ok(result['test_shop']);
        //        test.ifError(err);
        //        callback(err);
        //    });
        //}
    ], function (err) {
        test.ifError(err);
        test.done();
    });

};<|endoftext|>


<commit_before>steal('can/util',
	  'can/view',
	  'can/view/scanner.js',
	  'can/observe/compute',
	  'can/view/render.js',
function( can ){

	can.view.ext = ".mustache";

	var extend = can.extend,
		CONTEXT = '___c0nt3xt',
		Mustache = function( options ) {
			// Supports calling Mustache without the constructor
			// This returns a function that renders the template.
			if ( this.constructor != Mustache ) {
				var mustache = new Mustache(options);
				return function( data, helpers ) {
					 return mustache.render(data, helpers);
				};
			}

			// If we get a `function` directly, it probably is coming from
			// a `steal`-packaged view.
			if ( typeof options == "function" ) {
				this.template = {
					fn: options
				};
				return;
			}

			// Set options on self.
			extend(this, options);
			this.template = this.scanner.scan(this.text, this.name);
		};

	can.Mustache = window.Mustache = Mustache;

	/**
	 * @Prototype
	 */
	Mustache.prototype.
	/**
	 * Renders an object with view helpers attached to the view.
	 *
	 *		 new Mustache({text: "<%= message %>"}).render({
	 *			 message: "foo"
	 *		 },{helper: function(){ ... }})
	 *
	 * @param {Object} object data to be rendered
	 * @param {Object} [extraHelpers] an object with view helpers
	 * @return {String} returns the result of the string
	 */
	render = function( object, extraHelpers ) {
		object = object || {};
		return this.template.fn.call(object, object, new Mustache.Helpers(object, extraHelpers || {}));
	};

	extend(Mustache.prototype, {
		/**
		 * Singleton scanner instance for parsing templates.
		 */
		scanner: new can.view.Scanner({
			/**
			 * Inject additional start text.
			 */
			startTxt: 'var ' + CONTEXT + ' = {};',

			/**
			 * An ordered token registry for the scanner.
			 * This needs to be ordered by priority to prevent token parsing errors.
			 * Each token is defined as: ["token-name", "string representation", "optional regexp override"]
			 */
			tokens: [
				["templateLeft", "{{$"], // Template	 ---- Not supported
				["templateRight", "$}}"], // Right Template	---- Not supported
				["returnLeft", "{{{", "{{[{&]"], // Return Unescaped
				// ["commentFull", "{{!}}", "[\\s\\t]*{{!.+?}}\\n?"], // Comment
				["commentLeft", "{{!", "(\\n[\\s\\t]*{{!|{{!)"], // Comment
				["left", "{{~"], // Run
				["escapeLeft", "{{"], // Return Escaped
				["returnRight", "}}}"],
				["right", "}}"] // Right -> All have same FOR Mustache ...
			],

			helpers: [
				/**
				 * Partials
				 * Partials begin with a greater than sign, like {{> box}}.
				 *
				 * Partials are rendered at runtime (as opposed to compile time),
				 * so recursive partials are possible. Just avoid infinite loops.
				 *
				 * For example, this template and partial:
				 *
				 * 		base.mustache:
				 *
Names

				 * 			{{#names}}
				 * 				{{> user}}
				 * 			{{/names}}
				 *
				 * 		user.mustache:
				 * 			{{name}}
				 */
				{
					name: /^>[\s|\w]\w*/,
					fn:function(content, cmd){
						return "can.view.render('" + content.replace(/^>\s?/, '').trim() + "', _CONTEXT)";
					}
				},

				/**
				 * Convert the expression for use with interpolation/helpers.
				 */
				{
					name: /^.*$/,
					fn: function(content, cmd) {
						// Parse content
						var mode = false,
							result = [];
						if (content.length && (mode = content.match(/^([#^/]|else$)/))) {
							mode = mode[0];
							switch (mode) {
								case '#':
								case '^':
									result.push(cmd.insert + 'can.view.txt(0,"",0,this,function(){ return ');
									break;
								// Close section
								case '/':
									return { raw: '}}])}));' };
									break;
							}
							content = content.substring(1);
						}

						if (mode != 'else') {
							var args = content.replace(/^\s*/,'').replace(/\s*$/,'').split(/\s/),
								i = 0,
								arg, split;
							result.push('can.Mustache.txt(can.extend({}, ' + CONTEXT + ', this),' + (mode ? '"'+mode+'"' : 'null') + ',');

							// Append helper requests as a name string
							if (args.length > 1) {
								i = 1;
								result.push('"' + args[0] + '"');
							}

							// Iterate through the arguments
							for (; arg = args[i]; i++) {
								i > 0 && result.push(',');
								result.push('can.Mustache.get("' + arg.replace(/"/g,'\\"') + '",this,' + CONTEXT + ')');
							}
						}

						// Handle sections
						mode && mode != 'else' && result.push(',[{_:{');
						switch (mode) {
							// Truthy section
							case '#':
								result.push('}},{fn:function(' + CONTEXT + '){');
								break;
							// If/else section
							case 'else':
								result.push('}},{inverse:function(' + CONTEXT + '){');
								break;
							// Falsey section
							case '^':
								result.push('}},{inverse:function(' + CONTEXT + '){');
								break;

							// Not a section
							default:
								result.push(');');
								break;
						}

						result = result.join('');
						return mode ? { raw: result } : result;
					}
				}
			]
		})
	});

	/**
	 * Addin default helpers first.  We could prob do this
	 * differently if we didn't 'break' on every match.
	 */
	var helpers = can.view.Scanner.prototype.helpers;
	for (var i = 0; i < helpers.length; i++) {
		Mustache.prototype.scanner.helpers.unshift(helpers[i]);
	};

	Mustache.Helpers = function( data, extras ) {
		this._data = data;
		this._extras = extras;
		extend(this, extras);
	};

	Mustache.registerHelper = function(name, fn){
		this._helpers.push({ name: name, fn: fn });
	};

	Mustache.registerPartial = function(id, text) {
		// Get the renderer function.
		var d = new can.Deferred(),
			type = can.view.types['.mustache'],
			func = type.renderer(id, text);

		// Cache if we are caching.
		if ( can.view.cache ) {
			can.view.cached[id] = d;
			d.__view_id = id;
			can.view.cachedRenderers[id] = func;
		}

		d.resolve(func);
	};

	/**
	 * @param {String} [mode]	The mode to evaluate the section with: # for truthy, ^ for falsey
	 */
	Mustache.txt = function(context, mode, name) {
		var args = Array.prototype.slice.call(arguments, 3),
			options = can.extend.apply(can, [{
					fn: function() {},
					inverse: function() {}
				}].concat(mode ? args.pop() : [])),
			validArgs = args.length > 0 ? args : [name],
			valid = true,
			result = [],
			i, helper;

		// Validate based on the mode if necessary
		if (mode) {
			for (i = 0; i < validArgs.length; i++) {
				if (can.isArray(validArgs[i])) {
					valid = mode == '#' ? valid && !!validArgs[i].length
						: mode == '^' ? valid && !validArgs[i].length
						: valid;
				}
				else {
					valid = mode == '#' ? valid && !!validArgs[i]
						: mode == '^' ? valid && !validArgs[i]
						: valid;
				}
			}
		}

		// If there is more than one argument, it's a helper
		if (args.length > 0) {
			for (i = 0; helper = this._helpers[i]; i++) {
				// Find the correct helper
				if (helper.name == name) {
					args.push({
						fn: can.proxy(options.fn, context),
						inverse: can.proxy(options.inverse, context)
					});
					return helper.fn.apply(context, args) || '';
				}
			}
			return '';
		}
		// Otherwise interpolate like normal
		else if (valid) {
			// Handle truthyness
			switch (mode) {
				case '#':
					// Iterate over arrays
					if (can.isArray(name)) {
						for (i = 0; i < name.length; i++) {
							result.push(options.fn.call(name[i] || {}, context) || '');
						}
						return result.join('');
					}
					// Normal case.
					else {
						return options.fn.call(name || {}, context) || '';
					}
					break;
				case '^':
					return options.inverse.call(name || {}, context) || '';
					break;
				default:
					return '' + (name || '');
					break;
			}
		}
	};

	/**
	 * Resolves a reference for a given object (and then a context if that fails).
	 *	obj = this
	 *	context = { a: true }
	 *	ref = 'a.b.c'
	 *		=> obj.a.b.c || context.a.b.c || ''
	 *
	 * This implements the following Mustache specs:
	 * 	Deeply Nested Contexts
	 *	All elements on the context stack should be accessible.
	 *		{{#bool}}B {{#bool}}C{{/bool}} D{{/bool}}
	 *		{ bool: true }
	 *		=> "B C D"
	 * 	Basic Context Miss Interpolation
	 * 	Failed context lookups should default to empty strings.
	 *  	{{cannot}}
	 *		=> ""
	 * 	Dotted Names - Broken Chains
	 * 	Any falsey value prior to the last part of the name should yield ''.
	 *		{{a.b.c}}
	 *		{ a: { d: 1 } }
	 *		=> ""
	 *
	 * @param {String} ref      The reference to check for on the obj/context.
	 * @param {Object} obj  		The object to use for checking for a reference.
	 * @param {Object} context  The context to use for checking for a reference if it doesn't exist in the object.
	 */
	Mustache.get = function(ref, obj, context) {
		var contexts = [obj, context],
			names = ref.split('.'),
			lastValue, value, name, i, j;

		// Handle "this" references for list iteration: {{.}} or {{this}}
		if (/^\.|this$/.test(ref)) {
			return obj || context || '';
		}
		// Handle object resolution.
		else {
			for (i = 0; i < contexts.length; i++) {
				// Check the context for the reference
				value = contexts[i];

				// Make sure the context isn't a failed object before diving into it.
				if (value !== undefined) {
					for (j = 0; j < names.length; j++) {
						// Keep running up the tree while there are matches.
						if (typeof value[names[j]] != 'undefined') {
							lastValue = value;
							value = value[name = names[j]];
						}
						else {
							lastValue = value = undefined;
							break;
						}
					}
				}

				// Found a matched reference
				if (value !== undefined) {
					// Add support for observes
					if (can.isFunction(lastValue.attr) && lastValue.constructor && lastValue.constructor.canMakeObserve) {
						return lastValue.attr(name);
					}
					// Support functions stored in objects
					else if (can.isFunction(lastValue[name])) {
						return lastValue[name]();
					}
					else {
						return value;
					}
				}
			}
		}

		return '';
	};

	Mustache._helpers = [
		// if, else, unless, each, with

		/**
		 * {{#if expr}}
		 *   Do {{something}}
		 * {{else}}
		 *   Do {{nothing}}
		 * {{/if}}
		 */
		{
			name: 'if',
			fn: function(expr, options){
				if (!!expr) {
					return options.fn(this);
				}
				else {
					return options.inverse(this);
				}
			}
		},

		{
			name: 'unless',
			fn: function(expr, options){
				if (!expr) {
					return options.fn(this);
				}
			}
		},

		{
			name: 'each',
			fn: function(expr, options) {
				if (!!expr && expr.length) {
					var result = [];
					for (var i = 0; i < expr.length; i++) {
						result.push(options.fn(expr[i]));
					}
					return result.join('');
				}
			}
		},

		{
			name: 'with',
			fn: function(expr, options){
				if (!!expr) {
					return options.fn(expr);
				}
			}
		}
	];

	/**
	 * Register the view.
	 */
	can.view.register({
		suffix: "mustache",

		contentType: "x-mustache-template",

		// returns a `function` that renders the view.
		script: function( id, src ) {
			return "can.Mustache(function(_CONTEXT,_VIEW) { " + new Mustache({
				text: src,
				name: id
			}).template.out + " })";
		},

		renderer: function( id, text ) {
			return Mustache({
				text: text,
				name: id
			});
		}
	});

});<commit_msg>Fixed recursive mustache partials.<commit_after>steal('can/util',
	  'can/view',
	  'can/view/scanner.js',
	  'can/observe/compute',
	  'can/view/render.js',
function( can ){

	can.view.ext = ".mustache";

	var extend = can.extend,
		CONTEXT = '___c0nt3xt',
		Mustache = function( options ) {
			// Supports calling Mustache without the constructor
			// This returns a function that renders the template.
			if ( this.constructor != Mustache ) {
				var mustache = new Mustache(options);
				return function( data, helpers ) {
					 return mustache.render(data, helpers);
				};
			}

			// If we get a `function` directly, it probably is coming from
			// a `steal`-packaged view.
			if ( typeof options == "function" ) {
				this.template = {
					fn: options
				};
				return;
			}

			// Set options on self.
			extend(this, options);
			this.template = this.scanner.scan(this.text, this.name);
		};

	can.Mustache = window.Mustache = Mustache;

	/**
	 * @Prototype
	 */
	Mustache.prototype.
	/**
	 * Renders an object with view helpers attached to the view.
	 *
	 *		 new Mustache({text: "<%= message %>"}).render({
	 *			 message: "foo"
	 *		 },{helper: function(){ ... }})
	 *
	 * @param {Object} object data to be rendered
	 * @param {Object} [extraHelpers] an object with view helpers
	 * @return {String} returns the result of the string
	 */
	render = function( object, extraHelpers ) {
		object = object || {};
		return this.template.fn.call(object, object, new Mustache.Helpers(object, extraHelpers || {}));
	};

	extend(Mustache.prototype, {
		/**
		 * Singleton scanner instance for parsing templates.
		 */
		scanner: new can.view.Scanner({
			/**
			 * Inject additional start text.
			 */
			startTxt: 'var ' + CONTEXT + ' = {};',

			/**
			 * An ordered token registry for the scanner.
			 * This needs to be ordered by priority to prevent token parsing errors.
			 * Each token is defined as: ["token-name", "string representation", "optional regexp override"]
			 */
			tokens: [
				["templateLeft", "{{$"], // Template	 ---- Not supported
				["templateRight", "$}}"], // Right Template	---- Not supported
				["returnLeft", "{{{", "{{[{&]"], // Return Unescaped
				// ["commentFull", "{{!}}", "[\\s\\t]*{{!.+?}}\\n?"], // Comment
				["commentLeft", "{{!", "(\\n[\\s\\t]*{{!|{{!)"], // Comment
				["left", "{{~"], // Run
				["escapeLeft", "{{"], // Return Escaped
				["returnRight", "}}}"],
				["right", "}}"] // Right -> All have same FOR Mustache ...
			],

			helpers: [
				/**
				 * Partials
				 * Partials begin with a greater than sign, like {{> box}}.
				 *
				 * Partials are rendered at runtime (as opposed to compile time),
				 * so recursive partials are possible. Just avoid infinite loops.
				 *
				 * For example, this template and partial:
				 *
				 * 		base.mustache:
				 *
Names

				 * 			{{#names}}
				 * 				{{> user}}
				 * 			{{/names}}
				 *
				 * 		user.mustache:
				 * 			{{name}}
				 */
				{
					name: /^>[\s|\w]\w*/,
					fn:function(content, cmd){
						return "can.view.render('" + content.replace(/^>\s?/, '').trim() + "', can.extend({}, " + CONTEXT + ", this))";
					}
				},

				/**
				 * Convert the expression for use with interpolation/helpers.
				 */
				{
					name: /^.*$/,
					fn: function(content, cmd) {
						// Parse content
						var mode = false,
							result = [];
						if (content.length && (mode = content.match(/^([#^/]|else$)/))) {
							mode = mode[0];
							switch (mode) {
								case '#':
								case '^':
									result.push(cmd.insert + 'can.view.txt(0,"",0,this,function(){ return ');
									break;
								// Close section
								case '/':
									return { raw: '}}])}));' };
									break;
							}
							content = content.substring(1);
						}

						if (mode != 'else') {
							var args = content.replace(/^\s*/,'').replace(/\s*$/,'').split(/\s/),
								i = 0,
								arg, split;
							result.push('can.Mustache.txt(can.extend({}, ' + CONTEXT + ', this),' + (mode ? '"'+mode+'"' : 'null') + ',');

							// Append helper requests as a name string
							if (args.length > 1) {
								i = 1;
								result.push('"' + args[0] + '"');
							}

							// Iterate through the arguments
							for (; arg = args[i]; i++) {
								i > 0 && result.push(',');
								result.push('can.Mustache.get("' + arg.replace(/"/g,'\\"') + '",this,' + CONTEXT + ')');
							}
						}

						// Handle sections
						mode && mode != 'else' && result.push(',[{_:{');
						switch (mode) {
							// Truthy section
							case '#':
								result.push('}},{fn:function(' + CONTEXT + '){');
								break;
							// If/else section
							case 'else':
								result.push('}},{inverse:function(' + CONTEXT + '){');
								break;
							// Falsey section
							case '^':
								result.push('}},{inverse:function(' + CONTEXT + '){');
								break;

							// Not a section
							default:
								result.push(');');
								break;
						}

						result = result.join('');
						return mode ? { raw: result } : result;
					}
				}
			]
		})
	});

	/**
	 * Addin default helpers first.  We could prob do this
	 * differently if we didn't 'break' on every match.
	 */
	var helpers = can.view.Scanner.prototype.helpers;
	for (var i = 0; i < helpers.length; i++) {
		Mustache.prototype.scanner.helpers.unshift(helpers[i]);
	};

	Mustache.Helpers = function( data, extras ) {
		this._data = data;
		this._extras = extras;
		extend(this, extras);
	};

	Mustache.registerHelper = function(name, fn){
		this._helpers.push({ name: name, fn: fn });
	};

	Mustache.registerPartial = function(id, text) {
		// Get the renderer function.
		var d = new can.Deferred(),
			type = can.view.types['.mustache'],
			func = type.renderer(id, text);

		// Cache if we are caching.
		if ( can.view.cache ) {
			can.view.cached[id] = d;
			d.__view_id = id;
			can.view.cachedRenderers[id] = func;
		}

		d.resolve(func);
	};

	/**
	 * @param {String} [mode]	The mode to evaluate the section with: # for truthy, ^ for falsey
	 */
	Mustache.txt = function(context, mode, name) {
		var args = Array.prototype.slice.call(arguments, 3),
			options = can.extend.apply(can, [{
					fn: function() {},
					inverse: function() {}
				}].concat(mode ? args.pop() : [])),
			validArgs = args.length > 0 ? args : [name],
			valid = true,
			result = [],
			i, helper;

		// Validate based on the mode if necessary
		if (mode) {
			for (i = 0; i < validArgs.length; i++) {
				if (can.isArray(validArgs[i])) {
					valid = mode == '#' ? valid && !!validArgs[i].length
						: mode == '^' ? valid && !validArgs[i].length
						: valid;
				}
				else {
					valid = mode == '#' ? valid && !!validArgs[i]
						: mode == '^' ? valid && !validArgs[i]
						: valid;
				}
			}
		}

		// If there is more than one argument, it's a helper
		if (args.length > 0) {
			for (i = 0; helper = this._helpers[i]; i++) {
				// Find the correct helper
				if (helper.name == name) {
					args.push({
						fn: can.proxy(options.fn, context),
						inverse: can.proxy(options.inverse, context)
					});
					return helper.fn.apply(context, args) || '';
				}
			}
			return '';
		}
		// Otherwise interpolate like normal
		else if (valid) {
			// Handle truthyness
			switch (mode) {
				case '#':
					// Iterate over arrays
					if (can.isArray(name)) {
						for (i = 0; i < name.length; i++) {
							result.push(options.fn.call(name[i] || {}, context) || '');
						}
						return result.join('');
					}
					// Normal case.
					else {
						return options.fn.call(name || {}, context) || '';
					}
					break;
				case '^':
					return options.inverse.call(name || {}, context) || '';
					break;
				default:
					return '' + (name || '');
					break;
			}
		}
	};

	/**
	 * Resolves a reference for a given object (and then a context if that fails).
	 *	obj = this
	 *	context = { a: true }
	 *	ref = 'a.b.c'
	 *		=> obj.a.b.c || context.a.b.c || ''
	 *
	 * This implements the following Mustache specs:
	 * 	Deeply Nested Contexts
	 *	All elements on the context stack should be accessible.
	 *		{{#bool}}B {{#bool}}C{{/bool}} D{{/bool}}
	 *		{ bool: true }
	 *		=> "B C D"
	 * 	Basic Context Miss Interpolation
	 * 	Failed context lookups should default to empty strings.
	 *  	{{cannot}}
	 *		=> ""
	 * 	Dotted Names - Broken Chains
	 * 	Any falsey value prior to the last part of the name should yield ''.
	 *		{{a.b.c}}
	 *		{ a: { d: 1 } }
	 *		=> ""
	 *
	 * @param {String} ref      The reference to check for on the obj/context.
	 * @param {Object} obj  		The object to use for checking for a reference.
	 * @param {Object} context  The context to use for checking for a reference if it doesn't exist in the object.
	 */
	Mustache.get = function(ref, obj, context) {
		var contexts = [obj, context],
			names = ref.split('.'),
			lastValue, value, name, i, j;

		// Handle "this" references for list iteration: {{.}} or {{this}}
		if (/^\.|this$/.test(ref)) {
			return obj || context || '';
		}
		// Handle object resolution.
		else {
			for (i = 0; i < contexts.length; i++) {
				// Check the context for the reference
				value = contexts[i];

				// Make sure the context isn't a failed object before diving into it.
				if (value !== undefined) {
					for (j = 0; j < names.length; j++) {
						// Keep running up the tree while there are matches.
						if (typeof value[names[j]] != 'undefined') {
							lastValue = value;
							value = value[name = names[j]];
						}
						else {
							lastValue = value = undefined;
							break;
						}
					}
				}

				// Found a matched reference
				if (value !== undefined) {
					// Add support for observes
					if (can.isFunction(lastValue.attr) && lastValue.constructor && lastValue.constructor.canMakeObserve) {
						return lastValue.attr(name);
					}
					// Support functions stored in objects
					else if (can.isFunction(lastValue[name])) {
						return lastValue[name]();
					}
					else {
						return value;
					}
				}
			}
		}

		return '';
	};

	Mustache._helpers = [
		// if, else, unless, each, with

		/**
		 * {{#if expr}}
		 *   Do {{something}}
		 * {{else}}
		 *   Do {{nothing}}
		 * {{/if}}
		 */
		{
			name: 'if',
			fn: function(expr, options){
				if (!!expr) {
					return options.fn(this);
				}
				else {
					return options.inverse(this);
				}
			}
		},

		{
			name: 'unless',
			fn: function(expr, options){
				if (!expr) {
					return options.fn(this);
				}
			}
		},

		{
			name: 'each',
			fn: function(expr, options) {
				if (!!expr && expr.length) {
					var result = [];
					for (var i = 0; i < expr.length; i++) {
						result.push(options.fn(expr[i]));
					}
					return result.join('');
				}
			}
		},

		{
			name: 'with',
			fn: function(expr, options){
				if (!!expr) {
					return options.fn(expr);
				}
			}
		}
	];

	/**
	 * Register the view.
	 */
	can.view.register({
		suffix: "mustache",

		contentType: "x-mustache-template",

		// returns a `function` that renders the view.
		script: function( id, src ) {
			return "can.Mustache(function(_CONTEXT,_VIEW) { " + new Mustache({
				text: src,
				name: id
			}).template.out + " })";
		},

		renderer: function( id, text ) {
			return Mustache({
				text: text,
				name: id
			});
		}
	});

});<|endoftext|>