<commit_before>$ = jQuery;

var generalInformation;
var observations = new Array();
var verifications = new Array();

/**
 * Executed after page was loaded.
 */
$(document).ready(function() {
	initializeImageSlider();
	initializeSubmitVerificationButton();
});

function cacheAllData(result) {

	// cache general information
	generalInformation = result.general;

	// cache observation information
	if(result.observations != null) {
		for (var i = 0; i < result.observations.length; i ++) {
			observations.push(result.observations[i]);
		}
	}

	// cache verification information
	if(result.verifications != null) {
		for (var i = 0; i < result.verifications.length; i ++) {
			verifications.push(result.verifications[i]);
		}
	}
}

function submitVerification() {
	$.ajax({
		type: "POST",
		url: "/vote/save",
		success: function(result){
			// scroll to the top of the page to display the next observation
			$('html, body').animate({ scrollTop: 0 });

			var currentVerifications = getVerificationsForObservation(observations[currentMainImageIndex].observation_id);

			if (result.name_lang == null) {
				result.name_lang = Drupal.t("No translation available");
			}
			var myVote = {
				comment: $('#comment').val(),
				observation_id: observations[currentMainImageIndex].observation_id.toString(),
				organism_id: result.id,
				scientific_name: result.name_lat,
				translated_name: result.name_lang,
				user_id: generalInformation.current_user_id.toString(),
				user_name: generalInformation.current_user_name,
				vote_timestamp: Math.round((new Date()).getTime() / 1000).toString()
			};

			if(currentVerifications == null) {
				currentVerifications = [myVote];
			} else {
				for(var i = 0; i < currentVerifications.length; i++) {
					if(currentVerifications[i].user_id == generalInformation.current_user_id) {
						currentVerifications.splice(i, 1);
					}
				}
				currentVerifications.push(myVote);
			}

			setVerificationsForObservation(observations[currentMainImageIndex].observation_id, currentVerifications);

			nextImage();
		},
		error: function(result) {
			observation.setMessage(Drupal.t('Could not save the verification. Please try again.'), 'error', 5000);
		},
		data: {
			observation_id: observations[currentMainImageIndex].observation_id,
			organism_name: $('#organism_name').val(),
			date: $('#date').val(),
			time: $('#time').val(),
			vote_comment: $('#comment').val()
		}
	});
}

/**
 * Initializes the submit verification button.
 */
function initializeSubmitVerificationButton() {
	$('#submitVerification').click(function() {
		submitVerification();
	});
}

function getVerificationsForObservation(observation_id) {
	var resultArray = new Array();
	for (var i = 0; i < verifications.length; i ++) {
		if (verifications[i].observation_id == observation_id) {
			resultArray.push(verifications[i]);
		}
	}
	return resultArray;
}

function setVerificationsForObservation(observation_id, newVerificationsArray) {
	for (var i = 0; i < verifications.length; i ++) {
		if (verifications[i].observation_id == observation_id) {
			verifications.splice(i, 1);
		}
	}

	for (var i = 0; i < newVerificationsArray.length; i ++) {
		verifications.push(newVerificationsArray[i]);
	}
}

function getVerificationsPerOrganism(filteredVerificationsArray) {
	var alreadyPushedOrganismIds = [];
	var resultArray = [];

	for (var i = 0; i < filteredVerificationsArray.length; i++) {
		var currentOrganismId = filteredVerificationsArray[i].organism_id;
		if (alreadyPushedOrganismIds.indexOf(currentOrganismId) == -1) {
			resultArray.push({
				organism_id: currentOrganismId,
				verifications: [filteredVerificationsArray[i]]
			});
			alreadyPushedOrganismIds.push(currentOrganismId);
		} else {
			for (var b = 0; b < resultArray.length; b++) {
				if (currentOrganismId == resultArray[b].organism_id) {
					resultArray[b].verifications.push(filteredVerificationsArray[i]);
					break;
				}
			}
		}
	}

	return resultArray;
}

/**
 * Loads the votes from other users for the current observation.
 */
function initializeVotesFromOtherUsers() {
	var container = $('#selectBoxContainer');
	var noVerificationsMessage = $('#noVerificationsMessage');

	container.html('');

	// get the verifications according to the current observation
	var currentVerifications = getVerificationsForObservation(observations[currentMainImageIndex].observation_id);

	if (currentVerifications.length > 0) {

		// display verification container
		noVerificationsMessage.hide();
		container.show();

		var totalVotes = currentVerifications.length;

		var verificationsPerOrganism = getVerificationsPerOrganism(currentVerifications);
		var htmlString = "";

		for (var i = 0; i < verificationsPerOrganism.length; i++) {
			var votesForCurrentOrganism = verificationsPerOrganism[i].verifications.length;
			var votesPercent = Math.round(votesForCurrentOrganism / totalVotes * 100, 0);

			htmlString +=		'
'
							  + '
'
							  + '' + verificationsPerOrganism[i].verifications[0].translated_name + ''
							  + '' + verificationsPerOrganism[i].verifications[0].scientific_name + ''
							  + '' + votesForCurrentOrganism + ' ' + Drupal.t('verifications') + ''
							  + '
'
							  + '
' + Drupal.t('Agree') + '
'
							  + '
';

			for (var a = 0; a < verificationsPerOrganism[i].verifications.length; a++) {
				if(verificationsPerOrganism[i].verifications[a].comment != "" && verificationsPerOrganism[i].verifications[a].comment != null) {
					htmlString +=		'
'
									  + '
' + verificationsPerOrganism[i].verifications[a].user_name + ' am ' + new Date(verificationsPerOrganism[i].verifications[a].vote_timestamp * 1000).format("d.m.Y H:i") + ':
'
									  + '
' + verificationsPerOrganism[i].verifications[a].comment + '
'
									  + '
';
				}
			}

			htmlString +=		'
'
							  + '
';
		}
		container.html(htmlString);
	} else {

		// hide container and display information message
		container.hide();
		noVerificationsMessage.html(Drupal.t('No verifications found for this observation.'));
		noVerificationsMessage.show();
	}

	initializeSelectBox();
}

//Simulates PHP's date function
Date.prototype.format=function(e){var t="";var n=Date.replaceChars;for(var r=0;r<e.length;r++){var i=e.charAt(r);if(r-1>=0&&e.charAt(r-1)=="\\"){t+=i}else if(n[i]){t+=n[i].call(this)}else if(i!="\\"){t+=i}}return t};Date.replaceChars={shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longDays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],d:function(){return(this.getDate()<10?"0":"")+this.getDate()},D:function(){return Date.replaceChars.shortDays[this.getDay()]},j:function(){return this.getDate()},l:function(){return Date.replaceChars.longDays[this.getDay()]},N:function(){return this.getDay()+1},S:function(){return this.getDate()%10==1&&this.getDate()!=11?"st":this.getDate()%10==2&&this.getDate()!=12?"nd":this.getDate()%10==3&&this.getDate()!=13?"rd":"th"},w:function(){return this.getDay()},z:function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil((this-e)/864e5)},W:function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil(((this-e)/864e5+e.getDay()+1)/7)},F:function(){return Date.replaceChars.longMonths[this.getMonth()]},m:function(){return(this.getMonth()<9?"0":"")+(this.getMonth()+1)},M:function(){return Date.replaceChars.shortMonths[this.getMonth()]},n:function(){return this.getMonth()+1},t:function(){var e=new Date;return(new Date(e.getFullYear(),e.getMonth(),0)).getDate()},L:function(){var e=this.getFullYear();return e%400==0||e%100!=0&&e%4==0},o:function(){var e=new Date(this.valueOf());e.setDate(e.getDate()-(this.getDay()+6)%7+3);return e.getFullYear()},Y:function(){return this.getFullYear()},y:function(){return(""+this.getFullYear()).substr(2)},a:function(){return this.getHours()<12?"am":"pm"},A:function(){return this.getHours()<12?"AM":"PM"},B:function(){return Math.floor(((this.getUTCHours()+1)%24+this.getUTCMinutes()/60+this.getUTCSeconds()/3600)*1e3/24)},g:function(){return this.getHours()%12||12},G:function(){return this.getHours()},h:function(){return((this.getHours()%12||12)<10?"0":"")+(this.getHours()%12||12)},H:function(){return(this.getHours()<10?"0":"")+this.getHours()},i:function(){return(this.getMinutes()<10?"0":"")+this.getMinutes()},s:function(){return(this.getSeconds()<10?"0":"")+this.getSeconds()},u:function(){var e=this.getMilliseconds();return(e<10?"00":e<100?"0":"")+e},e:function(){return"Not Yet Supported"},I:function(){var e=null;for(var t=0;t<12;++t){var n=new Date(this.getFullYear(),t,1);var r=n.getTimezoneOffset();if(e===null)e=r;else if(r<e){e=r;break}else if(r>e)break}return this.getTimezoneOffset()==e|0},O:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+"00"},P:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+":00"},T:function(){var e=this.getMonth();this.setMonth(0);var t=this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/,"$1");this.setMonth(e);return t},Z:function(){return-this.getTimezoneOffset()*60},c:function(){return this.format("Y-m-d\\TH:i:sP")},r:function(){return this.toString()},U:function(){return this.getTime()/1e3}}<commit_msg>When no comment is available, only show the username and the date<commit_after>$ = jQuery;

var generalInformation;
var observations = new Array();
var verifications = new Array();

/**
 * Executed after page was loaded.
 */
$(document).ready(function() {
	initializeImageSlider();
	initializeSubmitVerificationButton();
});

function cacheAllData(result) {

	// cache general information
	generalInformation = result.general;

	// cache observation information
	if(result.observations != null) {
		for (var i = 0; i < result.observations.length; i ++) {
			observations.push(result.observations[i]);
		}
	}

	// cache verification information
	if(result.verifications != null) {
		for (var i = 0; i < result.verifications.length; i ++) {
			verifications.push(result.verifications[i]);
		}
	}
}

