<commit_before>(function($) {

  var intIntervalTime = 100;
	var newpage;
	var pageurl = window.location.href;
	var data;
	var editableData;
	var pageType

	editableData = {
		"t1":[
			{"class":'.slate--home--hero-banner .grid-col ',"jsonKey":"uri"},
			//{"class":'.slate--home--hero-banner .grid-col ',"jsonKey":"name"},
			],
		"t2":[],
		"t3":[],
		"t4":[],
		"t5":[]
	}

	setupFlorence();
	// renderPage();

	// URI simple parser
	var parser = document.createElement('a');
	parser.href = pageurl.replace("#!/", ""); //takes out #! from Angular.js
	parser.protocol; // => "http:"
	parser.hostname; // => "example.com"
	parser.port;     // => "3000"
	parser.pathname; // => "/pathname/"
	parser.search;   // => "?search=test"
	parser.hash;     // => "#hash"
	parser.host;     // => "example.com:3000"

	var checkLocation = function() {
		if (pageurl != window.location.href) {
			pageurl = window.location.href;
			$(window.location).trigger("change", {
				newpage: getPageData()
			});
		}
	}

	function getPageData(){
		pageurldata = pageurl.replace("#!", "data");

		$.ajax({
			url:pageurldata,
			dataType: 'json', // Notice! JSONP <-- P (lowercase)
			crossDomain: true,
			// jsonpCallback: 'callback',
			// type: 'GET',
			success:function(response){
				// do stuff with json (in this case an array)
				// console.log("Success");
				data = response
				pageType = data.level
				addEditSections()
			},
			error:function(){
				console.log('Error');
			}
		});
	}

	var florenceForm = '
'                   +
	 											'Edit'       +
												'
'                     +
													'Cancel' +
													'<form onsubmit="return false;">'                   +
														'<textarea id="json"></textarea>'                 +
														'<button class="florence-update" >Update</button>'+
													'</form>'                                           +
												'
'                                              +
											'
';

	function addEditSections(){
		for(i = 0; i < editableData[pageType].length; i ++){
			var selector, jsonKey
			selector = editableData[pageType][i].class
			jsonKey  = editableData[pageType][i].jsonKey

			$(selector).each(function(index,element){
				var jsonUpdater,jsonPath,uriUpdater;

				setJsonPath(jsonKey);
				jsonUpdater =makeUpdateFunction(jsonKey);
				$(element).prepend(florenceForm);
				$('textarea',element).val(jsonPath);
				editableForm(element,index,jsonUpdater);

				function setJsonPath(jsonKey){
					// will eventually handle all the data paths
					if(data.level === "t1"){
						//find the old value to prepoulate the form
						if(jsonKey !== "uri"){
							jsonPath = data['sections'][index]['items'][0][jsonKey]
						} else {
							splitUrl = data['sections'][index]['items'][0][jsonKey].split("/")
							jsonPath = splitUrl[splitUrl.length - 2] === "timeseries" ? splitUrl[splitUrl.length - 1] : splitUrl[splitUrl.length - 2]
						}

					} else if( data.level === "t2"){
						console.log(" error - t2 data path not implemented")
					} else if(true){
					 	console.log("error getting path to json data ")}
				}

				function makeUpdateFunction(jsonKey){

					if(jsonKey !== "uri"){
						return function(newVal){
							data['sections'][index]['items'][0][jsonKey] = newVal;
						}
					} else {
							return makeUriUpdater(index,jsonKey)
					}
				}

				function makeUriUpdater(index,jsonKey){
					return function uriUpdater(cdid){
						var url
						$.ajax({
							url: "http://localhost:8080/search?cdid=" +cdid,
							crossDomain: true,
							dataType: "json",
							async: false,
							success:function(response){
								url = response;
								console.log(url)
							},
							error:function(){console.log( "error retrieving url from tredegar")}
						})

						data['sections'][index]['items'][0][jsonKey] = url;

					}
				}
			});
		}

		function editableForm(element,index,jsonUpdater) {
			$('.florence-editbtn',element).click(function(){
				$('.florence-editform',element).show();
			});

			$('.florence-cancelbtn',element).click(function(){
				$('.florence-editform',element).hide();
			});

			$('.florence-update',element).click(function(){
				jsonUpdater($('textarea',element).val());
				updatePage();
			});
		}
	}

  function setupFlorence(){
  	$('head').prepend('<link href="http://localhost:8081/css/main.css" rel="stylesheet" type="text/css">');
  	var bodycontent = $('body').html();
  	var florence_bar =
  		'
'                                               +
  			'
Florence v0.1
'                     +
  			''                                         +
  				'
'                                                             +
  					'
Edit
' +
  						'
'                                     +
  							'
Save changes
'      +
  							'
Cancel changes
'  +
  						'
'                                                        +
  					'
Versions
'         +
  					'
Tasks
'               +
  					'
Site map
'          +
  				'
'                                                            +
  			''                                                             +
  		'
';
  	$('body').wrapInner('

');
  	$('body').prepend(florence_bar);

		$('.fl-edit').click(function(){
			// console.log('Florence Edit clicked');
			// $('.florence-editform').show();
			getPageData();
		});

	}

	function updatePage(){
		$.ajax({
	           url:"http://localhost:8081/data",
	           type:"POST",
	           data: JSON.stringify({
	               json: JSON.stringify(data),
                   id: parser.pathname
	           }),
	           contentType:"application/json; charset=utf-8",
	           dataType:"text"
	       	}).done(function(){
	           console.log("Done!");
	           location.reload();
	       	}).fail(function(jqXHR, textStatus){
	           alert(textStatus);
	       	})
	}

	setInterval(checkLocation, intIntervalTime);

})(jQuery);
<commit_msg>editing a url now retrieves related data and updates the name<commit_after>(function($) {

  var intIntervalTime = 100;
	var newpage;
	var pageurl = window.location.href;
	var data;
	var editableData;
	var pageType

	editableData = {
		"t1":[
			{"class":'.slate--home--hero-banner .grid-col ',"jsonKey":"uri"},
			//{"class":'.slate--home--hero-banner .grid-col ',"jsonKey":"name"},
			],
		"t2":[],
		"t3":[],
		"t4":[],
		"t5":[]
	}

	setupFlorence();
	// renderPage();

	// URI simple parser
	var parser = document.createElement('a');
	parser.href = pageurl.replace("#!/", ""); //takes out #! from Angular.js
	parser.protocol; // => "http:"
	parser.hostname; // => "example.com"
	parser.port;     // => "3000"
	parser.pathname; // => "/pathname/"
	parser.search;   // => "?search=test"
	parser.hash;     // => "#hash"
	parser.host;     // => "example.com:3000"

	var checkLocation = function() {
		if (pageurl != window.location.href) {
			pageurl = window.location.href;
			$(window.location).trigger("change", {
				newpage: getPageData()
			});
		}
	}

	function getPageData(){
		pageurldata = pageurl.replace("#!", "data");

		$.ajax({
			url:pageurldata,
			dataType: 'json', // Notice! JSONP <-- P (lowercase)
			crossDomain: true,
			// jsonpCallback: 'callback',
			// type: 'GET',
			success:function(response){
				// do stuff with json (in this case an array)
				// console.log("Success");
				data = response
				pageType = data.level
				addEditSections()
			},
			error:function(){
				console.log('Error');
			}
		});
	}

	var florenceForm = '
'                   +
	 											'Edit'       +
												'
'                     +
													'Cancel' +
													'<form onsubmit="return false;">'                   +
														'<textarea id="json"></textarea>'                 +
														'<button class="florence-update" >Update</button>'+
													'</form>'                                           +
												'
'                                              +
											'
';

	function addEditSections(){
		for(i = 0; i < editableData[pageType].length; i ++){
			var selector, jsonKey
			selector = editableData[pageType][i].class
			jsonKey  = editableData[pageType][i].jsonKey

			$(selector).each(function(index,element){
				var jsonUpdater,jsonPath,uriUpdater;

				setJsonPath(jsonKey);
				jsonUpdater =makeUpdateFunction(jsonKey);
				$(element).prepend(florenceForm);
				$('textarea',element).val(jsonPath);
				editableForm(element,index,jsonUpdater);

				function setJsonPath(jsonKey){
					// will eventually handle all the data paths
					if(data.level === "t1"){
						//find the old value to prepoulate the form
						if(jsonKey !== "uri"){
							jsonPath = data['sections'][index]['items'][0][jsonKey]
						} else {
							splitUrl = data['sections'][index]['items'][0][jsonKey].split("/")
							jsonPath = splitUrl[splitUrl.length - 2] === "timeseries" ? splitUrl[splitUrl.length - 1] : splitUrl[splitUrl.length - 2]
						}

					} else if( data.level === "t2"){
						console.log(" error - t2 data path not implemented")
					} else if(true){
					 	console.log("error getting path to json data ")}
				}

				function makeUpdateFunction(jsonKey){

					if(jsonKey !== "uri"){
						return function(newVal){
							data['sections'][index]['items'][0][jsonKey] = newVal;
						}
					} else {
							return makeUriUpdater(index,jsonKey)
					}
				}

				// Create a form to modify text and pass JSON data

				// TODO Kane editable form takes an update function and a  initial value as args

				function makeUriUpdater(index,jsonKey){
					return function uriUpdater(cdid){
						var url
						$.ajax({
							url: "http://localhost:8080/search?cdid=" +cdid,
							crossDomain: true,
							dataType: "json",
							async: false,
							success:function(response){
								url = response;
								console.log(url)
							},
							error:function(){console.log( "error retrieving url from tredegar")}
						})

						data['sections'][index]['items'][0][jsonKey] = url;
						console.log(url)

						$.ajax({
							url:"http://localhost:8080/data"+url,
							crossDomain:true,
							dataType:"json",
							async:false,
							success:function(response){
								data['sections'][index]['items'][0]["name"] = response["name"]
							},
							error:function(){console.log("error retrieving data from tredegar")}
						})
					}
				}
			});
		}

		function editableForm(element,index,jsonUpdater) {
			$('.florence-editbtn',element).click(function(){
				$('.florence-editform',element).show();
			});

			$('.florence-cancelbtn',element).click(function(){
				$('.florence-editform',element).hide();
			});

			$('.florence-update',element).click(function(){
				jsonUpdater($('textarea',element).val());
				updatePage();
			});
		}
	}

  function setupFlorence(){
  	$('head').prepend('<link href="http://localhost:8081/css/main.css" rel="stylesheet" type="text/css">');
  	var bodycontent = $('body').html();
  	var florence_bar =
  		'
'                                               +
  			'
Florence v0.1
'                     +
  			''                                         +
  				'
'                                                             +
  					'
Edit
' +
  						'
'                                     +
  							'
Save changes
'      +
  							'
Cancel changes
'  +
  						'
'                                                        +
  					'
Versions
'         +
  					'
Tasks
'               +
  					'
Site map
'          +
  				'
'                                                            +
  			''                                                             +
  		'
';
  	$('body').wrapInner('

');
  	$('body').prepend(florence_bar);

		$('.fl-edit').click(function(){
			// console.log('Florence Edit clicked');
			// $('.florence-editform').show();
			getPageData();
		});

	}

	function updatePage(){
		$.ajax({
	           url:"http://localhost:8081/data",
	           type:"POST",
	           data: JSON.stringify({
	               json: JSON.stringify(data),
                   id: parser.pathname
	           }),
	           contentType:"application/json; charset=utf-8",
	           dataType:"text"
	       	}).done(function(){
	           console.log("Done!");
	           location.reload();
	       	}).fail(function(jqXHR, textStatus){
	           alert(textStatus);
	       	})
	}

	setInterval(checkLocation, intIntervalTime);

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

module.exports = [
    {
        func: 'hears',
        args: [['start (.*) (\\d)'], ['direct_mention'], (bot, msg) => {
            var time = msg.match(1);
            var numchairs = msg.match(2);
            bot.reply(msg, `Ok, let's start a game at ${time} with ${numchairs} chairs`);
        }]
    }, {
        func: 'hears',
        args: [['sit (\\d)'], ['direct_message'], (bot, msg) => {
            var c = msg.match(1);
            bot.reply(msg, `Ok, you can sit on ${c}`);
        }]
    }, {
        func: 'hears',
        args: [['force (\d)'], ['direct_message'], (bot, msg) => {
            var c = msg.match(1);
            bot.reply(msg, `Ok, you can force on ${c}`);
        }]
    }
];
<commit_msg>match is an array not a function<commit_after>'use strict';

module.exports = [
    {
        func: 'hears',
        args: [['start (.*) (\\d)'], ['direct_mention'], (bot, msg) => {
            var time = msg.match[1];
            var numchairs = msg.match[2];
            bot.reply(msg, `Ok, let's start a game at ${time} with ${numchairs} chairs`);
        }]
    }, {
        func: 'hears',
        args: [['sit (\\d)'], ['direct_message'], (bot, msg) => {
            var c = msg.match[1];
            bot.reply(msg, `Ok, you can sit on ${c}`);
        }]
    }, {
        func: 'hears',
        args: [['force (\d)'], ['direct_message'], (bot, msg) => {
            var c = msg.match[1];
            bot.reply(msg, `Ok, you can force on ${c}`);
        }]
    }
];
<|endoftext|>


<commit_before>module.exports = {
    "locations": {
        "00": {
            "name": "Origin",
            "description": "A hole to see the sky through",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 0
            }
        },
        "01": {
            "name": "South",
            "description": "The path to civilization",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -6
            }
        },
        "02": {
            "name": "East",
            "description": "The sun rises",
            "coord": {
                "x": 6,
                "y": 0,
                "z": 0
            }
        },
        "03": {
            "name": "North",
            "description": "To eternity",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 6
            }
        },
        "04": {
            "name": "West",
            "description": "Dusk over mountains",
            "coord": {
                "x": -6,
                "y": 0,
                "z": 0
            }
        },

        "10": {
            "name": "South Gate",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -34
            }
        },
        "11": {
            "name": "Into the fold",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -24
            }
        },
        "12": {
            "name": "First Contact",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -14
            }
        },
        "13": {
            "name": "South Entry",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -9
            }
        },
        "14": {
            "name": "North Entry",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 9
            }
        },
        "15": {
            "name": "The Edge of Civilization",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 14
            }
        },
        "16": {
            "name": "North Gate",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 24
            }
        },

        "20": {
            "name": "West Gate",
            // "description": "",
            "coord": {
                "x": -29,
                "y": 0,
                "z": 0
            }
        },
        "21": {
            "name": "Ritual",
            // "description": "",
            "coord": {
                "x": -20,
                "y": 0,
                "z": 0
            }
        },
        "22": {
            "name": "Sunset Through the Trees",
            // "description": "",
            "coord": {
                "x": -14,
                "y": 0,
                "z": 0
            }
        },
        "23": {
            "name": "West Entry",
            // "description": "",
            "coord": {
                "x": -9,
                "y": 0,
                "z": 0
            }
        },
        "24": {
            "name": "East Entry",
            // "description": "",
            "coord": {
                "x": 9,
                "y": 0,
                "z": 0
            }
        },
        "25": {
            "name": "Dawn in the Forest",
            // "description": "",
            "coord": {
                "x": 14,
                "y": 0,
                "z": 0
            }
        },
        "26": {
            "name": "Introspection",
            // "description": "",
            "coord": {
                "x": 20,
                "y": 0,
                "z": 0
            }
        },
        "27": {
            "name": "East Gate",
            // "description": "",
            "coord": {
                "x": 29,
                "y": 0,
                "z": 0
            }
        }

    },
    "dates": {
        "2016-11-01": [
            {
                "type": "model",
                "title": "First forest model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "16-11-temple.gltf"
            }
        ],
        "2016-12-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "16-12-temple.gltf"
            }
        ],
        "2017-01-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "17-01-temple.gltf"
            }
        ],
        "2017-02-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "17-02-temple.gltf"
            }
        ],
        "2017-05-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "test2",
                "location": "origin",
                "source": "somesorce.gltf"
            }
        ],
        "2017-06-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "test3",
                "location": "origin",
                "source": "somesorce.gltf"
            }
        ],
        "2017-07-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "test4",
                "location": "origin",
                "source": "somesorce.gltf"
            }
        ],
        "2017-08-01": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "test5",
                "location": "origin",
                "source": "17-08-temple.gltf"
            }
        ],
        "2017-08-15": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "test6",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-16": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "test7",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-17": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "test8",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-18": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "test9",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-19": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-20": [
            {
                "type": "model",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.gltf"
            },
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-21": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-22": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-23": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-24": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-25": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-26": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-27": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-28": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "main01",
                "source": "somesorce.jpg"
            }
        ],
        "2017-09-02": [
            {
                "type": "360",
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ]
    }
}<commit_msg>data model updates<commit_after>module.exports = {
    "locations": {
        "origin": {
            "title": "Origin",
            "description": "A hole to see the sky through",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 0
            }
        },
        "interiorSouth": {
            "title": "South",
            "description": "The path to civilization",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -6
            }
        },
        "interiorEast": {
            "title": "East",
            "description": "The sun rises",
            "coord": {
                "x": 6,
                "y": 0,
                "z": 0
            }
        },
        "interiorNorth": {
            "title": "North",
            "description": "To eternity",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 6
            }
        },
        "interiorWest": {
            "title": "West",
            "description": "Dusk over mountains",
            "coord": {
                "x": -6,
                "y": 0,
                "z": 0
            }
        },
        "southGate": {
            "title": "South Gate",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -34
            }
        },
        "southCourtyard": {
            "title": "Into the fold",
            "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -24
            }
        },
        "southCantilever": {
            "title": "First Contact",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -14
            }
        },
        "southEntry": {
            "title": "South Entry",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": -9
            }
        },
        "northEntry": {
            "title": "North Entry",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 9
            }
        },
        "northCantilever": {
            "title": "The Edge of Civilization",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 14
            }
        },
        "northGate": {
            "title": "North Gate",
            // "description": "",
            "coord": {
                "x": 0,
                "y": 0,
                "z": 24
            }
        },
        "westGate": {
            "title": "West Gate",
            // "description": "",
            "coord": {
                "x": -29,
                "y": 0,
                "z": 0
            }
        },
        "westCourtyard": {
            "title": "Ritual",
            // "description": "",
            "coord": {
                "x": -20,
                "y": 0,
                "z": 0
            }
        },
        "westCantilever": {
            "title": "Sunset Through the Trees",
            // "description": "",
            "coord": {
                "x": -14,
                "y": 0,
                "z": 0
            }
        },
        "westEntry": {
            "title": "West Entry",
            // "description": "",
            "coord": {
                "x": -9,
                "y": 0,
                "z": 0
            }
        },
        "eastEntry": {
            "title": "East Entry",
            // "description": "",
            "coord": {
                "x": 9,
                "y": 0,
                "z": 0
            }
        },
        "eastCantilever": {
            "title": "Dawn in the Forest",
            // "description": "",
            "coord": {
                "x": 14,
                "y": 0,
                "z": 0
            }
        },
        "eastCourtyard": {
            "title": "Introspection",
            // "description": "",
            "coord": {
                "x": 20,
                "y": 0,
                "z": 0
            }
        },
        "eastGate": {
            "title": "East Gate",
            // "description": "",
            "coord": {
                "x": 29,
                "y": 0,
                "z": 0
            }
        }
    },
    "models": {
        "2016-11-01":
        {
            "title": "First forest model",
            "description": "Initial 3D model",
            "location": "origin",
            "source": "16-11-temple.gltf"
        },
        "2016-12-01":
        {
            "title": "Design iteration model",
            "description": "Initial 3D model",
            "location": "origin",
            "source": "16-12-temple.gltf"
        },
        "2017-01-01":
        {
            "title": "Design iteration model",
            "description": "Initial 3D model",
            "location": "origin",
            "source": "17-01-temple.gltf"
        },
        "2017-02-01":
        {
            "title": "Design iteration model",
            "description": "Initial 3D model",
            "location": "origin",
            "source": "17-02-temple.gltf"
        },
        "2017-05-01":
        {
            "title": "Design iteration model",
            "description": "test2",
            "location": "origin",
            "source": "somesorce.gltf"
        },
        "2017-06-01":
        {
            "title": "Design iteration model",
            "description": "test3",
            "location": "origin",
            "source": "somesorce.gltf"
        },
        "2017-07-01":
        {
            "title": "Design iteration model",
            "description": "test4",
            "location": "origin",
            "source": "somesorce.gltf"
        },
        "2017-08-01":
        {
            "title": "Design iteration model",
            "description": "test5",
            "location": "origin",
            "source": "17-08-temple.gltf"
        }
    },
    "360images": {
        "2017-08-15": [
            {
                "title": "360-test-1",
                "description": "test6",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-16": [
            {
                "title": "360-test-2",
                "description": "test7",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-17": [
            {
                "title": "360-test-3",
                "description": "test8",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-18": [
            {
                "title": "360-test-4",
                "description": "test9",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-19": [
            {
                "title": "360-test-5",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-20": [
            {
                "title": "360-test-6",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-21": [
            {
                "title": "360-test-7",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-22": [
            {
                "title": "360-test-8",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-23": [
            {
                "title": "360-test-9",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-24": [
            {
                "title": "360-test-10",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-25": [
            {
                "title": "360-test-11",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-26": [
            {
                "title": "360-test-12",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-27": [
            {
                "title": "360-test-13",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ],
        "2017-08-28": [
            {
                "title": "Design iteration model",
                "description": "Initial 3D model",
                "location": "main01",
                "source": "somesorce.jpg"
            }
        ],
        "2017-09-02": [
            {
                "title": "360-test-14",
                "description": "Initial 3D model",
                "location": "origin",
                "source": "somesorce.jpg"
            }
        ]
    }
}<|endoftext|>


<commit_before>var util = require('../util')
var uiutil = require('../helpers/uiHelper')
var traceHelper = require('../helpers/traceHelper')
var ethutil = require('ethereumjs-util')
var Web3 = require('web3')

function web3VmProvider () {
  var self = this
  this.web3 = new Web3()
  this.vm
  this.vmTraces = {}
  this.txs = {}
  this.txsReceipt = {}
  this.processingHash
  this.processingAddress
  this.processingIndex
  this.previousDepth = 0
  this.incr = 0
  this.eth = {}
  this.debug = {}
  this.eth.getCode = (...args) => self.getCode(...args)
  this.eth.getTransaction = (...args) => self.getTransaction(...args)
  this.eth.getTransactionReceipt = (...args) => self.getTransactionReceipt(...args)
  this.eth.getTransactionFromBlock = (...args) => self.getTransactionFromBlock(...args)
  this.eth.getBlockNumber = (...args) => self.getBlockNumber(...args)
  this.debug.traceTransaction = (...args) => self.traceTransaction(...args)
  this.debug.storageRangeAt = (...args) => self.storageRangeAt(...args)
  this.debug.preimage = (...args) => self.preimage(...args)
  this.providers = { 'HttpProvider': function (url) {} }
  this.currentProvider = {'host': 'vm provider'}
  this.storageCache = {}
  this.lastProcessedStorageTxHash = {}
  this.sha3Preimages = {}
  // util
  this.sha3 = (...args) => self.web3.utils.sha3(...args)
  this.toHex = (...args) => self.web3.utils.toHex(...args)
  this.toAscii = (...args) => self.web3.utils.hexToAscii(...args)
  this.fromAscii = (...args) => self.web3.utils.asciiToHex(...args)
  this.fromDecimal = (...args) => self.web3.utils.numberToHex(...args)
  this.fromWei = (...args) => self.web3.utils.fromWei(...args)
  this.toWei = (...args) => self.web3.utils.toWei(...args)
  this.toBigNumber = (...args) => self.web3.utils.toBN(...args)
  this.isAddress = (...args) => self.web3.utils.isAddress(...args)
  this.utils = Web3.utils || []
}

web3VmProvider.prototype.setVM = function (vm) {
  if (this.vm === vm) return
  var self = this
  this.vm = vm
  this.vm.on('step', function (data) {
    self.pushTrace(self, data)
  })
  this.vm.on('afterTx', function (data) {
    self.txProcessed(self, data)
  })
  this.vm.on('beforeTx', function (data) {
    self.txWillProcess(self, data)
  })
}

web3VmProvider.prototype.releaseCurrentHash = function () {
  var ret = this.processingHash
  this.processingHash = undefined
  return ret
}

web3VmProvider.prototype.txWillProcess = function (self, data) {
  self.incr++
  self.processingHash = util.hexConvert(data.hash())
  self.vmTraces[self.processingHash] = {
    gas: '0x0',
    return: '0x0',
    structLogs: []
  }
  var tx = {}
  tx.hash = self.processingHash
  tx.from = util.hexConvert(data.getSenderAddress())
  if (data.to && data.to.length) {
    tx.to = util.hexConvert(data.to)
  }
  this.processingAddress = tx.to
  tx.data = util.hexConvert(data.data)
  tx.input = util.hexConvert(data.input)
  tx.gas = (new ethutil.BN(util.hexConvert(data.gas).replace('0x', ''), 16)).toString(10)
  if (data.value) {
    tx.value = util.hexConvert(data.value)
  }
  self.txs[self.processingHash] = tx
  self.txsReceipt[self.processingHash] = tx
  self.storageCache[self.processingHash] = {}
  if (tx.to) {
    const account = ethutil.toBuffer(tx.to)
    self.vm.stateManager.dumpStorage(account, function (storage) {
      self.storageCache[self.processingHash][tx.to] = storage
      self.lastProcessedStorageTxHash[tx.to] = self.processingHash
    })
  }
  this.processingIndex = 0
}

web3VmProvider.prototype.txProcessed = function (self, data) {
  var lastOp = self.vmTraces[self.processingHash].structLogs[self.processingIndex - 1]
  if (lastOp) {
    lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'SELFDESTRUCT'
  }
  self.vmTraces[self.processingHash].gas = '0x' + data.gasUsed.toString(16)

  var logs = []
  for (var l in data.execResult.logs) {
    var log = data.execResult.logs[l]
    var topics = []
    if (log[1].length > 0) {
      for (var k in log[1]) {
        topics.push('0x' + log[1][k].toString('hex'))
      }
    } else {
      topics.push('0x')
    }
    logs.push({
      address: '0x' + log[0].toString('hex'),
      data: '0x' + log[2].toString('hex'),
      topics: topics,
      rawVMResponse: log
    })
  }
  self.txsReceipt[self.processingHash].logs = logs
  self.txsReceipt[self.processingHash].transactionHash = self.processingHash
  const status = data.execResult.exceptionError ? 0 : 1
  self.txsReceipt[self.processingHash].status = `0x${status}`

  if (data.createdAddress) {
    var address = util.hexConvert(data.createdAddress)
    self.vmTraces[self.processingHash].return = address
    self.txsReceipt[self.processingHash].contractAddress = address
  } else if (data.execResult.returnValue) {
    self.vmTraces[self.processingHash].return = util.hexConvert(data.execResult.returnValue)
  } else {
    self.vmTraces[self.processingHash].return = '0x'
  }
  this.processingIndex = null
  this.processingAddress = null
  this.previousDepth = 0
}

web3VmProvider.prototype.pushTrace = function (self, data) {
  var depth = data.depth + 1 // geth starts the depth from 1
  if (!self.processingHash) {
    console.log('no tx processing')
    return
  }
  var previousopcode
  if (self.vmTraces[self.processingHash] && self.vmTraces[self.processingHash].structLogs[this.processingIndex - 1]) {
    previousopcode = self.vmTraces[self.processingHash].structLogs[this.processingIndex - 1]
  }

  if (this.previousDepth > depth && previousopcode) {
    // returning from context, set error it is not STOP, RETURN
    previousopcode.invalidDepthChange = previousopcode.op !== 'RETURN' && previousopcode.op !== 'STOP'
  }
  var step = {
    stack: util.hexListFromBNs(data.stack),
    memory: util.formatMemory(data.memory),
    storage: data.storage,
    op: data.opcode.name,
    pc: data.pc,
    gasCost: data.opcode.fee.toString(),
    gas: data.gasLeft.toString(),
    depth: depth,
    error: data.error === false ? undefined : data.error
  }
  self.vmTraces[self.processingHash].structLogs.push(step)
  if (traceHelper.newContextStorage(step)) {
    if (step.op === 'CREATE') {
      this.processingAddress = traceHelper.contractCreationToken(this.processingIndex)
      this.storageCache[this.processingHash][this.processingAddress] = {}
      this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
    } else {
      this.processingAddress = uiutil.normalizeHexAddress(step.stack[step.stack.length - 2])
      if (!self.storageCache[self.processingHash][this.processingAddress]) {
        const account = ethutil.toBuffer(this.processingAddress)
        self.vm.stateManager.dumpStorage(account, function (storage) {
          self.storageCache[self.processingHash][self.processingAddress] = storage
          self.lastProcessedStorageTxHash[self.processingAddress] = self.processingHash
        })
      }
    }
  }
  if (previousopcode && traceHelper.isSHA3Instruction(previousopcode)) {
    var preimage = getSha3Input(previousopcode.stack, previousopcode.memory)
    var imageHash = step.stack[step.stack.length - 1].replace('0x', '')
    self.sha3Preimages[imageHash] = {
      'preimage': preimage
    }
  }

  this.processingIndex++
  this.previousDepth = depth
}

web3VmProvider.prototype.getCode = function (address, cb) {
  const account = ethutil.toBuffer(address)
  this.vm.stateManager.getContractCode(account, function (error, result) {
    cb(error, util.hexConvert(result))
  })
}

web3VmProvider.prototype.setProvider = function (provider) {}

web3VmProvider.prototype.traceTransaction = function (txHash, options, cb) {
  if (this.vmTraces[txHash]) {
    if (cb) {
      cb(null, this.vmTraces[txHash])
    }
    return this.vmTraces[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve traces ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, address, start, maxLength, cb) { // txIndex is the hash in the case of the VM
  // we don't use the range params here

  if (txIndex === 'latest') {
    txIndex = this.lastProcessedStorageTxHash[address]
  }

  if (this.storageCache[txIndex] && this.storageCache[txIndex][address]) {
    var storage = this.storageCache[txIndex][address]
    return cb(null, {
      storage: JSON.parse(JSON.stringify(storage)),
      nextKey: null
    })
  } else {
    cb('unable to retrieve storage ' + txIndex + ' ' + address)
  }
}

web3VmProvider.prototype.getBlockNumber = function (cb) { cb(null, 'vm provider') }

web3VmProvider.prototype.getTransaction = function (txHash, cb) {
  if (this.txs[txHash]) {
    if (cb) {
      cb(null, this.txs[txHash])
    }
    return this.txs[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve tx ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.getTransactionReceipt = function (txHash, cb) {
  // same as getTransaction but return the created address also
  if (this.txsReceipt[txHash]) {
    if (cb) {
      cb(null, this.txsReceipt[txHash])
    }
    return this.txsReceipt[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve txReceipt ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.getTransactionFromBlock = function (blockNumber, txIndex, cb) {
  var mes = 'not supposed to be needed by remix in vmmode'
  console.log(mes)
  if (cb) {
    cb(mes, null)
  }
}

web3VmProvider.prototype.preimage = function (hashedKey, cb) {
  hashedKey = hashedKey.replace('0x', '')
  cb(null, this.sha3Preimages[hashedKey] !== undefined ? this.sha3Preimages[hashedKey].preimage : null)
}

function getSha3Input (stack, memory) {
  var memoryStart = stack[stack.length - 1]
  var memoryLength = stack[stack.length - 2]
  var memStartDec = (new ethutil.BN(memoryStart.replace('0x', ''), 16)).toString(10)
  memoryStart = parseInt(memStartDec) * 2
  var memLengthDec = (new ethutil.BN(memoryLength.replace('0x', ''), 16).toString(10))
  memoryLength = parseInt(memLengthDec) * 2

  var i = Math.floor(memoryStart / 32)
  var maxIndex = Math.floor(memoryLength / 32) + i
  if (!memory[i]) {
    return emptyFill(memoryLength)
  }
  var sha3Input = memory[i].slice(memoryStart - 32 * i)
  i++
  while (i < maxIndex) {
    sha3Input += memory[i] ? memory[i] : emptyFill(32)
    i++
  }
  if (sha3Input.length < memoryLength) {
    var leftSize = memoryLength - sha3Input.length
    sha3Input += memory[i] ? memory[i].slice(0, leftSize) : emptyFill(leftSize)
  }
  return sha3Input
}

function emptyFill (size) {
  return (new Array(size)).join('0')
}

module.exports = web3VmProvider
<commit_msg>explicit utils usage removed<commit_after>var util = require('../util')
var uiutil = require('../helpers/uiHelper')
var traceHelper = require('../helpers/traceHelper')
var ethutil = require('ethereumjs-util')
var Web3 = require('web3')

function web3VmProvider () {
  var self = this
  this.web3 = new Web3()
  this.vm
  this.vmTraces = {}
  this.txs = {}
  this.txsReceipt = {}
  this.processingHash
  this.processingAddress
  this.processingIndex
  this.previousDepth = 0
  this.incr = 0
  this.eth = {}
  this.debug = {}
  this.eth.getCode = (...args) => self.getCode(...args)
  this.eth.getTransaction = (...args) => self.getTransaction(...args)
  this.eth.getTransactionReceipt = (...args) => self.getTransactionReceipt(...args)
  this.eth.getTransactionFromBlock = (...args) => self.getTransactionFromBlock(...args)
  this.eth.getBlockNumber = (...args) => self.getBlockNumber(...args)
  this.debug.traceTransaction = (...args) => self.traceTransaction(...args)
  this.debug.storageRangeAt = (...args) => self.storageRangeAt(...args)
  this.debug.preimage = (...args) => self.preimage(...args)
  this.providers = { 'HttpProvider': function (url) {} }
  this.currentProvider = {'host': 'vm provider'}
  this.storageCache = {}
  this.lastProcessedStorageTxHash = {}
  this.sha3Preimages = {}
  // util
  this.utils = Web3.utils || []
}

web3VmProvider.prototype.setVM = function (vm) {
  if (this.vm === vm) return
  var self = this
  this.vm = vm
  this.vm.on('step', function (data) {
    self.pushTrace(self, data)
  })
  this.vm.on('afterTx', function (data) {
    self.txProcessed(self, data)
  })
  this.vm.on('beforeTx', function (data) {
    self.txWillProcess(self, data)
  })
}

web3VmProvider.prototype.releaseCurrentHash = function () {
  var ret = this.processingHash
  this.processingHash = undefined
  return ret
}

web3VmProvider.prototype.txWillProcess = function (self, data) {
  self.incr++
  self.processingHash = util.hexConvert(data.hash())
  self.vmTraces[self.processingHash] = {
    gas: '0x0',
    return: '0x0',
    structLogs: []
  }
  var tx = {}
  tx.hash = self.processingHash
  tx.from = util.hexConvert(data.getSenderAddress())
  if (data.to && data.to.length) {
    tx.to = util.hexConvert(data.to)
  }
  this.processingAddress = tx.to
  tx.data = util.hexConvert(data.data)
  tx.input = util.hexConvert(data.input)
  tx.gas = (new ethutil.BN(util.hexConvert(data.gas).replace('0x', ''), 16)).toString(10)
  if (data.value) {
    tx.value = util.hexConvert(data.value)
  }
  self.txs[self.processingHash] = tx
  self.txsReceipt[self.processingHash] = tx
  self.storageCache[self.processingHash] = {}
  if (tx.to) {
    const account = ethutil.toBuffer(tx.to)
    self.vm.stateManager.dumpStorage(account, function (storage) {
      self.storageCache[self.processingHash][tx.to] = storage
      self.lastProcessedStorageTxHash[tx.to] = self.processingHash
    })
  }
  this.processingIndex = 0
}

web3VmProvider.prototype.txProcessed = function (self, data) {
  var lastOp = self.vmTraces[self.processingHash].structLogs[self.processingIndex - 1]
  if (lastOp) {
    lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'SELFDESTRUCT'
  }
  self.vmTraces[self.processingHash].gas = '0x' + data.gasUsed.toString(16)

  var logs = []
  for (var l in data.execResult.logs) {
    var log = data.execResult.logs[l]
    var topics = []
    if (log[1].length > 0) {
      for (var k in log[1]) {
        topics.push('0x' + log[1][k].toString('hex'))
      }
    } else {
      topics.push('0x')
    }
    logs.push({
      address: '0x' + log[0].toString('hex'),
      data: '0x' + log[2].toString('hex'),
      topics: topics,
      rawVMResponse: log
    })
  }
  self.txsReceipt[self.processingHash].logs = logs
  self.txsReceipt[self.processingHash].transactionHash = self.processingHash
  const status = data.execResult.exceptionError ? 0 : 1
  self.txsReceipt[self.processingHash].status = `0x${status}`

  if (data.createdAddress) {
    var address = util.hexConvert(data.createdAddress)
    self.vmTraces[self.processingHash].return = address
    self.txsReceipt[self.processingHash].contractAddress = address
  } else if (data.execResult.returnValue) {
    self.vmTraces[self.processingHash].return = util.hexConvert(data.execResult.returnValue)
  } else {
    self.vmTraces[self.processingHash].return = '0x'
  }
  this.processingIndex = null
  this.processingAddress = null
  this.previousDepth = 0
}

web3VmProvider.prototype.pushTrace = function (self, data) {
  var depth = data.depth + 1 // geth starts the depth from 1
  if (!self.processingHash) {
    console.log('no tx processing')
    return
  }
  var previousopcode
  if (self.vmTraces[self.processingHash] && self.vmTraces[self.processingHash].structLogs[this.processingIndex - 1]) {
    previousopcode = self.vmTraces[self.processingHash].structLogs[this.processingIndex - 1]
  }

  if (this.previousDepth > depth && previousopcode) {
    // returning from context, set error it is not STOP, RETURN
    previousopcode.invalidDepthChange = previousopcode.op !== 'RETURN' && previousopcode.op !== 'STOP'
  }
  var step = {
    stack: util.hexListFromBNs(data.stack),
    memory: util.formatMemory(data.memory),
    storage: data.storage,
    op: data.opcode.name,
    pc: data.pc,
    gasCost: data.opcode.fee.toString(),
    gas: data.gasLeft.toString(),
    depth: depth,
    error: data.error === false ? undefined : data.error
  }
  self.vmTraces[self.processingHash].structLogs.push(step)
  if (traceHelper.newContextStorage(step)) {
    if (step.op === 'CREATE') {
      this.processingAddress = traceHelper.contractCreationToken(this.processingIndex)
      this.storageCache[this.processingHash][this.processingAddress] = {}
      this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
    } else {
      this.processingAddress = uiutil.normalizeHexAddress(step.stack[step.stack.length - 2])
      if (!self.storageCache[self.processingHash][this.processingAddress]) {
        const account = ethutil.toBuffer(this.processingAddress)
        self.vm.stateManager.dumpStorage(account, function (storage) {
          self.storageCache[self.processingHash][self.processingAddress] = storage
          self.lastProcessedStorageTxHash[self.processingAddress] = self.processingHash
        })
      }
    }
  }
  if (previousopcode && traceHelper.isSHA3Instruction(previousopcode)) {
    var preimage = getSha3Input(previousopcode.stack, previousopcode.memory)
    var imageHash = step.stack[step.stack.length - 1].replace('0x', '')
    self.sha3Preimages[imageHash] = {
      'preimage': preimage
    }
  }

  this.processingIndex++
  this.previousDepth = depth
}

web3VmProvider.prototype.getCode = function (address, cb) {
  const account = ethutil.toBuffer(address)
  this.vm.stateManager.getContractCode(account, function (error, result) {
    cb(error, util.hexConvert(result))
  })
}

web3VmProvider.prototype.setProvider = function (provider) {}

web3VmProvider.prototype.traceTransaction = function (txHash, options, cb) {
  if (this.vmTraces[txHash]) {
    if (cb) {
      cb(null, this.vmTraces[txHash])
    }
    return this.vmTraces[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve traces ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, address, start, maxLength, cb) { // txIndex is the hash in the case of the VM
  // we don't use the range params here

  if (txIndex === 'latest') {
    txIndex = this.lastProcessedStorageTxHash[address]
  }

  if (this.storageCache[txIndex] && this.storageCache[txIndex][address]) {
    var storage = this.storageCache[txIndex][address]
    return cb(null, {
      storage: JSON.parse(JSON.stringify(storage)),
      nextKey: null
    })
  } else {
    cb('unable to retrieve storage ' + txIndex + ' ' + address)
  }
}

web3VmProvider.prototype.getBlockNumber = function (cb) { cb(null, 'vm provider') }

web3VmProvider.prototype.getTransaction = function (txHash, cb) {
  if (this.txs[txHash]) {
    if (cb) {
      cb(null, this.txs[txHash])
    }
    return this.txs[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve tx ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.getTransactionReceipt = function (txHash, cb) {
  // same as getTransaction but return the created address also
  if (this.txsReceipt[txHash]) {
    if (cb) {
      cb(null, this.txsReceipt[txHash])
    }
    return this.txsReceipt[txHash]
  } else {
    if (cb) {
      cb('unable to retrieve txReceipt ' + txHash, null)
    }
  }
}

web3VmProvider.prototype.getTransactionFromBlock = function (blockNumber, txIndex, cb) {
  var mes = 'not supposed to be needed by remix in vmmode'
  console.log(mes)
  if (cb) {
    cb(mes, null)
  }
}

web3VmProvider.prototype.preimage = function (hashedKey, cb) {
  hashedKey = hashedKey.replace('0x', '')
  cb(null, this.sha3Preimages[hashedKey] !== undefined ? this.sha3Preimages[hashedKey].preimage : null)
}

function getSha3Input (stack, memory) {
  var memoryStart = stack[stack.length - 1]
  var memoryLength = stack[stack.length - 2]
  var memStartDec = (new ethutil.BN(memoryStart.replace('0x', ''), 16)).toString(10)
  memoryStart = parseInt(memStartDec) * 2
  var memLengthDec = (new ethutil.BN(memoryLength.replace('0x', ''), 16).toString(10))
  memoryLength = parseInt(memLengthDec) * 2

  var i = Math.floor(memoryStart / 32)
  var maxIndex = Math.floor(memoryLength / 32) + i
  if (!memory[i]) {
    return emptyFill(memoryLength)
  }
  var sha3Input = memory[i].slice(memoryStart - 32 * i)
  i++
  while (i < maxIndex) {
    sha3Input += memory[i] ? memory[i] : emptyFill(32)
    i++
  }
  if (sha3Input.length < memoryLength) {
    var leftSize = memoryLength - sha3Input.length
    sha3Input += memory[i] ? memory[i].slice(0, leftSize) : emptyFill(leftSize)
  }
  return sha3Input
}

function emptyFill (size) {
  return (new Array(size)).join('0')
}

module.exports = web3VmProvider
<|endoftext|>


<commit_before>import jwt from 'jsonwebtoken';

import { refreshTokens } from './auth';

export default (SECRET, User) => async (req, res, next) => {
  let token = req.universalCookies.get('x-token') || req.headers['x-token'];

  // if header available
  if (req.headers['x-token']) {
    // check if header token matches cookie token
    if (
      req.headers['x-token'] !== req.universalCookies.get('x-token') ||
      req.headers['x-refresh-token'] !==
        req.universalCookies.get('x-refresh-token')
    ) {
      // if x-token is not empty and not the same as cookie x-token revoke authentication
      token = undefined;
    }
  }

  // if cookie available
  if (req.universalCookies.get('x-token')) {
    // check if header token matches cookie token
    if (
      req.universalCookies.get('x-token') !==
        req.universalCookies.get('r-token') ||
      req.universalCookies.get('x-refresh-token') !==
        req.universalCookies.get('r-refresh-token')
    ) {
      // if x-token is not empty and not the same as cookie x-token revoke authentication
      token = undefined;
    }
  }
  //console.log(token);
  if (token && token !== 'null') {
    try {
      const { user } = jwt.verify(token, SECRET);
      req.user = user;
    } catch (err) {
      const refreshToken =
        req.universalCookies.get('x-refresh-token') ||
        req.headers['x-refresh-token'];
      const newTokens = await refreshTokens(token, refreshToken, User, SECRET);

      if (newTokens.token && newTokens.refreshToken) {
        res.set('Access-Control-Allow-Origin', 'true');
        res.set('Access-Control-Expose-Headers', 'x-token, x-refresh-token');
        res.set('x-token', newTokens.token);
        res.set('x-refresh-token', newTokens.refreshToken);

        req.universalCookies.set('x-token', newTokens.token, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: true
        });
        req.universalCookies.set('x-refresh-token', newTokens.refreshToken, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: true
        });

        req.universalCookies.set('r-token', newTokens.token, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: false
        });
        req.universalCookies.set('r-refresh-token', newTokens.refreshToken, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: false
        });
      }
      req.user = newTokens.user;
    }
  }

  next();
};
<commit_msg>remove unneeded code<commit_after>import jwt from 'jsonwebtoken';

import { refreshTokens } from './auth';

export default (SECRET, User) => async (req, res, next) => {
  let token = req.universalCookies.get('x-token') || req.headers['x-token'];

  // if header available
  if (req.headers['x-token']) {
    // check if header token matches cookie token
    if (
      req.headers['x-token'] !== req.universalCookies.get('x-token') ||
      req.headers['x-refresh-token'] !==
        req.universalCookies.get('x-refresh-token')
    ) {
      // if x-token is not empty and not the same as cookie x-token revoke authentication
      token = undefined;
    }
  }

  // if cookie available
  if (req.universalCookies.get('x-token')) {
    // check if header token matches cookie token
    if (
      req.universalCookies.get('x-token') !==
        req.universalCookies.get('r-token') ||
      req.universalCookies.get('x-refresh-token') !==
        req.universalCookies.get('r-refresh-token')
    ) {
      // if x-token is not empty and not the same as cookie x-token revoke authentication
      token = undefined;
    }
  }
  //console.log(token);
  if (token && token !== 'null') {
    try {
      const { user } = jwt.verify(token, SECRET);
      req.user = user;
    } catch (err) {
      const refreshToken =
        req.universalCookies.get('x-refresh-token') ||
        req.headers['x-refresh-token'];
      const newTokens = await refreshTokens(token, refreshToken, User, SECRET);

      if (newTokens.token && newTokens.refreshToken) {
        res.set('Access-Control-Expose-Headers', 'x-token, x-refresh-token');
        res.set('x-token', newTokens.token);
        res.set('x-refresh-token', newTokens.refreshToken);

        req.universalCookies.set('x-token', newTokens.token, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: true
        });
        req.universalCookies.set('x-refresh-token', newTokens.refreshToken, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: true
        });

        req.universalCookies.set('r-token', newTokens.token, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: false
        });
        req.universalCookies.set('r-refresh-token', newTokens.refreshToken, {
          maxAge: 60 * 60 * 24 * 7,
          httpOnly: false
        });
      }
      req.user = newTokens.user;
    }
  }

  next();
};
<|endoftext|>


<commit_before>'use strict';

/**
 * @file
 * Configure main routes
 * Includes utility routes (example: /moreinfo)
 */

import express from 'express';
const MainRoutes = express.Router();
import React from 'react';
import ReactDOM from 'react-dom/server';

import {stringToObject} from '../../utils/QueryParser.util.js';

// loading components
import {defaultLikes} from '../../client/components/Recommend/Recommendations.store.js';
import FrontpageContainer from '../../client/components/FrontPage/FrontpageContainer.component.js';

function getRecommendations(res, likes) {
  res.callServiceProvider('getRecommendations', {likes: likes, dislikes: []}, 50).then((recommendations) => {
    // got recommendations
    const content = ReactDOM.renderToString(<FrontpageContainer application='mobilsoeg' recommendations={recommendations} />);
    res.render('frontpage', {
      frontpageContainerString: content,
      recommendations: JSON.stringify(recommendations)
    });
  }, () => {
    // error occurred (most likely a timeout hit)
    res.render('frontpage');
  });
}

MainRoutes.get('/', (req, res) => {
  if (req.isAuthenticated()) {
    // user is logged in, get profile.
    res.callServiceProvider('findMobilSoegProfile', null, 400).then((profile) => {
      let likes = profile[0].body.likes.map((like) => {
        return like.item_id;
      });

      likes = likes.length > 0 ? likes : defaultLikes;
      // got profile, get recommendations
      getRecommendations(res, likes);
    }, () => {
      res.render('frontpage');
    });
  }
  else {
    getRecommendations(res, defaultLikes);
  }
});

MainRoutes.get(['/search', '/search/*'], (req, res) => {
  res.render('search', {
    props: JSON.stringify({query: stringToObject(req.query || []) || []})
  });
});

MainRoutes.post(['/report-violation'], function(req, res) {
  const logger = req.app.get('logger');
  if (req.body) {
    logger.log('warning', 'CSP Violation: ', req.body);
  }
  else {
    logger.log('warning', 'CSP Violation: No data received!');
  }
  res.status(204).end();
});

export default MainRoutes;
<commit_msg>Accumulated commit of the following from branch 'origin/ready/jph-198':<commit_after>'use strict';

/**
 * @file
 * Configure main routes
 * Includes utility routes (example: /moreinfo)
 */

import express from 'express';
const MainRoutes = express.Router();
import React from 'react';
import ReactDOM from 'react-dom/server';

import {stringToObject} from '../../utils/QueryParser.util.js';

// loading components
import {defaultLikes} from '../../client/components/Recommend/Recommendations.store.js';
import FrontpageContainer from '../../client/components/FrontPage/FrontpageContainer.component.js';

function getRecommendations(res, likes) {
  res.callServiceProvider('getRecommendations', {likes: likes, dislikes: [], isFrontPage: true}, 50).then((recommendations) => {
    // got recommendations
    const content = ReactDOM.renderToString(<FrontpageContainer application='mobilsoeg' recommendations={recommendations} />);
    res.render('frontpage', {
      frontpageContainerString: content,
      recommendations: JSON.stringify(recommendations)
    });
  }, () => {
    // error occurred (most likely a timeout hit)
    res.render('frontpage');
  });
}

MainRoutes.get('/', (req, res) => {
  if (req.isAuthenticated()) {
    // user is logged in, get profile.
    res.callServiceProvider('findMobilSoegProfile', null, 400).then((profile) => {
      let likes = profile[0].body.likes.map((like) => {
        return like.item_id;
      });

      likes = likes.length > 0 ? likes : defaultLikes;
      // got profile, get recommendations
      getRecommendations(res, likes);
    }, () => {
      res.render('frontpage');
    });
  }
  else {
    getRecommendations(res, defaultLikes);
  }
});

MainRoutes.get(['/search', '/search/*'], (req, res) => {
  res.render('search', {
    props: JSON.stringify({query: stringToObject(req.query || []) || []})
  });
});

MainRoutes.post(['/report-violation'], function(req, res) {
  const logger = req.app.get('logger');
  if (req.body) {
    logger.log('warning', 'CSP Violation: ', req.body);
  }
  else {
    logger.log('warning', 'CSP Violation: No data received!');
  }
  res.status(204).end();
});

export default MainRoutes;
<|endoftext|>


<commit_before>document.addEventListener('turbolinks:load', function() {
    if (document.getElementById('post-attachment-dropzone') === null) {
        return;
    }

    const attachmentDescription = new Vue({
        el: '#modalAttachment',
        data: {
            attachment: {},
            active: null,
        },
        methods: {
            loadInfo: function(data) {
                let name = data.name + data.id;

                data.url = '/storage/' + data.path + data.name + '.' + data.extension;

                if (!this.attachment.hasOwnProperty(name)) {
                    this.attachment[name] = data;
                }
                this.active = name;
            },
            save: function() {
                let data = this.attachment[this.active];

                $('#modalAttachment').modal('toggle');

                $.ajax({
                    type: 'POST',
                    url: dashboard.prefix('/systems/files/post/' + data.id),
                    data: {
                        _token: $("meta[name='csrf_token']").attr('content'),
                        attachment: data,
                        _method: 'PUT',
                    },
                    dataType: 'html',
                    success: function(data) {
                        console.log('file update');
                    },
                });
            },
        },
    });

    const postDropzone = new Dropzone('.dropzone', {
        url: dashboard.prefix('/systems/files'),
        method: 'post',
        uploadMultiple: false,
        parallelUploads: 100,
        maxFilesize: 9999,
        paramName: 'files',
        acceptedFiles: $('#post-attachment-dropzone').data('accepted'),
        maxThumbnailFilesize: 99999,
        previewsContainer: '.visual-dropzone',
        //previewTemplate: document.getElementById('preview-template').innerHTML,
        addRemoveLinks: false,
        dictFileTooBig: 'File is big',

        init: function() {
            this.on('addedfile', function(e) {
                var n = Dropzone.createElement(
                    "",
                    ),
                    t = this;
                n.addEventListener('click', function(n) {
                    n.preventDefault(), n.stopPropagation(), t.removeFile(e);
                }),
                    e.previewElement.appendChild(n);

                var n = Dropzone.createElement(
                    "",
                    ),
                    t = this;
                n.addEventListener('click', function(n) {
                    attachmentDescription.loadInfo(e.data);
                    $('#modalAttachment').modal('show');
                }),
                    e.previewElement.appendChild(n);
            });

            this.on('completemultiple', function(file, json) {
                $('.sortable-dropzone').sortable('enable');
            });

            const instanceDropZone = this;

            const id = $('#post').data('post-id');
            if (id !== undefined) {
                $.ajax({
                    type: 'get',
                    url: dashboard.prefix('/systems/files/post/' + id),
                    data: { _token: $("meta[name='csrf_token']").attr('content') },
                    dataType: 'html',
                    success: function(data) {
                        const images = JSON.parse(data);

                        images.forEach(function(item, i, arr) {
                            const mockFile = {
                                id: item.id,
                                name: item.original_name,
                                size: item.size,
                                type: item.mime,
                                status: Dropzone.ADDED,
                                url: '/storage/' + item.path + item.name + '.' + item.extension,
                                data: item,
                            };

                            instanceDropZone.emit('addedfile', mockFile);
                            instanceDropZone.emit('thumbnail', mockFile, mockFile.url);
                            instanceDropZone.files.push(mockFile);
                            $('.dz-preview:last-child')
                                .attr('data-file-id', item.id)
                                .addClass('file-sort');
                        });

                        $('.dz-progress').remove();
                    },
                });
            }

            this.on('sending', function(file, xhr, formData) {
                formData.append('_token', $("meta[name='csrf_token']").attr('content'));
                formData.append(
                    'storage',
                    $('#post-attachment-dropzone').data('storage'),
                );
            });

            this.on('removedfile', function(file) {
                $('.files-' + file.data.id).remove();

                $.ajax({
                    type: 'delete',
                    url: dashboard.prefix('/systems/files/' + file.data.id),
                    data: {
                        _token: $("meta[name='csrf_token']").attr('content'),
                        storage: $('#post-attachment-dropzone').data('storage'),
                    },
                    dataType: 'html',
                    success: function(data) {
                        //
                    },
                });
            });
        },
        error: function(file, response) {
            if ($.type(response) === 'string') {
                return response; //dropzone sends it's own error messages in string
            }
            return response.message;
        },
        success: function(file, response) {
            file.data = response;
            $('.dz-preview:last-child')
                .attr('data-file-id', response.id)
                .addClass('file-sort');
            $(
                "<input type='hidden' class='files-" +
                response.id +
                "' name='files[]' value='" +
                response.id +
                "'  />",
            ).appendTo('.dropzone');
        },
    });

    $('.sortable-dropzone').sortable({
        update: function() {
            const items = {};
            $('.file-sort').each(function(index, value) {
                const id = $(this).attr('data-file-id');
                items[id] = index;
            });

            $.ajax({
                type: 'post',
                url: dashboard.prefix('/systems/files/sort'),
                data: {
                    _token: $("meta[name='csrf_token']").attr('content'),
                    files: items,
                },
                dataType: 'html',
                success: function(response) {
                    console.log(response);
                },
            });
        },
    });
});<commit_msg>Apply fixes from StyleCI (#596)<commit_after>document.addEventListener('turbolinks:load', function() {
  if (document.getElementById('post-attachment-dropzone') === null) {
    return;
  }

  const attachmentDescription = new Vue({
    el: '#modalAttachment',
    data: {
      attachment: {},
      active: null,
    },
    methods: {
      loadInfo: function(data) {
        let name = data.name + data.id;

        data.url = '/storage/' + data.path + data.name + '.' + data.extension;

        if (!this.attachment.hasOwnProperty(name)) {
          this.attachment[name] = data;
        }
        this.active = name;
      },
      save: function() {
        let data = this.attachment[this.active];

        $('#modalAttachment').modal('toggle');

        $.ajax({
          type: 'POST',
          url: dashboard.prefix('/systems/files/post/' + data.id),
          data: {
            _token: $("meta[name='csrf_token']").attr('content'),
            attachment: data,
            _method: 'PUT',
          },
          dataType: 'html',
          success: function(data) {
            console.log('file update');
          },
        });
      },
    },
  });

  const postDropzone = new Dropzone('.dropzone', {
    url: dashboard.prefix('/systems/files'),
    method: 'post',
    uploadMultiple: false,
    parallelUploads: 100,
    maxFilesize: 9999,
    paramName: 'files',
    acceptedFiles: $('#post-attachment-dropzone').data('accepted'),
    maxThumbnailFilesize: 99999,
    previewsContainer: '.visual-dropzone',
    //previewTemplate: document.getElementById('preview-template').innerHTML,
    addRemoveLinks: false,
    dictFileTooBig: 'File is big',

    init: function() {
      this.on('addedfile', function(e) {
        var n = Dropzone.createElement(
            "",
          ),
          t = this;
        n.addEventListener('click', function(n) {
          n.preventDefault(), n.stopPropagation(), t.removeFile(e);
        }),
          e.previewElement.appendChild(n);

        var n = Dropzone.createElement(
            "",
          ),
          t = this;
        n.addEventListener('click', function(n) {
          attachmentDescription.loadInfo(e.data);
          $('#modalAttachment').modal('show');
        }),
          e.previewElement.appendChild(n);
      });

      this.on('completemultiple', function(file, json) {
        $('.sortable-dropzone').sortable('enable');
      });

      const instanceDropZone = this;

      const id = $('#post').data('post-id');
      if (id !== undefined) {
        $.ajax({
          type: 'get',
          url: dashboard.prefix('/systems/files/post/' + id),
          data: { _token: $("meta[name='csrf_token']").attr('content') },
          dataType: 'html',
          success: function(data) {
            const images = JSON.parse(data);

            images.forEach(function(item, i, arr) {
              const mockFile = {
                id: item.id,
                name: item.original_name,
                size: item.size,
                type: item.mime,
                status: Dropzone.ADDED,
                url: '/storage/' + item.path + item.name + '.' + item.extension,
                data: item,
              };

              instanceDropZone.emit('addedfile', mockFile);
              instanceDropZone.emit('thumbnail', mockFile, mockFile.url);
              instanceDropZone.files.push(mockFile);
              $('.dz-preview:last-child')
                .attr('data-file-id', item.id)
                .addClass('file-sort');
            });

            $('.dz-progress').remove();
          },
        });
      }

      this.on('sending', function(file, xhr, formData) {
        formData.append('_token', $("meta[name='csrf_token']").attr('content'));
        formData.append(
          'storage',
          $('#post-attachment-dropzone').data('storage'),
        );
      });

      this.on('removedfile', function(file) {
        $('.files-' + file.data.id).remove();

        $.ajax({
          type: 'delete',
          url: dashboard.prefix('/systems/files/' + file.data.id),
          data: {
            _token: $("meta[name='csrf_token']").attr('content'),
            storage: $('#post-attachment-dropzone').data('storage'),
          },
          dataType: 'html',
          success: function(data) {
            //
          },
        });
      });
    },
    error: function(file, response) {
      if ($.type(response) === 'string') {
        return response; //dropzone sends it's own error messages in string
      }
      return response.message;
    },
    success: function(file, response) {
      file.data = response;
      $('.dz-preview:last-child')
        .attr('data-file-id', response.id)
        .addClass('file-sort');
      $(
        "<input type='hidden' class='files-" +
          response.id +
          "' name='files[]' value='" +
          response.id +
          "'  />",
      ).appendTo('.dropzone');
    },
  });

  $('.sortable-dropzone').sortable({
    update: function() {
      const items = {};
      $('.file-sort').each(function(index, value) {
        const id = $(this).attr('data-file-id');
        items[id] = index;
      });

      $.ajax({
        type: 'post',
        url: dashboard.prefix('/systems/files/sort'),
        data: {
          _token: $("meta[name='csrf_token']").attr('content'),
          files: items,
        },
        dataType: 'html',
        success: function(response) {
          console.log(response);
        },
      });
    },
  });
});
<|endoftext|>


<commit_before>/**
 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
 * directory of this distribution and at
 * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
 */
;
(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        define(factory);
    } else if (typeof exports === "object") {
        module.exports = factory();
    } else {
        root.ResizeSensor = factory();
    }
}(this, function () {

    //Make sure it does not throw in a SSR (Server Side Rendering) situation
    if (typeof window === "undefined") {
        return null;
    }
    // Only used for the dirty checking, so the event callback count is limted to max 1 call per fps per sensor.
    // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and
    // would generate too many unnecessary events.
    var requestAnimationFrame = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function (fn) {
            return window.setTimeout(fn, 20);
        };

    /**
     * Iterate over each of the provided element(s).
     *
     * @param {HTMLElement|HTMLElement[]} elements
     * @param {Function}                  callback
     */
    function forEachElement(elements, callback){
        var elementsType = Object.prototype.toString.call(elements);
        var isCollectionTyped = ('[object Array]' === elementsType
            || ('[object NodeList]' === elementsType)
            || ('[object HTMLCollection]' === elementsType)
            || ('[object Object]' === elementsType)
            || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery
            || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools
        );
        var i = 0, j = elements.length;
        if (isCollectionTyped) {
            for (; i < j; i++) {
                callback(elements[i]);
            }
        } else {
            callback(elements);
        }
    }

    /**
     * Class for dimension change detection.
     *
     * @param {Element|Element[]|Elements|jQuery} element
     * @param {Function} callback
     *
     * @constructor
     */
    var ResizeSensor = function(element, callback) {
        /**
         *
         * @constructor
         */
        function EventQueue() {
            var q = [];
            this.add = function(ev) {
                q.push(ev);
            };

            var i, j;
            this.call = function() {
                for (i = 0, j = q.length; i < j; i++) {
                    q[i].call();
                }
            };

            this.remove = function(ev) {
                var newQueue = [];
                for(i = 0, j = q.length; i < j; i++) {
                    if(q[i] !== ev) newQueue.push(q[i]);
                }
                q = newQueue;
            }

            this.length = function() {
                return q.length;
            }
        }

        /**
         * @param {HTMLElement} element
         * @param {String}      prop
         * @returns {String|Number}
         */
        function getComputedStyle(element, prop) {
            if (element.currentStyle) {
                return element.currentStyle[prop];
            } else if (window.getComputedStyle) {
                return window.getComputedStyle(element, null).getPropertyValue(prop);
            } else {
                return element.style[prop];
            }
        }

        /**
         *
         * @param {HTMLElement} element
         * @param {Function}    resized
         */
        function attachResizeEvent(element, resized) {
            if (!element.resizedAttached) {
                element.resizedAttached = new EventQueue();
                element.resizedAttached.add(resized);
            } else if (element.resizedAttached) {
                element.resizedAttached.add(resized);
                return;
            }

            element.resizeSensor = document.createElement('div');
            element.resizeSensor.className = 'resize-sensor';
            var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;';
            var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';

            element.resizeSensor.style.cssText = style;
            element.resizeSensor.innerHTML =
                '
' +
                    '

' +
                '
' +
                '
' +
                    '

' +
                '
';
            element.appendChild(element.resizeSensor);

            if (getComputedStyle(element, 'position') == 'static') {
                element.style.position = 'relative';
            }

            var expand = element.resizeSensor.childNodes[0];
            var expandChild = expand.childNodes[0];
            var shrink = element.resizeSensor.childNodes[1];

            var reset = function() {
                expandChild.style.width  = 100000 + 'px';
                expandChild.style.height = 100000 + 'px';

                expand.scrollLeft = 100000;
                expand.scrollTop = 100000;

                shrink.scrollLeft = 100000;
                shrink.scrollTop = 100000;
            };

            reset();
            var dirty = false;

            var dirtyChecking = function() {
                if (!element.resizedAttached) return;

                if (dirty) {
                    element.resizedAttached.call();
                    dirty = false;
                }

                requestAnimationFrame(dirtyChecking);
            };

            requestAnimationFrame(dirtyChecking);
            var lastWidth, lastHeight;
            var cachedWidth, cachedHeight; //useful to not query offsetWidth twice

            var onScroll = function() {
              if ((cachedWidth = element.offsetWidth) != lastWidth || (cachedHeight = element.offsetHeight) != lastHeight) {
                  dirty = true;

                  lastWidth = cachedWidth;
                  lastHeight = cachedHeight;
              }
              reset();
            };

            var addEvent = function(el, name, cb) {
                if (el.attachEvent) {
                    el.attachEvent('on' + name, cb);
                } else {
                    el.addEventListener(name, cb);
                }
            };

            addEvent(expand, 'scroll', onScroll);
            addEvent(shrink, 'scroll', onScroll);
        }

        forEachElement(element, function(elem){
            attachResizeEvent(elem, callback);
        });

        this.detach = function(ev) {
            ResizeSensor.detach(element, ev);
        };
    };

    ResizeSensor.detach = function(element, ev) {
        forEachElement(element, function(elem){
            if(elem.resizedAttached && typeof ev == "function"){
                elem.resizedAttached.remove(ev);
                if(elem.resizedAttached.length()) return;
            }
            if (elem.resizeSensor) {
                if (elem.contains(elem.resizeSensor)) {
                    elem.removeChild(elem.resizeSensor);
                }
                delete elem.resizeSensor;
                delete elem.resizedAttached;
            }
        });
    };

    return ResizeSensor;

}));
<commit_msg>Removed dirty checking, minor optimizations (#135)<commit_after>/**
 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
 * directory of this distribution and at
 * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
 */
;
(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        define(factory);
    } else if (typeof exports === "object") {
        module.exports = factory();
    } else {
        root.ResizeSensor = factory();
    }
}(this, function () {

    //Make sure it does not throw in a SSR (Server Side Rendering) situation
    if (typeof window === "undefined") {
        return null;
    }
    // Only used for the dirty checking, so the event callback count is limted to max 1 call per fps per sensor.
    // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and
    // would generate too many unnecessary events.
    var requestAnimationFrame = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function (fn) {
            return window.setTimeout(fn, 20);
        };

    /**
     * Iterate over each of the provided element(s).
     *
     * @param {HTMLElement|HTMLElement[]} elements
     * @param {Function}                  callback
     */
    function forEachElement(elements, callback){
        var elementsType = Object.prototype.toString.call(elements);
        var isCollectionTyped = ('[object Array]' === elementsType
            || ('[object NodeList]' === elementsType)
            || ('[object HTMLCollection]' === elementsType)
            || ('[object Object]' === elementsType)
            || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery
            || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools
        );
        var i = 0, j = elements.length;
        if (isCollectionTyped) {
            for (; i < j; i++) {
                callback(elements[i]);
            }
        } else {
            callback(elements);
        }
    }

    /**
     * Class for dimension change detection.
     *
     * @param {Element|Element[]|Elements|jQuery} element
     * @param {Function} callback
     *
     * @constructor
     */
    var ResizeSensor = function(element, callback) {
        /**
         *
         * @constructor
         */
        function EventQueue() {
            var q = [];
            this.add = function(ev) {
                q.push(ev);
            };

            var i, j;
            this.call = function() {
                for (i = 0, j = q.length; i < j; i++) {
                    q[i].call();
                }
            };

            this.remove = function(ev) {
                var newQueue = [];
                for(i = 0, j = q.length; i < j; i++) {
                    if(q[i] !== ev) newQueue.push(q[i]);
                }
                q = newQueue;
            }

            this.length = function() {
                return q.length;
            }
        }

        /**
         * @param {HTMLElement} element
         * @param {String}      prop
         * @returns {String|Number}
         */
        function getComputedStyle(element, prop) {
            if (element.currentStyle) {
                return element.currentStyle[prop];
            } else if (window.getComputedStyle) {
                return window.getComputedStyle(element, null).getPropertyValue(prop);
            } else {
                return element.style[prop];
            }
        }

        /**
         *
         * @param {HTMLElement} element
         * @param {Function}    resized
         */
        function attachResizeEvent(element, resized) {
            if (!element.resizedAttached) {
                element.resizedAttached = new EventQueue();
                element.resizedAttached.add(resized);
            } else if (element.resizedAttached) {
                element.resizedAttached.add(resized);
                return;
            }

            element.resizeSensor = document.createElement('div');
            element.resizeSensor.className = 'resize-sensor';
            var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;';
            var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';

            element.resizeSensor.style.cssText = style;
            element.resizeSensor.innerHTML =
                '
' +
                    '

' +
                '
' +
                '
' +
                    '

' +
                '
';
            element.appendChild(element.resizeSensor);

            if (getComputedStyle(element, 'position') == 'static') {
                element.style.position = 'relative';
            }

            var expand = element.resizeSensor.childNodes[0];
            var expandChild = expand.childNodes[0];
            var shrink = element.resizeSensor.childNodes[1];
            var dirty, rafId, newWidth, newHeight;
            var lastWidth = element.offsetWidth;
            var lastHeight = element.offsetHeight;

            var reset = function() {
                expandChild.style.width = '100000px';
                expandChild.style.height = '100000px';

                expand.scrollLeft = 100000;
                expand.scrollTop = 100000;

                shrink.scrollLeft = 100000;
                shrink.scrollTop = 100000;
            };

            reset();

            var onResized = function() {
                rafId = 0;

                if (!dirty) return;

                lastWidth = newWidth;
                lastHeight = newHeight;

                if (element.resizedAttached) {
                    element.resizedAttached.call();
                }
            };

            var onScroll = function() {
                newWidth = element.offsetWidth;
                newHeight = element.offsetHeight;
                dirty = newWidth != lastWidth || newHeight != lastHeight;

                if (dirty && !rafId) {
                    rafId = requestAnimationFrame(onResized);
                }

                reset();
            };

            var addEvent = function(el, name, cb) {
                if (el.attachEvent) {
                    el.attachEvent('on' + name, cb);
                } else {
                    el.addEventListener(name, cb);
                }
            };

            addEvent(expand, 'scroll', onScroll);
            addEvent(shrink, 'scroll', onScroll);
        }

        forEachElement(element, function(elem){
            attachResizeEvent(elem, callback);
        });

        this.detach = function(ev) {
            ResizeSensor.detach(element, ev);
        };
    };

    ResizeSensor.detach = function(element, ev) {
        forEachElement(element, function(elem){
            if(elem.resizedAttached && typeof ev == "function"){
                elem.resizedAttached.remove(ev);
                if(elem.resizedAttached.length()) return;
            }
            if (elem.resizeSensor) {
                if (elem.contains(elem.resizeSensor)) {
                    elem.removeChild(elem.resizeSensor);
                }
                delete elem.resizeSensor;
                delete elem.resizedAttached;
            }
        });
    };

    return ResizeSensor;

}));
<|endoftext|>