<commit_before>//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require fe/fe.common.js
//= require fe/jquery.scrollTo-min.js
//= require fe/jquery.validate.pack.js

// used by answer sheets

(function($) {
  //debugger;
	$(function() {

		$(document).on('click', '.save_button', function() {
			$.fe.pageHandler.savePage($(this).closest('.answer-page'), true);
		});

		$(document).on('click', '.reference_send_invite', function() {
            var el = this;
			var data = $(el).closest('form').serializeArray();

			data.push({name: 'answer_sheet_type', value: answer_sheet_type});
      $.ajax({url: $(el).attr('href'), data: data, dataType: 'script',  type: 'POST',
                        beforeSend: function (xhr) {
                            $('body').trigger('ajax:loading', xhr);
                        },
                        complete: function (xhr) {
                            $('body').trigger('ajax:complete', xhr);
                        },
                        error: function (xhr, status, error) {
                            $('body').trigger('ajax:failure', [xhr, status, error]);
                        }
										});
			return false;
		});
		$(document).on('focus', 'textarea[maxlength]', function() {
			var max = parseInt($(this).attr('maxlength'));
			$(this).parent().find('.charsRemaining').html('You have ' + (max - $(this).val().length) + ' characters remaining');
		}).on('keyup', 'textarea[maxlength]', function(){
			var max = parseInt($(this).attr('maxlength'));
			if($(this).val().length > max){
				$(this).val($(this).val().substr(0, $(this).attr('maxlength')));
			}
			$(this).parent().find('.charsRemaining').html('You have ' + (max - $(this).val().length) + ' characters remaining');
		}).on('blur', 'textarea[maxlength]', function() {
			$(this).parent().find('.charsRemaining').html('');
		});
  });

	$.fe = {};
	$.fe.pageHandler = {
	  initialize : function(page) {
	    this.auto_save_frequency = 30;  // seconds
	    this.timer_id = null;
		  this.suspendLoad = false;

	    this.current_page = page;
			$('#' + page).data('form_data', this.captureForm($('#' + page)));
	    this.registerAutoSave();

	    this.page_validation = {};  // validation objects for each page
	    this.enableValidation(page);

	    // this.background_load = false;
	    // this.final_submission = false;
	  },

	  // swap to a different page
	  showPage : function(page) {
	    // hide the old
	    $('#' + this.current_page + '-li').removeClass('active');
	    $('#' + this.current_page).hide();

			// HACK: Need to clear the main error message when returning to the submit page
			//       It is very confusing to users to be there when they revisit the page
			if ((page=='submit_page') && ($('#submit_message')[0] != null)) $('#submit_message').hide();
			if ((page=='submit_page') && ($('#application_errors')[0] != null)) $('#application_errors').html('');

	    // show the new
			// $('#' + page + '-li').removeClass('incomplete');
			// $('#' + page + '-li').removeClass('valid');
			$('#' + page + '-li').addClass('active');
	    $('#' + page).show();
	    this.current_page = page;
	    this.registerAutoSave(page);
	    this.suspendLoad = false;
	    fixGridColumnWidths();
	  },

	  // callback onSuccess
	  pageLoaded : function(response) {
	    // var response = new String(transport.responseText);
	    var match = response.match(/<div id=\"(.*?)\"/i); // what did I just load? parse out the first div id
	    if( match != null )
	    {
	      var page = match[1];
	      $('#preview').append(response);
	      // if(this.background_load) $('#' + page).hide(); else
				$.fe.pageHandler.showPage(page);  // show after load, unless loading in background
				setUpJsHelpers();
	      $.fe.pageHandler.enableValidation(page);
				// $.fe.pageHandler.validatePage('#' + page);
				$('#' + page).data('form_data', $.fe.pageHandler.captureForm($('#' + page)));
	    }
			$('#page_ajax_spinner').hide();
			$('.reference_send_invite').button();
			updateTotals();
	  },

	  loadPage : function(page, url) {
	    if (!this.suspendLoad) {
				this.suspendLoad = true; // don't load a page if one is currently loading (prevent double-click behavior where two pages end up visible!)

				this.unregisterAutoSave();  // don't auto-save while loading/saving
			      // will register auto-save on new page once loaded/shown

				$.scrollTo('#main');

		    this.validatePage(this.current_page);   // mark current page as valid (or not) as we're leaving

		    this.savePage();

		    if( $.fe.pageHandler.isPageLoaded(page) && page.match('no_cache') == null )   // if already loaded (element exists) excluding pages that need reloading
		    {
		      $.fe.pageHandler.showPage(page);
					$('#page_ajax_spinner').hide();
		    }
		    else
		    {
					$.ajax({
             url: url,
             type: 'GET',
						 data: {'answer_sheet_type':answer_sheet_type},
						 success: $.fe.pageHandler.pageLoaded,
             error: function (xhr, status, error) {
                alert("There was a problem loading that page. We've been notified and will fix it as soon as possible. To work on other pages, please refresh the website.");
								document.location = document.location;
             },
             beforeSend: function (xhr) {
                 $('body').trigger('ajax:loading', xhr);
             },
             complete: function (xhr) {
                 $('body').trigger('ajax:complete', xhr);
             }
         });
		      // new Ajax.Request(url, {asynchronous:true, evalScripts:false, method:'get',
		      //     onSuccess:this.pageLoaded.bind(this)});
		    }
			}
	  },

	  // save form if any changes were made
	  savePage : function(page, force) {
			if (page == null) page = $('#' + this.current_page);
      // don't save more than once per second
      timeNow = new Date();
      if (typeof(lastSave) != "undefined" && lastSave && !force && (timeNow - lastSave < 1000)) {
        return true;
      }
      lastSave = timeNow;
      form_data = this.captureForm(page);
      if( form_data ) {
        if( page.data('form_data') == null || page.data('form_data').data !== form_data.data || force === true) {  // if any changes
          page.data('form_data', form_data);
          $.ajax({url: form_data.url, type: 'put', data: form_data.data,
                 beforeSend: function (xhr) {
                   $('#spinner_' + page.attr('id')).show();
                 },
                 complete: function (xhr) {
                   $('#spinner_' + page.attr('id')).hide();
                 },
                 error: function() {
                   page.data('form_data', null);    // on error, force save for next call to save
                   // WARNING: race conditions with load & show?
                   // sort of a mess if save fails while another page is already loading!!
                 }});
        }
      }
      // Update last saved stamp
    },

		savePages : function(force) {
			$('.answer-page').each(function() {$.fe.pageHandler.savePage($(this), force)})
		},

	  // setup a timer to auto-save (only one timer, for the page being viewed)
	  registerAutoSave: function(page) {
	    this.timer_id = setInterval(this.savePages, this.auto_save_frequency * 1000);
	  },

	  unregisterAutoSave: function() {
	    if( this.timer_id != null )
	    {
	      clearInterval(this.timer_id);
	      this.timer_id = null;
	    }
	  },

	  // serialize form data and extract url to post to
	  captureForm : function(page) {
	    form_el = $('#' + page.attr('id') + '-form');
	    if( form_el[0] == null ) return null;
			return {url: form_el.attr('action'), data: form_el.serialize() + '&answer_sheet_type=' + answer_sheet_type};
	  },

	  // enable form validation (when form is loaded)
	  enableValidation : function(page) {
	    $('#' + page + '-form').validate({onsubmit:false, focusInvalid:true, onfocusout: function(element) { this.element(element);}});
	    // $('#' + page + '-form').valid();
	  },

	  validatePage : function(page) {
			try {
			  var li = $('#' + page + '-li');
			  var form = $('#' + page + '-form');

		    valid = form.valid();
				// Move radio button errors up
				$('input[type=radio].error').closest('tr').addClass('error');
				$('.choice_field input[type=radio].error').removeClass('error')
					.closest('.choice_field')
					.addClass('error');
				$('div.yesno label.error').hide();

		    if(valid)  {
		      el.removeClass('incomplete');
				  el.addClass('complete');
		    } else {
				  el.removeClass('complete');
		      el.addClass('incomplete');
		    }
		    return valid;
			}
			catch(err) {

				// If the user clicks too quickly, sometimes the page element isn't properly defined yet.
				// If we don't catch the error, js stops execution. If we catch it, the user just has to click again.
			}
			$('page_ajax_spinner').hide();
	  },

  // callback when falls to 0 active Ajax requests
  completeAll : function()
  {
		$('#submit_button').attr('disabled', true)
		$('#submit_message').html('');
		$('#submit_message').hide();
		// validate all the pages
  	$('.page_link').each(function(index, page) {
			$.fe.pageHandler.validatePage($(page).attr('data-page-id'));
		});
		var all_valid = ($('#list-pages li.incomplete').length == 0);

		// Make sure any necessary payments are made
		var payments_made = $('.payment_question.required').length <= $('.payment').length

		if(  payments_made)
		{
		  this.savePage($('#' + $.fe.pageHandler.current_page));  // in case any input fields on submit_page

		  // submit the application
		  if($('#submit_to')[0] != null)
		  {
		    url = $('#submit_to').val();
			  // clear out pages array to force reload.  This enables "frozen" apps
			  //       immediately after submission - :onSuccess (for USCM which stays in the application vs. redirecting to the dashboard)
			  var curr = $.fe.pageHandler.current_page;
			  $.ajax({url: url, dataType:'script',
			 		data: {answer_sheet_type: answer_sheet_type},
					type:'post',
					beforeSend: function(xhr) {
          	$('body').trigger('ajax:loading', xhr);
					},
					success: function(xhr) {
						$('#list-pages a').each(function() {
						  if ($(this).attr('data-page-id') != curr) $('#' + $(this).attr('data-page-id')).remove();
						})
					},
					complete: function(xhr) {
            $('body').trigger('ajax:complete', xhr);
		  			var btn = $('#submit_button');
						if (btn) { btn.attr('disabled', false); }
					}
				});
		  }
		}
		else
		{
		  // some pages aren't valid
 	    $('#submit_message').html("Please make a payment");
		  $('#submit_message').show();

		  var btn = $('#submit_button'); if (btn) { btn.attr('disabled', false); }
		}
  },

    // is page loaded? (useful for toggling enabled state of questions)
    isPageLoaded : function(page)
    {
      return $('#' + page)[0] != null
    },

    checkConditional : function($element_li) {
      matchable_answers = String($element_li.data('conditional_answer')).split(',').map(function(s) { return s.trim(); })
      if ($element_li.hasClass('fe_choicefield') && $element_li.hasClass('yes-no')) {
        if ($(matchable_answers).filter([1, '1', true, 'true', 'yes']).length > 0) {
          matchable_answers = [1, '1', true, 'true', 'yes'];
        }
        vals = $([$element_li.find("input[type=radio]:checked").val()]);
      } else if ($element_li.hasClass('fe_choicefield') && $element_li.hasClass('checkbox')) {
        vals = $element_li.find("input[type=checkbox]:checked").map(function(i, el) { return $(el).val(); });
      } else {
        vals = $([$element_li.find("input:visible, select:visible").val()]);
      }
      match = $(matchable_answers).filter(vals).length > 0;

      switch ($element_li.data('conditional_type')) {
        case 'Fe::Element':
          if (match) {
            $("#element_" + $element_li.data('conditional_id')).show();
          } else {
            $("#element_" + $element_li.data('conditional_id')).hide();
          }
        case 'Fe::Page':
          li_id = "li#fe_application_" + $element_li.data('application_id') + '-fe_page_' + $element_li.data('conditional_id') + '-li';
          if (match) {
            $(li_id).show();
          } else {
            $(li_id).hide();
          }
      }
    }

  };

  $(document).on('click', "li.conditional input, li.conditional select", function() {
    $.fe.pageHandler.checkConditional($(this).closest('li'));
  });
  $(document).on('keyup', "li.conditional input, li.conditional select", function() { $(this).click(); });
  $(document).on('blug', "li.conditional input, li.conditional select", function() { $(this).click(); });
  $(document).on('change', "li.conditional select", function() { $(this).click(); });

})(jQuery);

$(function() {
	fixGridColumnWidths();
  setUpCalendars();
});

function updateTotal(id) {
  try {
    total = 0;
    $(".col_" + id).each(function(index, el) {
      total += Number($(el).val());
    });
    $('#total_' + id).val(total);
  } catch(e) {
  }
}

function submitToFrame(id, url)
{
  form = $('<form method="post" action="'+url+'.js" endtype="multipart/form-data"></form>')
  var csrf_token = $('meta[name=csrf-token]').attr('content'),
      csrf_param = $('meta[name=csrf-param]').attr('content'),
			dom_id = '#attachment_field_' + id,
			metadata_input = '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />',
			file_field = '<input type="file" name="answers['+ id + ']>';
	if ($(dom_id).val() == '')	return;
  form.hide()
      .append(metadata_input)
      .append(file_field)
      .appendTo('body');
	$(dom_id + "-spinner").show();
  form.submit();
	return false
}
<commit_msg>trigger a totalChanged when the total of a grid with total changes<commit_after>//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require fe/fe.common.js
//= require fe/jquery.scrollTo-min.js
//= require fe/jquery.validate.pack.js

// used by answer sheets

(function($) {
  //debugger;
	$(function() {

		$(document).on('click', '.save_button', function() {
			$.fe.pageHandler.savePage($(this).closest('.answer-page'), true);
		});

		$(document).on('click', '.reference_send_invite', function() {
            var el = this;
			var data = $(el).closest('form').serializeArray();

			data.push({name: 'answer_sheet_type', value: answer_sheet_type});
      $.ajax({url: $(el).attr('href'), data: data, dataType: 'script',  type: 'POST',
                        beforeSend: function (xhr) {
                            $('body').trigger('ajax:loading', xhr);
                        },
                        complete: function (xhr) {
                            $('body').trigger('ajax:complete', xhr);
                        },
                        error: function (xhr, status, error) {
                            $('body').trigger('ajax:failure', [xhr, status, error]);
                        }
										});
			return false;
		});
		$(document).on('focus', 'textarea[maxlength]', function() {
			var max = parseInt($(this).attr('maxlength'));
			$(this).parent().find('.charsRemaining').html('You have ' + (max - $(this).val().length) + ' characters remaining');
		}).on('keyup', 'textarea[maxlength]', function(){
			var max = parseInt($(this).attr('maxlength'));
			if($(this).val().length > max){
				$(this).val($(this).val().substr(0, $(this).attr('maxlength')));
			}
			$(this).parent().find('.charsRemaining').html('You have ' + (max - $(this).val().length) + ' characters remaining');
		}).on('blur', 'textarea[maxlength]', function() {
			$(this).parent().find('.charsRemaining').html('');
		});
  });

	$.fe = {};
	$.fe.pageHandler = {
	  initialize : function(page) {
	    this.auto_save_frequency = 30;  // seconds
	    this.timer_id = null;
		  this.suspendLoad = false;

	    this.current_page = page;
			$('#' + page).data('form_data', this.captureForm($('#' + page)));
	    this.registerAutoSave();

	    this.page_validation = {};  // validation objects for each page
	    this.enableValidation(page);

	    // this.background_load = false;
	    // this.final_submission = false;
	  },

	  // swap to a different page
	  showPage : function(page) {
	    // hide the old
	    $('#' + this.current_page + '-li').removeClass('active');
	    $('#' + this.current_page).hide();

			// HACK: Need to clear the main error message when returning to the submit page
			//       It is very confusing to users to be there when they revisit the page
			if ((page=='submit_page') && ($('#submit_message')[0] != null)) $('#submit_message').hide();
			if ((page=='submit_page') && ($('#application_errors')[0] != null)) $('#application_errors').html('');

	    // show the new
			// $('#' + page + '-li').removeClass('incomplete');
			// $('#' + page + '-li').removeClass('valid');
			$('#' + page + '-li').addClass('active');
	    $('#' + page).show();
	    this.current_page = page;
	    this.registerAutoSave(page);
	    this.suspendLoad = false;
	    fixGridColumnWidths();
	  },

	  // callback onSuccess
	  pageLoaded : function(response) {
	    // var response = new String(transport.responseText);
	    var match = response.match(/<div id=\"(.*?)\"/i); // what did I just load? parse out the first div id
	    if( match != null )
	    {
	      var page = match[1];
	      $('#preview').append(response);
	      // if(this.background_load) $('#' + page).hide(); else
				$.fe.pageHandler.showPage(page);  // show after load, unless loading in background
				setUpJsHelpers();
	      $.fe.pageHandler.enableValidation(page);
				// $.fe.pageHandler.validatePage('#' + page);
				$('#' + page).data('form_data', $.fe.pageHandler.captureForm($('#' + page)));
	    }
			$('#page_ajax_spinner').hide();
			$('.reference_send_invite').button();
			updateTotals();
	  },

	  loadPage : function(page, url) {
	    if (!this.suspendLoad) {
				this.suspendLoad = true; // don't load a page if one is currently loading (prevent double-click behavior where two pages end up visible!)

				this.unregisterAutoSave();  // don't auto-save while loading/saving
			      // will register auto-save on new page once loaded/shown

				$.scrollTo('#main');

		    this.validatePage(this.current_page);   // mark current page as valid (or not) as we're leaving

		    this.savePage();

		    if( $.fe.pageHandler.isPageLoaded(page) && page.match('no_cache') == null )   // if already loaded (element exists) excluding pages that need reloading
		    {
		      $.fe.pageHandler.showPage(page);
					$('#page_ajax_spinner').hide();
		    }
		    else
		    {
					$.ajax({
             url: url,
             type: 'GET',
						 data: {'answer_sheet_type':answer_sheet_type},
						 success: $.fe.pageHandler.pageLoaded,
             error: function (xhr, status, error) {
                alert("There was a problem loading that page. We've been notified and will fix it as soon as possible. To work on other pages, please refresh the website.");
								document.location = document.location;
             },
             beforeSend: function (xhr) {
                 $('body').trigger('ajax:loading', xhr);
             },
             complete: function (xhr) {
                 $('body').trigger('ajax:complete', xhr);
             }
         });
		      // new Ajax.Request(url, {asynchronous:true, evalScripts:false, method:'get',
		      //     onSuccess:this.pageLoaded.bind(this)});
		    }
			}
	  },

	  // save form if any changes were made
	  savePage : function(page, force) {
			if (page == null) page = $('#' + this.current_page);
      // don't save more than once per second
      timeNow = new Date();
      if (typeof(lastSave) != "undefined" && lastSave && !force && (timeNow - lastSave < 1000)) {
        return true;
      }
      lastSave = timeNow;
      form_data = this.captureForm(page);
      if( form_data ) {
        if( page.data('form_data') == null || page.data('form_data').data !== form_data.data || force === true) {  // if any changes
          page.data('form_data', form_data);
          $.ajax({url: form_data.url, type: 'put', data: form_data.data,
                 beforeSend: function (xhr) {
                   $('#spinner_' + page.attr('id')).show();
                 },
                 complete: function (xhr) {
                   $('#spinner_' + page.attr('id')).hide();
                 },
                 error: function() {
                   page.data('form_data', null);    // on error, force save for next call to save
                   // WARNING: race conditions with load & show?
                   // sort of a mess if save fails while another page is already loading!!
                 }});
        }
      }
      // Update last saved stamp
    },

		savePages : function(force) {
			$('.answer-page').each(function() {$.fe.pageHandler.savePage($(this), force)})
		},

	  // setup a timer to auto-save (only one timer, for the page being viewed)
	  registerAutoSave: function(page) {
	    this.timer_id = setInterval(this.savePages, this.auto_save_frequency * 1000);
	  },

	  unregisterAutoSave: function() {
	    if( this.timer_id != null )
	    {
	      clearInterval(this.timer_id);
	      this.timer_id = null;
	    }
	  },

	  // serialize form data and extract url to post to
	  captureForm : function(page) {
	    form_el = $('#' + page.attr('id') + '-form');
	    if( form_el[0] == null ) return null;
			return {url: form_el.attr('action'), data: form_el.serialize() + '&answer_sheet_type=' + answer_sheet_type};
	  },

	  // enable form validation (when form is loaded)
	  enableValidation : function(page) {
	    $('#' + page + '-form').validate({onsubmit:false, focusInvalid:true, onfocusout: function(element) { this.element(element);}});
	    // $('#' + page + '-form').valid();
	  },

	  validatePage : function(page) {
			try {
			  var li = $('#' + page + '-li');
			  var form = $('#' + page + '-form');

		    valid = form.valid();
				// Move radio button errors up
				$('input[type=radio].error').closest('tr').addClass('error');
				$('.choice_field input[type=radio].error').removeClass('error')
					.closest('.choice_field')
					.addClass('error');
				$('div.yesno label.error').hide();

		    if(valid)  {
		      el.removeClass('incomplete');
				  el.addClass('complete');
		    } else {
				  el.removeClass('complete');
		      el.addClass('incomplete');
		    }
		    return valid;
			}
			catch(err) {

				// If the user clicks too quickly, sometimes the page element isn't properly defined yet.
				// If we don't catch the error, js stops execution. If we catch it, the user just has to click again.
			}
			$('page_ajax_spinner').hide();
	  },

  // callback when falls to 0 active Ajax requests
  completeAll : function()
  {
		$('#submit_button').attr('disabled', true)
		$('#submit_message').html('');
		$('#submit_message').hide();
		// validate all the pages
  	$('.page_link').each(function(index, page) {
			$.fe.pageHandler.validatePage($(page).attr('data-page-id'));
		});
		var all_valid = ($('#list-pages li.incomplete').length == 0);

		// Make sure any necessary payments are made
		var payments_made = $('.payment_question.required').length <= $('.payment').length

		if(  payments_made)
		{
		  this.savePage($('#' + $.fe.pageHandler.current_page));  // in case any input fields on submit_page

		  // submit the application
		  if($('#submit_to')[0] != null)
		  {
		    url = $('#submit_to').val();
			  // clear out pages array to force reload.  This enables "frozen" apps
			  //       immediately after submission - :onSuccess (for USCM which stays in the application vs. redirecting to the dashboard)
			  var curr = $.fe.pageHandler.current_page;
			  $.ajax({url: url, dataType:'script',
			 		data: {answer_sheet_type: answer_sheet_type},
					type:'post',
					beforeSend: function(xhr) {
          	$('body').trigger('ajax:loading', xhr);
					},
					success: function(xhr) {
						$('#list-pages a').each(function() {
						  if ($(this).attr('data-page-id') != curr) $('#' + $(this).attr('data-page-id')).remove();
						})
					},
					complete: function(xhr) {
            $('body').trigger('ajax:complete', xhr);
		  			var btn = $('#submit_button');
						if (btn) { btn.attr('disabled', false); }
					}
				});
		  }
		}
		else
		{
		  // some pages aren't valid
 	    $('#submit_message').html("Please make a payment");
		  $('#submit_message').show();

		  var btn = $('#submit_button'); if (btn) { btn.attr('disabled', false); }
		}
  },

    // is page loaded? (useful for toggling enabled state of questions)
    isPageLoaded : function(page)
    {
      return $('#' + page)[0] != null
    },

    checkConditional : function($element_li) {
      matchable_answers = String($element_li.data('conditional_answer')).split(',').map(function(s) { return s.trim(); })
      if ($element_li.hasClass('fe_choicefield') && $element_li.hasClass('yes-no')) {
        if ($(matchable_answers).filter([1, '1', true, 'true', 'yes']).length > 0) {
          matchable_answers = [1, '1', true, 'true', 'yes'];
        }
        vals = $([$element_li.find("input[type=radio]:checked").val()]);
      } else if ($element_li.hasClass('fe_choicefield') && $element_li.hasClass('checkbox')) {
        vals = $element_li.find("input[type=checkbox]:checked").map(function(i, el) { return $(el).val(); });
      } else {
        vals = $([$element_li.find("input:visible, select:visible").val()]);
      }
      match = $(matchable_answers).filter(vals).length > 0;

      switch ($element_li.data('conditional_type')) {
        case 'Fe::Element':
          if (match) {
            $("#element_" + $element_li.data('conditional_id')).show();
          } else {
            $("#element_" + $element_li.data('conditional_id')).hide();
          }
        case 'Fe::Page':
          li_id = "li#fe_application_" + $element_li.data('application_id') + '-fe_page_' + $element_li.data('conditional_id') + '-li';
          if (match) {
            $(li_id).show();
          } else {
            $(li_id).hide();
          }
      }
    }

  };

  $(document).on('click', "li.conditional input, li.conditional select", function() {
    $.fe.pageHandler.checkConditional($(this).closest('li'));
  });
  $(document).on('keyup', "li.conditional input, li.conditional select", function() { $(this).click(); });
  $(document).on('blug', "li.conditional input, li.conditional select", function() { $(this).click(); });
  $(document).on('change', "li.conditional select", function() { $(this).click(); });

})(jQuery);

$(function() {
	fixGridColumnWidths();
  setUpCalendars();
});

function updateTotal(id) {
  try {
    total = 0;
    $(".col_" + id).each(function(index, el) {
      total += Number($(el).val());
    });
    $('#total_' + id).val(total).trigger('totalChanged');
  } catch(e) {
  }
}

function submitToFrame(id, url)
{
  form = $('<form method="post" action="'+url+'.js" endtype="multipart/form-data"></form>')
  var csrf_token = $('meta[name=csrf-token]').attr('content'),
      csrf_param = $('meta[name=csrf-param]').attr('content'),
			dom_id = '#attachment_field_' + id,
			metadata_input = '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />',
			file_field = '<input type="file" name="answers['+ id + ']>';
	if ($(dom_id).val() == '')	return;
  form.hide()
      .append(metadata_input)
      .append(file_field)
      .appendTo('body');
	$(dom_id + "-spinner").show();
  form.submit();
	return false
}
<|endoftext|>


<commit_before>'use strict';
let generator = require('yeoman-generator');

module.exports = generator.Base.extend({

  constructor: function() {
    generator.Base.apply(this, arguments);

    this.option('skip-install');
  },

  install: function() {

    if(!this.options['skip-install']) {
      this.installDependencies({ bower: false });
    }

    // Run the base react-webpack generator, then run the dispatcher
    this.composeWith(
      'react-webpack',
      {
        options: {
          'skip-install': this.options['skip-install']
        }
      },
      {
        local: require.resolve('generator-react-webpack'),
        link: 'strong'
      }
    ).on('end', () => {

      // Run the create root method
      this.composeWith('react-webpack-redux:root', {
        args: ['Root']
      });

      // Install redux and react bindings as requirement
      this.npmInstall(['redux', 'react-redux'], { 'save': true });

      // Rewrite the webpack version the the last know working beta version
      // It is left here in plain sight, to remind about the pain updating to
      // a master branch without checking for the actual version.
      //
      // TODO: throw this out as soon as the next stable version is released
      this.npmInstall(['webpack@2.1.0-beta.6'], { 'save-dev': true });
    });
  }
});
<commit_msg>Removed webpack related quick fix, since it is stable now.<commit_after>'use strict';
let generator = require('yeoman-generator');

module.exports = generator.Base.extend({

  constructor: function() {
    generator.Base.apply(this, arguments);

    this.option('skip-install');
  },

  install: function() {

    if(!this.options['skip-install']) {
      this.installDependencies({ bower: false });
    }

    // Run the base react-webpack generator, then run the dispatcher
    this.composeWith(
      'react-webpack',
      {
        options: {
          'skip-install': this.options['skip-install']
        }
      },
      {
        local: require.resolve('generator-react-webpack'),
        link: 'strong'
      }
    ).on('end', () => {

      // Run the create root method
      this.composeWith('react-webpack-redux:root', {
        args: ['Root']
      });

      // Install redux and react bindings as requirement
      this.npmInstall(['redux', 'react-redux'], { 'save': true });
    });
  }
});
<|endoftext|>


<commit_before>'use strict';
var yo = require('yeoman-generator'),
	chalk = require('chalk'),
	yosay = require('yosay'),
	mkdirp = require('mkdirp'),
	path = require('path'),
	config = require('./config.json');

////////////////////////////////////////////////////////////////////////////////////////////
// initializing - Your initialization methods (checking current project state, getting configs, etc)
// prompting - Where you prompt users for options (where you'd call this.prompt())
// configuring - Saving configurations and configure the project (creating .editorconfig files and other metadata files)
// default - If the method name doesn't match a priority, it will be pushed to this group.
// writing - Where you write the generator specific files (routes, controllers, etc)
// conflicts - Where conflicts are handled (used internally)
// install - Where installation are run (npm, bower)
// end - Called last, cleanup, say good bye, etc
///////////////////////////////////////////////////////////////////////////////////////////

module.exports = yo.generators.Base.extend({
	constructor: function (arg, options) {
		yo.generators.Base.apply(this, arguments);
		this.settings = config;
	},
	prompting: function () {
		var done = this.async();

		// Have Yeoman greet the user.
		this.log(yosay(
			'Welcome to the ' + chalk.red('frontend-incubator') + ' generator!'
		));

		var prompts = [{
			name: 'projectName',
			message: 'What is the name of your project?',
			default: path.basename(process.cwd())
		}, {
			name: 'projectVersion',
			message: 'What is version of your project?',
			default: '1.0.0'
		}, {
			name: 'es2015orLoose',
			message: 'Which babel do you want to use?',
			default: 'es2015-loose',
			type: 'list',
			choices: [{
				name: 'es2015-loose',
				value: 'es2015-loose'
			}, {
				name: 'es2015',
				value: 'es2015'
			}]
		}, {
			name: 'useDefaultConfig',
			message: 'Would you like to use the default incubator configuration?',
			default: true,
			type: 'confirm'
		}];

		//var extraPrompts = [{
		//	name: 'sourceRoot',
		//	message: 'What is the root of your sources?',
		//	default: this.settings.paths.src.root
		//}];

		this.prompt(prompts, function (props) {
			this.props = props;

			if (!props.useDefaultConfig) {
				console.log('This feature is not yet implemented. Using default instead');
				// @TODO: ask extra questions to the user here
				//var that = this;
				//this.prompt(extraPrompts, function (/*extraProps*/) {
				//that.extraProps = extraProps;
				done();
				//});
			} else {
				// To access props later use this.props.someOption;

				done();
			}
		}.bind(this));
	},

	writing: function () {

		this.fs.copyTpl(
			this.templatePath('package.json'),
			this.destinationPath('package.json'), {
				name: this.props.projectName,
				version: this.props.projectVersion
			}
		);

		this.fs.copyTpl(
			this.templatePath('config.json'),
			this.destinationPath('config.json'), {
				paths: this.settings.paths,
				esVersion: this.props.es2015orLoose
			}
		);

		this.fs.copyTpl(
			this.templatePath('README.md'),
			this.destinationPath('README.md'), {
				name: this.props.projectName,
				useDefaultConfig: this.props.useDefaultConfig
			}
		);

		var simpleCopyFiles = ['.editorconfig', '.gitattributes', '.gitignore', '.jshintrc', 'gulpfile.js', 'tasks.json'];
		for (var i = 0; i < simpleCopyFiles.length; i++) {
			this.fs.copyTpl(
				this.templatePath(simpleCopyFiles[i]),
				this.destinationPath(simpleCopyFiles[i])
			);
		}

		var paths = this.settings.paths.src,
			keep = '/.keep',
			keepText = 'remove this file when you\'ve added content to this folder';

		this.fs.write(paths.root + '/' + paths.asset.javascript + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.image + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.font + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.scss + keep, keepText);

		this.fs.write(paths.root + '/' + paths.prototype.template + keep, keepText);
		this.fs.write(paths.root + '/' + paths.prototype.data + keep, keepText);
		this.fs.write(paths.root + '/' + paths.prototype.webroot + keep, keepText);

		// @TODO issue 4
		var KSSDir = paths.root + '/' + paths.patternLibrary.root;
		this.bulkDirectory(KSSDir, KSSDir);
	},

	install: function () {
		//this.installDependencies({bower: false});
	}
});
<commit_msg>enable installation of dependencies<commit_after>'use strict';
var yo = require('yeoman-generator'),
	chalk = require('chalk'),
	yosay = require('yosay'),
	mkdirp = require('mkdirp'),
	path = require('path'),
	config = require('./config.json');

////////////////////////////////////////////////////////////////////////////////////////////
// initializing - Your initialization methods (checking current project state, getting configs, etc)
// prompting - Where you prompt users for options (where you'd call this.prompt())
// configuring - Saving configurations and configure the project (creating .editorconfig files and other metadata files)
// default - If the method name doesn't match a priority, it will be pushed to this group.
// writing - Where you write the generator specific files (routes, controllers, etc)
// conflicts - Where conflicts are handled (used internally)
// install - Where installation are run (npm, bower)
// end - Called last, cleanup, say good bye, etc
///////////////////////////////////////////////////////////////////////////////////////////

module.exports = yo.generators.Base.extend({
	constructor: function (arg, options) {
		yo.generators.Base.apply(this, arguments);
		this.settings = config;
	},
	prompting: function () {
		var done = this.async();

		// Have Yeoman greet the user.
		this.log(yosay(
			'Welcome to the ' + chalk.red('frontend-incubator') + ' generator!'
		));

		var prompts = [{
			name: 'projectName',
			message: 'What is the name of your project?',
			default: path.basename(process.cwd())
		}, {
			name: 'projectVersion',
			message: 'What is version of your project?',
			default: '1.0.0'
		}, {
			name: 'es2015orLoose',
			message: 'Which babel do you want to use?',
			default: 'es2015-loose',
			type: 'list',
			choices: [{
				name: 'es2015-loose',
				value: 'es2015-loose'
			}, {
				name: 'es2015',
				value: 'es2015'
			}]
		}, {
			name: 'useDefaultConfig',
			message: 'Would you like to use the default incubator configuration?',
			default: true,
			type: 'confirm'
		}];

		//var extraPrompts = [{
		//	name: 'sourceRoot',
		//	message: 'What is the root of your sources?',
		//	default: this.settings.paths.src.root
		//}];

		this.prompt(prompts, function (props) {
			this.props = props;

			if (!props.useDefaultConfig) {
				console.log('This feature is not yet implemented. Using default instead');
				// @TODO: ask extra questions to the user here
				//var that = this;
				//this.prompt(extraPrompts, function (/*extraProps*/) {
				//that.extraProps = extraProps;
				done();
				//});
			} else {
				// To access props later use this.props.someOption;

				done();
			}
		}.bind(this));
	},

	writing: function () {

		this.fs.copyTpl(
			this.templatePath('package.json'),
			this.destinationPath('package.json'), {
				name: this.props.projectName,
				version: this.props.projectVersion
			}
		);

		this.fs.copyTpl(
			this.templatePath('config.json'),
			this.destinationPath('config.json'), {
				paths: this.settings.paths,
				esVersion: this.props.es2015orLoose
			}
		);

		this.fs.copyTpl(
			this.templatePath('README.md'),
			this.destinationPath('README.md'), {
				name: this.props.projectName,
				useDefaultConfig: this.props.useDefaultConfig
			}
		);

		var simpleCopyFiles = ['.editorconfig', '.gitattributes', '.gitignore', '.jshintrc', 'gulpfile.js', 'tasks.json'];
		for (var i = 0; i < simpleCopyFiles.length; i++) {
			this.fs.copyTpl(
				this.templatePath(simpleCopyFiles[i]),
				this.destinationPath(simpleCopyFiles[i])
			);
		}

		var paths = this.settings.paths.src,
			keep = '/.keep',
			keepText = 'remove this file when you\'ve added content to this folder';

		this.fs.write(paths.root + '/' + paths.asset.javascript + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.image + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.font + keep, keepText);
		this.fs.write(paths.root + '/' + paths.asset.scss + keep, keepText);

		this.fs.write(paths.root + '/' + paths.prototype.template + keep, keepText);
		this.fs.write(paths.root + '/' + paths.prototype.data + keep, keepText);
		this.fs.write(paths.root + '/' + paths.prototype.webroot + keep, keepText);

		// @TODO issue 4
		var KSSDir = paths.root + '/' + paths.patternLibrary.root;
		this.bulkDirectory(KSSDir, KSSDir);
	},

	install: function () {
		this.installDependencies({bower: false});
	}
});
<|endoftext|>


<commit_before>'use strict';

var generators = require('yeoman-generator'),
  chalk = require('chalk'),
  mkdirp = require('mkdirp'),
  _ = require('lodash'),
  mainDependencies = require('./mainDeps.json'),
  gulpDependencies = require('./gulpDeps.json'),
  devDependencies = require('./devDeps.json');

module.exports = generators.Base.extend({
  constructor: function () {
    // Clear screen before running generator
    this.spawnCommand('clear', []);
    generators.Base.apply(this, arguments);

    // Store user-inputed appname
    this.argument('appname', { type: String, required: false });
    this.appname = this.app_name || this.appname;
  },

  initializing: function () {
    this.packageJson = this.fs.readJSON(this.destinationPath('package.json'),{});

    // Displays solid line or specified character as a visual divider
    this.separator = function (c) {
      var line = c ? chalk.yellow(_.repeat(c, 60)) : chalk.gray.underline(_.repeat(' ', 60));

      this.log('\n' + line);
    };

    // Helper function to check if dependency exists
    this.checkDeps = function (depsObject, whereToLook) {
      var pkg = this.packageJson,
        log = this.log;

      return _.chain(depsObject)
      // Checks if dependency exist
      .pick(function (value, name) {
        var hasModule = !_.has(pkg[whereToLook], name);

        if (hasModule) {
          log(chalk.cyan(name) + chalk.cyan.bold(' does not exist: ') + value);
        }
        return hasModule;
      })
      // Maps module to module@version (i.e `gulp` -> `gulp@3.8.11`)
      .mapKeys(function (moduleVerison, moduleName) {
        if (moduleVerison.match(/\*/)) {
          console.log('Get latest ' + moduleName);
          return moduleName + moduleVerison.replace('*','@latest');
        } else {
          return moduleName + moduleVerison.replace('^','@');
        }
      })
      // Returns the keys
      .keys()
      .value();
    };

    this.separator('.');
    this.log('\nWelcome to the ' + chalk.yellow.bold('Clay Instance') + ' generator!');
    this.separator('.');
  },

  prompting: function () {
    var done = this.async(),
      prompts = require('./prompts.js')(this.packageJson);

    this.prompt(prompts, function (props) {
      this.props = props;

      done();
    }.bind(this));

  },

  writing: {
    packageJson: function () {
      var currentPackageJson,
        msg,
        newPackageJson = {},
        packageJsonOrder = ['name','version','description','license','main','scripts','keywords','repository','dependencies','devDependencies'];

      // Sets a field in package.json if it doesn't exist
      this.setPackageJsonField = function (field) {
        if (!this.packageJson[field]) {
          this.packageJson[field] = this.props[field];
        } else {
          msg = _.endsWith(field, 's') ? ' exist: ' : ' exists: ';
          console.log(chalk.blue(field) + chalk.blue.bold(msg) + this.packageJson[field]);
        }
      };

      if (this.fs.exists(this.destinationPath('package.json'))) {
        this.log(chalk.yellow('\npackage.json') + ' found. Revising it.');
        this.packageJson = this.fs.readJSON(this.destinationPath('package.json'),{});

        this.setPackageJsonField('description');
        this.setPackageJsonField('keywords');

        currentPackageJson = this.packageJson;

        // Re-order fiels in pre-specified order
        _.each(packageJsonOrder, function (key) {
          newPackageJson[key] = currentPackageJson[key];
        });

        this.fs.writeJSON('package.json', newPackageJson);

      } else {
        this.log('No ' + chalk.red('package.json') + ' found. Creating one.');
        this.fs.copyTpl(
          this.templatePath('_package.json'),
          this.destinationPath('package.json'),
          {
            appname: this.appname,
            description: this.props.description,
            keywords: this.props.keywords,
            dependencies: JSON.stringify(_.extend(mainDependencies, gulpDependencies), null, 4),
            devDependencies: JSON.stringify(devDependencies, null, 4)
          }
        );
      }
      this.separator();
    },

    createFolders: function () {
      var done = this.async(),
        log = this.log,
        folders = ['sites', 'components', 'behaviors', 'validators'];

      if (folders) {
        log('Generating ' + chalk.blue(folders));
      }

      // Create app folders
      _.each(folders, function (name) {
        mkdirp(name, function (err) {
          if (err) {
            log(chalk.red(err.message, err.stack));
            process.exit(0);
          }

          done();
        });
      });

    },

    gulp: function () {
      this.fs.copy(
        this.templatePath('_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );
      this.log('Generating ' + chalk.yellow.bold('gulpfile.js'));

      // Creates gulp/tasks & gulp/utils
      this.directory(
        this.templatePath('gulp'),
        this.destinationPath('gulp')
      );
      this.log('Generating ' + chalk.yellow.bold('gulp folders.'));
    },

    tests: function () {
      // Creates tests/mocha.opts
      this.directory(
        this.templatePath('test'),
        this.destinationPath('test')
      );
      this.log('Generating ' + chalk.yellow.bold('test folder.'));
    },

    app: function () {
      this.fs.copyTpl(
        this.templatePath('README.md'),
        this.destinationPath('README.md'),
        {
          appname: this.appname
        }
      );

      this.fs.copy(
        this.templatePath('_app.js'),
        this.destinationPath('app.js')
      );
    },

    git: function () {
      this.fs.copy(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('eslintrc'),
        this.destinationPath('.eslintrc')
      );
      this.fs.copy(
        this.templatePath('_csscomb.json'),
        this.destinationPath('csscomb.json')
      );
    }
  },

  // Run npm install
  install: {
    app: function () {
      // Check if main dependencies exist
      var mainDependencies = require('./mainDeps.json');

      this.separator();
      mainDependencies = this.checkDeps(mainDependencies,'dependencies');
      this.npmInstall(mainDependencies, { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('main dependencies.'));
    },

    gulp: function () {
      // Check if gulp dependencies exist
      var gulpDependencies = require('./gulpDeps.json');

      this.separator();
      gulpDependencies = this.checkDeps(gulpDependencies, 'dependencies');
      this.npmInstall(gulpDependencies, { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('gulp dependencies.'));
    },

    devDeps: function () {
      // Check if devDependencies exist
      var devDependencies = require('./devDeps.json');

      this.separator();
      devDependencies = this.checkDeps(devDependencies, 'devDependencies');
      this.npmInstall(devDependencies, { 'saveDev': true });
      this.log('Installed ' + chalk.yellow.bold('dev dependencies.'));
    },

    main: function () {
      this.npmInstall();
      this.separator('x');
      this.log('\n\tYour app ' + chalk.yellow.bold(this.appname) + ' was created.');
      this.separator('x');
    }
  }
});
<commit_msg>App: Fixed error handling<commit_after>'use strict';

var generators = require('yeoman-generator'),
  chalk = require('chalk'),
  mkdirp = require('mkdirp'),
  _ = require('lodash'),
  mainDependencies = require('./mainDeps.json'),
  gulpDependencies = require('./gulpDeps.json'),
  devDependencies = require('./devDeps.json');

module.exports = generators.Base.extend({
  constructor: function () {
    // Clear screen before running generator
    this.spawnCommand('clear', []);
    generators.Base.apply(this, arguments);
    this.env.error(chalk.red.bold('You must provide a name for your clay instance!'));

    // Store user-inputed appname
    this.argument('appname', { type: String, required: true, desc:'Application name (Use only _ or -)', defaults:'example' });
    this.appname = this.appname;
  },

  initializing: function () {
    this.packageJson = this.fs.readJSON(this.destinationPath('package.json'),{});

    // Displays solid line or specified character as a visual divider
    this.separator = function (c) {
      var line = c ? chalk.yellow(_.repeat(c, 60)) : chalk.gray.underline(_.repeat(' ', 60));

      this.log('\n' + line);
    };

    // Helper function to check if dependency exists
    this.checkDeps = function (depsObject, whereToLook) {
      var pkg = this.packageJson,
        log = this.log;

      return _.chain(depsObject)
      // Checks if dependency exist
      .pick(function (value, name) {
        var hasModule = !_.has(pkg[whereToLook], name);

        if (hasModule) {
          log(chalk.cyan(name) + chalk.cyan.bold(' does not exist: ') + value);
        }
        return hasModule;
      })
      // Maps module to module@version (i.e `gulp` -> `gulp@3.8.11`)
      .mapKeys(function (moduleVerison, moduleName) {
        if (moduleVerison.match(/\*/)) {
          console.log('Get latest ' + moduleName);
          return moduleName + moduleVerison.replace('*','@latest');
        } else {
          return moduleName + moduleVerison.replace('^','@');
        }
      })
      // Returns the keys
      .keys()
      .value();
    };

    this.separator('.');
    this.log('\nWelcome to the ' + chalk.yellow.bold('Clay Instance') + ' generator!');
    this.separator('.');
  },

  prompting: function () {
    var done = this.async(),
      prompts = require('./prompts.js')(this.packageJson);

    this.prompt(prompts, function (props) {
      this.props = props;

      done();
    }.bind(this));

  },

  writing: {
    packageJson: function () {
      var currentPackageJson,
        msg,
        newPackageJson = {},
        packageJsonOrder = ['name','version','description','license','main','scripts','keywords','repository','dependencies','devDependencies'];

      // Sets a field in package.json if it doesn't exist
      this.setPackageJsonField = function (field) {
        if (!this.packageJson[field]) {
          this.packageJson[field] = this.props[field];
        } else {
          msg = _.endsWith(field, 's') ? ' exist: ' : ' exists: ';
          console.log(chalk.blue(field) + chalk.blue.bold(msg) + this.packageJson[field]);
        }
      };

      if (this.fs.exists(this.destinationPath('package.json'))) {
        this.log(chalk.yellow('\npackage.json') + ' found. Revising it.');
        this.packageJson = this.fs.readJSON(this.destinationPath('package.json'),{});

        this.setPackageJsonField('description');
        this.setPackageJsonField('keywords');

        currentPackageJson = this.packageJson;

        // Re-order fiels in pre-specified order
        _.each(packageJsonOrder, function (key) {
          newPackageJson[key] = currentPackageJson[key];
        });

        this.fs.writeJSON('package.json', newPackageJson);

      } else {
        this.log('No ' + chalk.red('package.json') + ' found. Creating one.');
        this.fs.copyTpl(
          this.templatePath('_package.json'),
          this.destinationPath('package.json'),
          {
            appname: this.appname,
            description: this.props.description,
            keywords: this.props.keywords,
            dependencies: JSON.stringify(_.extend(mainDependencies, gulpDependencies), null, 4),
            devDependencies: JSON.stringify(devDependencies, null, 4)
          }
        );
      }
      this.separator();
    },

    createFolders: function () {
      var done = this.async(),
        log = this.log,
        folders = ['sites', 'components', 'behaviors', 'validators'];

      if (folders) {
        log('Generating ' + chalk.blue(folders));
      }

      // Create app folders
      _.each(folders, function (name) {
        mkdirp(name, function (err) {
          if (err) {
            log(chalk.red(err.message, err.stack));
            process.exit(0);
          }

          done();
        });
      });

    },

    gulp: function () {
      this.fs.copy(
        this.templatePath('_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );
      this.log('Generating ' + chalk.yellow.bold('gulpfile.js'));

      // Creates gulp/tasks & gulp/utils
      this.directory(
        this.templatePath('gulp'),
        this.destinationPath('gulp')
      );
      this.log('Generating ' + chalk.yellow.bold('gulp folders.'));
    },

    tests: function () {
      // Creates tests/mocha.opts
      this.directory(
        this.templatePath('test'),
        this.destinationPath('test')
      );
      this.log('Generating ' + chalk.yellow.bold('test folder.'));
    },

    app: function () {
      this.fs.copyTpl(
        this.templatePath('README.md'),
        this.destinationPath('README.md'),
        {
          appname: this.appname
        }
      );

      this.fs.copy(
        this.templatePath('_app.js'),
        this.destinationPath('app.js')
      );
    },

    git: function () {
      this.fs.copy(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('eslintrc'),
        this.destinationPath('.eslintrc')
      );
      this.fs.copy(
        this.templatePath('_csscomb.json'),
        this.destinationPath('csscomb.json')
      );
    }
  },

  // Run npm install
  install: {
    app: function () {
      // Check if main dependencies exist
      var mainDependencies = require('./mainDeps.json');

      this.separator();
      mainDependencies = this.checkDeps(mainDependencies,'dependencies');
      this.npmInstall(mainDependencies, { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('main dependencies.'));
    },

    gulp: function () {
      // Check if gulp dependencies exist
      var gulpDependencies = require('./gulpDeps.json');

      this.separator();
      gulpDependencies = this.checkDeps(gulpDependencies, 'dependencies');
      this.npmInstall(gulpDependencies, { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('gulp dependencies.'));
    },

    devDeps: function () {
      // Check if devDependencies exist
      var devDependencies = require('./devDeps.json');

      this.separator();
      devDependencies = this.checkDeps(devDependencies, 'devDependencies');
      this.npmInstall(devDependencies, { 'saveDev': true });
      this.log('Installed ' + chalk.yellow.bold('dev dependencies.'));
    },

    main: function () {
      this.npmInstall();
      this.separator('x');
      this.log('\n\tYour app ' + chalk.yellow.bold(this.appname) + ' was created.');
      this.separator('x');
    }
  }
});
<|endoftext|>


<commit_before>'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');

module.exports = yeoman.generators.Base.extend({
    prompting: function () {
        var done = this.async();

        // Have Yeoman greet the user.
        this.log(yosay(
            'This is the awesome and amazing ' + chalk.red('WEAN-ready-to-install') + ' generator!'
        ));

        //Get array of inputs from the user
        var prompts = [{
                type: 'input',
                name: 'name',
                message: 'What would you love to name this project?',
                default: this.appname
        },
            {
                type: 'input',
                name: 'description',
                message: 'Please describe the project',
                default: "No description yet"
        },
            {
                type: 'input',
                name: 'repository',
                message: 'What is the project\'s GitHub repository?',
                default: "No repository yet"
        },
            {
                type: 'input',
                name: 'license',
                message: 'How would you love to license the project?',
                default: "MIT"
        }];

        this.prompt(prompts, function (props) {
            this.props = props;
            // To access props later use this.props.name;

            done();
        }.bind(this));
    },

    writing: {
        //Copy the confuguration files
        config: function () {
            this.fs.copyTpl(
                this.templatePath('_package.json'),
                this.destinationPath('package.json'), {
                    name: this.props.name,
                    description: this.props.description,
                    repository: this.props.repository,
                    license: this.props.license,
                }
            );
            this.fs.copyTpl(
                this.templatePath('_bower.json'),
                this.destinationPath('bower.json'), {
                    name: this.props.name
                }
            );
            this.fs.copy(
                this.templatePath('_gruntfile.js'),
                this.destinationPath('Gruntfile.js')
            );
        },

        //Copy the project files
        projectfiles: function () {
            this.fs.copy(
                this.templatePath('editorconfig'),
                this.destinationPath('.editorconfig')
            );
            this.fs.copy(
                this.templatePath('jshintrc'),
                this.destinationPath('.jshintrc')
            );
            this.fs.copy(
                this.templatePath('bowerrc'),
                this.destinationPath('.bowerrc')
            );
            this.fs.copyTpl(
                this.templatePath('_README.md'),
                this.destinationPath('README.md'), {
                    name: this.props.name,
                    description: this.props.description
                }
            );
        },

        //Copy the application files
        app: function () {
            // app/
            //////app.js
            this.fs.copy(
                this.templatePath('_app/_app.js'),
                this.destinationPath('app/app.js')
            );
            /////index.html
            this.fs.copyTpl(
                this.templatePath('_app/_index.html'),
                this.destinationPath('app/index.html'), {
                    name: this.props.name
                }
            );

            // app/routes/
            /////////////index.js
            this.fs.copy(
                this.templatePath('_app/_routes/_index.js'),
                this.destinationPath('app/routes/index.js')
            );

            // app/views/
            /////////////index.ejs
            this.fs.copyTpl(
                this.templatePath('_app/_views/_index.ejs'),
                this.destinationPath('app/views/index.ejs'), {
                    name: this.props.name
                }
            );

            // app/public/
            /////////////css
            /////////////////app.css
            this.fs.copy(
                this.templatePath('_app/_public/_css/_app.css'),
                this.destinationPath('app/public/css/app.css')
            );

            /////////////js
            /////////////////app.js
            this.fs.copy(
                this.templatePath('_app/_public/_js/_app.js'),
                this.destinationPath('app/public/js/app.js')
            );

            /////////////partials
            /////////////////header.html
            this.fs.copyTpl(
                this.templatePath('_app/_public/_partials/_header.html'),
                this.destinationPath('app/public/partials/header.html'), {
                    name: this.props.name
                }
            );
        },
    },

    install: function () {
        this.log('You now need, from the project root, to run "npm install" and "bower install" (maybe "sudo npm install" and "sudo bower install --allow-root")');
    }
});
<commit_msg>improvements of the final instructions and name update<commit_after>'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');

module.exports = yeoman.generators.Base.extend({
    prompting: function () {
        var done = this.async();

        // Have Yeoman greet the user.
        this.log(yosay(
            'This is the awesome and amazing ' + chalk.red('WEAN-EASY') + ' generator!'
        ));

        //Get array of inputs from the user
        var prompts = [{
                type: 'input',
                name: 'name',
                message: 'What would you love to name this project?',
                default: this.appname
        },
            {
                type: 'input',
                name: 'description',
                message: 'Please describe the project',
                default: "No description yet"
        },
            {
                type: 'input',
                name: 'repository',
                message: 'What is the project\'s GitHub repository?',
                default: "No repository yet"
        },
            {
                type: 'input',
                name: 'license',
                message: 'How would you love to license the project?',
                default: "MIT"
        }];

        this.prompt(prompts, function (props) {
            this.props = props;
            // To access props later use this.props.name;

            done();
        }.bind(this));
    },

    writing: {
        //Copy the confuguration files
        config: function () {
            this.fs.copyTpl(
                this.templatePath('_package.json'),
                this.destinationPath('package.json'), {
                    name: this.props.name,
                    description: this.props.description,
                    repository: this.props.repository,
                    license: this.props.license,
                }
            );
            this.fs.copyTpl(
                this.templatePath('_bower.json'),
                this.destinationPath('bower.json'), {
                    name: this.props.name
                }
            );
            this.fs.copy(
                this.templatePath('_gruntfile.js'),
                this.destinationPath('Gruntfile.js')
            );
        },

        //Copy the project files
        projectfiles: function () {
            this.fs.copy(
                this.templatePath('editorconfig'),
                this.destinationPath('.editorconfig')
            );
            this.fs.copy(
                this.templatePath('jshintrc'),
                this.destinationPath('.jshintrc')
            );
            this.fs.copy(
                this.templatePath('bowerrc'),
                this.destinationPath('.bowerrc')
            );
            this.fs.copyTpl(
                this.templatePath('_README.md'),
                this.destinationPath('README.md'), {
                    name: this.props.name,
                    description: this.props.description
                }
            );
        },

        //Copy the application files
        app: function () {
            // app/
            //////app.js
            this.fs.copy(
                this.templatePath('_app/_app.js'),
                this.destinationPath('app/app.js')
            );
            /////index.html
            this.fs.copyTpl(
                this.templatePath('_app/_index.html'),
                this.destinationPath('app/index.html'), {
                    name: this.props.name
                }
            );

            // app/routes/
            /////////////index.js
            this.fs.copy(
                this.templatePath('_app/_routes/_index.js'),
                this.destinationPath('app/routes/index.js')
            );

            // app/views/
            /////////////index.ejs
            this.fs.copyTpl(
                this.templatePath('_app/_views/_index.ejs'),
                this.destinationPath('app/views/index.ejs'), {
                    name: this.props.name
                }
            );

            // app/public/
            /////////////css
            /////////////////app.css
            this.fs.copy(
                this.templatePath('_app/_public/_css/_app.css'),
                this.destinationPath('app/public/css/app.css')
            );

            /////////////js
            /////////////////app.js
            this.fs.copy(
                this.templatePath('_app/_public/_js/_app.js'),
                this.destinationPath('app/public/js/app.js')
            );

            /////////////partials
            /////////////////header.html
            this.fs.copyTpl(
                this.templatePath('_app/_public/_partials/_header.html'),
                this.destinationPath('app/public/partials/header.html'), {
                    name: this.props.name
                }
            );
        },
    },

    install: function () {
        this.log('');
        this.log('IMPORTANT : HOW TO FINALIZE THE PROJECT INSTALLATION');
        this.log('You now need to install the dependencies. Just like in any NPM and Bower project.');
        this.log('Verify that you are in the project root folder.');
        this.log('If you have no sudo/root type of problem you can directly run '+chalk.red('npm install')+' and '+chalk.red('bower install'));
        this.log('If you have sudo/root errors (like for Mac OS X users) you should run '+chalk.red('sudo npm install')+' and '+chalk.red('sudo bower install --allow-root'));
    }
});
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var _firefox_ReaderMode = {
    // If this is http or https content, and not an index page, then try to run Readability. If anything
    // fails, the app will never be notified and we don't show the button. That is ok for now since there
    // is no error feedback possible anyway.

    readabilityResult: null,

    checkReadability: function() {
        if ((document.location.protocol === "http:" || document.location.protocol === "https:") && document.location.pathname !== "/") {
            // Short circuit in case we already ran Readability. This mostly happens when going
            // back/forward: the page will be cached and the result will still be there.
            if (_firefox_ReaderMode.readabilityResult && _firefox_ReaderMode.readabilityResult.content) {
                webkit.messageHandlers.readerModeMessageHandler.postMessage("Available");
            } else {
                var uri = {
                    spec: document.location.href,
                    host: document.location.host,
                    prePath: document.location.protocol + "//" + document.location.host, // TODO This is incomplete, needs username/password and port
                    scheme: document.location.protocol.substr(0, document.location.protocol.indexOf(":")),
                    pathBase: document.location.protocol + "//" + document.location.host + location.pathname.substr(0, location.pathname.lastIndexOf("/") + 1)
                }
                var readability = new Readability(uri, document.cloneNode(true));
                _firefox_ReaderMode.readabilityResult = readability.parse();
                webkit.messageHandlers.readerModeMessageHandler.postMessage(_firefox_ReaderMode.readabilityResult !== null ? "Available" : "Unavailable");
            }
        } else if (document.location.protocol === "about:" && document.location.pathname === "reader") {
            webkit.messageHandlers.readerModeMessageHandler.postMessage("Active");
        } else {
            webkit.messageHandlers.readerModeMessageHandler.postMessage("Unavailable");
        }
    },

    // Readerize the document. Since we did the actual readerization already in checkReadability, we
    // can simply return the results we already have.

    readerize: function() {
        return _firefox_ReaderMode.readabilityResult;
    },

    // TODO The following code only makes sense in about:reader context. It may be a good idea to move
    //   it out of this file and into for example a Reader.js.

    currentStyle: null,

    setStyle: function(style) {
        // Configure the theme (light, dark)
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove(_firefox_ReaderMode.currentStyle.theme);
        }
        document.body.classList.add(style.theme);

        // Configure the font size (1-5)
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove("font-size" + _firefox_ReaderMode.currentStyle.fontSize);
        }
        document.body.classList.add("font-size" + style.fontSize);

        // Configure the font type
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove(_firefox_ReaderMode.currentStyle.fontType);
        }
        document.body.classList.add(style.fontType);

        // Remember the style
        _firefox_ReaderMode.currentStyle = style;
    },

    _BLOCK_IMAGES_SELECTOR: ".content p > img:only-child, " +
        ".content p > a:only-child > img:only-child, " +
        ".content .wp-caption img, " +
        ".content figure img",

    updateImageMargins: function() {
        var contentElement = document.getElementById('reader-content');

        var windowWidth = window.innerWidth;
        var contentWidth = contentElement.offsetWidth;
        var maxWidthStyle = windowWidth + "px !important";

        var setImageMargins = function(img) {
            if (!img._originalWidth) {
                img._originalWidth = img.offsetWidth;
            }

            var imgWidth = img._originalWidth;

            // If the image is taking more than half of the screen, just make
            // it fill edge-to-edge.
            if (imgWidth < contentWidth && imgWidth > windowWidth * 0.55) {
                imgWidth = windowWidth;
            }

            var sideMargin = Math.max((contentWidth - windowWidth) / 2, (contentWidth - imgWidth) / 2);

            var imageStyle = sideMargin + "px !important";
            var widthStyle = imgWidth + "px !important";

            var cssText = "max-width: " + maxWidthStyle + ";" +
                "width: " + widthStyle + ";" +
                "margin-left: " + imageStyle + ";" +
                "margin-right: " + imageStyle + ";";

            img.style.cssText = cssText;
        }

        var imgs = document.querySelectorAll(_firefox_ReaderMode._BLOCK_IMAGES_SELECTOR);
        for (var i = imgs.length; --i >= 0;) {
            var img = imgs[i];
            if (img.width > 0) {
                setImageMargins(img);
            } else {
                img.onload = function() {
                    setImageMargins(img);
                }
            }
        }
    },

    // Loop over the style sheets, find all the the @font-face declarations and fix the
    // relative src attributes so that they point to our embedded web server.
    fixFontFaces: function(webServerBase) {
        for (var i = 0; i < document.styleSheets.length; i++) {
            var sheet = document.styleSheets[i];
            for (var j = 0; j < sheet.cssRules.length; j++) {
                var rule = sheet.cssRules[j];
                if (rule.type === 5 && rule.style && rule.style.src) { // TODO: CSSFontFaceRule == 5 - No symbol for this? Or better check?
                    var matches = rule.style.src.match(/^url\(((?:Charis|FiraSans).*\.ttf)\)$/);
                    if (matches) {
                        rule.style.src = "url(" + webServerBase + "/fonts/" + matches[1] + ")";
                    }
                }
            }
        }
    },

    showContent: function() {
        // Make the reader visible
        var messageElement = document.getElementById('reader-message');
        messageElement.style.display = "none";
        var headerElement = document.getElementById('reader-header');
        headerElement.style.display = "block"
        var contentElement = document.getElementById('reader-content');
        contentElement.style.display = "block";
    },

    configureReader: function() {
        // Fix the @font-face declarations and turn their url into an absolute one, pointing to our
        // embedded web server.
        _firefox_ReaderMode.fixFontFaces(_firefox_ReaderPage.webServerBase);

        // Configure the reader with the initial style that was injected in the page.
        _firefox_ReaderMode.setStyle(_firefox_ReaderPage.style);

        // The order here is important. Because updateImageMargins depends on contentElement.offsetWidth which
        // will not be set until contentElement is visible. If this leads to annoying content reflowing then we
        // need to look at an alternative way to do this.
        _firefox_ReaderMode.showContent();
        _firefox_ReaderMode.updateImageMargins();
    }
};

window.addEventListener('load', function(event) {
    // If this is an about:reader page that we are loading, apply the initial style to the page.
    if (document.location.protocol === "about:" && document.location.pathname === "reader") {
        _firefox_ReaderMode.configureReader();
    }
});

window.addEventListener('pageshow', function(event) {
    _firefox_ReaderMode.checkReadability();
});
<commit_msg>Serialize and parse document instead of cloning the document node<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var _firefox_ReaderMode = {
    // If this is http or https content, and not an index page, then try to run Readability. If anything
    // fails, the app will never be notified and we don't show the button. That is ok for now since there
    // is no error feedback possible anyway.

    readabilityResult: null,

    checkReadability: function() {
        if ((document.location.protocol === "http:" || document.location.protocol === "https:") && document.location.pathname !== "/") {
            // Short circuit in case we already ran Readability. This mostly happens when going
            // back/forward: the page will be cached and the result will still be there.
            if (_firefox_ReaderMode.readabilityResult && _firefox_ReaderMode.readabilityResult.content) {
                webkit.messageHandlers.readerModeMessageHandler.postMessage("Available");
            } else {
                var uri = {
                    spec: document.location.href,
                    host: document.location.host,
                    prePath: document.location.protocol + "//" + document.location.host, // TODO This is incomplete, needs username/password and port
                    scheme: document.location.protocol.substr(0, document.location.protocol.indexOf(":")),
                    pathBase: document.location.protocol + "//" + document.location.host + location.pathname.substr(0, location.pathname.lastIndexOf("/") + 1)
                }

                // document.cloneNode() can cause the webview to break (bug 1128774).
                // Serialize and then parse the document instead.
                var docStr = new XMLSerializer().serializeToString(document);
                var doc = new DOMParser().parseFromString(docStr, "text/html");
                var readability = new Readability(uri, doc);
                _firefox_ReaderMode.readabilityResult = readability.parse();
                webkit.messageHandlers.readerModeMessageHandler.postMessage(_firefox_ReaderMode.readabilityResult !== null ? "Available" : "Unavailable");
            }
        } else if (document.location.protocol === "about:" && document.location.pathname === "reader") {
            webkit.messageHandlers.readerModeMessageHandler.postMessage("Active");
        } else {
            webkit.messageHandlers.readerModeMessageHandler.postMessage("Unavailable");
        }
    },

    // Readerize the document. Since we did the actual readerization already in checkReadability, we
    // can simply return the results we already have.

    readerize: function() {
        return _firefox_ReaderMode.readabilityResult;
    },

    // TODO The following code only makes sense in about:reader context. It may be a good idea to move
    //   it out of this file and into for example a Reader.js.

    currentStyle: null,

    setStyle: function(style) {
        // Configure the theme (light, dark)
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove(_firefox_ReaderMode.currentStyle.theme);
        }
        document.body.classList.add(style.theme);

        // Configure the font size (1-5)
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove("font-size" + _firefox_ReaderMode.currentStyle.fontSize);
        }
        document.body.classList.add("font-size" + style.fontSize);

        // Configure the font type
        if (_firefox_ReaderMode.currentStyle != null) {
            document.body.classList.remove(_firefox_ReaderMode.currentStyle.fontType);
        }
        document.body.classList.add(style.fontType);

        // Remember the style
        _firefox_ReaderMode.currentStyle = style;
    },

    _BLOCK_IMAGES_SELECTOR: ".content p > img:only-child, " +
        ".content p > a:only-child > img:only-child, " +
        ".content .wp-caption img, " +
        ".content figure img",

    updateImageMargins: function() {
        var contentElement = document.getElementById('reader-content');

        var windowWidth = window.innerWidth;
        var contentWidth = contentElement.offsetWidth;
        var maxWidthStyle = windowWidth + "px !important";

        var setImageMargins = function(img) {
            if (!img._originalWidth) {
                img._originalWidth = img.offsetWidth;
            }

            var imgWidth = img._originalWidth;

            // If the image is taking more than half of the screen, just make
            // it fill edge-to-edge.
            if (imgWidth < contentWidth && imgWidth > windowWidth * 0.55) {
                imgWidth = windowWidth;
            }

            var sideMargin = Math.max((contentWidth - windowWidth) / 2, (contentWidth - imgWidth) / 2);

            var imageStyle = sideMargin + "px !important";
            var widthStyle = imgWidth + "px !important";

            var cssText = "max-width: " + maxWidthStyle + ";" +
                "width: " + widthStyle + ";" +
                "margin-left: " + imageStyle + ";" +
                "margin-right: " + imageStyle + ";";

            img.style.cssText = cssText;
        }

        var imgs = document.querySelectorAll(_firefox_ReaderMode._BLOCK_IMAGES_SELECTOR);
        for (var i = imgs.length; --i >= 0;) {
            var img = imgs[i];
            if (img.width > 0) {
                setImageMargins(img);
            } else {
                img.onload = function() {
                    setImageMargins(img);
                }
            }
        }
    },

    // Loop over the style sheets, find all the the @font-face declarations and fix the
    // relative src attributes so that they point to our embedded web server.
    fixFontFaces: function(webServerBase) {
        for (var i = 0; i < document.styleSheets.length; i++) {
            var sheet = document.styleSheets[i];
            for (var j = 0; j < sheet.cssRules.length; j++) {
                var rule = sheet.cssRules[j];
                if (rule.type === 5 && rule.style && rule.style.src) { // TODO: CSSFontFaceRule == 5 - No symbol for this? Or better check?
                    var matches = rule.style.src.match(/^url\(((?:Charis|FiraSans).*\.ttf)\)$/);
                    if (matches) {
                        rule.style.src = "url(" + webServerBase + "/fonts/" + matches[1] + ")";
                    }
                }
            }
        }
    },

    showContent: function() {
        // Make the reader visible
        var messageElement = document.getElementById('reader-message');
        messageElement.style.display = "none";
        var headerElement = document.getElementById('reader-header');
        headerElement.style.display = "block"
        var contentElement = document.getElementById('reader-content');
        contentElement.style.display = "block";
    },

    configureReader: function() {
        // Fix the @font-face declarations and turn their url into an absolute one, pointing to our
        // embedded web server.
        _firefox_ReaderMode.fixFontFaces(_firefox_ReaderPage.webServerBase);

        // Configure the reader with the initial style that was injected in the page.
        _firefox_ReaderMode.setStyle(_firefox_ReaderPage.style);

        // The order here is important. Because updateImageMargins depends on contentElement.offsetWidth which
        // will not be set until contentElement is visible. If this leads to annoying content reflowing then we
        // need to look at an alternative way to do this.
        _firefox_ReaderMode.showContent();
        _firefox_ReaderMode.updateImageMargins();
    }
};

window.addEventListener('load', function(event) {
    // If this is an about:reader page that we are loading, apply the initial style to the page.
    if (document.location.protocol === "about:" && document.location.pathname === "reader") {
        _firefox_ReaderMode.configureReader();
    }
});

window.addEventListener('pageshow', function(event) {
    _firefox_ReaderMode.checkReadability();
});
<|endoftext|>


<commit_before>'use strict';

var generators = require('yeoman-generator'),
  chalk = require('chalk'),
  mkdirp = require('mkdirp'),
  _ = require('lodash');

module.exports = generators.Base.extend({
  constructor: function () {
    generators.Base.apply(this, arguments);
    this.log('Welcome to the ' + chalk.yellow.bold('Clay Instance') + ' generator!');

    // Store user-inputed appname
    this.argument('appname', { type: String, required: false });
    this.appname = this.app_name || this.appname;
  },

  initializing: function () {
    this.packageJson = this.fs.readJSON(this.destinationPath('package.json'), {});
  },

  prompting: function () {
    var done = this.async(),
      prompts = require('./prompts.js')(this.packageJson);

    this.prompt(prompts, function (props) {
      this.props = props;

      done();
    }.bind(this));

  },

  writing: {
    packageJson: function () {
      var currentPackageJson,
        newPackageJson = {},
        packageJsonOrder = ['name','version','description','license','main','scripts','keywords','repository','dependencies','devDependencies'];

      // Sets a field in package.json if it doesn't exist
      this.setPackageJsonField = function (field) {
        if (!this.packageJson[field]) {
          this.packageJson[field] = this.props[field];
        } else {
          console.log(chalk.blue(field) + chalk.blue.bold(' exists: ') + this.packageJson[field]);
        }
      };

      if (this.fs.exists(this.destinationPath('package.json'))) {
        this.log(chalk.yellow('package.json') + ' found. Revising it.');
        this.packageJson = this.fs.readJSON(this.destinationPath('package.json'), {});

        this.setPackageJsonField('description');
        this.setPackageJsonField('keywords');

        currentPackageJson = this.packageJson;

        // Re-order fiels in pre-specified order
        _.each(packageJsonOrder, function (key) {
          newPackageJson[key] = currentPackageJson[key];
        });

        this.fs.writeJSON('package.json', newPackageJson);

      } else {
        this.log('No ' + chalk.red('package.json') + ' found. Creating one.');
        this.fs.copyTpl(
          this.templatePath('_package.json'),
          this.destinationPath('package.json'),
          {
            appname: this.appname,
            description: this.props.description,
            keywords: this.props.keywords
          }
        );
      }
    },

    createFolders: function () {
      var done = this.async(),
        log = this.log,
        folders = ['sites', 'components', 'behaviors', 'validators'];

      // Create app folders
      _.each(folders, function (name) {
        mkdirp(name, function (err) {
          if (err) {
            log(chalk.red(err.message, err.stack));
            process.exit(0);
          }

          done();
        });
      });
    },

    gulp: function () {
      this.fs.copy(
        this.templatePath('_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );
      this.log('Generating ' + chalk.yellow.bold('gulpfile.js'));

      // Creates gulp/tasks & gulp/utils
      this.directory(
        this.templatePath('gulp'),
        this.destinationPath('gulp')
      );
      this.log('Generating ' + chalk.yellow.bold('gulp folders.'));
    },

    app: function () {
      this.fs.copyTpl(
        this.templatePath('README.md'),
        this.destinationPath('README.md'),
        {
          appname: this.appname
        }
      );

      this.fs.copy(
        this.templatePath('_app.js'),
        this.destinationPath('app.js')
      );
    },

    git: function () {
      this.fs.copy(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('eslintrc'),
        this.destinationPath('.eslintrc')
      );
      this.fs.copy(
        this.templatePath('_csscomb.json'),
        this.destinationPath('csscomb.json')
      );
    }
  },

  // Run npm install
  install: {
    gulp: function () {
      var gulpDependencies = require('./gulpdeps.json');

      // Maps module to module@version (i.e `gulp` -> `gulp@3.8.11`)
      gulpDependencies =  _.mapKeys(gulpDependencies, function (moduleVerison, moduleName) {
        return moduleName + moduleVerison.replace('\^','@');
      });

      this.npmInstall(_.keys(gulpDependencies), { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('gulp dependencies.'));
    },

    main: function () {
      this.npmInstall();
      this.log('Your app ' + chalk.yellow.bold(this.appname) + ' was created.');
    }
  }
});
<commit_msg>App: Directory - Added logic to use prompts for folders<commit_after>'use strict';

var generators = require('yeoman-generator'),
  chalk = require('chalk'),
  mkdirp = require('mkdirp'),
  _ = require('lodash');

module.exports = generators.Base.extend({
  constructor: function () {
    generators.Base.apply(this, arguments);
    this.log('Welcome to the ' + chalk.yellow.bold('Clay Instance') + ' generator!');

    // Store user-inputed appname
    this.argument('appname', { type: String, required: false });
    this.appname = this.app_name || this.appname;
  },

  initializing: function () {
    this.packageJson = this.fs.readJSON(this.destinationPath('package.json'), {});
  },

  prompting: function () {
    var done = this.async(),
      prompts = require('./prompts.js')(this.packageJson);

    this.prompt(prompts, function (props) {
      this.props = props;

      done();
    }.bind(this));

  },

  writing: {
    packageJson: function () {
      var currentPackageJson,
        newPackageJson = {},
        packageJsonOrder = ['name','version','description','license','main','scripts','keywords','repository','dependencies','devDependencies'];

      // Sets a field in package.json if it doesn't exist
      this.setPackageJsonField = function (field) {
        if (!this.packageJson[field]) {
          this.packageJson[field] = this.props[field];
        } else {
          console.log(chalk.blue(field) + chalk.blue.bold(' exists: ') + this.packageJson[field]);
        }
      };

      if (this.fs.exists(this.destinationPath('package.json'))) {
        this.log(chalk.yellow('package.json') + ' found. Revising it.');
        this.packageJson = this.fs.readJSON(this.destinationPath('package.json'), {});

        this.setPackageJsonField('description');
        this.setPackageJsonField('keywords');

        currentPackageJson = this.packageJson;

        // Re-order fiels in pre-specified order
        _.each(packageJsonOrder, function (key) {
          newPackageJson[key] = currentPackageJson[key];
        });

        this.fs.writeJSON('package.json', newPackageJson);

      } else {
        this.log('No ' + chalk.red('package.json') + ' found. Creating one.');
        this.fs.copyTpl(
          this.templatePath('_package.json'),
          this.destinationPath('package.json'),
          {
            appname: this.appname,
            description: this.props.description,
            keywords: this.props.keywords
          }
        );
      }
    },

    createFolders: function () {
      var done = this.async(),
        log = this.log,
        folders = this.props.folders;

      log('Generating ' + chalk.blue(folders));

      // Create app folders
      _.each(folders, function (name) {
        mkdirp(name, function (err) {
          if (err) {
            log(chalk.red(err.message, err.stack));
            process.exit(0);
          }

          done();
        });
      });
    },

    gulp: function () {
      this.fs.copy(
        this.templatePath('_gulpfile.js'),
        this.destinationPath('gulpfile.js')
      );
      this.log('Generating ' + chalk.yellow.bold('gulpfile.js'));

      // Creates gulp/tasks & gulp/utils
      this.directory(
        this.templatePath('gulp'),
        this.destinationPath('gulp')
      );
      this.log('Generating ' + chalk.yellow.bold('gulp folders.'));
    },

    app: function () {
      this.fs.copyTpl(
        this.templatePath('README.md'),
        this.destinationPath('README.md'),
        {
          appname: this.appname
        }
      );

      this.fs.copy(
        this.templatePath('_app.js'),
        this.destinationPath('app.js')
      );
    },

    git: function () {
      this.fs.copy(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('eslintrc'),
        this.destinationPath('.eslintrc')
      );
      this.fs.copy(
        this.templatePath('_csscomb.json'),
        this.destinationPath('csscomb.json')
      );
    }
  },

  // Run npm install
  install: {
    gulp: function () {
      var gulpDependencies = require('./gulpdeps.json');

      // Maps module to module@version (i.e `gulp` -> `gulp@3.8.11`)
      gulpDependencies =  _.mapKeys(gulpDependencies, function (moduleVerison, moduleName) {
        return moduleName + moduleVerison.replace('\^','@');
      });

      this.npmInstall(_.keys(gulpDependencies), { 'save': true });
      this.log('Installed ' + chalk.yellow.bold('gulp dependencies.'));
    },

    main: function () {
      this.npmInstall();
      this.log('Your app ' + chalk.yellow.bold(this.appname) + ' was created.');
    }
  }
});
<|endoftext|>


<commit_before>import AWS from 'aws-sdk'
import InputValidator from './InputValidator'
import EmailFormatter from './EmailFormatter'

AWS.config.region = 'us-east-1'

exports.handler = function(event, context) {
  // Validate Inputs
  let errors = InputValidator.validate(event)

  if (errors) {
    context.fail(errors)
    return
  }

  // TODO Add task to SQS and invoke ECS container

  // Send Email
  let {emailText, subject} = EmailFormatter.format(event),
    ses = new AWS.SES()

  ses.sendEmail({
    Source: 'contact@moocfetcher.com',
    Destination: {
      ToAddresses: [event.email]
    },
    Message: {
      Subject: {
        Data: subject,
        Charset: 'UTF-8'
      },
      Body: {
        Text: {
          Data: emailText,
          Charset: 'UTF-8'
        }
      }
    }
  }, function(err) {
    if (err) {
      context.fail(err)
      return
    }
    context.succeed()
  })
}
<commit_msg>Add friendly name to email-address<commit_after>import AWS from 'aws-sdk'
import InputValidator from './InputValidator'
import EmailFormatter from './EmailFormatter'

AWS.config.region = 'us-east-1'

exports.handler = function(event, context) {
  // Validate Inputs
  let errors = InputValidator.validate(event)

  if (errors) {
    context.fail(errors)
    return
  }

  // TODO Add task to SQS and invoke ECS container

  // Send Email
  let {emailText, subject} = EmailFormatter.format(event),
    ses = new AWS.SES()

  ses.sendEmail({
    Source: 'MOOC Fetcher Support <contact@moocfetcher.com>',
    Destination: {
      ToAddresses: [event.email]
    },
    Message: {
      Subject: {
        Data: subject,
        Charset: 'UTF-8'
      },
      Body: {
        Text: {
          Data: emailText,
          Charset: 'UTF-8'
        }
      }
    }
  }, function(err) {
    if (err) {
      context.fail(err)
      return
    }
    context.succeed()
  })
}
<|endoftext|>