<commit_before>var authors = [],
	list = $( "#status-list" ),
	validEmailRexex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
	claAddress = "https://spreadsheets.google.com/feeds/list/0Aj5JJFjq9rZDdFJucXdGZXlRdVh2SUVUb2hsb0FBYkE/1/public/values?alt=json-in-script&sq=emailaddress%3D",
	caaAddress = "https://spreadsheets.google.com/feeds/list/0AgyHrN8YnS0IdDdvWkJRaHFoQmRuazFhUm8zckViMHc/1/public/values?alt=json-in-script&sq=emailaddress%3D";

asyncTest( "Fetched .patch file", function(){
	expect( 1 );
	chrome.tabs.getSelected( null, function( tab ) {
		var url = tab.url.replace( /\/files$|\/commits$/, "" ),
			record = false;
		$.get( url + ".patch", function( data ) {
			var authorLine = "";
			$.each( data.split( "\n" ), function( i, val ){
				if( /^From:/.test( val ) ){
					authorLine = val;
					record = true;
				} else  if( record === true && /^\s/.test( val ) ) {
					authorLine += val;
				} else if( record === true ) {
					var author = {},
						parts = authorLine.split( " " ),
						length = parts.length;

					author.email = parts[ length -1 ].replace( /<|>/g, "" );
					parts.splice( 0, 1 );
					parts.splice( length - 2, 1);
					if( /UTF-8/.test( parts.join( " " ) ) ){
						author.name = decodeURIComponent(parts.join( " " ).slice(10, -2).replace(/=/g, '%')).normalize( "NFC" );
					} else {
						author.name = parts.join( " " );
					}
					authors.push( author );
					record = false;
				}
			});
			if( authors.length > 0 ){
				ok( true, authors.length + " Authors Found" );
				start();
				checkAuthors();
				if( localStorage[ "checkCommit" ] === "true" || localStorage[ "checkCommit" ] === undefined ) {
					checkCommits( data );
				}
				if( localStorage[ "checkLines" ] === "true" || localStorage[ "checkCommit" ] === undefined ) {
					checkLineLength( data );
				}
			}
		});
	});
});