function submitVerification() {
	$.ajax({
		type: "POST",
		url: "/vote/save",
		success: function(result){
			// scroll to the top of the page to display the next observation
			$('html, body').animate({ scrollTop: 0 });

			var currentVerifications = getVerificationsForObservation(observations[currentMainImageIndex].observation_id);

			if (result.name_lang == null) {
				result.name_lang = Drupal.t("No translation available");
			}
			var myVote = {
				comment: $('#comment').val(),
				observation_id: observations[currentMainImageIndex].observation_id.toString(),
				organism_id: result.id,
				scientific_name: result.name_lat,
				translated_name: result.name_lang,
				user_id: generalInformation.current_user_id.toString(),
				user_name: generalInformation.current_user_name,
				vote_timestamp: Math.round((new Date()).getTime() / 1000).toString()
			};

			if(currentVerifications == null) {
				currentVerifications = [myVote];
			} else {
				for(var i = 0; i < currentVerifications.length; i++) {
					if(currentVerifications[i].user_id == generalInformation.current_user_id) {
						currentVerifications.splice(i, 1);
					}
				}
				currentVerifications.push(myVote);
			}

			setVerificationsForObservation(observations[currentMainImageIndex].observation_id, currentVerifications);

			nextImage();
		},
		error: function(result) {
			observation.setMessage(Drupal.t('Could not save the verification. Please try again.'), 'error', 5000);
		},
		data: {
			observation_id: observations[currentMainImageIndex].observation_id,
			organism_name: $('#organism_name').val(),
			date: $('#date').val(),
			time: $('#time').val(),
			vote_comment: $('#comment').val()
		}
	});
}

/**
 * Initializes the submit verification button.
 */
function initializeSubmitVerificationButton() {
	$('#submitVerification').click(function() {
		submitVerification();
	});
}

function getVerificationsForObservation(observation_id) {
	var resultArray = new Array();
	for (var i = 0; i < verifications.length; i ++) {
		if (verifications[i].observation_id == observation_id) {
			resultArray.push(verifications[i]);
		}
	}
	return resultArray;
}

function setVerificationsForObservation(observation_id, newVerificationsArray) {
	for (var i = 0; i < verifications.length; i ++) {
		if (verifications[i].observation_id == observation_id) {
			verifications.splice(i, 1);
		}
	}

	for (var i = 0; i < newVerificationsArray.length; i ++) {
		verifications.push(newVerificationsArray[i]);
	}
}

function getVerificationsPerOrganism(filteredVerificationsArray) {
	var alreadyPushedOrganismIds = [];
	var resultArray = [];

	for (var i = 0; i < filteredVerificationsArray.length; i++) {
		var currentOrganismId = filteredVerificationsArray[i].organism_id;
		if (alreadyPushedOrganismIds.indexOf(currentOrganismId) == -1) {
			resultArray.push({
				organism_id: currentOrganismId,
				verifications: [filteredVerificationsArray[i]]
			});
			alreadyPushedOrganismIds.push(currentOrganismId);
		} else {
			for (var b = 0; b < resultArray.length; b++) {
				if (currentOrganismId == resultArray[b].organism_id) {
					resultArray[b].verifications.push(filteredVerificationsArray[i]);
					break;
				}
			}
		}
	}

	return resultArray;
}

/**
 * Loads the votes from other users for the current observation.
 */
function initializeVotesFromOtherUsers() {
	var container = $('#selectBoxContainer');
	var noVerificationsMessage = $('#noVerificationsMessage');

	container.html('');

	// get the verifications according to the current observation
	var currentVerifications = getVerificationsForObservation(observations[currentMainImageIndex].observation_id);

	if (currentVerifications.length > 0) {

		// display verification container
		noVerificationsMessage.hide();
		container.show();

		var totalVotes = currentVerifications.length;

		var verificationsPerOrganism = getVerificationsPerOrganism(currentVerifications);
		var htmlString = "";

		for (var i = 0; i < verificationsPerOrganism.length; i++) {
			var votesForCurrentOrganism = verificationsPerOrganism[i].verifications.length;
			var votesPercent = Math.round(votesForCurrentOrganism / totalVotes * 100, 0);

			htmlString +=		'
'
							  + '
'
							  + '' + verificationsPerOrganism[i].verifications[0].translated_name + ''
							  + '' + verificationsPerOrganism[i].verifications[0].scientific_name + ''
							  + '' + votesForCurrentOrganism + ' ' + Drupal.t('verifications') + ''
							  + '
'
							  + '
' + Drupal.t('Agree') + '
'
							  + '
';

			for (var a = 0; a < verificationsPerOrganism[i].verifications.length; a++) {
				htmlString +=	'
'
									  + '
' + verificationsPerOrganism[i].verifications[a].user_name + ' am ' + new Date(verificationsPerOrganism[i].verifications[a].vote_timestamp * 1000).format("d.m.Y H:i") + '';
				if(verificationsPerOrganism[i].verifications[a].comment != "" && verificationsPerOrganism[i].verifications[a].comment != null) {
					htmlString +=		':

' + verificationsPerOrganism[i].verifications[a].comment + '
';
				} else {
					htmlString +=	'
';
				}
				htmlString +=	'
';
			}

			htmlString +=		'
'
							  + '
';
		}
		container.html(htmlString);
	} else {

		// hide container and display information message
		container.hide();
		noVerificationsMessage.html(Drupal.t('No verifications found for this observation.'));
		noVerificationsMessage.show();
	}

	initializeSelectBox();
}

//Simulates PHP's date function
Date.prototype.format=function(e){var t="";var n=Date.replaceChars;for(var r=0;r<e.length;r++){var i=e.charAt(r);if(r-1>=0&&e.charAt(r-1)=="\\"){t+=i}else if(n[i]){t+=n[i].call(this)}else if(i!="\\"){t+=i}}return t};Date.replaceChars={shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longDays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],d:function(){return(this.getDate()<10?"0":"")+this.getDate()},D:function(){return Date.replaceChars.shortDays[this.getDay()]},j:function(){return this.getDate()},l:function(){return Date.replaceChars.longDays[this.getDay()]},N:function(){return this.getDay()+1},S:function(){return this.getDate()%10==1&&this.getDate()!=11?"st":this.getDate()%10==2&&this.getDate()!=12?"nd":this.getDate()%10==3&&this.getDate()!=13?"rd":"th"},w:function(){return this.getDay()},z:function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil((this-e)/864e5)},W:function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil(((this-e)/864e5+e.getDay()+1)/7)},F:function(){return Date.replaceChars.longMonths[this.getMonth()]},m:function(){return(this.getMonth()<9?"0":"")+(this.getMonth()+1)},M:function(){return Date.replaceChars.shortMonths[this.getMonth()]},n:function(){return this.getMonth()+1},t:function(){var e=new Date;return(new Date(e.getFullYear(),e.getMonth(),0)).getDate()},L:function(){var e=this.getFullYear();return e%400==0||e%100!=0&&e%4==0},o:function(){var e=new Date(this.valueOf());e.setDate(e.getDate()-(this.getDay()+6)%7+3);return e.getFullYear()},Y:function(){return this.getFullYear()},y:function(){return(""+this.getFullYear()).substr(2)},a:function(){return this.getHours()<12?"am":"pm"},A:function(){return this.getHours()<12?"AM":"PM"},B:function(){return Math.floor(((this.getUTCHours()+1)%24+this.getUTCMinutes()/60+this.getUTCSeconds()/3600)*1e3/24)},g:function(){return this.getHours()%12||12},G:function(){return this.getHours()},h:function(){return((this.getHours()%12||12)<10?"0":"")+(this.getHours()%12||12)},H:function(){return(this.getHours()<10?"0":"")+this.getHours()},i:function(){return(this.getMinutes()<10?"0":"")+this.getMinutes()},s:function(){return(this.getSeconds()<10?"0":"")+this.getSeconds()},u:function(){var e=this.getMilliseconds();return(e<10?"00":e<100?"0":"")+e},e:function(){return"Not Yet Supported"},I:function(){var e=null;for(var t=0;t<12;++t){var n=new Date(this.getFullYear(),t,1);var r=n.getTimezoneOffset();if(e===null)e=r;else if(r<e){e=r;break}else if(r>e)break}return this.getTimezoneOffset()==e|0},O:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+"00"},P:function(){return(-this.getTimezoneOffset()<0?"-":"+")+(Math.abs(this.getTimezoneOffset()/60)<10?"0":"")+Math.abs(this.getTimezoneOffset()/60)+":00"},T:function(){var e=this.getMonth();this.setMonth(0);var t=this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/,"$1");this.setMonth(e);return t},Z:function(){return-this.getTimezoneOffset()*60},c:function(){return this.format("Y-m-d\\TH:i:sP")},r:function(){return this.toString()},U:function(){return this.getTime()/1e3}}<|endoftext|>


<commit_before>var puppeteer = require('puppeteer'),
    chalk = require('chalk'),
    fs = require('fs');

var URLs = require('./updates-urls.js');

// For each URL, we can check multiple CSS selectors and compare if it's value is correct
async function checkWebsites(){
  // Using for loops we can make the function wait for each async code to finish before the next iteration
  // https://stackoverflow.com/questions/46293216/crawling-multiple-url-in-a-loop-using-puppeteer
  for (let i = 0; i < URLs.length; i++) {
    const website = URLs[i];
    for (let j = 0; j < website.targets.length; j++) {
      const element = website.targets[j].element;
      const text = website.targets[j].value;

      const browser = await puppeteer.launch();
      const page = await browser.newPage();

      await page.goto(website.url);

      const pageElements = await page.$x(element);

      console.log(chalk.blue('Testing "' + website.url + '" for text ' + text + ':'));

      if (pageElements.length == 0) {
        console.log(chalk.red("Can't find element: " + element));
        // Uncomment this line to save HTML in a file and stop the script.
        const html = await page.content();
        fs.writeFile('./html-body.html', html, function(err) {
          console.log(chalk.red("Saved HTML to 'html-body.html' file!"));
        });

        await browser.close();
      } else {
        let textOfElement = await page.evaluate(el => el.textContent, pageElements[0]);

        if (textOfElement.trim() === text) {
          console.log(chalk.green('OK'));
        } else {
          // Something changed, report it
          console.log(chalk.red('Error in element:' + element));
          console.log(chalk.red('Expected value:' + text));
          console.log(chalk.red('Actual   value:' + textOfElement.trim()));
          console.log(chalk.red('Actual value before trim:' + textOfElement));
        }

        await browser.close();
      }
    }
  }
}

console.log(chalk.yellow('Testing if any information on the website requires updates'));
checkWebsites();
<commit_msg>check-for-updates script is no longer working<commit_after>//
// This script doesn't work anymore - the structure of each website has changed!
//

var puppeteer = require('puppeteer'),
    chalk = require('chalk'),
    fs = require('fs');

var URLs = require('./updates-urls.js');

// For each URL, we can check multiple CSS selectors and compare if it's value is correct
async function checkWebsites(){
  // Using for loops we can make the function wait for each async code to finish before the next iteration
  // https://stackoverflow.com/questions/46293216/crawling-multiple-url-in-a-loop-using-puppeteer
  for (let i = 0; i < URLs.length; i++) {
    const website = URLs[i];
    for (let j = 0; j < website.targets.length; j++) {
      const element = website.targets[j].element;
      const text = website.targets[j].value;

      const browser = await puppeteer.launch();
      const page = await browser.newPage();

      await page.goto(website.url);

      const pageElements = await page.$x(element);

      console.log(chalk.blue('Testing "' + website.url + '" for text ' + text + ':'));

      if (pageElements.length == 0) {
        console.log(chalk.red("Can't find element: " + element));
        // Uncomment this line to save HTML in a file and stop the script.
        const html = await page.content();
        fs.writeFile('./html-body.html', html, function(err) {
          console.log(chalk.red("Saved HTML to 'html-body.html' file!"));
        });

        await browser.close();
      } else {
        let textOfElement = await page.evaluate(el => el.textContent, pageElements[0]);

        if (textOfElement.trim() === text) {
          console.log(chalk.green('OK'));
        } else {
          // Something changed, report it
          console.log(chalk.red('Error in element:' + element));
          console.log(chalk.red('Expected value:' + text));
          console.log(chalk.red('Actual   value:' + textOfElement.trim()));
          console.log(chalk.red('Actual value before trim:' + textOfElement));
        }

        await browser.close();
      }
    }
  }
}

console.log(chalk.yellow('Testing if any information on the website requires updates'));
checkWebsites();
<|endoftext|>


<commit_before>;(function($, win, doc) {
  var $win = $(win);
  var $doc = $(doc);

  // Enable CSS active pseudo styles in Mobile Safari
  $doc.on({
    touchstart: function() {}
  });
})(jQuery, window, document);
<commit_msg>Initialize the fastclick plugin on document ready<commit_after>;(function($, win, doc) {
  var $win = $(win);
  var $doc = $(doc);

  // Enable CSS active pseudo styles in Mobile Safari
  $doc.on({
    touchstart: function() {},
    ready: function() {
      FastClick.attach(doc.body);
    }
  });
})(jQuery, window, document);
<|endoftext|>


<commit_before>import React, {useEffect, useLayoutEffect, useRef, useState} from 'react';
import { StateNavigator } from 'navigation';
import { NavigationHandler } from 'navigation-react';
import { NavigationStack } from 'navigation-react-native';

const Stack = ({ children, ...props }) => {
  const stateNavigatorRef = useRef(new StateNavigator([]))
  const stateNavigator = stateNavigatorRef.current;
  const [states, setStates] = useState([]);
  useEffect(() => {
    /**
     * Builds the new states from the children. Keeps the old states
     * but marks them as deleted (they're needed to parse old urls)
     */
    setStates(oldStates => {
      const { newStates, newStatesLookup } = React.Children.toArray(children)
        .reduce(({ newStates, newStatesLookup }, { props: { name, ...rest }}) => {
          newStates.push({ key: name, ...rest })
          newStatesLookup[name] = true;
          return { newStates, newStatesLookup };
        }, { newStates: [], newStatesLookup: {} })
      for(const oldState of oldStates) {
        if (!newStatesLookup[oldState.key])
          newStates.push({ ...oldState, __deleted: true });
      }
      return newStates;
    });
  }, [ children ]);
  useLayoutEffect(() => {
    /**
     * If the current stack contains any deleted scenes then navigates
     * to the first scene in the new stack. Adds a handler that prevents
     * attempted navigation to scenes in the old stack
     */
    const { state, url } = stateNavigator.stateContext;
    stateNavigator.configure(states);
    let changed = !state;
    if (!changed) {
      const { state, crumbs } = stateNavigator.parseLink(url);
      changed = state.__deleted || crumbs.filter(({ state }) => state.__deleted).length;
    }
    if (changed && states.length)
      stateNavigator.navigate(states[0].key);
    const validateNavigation = ({ __deleted }) => !__deleted;
    stateNavigator.onBeforeNavigate(validateNavigation);
    return () => stateNavigator.offBeforeNavigate(validateNavigation);
  }, [ states ]);
  return !!states.length && (
    <NavigationHandler stateNavigator={stateNavigator}>
      <NavigationStack {...props} />
    </NavigationHandler>
  )
}

Stack.Scene = () => null;

export default Stack;
<commit_msg>Simplified check for deleted scenes in stack<commit_after>import React, {useEffect, useLayoutEffect, useRef, useState} from 'react';
import { StateNavigator } from 'navigation';
import { NavigationHandler } from 'navigation-react';
import { NavigationStack } from 'navigation-react-native';

const Stack = ({ children, ...props }) => {
  const stateNavigatorRef = useRef(new StateNavigator([]))
  const stateNavigator = stateNavigatorRef.current;
  const [states, setStates] = useState([]);
  useEffect(() => {
    /**
     * Builds the new states from the children. Keeps the old states
     * but marks them as deleted (they're needed to parse old urls)
     */
    setStates(oldStates => {
      const { newStates, newStatesLookup } = React.Children.toArray(children)
        .reduce(({ newStates, newStatesLookup }, { props: { name, ...rest }}) => {
          newStates.push({ key: name, ...rest })
          newStatesLookup[name] = true;
          return { newStates, newStatesLookup };
        }, { newStates: [], newStatesLookup: {} })
      for(const oldState of oldStates) {
        if (!newStatesLookup[oldState.key])
          newStates.push({ ...oldState, __deleted: true });
      }
      return newStates;
    });
  }, [ children ]);
  useLayoutEffect(() => {
    /**
     * If the current stack contains any deleted scenes then navigates
     * to the first scene in the new stack. Adds a handler that prevents
     * attempted navigation to scenes in the old stack
     */
    const { state, url } = stateNavigator.stateContext;
    stateNavigator.configure(states);
    let changed = !state;
    if (!changed) {
      const { state: { __deleted }, crumbs } = stateNavigator.parseLink(url);
      changed = __deleted || crumbs.some(({ state: { __deleted } }) => __deleted);
    }
    if (changed && states.length)
      stateNavigator.navigate(states[0].key);
    const validateNavigation = ({ __deleted }) => !__deleted;
    stateNavigator.onBeforeNavigate(validateNavigation);
    return () => stateNavigator.offBeforeNavigate(validateNavigation);
  }, [ states ]);
  return !!states.length && (
    <NavigationHandler stateNavigator={stateNavigator}>
      <NavigationStack {...props} />
    </NavigationHandler>
  )
}

Stack.Scene = () => null;

export default Stack;
<|endoftext|>


<commit_before>import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Block from 'components/Block';
import { DropTarget } from 'react-dnd';
import update from 'react/lib/update';
import { saveResume } from 'actions/resumeActions';

import { RaisedButton, TextField, Paper } from 'material-ui/lib';

const blockTarget = {
  drop() {
  }
};

const Types = {
  BLOCK: 'block'
};

const ActionCreators = {
  saveResume: saveResume
};

const mapStateToProps = (state) => ({
  routerState: state.router
});
const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(ActionCreators, dispatch)
});

@DropTarget(Types.BLOCK, blockTarget, (connect) => ({
  connectDropTarget: connect.dropTarget()
}))
export class ResumeView extends React.Component {
  static propTypes = {
    actions: React.PropTypes.object,
    connectDropTarget: React.PropTypes.func.isRequired
  }

  constructor (props) {
    super(props);
    this.moveBlock = this.moveBlock.bind(this);
    this.findBlock = this.findBlock.bind(this);

    this.state = {
      blocks: [{
        id: 1,
        companyName: 'My Company',
        jobTitle: 'Senior Señor',
        year: '2015',
        location: 'San Francisco, CA'
      },
      {
        id: 2,
        companyName: 'Company 2',
        jobTitle: 'Mister Manager',
        year: '2014',
        location: 'Chicago, IL'
      },
      {
        id: 3,
        companyName: 'Company 3',
        jobTitle: 'Lowly Peon',
        year: '2012',
        location: 'New York, NY'
      }]
    };
  }

  handleSubmit() {
    this.props.actions.saveResume({
      blocks: this.state.blocks,
      resumeTitle: this.refs.resumeTitle.getValue()
    });
  }

  moveBlock(id, atIndex) {
    const { block, index } = this.findBlock(id);
    this.setState(update(this.state, {
      blocks: {
        $splice: [
          [index, 1],
          [atIndex, 0, block]
        ]
      }
    }));
  }

  findBlock(id) {
    const { blocks } = this.state;
    const block = blocks.filter(b => b.id === id)[0];

    return {
      block,
      index: blocks.indexOf(block)
    };
  }

  render() {
    const { connectDropTarget } = this.props;
    const { blocks } = this.state;

    return connectDropTarget(

          <TextField className='text-center'
                     style={{margin: '20px', backgroundColor: 'white'}}
                     hintStyle={{paddingLeft: '8px'}}
                     hintText='Your Resume Title'
                     ref='resumeTitle' />

          <RaisedButton label='Save Resume'
                        onClick={e => this.handleSubmit(e)} />

        <Paper style={{height: '800px', width: '95%', marginLeft: 'auto', marginRight: 'auto'}}>

          <Paper className='resumeContainer'
                 style={{marginLeft: '20px', marginRight: '20px'}} >
            {blocks.map(block => {
              return (
                <Block key={block.id}
                       id={block.id}
                       companyName={block.companyName}
                       jobTitle={block.jobTitle}
                       year={block.year}
                       location={block.location}
                       moveBlock={this.moveBlock}
                       findBlock={this.findBlock} />
              );
            })}
          </Paper>

        </Paper>

    );
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ResumeView);
<commit_msg>[feat]: Can now print the resume<commit_after>import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Block from 'components/Block';
import { DropTarget } from 'react-dnd';
import update from 'react/lib/update';
import { saveResume } from 'actions/resumeActions';

import { RaisedButton, TextField, Paper } from 'material-ui/lib';

const blockTarget = {
  drop() {
  }
};

const Types = {
  BLOCK: 'block'
};

const ActionCreators = {
  saveResume: saveResume
};

const mapStateToProps = (state) => ({
  routerState: state.router
});
const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(ActionCreators, dispatch)
});

@DropTarget(Types.BLOCK, blockTarget, (connect) => ({
  connectDropTarget: connect.dropTarget()
}))
export class ResumeView extends React.Component {
  static propTypes = {
    actions: React.PropTypes.object,
    connectDropTarget: React.PropTypes.func.isRequired
  }

  constructor (props) {
    super(props);
    this.moveBlock = this.moveBlock.bind(this);
    this.findBlock = this.findBlock.bind(this);

    this.state = {
      blocks: [{
        id: 1,
        companyName: 'My Company',
        jobTitle: 'Senior Señor',
        year: '2015',
        location: 'San Francisco, CA'
      },
      {
        id: 2,
        companyName: 'Company 2',
        jobTitle: 'Mister Manager',
        year: '2014',
        location: 'Chicago, IL'
      },
      {
        id: 3,
        companyName: 'Company 3',
        jobTitle: 'Lowly Peon',
        year: '2012',
        location: 'New York, NY'
      }]
    };
  }