function validEmail ( email ) {
	return validEmailRexex.test( email );
}
function validName ( name, entrys, caa ) {
	var length = name.split( " " ).length,
		returnValue = true;

	if( length <= 1 ){
		if( entrys ) {
			$.each( entrys, function( index , entry ) {
				if( !caa && entry.gsx$nameconfirmation.$t === "" ) {
					returnValue = false;
				}
			});
		} else {
			returnValue = false;
		}
	}

	return returnValue;
}
function fetchSpreadsheet( author, url, caa, found, claData ) {
	$.ajax({
		url: url + "%22" + encodeURIComponent( author.email ) + "%22",
		success: function( data ) {
			if( data.feed.entry !== undefined ) {
				if( checkName( author, data.feed.entry ) ){
					ok( validName( author.name, data.feed.entry ), "Name length valid or confimed" );
					ok( checkConfirmation( data.feed.entry ), "Confirmed signing" );
					ok( true, "Name matches");
					start();
				} else if( !caa ) {
					fetchSpreadsheet( author, caaAddress, true, true, data );
				} else {
					ok( validName( author.name, data.feed.entry, caa ), "Name length valid or confimed" );
					ok( checkConfirmation( data.feed.entry ), "Confirmed signing" );
					ok( false, "Name does not match " + author.name + " != " +
						data.feed.entry[0].gsx$fullname.$t );
					start();
				}
			} else if( !caa ) {
				fetchSpreadsheet( author, caaAddress, true );
			} else if( found ) {
				ok( validName( author.name, claData.feed.entry ), "Name is at least 2 parts ( " + author.name + " )" );
				ok( checkConfirmation( claData.feed.entry ), "Confirmed signing" );
				ok( false, "Name does not match " + author.name + " != " +
					claData.feed.entry[0].gsx$fullname.$t );
				start();
			} else {
				ok( validName( author.name ), "Name is at least 2 parts ( " + author.name + " )" );
				ok( false, "Confirmed signing" );
				ok( false, "Email not found in sheet" );
				start();
			}
		},
		error: function(){
			ok( false, "Confirmed signing" );
			ok( validName( author.name ), "Name is at least 2 parts ( " + author.name + " )" );
			ok( false, "Error fetching sheet" );
			start();
		},
		dataType: "JSONP"
	});
}
function checkName ( author, sheet ) {
	var match = false;
	$.each( sheet, function( index, val ){
		if( val.gsx$fullname.$t.normalize( "NFC" ) === author.name ) {
			match = true;
			return;
		}
	});
	return match;
}
function checkConfirmation ( sheet ) {
	$.each( sheet, function( index, val ){
		if( val.gsx$confirmation.$t === "I AGREE" ) {
			match = true;
			return;
		}
	});
	return match;
}
function checkAuthors() {
	$.each( authors, function( index, author ){
		asyncTest( "Commit " + ( index + 1 ) + " " + author.name + " <" + author.email + ">", function(){
			ok( validEmail( author.email ), "Email is Valid  ( " + author.email + " )" );
			if ( validEmail( author.email ) ) {
				expect( 4 );
				fetchSpreadsheet( author, claAddress );
			} else {
				ok( false, "Name is at least 2 parts ( " + author.name + " )" );
				expect( 2 );
				start();
			}
		});
	});
}
function getCommitMessages( patch ){
	var record = false,
		commits = [],
		captureSecond = false,
		commit;

	$.each( patch.split( "\n" ), function( index, line ){
		if( /^Subject\:/.test( line ) ){
			if ( line.length >= 70 ) {
				captureSecond = true;
			}
			commit = line;
			record = true;
		} else if( captureSecond && /^\s/.test( line ) && record && !/^---/.test( line ) ) {
			commit += line;
			captureSecond = false;
		} else if( record && !/^---/.test( line ) ) {
			captureSecond = false;
			commit += "\n" + line;
		} else if( record && /^---/.test( line ) ) {
			record = false;
			captureSecond = false;
			commits.push( commit.replace( /Subject\:\s/, "" ).replace(/\[PATCH([0-9\/\s])*\](\s)*/, "") );
		}
	});
	return commits;
}
function getCommitLines( patch ){
	var commitName,
		record = false,
		files = {};
	$.each( patch.split( "\n" ), function( index, line ){
		if( /^\+\+\+/.test( line ) && !/(\.js)$/.test( line ) ){
			record = false;
		} else if( /^\+\+\+/.test( line ) && /(\.js)$/.test( line ) ) {
			record = true;
			fileName = line.replace( /^\+\+\+ b/, "" );
			if( files[ fileName ] === undefined ) {
				files[ fileName ] = [];
			}
		} else if( /^\+\s/.test( line ) && record ) {
			files[ fileName ].push( line.replace(/^\+/, "" ) );
		}
	});
	return files;
}
function checkCommitMessage( message ) {

	// Thanks to Jörn Zaefferer and commitPlease for this commmit message check
	var errors = [];

	message.split(/\n/).forEach(function ( line, index ) {
		// skip comments
		if ( /^#/.test( line ) ) {
			return;
		}
		if ( index === 0 ) {
			// allow tag commits
			if ( line.length > 72 ) {
				errors.push( "First line (subject) must be no longer than " +
					72 + " characters" );
			}

			if ( line.indexOf( ":" ) < 1 ) {
				errors.push( "First line (subject) must indicate the component" );
			}

			if ( line.substring( line.indexOf( ":" ) + 1 ).length < 1 ) {
				errors.push( "First line (subject) must have a message after the component" );
			}
		}
		if ( index === 1 && line.length > 0 ) {
			errors.push( "Second line must always be empty" );
		}
		if ( index > 1 && line.length > 80 ) {
			errors.push( "Commit message line " + ( index + 1 ) + " too long: " +
				line.length + " characters, only " + 80 +
				" allowed. Was: " + line.substring( 0, 20 ) + "[...]" );
		}
		// ticket references
		if ( /^(clos|fix|resolv)(e[sd]|ing)/i.test( line ) ) {
			if ( !/^(Fixes|Closes)\s+[^\s\d]+(\s|$)/.test( line ) &&
					!/^(Fixes|Closes) (.*#|gh-)[0-9]+/.test( line ) ) {
				errors.push( "Invalid ticket reference, must be " +
					"/(Fixes|Closes) (.*#|gh-)[0-9]+/, was: " + line );
			}
		}
	});

	return errors;
}
function checkCommits( patch ) {
	var commits = getCommitMessages( patch );
	$.each( commits, function( index, commit ){
		test( "Commit " + ( index + 1 ) + " message meet guidlines", function(){
			var errors = checkCommitMessage( commit );

			if( errors.length > 0 ){
				$.each( errors, function( i, error ){
					ok( false, error );
				});
			} else {
				ok( true, "Commit message valid" );
			}
		});
	});
}
function checkLineLength( patch ) {
	var files = getCommitLines( patch );

	if( Object.keys( files ).length > 0 ) {
		$.each( files, function( fileName, lines ){
			test( "file " + fileName + " lines less then 100 characters", function(){
				console.log( lines );
				if( lines.length > 0 ){
					$.each( lines, function( i, line ){
						var tabCount = line.match( /\t/g ).length,
							length;
						length = line.length + ( tabCount * 3 );
						ok( length < 100, line );
					});
				} else {
					ok( true, "blank line" );
				}
			});
		});
	}
}
<commit_msg>Make sure it works from any valid pr link including comments, diffs, and patchs<commit_after>var authors = [],
	list = $( "#status-list" ),
	validEmailRexex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
	claAddress = "https://spreadsheets.google.com/feeds/list/0Aj5JJFjq9rZDdFJucXdGZXlRdVh2SUVUb2hsb0FBYkE/1/public/values?alt=json-in-script&sq=emailaddress%3D",
	caaAddress = "https://spreadsheets.google.com/feeds/list/0AgyHrN8YnS0IdDdvWkJRaHFoQmRuazFhUm8zckViMHc/1/public/values?alt=json-in-script&sq=emailaddress%3D";

asyncTest( "Fetched .patch file", function(){
	expect( 1 );
	chrome.tabs.getSelected( null, function( tab ) {
		var url = tab.url.match(/https:\/\/github\.com\/jquery\/[^\/]+\/pull\/\d+/),
			record = false;

		$.get( url + ".patch", function( data ) {
			var authorLine = "";
			$.each( data.split( "\n" ), function( i, val ){
				if( /^From:/.test( val ) ){
					authorLine = val;
					record = true;
				} else  if( record === true && /^\s/.test( val ) ) {
					authorLine += val;
				} else if( record === true ) {
					var author = {},
						parts = authorLine.split( " " ),
						length = parts.length;

					author.email = parts[ length -1 ].replace( /<|>/g, "" );
					parts.splice( 0, 1 );
					parts.splice( length - 2, 1);
					if( /UTF-8/.test( parts.join( " " ) ) ){
						author.name = decodeURIComponent(parts.join( " " ).slice(10, -2).replace(/=/g, '%')).normalize( "NFC" );
					} else {
						author.name = parts.join( " " );
					}
					authors.push( author );
					record = false;
				}
			});
			if( authors.length > 0 ){
				ok( true, authors.length + " Authors Found" );
				start();
				checkAuthors();
				if( localStorage[ "checkCommit" ] === "true" || localStorage[ "checkCommit" ] === undefined ) {
					checkCommits( data );
				}
				if( localStorage[ "checkLines" ] === "true" || localStorage[ "checkCommit" ] === undefined ) {
					checkLineLength( data );
				}
			}
		});
	});
});

function validEmail ( email ) {
	return validEmailRexex.test( email );
}
function validName ( name, entrys, caa ) {
	var length = name.split( " " ).length,
		returnValue = true;

	if( length <= 1 ){
		if( entrys ) {
			$.each( entrys, function( index , entry ) {
				if( !caa && entry.gsx$nameconfirmation.$t === "" ) {
					returnValue = false;
				}
			});
		} else {
			returnValue = false;
		}
	}

	return returnValue;
}
function fetchSpreadsheet( author, url, caa, found, claData ) {
	$.ajax({
		url: url + "%22" + encodeURIComponent( author.email ) + "%22",
		success: function( data ) {
			if( data.feed.entry !== undefined ) {
				if( checkName( author, data.feed.entry ) ){
					ok( validName( author.name, data.feed.entry ), "Name length valid or confimed" );
					ok( checkConfirmation( data.feed.entry ), "Confirmed signing" );
					ok( true, "Name matches");
					start();
				} else if( !caa ) {
					fetchSpreadsheet( author, caaAddress, true, true, data );
				} else {
					ok( validName( author.name, data.feed.entry, caa ), "Name length valid or confimed" );
					ok( checkConfirmation( data.feed.entry ), "Confirmed signing" );
					ok( false, "Name does not match " + author.name + " != " +
						data.feed.entry[0].gsx$fullname.$t );
					start();
				}
			} else if( !caa ) {
				fetchSpreadsheet( author, caaAddress, true );
			} else if( found ) {
				ok( validName( author.name, claData.feed.entry ), "Name is at least 2 parts ( " + author.name + " )" );
				ok( checkConfirmation( claData.feed.entry ), "Confirmed signing" );
				ok( false, "Name does not match " + author.name + " != " +
					claData.feed.entry[0].gsx$fullname.$t );
				start();
			} else {
				ok( validName( author.name ), "Name is at least 2 parts ( " + author.name + " )" );
				ok( false, "Confirmed signing" );
				ok( false, "Email not found in sheet" );
				start();
			}
		},
		error: function(){
			ok( false, "Confirmed signing" );
			ok( validName( author.name ), "Name is at least 2 parts ( " + author.name + " )" );
			ok( false, "Error fetching sheet" );
			start();
		},
		dataType: "JSONP"
	});
}
function checkName ( author, sheet ) {
	var match = false;
	$.each( sheet, function( index, val ){
		if( val.gsx$fullname.$t.normalize( "NFC" ) === author.name ) {
			match = true;
			return;
		}
	});
	return match;
}
function checkConfirmation ( sheet ) {
	$.each( sheet, function( index, val ){
		if( val.gsx$confirmation.$t === "I AGREE" ) {
			match = true;
			return;
		}
	});
	return match;
}
function checkAuthors() {
	$.each( authors, function( index, author ){
		asyncTest( "Commit " + ( index + 1 ) + " " + author.name + " <" + author.email + ">", function(){
			ok( validEmail( author.email ), "Email is Valid  ( " + author.email + " )" );
			if ( validEmail( author.email ) ) {
				expect( 4 );
				fetchSpreadsheet( author, claAddress );
			} else {
				ok( false, "Name is at least 2 parts ( " + author.name + " )" );
				expect( 2 );
				start();
			}
		});
	});
}
function getCommitMessages( patch ){
	var record = false,
		commits = [],
		captureSecond = false,
		commit;

	$.each( patch.split( "\n" ), function( index, line ){
		if( /^Subject\:/.test( line ) ){
			if ( line.length >= 70 ) {
				captureSecond = true;
			}
			commit = line;
			record = true;
		} else if( captureSecond && /^\s/.test( line ) && record && !/^---/.test( line ) ) {
			commit += line;
			captureSecond = false;
		} else if( record && !/^---/.test( line ) ) {
			captureSecond = false;
			commit += "\n" + line;
		} else if( record && /^---/.test( line ) ) {
			record = false;
			captureSecond = false;
			commits.push( commit.replace( /Subject\:\s/, "" ).replace(/\[PATCH([0-9\/\s])*\](\s)*/, "") );
		}
	});
	return commits;
}
function getCommitLines( patch ){
	var commitName,
		record = false,
		files = {};
	$.each( patch.split( "\n" ), function( index, line ){
		if( /^\+\+\+/.test( line ) && !/(\.js)$/.test( line ) ){
			record = false;
		} else if( /^\+\+\+/.test( line ) && /(\.js)$/.test( line ) ) {
			record = true;
			fileName = line.replace( /^\+\+\+ b/, "" );
			if( files[ fileName ] === undefined ) {
				files[ fileName ] = [];
			}
		} else if( /^\+\s/.test( line ) && record ) {
			files[ fileName ].push( line.replace(/^\+/, "" ) );
		}
	});
	return files;
}
function checkCommitMessage( message ) {

	// Thanks to Jörn Zaefferer and commitPlease for this commmit message check
	var errors = [];

	message.split(/\n/).forEach(function ( line, index ) {
		// skip comments
		if ( /^#/.test( line ) ) {
			return;
		}
		if ( index === 0 ) {
			// allow tag commits
			if ( line.length > 72 ) {
				errors.push( "First line (subject) must be no longer than " +
					72 + " characters" );
			}

			if ( line.indexOf( ":" ) < 1 ) {
				errors.push( "First line (subject) must indicate the component" );
			}

			if ( line.substring( line.indexOf( ":" ) + 1 ).length < 1 ) {
				errors.push( "First line (subject) must have a message after the component" );
			}
		}
		if ( index === 1 && line.length > 0 ) {
			errors.push( "Second line must always be empty" );
		}
		if ( index > 1 && line.length > 80 ) {
			errors.push( "Commit message line " + ( index + 1 ) + " too long: " +
				line.length + " characters, only " + 80 +
				" allowed. Was: " + line.substring( 0, 20 ) + "[...]" );
		}
		// ticket references
		if ( /^(clos|fix|resolv)(e[sd]|ing)/i.test( line ) ) {
			if ( !/^(Fixes|Closes)\s+[^\s\d]+(\s|$)/.test( line ) &&
					!/^(Fixes|Closes) (.*#|gh-)[0-9]+/.test( line ) ) {
				errors.push( "Invalid ticket reference, must be " +
					"/(Fixes|Closes) (.*#|gh-)[0-9]+/, was: " + line );
			}
		}
	});

	return errors;
}
function checkCommits( patch ) {
	var commits = getCommitMessages( patch );
	$.each( commits, function( index, commit ){
		test( "Commit " + ( index + 1 ) + " message meet guidlines", function(){
			var errors = checkCommitMessage( commit );

			if( errors.length > 0 ){
				$.each( errors, function( i, error ){
					ok( false, error );
				});
			} else {
				ok( true, "Commit message valid" );
			}
		});
	});
}
function checkLineLength( patch ) {
	var files = getCommitLines( patch );

	if( Object.keys( files ).length > 0 ) {
		$.each( files, function( fileName, lines ){
			test( "file " + fileName + " lines less then 100 characters", function(){
				console.log( lines );
				if( lines.length > 0 ){
					$.each( lines, function( i, line ){
						var tabCount = line.match( /\t/g ).length,
							length;
						length = line.length + ( tabCount * 3 );
						ok( length < 100, line );
					});
				} else {
					ok( true, "blank line" );
				}
			});
		});
	}
}
<|endoftext|>


<commit_before>"use strict";

var Config = {
  supportsHistory : !!(window.history && history.pushState),
  inMaintenanceMode : false,

  treeName: 'mozilla-central',
  hgBaseURL: "https://hg.mozilla.org/",
  hgURL: "https://hg.mozilla.org/mozilla-central/",
  hgRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  hgMCURL: "https://hg.mozilla.org/mozilla-central/",
  hgMCRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgMCPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  showBugURL: "https://bugzilla.mozilla.org/show_bug.cgi?id=",
  versionURL: "php/getVersion.php",

  // Here be dragons
  versionRE: /^mozilla\d+$/i,
  csetInputRE: /^(tip|[\da-f]{12,40})$/i,
  csetIDRE: /\b([\da-f]{12,40})\b/ig,
  leaveOpenRE: /leave(?:-|\s+)open/i,
  bugNumRE: /\b(\d{4,7})\b/g,
  strictBugNumRE: /^(\d{4,7})$/,
  mergeRE: /\bmerg(ed?|ing)\b/i,
  backoutRE: /back(ing|ed)?\s*out/i,
  revertRE: /revert(ing)?/i,
  partialRevertRE: /(?:from|in)(?:\s+(?:rev(?:ision)?|c(?:hange)?set))?\s+([\da-f]{12,40})/i,
  partialTestRE: /test\s+for/i,
  revertRangeRE: /revert(?:ing)?\s+to(?:\s+(?:rev(?:ision)?|c(?:hange)set))?\s+([\da-f]{12,40})/i,
  csetRangeRE: /\b([\da-f]{12,40})\s*(?:to|:|-|through)\s*([\da-f]{12,40})/i,
  hgRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  hgMCRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgMCRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgMCPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  emailRE: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,   // I'm not looking for RFC 822 compliance here!

  // The many ways bug numbers are specified
  bugRE1: /b(?:ug)?=(\d{4,7})\b/i,                       // e.g. b=XXXXXX
  bugRE2: /^fix(?:es)?\s*(?:for\s*)?(\d{4,7})\b/i,                         // Fix is sometimes used as a synonym for bug
  bugRE3: /to\s+fix\s+bug\s+(\d{4,7})/i,
  bugRE4: /\((\d{4,7}), r=/i,                          // e.g. JS-team style (XXXXXX, r=foo)
  bugRE5: /but\s*(\d{4,7})/i,                          // The typo but XXXXXX happens quite often
  bugRE6: /\bb(?:u?g(?:zilla)?)?:?\s*#?(\d{4,7})\b/i,  // The catchall
  bugRE7: /^(\d{4,7})\b/i,                              // e.g. XXXXXX,

  repoMergeRE: "\\s+(&|and|with|<->|<>|-?->|(in|on)?to)\\s+",

  mcSynonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"],

  treeInfo: {
    "mozilla-inbound": {
      repo: "integration/mozilla-inbound",
      synonyms: ["mozilla-inbound", "inbound", "m-i", "mi"]
    },
    "mozilla-aurora": {
      repo: "releases/mozilla-aurora",
      synonyms: ["releases/mozilla-aurora", "mozilla-aurora"]
    },
    "mozilla-beta": {
      repo: "releases/mozilla-beta",
      synonyms: ["releases/mozilla-beta", "mozilla-beta"]
    },
    "mozilla-release": {
      repo: "releases/mozilla-release",
      synonyms: ["releases/mozilla-release", "mozilla-release"]
    },
    "mozilla-esr10": {
      repo: "releases/mozilla-esr10",
      synonyms: ["releases/mozilla-esr10", "mozilla-esr10"]
    },
    "jetpack": {
      repo: "projects/addon-sdk",
      synonyms: ["projects/addon-sdk", "addon-sdk"]
    },
    "build-system": {
      repo: "projects/build-system",
      synonyms: ["build-system", "b-s", "bs"]
    },
    "fx-team": {
      repo: "integration/fx-team",
      synonyms: ["fx-team"],
      additions: "[fixed-in-fx-team]"
    },
    "graphics": {
      repo: "projects/graphics",
      synonyms: ["projects/graphics", "graphics"]
    },
    "ionmonkey": {
      repo: "projects/ionmonkey",
      synonyms: ["projects/ionmonkey", "ionmonkey", "im"]
    },
    "jaegermonkey": {
      repo: "projects/jaegermonkey",
      synonyms: ["projects/jaegermonkey", "jm"]
    },
    "profiling": {
      repo: "projects/profiling",
      synonyms: ["profiling", "projects/profiling"]
    },
    "services-central": {
      repo: "services/services-central",
      synonyms: ["services-central", "s-c", "sc", "services/services-central"],
      additions: "[fixed in services]"
    },
    "ux": {
      repo: "projects/ux",
      synonyms: ["ux", "projects/ux"]
    },
    "alder": {
      repo: "projects/alder",
      synonyms: ["alder", "projects/alder"]
    },
    "ash": {
      repo: "projects/ash",
      synonyms: ["ash", "projects/ash"]
    },
    "birch": {
      repo: "projects/birch",
      synonyms: ["projects/birch", "birch"]
    },
    "cedar": {
      repo: "projects/cedar",
      synonyms: ["projects/cedar", "cedar"]
    },
    "elm": {
      repo: "projects/elm",
      synonyms: ["projects/elm", "elm"]
    },
    "holly": {
      repo: "projects/holly",
      synonyms: ["projects/holly", "holly"]
    },
    "larch": {
      repo: "projects/larch",
      synonyms: ["projects/larch", "larch"]
    },
    "maple": {
      repo: "projects/maple",
      synonyms: ["projects/maple", "maple"]
    },
    "oak": {
      repo: "projects/oak",
      synonyms: ["projects/oak", "oak"]
    },
    "pine": {
      repo: "projects/pine",
      synonyms: ["projects/pine", "pine"]
    },
    "accessibility": {
      repo: "projects/accessibility",
      synonyms: ["projects/accessibility", "accessibility"]
    },
    "devtools": {
      repo: "projects/devtools",
      synonyms: ["projects/devtools", "devtools"]
    },
    "electrolysis": {
      repo: "projects/electrolysis",
      synonyms: ["projects/electrolysis", "electrolysis", "e10s"]
    },
    "places": {
      repo: "projects/places",
      synonyms: ["projects/places", "places"]
    }
  }
};

Config.bugNumberREs = [Config.bugRE1, Config.bugRE2, Config.bugRE3,
                       Config.bugRE4, Config.bugRE5, Config.bugRE6, Config.bugRE7];

(function () {
  var base = Config.hgBaseURL;
  for (var treeName in Config.treeInfo) {
    var repo = Config.treeInfo[treeName].repo;
    Config.treeInfo[treeName]['hgURL'] = base + repo + '/';
    Config.treeInfo[treeName]['hgRevURL'] = base + repo + '/rev/';
    Config.treeInfo[treeName]['hgPushlogURL'] = base + repo + '/pushloghtml?changeset=';
    Config.treeInfo[treeName]['hgRevRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/');
    Config.treeInfo[treeName]['hgRevFullRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/[\\da-f]{12}', 'ig');
    Config.treeInfo[treeName]['hgPushlogRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/pushloghtml\\?changeset=', 'ig');
  }
})();

// Detect input type="email" support
$(document).ready(function() {
  Config.needsValidation = $('#username').prop('type') != 'email';
});
<commit_msg>Tweak "revert to" regular expression for cases where the tree name is specified<commit_after>"use strict";

var Config = {
  supportsHistory : !!(window.history && history.pushState),
  inMaintenanceMode : false,

  treeName: 'mozilla-central',
  hgBaseURL: "https://hg.mozilla.org/",
  hgURL: "https://hg.mozilla.org/mozilla-central/",
  hgRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  hgMCURL: "https://hg.mozilla.org/mozilla-central/",
  hgMCRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgMCPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  showBugURL: "https://bugzilla.mozilla.org/show_bug.cgi?id=",
  versionURL: "php/getVersion.php",

  // Here be dragons
  versionRE: /^mozilla\d+$/i,
  csetInputRE: /^(tip|[\da-f]{12,40})$/i,
  csetIDRE: /\b([\da-f]{12,40})\b/ig,
  leaveOpenRE: /leave(?:-|\s+)open/i,
  bugNumRE: /\b(\d{4,7})\b/g,
  strictBugNumRE: /^(\d{4,7})$/,
  mergeRE: /\bmerg(ed?|ing)\b/i,
  backoutRE: /back(ing|ed)?\s*out/i,
  revertRE: /revert(ing)?/i,
  partialRevertRE: /(?:from|in)(?:\s+(?:rev(?:ision)?|c(?:hange)?set))?\s+([\da-f]{12,40})/i,
  partialTestRE: /test\s+for/i,
  revertRangeRE: /revert(?:ing)?\s+(?:\S+\s+)?to(?:\s+(?:rev(?:ision)?|c(?:hange)set))?\s+([\da-f]{12,40})/i,
  csetRangeRE: /\b([\da-f]{12,40})\s*(?:to|:|-|through)\s*([\da-f]{12,40})/i,
  hgRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  hgMCRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgMCRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgMCPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  emailRE: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,   // I'm not looking for RFC 822 compliance here!

  // The many ways bug numbers are specified
  bugRE1: /b(?:ug)?=(\d{4,7})\b/i,                       // e.g. b=XXXXXX
  bugRE2: /^fix(?:es)?\s*(?:for\s*)?(\d{4,7})\b/i,                         // Fix is sometimes used as a synonym for bug
  bugRE3: /to\s+fix\s+bug\s+(\d{4,7})/i,
  bugRE4: /\((\d{4,7}), r=/i,                          // e.g. JS-team style (XXXXXX, r=foo)
  bugRE5: /but\s*(\d{4,7})/i,                          // The typo but XXXXXX happens quite often
  bugRE6: /\bb(?:u?g(?:zilla)?)?:?\s*#?(\d{4,7})\b/i,  // The catchall
  bugRE7: /^(\d{4,7})\b/i,                              // e.g. XXXXXX,

  repoMergeRE: "\\s+(&|and|with|<->|<>|-?->|(in|on)?to)\\s+",

  mcSynonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"],

  treeInfo: {
    "mozilla-inbound": {
      repo: "integration/mozilla-inbound",
      synonyms: ["mozilla-inbound", "inbound", "m-i", "mi"]
    },
    "mozilla-aurora": {
      repo: "releases/mozilla-aurora",
      synonyms: ["releases/mozilla-aurora", "mozilla-aurora"]
    },
    "mozilla-beta": {
      repo: "releases/mozilla-beta",
      synonyms: ["releases/mozilla-beta", "mozilla-beta"]
    },
    "mozilla-release": {
      repo: "releases/mozilla-release",
      synonyms: ["releases/mozilla-release", "mozilla-release"]
    },
    "mozilla-esr10": {
      repo: "releases/mozilla-esr10",
      synonyms: ["releases/mozilla-esr10", "mozilla-esr10"]
    },
    "jetpack": {
      repo: "projects/addon-sdk",
      synonyms: ["projects/addon-sdk", "addon-sdk"]
    },
    "build-system": {
      repo: "projects/build-system",
      synonyms: ["build-system", "b-s", "bs"]
    },
    "fx-team": {
      repo: "integration/fx-team",
      synonyms: ["fx-team"],
      additions: "[fixed-in-fx-team]"
    },
    "graphics": {
      repo: "projects/graphics",
      synonyms: ["projects/graphics", "graphics"]
    },
    "ionmonkey": {
      repo: "projects/ionmonkey",
      synonyms: ["projects/ionmonkey", "ionmonkey", "im"]
    },
    "jaegermonkey": {
      repo: "projects/jaegermonkey",
      synonyms: ["projects/jaegermonkey", "jm"]
    },
    "profiling": {
      repo: "projects/profiling",
      synonyms: ["profiling", "projects/profiling"]
    },
    "services-central": {
      repo: "services/services-central",
      synonyms: ["services-central", "s-c", "sc", "services/services-central"],
      additions: "[fixed in services]"
    },
    "ux": {
      repo: "projects/ux",
      synonyms: ["ux", "projects/ux"]
    },
    "alder": {
      repo: "projects/alder",
      synonyms: ["alder", "projects/alder"]
    },
    "ash": {
      repo: "projects/ash",
      synonyms: ["ash", "projects/ash"]
    },
    "birch": {
      repo: "projects/birch",
      synonyms: ["projects/birch", "birch"]
    },
    "cedar": {
      repo: "projects/cedar",
      synonyms: ["projects/cedar", "cedar"]
    },
    "elm": {
      repo: "projects/elm",
      synonyms: ["projects/elm", "elm"]
    },
    "holly": {
      repo: "projects/holly",
      synonyms: ["projects/holly", "holly"]
    },
    "larch": {
      repo: "projects/larch",
      synonyms: ["projects/larch", "larch"]
    },
    "maple": {
      repo: "projects/maple",
      synonyms: ["projects/maple", "maple"]
    },
    "oak": {
      repo: "projects/oak",
      synonyms: ["projects/oak", "oak"]
    },
    "pine": {
      repo: "projects/pine",
      synonyms: ["projects/pine", "pine"]
    },
    "accessibility": {
      repo: "projects/accessibility",
      synonyms: ["projects/accessibility", "accessibility"]
    },
    "devtools": {
      repo: "projects/devtools",
      synonyms: ["projects/devtools", "devtools"]
    },
    "electrolysis": {
      repo: "projects/electrolysis",
      synonyms: ["projects/electrolysis", "electrolysis", "e10s"]
    },
    "places": {
      repo: "projects/places",
      synonyms: ["projects/places", "places"]
    }
  }
};

Config.bugNumberREs = [Config.bugRE1, Config.bugRE2, Config.bugRE3,
                       Config.bugRE4, Config.bugRE5, Config.bugRE6, Config.bugRE7];

(function () {
  var base = Config.hgBaseURL;
  for (var treeName in Config.treeInfo) {
    var repo = Config.treeInfo[treeName].repo;
    Config.treeInfo[treeName]['hgURL'] = base + repo + '/';
    Config.treeInfo[treeName]['hgRevURL'] = base + repo + '/rev/';
    Config.treeInfo[treeName]['hgPushlogURL'] = base + repo + '/pushloghtml?changeset=';
    Config.treeInfo[treeName]['hgRevRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/');
    Config.treeInfo[treeName]['hgRevFullRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/[\\da-f]{12}', 'ig');
    Config.treeInfo[treeName]['hgPushlogRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/pushloghtml\\?changeset=', 'ig');
  }
})();

// Detect input type="email" support
$(document).ready(function() {
  Config.needsValidation = $('#username').prop('type') != 'email';
});
<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/**
 * General dialog type. Migrated from Joist on 4/10/2018
 *
 * @author Jonathan Olson (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrea Lin (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( require => {
  'use strict';

  // modules
  const AccessibilityUtil = require( 'SCENERY/accessibility/AccessibilityUtil' );
  const AccessiblePeer = require( 'SCENERY/accessibility/AccessiblePeer' );
  const AlignBox = require( 'SCENERY/nodes/AlignBox' );
  const DialogIO = require( 'SUN/DialogIO' );
  const Display = require( 'SCENERY/display/Display' );
  const FullScreen = require( 'SCENERY/util/FullScreen' );
  const HBox = require( 'SCENERY/nodes/HBox' );
  const inherit = require( 'PHET_CORE/inherit' );
  const KeyboardUtil = require( 'SCENERY/accessibility/KeyboardUtil' );
  const Panel = require( 'SUN/Panel' );
  const Path = require( 'SCENERY/nodes/Path' );
  const RectangularButtonView = require( 'SUN/buttons/RectangularButtonView' );
  const RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  const Shape = require( 'KITE/Shape' );
  const sun = require( 'SUN/sun' );
  const SunA11yStrings = require( 'SUN/SunA11yStrings' );
  const Tandem = require( 'TANDEM/Tandem' );
  const VBox = require( 'SCENERY/nodes/VBox' );

  // strings
  const closeString = SunA11yStrings.close.value;

  // constants
  const CLOSE_BUTTON_WIDTH = 14;

  /**
   * @param {Node} content - The content to display inside the dialog (not including the title)
   * @param {Object} [options]
   * @constructor
   */
  function Dialog( content, options ) {

    options = _.extend( {

      /* Margins and spacing:
       ____________________________________________________________________________
      |                                     |                          |           |
      |                                     |                          closeButton |
      |                                     topMargin                  TopMargin   |
      |                                     |                         _|___        |
      |                  ___________________|____________________    |     |       |
      |--------l--------|                                        |-x-|  X  |---c---|
      |        e        |   Title                                | S |_____|   l   |
      |        f        |________________________________________| P           o   |
      |        t        |   |                                    | a           s   |
      |        M        |   ySpacing                             | c           e   |
      |        a        |___|____________________________________| i           B   |
      |        r        |                                        | n           u   |
      |        g        |   Content                              | g           t   |
      |        i        |                                        |             t   |
      |        n        |                                        |             o   |
      |                 |                                        |             n   |
      |                 |                                        |             R   |
      |                 |                                        |             i   |
      |                 |                                        |             g   |
      |                 |                                        |             h   |
      |                 |                                        |             M   |
      |                 |________________________________________|             a   |
      |                                     |                                  r   |
      |                                     |                                  g   |
      |                                     bottomMargin                       i   |
      |                                     |                                  n   |
      |_____________________________________|______________________________________|
       */

      xSpacing: 10, // {number} how far the title and content is placed to the left of the close button
      ySpacing: 10, // {number} vertical space between title and content
      topMargin: 15, // {number} margin above content, or above title if provided
      bottomMargin: 15, // {number} margin below content
      leftMargin: null, // {number|null} margin to the left of the content.  If null, this is computed so that we have
      // the same margins on the left and right of the content.
      closeButtonTopMargin: 10, // {number} margin above the close button
      closeButtonRightMargin: 10, // {number} margin to the right of the close button

      // more Dialog-specific options
      modal: true, // {boolean} modal dialogs prevent interaction with the rest of the sim while open

      // {Node|null} Title to be displayed at top. For a11y, make sure that its primary sibling has an accessible name
      title: null,
      titleAlign: 'center', // horizontal alignment of the title: {string} left, right or center

      // {function} which sets the dialog's position in global coordinates. called as
      // layoutStrategy( dialog, simBounds, screenBounds, scale )
      layoutStrategy: Dialog.DEFAULT_LAYOUT_STRATEGY,

      // close button options
      closeButtonListener: () => this.hide(),
      closeButtonTouchAreaXDilation: 0,
      closeButtonTouchAreaYDilation: 0,
      closeButtonMouseAreaXDilation: 0,
      closeButtonMouseAreaYDilation: 0,

      // {function|null} called after the dialog is shown, see https://github.com/phetsims/joist/issues/478
      showCallback: null,

      // {function|null} called after the dialog is hidden, see https://github.com/phetsims/joist/issues/478
      hideCallback: null,

      // pass through to Panel options
      cornerRadius: 10, // {number} radius of the dialog's corners
      resize: true, // {boolean} whether to resize if content's size changes
      fill: 'white', // {string|Color}
      stroke: 'black', // {string|Color}
      backgroundPickable: true,
      tandem: Tandem.optional,
      phetioType: DialogIO,
      phetioReadOnly: false, // default to false so it can pass it through to the close button
      phetioState: false, // default to false so it can pass it through to the close button

      // a11y options
      tagName: 'div',
      ariaRole: 'dialog',
      focusOnCloseNode: null // {Node} receives focus on close, if null focus returns to element that had focus on open
    }, options );

    assert && assert( options.xMargin === undefined, 'Dialog sets xMargin' );
    options.xMargin = 0;
    assert && assert( options.yMargin === undefined, 'Dialog sets yMargin' );
    options.yMargin = 0;

    // if left margin is specified in options, use it. otherwise, set it to make the left right gutters symmetrical
    if ( options.leftMargin === null ) {
      options.leftMargin = options.xSpacing + CLOSE_BUTTON_WIDTH + options.closeButtonRightMargin;
    }

    // @private (read-only)
    this.isModal = options.modal;

    // @private
    this.showCallback = options.showCallback;
    this.hideCallback = options.hideCallback;

    // see https://github.com/phetsims/joist/issues/293
    assert && assert( this.isModal, 'Non-modal dialogs not currently supported' );

    // @protected - whether the dialog is showing
    this.isShowing = false;

    // create close button
    const closeButton = new CloseButton( {

      iconLength: CLOSE_BUTTON_WIDTH,
      listener: () => {
        options.closeButtonListener();

        // if listener was fired because of accessibility
        if ( closeButton.buttonModel.isA11yClicking() ) {
          this.focusActiveElement();
        }
      },

      // phet-io
      tandem: options.tandem.createTandem( 'closeButton' ),
      phetioReadOnly: options.phetioReadOnly, // match the readOnly of the Dialog
      phetioState: options.phetioState, // match the state transfer of the Dialog

      // a11y
      tagName: 'button',
      innerContent: closeString
    } );

    // touch/mouse areas for the close button
    closeButton.touchArea = closeButton.bounds.dilatedXY(
      options.closeButtonTouchAreaXDilation,
      options.closeButtonTouchAreaYDilation
    );
    closeButton.mouseArea = closeButton.bounds.dilatedXY(
      options.closeButtonMouseAreaXDilation,
      options.closeButtonMouseAreaYDilation
    );

    // @private (a11y)
    this.closeButton = closeButton;

    // Align content, title, and close button using spacing and margin options

    // align content and title (if provided) vertically
    const contentAndTitle = new VBox( {
      children: options.title ? [ options.title, content ] : [ content ],
      spacing: options.ySpacing,
      align: options.titleAlign
    } );

    // add topMargin, bottomMargin, and leftMargin
    const contentAndTitleWithMargins = new AlignBox( contentAndTitle, {
      topMargin: options.topMargin,
      bottomMargin: options.bottomMargin,
      leftMargin: options.leftMargin
    } );

    // add closeButtonTopMargin and closeButtonRightMargin
    const closeButtonWithMargins = new AlignBox( closeButton, {
      topMargin: options.closeButtonTopMargin,
      rightMargin: options.closeButtonRightMargin
    } );

    // create content for Panel
    const dialogContent = new HBox( {
      children: [ contentAndTitleWithMargins, closeButtonWithMargins ],
      spacing: options.xSpacing,
      align: 'top'
    } );

    Panel.call( this, dialogContent, options );

    const sim = window.phet.joist.sim;

    // @private
    this.updateLayout = () => {
      options.layoutStrategy( this, sim.boundsProperty.value, sim.screenBoundsProperty.value, sim.scaleProperty.value );
    };

    this.updateLayout();

    // @private
    this.sim = sim;

    // a11y - set the order of content, close button first so remaining content can be read from top to bottom
    // with virtual cursor
    this.accessibleOrder = [ closeButton, options.title, content ].filter( node => node !== undefined );

    // a11y - set the aria-labelledby relation so that whenever focus enters the dialog the title is read
    if ( options.title && options.title.tagName ) {
      this.addAriaLabelledbyAssociation( {
        thisElementName: AccessiblePeer.PRIMARY_SIBLING,
        otherNode: options.title,
        otherElementName: AccessiblePeer.PRIMARY_SIBLING
      } );
    }

    // must be removed on dispose
    this.sim.resizedEmitter.addListener( this.updateLayout );

    // @private (a11y) - the active element when the dialog is shown, tracked so that focus can be restored on close
    this.activeElement = options.focusOnCloseNode || null;

    // a11y - close the dialog when pressing "escape"
    const escapeListener = {
      keydown: event => {
        const domEvent = event.domEvent;

        if ( domEvent.keyCode === KeyboardUtil.KEY_ESCAPE ) {
          domEvent.preventDefault();
          this.hide();
          this.focusActiveElement();
        }
        else if ( domEvent.keyCode === KeyboardUtil.KEY_TAB && FullScreen.isFullScreen() ) {

          // prevent a particular bug in Windows 7/8.1 Firefox where focus gets trapped in the document
          // when the navigation bar is hidden and there is only one focusable element in the DOM
          // see https://bugzilla.mozilla.org/show_bug.cgi?id=910136
          const activeId = Display.focus.trail.getUniqueId();
          const noNextFocusable = AccessibilityUtil.getNextFocusable().id === activeId;
          const noPreviousFocusable = AccessibilityUtil.getPreviousFocusable().id === activeId;

          if ( noNextFocusable && noPreviousFocusable ) {
            domEvent.preventDefault();
          }
        }
      }
    };
    this.addInputListener( escapeListener );

    // @private - to be called on dispose()
    this.disposeDialog = () => {
      this.sim.resizedEmitter.removeListener( this.updateLayout );
      this.removeInputListener( escapeListener );

      closeButton.dispose();

      // remove dialog content from scene graph, but don't dispose because Panel
      // needs to remove listeners on the content in its dispose()
      dialogContent.removeAllChildren();
      dialogContent.detach();
    };
  }

  sun.register( 'Dialog', Dialog );

  // @private
  Dialog.DEFAULT_LAYOUT_STRATEGY = ( dialog, simBounds, screenBounds, scale ) => {

    // The size is set in the Sim.topLayer, but we need to update the location here
    dialog.center = simBounds.center.times( 1.0 / scale );
  };

  inherit( Panel, Dialog, {

    // @public
    show: function() {
      if ( !this.isShowing ) {
        window.phet.joist.sim.showPopup( this, this.isModal );
        this.isShowing = true;

        // a11y - focus is returned to this element if dialog closed from accessible input
        this.activeElement = this.activeElement || Display.focusedNode;

        // a11y - modal dialogs should be the only readable content in the sim
        // TODO: non-modal dialogs shouldn't hide other accessible content, and this should be dependant on other
        // things in the sim modalNodeStack, see https://github.com/phetsims/joist/issues/293
        this.sim.setAccessibleViewsVisible( false );

        // In case the window size has changed since the dialog was hidden, we should try layout out again.
        // See https://github.com/phetsims/joist/issues/362
        this.updateLayout();

        // Do this last
        this.showCallback && this.showCallback();
      }
    },

    /**
     * Hide the dialog.  If you create a new dialog next time you show(), be sure to dispose this
     * dialog instead.
     * @public
     */
    hide: function() {
      if ( this.isShowing ) {

        window.phet.joist.sim.hidePopup( this, this.isModal );
        this.isShowing = false;

        // a11y - when the dialog is hidden, make all ScreenView content visible to assistive technology
        this.sim.setAccessibleViewsVisible( true );

        // Do this last
        this.hideCallback && this.hideCallback();
      }
    },

    /**
     * Make eligible for garbage collection.
     * @public
     */
    dispose() {
      this.hide();
      this.disposeDialog();
      Panel.prototype.dispose.call( this );
    },

    /**
     * If there is an active element, focus it.  Should almost always be called after the Dialog has been closed.
     *
     * @public
     * @a11y
     */
    focusActiveElement() {
      this.activeElement && this.activeElement.focus();
    },

    /**
     * Place keyboard focus on the close button, useful when opening the dialog with an accessibility interaction.
     * @public
     */
    focusCloseButton() {
      this.closeButton.focus();
    }
  } );

  /**
   * The close button for Dialog
   * A flat x
   *
   * @param {Object} [options] - see RectangularPushButton
   * @constructor
   */
  function CloseButton( options ) {
    options = _.extend( {
      iconLength: 7,
      baseColor: 'transparent',
      buttonAppearanceStrategy: RectangularButtonView.FlatAppearanceStrategy,
      xMargin: 0,
      yMargin: 0,
      listener: null // {function} called when the button is pressed
    }, options );

    // close button shape, an 'X'
    const closeButtonShape = new Shape()
      .moveTo( -options.iconLength / 2, -options.iconLength / 2 )
      .lineTo( options.iconLength / 2, options.iconLength / 2 )
      .moveTo( options.iconLength / 2, -options.iconLength / 2 )
      .lineTo( -options.iconLength / 2, options.iconLength / 2 );

    assert && assert( !options.content, 'Dialog.CloseButton sets content' );

    options.content = new Path( closeButtonShape, {
      stroke: 'black',
      lineCap: 'round',
      lineWidth: 2
    } );

    RectangularPushButton.call( this, options );
  }

  sun.register( 'Dialog.CloseButton', CloseButton );
  inherit( RectangularPushButton, CloseButton );

  return Dialog;
} );<commit_msg>Added isShowingProperty to Dialog, see https://github.com/phetsims/sun/issues/369<commit_after>// Copyright 2018, University of Colorado Boulder

/**
 * General dialog type. Migrated from Joist on 4/10/2018
 *
 * @author Jonathan Olson (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrea Lin (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( require => {
  'use strict';

  // modules
  const AccessibilityUtil = require( 'SCENERY/accessibility/AccessibilityUtil' );
  const AccessiblePeer = require( 'SCENERY/accessibility/AccessiblePeer' );
  const AlignBox = require( 'SCENERY/nodes/AlignBox' );
  const BooleanProperty = require( 'AXON/BooleanProperty' );
  const DialogIO = require( 'SUN/DialogIO' );
  const Display = require( 'SCENERY/display/Display' );
  const FullScreen = require( 'SCENERY/util/FullScreen' );
  const HBox = require( 'SCENERY/nodes/HBox' );
  const inherit = require( 'PHET_CORE/inherit' );
  const KeyboardUtil = require( 'SCENERY/accessibility/KeyboardUtil' );
  const Panel = require( 'SUN/Panel' );
  const Path = require( 'SCENERY/nodes/Path' );
  const RectangularButtonView = require( 'SUN/buttons/RectangularButtonView' );
  const RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  const Shape = require( 'KITE/Shape' );
  const sun = require( 'SUN/sun' );
  const SunA11yStrings = require( 'SUN/SunA11yStrings' );
  const Tandem = require( 'TANDEM/Tandem' );
  const VBox = require( 'SCENERY/nodes/VBox' );

  // strings
  const closeString = SunA11yStrings.close.value;

  // constants
  const CLOSE_BUTTON_WIDTH = 14;

  /**
   * @param {Node} content - The content to display inside the dialog (not including the title)
   * @param {Object} [options]
   * @constructor
   */
  function Dialog( content, options ) {

    options = _.extend( {

      /* Margins and spacing:
       ____________________________________________________________________________
      |                                     |                          |           |
      |                                     |                          closeButton |
      |                                     topMargin                  TopMargin   |
      |                                     |                         _|___        |
      |                  ___________________|____________________    |     |       |
      |--------l--------|                                        |-x-|  X  |---c---|
      |        e        |   Title                                | S |_____|   l   |
      |        f        |________________________________________| P           o   |
      |        t        |   |                                    | a           s   |
      |        M        |   ySpacing                             | c           e   |
      |        a        |___|____________________________________| i           B   |
      |        r        |                                        | n           u   |
      |        g        |   Content                              | g           t   |
      |        i        |                                        |             t   |
      |        n        |                                        |             o   |
      |                 |                                        |             n   |
      |                 |                                        |             R   |
      |                 |                                        |             i   |
      |                 |                                        |             g   |
      |                 |                                        |             h   |
      |                 |                                        |             M   |
      |                 |________________________________________|             a   |
      |                                     |                                  r   |
      |                                     |                                  g   |
      |                                     bottomMargin                       i   |
      |                                     |                                  n   |
      |_____________________________________|______________________________________|
       */

      xSpacing: 10, // {number} how far the title and content is placed to the left of the close button
      ySpacing: 10, // {number} vertical space between title and content
      topMargin: 15, // {number} margin above content, or above title if provided
      bottomMargin: 15, // {number} margin below content
      leftMargin: null, // {number|null} margin to the left of the content.  If null, this is computed so that we have
      // the same margins on the left and right of the content.
      closeButtonTopMargin: 10, // {number} margin above the close button
      closeButtonRightMargin: 10, // {number} margin to the right of the close button

      // more Dialog-specific options
      modal: true, // {boolean} modal dialogs prevent interaction with the rest of the sim while open

      // {Node|null} Title to be displayed at top. For a11y, make sure that its primary sibling has an accessible name
      title: null,
      titleAlign: 'center', // horizontal alignment of the title: {string} left, right or center

      // {function} which sets the dialog's position in global coordinates. called as
      // layoutStrategy( dialog, simBounds, screenBounds, scale )
      layoutStrategy: Dialog.DEFAULT_LAYOUT_STRATEGY,

      // close button options
      closeButtonListener: () => this.hide(),
      closeButtonTouchAreaXDilation: 0,
      closeButtonTouchAreaYDilation: 0,
      closeButtonMouseAreaXDilation: 0,
      closeButtonMouseAreaYDilation: 0,

      // {function|null} called after the dialog is shown, see https://github.com/phetsims/joist/issues/478
      showCallback: null,

      // {function|null} called after the dialog is hidden, see https://github.com/phetsims/joist/issues/478
      hideCallback: null,

      // pass through to Panel options
      cornerRadius: 10, // {number} radius of the dialog's corners
      resize: true, // {boolean} whether to resize if content's size changes
      fill: 'white', // {string|Color}
      stroke: 'black', // {string|Color}
      backgroundPickable: true,
      tandem: Tandem.optional,
      phetioType: DialogIO,
      phetioReadOnly: false, // default to false so it can pass it through to the close button
      phetioState: false, // default to false so it can pass it through to the close button

      // a11y options
      tagName: 'div',
      ariaRole: 'dialog',
      focusOnCloseNode: null // {Node} receives focus on close, if null focus returns to element that had focus on open
    }, options );

    assert && assert( options.xMargin === undefined, 'Dialog sets xMargin' );
    options.xMargin = 0;
    assert && assert( options.yMargin === undefined, 'Dialog sets yMargin' );
    options.yMargin = 0;

    // if left margin is specified in options, use it. otherwise, set it to make the left right gutters symmetrical
    if ( options.leftMargin === null ) {
      options.leftMargin = options.xSpacing + CLOSE_BUTTON_WIDTH + options.closeButtonRightMargin;
    }

    // @private (read-only)
    this.isModal = options.modal;

    // @private
    this.showCallback = options.showCallback;
    this.hideCallback = options.hideCallback;

    // see https://github.com/phetsims/joist/issues/293
    assert && assert( this.isModal, 'Non-modal dialogs not currently supported' );

    // @protected (read-only) - whether the dialog is showing
    this.isShowingProperty = new BooleanProperty( false, {
      tandem: options.tandem.createTandem( 'isShowingProperty' ),
      phetioReadOnly: true
    } );

    // create close button
    const closeButton = new CloseButton( {

      iconLength: CLOSE_BUTTON_WIDTH,
      listener: () => {
        options.closeButtonListener();

        // if listener was fired because of accessibility
        if ( closeButton.buttonModel.isA11yClicking() ) {
          this.focusActiveElement();
        }
      },

      // phet-io
      tandem: options.tandem.createTandem( 'closeButton' ),
      phetioReadOnly: options.phetioReadOnly, // match the readOnly of the Dialog
      phetioState: options.phetioState, // match the state transfer of the Dialog

      // a11y
      tagName: 'button',
      innerContent: closeString
    } );

    // touch/mouse areas for the close button
    closeButton.touchArea = closeButton.bounds.dilatedXY(
      options.closeButtonTouchAreaXDilation,
      options.closeButtonTouchAreaYDilation
    );
    closeButton.mouseArea = closeButton.bounds.dilatedXY(
      options.closeButtonMouseAreaXDilation,
      options.closeButtonMouseAreaYDilation
    );

    // @private (a11y)
    this.closeButton = closeButton;

    // Align content, title, and close button using spacing and margin options

    // align content and title (if provided) vertically
    const contentAndTitle = new VBox( {
      children: options.title ? [ options.title, content ] : [ content ],
      spacing: options.ySpacing,
      align: options.titleAlign
    } );

    // add topMargin, bottomMargin, and leftMargin
    const contentAndTitleWithMargins = new AlignBox( contentAndTitle, {
      topMargin: options.topMargin,
      bottomMargin: options.bottomMargin,
      leftMargin: options.leftMargin
    } );

    // add closeButtonTopMargin and closeButtonRightMargin
    const closeButtonWithMargins = new AlignBox( closeButton, {
      topMargin: options.closeButtonTopMargin,
      rightMargin: options.closeButtonRightMargin
    } );

    // create content for Panel
    const dialogContent = new HBox( {
      children: [ contentAndTitleWithMargins, closeButtonWithMargins ],
      spacing: options.xSpacing,
      align: 'top'
    } );

    Panel.call( this, dialogContent, options );

    const sim = window.phet.joist.sim;

    // @private
    this.updateLayout = () => {
      options.layoutStrategy( this, sim.boundsProperty.value, sim.screenBoundsProperty.value, sim.scaleProperty.value );
    };

    this.updateLayout();

    // @private
    this.sim = sim;

    // a11y - set the order of content, close button first so remaining content can be read from top to bottom
    // with virtual cursor
    this.accessibleOrder = [ closeButton, options.title, content ].filter( node => node !== undefined );

    // a11y - set the aria-labelledby relation so that whenever focus enters the dialog the title is read
    if ( options.title && options.title.tagName ) {
      this.addAriaLabelledbyAssociation( {
        thisElementName: AccessiblePeer.PRIMARY_SIBLING,
        otherNode: options.title,
        otherElementName: AccessiblePeer.PRIMARY_SIBLING
      } );
    }

    // must be removed on dispose
    this.sim.resizedEmitter.addListener( this.updateLayout );

    // @private (a11y) - the active element when the dialog is shown, tracked so that focus can be restored on close
    this.activeElement = options.focusOnCloseNode || null;

    // a11y - close the dialog when pressing "escape"
    const escapeListener = {
      keydown: event => {
        const domEvent = event.domEvent;

        if ( domEvent.keyCode === KeyboardUtil.KEY_ESCAPE ) {
          domEvent.preventDefault();
          this.hide();
          this.focusActiveElement();
        }
        else if ( domEvent.keyCode === KeyboardUtil.KEY_TAB && FullScreen.isFullScreen() ) {

          // prevent a particular bug in Windows 7/8.1 Firefox where focus gets trapped in the document
          // when the navigation bar is hidden and there is only one focusable element in the DOM
          // see https://bugzilla.mozilla.org/show_bug.cgi?id=910136
          const activeId = Display.focus.trail.getUniqueId();
          const noNextFocusable = AccessibilityUtil.getNextFocusable().id === activeId;
          const noPreviousFocusable = AccessibilityUtil.getPreviousFocusable().id === activeId;

          if ( noNextFocusable && noPreviousFocusable ) {
            domEvent.preventDefault();
          }
        }
      }
    };
    this.addInputListener( escapeListener );

    // @private - to be called on dispose()
    this.disposeDialog = () => {
      this.sim.resizedEmitter.removeListener( this.updateLayout );
      this.removeInputListener( escapeListener );

      closeButton.dispose();

      // remove dialog content from scene graph, but don't dispose because Panel
      // needs to remove listeners on the content in its dispose()
      dialogContent.removeAllChildren();
      dialogContent.detach();
    };
  }

  sun.register( 'Dialog', Dialog );

  // @private
  Dialog.DEFAULT_LAYOUT_STRATEGY = ( dialog, simBounds, screenBounds, scale ) => {

    // The size is set in the Sim.topLayer, but we need to update the location here
    dialog.center = simBounds.center.times( 1.0 / scale );
  };

  inherit( Panel, Dialog, {

    // @public
    show: function() {
      if ( !this.isShowingProperty.value ) {
        window.phet.joist.sim.showPopup( this, this.isModal );
        this.isShowingProperty.value = true;

        // a11y - focus is returned to this element if dialog closed from accessible input
        this.activeElement = this.activeElement || Display.focusedNode;

        // a11y - modal dialogs should be the only readable content in the sim
        // TODO: non-modal dialogs shouldn't hide other accessible content, and this should be dependant on other
        // things in the sim modalNodeStack, see https://github.com/phetsims/joist/issues/293
        this.sim.setAccessibleViewsVisible( false );

        // In case the window size has changed since the dialog was hidden, we should try layout out again.
        // See https://github.com/phetsims/joist/issues/362
        this.updateLayout();

        // Do this last
        this.showCallback && this.showCallback();
      }
    },

    /**
     * Hide the dialog.  If you create a new dialog next time you show(), be sure to dispose this
     * dialog instead.
     * @public
     */
    hide: function() {
      if ( this.isShowingProperty.value ) {

        window.phet.joist.sim.hidePopup( this, this.isModal );
        this.isShowingProperty.value = false;

        // a11y - when the dialog is hidden, make all ScreenView content visible to assistive technology
        this.sim.setAccessibleViewsVisible( true );

        // Do this last
        this.hideCallback && this.hideCallback();
      }
    },

    /**
     * Make eligible for garbage collection.
     * @public
     */
    dispose() {
      this.hide();
      this.disposeDialog();
      Panel.prototype.dispose.call( this );
    },

    /**
     * If there is an active element, focus it.  Should almost always be called after the Dialog has been closed.
     *
     * @public
     * @a11y
     */
    focusActiveElement() {
      this.activeElement && this.activeElement.focus();
    },

    /**
     * Place keyboard focus on the close button, useful when opening the dialog with an accessibility interaction.
     * @public
     */
    focusCloseButton() {
      this.closeButton.focus();
    }
  } );

  /**
   * The close button for Dialog
   * A flat x
   *
   * @param {Object} [options] - see RectangularPushButton
   * @constructor
   */
  function CloseButton( options ) {
    options = _.extend( {
      iconLength: 7,
      baseColor: 'transparent',
      buttonAppearanceStrategy: RectangularButtonView.FlatAppearanceStrategy,
      xMargin: 0,
      yMargin: 0,
      listener: null // {function} called when the button is pressed
    }, options );

    // close button shape, an 'X'
    const closeButtonShape = new Shape()
      .moveTo( -options.iconLength / 2, -options.iconLength / 2 )
      .lineTo( options.iconLength / 2, options.iconLength / 2 )
      .moveTo( options.iconLength / 2, -options.iconLength / 2 )
      .lineTo( -options.iconLength / 2, options.iconLength / 2 );

    assert && assert( !options.content, 'Dialog.CloseButton sets content' );

    options.content = new Path( closeButtonShape, {
      stroke: 'black',
      lineCap: 'round',
      lineWidth: 2
    } );

    RectangularPushButton.call( this, options );
  }

  sun.register( 'Dialog.CloseButton', CloseButton );
  inherit( RectangularPushButton, CloseButton );

  return Dialog;
} );<|endoftext|>