  handleSubmit() {
    this.props.actions.saveResume({
      blocks: this.state.blocks,
      resumeTitle: this.refs.resumeTitle.getValue()
    });
  }

  moveBlock(id, atIndex) {
    const { block, index } = this.findBlock(id);
    this.setState(update(this.state, {
      blocks: {
        $splice: [
          [index, 1],
          [atIndex, 0, block]
        ]
      }
    }));
  }

  findBlock(id) {
    const { blocks } = this.state;
    const block = blocks.filter(b => b.id === id)[0];

    return {
      block,
      index: blocks.indexOf(block)
    };
  }

  handlPrint() {
    let prtContent = document.getElementById("resumeContainer");
    console.log(prtContent);
    let WinPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0');
    WinPrint.document.write(prtContent.innerHTML);
    WinPrint.document.close();
    WinPrint.focus();
    WinPrint.print();
    WinPrint.close();
  }

  render() {
    const { connectDropTarget } = this.props;
    const { blocks } = this.state;

    return connectDropTarget(

          <TextField className='text-center'
                     style={{margin: '20px', backgroundColor: 'white'}}
                     hintStyle={{paddingLeft: '8px'}}
                     hintText='Your Resume Title'
                     ref='resumeTitle' />

          <RaisedButton label='Save Resume'
                        onClick={e => this.handleSubmit(e)} />
          <RaisedButton label='Print resume' onClick={e => this.handlPrint(e)} />

        <Paper style={{height: '800px', width: '95%', marginLeft: 'auto', marginRight: 'auto'}}>

          <Paper className='resumeContainer' id='resumeContainer'
                 style={{marginLeft: '20px', marginRight: '20px'}} >
            {blocks.map(block => {
              return (
                <Block key={block.id}
                       id={block.id}
                       companyName={block.companyName}
                       jobTitle={block.jobTitle}
                       year={block.year}
                       location={block.location}
                       moveBlock={this.moveBlock}
                       findBlock={this.findBlock} />
              );
            })}
          </Paper>

        </Paper>

    );
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ResumeView);
<|endoftext|>


<commit_before>// Given a linked list, determine if it has a cycle in it.

// which would return true if the given Node is the first of a list with a loop, and false otherwise?
// How could you write so that it takes a constant amount of space and a reasonable amount of time?

// Here's a picture of what a list with a loop looks like:

// 1 -> 2 -> 3-> 4 -> 5 -> 6 -> 3

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {boolean}
 */

var hasCycle = function(head) {
    if( head === null) return false; // list does not exist..so no loop either.

    var slow = fast = head; // create two references to the start of the list.

     while(true) {
        slow = slow.next;          // 1 hop.
        if( fast.next !== null )
            fast = fast.next.next; // 2 hops.
        else
            return false;          // next node null => no loop.

        if( slow === null || fast === null ) // if either hits null..no loop.
            return false;
        if( slow === fast ) // if the two ever meet...we must have a loop.
            return true;
    }
};
<commit_msg>add notes<commit_after>// Given a linked list, determine if it has a cycle in it.

// which would return true if the given Node is the first of a list with a loop, and false otherwise?
// How could you write so that it takes a constant amount of space and a reasonable amount of time?

// Here's a picture of what a list with a loop looks like:

// 1 -> 2 -> 3-> 4 -> 5 -> 6 -> 3

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {boolean}
 */

// Floyd's cycle-finding algorithm, also know as tortoise and hare algorithm.
// The idea is to have two references to the list and move them at different speeds.
// Move one forward by 1 node and the other by 2 nodes.

// If the linked list has a loop they will definitely meet.
// Else either of the two references(or their next) will become null.

var hasCycle = function(head) {
    if( head === null) return false; // list does not exist..so no loop either.

    var slow = fast = head; // create two references to the start of the list.

     while(true) {
        slow = slow.next;          // 1 hop.
        if( fast.next !== null )
            fast = fast.next.next; // 2 hops.
        else
            return false;          // next node null => no loop.

        if( slow === null || fast === null ) // if either hits null..no loop.
            return false;
        if( slow === fast ) // if the two ever meet...we must have a loop.
            return true;
    }
};
<|endoftext|>


<commit_before>import $ from 'jquery';
import _ from 'underscore';

import DatasetModel from '../models/DatasetModel';
import CreateDatasetLicenseInfoWidget from './CreateDatasetLicenseInfoWidget';
import View from '../view';
import {showAlertDialog} from '../common/utilities';
import router from '../router';

import CreateDatasetTemplate from './createDataset.pug';
import './createDataset.styl';

const CreateDatasetView = View.extend({
    events: {
        'click #isic-create-dataset-show-license-info-link': 'showLicenseInfo',
        'change input[name="attribution"]': function (event) {
            // Update attribution name field sensitivity
            const target = $(event.target);
            if (target.val() === 'anonymous') {
                this.$('#isic-create-dataset-attribution-name').girderEnable(false);
            } else {
                this.$('#isic-create-dataset-attribution-name').girderEnable(true);
            }
        },
        'change #isic-create-dataset-license': function (event) {
            // Disable anonymous attribution unless CC-0 license is selected
            const target = $(event.target);
            const anonymous = this.$('#isic-create-dataset-attribution-anonymous');
            if (target.val() === 'CC-0') {
                anonymous.girderEnable(true);
            } else {
                if (anonymous.prop('checked')) {
                    this.$('#isic-create-dataset-attribution-attributed-to').prop('checked', true);
                    this.$('#isic-create-dataset-attribution-attributed-to').change();
                }
                anonymous.girderEnable(false);
            }
        },
        'submit #isic-create-dataset-form': function (event) {
            event.preventDefault();
            this.$('#isic-create-dataset-submit').girderEnable(false);

            const name = this.$('#isic-create-dataset-name').val();
            const description = this.$('#isic-create-dataset-description').val();
            const owner = this.$('#isic-create-dataset-owner').val();
            const license = this.$('#isic-create-dataset-license').val();
            const anonymous = this.$('#isic-create-dataset-attribution-anonymous').prop('checked');
            const attribution = this.$('#isic-create-dataset-attribution-name').val();

            this.dataset
                .set({
                    name: name,
                    description: description,
                    owner: owner,
                    license: license,
                    attribution: (anonymous ? 'Anonymous' : attribution)
                })
                .save()
                .done(() => {
                    showAlertDialog({
                        text: '
Dataset created successfully.
',
                        escapedHtml: true,
                        callback: () => {
                            // Navigate to dataset view
                            router.navigate(
                                'dataset',
                                {trigger: true});
                        }
                    });
                })
                .fail((resp) => {
                    showAlertDialog({
                        text: `<h4>Error submitting dataset</h4><br>${_.escape(resp.responseJSON.message)}`,
                        escapedHtml: true
                    });
                    this.$('#isic-create-dataset-submit').girderEnable(true);
                });
        }
    },

    initialize: function (settings) {
        this.dataset = new DatasetModel();

        this.render();
    },

    render: function () {
        this.$el.html(CreateDatasetTemplate());

        this.$('input#isic-create-dataset-name').focus();

        return this;
    },

    showLicenseInfo: function () {
        if (!this.licenseInfoWidget) {
            this.licenseInfoWidget = new CreateDatasetLicenseInfoWidget({
                el: $('#g-dialog-container'),
                parentView: this
            });
        }
        this.licenseInfoWidget.render();
    }
});

export default CreateDatasetView;
<commit_msg>Minor refactor of CreateDatasetViewEvents<commit_after>import $ from 'jquery';
import _ from 'underscore';

import DatasetModel from '../models/DatasetModel';
import CreateDatasetLicenseInfoWidget from './CreateDatasetLicenseInfoWidget';
import View from '../view';
import {showAlertDialog} from '../common/utilities';
import router from '../router';

import CreateDatasetTemplate from './createDataset.pug';
import './createDataset.styl';

const CreateDatasetView = View.extend({
    events: {
        'click #isic-create-dataset-show-license-info-link': 'showLicenseInfo',
        'change input[name="attribution"]': function (event) {
            // Update attribution name field sensitivity
            const attributionEl = $(event.currentTarget);
            const isAttributed = attributionEl.val() === 'attributed-to';
            this.$('#isic-create-dataset-attribution-name').girderEnable(isAttributed);
        },
        'change #isic-create-dataset-license': function (event) {
            const licenseEl = $(event.currentTarget);
            const isCC0 = licenseEl.val() === 'CC-0';
            const anonymousEl = this.$('#isic-create-dataset-attribution-anonymous');
            const isAnonymous = anonymousEl.prop('checked');

            anonymousEl.girderEnable(isCC0);
            if (!isCC0 && isAnonymous) {
                // Can no longer be anonymous
                this.$('#isic-create-dataset-attribution-attributed-to')
                    .prop('checked', true)
                    .change();
            }
        },
        'submit #isic-create-dataset-form': function (event) {
            event.preventDefault();
            this.$('#isic-create-dataset-submit').girderEnable(false);

            const name = this.$('#isic-create-dataset-name').val();
            const description = this.$('#isic-create-dataset-description').val();
            const owner = this.$('#isic-create-dataset-owner').val();
            const license = this.$('#isic-create-dataset-license').val();
            const anonymous = this.$('#isic-create-dataset-attribution-anonymous').prop('checked');
            const attribution = this.$('#isic-create-dataset-attribution-name').val();

            this.dataset
                .set({
                    name: name,
                    description: description,
                    owner: owner,
                    license: license,
                    attribution: (anonymous ? 'Anonymous' : attribution)
                })
                .save()
                .done(() => {
                    showAlertDialog({
                        text: '
Dataset created successfully.
',
                        escapedHtml: true,
                        callback: () => {
                            // Navigate to dataset view
                            router.navigate(
                                'dataset',
                                {trigger: true});
                        }
                    });
                })
                .fail((resp) => {
                    showAlertDialog({
                        text: `<h4>Error submitting dataset</h4><br>${_.escape(resp.responseJSON.message)}`,
                        escapedHtml: true
                    });
                    this.$('#isic-create-dataset-submit').girderEnable(true);
                });
        }
    },

    initialize: function (settings) {
        this.dataset = new DatasetModel();

        this.render();
    },

    render: function () {
        this.$el.html(CreateDatasetTemplate());

        this.$('input#isic-create-dataset-name').focus();

        return this;
    },

    showLicenseInfo: function () {
        if (!this.licenseInfoWidget) {
            this.licenseInfoWidget = new CreateDatasetLicenseInfoWidget({
                el: $('#g-dialog-container'),
                parentView: this
            });
        }
        this.licenseInfoWidget.render();
    }
});

export default CreateDatasetView;
<|endoftext|>


<commit_before>const webpack = require("webpack");
const env = require("./env");
const autoprefixer = require("autoprefixer");
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
const CSSMinimizerPlugin = require("css-minimizer-webpack-plugin");
const ForkTSCheckerPlugin = require("fork-ts-checker-webpack-plugin");
const HTMLPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const StylelintPlugin = require("stylelint-webpack-plugin");
const TSImportPlugin = require("ts-import-plugin");

const config = {
    mode: "production",
    entry: `${env.src}/index.tsx`,
    output: {
        path: env.dist,
        filename: "static/js/[name].[chunkhash:8].js",
        publicPath: env.webpackJSON === null ? "/" : env.webpackJSON.publicPath,
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".less"],
        modules: [env.src, "node_modules"],
        alias: {
            conf: env.conf,
            lib: env.lib,
        },
    },
    devtool: false,
    bail: true,
    optimization: {
        moduleIds: "named",
        runtimeChunk: "single",
        splitChunks: {
            automaticNameDelimiter: "-",
            maxAsyncRequests: 10,
        },
        minimizer: [
            new TerserPlugin({
                parallel: true,
            }),
            new CSSMinimizerPlugin(),
        ],
    },
    performance: {
        maxEntrypointSize: 1000000,
        maxAssetSize: 1000000,
    },
    module: {
        rules: [
            {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false,
                },
            },
            {
                test: /\.(ts|tsx)$/,
                include: env.src,
                loader: "ts-loader",
                options: {
                    configFile: env.tsConfig,
                    transpileOnly: true,
                    getCustomTransformers: () => ({
                        before: [TSImportPlugin({libraryName: "antd", libraryDirectory: "es", style: true})],
                    }),
                },
            },
            {
                test: /\.(css|less)$/,
                use: [
                    MiniCSSExtractPlugin.loader,
                    {
                        loader: "css-loader",
                        options: {
                            sourceMap: false,
                            importLoaders: 2,
                        },
                    },
                    {
                        loader: "postcss-loader",
                        options: {
                            sourceMap: false,
                            postcssOptions: {
                                plugins: [autoprefixer],
                            },
                        },
                    },
                    {
                        loader: "less-loader",
                        options: {
                            sourceMap: false,
                            lessOptions: {
                                javascriptEnabled: true,
                            },
                        },
                    },
                ],
            },
            {
                test: /\.(png|jpe?g|gif)$/,
                type: "asset/resource",
                generator: {
                    filename: "static/img/[name].[hash:8].[ext]",
                },
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                type: "asset/resource",
                generator: {
                    filename: "static/font/[name].[hash:8].[ext]",
                },
            },
            {
                test: /\.ico$/,
                type: "asset/resource",
                generator: {
                    filename: "static/ico/[name].[hash:8].ico",
                },
            },
        ],
    },
    plugins: [
        new MiniCSSExtractPlugin({
            filename: "static/css/[name].[contenthash:8].css",
            ignoreOrder: true,
        }),
        new ForkTSCheckerPlugin({
            typescript: {configFile: env.tsConfig},
            eslint: {files: `${env.src}/**/*.{ts,tsx}`},
        }),
        new StylelintPlugin({
            configFile: env.stylelintConfig,
            context: env.src,
            files: "**/*.less",
            syntax: "less",
        }),
        new HTMLPlugin({
            template: `${env.src}/index.html`,
            minify: {
                collapseBooleanAttributes: true,
                collapseInlineTagWhitespace: true,
                collapseWhitespace: true,
                includeAutoGeneratedTags: false,
                keepClosingSlash: true,
                minifyCSS: true,
                minifyJS: true,
                minifyURLs: true,
                removeAttributeQuotes: true,
                removeComments: true,
                removeEmptyAttributes: true,
                removeRedundantAttributes: true,
                removeScriptTypeAttributes: true,
                removeStyleLinkTypeAttributes: true,
                removeTagWhitespace: true,
                useShortDoctype: true,
            },
        }),
        new webpack.ProgressPlugin({profile: env.profile}),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    ],
};