<commit_before>var express = require('express'),
	bodyParser = require('body-parser'),
    authenticate = require('azure-mobile-apps/src/express/middleware/authenticate'),
    authorize = require('azure-mobile-apps/src/express/middleware/authorize');

var sql = require('mssql');
var util = require('../util');

const queryTertulias = 'SELECT' +
' tr_id         AS id,' +
' tr_name       AS name,' +
' tr_subject    AS subject,' +
' ev_targetdate AS nextEventDate,' +
' lo_name       AS nextEventLocation,' +
' no_count      AS messages,' +
' nv_name       AS role ' +
' FROM Tertulias' +
' INNER JOIN Members ON mb_tertulia = tr_id' +
' INNER JOIN Enumvalues ON mb_role = nv_id' +
' INNER JOIN Users ON mb_user = us_id' +
' LEFT JOIN' +
' (SELECT * FROM' +
' (SELECT RANK() OVER(PARTITION BY ev_tertulia ORDER BY ev_targetdate DESC) AS "rank", * FROM Events' +
'  INNER JOIN Locations on ev_location = lo_id WHERE ev_targetdate > GETDATE()) AS a WHERE a.rank = 1) AS b' +
' ON ev_tertulia = tr_id' +
' LEFT JOIN (SELECT no_tertulia, count(*) AS no_count FROM Notifications WHERE no_id NOT IN' +
' (SELECT no_id FROM Notifications INNER JOIN Readnotifications ON rn_notification = no_id' +
' INNER JOIN Users ON rn_user = us_id WHERE us_sid = @sid)' +
' GROUP BY no_tertulia) AS c ON no_tertulia = tr_id' +
' WHERE tr_is_cancelled = 0 AND us_sid = @sid';

module.exports = function (configuration) {
    var router = express.Router();

	var completeError = function(err, res) {
	    if (err) {
	        console.error(err);
	        if (res) res.sendStatus(500);
	    }
	};

    router.get('/', (req, res, next) => {
		var route = '/tertulias';
		req['tertulias'] = {};
		req['route'] = route;
		req['resultsTag'] = 'tertulias';
		req.tertulias['query'] = queryTertulias;
	    req.tertulias['paramsTypes'] = { 'sid': sql.NVarChar }; // String -> sql.NVarChar; Number -> sql.Int; Boolean -> sql.Bit; Date -> sql.DateTime; Buffer -> sql.VarBinary; sql.Table -> sql.TVP
	    req.tertulias['paramsValues'] = { 'sid': req.azureMobile.user.id };
	    req.tertulias['links'] = '[ ' +
			'{ rel: "self", method: "GET", href: "' + route + '" }, ' +
			'{ rel: "create", method: "POST", href: "' + route + '" }, ' +
			'{ rel: "searchPublic", method: "GET", href: "' + route + '/publicsearch" } ' +
		']';
	    req.tertulias['itemLinks'] = '[ ' +
			'{ rel: "self", method: "GET", href: "' + route + '/:tertulia" }, ' +
			'{ rel: "update", method: "PUT", href: "' + route + '/:tertulia" }, ' +
			'{ rel: "delete", method: "DELETE", href: "' + route + '/:tertulia" } ' +
		']';
	    goGet(req, res, next);
    	/*
		*/
	});

	var goGet = function(req, res, next) {
		console.log('VAMOS AQUI: 1');
		var query = req.tertulias.query;
		var resultsTag = req.tertulias.resultsTag;
		var route = req.tertulias.route;
	    var paramsTypes = req.tertulias.paramsTypes;
	    var paramsValues = req.tertulias.paramsValues;
	    var links = req.tertulias.links;
	    var itemLinks = req.tertulias.itemLinks;
		console.log('VAMOS AQUI: 2');

		var connection = new sql.Connection(util.sqlConfiguration);
	    connection.connect(function(err) {
			console.log('VAMOS AQUI: 3');
	        var preparedStatement = new sql.PreparedStatement(connection);
	        for (var key in paramsTypes)
	        	preparedStatement.input(key, paramsTypes[key]);
			console.log('VAMOS AQUI: 4');
	        preparedStatement.prepare(query, function(err) {
	            if (err) {
	            	completeError(err, res);
	            	return;
	            }
				console.log('VAMOS AQUI: 5');
	            preparedStatement.execute(paramsValues,
	                function(err, recordset, affected) {
						console.log('VAMOS AQUI: 6');
	                    if (err) {
	                    	completeError(err, res);
	                    	return;
	                    }
						console.log('VAMOS AQUI: 7');
	                    res.type('application/json');
                    	if (typeof itemLinks !== typeof undefined) {
							console.log(itemLinks);
		                    recordset.forEach(function(elem) {
								console.log(elem);
		                    	elem['links'] = JSON.parse(itemLinks.replace(/:tertulia/g, elem.tr_id));
                    		});
	                    };
	                    preparedStatement.unprepare();
						console.log('VAMOS AQUI: 8');
	                    var results = {};
	                    results[resultsTag] = recordset;
						console.log('VAMOS AQUI: 9');
	                    results['links'] = links;
	                    console.log(results);
	                    res.json(results);
	                    next();
	                }
	            );
	        });
	    });
		/*
	    */
	}

    return router;

}
<commit_msg>wip save<commit_after>var express = require('express'),
	bodyParser = require('body-parser'),
    authenticate = require('azure-mobile-apps/src/express/middleware/authenticate'),
    authorize = require('azure-mobile-apps/src/express/middleware/authorize');