module.exports = config;
<commit_msg>update webpack config to support IE 11<commit_after>const webpack = require("webpack");
const env = require("./env");
const autoprefixer = require("autoprefixer");
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
const CSSMinimizerPlugin = require("css-minimizer-webpack-plugin");
const ForkTSCheckerPlugin = require("fork-ts-checker-webpack-plugin");
const HTMLPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const StylelintPlugin = require("stylelint-webpack-plugin");
const TSImportPlugin = require("ts-import-plugin");

const config = {
    mode: "production",
    entry: `${env.src}/index.tsx`,
    output: {
        path: env.dist,
        filename: "static/js/[name].[chunkhash:8].js",
        publicPath: env.webpackJSON === null ? "/" : env.webpackJSON.publicPath,
        environment: {
            arrowFunction: false,
            bigIntLiteral: false,
            const: false,
            destructuring: false,
            dynamicImport: false,
            forOf: false,
            module: false,
        },
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".less"],
        modules: [env.src, "node_modules"],
        alias: {
            conf: env.conf,
            lib: env.lib,
        },
    },
    devtool: false,
    bail: true,
    optimization: {
        moduleIds: "named",
        runtimeChunk: "single",
        splitChunks: {
            automaticNameDelimiter: "-",
            maxAsyncRequests: 10,
        },
        minimizer: [
            new TerserPlugin({
                parallel: true,
            }),
            new CSSMinimizerPlugin(),
        ],
    },
    performance: {
        maxEntrypointSize: 1000000,
        maxAssetSize: 1000000,
    },
    module: {
        rules: [
            {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false,
                },
            },
            {
                test: /\.(ts|tsx)$/,
                include: env.src,
                loader: "ts-loader",
                options: {
                    configFile: env.tsConfig,
                    transpileOnly: true,
                    getCustomTransformers: () => ({
                        before: [TSImportPlugin({libraryName: "antd", libraryDirectory: "es", style: true})],
                    }),
                },
            },
            {
                test: /\.(css|less)$/,
                use: [
                    MiniCSSExtractPlugin.loader,
                    {
                        loader: "css-loader",
                        options: {
                            sourceMap: false,
                            importLoaders: 2,
                        },
                    },
                    {
                        loader: "postcss-loader",
                        options: {
                            sourceMap: false,
                            postcssOptions: {
                                plugins: [autoprefixer],
                            },
                        },
                    },
                    {
                        loader: "less-loader",
                        options: {
                            sourceMap: false,
                            lessOptions: {
                                javascriptEnabled: true,
                            },
                        },
                    },
                ],
            },
            {
                test: /\.(png|jpe?g|gif)$/,
                type: "asset/resource",
                generator: {
                    filename: "static/img/[name].[hash:8].[ext]",
                },
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                type: "asset/resource",
                generator: {
                    filename: "static/font/[name].[hash:8].[ext]",
                },
            },
            {
                test: /\.ico$/,
                type: "asset/resource",
                generator: {
                    filename: "static/ico/[name].[hash:8].ico",
                },
            },
        ],
    },
    plugins: [
        new MiniCSSExtractPlugin({
            filename: "static/css/[name].[contenthash:8].css",
            ignoreOrder: true,
        }),
        new ForkTSCheckerPlugin({
            typescript: {configFile: env.tsConfig},
            eslint: {files: `${env.src}/**/*.{ts,tsx}`},
        }),
        new StylelintPlugin({
            configFile: env.stylelintConfig,
            context: env.src,
            files: "**/*.less",
            syntax: "less",
        }),
        new HTMLPlugin({
            template: `${env.src}/index.html`,
            minify: {
                collapseBooleanAttributes: true,
                collapseInlineTagWhitespace: true,
                collapseWhitespace: true,
                includeAutoGeneratedTags: false,
                keepClosingSlash: true,
                minifyCSS: true,
                minifyJS: true,
                minifyURLs: true,
                removeAttributeQuotes: true,
                removeComments: true,
                removeEmptyAttributes: true,
                removeRedundantAttributes: true,
                removeScriptTypeAttributes: true,
                removeStyleLinkTypeAttributes: true,
                removeTagWhitespace: true,
                useShortDoctype: true,
            },
        }),
        new webpack.ProgressPlugin({profile: env.profile}),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    ],
};

module.exports = config;
<|endoftext|>


<commit_before>import { PureComponent, Children } from 'react'
import PropTypes from 'prop-types'
import compose from './compose'
import { CONTEXT_KEY } from './const'

export default class ThemeProvider extends PureComponent {
  static propTypes = {
    theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
    compose: PropTypes.bool,
    children: PropTypes.element.isRequired,
  }

  static defaultProps = {
    compose: true,
  }

  static contextTypes = {
    [CONTEXT_KEY]: PropTypes.object,
  }

  static childContextTypes = {
    [CONTEXT_KEY]: PropTypes.object,
  }

  constructor(props, context) {
    super(props, context)
    this.buildTheme(props, context)
  }

  componentWillUpdate(props, state, context) {
    if (this.context[CONTEXT_KEY] !== context[CONTEXT_KEY] || this.props.theme !== props.theme) {
      this.buildTheme(props, context)
    }
  }

  buildTheme(props, context) {
    const { theme } = props
    const { [CONTEXT_KEY]: parentTheme } = context

    if (typeof theme === 'function') {
      this.theme = theme(parentTheme)
    } else if (parentTheme && props.compose) {
      this.theme = compose(parentTheme, theme)
    } else {
      this.theme = theme
    }
  }

  getChildContext() {
    return { [CONTEXT_KEY]: this.theme }
  }

  render() {
    return Children.only(this.props.children)
  }
}
<commit_msg>Prevent mutating parent context theme<commit_after>import { PureComponent, Children } from 'react'
import PropTypes from 'prop-types'
import compose from './compose'
import { CONTEXT_KEY } from './const'

export default class ThemeProvider extends PureComponent {
  static propTypes = {
    theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
    compose: PropTypes.bool,
    children: PropTypes.element.isRequired,
  }

  static defaultProps = {
    compose: true,
  }

  static contextTypes = {
    [CONTEXT_KEY]: PropTypes.object,
  }

  static childContextTypes = {
    [CONTEXT_KEY]: PropTypes.object,
  }

  constructor(props, context) {
    super(props, context)
    this.buildTheme(props, context)
  }

  componentWillUpdate(props, state, context) {
    if (this.context[CONTEXT_KEY] !== context[CONTEXT_KEY] || this.props.theme !== props.theme) {
      this.buildTheme(props, context)
    }
  }