var sql = require('mssql');
var util = require('../util');

const queryTertulias = 'SELECT' +
' tr_id         AS id,' +
' tr_name       AS name,' +
' tr_subject    AS subject,' +
' ev_targetdate AS nextEventDate,' +
' lo_name       AS nextEventLocation,' +
' no_count      AS messages,' +
' nv_name       AS role ' +
' FROM Tertulias' +
' INNER JOIN Members ON mb_tertulia = tr_id' +
' INNER JOIN Enumvalues ON mb_role = nv_id' +
' INNER JOIN Users ON mb_user = us_id' +
' LEFT JOIN' +
' (SELECT * FROM' +
' (SELECT RANK() OVER(PARTITION BY ev_tertulia ORDER BY ev_targetdate DESC) AS "rank", * FROM Events' +
'  INNER JOIN Locations on ev_location = lo_id WHERE ev_targetdate > GETDATE()) AS a WHERE a.rank = 1) AS b' +
' ON ev_tertulia = tr_id' +
' LEFT JOIN (SELECT no_tertulia, count(*) AS no_count FROM Notifications WHERE no_id NOT IN' +
' (SELECT no_id FROM Notifications INNER JOIN Readnotifications ON rn_notification = no_id' +
' INNER JOIN Users ON rn_user = us_id WHERE us_sid = @sid)' +
' GROUP BY no_tertulia) AS c ON no_tertulia = tr_id' +
' WHERE tr_is_cancelled = 0 AND us_sid = @sid';