  buildTheme(props, context) {
    const { theme } = props
    const { [CONTEXT_KEY]: parentTheme } = context

    if (typeof theme === 'function') {
      this.theme = theme(parentTheme)
    } else if (parentTheme && props.compose) {
      this.theme = compose({}, parentTheme, theme)
    } else {
      this.theme = theme
    }
  }

  getChildContext() {
    return { [CONTEXT_KEY]: this.theme }
  }

  render() {
    return Children.only(this.props.children)
  }
}
<|endoftext|>


<commit_before>var server = io();
//Add socket.io stuff here
var dataObj = {}
$(document).ready(function(){
	$("#create-btn").click(function(){
        console.log(" iam not a hauaman");
		dataObj.lyrics = $("#lyrics").val();
		dataObj.instruments = $("#instr-dropdown").val();
		dataObj.tempo = parseInt($("#tempo").val());
		dataObj.songLength =(parseInt($("#minutes_song").val())*60)+parseInt($("#seconds_song").val());
		dataObj.key = $("#key-dropdown").val();
		dataObj.dance = parseInt($("#danceAmount").val());
		//affinities
		dataObj.lyr = parseInt($("#lyricAffin").val());
		dataObj.ins = parseInt($("#instAffin").val());
		dataObj.tem = parseInt($("#tempoAffin").val());
		dataObj.len = parseInt($("#lengthAffin").val());
		dataObj.kyA = parseInt($("#keyAffin").val());
		dataObj.dan = parseInt($("#danceAffin").val());

        server.emit('songinfo', dataObj);
	});

});
<commit_msg>Progress on comm<commit_after>var server = io();
//Add socket.io stuff here
var dataObj = {}

function makePlayers() {
    $(".player").each(function(ply) {
        ply = $(ply);
        var audio = ply.find("audio");
        var btn = ply.find("img");

        console.log(btn);

        btn.click(function() {
            if (audio.paused) {
                audio.play();
            } else {
                audio.pause();
            }
        });
    });
}

$(document).ready(function(){
    makePlayers();

	$("#create-btn").click(function(){
        console.log(" iam not a hauaman");
		dataObj.lyrics = $("#lyrics").val();
		dataObj.instruments = $("#instr-dropdown").val();
		dataObj.tempo = parseInt($("#tempo").val());
		dataObj.songLength =(parseInt($("#minutes_song").val())*60)+parseInt($("#seconds_song").val());
		dataObj.key = $("#key-dropdown").val();
		dataObj.dance = parseInt($("#danceAmount").val());
		//affinities
		dataObj.lyr = parseInt($("#lyricAffin").val());
		dataObj.ins = parseInt($("#instAffin").val());
		dataObj.tem = parseInt($("#tempoAffin").val());
		dataObj.len = parseInt($("#lengthAffin").val());
		dataObj.kyA = parseInt($("#keyAffin").val());
		dataObj.dan = parseInt($("#danceAffin").val());

        server.emit('songinfo', dataObj);
	});

});
<|endoftext|>


<commit_before>import {
  GPS_BUSY,
  GPS_BUSY_DONE,
  GPS_SEARCH,
  GPS_FAVORITE,
  GPS_FAVORITE_REMOVE,
  CREATE_ROUTE,
  DELETE_ROUTE,
} from './index.js'

export const isWormhole = name => /^J[0-9]{6}$/.test(name)
export const matchRoute = (origin, system) => route => ((route.origin.id === origin.id) && (route.destination.id === system.id))

const byOriginId = id => route => route.origin.id === id

export const deleteFavorite = system => ({
  type: GPS_FAVORITE_REMOVE,
  system
})

export const deleteRoute = (origin, destination) => ({
  type: DELETE_ROUTE,
  origin,
  destination
})

export const saveRoute = systems => ({
  type: CREATE_ROUTE,
  systems
})

export const addFavorite = system => (dispatch, getState, {api}) => {
  dispatch({ type: GPS_FAVORITE, system })

  const { gps, history } = getState()
  const favoriteRoutes = history.origins
  .filter(origin => origin.id !== system.id)
  .filter(origin => !gps.routes.some(matchRoute(origin, system)))
  .map(origin => {
    return dispatch(createRoute(origin, system))
    .then(route => dispatch(saveRoute(route)))
  })

  return Promise.all(favoriteRoutes)
}

const createRoute = (origin, destination) => (dispatch, getState, {api}) => {
  const alreadyExists = getState().gps.routes.find(r => {
    return r.origin.id === origin.id
    && r.destination.id === destination.id
  })

  if ( alreadyExists ) return Promise.resolve(alreadyExists)

  return Promise.all([
    api.gps.shortest(origin, destination),
    api.gps.safest(origin, destination)
  ])
  .then(([shortest, safest]) => ({shortest, safest}))
}

const createFavoriteRoutes = origin => (dispatch, getState, {api}) => {
  const { favorites, routes } = getState().gps
  const favoriteRoutes = favorites
  .filter(destination => origin.id !== destination.id )
  .filter(destination => !routes.some(matchRoute(origin, destination)))
  .map(destination => dispatch(createRoute(origin, destination)))

  return Promise.all(favoriteRoutes)
}

export const createRouteFromPaste = () => (dispatch, getState, {api}) => {
  const { raw } = getState().history.lastPasted
  const { routes } = getState().gps

  if ( raw.length > 25 ) return

  return api.gps.identify(raw)
  .then(origin => {
    return routes.find(byOriginId(origin.id))
    ? Promise.reject('route already exists') // at least, its origin
    : origin
  })
  .then(origin => dispatch(createFavoriteRoutes(origin)))
  .then(routes => {
    return routes
    .filter(route => !!route)
    .map(route => dispatch(saveRoute(route)))
  })
  .catch(err => {
    if ( 'route already exists' !== err ) throw err
    console.warn(err)
    return Promise.resolve()
  })
}

export const searchOrigin = origin => ({ type: GPS_SEARCH, origin })
export const searchDestination = destination => ({ type: GPS_SEARCH, destination })
const gpsBusy = () => ({ type: GPS_BUSY })
const gpsBusyDone = () => ({ type: GPS_BUSY_DONE })

export const search = (origin, destination) => (dispatch, getState, {api}) => {
  if ( origin ) dispatch(searchOrigin(origin))
  if ( destination ) dispatch(searchDestination(destination))
  const { layout } = getState

  dispatch(gpsBusy())

  return Promise.all([
    api.gps.identify(origin),
    api.gps.identify(destination)
  ])
  .then(identified => {
    console.log('search successful, now create route', identified)
    return dispatch(createRoute(identified[0], identified[1])) // TODO create shortest, safest
  })
  .then(route => { // why do I receive the root state here ???
    console.log('created route:', route)

    return dispatch(createFavoriteRoutes(route.shortest[0]))
    .then(fav => [route, ...fav])
    .then(routes => {
      return routes.map(r => dispatch(saveRoute(r)))
    })
  })
  .catch(err => {
    console.warn(err)
    return Promise.resolve()
  })
  .then(() => dispatch(gpsBusyDone()))
}
<commit_msg>disabled searchOrigin and searchDestination dispatches<commit_after>import {
  GPS_BUSY,
  GPS_BUSY_DONE,
  GPS_SEARCH,
  GPS_FAVORITE,
  GPS_FAVORITE_REMOVE,
  CREATE_ROUTE,
  DELETE_ROUTE,
} from './index.js'

export const isWormhole = name => /^J[0-9]{6}$/.test(name)
export const matchRoute = (origin, system) => route => ((route.origin.id === origin.id) && (route.destination.id === system.id))

const byOriginId = id => route => route.origin.id === id

export const deleteFavorite = system => ({
  type: GPS_FAVORITE_REMOVE,
  system
})

export const deleteRoute = (origin, destination) => ({
  type: DELETE_ROUTE,
  origin,
  destination
})

export const saveRoute = systems => ({
  type: CREATE_ROUTE,
  systems
})

export const addFavorite = system => (dispatch, getState, {api}) => {
  dispatch({ type: GPS_FAVORITE, system })

  const { gps, history } = getState()
  const favoriteRoutes = history.origins
  .filter(origin => origin.id !== system.id)
  .filter(origin => !gps.routes.some(matchRoute(origin, system)))
  .map(origin => {
    return dispatch(createRoute(origin, system))
    .then(route => dispatch(saveRoute(route)))
  })

  return Promise.all(favoriteRoutes)
}

const createRoute = (origin, destination) => (dispatch, getState, {api}) => {
  const alreadyExists = getState().gps.routes.find(r => {
    return r.origin.id === origin.id
    && r.destination.id === destination.id
  })

  if ( alreadyExists ) return Promise.resolve(alreadyExists)

  return Promise.all([
    api.gps.shortest(origin, destination),
    api.gps.safest(origin, destination)
  ])
  .then(([shortest, safest]) => ({shortest, safest}))
}

const createFavoriteRoutes = origin => (dispatch, getState, {api}) => {
  const { favorites, routes } = getState().gps
  const favoriteRoutes = favorites
  .filter(destination => origin.id !== destination.id )
  .filter(destination => !routes.some(matchRoute(origin, destination)))
  .map(destination => dispatch(createRoute(origin, destination)))

  return Promise.all(favoriteRoutes)
  .then(routes => routes.filter(route => !!route))
}

export const createRouteFromPaste = () => (dispatch, getState, {api}) => {
  const { raw } = getState().history.lastPasted
  const { routes } = getState().gps

  if ( raw.length > 25 ) return

  return api.gps.identify(raw)
  .then(origin => {
    return routes.find(byOriginId(origin.id))
    ? Promise.reject('route already exists') // at least, its origin.
    : origin
  })
  .then(origin => dispatch(createFavoriteRoutes(origin)))
  .then(routes => {
    return routes.map(route => dispatch(saveRoute(route)))
  })
  .catch(err => {
    if ( 'route already exists' !== err ) throw err
    console.warn(err)
    return Promise.resolve()
  })
}

export const searchOrigin = origin => ({ type: GPS_SEARCH, origin })
export const searchDestination = destination => ({ type: GPS_SEARCH, destination })
const gpsBusy = () => ({ type: GPS_BUSY })
const gpsBusyDone = () => ({ type: GPS_BUSY_DONE })