module.exports = function (configuration) {
    var router = express.Router();

	var completeError = function(err, res) {
	    if (err) {
	        console.error(err);
	        if (res) res.sendStatus(500);
	    }
	};

    router.get('/', (req, res, next) => {
		var route = '/tertulias';
		req['tertulias'] = {};
		req['route'] = route;
		req['resultsTag'] = 'tertulias';
		req.tertulias['query'] = queryTertulias;
	    req.tertulias['paramsTypes'] = { 'sid': sql.NVarChar }; // String -> sql.NVarChar; Number -> sql.Int; Boolean -> sql.Bit; Date -> sql.DateTime; Buffer -> sql.VarBinary; sql.Table -> sql.TVP
	    req.tertulias['paramsValues'] = { 'sid': req.azureMobile.user.id };
	    req.tertulias['links'] = '[ ' +
			'{ rel: "self", method: "GET", href: "' + route + '" }, ' +
			'{ rel: "create", method: "POST", href: "' + route + '" }, ' +
			'{ rel: "searchPublic", method: "GET", href: "' + route + '/publicsearch" } ' +
		']';
	    req.tertulias['itemLinks'] = '[ ' +
			'{ rel: "self", method: "GET", href: "' + route + '/:tertulia" }, ' +
			'{ rel: "update", method: "PUT", href: "' + route + '/:tertulia" }, ' +
			'{ rel: "delete", method: "DELETE", href: "' + route + '/:tertulia" } ' +
		']';
	    goGet(req, res, next);
    	/*
		*/
	});

	var goGet = function(req, res, next) {
		console.log('VAMOS AQUI: 1');
		var query = req.tertulias.query;
		var resultsTag = req.tertulias.resultsTag;
		var route = req.tertulias.route;
	    var paramsTypes = req.tertulias.paramsTypes;
	    var paramsValues = req.tertulias.paramsValues;
	    var links = req.tertulias.links;
	    var itemLinks = req.tertulias.itemLinks;
		console.log('VAMOS AQUI: 2');

		var connection = new sql.Connection(util.sqlConfiguration);
	    connection.connect(function(err) {
			console.log('VAMOS AQUI: 3');
	        var preparedStatement = new sql.PreparedStatement(connection);
	        for (var key in paramsTypes)
	        	preparedStatement.input(key, paramsTypes[key]);
			console.log('VAMOS AQUI: 4');
	        preparedStatement.prepare(query, function(err) {
	            if (err) {
	            	completeError(err, res);
	            	return;
	            }
				console.log('VAMOS AQUI: 5');
	            preparedStatement.execute(paramsValues,
	                function(err, recordset, affected) {
						console.log('VAMOS AQUI: 6');
	                    if (err) {
	                    	completeError(err, res);
	                    	return;
	                    }
						console.log('VAMOS AQUI: 7');
	                    res.type('application/json');
                    	if (typeof itemLinks !== typeof undefined) {
							console.log(itemLinks);
		                    recordset.forEach(function(elem) {
								console.log(elem);
		                    	elem['links'] = JSON.parse(itemLinks.replace(/:tertulia/g, elem.id));
                    		});
	                    };
	                    preparedStatement.unprepare();
						console.log('VAMOS AQUI: 8');
	                    var results = {};
	                    results[resultsTag] = recordset;
						console.log('VAMOS AQUI: 9');
	                    results['links'] = links;
	                    console.log(results);
	                    res.json(results);
	                    next();
	                }
	            );
	        });
	    });
		/*
	    */
	}

    return router;

}
<|endoftext|>


<commit_before>(function() {
    var fs = require('fs-extra');
    var gulp = require('gulp');
    var gulpFilter = ${lessEnabled} && ${coffeeEnabled} : require('gulp-filter');

    if (${lessEnabled}) {
        var less = require('gulp-less');
        var cssmin = require('gulp-minify-css');
        gulp.task('less', function() {
            if (fs.existsSync('${srcLess}')) {
                if (!fs.existsSync('${destLess}')) {
                    fs.mkdirsSync('${destLess}');
                }
                var g = gulp.src('${srcLess}/**/*.less')
                    .pipe(gulpFilter(${filterLess}))
                    .pipe(less());
                if (${minifyLess}) {
                    g = g.pipe(cssmin({root: '${srcLess}'}));
                }
                g.pipe(gulp.dest('${destLess}'));
            }
        });
    }

    if (${coffeeEnabled}) {
        var coffee = require('gulp-coffee');
        var uglify = require('gulp-uglify');
        var include = require("gulp-include");
        gulp.task('coffee', function() {
            if (fs.existsSync('${srcCoffee}')) {
                if (!fs.existsSync('${destCoffee}')) {
                    fs.mkdirsSync('${destCoffee}');
                }
                var g = gulp.src('${srcCoffee}/**/*.coffee')
                    .pipe(include())
                    .pipe(gulpFilter(${filterCoffee}))
                    .pipe(coffee())
                if (${minifyCoffee}) {
                    g = g.pipe(uglify())
                }
                g.pipe(gulp.dest('${destCoffee}'));
            }
        });
    }

    if (${bowerEnabled}) {
        var mainBowerFiles = require('main-bower-files');
        gulp.task('bower-files', function() {
            if (fs.existsSync('bower.json')) {
                gulp.src(mainBowerFiles(), { base: '${workDir}/bower_components' })
                    .pipe(gulp.dest('${destLib}'));
            }
        });
    }

    gulp.task('watch', function() {
        if (fs.existsSync('${srcLess}')) {
            gulp.watch('${srcLess}/**/*.less', ['less']);
        }
        if (fs.existsSync('${srcCoffee}')) {
            gulp.watch('${srcCoffee}/**/*.coffee', ['coffee']);
        }
    });
})();
<commit_msg>Fixed wrong expression in gulpfile.js.<commit_after>(function() {
    var fs = require('fs-extra');
    var gulp = require('gulp');
    var gulpFilter = ${lessEnabled} && ${coffeeEnabled} ? require('gulp-filter') : 0;

    if (${lessEnabled}) {
        var less = require('gulp-less');
        var cssmin = require('gulp-minify-css');
        gulp.task('less', function() {
            if (fs.existsSync('${srcLess}')) {
                if (!fs.existsSync('${destLess}')) {
                    fs.mkdirsSync('${destLess}');
                }
                var g = gulp.src('${srcLess}/**/*.less')
                    .pipe(gulpFilter(${filterLess}))
                    .pipe(less());
                if (${minifyLess}) {
                    g = g.pipe(cssmin({root: '${srcLess}'}));
                }
                g.pipe(gulp.dest('${destLess}'));
            }
        });
    }

    if (${coffeeEnabled}) {
        var coffee = require('gulp-coffee');
        var uglify = require('gulp-uglify');
        var include = require("gulp-include");
        gulp.task('coffee', function() {
            if (fs.existsSync('${srcCoffee}')) {
                if (!fs.existsSync('${destCoffee}')) {
                    fs.mkdirsSync('${destCoffee}');
                }
                var g = gulp.src('${srcCoffee}/**/*.coffee')
                    .pipe(include())
                    .pipe(gulpFilter(${filterCoffee}))
                    .pipe(coffee())
                if (${minifyCoffee}) {
                    g = g.pipe(uglify())
                }
                g.pipe(gulp.dest('${destCoffee}'));
            }
        });
    }

    if (${bowerEnabled}) {
        var mainBowerFiles = require('main-bower-files');
        gulp.task('bower-files', function() {
            if (fs.existsSync('bower.json')) {
                gulp.src(mainBowerFiles(), { base: '${workDir}/bower_components' })
                    .pipe(gulp.dest('${destLib}'));
            }
        });
    }

    gulp.task('watch', function() {
        if (fs.existsSync('${srcLess}')) {
            gulp.watch('${srcLess}/**/*.less', ['less']);
        }
        if (fs.existsSync('${srcCoffee}')) {
            gulp.watch('${srcCoffee}/**/*.coffee', ['coffee']);
        }
    });
})();
<|endoftext|>