export const search = (origin, destination) => (dispatch, getState, {api}) => {
  //if ( origin ) dispatch(searchOrigin(origin))
  //if ( destination ) dispatch(searchDestination(destination))
  const { layout } = getState

  dispatch(gpsBusy())

  return Promise.all([
    api.gps.identify(origin),
    api.gps.identify(destination)
  ])
  .then(([origin, destination]) => {
    console.log('search successful, now create route', [origin, destination])
    return dispatch(createRoute(origin, destination))
  })
  .then(route => {
    console.log('created route:', route)

    return dispatch(createFavoriteRoutes(route.shortest[0]))
    .then(fav => [route, ...fav])
    .then(routes => {
      return routes.map(r => dispatch(saveRoute(r)))
    })
  })
  .catch(err => {
    console.warn(err)
    return Promise.resolve()
  })
  .then(() => dispatch(gpsBusyDone()))
}
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2017 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

/* eslint-disable max-len */
/* global getParamsFromSelectors:false, inlineAjaxForm:false, updateHtml:false */

(function(global) {
    'use strict';

    $(document).ready(function() {
        setupActionLinks();
        setupAjaxForms();
        setupConfirmPopup();
        setupMathJax();
        setupSelectAllNone();
        setupAnchorLinks();
        setupToggleLinks();
    });

    global.getParamsFromSelectors = function getParamsFromSelectors() {
        var fieldParams = {};
        _.each(arguments, function(selector) {
            $(selector).each(function() {
                if (!(this.name in fieldParams)) {
                    fieldParams[this.name] = [];
                }
                fieldParams[this.name].push($(this).val());
            });
        });
        return fieldParams;
    };

    global.getFormParams = function getFormParams($form) {
        return getParamsFromSelectors($form.find('input[type=text]:not(:disabled), input[type=hidden]:not(:disabled), \
                                                  input:checked:not(:disabled), textarea:not(:disabled), \
                                                  select:not(:disabled)'));
    };

    function setupSelectAllNone() {
        $('body').on('click', '[data-select-all]', function() {
            var selector = $(this).data('select-all');
            $(selector).filter(':not(:checked)').prop('checked', true).trigger('change');
        });

        $('body').on('click', '[data-select-none]', function() {
            var selector = $(this).data('select-none');
            $(selector).filter(':checked').prop('checked', false).trigger('change');
        });
    }

    function setupConfirmPopup() {
        $('body').on('click', '[data-confirm]:not(button[data-href]):not(input:button[data-href]):not(a[data-method][data-href]):not(a[data-ajax-dialog][data-href])', function() {
            var $this = $(this);

            function performAction() {
                var evt = $.Event('indico:confirmed');
                $this.trigger(evt);

                // Handle custom code
                if (evt.isDefaultPrevented()) {
                    return;
                }

                if ($this.is('form')) {
                    $this.submit();
                } else {
                    window.location = $this.attr('href');
                }
            }

            var evtBefore = $.Event('indico:beforeConfirmed');
            $this.trigger(evtBefore);

            if (evtBefore.isDefaultPrevented()) {
                performAction();
            } else {
                confirmPrompt($(this).data('confirm'), $(this).data('title')).then(performAction);
            }

            return false;
        });
    }

    function setupActionLinks() {
        var selectors = [
            'button[data-href][data-method]', 'input:button[data-href][data-method]', 'a[data-href][data-method]',
            'button[data-href][data-ajax-dialog]', 'input:button[data-href][data-ajax-dialog]', 'a[data-href][data-ajax-dialog]',
            'button[data-content][data-ajax-dialog]', 'input:button[data-content][data-ajax-dialog]', 'a[data-content][data-ajax-dialog]'
        ];
        $('body').on('click', selectors.join(', '), function(e) {
            e.preventDefault();
            var $this = $(this);
            if ($this.hasClass('disabled')) {
                return;
            }
            var url = $this.data('href');
            var method = ($this.data('method') || 'GET').toUpperCase();
            var params = $this.data('params') || {};
            var paramsSelector = $this.data('params-selector');
            var update = $this.data('update');
            var ajax = $this.data('ajax') !== undefined;
            var replaceUpdate = $this.data('replace-update') !== undefined;
            var highlightUpdate = $this.data('highlight-update') !== undefined;
            var dialog = $this.data('ajax-dialog') !== undefined;
            var reload = $this.data('reload-after');
            var redirect = $this.data('redirect-after');
            var content = $this.data('content');

            if (!$.isPlainObject(params)) {
                throw new Error('Invalid params. Must be valid JSON if set.');
            }

            if (paramsSelector) {
                params = $.extend({}, getParamsFromSelectors(paramsSelector), params);
            }

            function execute() {
                var evt = $.Event('indico:confirmed');
                $this.trigger(evt);

                // Handle custom code
                if (evt.isDefaultPrevented()) {
                    return;
                }

                // Handle AJAX dialog
                if (dialog) {
                    var closeButton = $this.data('close-button');
                    ajaxDialog({
                        trigger: $this,
                        url: url,
                        method: method,
                        data: params,
                        content: $(content).html(),
                        title: $this.data('title'),
                        subtitle: $this.data('subtitle'),
                        closeButton: closeButton === undefined ? false : (closeButton || true),
                        dialogClasses: $this.data('dialog-classes'),
                        hidePageHeader: $this.data('hide-page-header') !== undefined,
                        confirmCloseUnsaved: $this.data('confirm-close-unsaved') !== undefined,
                        onClose: function(data, customData) {
                            if (data) {
                                handleFlashes(data, true, $this);
                                if (update) {
                                    updateHtml(update, data, replaceUpdate, highlightUpdate);
                                } else if (reload !== undefined && reload !== 'customData') {
                                    IndicoUI.Dialogs.Util.progress();
                                    location.reload();
                                } else if (redirect !== undefined) {
                                    IndicoUI.Dialogs.Util.progress();
                                    location.href = redirect;
                                }
                            } else if (reload === 'customData' && customData) {
                                IndicoUI.Dialogs.Util.progress();
                                location.reload();
                            }
                        }
                    });
                    return;
                }

                // Handle html update or reload
                if (ajax || update || reload !== undefined || redirect !== undefined) {
                    $.ajax({
                        method: method,
                        url: url,
                        data: params,
                        error: handleAjaxError,
                        complete: IndicoUI.Dialogs.Util.progress(),
                        success: function(data) {
                            var successEvt = $.Event('declarative:success');
                            $this.trigger(successEvt, [data]);
                            if (successEvt.isDefaultPrevented()) {
                                return;
                            }
                            if (update) {
                                handleFlashes(data, true, $this);
                                updateHtml(update, data, replaceUpdate, highlightUpdate);
                            } else if (reload !== undefined) {
                                IndicoUI.Dialogs.Util.progress();
                                location.reload();
                            } else if (redirect !== undefined) {
                                IndicoUI.Dialogs.Util.progress();
                                location.href = redirect;
                            } else if (data.redirect) {
                                IndicoUI.Dialogs.Util.progress();
                                location.href = data.redirect;
                            }
                        }
                    });
                    return;
                }

                // Handle normal GET/POST
                if (method === 'GET') {
                    location.href = build_url(url, params);
                } else if (method === 'POST') {
                    var form = $('<form>', {
                        action: url,
                        method: method
                    });
                    form.append($('<input>', {type: 'hidden', name: 'csrf_token', value: $('#csrf-token').attr('content')}));
                    $.each(params, function(key, value) {
                        form.append($('<input>', {type: 'hidden', name: key, value: value}));
                    });
                    form.appendTo('body').submit();
                }
            }

            var promptMsg = $this.data('confirm');
            var confirmed;
            if (!promptMsg) {
                confirmed = $.Deferred().resolve();
            } else {
                confirmed = confirmPrompt(promptMsg, $(this).data('title') || $T('Confirm action'));
            }
            confirmed.then(execute);
        });
    }

    function setupAjaxForms() {
        function _getOptions($elem, extra) {
            var updateOpts = $elem.data('update');
            return $.extend({
                context: $elem,
                formContainer: $elem.data('form-container'),
                confirmCloseUnsaved: $elem.data('confirm-close-unsaved') !== undefined,
                update: updateOpts ? {
                    element: $elem.data('update'),
                    replace: $elem.data('replace-update') !== undefined,
                    highlight: $elem.data('highlight-update') !== undefined
                } : null
            }, extra);
        }

        function _handleClick(evt) {
            evt.preventDefault();
            var $this = $(this);
            if ($this.hasClass('disabled')) {
                return;
            }

            inlineAjaxForm(_getOptions($this, {
                load: {
                    url: $this.data('href')
                },
                scrollToForm: $this.data('scroll-to-form') !== undefined
            }));

            function toggleDisabled(disabled) {
                if ($this.data('hide-trigger') !== undefined) {
                    $this.toggle(!disabled);
                }
                if ($this.is('a')) {
                    $this.toggleClass('disabled', disabled);
                } else {
                    $this.prop('disabled', disabled);
                }
            }

            $this.on('ajaxForm:show', function() {
                toggleDisabled(true);
            }).on('ajaxForm:hide', function() {
                toggleDisabled(false);
            });
        }

        function _handleHtmlUpdate($elem) {
            $elem.find('form[data-ajax-form]').each(function() {
                var $this = $(this);
                inlineAjaxForm(_getOptions($this, {
                    load: null,
                    initiallyHidden: $this.data('initially-hidden') !== undefined
                }));
            });
        }

        $('body').on('click', 'button[data-ajax-form], a[data-ajax-form]', _handleClick);
        $('body').on('indico:htmlUpdated', function(evt) {
            _handleHtmlUpdate($(evt.target));
        });
        _handleHtmlUpdate($('body'));
    }

    function setupMathJax() {
        var $elems = $('.js-mathjax');
        if ($elems.length) {
            $elems.mathJax();
        }
    }

    function setupAnchorLinks() {
        $('[data-anchor]').each(function() {
            var $elem = $(this);
            var fragment = $elem.data('anchor');
            $('<a>', {
                class: 'anchor-link',
                href: '#' + fragment,
                title: $T.gettext('Direct link to this item')
            }).html('¶').appendTo($elem);
        });
    }

    function setupToggleLinks() {
        $('body').on('click', '[data-toggle]:not([data-toggle=dropdown])', function(evt) {
            evt.preventDefault();
            var $elem = $(this);
            var accordion = $elem.data('accordion');
            var toggleClass = $elem.data('toggle-class');
            var isVisible = $elem.hasClass('js-details-visible');

            function toggleDetails($trigger) {
                var $target = $($trigger.data('toggle'));
                var wasVisible = $trigger.hasClass('js-details-visible');
                $target.slideToggle('fast');
                $trigger.toggleClass('js-details-visible');
                if (toggleClass) {
                    $(toggleClass.target).toggleClass(toggleClass.class);
                }
                $trigger.text(wasVisible ? $trigger.data('show-text') : $trigger.data('hide-text'));
            }

            if (!isVisible && accordion !== undefined) {
                $(accordion).find('.js-details-visible').each(function() {
                    toggleDetails($(this));
                });
            }

            toggleDetails($elem);
        });
    }
})(window);
<commit_msg>Hide qtip on ajax-form trigger<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2017 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

/* eslint-disable max-len */
/* global getParamsFromSelectors:false, inlineAjaxForm:false, updateHtml:false */

(function(global) {
    'use strict';

    $(document).ready(function() {
        setupActionLinks();
        setupAjaxForms();
        setupConfirmPopup();
        setupMathJax();
        setupSelectAllNone();
        setupAnchorLinks();
        setupToggleLinks();
    });

    global.getParamsFromSelectors = function getParamsFromSelectors() {
        var fieldParams = {};
        _.each(arguments, function(selector) {
            $(selector).each(function() {
                if (!(this.name in fieldParams)) {
                    fieldParams[this.name] = [];
                }
                fieldParams[this.name].push($(this).val());
            });
        });
        return fieldParams;
    };

    global.getFormParams = function getFormParams($form) {
        return getParamsFromSelectors($form.find('input[type=text]:not(:disabled), input[type=hidden]:not(:disabled), \
                                                  input:checked:not(:disabled), textarea:not(:disabled), \
                                                  select:not(:disabled)'));
    };

    function setupSelectAllNone() {
        $('body').on('click', '[data-select-all]', function() {
            var selector = $(this).data('select-all');
            $(selector).filter(':not(:checked)').prop('checked', true).trigger('change');
        });

        $('body').on('click', '[data-select-none]', function() {
            var selector = $(this).data('select-none');
            $(selector).filter(':checked').prop('checked', false).trigger('change');
        });
    }

    function setupConfirmPopup() {
        $('body').on('click', '[data-confirm]:not(button[data-href]):not(input:button[data-href]):not(a[data-method][data-href]):not(a[data-ajax-dialog][data-href])', function() {
            var $this = $(this);

            function performAction() {
                var evt = $.Event('indico:confirmed');
                $this.trigger(evt);

                // Handle custom code
                if (evt.isDefaultPrevented()) {
                    return;
                }

                if ($this.is('form')) {
                    $this.submit();
                } else {
                    window.location = $this.attr('href');
                }
            }

            var evtBefore = $.Event('indico:beforeConfirmed');
            $this.trigger(evtBefore);

            if (evtBefore.isDefaultPrevented()) {
                performAction();
            } else {
                confirmPrompt($(this).data('confirm'), $(this).data('title')).then(performAction);
            }

            return false;
        });
    }

    function setupActionLinks() {
        var selectors = [
            'button[data-href][data-method]', 'input:button[data-href][data-method]', 'a[data-href][data-method]',
            'button[data-href][data-ajax-dialog]', 'input:button[data-href][data-ajax-dialog]', 'a[data-href][data-ajax-dialog]',
            'button[data-content][data-ajax-dialog]', 'input:button[data-content][data-ajax-dialog]', 'a[data-content][data-ajax-dialog]'
        ];
        $('body').on('click', selectors.join(', '), function(e) {
            e.preventDefault();
            var $this = $(this);
            if ($this.hasClass('disabled')) {
                return;
            }
            var url = $this.data('href');
            var method = ($this.data('method') || 'GET').toUpperCase();
            var params = $this.data('params') || {};
            var paramsSelector = $this.data('params-selector');
            var update = $this.data('update');
            var ajax = $this.data('ajax') !== undefined;
            var replaceUpdate = $this.data('replace-update') !== undefined;
            var highlightUpdate = $this.data('highlight-update') !== undefined;
            var dialog = $this.data('ajax-dialog') !== undefined;
            var reload = $this.data('reload-after');
            var redirect = $this.data('redirect-after');
            var content = $this.data('content');

            if (!$.isPlainObject(params)) {
                throw new Error('Invalid params. Must be valid JSON if set.');
            }

            if (paramsSelector) {
                params = $.extend({}, getParamsFromSelectors(paramsSelector), params);
            }

            function execute() {
                var evt = $.Event('indico:confirmed');
                $this.trigger(evt);

                // Handle custom code
                if (evt.isDefaultPrevented()) {
                    return;
                }

                // Handle AJAX dialog
                if (dialog) {
                    var closeButton = $this.data('close-button');
                    ajaxDialog({
                        trigger: $this,
                        url: url,
                        method: method,
                        data: params,
                        content: $(content).html(),
                        title: $this.data('title'),
                        subtitle: $this.data('subtitle'),
                        closeButton: closeButton === undefined ? false : (closeButton || true),
                        dialogClasses: $this.data('dialog-classes'),
                        hidePageHeader: $this.data('hide-page-header') !== undefined,
                        confirmCloseUnsaved: $this.data('confirm-close-unsaved') !== undefined,
                        onClose: function(data, customData) {
                            if (data) {
                                handleFlashes(data, true, $this);
                                if (update) {
                                    updateHtml(update, data, replaceUpdate, highlightUpdate);
                                } else if (reload !== undefined && reload !== 'customData') {
                                    IndicoUI.Dialogs.Util.progress();
                                    location.reload();
                                } else if (redirect !== undefined) {
                                    IndicoUI.Dialogs.Util.progress();
                                    location.href = redirect;
                                }
                            } else if (reload === 'customData' && customData) {
                                IndicoUI.Dialogs.Util.progress();
                                location.reload();
                            }
                        }
                    });
                    return;
                }

                // Handle html update or reload
                if (ajax || update || reload !== undefined || redirect !== undefined) {
                    $.ajax({
                        method: method,
                        url: url,
                        data: params,
                        error: handleAjaxError,
                        complete: IndicoUI.Dialogs.Util.progress(),
                        success: function(data) {
                            var successEvt = $.Event('declarative:success');
                            $this.trigger(successEvt, [data]);
                            if (successEvt.isDefaultPrevented()) {
                                return;
                            }
                            if (update) {
                                handleFlashes(data, true, $this);
                                updateHtml(update, data, replaceUpdate, highlightUpdate);
                            } else if (reload !== undefined) {
                                IndicoUI.Dialogs.Util.progress();
                                location.reload();
                            } else if (redirect !== undefined) {
                                IndicoUI.Dialogs.Util.progress();
                                location.href = redirect;
                            } else if (data.redirect) {
                                IndicoUI.Dialogs.Util.progress();
                                location.href = data.redirect;
                            }
                        }
                    });
                    return;
                }

                // Handle normal GET/POST
                if (method === 'GET') {
                    location.href = build_url(url, params);
                } else if (method === 'POST') {
                    var form = $('<form>', {
                        action: url,
                        method: method
                    });
                    form.append($('<input>', {type: 'hidden', name: 'csrf_token', value: $('#csrf-token').attr('content')}));
                    $.each(params, function(key, value) {
                        form.append($('<input>', {type: 'hidden', name: key, value: value}));
                    });
                    form.appendTo('body').submit();
                }
            }

            var promptMsg = $this.data('confirm');
            var confirmed;
            if (!promptMsg) {
                confirmed = $.Deferred().resolve();
            } else {
                confirmed = confirmPrompt(promptMsg, $(this).data('title') || $T('Confirm action'));
            }
            confirmed.then(execute);
        });
    }

    function setupAjaxForms() {
        function _getOptions($elem, extra) {
            var updateOpts = $elem.data('update');
            return $.extend({
                context: $elem,
                formContainer: $elem.data('form-container'),
                confirmCloseUnsaved: $elem.data('confirm-close-unsaved') !== undefined,
                update: updateOpts ? {
                    element: $elem.data('update'),
                    replace: $elem.data('replace-update') !== undefined,
                    highlight: $elem.data('highlight-update') !== undefined
                } : null
            }, extra);
        }

        function _handleClick(evt) {
            evt.preventDefault();
            var $this = $(this);
            if ($this.hasClass('disabled')) {
                return;
            }

            inlineAjaxForm(_getOptions($this, {
                load: {
                    url: $this.data('href')
                },
                scrollToForm: $this.data('scroll-to-form') !== undefined
            }));

            function toggleDisabled(disabled) {
                if ($this.data('hide-trigger') !== undefined) {
                    $this.toggle(!disabled);
                }
                if ($this.is('a')) {
                    $this.toggleClass('disabled', disabled);
                } else {
                    $this.prop('disabled', disabled);
                }

                if (disabled) {
                    $this.trigger('indico:closeAutoTooltip');
                }
            }

            $this.on('ajaxForm:show', function() {
                toggleDisabled(true);
            }).on('ajaxForm:hide', function() {
                toggleDisabled(false);
            });
        }

        function _handleHtmlUpdate($elem) {
            $elem.find('form[data-ajax-form]').each(function() {
                var $this = $(this);
                inlineAjaxForm(_getOptions($this, {
                    load: null,
                    initiallyHidden: $this.data('initially-hidden') !== undefined
                }));
            });
        }

        $('body').on('click', 'button[data-ajax-form], a[data-ajax-form]', _handleClick);
        $('body').on('indico:htmlUpdated', function(evt) {
            _handleHtmlUpdate($(evt.target));
        });
        _handleHtmlUpdate($('body'));
    }

    function setupMathJax() {
        var $elems = $('.js-mathjax');
        if ($elems.length) {
            $elems.mathJax();
        }
    }

    function setupAnchorLinks() {
        $('[data-anchor]').each(function() {
            var $elem = $(this);
            var fragment = $elem.data('anchor');
            $('<a>', {
                class: 'anchor-link',
                href: '#' + fragment,
                title: $T.gettext('Direct link to this item')
            }).html('¶').appendTo($elem);
        });
    }

    function setupToggleLinks() {
        $('body').on('click', '[data-toggle]:not([data-toggle=dropdown])', function(evt) {
            evt.preventDefault();
            var $elem = $(this);
            var accordion = $elem.data('accordion');
            var toggleClass = $elem.data('toggle-class');
            var isVisible = $elem.hasClass('js-details-visible');

            function toggleDetails($trigger) {
                var $target = $($trigger.data('toggle'));
                var wasVisible = $trigger.hasClass('js-details-visible');
                $target.slideToggle('fast');
                $trigger.toggleClass('js-details-visible');
                if (toggleClass) {
                    $(toggleClass.target).toggleClass(toggleClass.class);
                }
                $trigger.text(wasVisible ? $trigger.data('show-text') : $trigger.data('hide-text'));
            }

            if (!isVisible && accordion !== undefined) {
                $(accordion).find('.js-details-visible').each(function() {
                    toggleDetails($(this));
                });
            }

            toggleDetails($elem);
        });
    }
})(window);
<|endoftext|>