<commit_before>define([
  'jquery',
  'handlebars',
  'backbone',
  'text!static/templates/contactUsNewsletter.handlebars'
], function($, Handlebars, Backbone, tplNewsletter) {

  'use strict';

  var topics = {
    'report-a-bug-or-error-on-gfw': {
      name: 'Report a bug or error on GFW',
      placeholder: 'Explain the bug or error and tell us where on the website you encountered it. What browser (e.g., Chrome version 50.0.2661.94 m) and operating system (e.g., Windows 8.1) do you use?',
    },
    'provide-feedback': {
      name: 'Provide feedback',
      placeholder: 'Tell us about your experience with GFW! Examples: How can we improve GFW? Why did you visit GFW? How do you use GFW? If and how is the information provided by GFW useful for your work? Are there any additional features and/or data that would be useful?  Was anything confusing or difficult to use?  Etc...',
    },
    'media-request': {
      name: 'Media request',
      placeholder: 'How can we help you?',
    },
    'data-related-inquiry': {
      name: 'Data-related inquiry or suggestion',
      placeholder: 'How can we help you?',
    },
    'gfw-commodities-inquiry': {
      name: 'GFW Commodities inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-fires-inquiry': {
      name: 'GFW Fires inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-climate-inquiry': {
      name: 'GFW Climate inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-water-inquiry': {
      name: 'GFW Water inquiry',
      placeholder: 'How can we help you?',
    },
    'general-inquiry': {
      name: 'General inquiry',
      placeholder: 'How can we help you?',
    },
  }

  var constraints = {
    'email': {
      presence: true,
      email: true
    },
    'topic': {
      presence: true
    },
    'message': {
      presence: true
    }
  };

  var ContacUsView = Backbone.View.extend({

    el: '#contact_us',

    events: {
      'click .js-btn-submit': 'actionSubmit',
      'click .js-newsletter-sign-up': 'onNewsletterSignup',
      'change input, textarea, select': 'changeInput',
      'change #contact-topic': 'changeTopic'
    },

    templateNewsletter: Handlebars.compile(tplNewsletter),

    initialize: function() {
      this.$spinner = this.$el.find('.m-spinner');
      this.$form = this.$el.find('#contact-form');
      this.$step = this.$el.find('.step');
      this.$stepBtn = this.$el.find('.step-btn');
      this.$contactMessage = this.$el.find('#contact-message');
      this.$body = $('html, body');
      this.$container = $('.content-static');
      this.$newsletter = this.$el.find('#newsletter');
    },

    actionSubmit: function(e) {
      e && e.preventDefault();
      this.validate(e) ? this.sendForm() : this.updateForm();
    },

    // Send the data to the API
    sendForm: function() {
      // Production send request
      // Send request
      this.$spinner.addClass('-start');
      var xhr = new XMLHttpRequest();

      xhr.open('POST', window.gfw.config.GFW_API_HOST_NEW_API + '/form/contact-us');
      xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');

      xhr.onload = function() {
        if (xhr.status === 200 || xhr.status === 201 || xhr.status === 204) {
          this.$body.animate({
            scrollTop: this.$container.offset().top
          }, 'slow');
          this.changeStep('success');
          this.resetForm();
          this.$spinner.removeClass('-start');
        } else {
          this.changeStep('error');
          this.$spinner.removeClass('-start');
        }
      }.bind(this);

      xhr.onerror = function() {
        this.changeStep('error');
        this.$spinner.removeClass('-start');
      }.bind(this);

      xhr.send(JSON.stringify(this.serialize(this.$form[0])));

      // // Develop Send request
      // // Comment this code if this is going to pro
      // if (true) {
      //   this.changeStep('success');
      //   this.$spinner.removeClass('-start');
      // } else {
      //   this.changeStep('error');
      //   this.$spinner.removeClass('-start');
      // }
    },

    updateForm: function() {
      this.$form.find('input, textarea, select').removeClass('-error');
      this.$form.find('label').removeClass('-error');
      for (var key in this.errors) {
        var $input = this.$form.find('#'+key);
        var $label = this.$form.find('label[for='+key+']');
        $input.addClass('-error');
        $label.addClass('-error');
      }
    },

    resetForm: function() {
      this.$form.find('input, textarea, select').val(null);
    },

    serialize: function(form) {
    	if (!form || form.nodeName !== "FORM") {
    		return;
    	}
    	var obj = {};
    	for (var i = form.elements.length - 1; i >= 0; i = i - 1) {
    		if (form.elements[i].name === "") {
    			continue;
    		}
    		switch (form.elements[i].nodeName) {
    		case 'INPUT':
    			switch (form.elements[i].type) {
    			case 'text':
    			case 'email':
    			case 'hidden':
    			case 'password':
    			case 'button':
    			case 'reset':
    			case 'submit':
    				obj[form.elements[i].name] = form.elements[i].value;
    				break;
    			case 'checkbox':
    			case 'radio':
            if (form.elements[i].checked) {
              obj[form.elements[i].name] = form.elements[i].value;
            } else if (!obj[form.elements[i].name]) {
              obj[form.elements[i].name] = false;
            }
    				break;
    			case 'file':
    				break;
    			}
    			break;
    		case 'TEXTAREA':
    			obj[form.elements[i].name] = form.elements[i].value;
    			break;
    		case 'SELECT':
    			switch (form.elements[i].type) {
      			case 'select-one':
      				obj[form.elements[i].name] = form.elements[i].value;
      				break;
      			case 'select-multiple':
      				for (var j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
      					if (form.elements[i].options[j].selected) {
      						obj[form.elements[i].name] = form.elements[i].options[j].value;
      					}
      				}
      				break;
    			}
    			break;
    		case 'BUTTON':
    			switch (form.elements[i].type) {
      			case 'reset':
      			case 'submit':
      			case 'button':
      				obj[form.elements[i].name] = form.elements[i].value;
      				break;
      		}
    			break;
    		}
    	}
    	return obj;
    },

    validate: function(e) {
      e && e.preventDefault();
      var attributes = this.serialize(this.$form[0]);

      // Validate form, if is valid the response will be undefined
      this.errors = validate(attributes, constraints);
      return ! !!this.errors;
    },

    validateInput: function(name, value) {
      var errors = validate.single(value, constraints[name]);
      if (!!errors && this.errors) {
        this.errors[name] = errors[0];
      } else {
        this.errors && this.errors[name] && delete this.errors[name];
      }
    },

    onNewsletterSignup: function(e) {
      e && e.preventDefault();
      e.currentTarget.classList.add('-hidden');

      if (this.timer) {
        clearTimeout(this.timer);
      }
      this.$newsletter.html(this.templateNewsletter({}));
      this.timer = setTimeout(function() {
        this.$newsletter.find('.-js-newsletter').removeClass('-loading');
      }.bind(this), 2000);
    },

    changeInput: function(e) {
      e && e.preventDefault();
      this.validateInput(e.currentTarget.name, e.currentTarget.value);
      this.updateForm();
    },

    changeStep: function(step) {
      this.$step.removeClass('-active');
      this.$stepBtn.removeClass('-active');

      // Set actives
      this.$el.find('.step[data-step="'+step+'"]').addClass('-active');
      this.$el.find('.step-btn[data-step="'+step+'"]').addClass('-active');
    },

    changeTopic: function(e) {
      var topic = e.currentTarget.value;
      e.currentTarget.classList.add('hide');
      if (!!topic) {
        var placeholder = topics[topic]['placeholder'];
        this.$contactMessage.attr('placeholder', placeholder);
      }
    }

  });

  return ContacUsView;
});
<commit_msg>Fix: Contact us - missing credentials<commit_after>define([
  'jquery',
  'handlebars',
  'backbone',
  'text!static/templates/contactUsNewsletter.handlebars'
], function($, Handlebars, Backbone, tplNewsletter) {

  'use strict';

  var topics = {
    'report-a-bug-or-error-on-gfw': {
      name: 'Report a bug or error on GFW',
      placeholder: 'Explain the bug or error and tell us where on the website you encountered it. What browser (e.g., Chrome version 50.0.2661.94 m) and operating system (e.g., Windows 8.1) do you use?',
    },
    'provide-feedback': {
      name: 'Provide feedback',
      placeholder: 'Tell us about your experience with GFW! Examples: How can we improve GFW? Why did you visit GFW? How do you use GFW? If and how is the information provided by GFW useful for your work? Are there any additional features and/or data that would be useful?  Was anything confusing or difficult to use?  Etc...',
    },
    'media-request': {
      name: 'Media request',
      placeholder: 'How can we help you?',
    },
    'data-related-inquiry': {
      name: 'Data-related inquiry or suggestion',
      placeholder: 'How can we help you?',
    },
    'gfw-commodities-inquiry': {
      name: 'GFW Commodities inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-fires-inquiry': {
      name: 'GFW Fires inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-climate-inquiry': {
      name: 'GFW Climate inquiry',
      placeholder: 'How can we help you?',
    },
    'gfw-water-inquiry': {
      name: 'GFW Water inquiry',
      placeholder: 'How can we help you?',
    },
    'general-inquiry': {
      name: 'General inquiry',
      placeholder: 'How can we help you?',
    },
  }

  var constraints = {
    'email': {
      presence: true,
      email: true
    },
    'topic': {
      presence: true
    },
    'message': {
      presence: true
    }
  };

  var ContacUsView = Backbone.View.extend({

    el: '#contact_us',

    events: {
      'click .js-btn-submit': 'actionSubmit',
      'click .js-newsletter-sign-up': 'onNewsletterSignup',
      'change input, textarea, select': 'changeInput',
      'change #contact-topic': 'changeTopic'
    },

    templateNewsletter: Handlebars.compile(tplNewsletter),

    initialize: function() {
      this.$spinner = this.$el.find('.m-spinner');
      this.$form = this.$el.find('#contact-form');
      this.$step = this.$el.find('.step');
      this.$stepBtn = this.$el.find('.step-btn');
      this.$contactMessage = this.$el.find('#contact-message');
      this.$body = $('html, body');
      this.$container = $('.content-static');
      this.$newsletter = this.$el.find('#newsletter');
    },

    actionSubmit: function(e) {
      e && e.preventDefault();
      this.validate(e) ? this.sendForm() : this.updateForm();
    },

    // Send the data to the API
    sendForm: function() {
      // Production send request
      // Send request
      this.$spinner.addClass('-start');
      var xhr = new XMLHttpRequest();

      xhr.open('POST', window.gfw.config.GFW_API_HOST_NEW_API + '/form/contact-us');
      xhr.withCredentials = true;
      xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');

      xhr.onload = function() {
        if (xhr.status === 200 || xhr.status === 201 || xhr.status === 204) {
          this.$body.animate({
            scrollTop: this.$container.offset().top
          }, 'slow');
          this.changeStep('success');
          this.resetForm();
          this.$spinner.removeClass('-start');
        } else {
          this.changeStep('error');
          this.$spinner.removeClass('-start');
        }
      }.bind(this);

      xhr.onerror = function() {
        this.changeStep('error');
        this.$spinner.removeClass('-start');
      }.bind(this);

      xhr.send(JSON.stringify(this.serialize(this.$form[0])));

      // // Develop Send request
      // // Comment this code if this is going to pro
      // if (true) {
      //   this.changeStep('success');
      //   this.$spinner.removeClass('-start');
      // } else {
      //   this.changeStep('error');
      //   this.$spinner.removeClass('-start');
      // }
    },

    updateForm: function() {
      this.$form.find('input, textarea, select').removeClass('-error');
      this.$form.find('label').removeClass('-error');
      for (var key in this.errors) {
        var $input = this.$form.find('#'+key);
        var $label = this.$form.find('label[for='+key+']');
        $input.addClass('-error');
        $label.addClass('-error');
      }
    },

    resetForm: function() {
      this.$form.find('input, textarea, select').val(null);
    },

    serialize: function(form) {
    	if (!form || form.nodeName !== "FORM") {
    		return;
    	}
    	var obj = {};
    	for (var i = form.elements.length - 1; i >= 0; i = i - 1) {
    		if (form.elements[i].name === "") {
    			continue;
    		}
    		switch (form.elements[i].nodeName) {
    		case 'INPUT':
    			switch (form.elements[i].type) {
    			case 'text':
    			case 'email':
    			case 'hidden':
    			case 'password':
    			case 'button':
    			case 'reset':
    			case 'submit':
    				obj[form.elements[i].name] = form.elements[i].value;
    				break;
    			case 'checkbox':
    			case 'radio':
            if (form.elements[i].checked) {
              obj[form.elements[i].name] = form.elements[i].value;
            } else if (!obj[form.elements[i].name]) {
              obj[form.elements[i].name] = false;
            }
    				break;
    			case 'file':
    				break;
    			}
    			break;
    		case 'TEXTAREA':
    			obj[form.elements[i].name] = form.elements[i].value;
    			break;
    		case 'SELECT':
    			switch (form.elements[i].type) {
      			case 'select-one':
      				obj[form.elements[i].name] = form.elements[i].value;
      				break;
      			case 'select-multiple':
      				for (var j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
      					if (form.elements[i].options[j].selected) {
      						obj[form.elements[i].name] = form.elements[i].options[j].value;
      					}
      				}
      				break;
    			}
    			break;
    		case 'BUTTON':
    			switch (form.elements[i].type) {
      			case 'reset':
      			case 'submit':
      			case 'button':
      				obj[form.elements[i].name] = form.elements[i].value;
      				break;
      		}
    			break;
    		}
    	}
    	return obj;
    },

    validate: function(e) {
      e && e.preventDefault();
      var attributes = this.serialize(this.$form[0]);

      // Validate form, if is valid the response will be undefined
      this.errors = validate(attributes, constraints);
      return ! !!this.errors;
    },

    validateInput: function(name, value) {
      var errors = validate.single(value, constraints[name]);
      if (!!errors && this.errors) {
        this.errors[name] = errors[0];
      } else {
        this.errors && this.errors[name] && delete this.errors[name];
      }
    },

    onNewsletterSignup: function(e) {
      e && e.preventDefault();
      e.currentTarget.classList.add('-hidden');

      if (this.timer) {
        clearTimeout(this.timer);
      }
      this.$newsletter.html(this.templateNewsletter({}));
      this.timer = setTimeout(function() {
        this.$newsletter.find('.-js-newsletter').removeClass('-loading');
      }.bind(this), 2000);
    },

    changeInput: function(e) {
      e && e.preventDefault();
      this.validateInput(e.currentTarget.name, e.currentTarget.value);
      this.updateForm();
    },

    changeStep: function(step) {
      this.$step.removeClass('-active');
      this.$stepBtn.removeClass('-active');

      // Set actives
      this.$el.find('.step[data-step="'+step+'"]').addClass('-active');
      this.$el.find('.step-btn[data-step="'+step+'"]').addClass('-active');
    },

    changeTopic: function(e) {
      var topic = e.currentTarget.value;
      e.currentTarget.classList.add('hide');
      if (!!topic) {
        var placeholder = topics[topic]['placeholder'];
        this.$contactMessage.attr('placeholder', placeholder);
      }
    }

  });

  return ContacUsView;
});
<|endoftext|>


<commit_before>// As documented on the reference below, turbolinks 5 does not treat a render
// after a form submit by default, leaving the users to implement their own
// solutions.
//
// https://github.com/turbolinks/turbolinks/issues/85#issuecomment-323446272
//
// The code below imitates the behavior of turbolinks when treating regular GET
// responses. Namely, it:
//   - Replaces only the body of the page
//   - It runs all script tags on the body of the new page
//   - It fires the turbolinks:load event
//
// This doesn't mean it does ALL what turbolinks does. For example, we don't
// merge script tags from old and new page <head> elements.
// This also doesn't change the browser history or does any change to the URL.
// The reason we don't do such things is simply that this gem is a solution to
// render errors in forms, and usually we render the same page/form we had rendered
// before the submit.

var TurbolinksForm = function(){};

// Attach an event handler function for one or more events to the selected elements.
// This method is inspired by JQuery on() and was created so that we could remove the dependency
// on JQuery.
// Ref: https://stackoverflow.com/questions/25248286/native-js-equivalent-to-jquery-delegation#answer-46595740
TurbolinksForm.on = function(eventHandlerOwner, event, delegateSelector, handler) {
  // handles call with 3 arguments
  if (!handler && delegateSelector) {
    handler = delegateSelector;
    delegateSelector = undefined;
  }

  $(eventHandlerOwner).on(event, function(e) {
    if (delegateSelector) {
      // goes up the dom tree searching for the delegate
      var currentTarget = e.target;
      while (currentTarget != null && currentTarget !== this && !currentTarget.matches(delegateSelector)) {
        currentTarget = currentTarget.parentElement;
      }

      // if delegate found, call the handler there
      if (currentTarget != null && currentTarget.matches(delegateSelector)) {
        handler.apply(currentTarget, arguments);
      }
    }
    // if there is no delegation, just call the handler directly
    else {
      handler.apply(eventHandlerOwner, arguments);
    }
  });
}

TurbolinksForm.handleResponse = function(xhr, renderingError) {
  // parses response
  var newDom = new DOMParser().parseFromString(xhr.responseText, "text/html");

  // Some browsers (PhantomJS and earlier versions of Firefox and IE) don't implement
  // parsing from string for "text/html" format. So we use an alternative method
  // described here:
  // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/HTML_to_DOM#Parsing_Complete_HTML_to_DOM
  if (newDom == null) {
    newDom = document.implementation.createHTMLDocument("document");
    newDom.documentElement.innerHTML = xhr.responseText;
  }

  if (newDom == null) {
    console.error("turbolinks-form was not able to parse response from server.");
  }

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:before-render', {data: {newBody: newDom.body}});

  // console.log('before-render')

  // replaces whole head if rendering an error page. Useful when handling 500 error, since applications
  // usually have a whole different set of styles for this page. This is consistent with Turbolinks.
  if (renderingError) {
    // head replacement doesn't work the same way as body replacement. We must use the replaceChild()
    // function for it to work effectively
    document.documentElement.replaceChild(newDom.head, document.head);
  }

  // Removes/saves all script tags contents.
  // Most browsers don't run the new <script> tags when we replace the page body,
  // but some do (like PhantomJS). So we clear all script tags to ensure nothing
  // will run on any browser.
  var newBodyScripts = newDom.body.getElementsByTagName('script');
  var newBodyScriptContents = [];
  for (var i=0; i<newBodyScripts.length; i++) {
    var script = newBodyScripts[i];
    newBodyScriptContents.push(script.text);
    script.text = "";
  }

  // if there is no target, replaces whole body
  var target;
  if (!xhr.getResponseHeader('turbolinks-form-render-target') || renderingError) {
    document.body = newDom.body;
    target = document.body;
  }
  // if there is a specific target
  else {
    target = document.body.querySelector(xhr.getResponseHeader('turbolinks-form-render-target'));
    if (target) {
      // clears target contents
      while (target.firstChild) {
        target.removeChild(target.firstChild);
      }
      // fills target with new content
      while (newDom.body.firstChild) {
        target.appendChild(newDom.body.removeChild(newDom.body.firstChild));
      }
    }
    else {
      console.warn('[turbolinks-form] target not found for selector: ' + xhr.getResponseHeader('turbolinks-form-render-target'));
    }
  }

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:render');

  // console.log('render')

  // Add scripts to body, so they are run on any browser
  var bodyScripts = target.getElementsByTagName('script');
  for (var i=0; i<bodyScripts.length; i++) {
    var script = bodyScripts[i];
    var newScript = document.createElement("script");
    newScript.text = newBodyScriptContents[i];
    script.parentNode.replaceChild(newScript, script);
  }

  scrollTo(0, 0);
  Turbolinks.dispatch("turbolinks:load");
}

// This code is only activated if:
//  1) HTTP status code is 422 unprocessable_entity
//  2) Response has the 'turbolinks-form-render' header
//
// PS: it is also activated on errors with code 500 or 404, so that we can know the
//     error is happening and not that the site is unresponsive
TurbolinksForm.on(document, "ajax:error", function(e, xhr) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!xhr && e.detail)
    var xhr = e.detail[2];

  // Replaces whole body and whole head when a true error occurs (same behavior as turbolinks)
  // This is done even when there is no turbolinks-form-render header (this affects all AJAX requests)
  // because when an error occurrs this header is not added by the server
  var isError500 = (xhr.status == 500)
  var isError404 = (xhr.status == 404)
  if (isError500 || isError404) {
    console.info("Error Response handled by turbolinks-form");
    TurbolinksForm.handleResponse(xhr, true);
    return;
  }

  // does not intercept unrelated AJAX responses
  if (!xhr || !xhr.getResponseHeader('turbolinks-form-render'))
    return;

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});

  // handles form error (replaces body/target only, does not touch head)
  var isFormErrorResponse = (xhr.status == 422);
  if (isFormErrorResponse) {
    TurbolinksForm.handleResponse(xhr);
    return;
  }
});

// This code is only activated if:
//  1) HTTP status code is 200
//  2) Response has 'turbolinks-form-render' header and 'turbolinks-form-render-when-success' header
//
// This handling is useful when we dont want a redirect after a successful submit
TurbolinksForm.on(document, "ajax:success", function(e, data, status, xhr) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!status && e.detail)
    var status = e.detail[1];
  if (!xhr && e.detail)
    var xhr = e.detail[2];

  // does not intercept unrelated AJAX responses
  if (!xhr || !xhr.getResponseHeader('turbolinks-form-render'))
    return;

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});

  var isFormSuccessResponse = (xhr.status == 200 && xhr.getResponseHeader('turbolinks-form-render-when-success'));
  if (isFormSuccessResponse) {
    TurbolinksForm.handleResponse(xhr);
  }
});

// Sets up event delegation to forms with data-turbolinks-form attribute
TurbolinksForm.on(document, "ajax:beforeSend", "[data-turbolinks-form]", function(e, xhr, options) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!xhr && e.detail)
    var xhr = e.detail[0];
  if (!options && e.detail)
    var options = e.detail[1];

  // adds the turbolinks-form-submit header for forms with data-turbolinks-form attribute being submitted,
  // so the controller knows it has to put the turbolinks-form-render header on the response
  xhr.setRequestHeader('turbolinks-form-submit', '1');

  // changes default Accept header to say we preferably want an HTML content as a response
  xhr.setRequestHeader('Accept', '*/*;q=0.5, text/javascript;q=0.9, application/javascript;q=0.9, application/ecmascript;q=0.9, application/x-ecmascript;q=0.9, text/html')

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-start', {data: {xhr: xhr}});
});

// Polyfills

if (!Element.prototype.matches) {
  Element.prototype.matches =
      Element.prototype.matchesSelector ||
      Element.prototype.mozMatchesSelector ||
      Element.prototype.msMatchesSelector ||
      Element.prototype.oMatchesSelector ||
      Element.prototype.webkitMatchesSelector ||
      function(s) {
        var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i = matches.length;
        while (--i >= 0 && matches.item(i) !== this) {}
        return i > -1;
      };
}
<commit_msg>Handling timeout on xhr request<commit_after>// As documented on the reference below, turbolinks 5 does not treat a render
// after a form submit by default, leaving the users to implement their own
// solutions.
//
// https://github.com/turbolinks/turbolinks/issues/85#issuecomment-323446272
//
// The code below imitates the behavior of turbolinks when treating regular GET
// responses. Namely, it:
//   - Replaces only the body of the page
//   - It runs all script tags on the body of the new page
//   - It fires the turbolinks:load event
//
// This doesn't mean it does ALL what turbolinks does. For example, we don't
// merge script tags from old and new page <head> elements.
// This also doesn't change the browser history or does any change to the URL.
// The reason we don't do such things is simply that this gem is a solution to
// render errors in forms, and usually we render the same page/form we had rendered
// before the submit.

var TurbolinksForm = function(){};

// Attach an event handler function for one or more events to the selected elements.
// This method is inspired by JQuery on() and was created so that we could remove the dependency
// on JQuery.
// Ref: https://stackoverflow.com/questions/25248286/native-js-equivalent-to-jquery-delegation#answer-46595740
TurbolinksForm.on = function(eventHandlerOwner, event, delegateSelector, handler) {
  // handles call with 3 arguments
  if (!handler && delegateSelector) {
    handler = delegateSelector;
    delegateSelector = undefined;
  }

  $(eventHandlerOwner).on(event, function(e) {
    if (delegateSelector) {
      // goes up the dom tree searching for the delegate
      var currentTarget = e.target;
      while (currentTarget != null && currentTarget !== this && !currentTarget.matches(delegateSelector)) {
        currentTarget = currentTarget.parentElement;
      }

      // if delegate found, call the handler there
      if (currentTarget != null && currentTarget.matches(delegateSelector)) {
        handler.apply(currentTarget, arguments);
      }
    }
    // if there is no delegation, just call the handler directly
    else {
      handler.apply(eventHandlerOwner, arguments);
    }
  });
}

TurbolinksForm.handleResponse = function(xhr, renderingError) {
  // parses response
  var newDom = new DOMParser().parseFromString(xhr.responseText, "text/html");

  // Some browsers (PhantomJS and earlier versions of Firefox and IE) don't implement
  // parsing from string for "text/html" format. So we use an alternative method
  // described here:
  // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/HTML_to_DOM#Parsing_Complete_HTML_to_DOM
  if (newDom == null) {
    newDom = document.implementation.createHTMLDocument("document");
    newDom.documentElement.innerHTML = xhr.responseText;
  }

  if (newDom == null) {
    console.error("turbolinks-form was not able to parse response from server.");
  }

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:before-render', {data: {newBody: newDom.body}});

  // console.log('before-render')

  // replaces whole head if rendering an error page. Useful when handling 500 error, since applications
  // usually have a whole different set of styles for this page. This is consistent with Turbolinks.
  if (renderingError) {
    // head replacement doesn't work the same way as body replacement. We must use the replaceChild()
    // function for it to work effectively
    document.documentElement.replaceChild(newDom.head, document.head);
  }

  // Removes/saves all script tags contents.
  // Most browsers don't run the new <script> tags when we replace the page body,
  // but some do (like PhantomJS). So we clear all script tags to ensure nothing
  // will run on any browser.
  var newBodyScripts = newDom.body.getElementsByTagName('script');
  var newBodyScriptContents = [];
  for (var i=0; i<newBodyScripts.length; i++) {
    var script = newBodyScripts[i];
    newBodyScriptContents.push(script.text);
    script.text = "";
  }

  // if there is no target, replaces whole body
  var target;
  if (!xhr.getResponseHeader('turbolinks-form-render-target') || renderingError) {
    document.body = newDom.body;
    target = document.body;
  }
  // if there is a specific target
  else {
    target = document.body.querySelector(xhr.getResponseHeader('turbolinks-form-render-target'));
    if (target) {
      // clears target contents
      while (target.firstChild) {
        target.removeChild(target.firstChild);
      }
      // fills target with new content
      while (newDom.body.firstChild) {
        target.appendChild(newDom.body.removeChild(newDom.body.firstChild));
      }
    }
    else {
      console.warn('[turbolinks-form] target not found for selector: ' + xhr.getResponseHeader('turbolinks-form-render-target'));
    }
  }

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:render');

  // console.log('render')

  // Add scripts to body, so they are run on any browser
  var bodyScripts = target.getElementsByTagName('script');
  for (var i=0; i<bodyScripts.length; i++) {
    var script = bodyScripts[i];
    var newScript = document.createElement("script");
    newScript.text = newBodyScriptContents[i];
    script.parentNode.replaceChild(newScript, script);
  }

  scrollTo(0, 0);
  Turbolinks.dispatch("turbolinks:load");
}

// This code is only activated if:
//  1) HTTP status code is 422 unprocessable_entity
//  2) Response has the 'turbolinks-form-render' header
//
// PS: it is also activated on errors with code 500 or 404, so that we can know the
//     error is happening and not that the site is unresponsive
TurbolinksForm.on(document, "ajax:error", function(e, xhr) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!xhr && e.detail)
    var xhr = e.detail[2];

  // Replaces whole body and whole head when a true error occurs (same behavior as turbolinks)
  // This is done even when there is no turbolinks-form-render header (this affects all AJAX requests)
  // because when an error occurs this header is not added by the server
  var isError500 = (xhr.status == 500)
  var isError404 = (xhr.status == 404)
  if (isError500 || isError404) {
    console.info("Error Response handled by turbolinks-form");
    // dispatches turbolinks event
    Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});
    TurbolinksForm.handleResponse(xhr, true);
    return;
  }

  // Detects timeout to trigger the request-end event. It is up to the developer to handle
  // the timeout on the 'turbolinks:request-end' handler
  // Obs: for the timeout to trigger, it is up to the developer to setup the timeout on the
  // rails-ujs or jquery-ujs (instructions: https://stackoverflow.com/questions/54464003/how-to-set-timeout-using-rails-ujs).
  // Otherwise, the default is no timeout.
  // Ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
  var isTimeout = (xhr.readyState == 0 || xhr.status == 0);
  if (isTimeout) {
    Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});
    return;
  }

  // does not intercept unrelated AJAX responses
  if (!xhr.getResponseHeader('turbolinks-form-render'))
    return;

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});

  // handles form error (replaces body/target only, does not touch head)
  var isFormErrorResponse = (xhr.status == 422);
  if (isFormErrorResponse) {
    TurbolinksForm.handleResponse(xhr);
    return;
  }
});

// This code is only activated if:
//  1) HTTP status code is 200
//  2) Response has 'turbolinks-form-render' header and 'turbolinks-form-render-when-success' header
//
// This handling is useful when we dont want a redirect after a successful submit
TurbolinksForm.on(document, "ajax:success", function(e, data, status, xhr) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!status && e.detail)
    var status = e.detail[1];
  if (!xhr && e.detail)
    var xhr = e.detail[2];

  // does not intercept unrelated AJAX responses
  if (!xhr || !xhr.getResponseHeader('turbolinks-form-render'))
    return;

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-end', {data: {xhr: xhr}});

  var isFormSuccessResponse = (xhr.status == 200 && xhr.getResponseHeader('turbolinks-form-render-when-success'));
  if (isFormSuccessResponse) {
    TurbolinksForm.handleResponse(xhr);
  }
});

// Sets up event delegation to forms with data-turbolinks-form attribute
TurbolinksForm.on(document, "ajax:beforeSend", "[data-turbolinks-form]", function(e, xhr, options) {
  // When using rails-ujs (instead of jquery-ujs) this handler receives a single event parameter
  // and other parameters must be extracted from e.detail
  // Ref: https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
  if (!xhr && e.detail)
    var xhr = e.detail[0];
  if (!options && e.detail)
    var options = e.detail[1];

  // adds the turbolinks-form-submit header for forms with data-turbolinks-form attribute being submitted,
  // so the controller knows it has to put the turbolinks-form-render header on the response
  xhr.setRequestHeader('turbolinks-form-submit', '1');

  // changes default Accept header to say we preferably want an HTML content as a response
  xhr.setRequestHeader('Accept', '*/*;q=0.5, text/javascript;q=0.9, application/javascript;q=0.9, application/ecmascript;q=0.9, application/x-ecmascript;q=0.9, text/html')

  // dispatches turbolinks event
  Turbolinks.dispatch('turbolinks:request-start', {data: {xhr: xhr}});
});

// Polyfills

if (!Element.prototype.matches) {
  Element.prototype.matches =
      Element.prototype.matchesSelector ||
      Element.prototype.mozMatchesSelector ||
      Element.prototype.msMatchesSelector ||
      Element.prototype.oMatchesSelector ||
      Element.prototype.webkitMatchesSelector ||
      function(s) {
        var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i = matches.length;
        while (--i >= 0 && matches.item(i) !== this) {}
        return i > -1;
      };
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Icon from '../Icon';

export default class Header extends Component {
  render() {
    return (

          {this.props.monthNames[this.props.month]}

          {this.props.year}

            <Icon name="chevron-back-18" />

            <Icon name="chevron-next-18" />

    );
  }
};
<commit_msg>chore: add back button roles to icons<commit_after>import React, { Component } from 'react';
import Icon from '../Icon';

export default class Header extends Component {
  render() {
    return (

          {this.props.monthNames[this.props.month]}

          {this.props.year}

            <Icon name="chevron-back-18" />

            <Icon name="chevron-next-18" />

    );
  }
};
<|endoftext|>


<commit_before>import { take, call, cancel, put, select,takeLatest } from 'redux-saga/effects';
import { LOAD_LANGUAGE,
  LOADING_LANGUAGE_COMPLETE,
  LOADING_LANGUAGE_ERROR
 } from './constants';

 import { CHANGE_LOCALE } from 'containers/LanguageProvider/constants';
import { loadingLanguageComplete, loadingLanguageError } from './actions';
// Individual exports for testing
import request from 'utils/request';

export const getLanguage = (state) => state.get('language');
export const getTranslatableStaticText = (state) => state.get('translatableStaticText');

export function* loadLanguageItem() {
  // getContactUs.get(email);

  const language = yield select(getLanguage);

  const requestURL = `https://api.beautifulrising.org/api/v1/text/ui?lang=${language.get('locale')}`;

  try {
    const data = yield call(request, requestURL);

    /** LOADING AREA **/
    yield put(loadingLanguageComplete(data));

  } catch (err) {
    yield call(put, loadingLanguageError(err));

  }
}
export function* initialLoadingCall() {
  // See example in containers/HomePage/sagas.js

  const action = yield takeLatest(LOAD_LANGUAGE, loadLanguageItem);

  // yield take(CHANGE_LOCALE);
  //
  // yield cancel(action);
  // // const sel = yield select('email');
  // yield ();
}

export function* languageChanged() {

  const action = yield takeLatest(CHANGE_LOCALE, loadLanguageItem);

  // yield take(CHANGE_LOCALE);
}

// All sagas to be loaded
export default [
  languageChanged,
  initialLoadingCall
];
<commit_msg>Fixed about menu<commit_after>import { take, call, cancel, put, select,takeLatest } from 'redux-saga/effects';
import { LOAD_LANGUAGE,
  LOADING_LANGUAGE_COMPLETE,
  LOADING_LANGUAGE_ERROR
 } from './constants';

 import { CHANGE_LOCALE } from 'containers/LanguageProvider/constants';
import { loadingLanguageComplete, loadingLanguageError } from './actions';
// Individual exports for testing
import request from 'utils/request';

export const getLanguage = (state) => state.get('language');
export const getTranslatableStaticText = (state) => state.get('translatableStaticText');

export function* loadLanguageItem() {
  // getContactUs.get(email);

  const language = yield select(getLanguage);

  const requestURL = `https://api.beautifulrising.org/api/v1/text/ui?lang=${language.get('locale')}`;

  try {
    const data = yield call(request, requestURL);

    console.log(data);
    /** LOADING AREA **/
    yield put(loadingLanguageComplete(data[0]));

  } catch (err) {
    yield call(put, loadingLanguageError(err));

  }
}
export function* initialLoadingCall() {
  // See example in containers/HomePage/sagas.js

  const action = yield takeLatest(LOAD_LANGUAGE, loadLanguageItem);

  // yield take(CHANGE_LOCALE);
  //
  // yield cancel(action);
  // // const sel = yield select('email');
  // yield ();
}

export function* languageChanged() {

  const action = yield takeLatest(CHANGE_LOCALE, loadLanguageItem);

  // yield take(CHANGE_LOCALE);
}

// All sagas to be loaded
export default [
  languageChanged,
  initialLoadingCall
];
<|endoftext|>


<commit_before>L.Control.MiniMap = L.Control.extend({
	options: {
		position: 'bottomright',
		toggleDisplay: false,
		zoomLevelOffset: -5,
		zoomLevelFixed: false,
		zoomAnimation: false,
		width: 150,
		height: 150
	},
	//layer is the map layer to be shown in the minimap
	initialize: function (layer, options) {
		L.Util.setOptions(this, options);
		this._layer = layer;
	},

	onAdd: function (map) {

		this._mainMap = map;

		//Creating the container and stopping events from spilling through to the main map.
		this._container = L.DomUtil.create('div', 'leaflet-control-minimap');
		this._container.style.width = this.options.width + 'px';
		this._container.style.height = this.options.height + 'px';
		L.DomEvent.disableClickPropagation(this._container);
		L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation);

		this._miniMap = new L.Map(this._container,
		{
			attributionControl: false,
			zoomControl: false,
			zoomAnimation: this.options.zoomAnimation,
			touchZoom: !this.options.zoomLevelFixed,
			scrollWheelZoom: !this.options.zoomLevelFixed,
			doubleClickZoom: !this.options.zoomLevelFixed,
			boxZoom: !this.options.zoomLevelFixed
		});
		//We make a copy so that the original layer object is untouched, this way we can add/remove multiple times
		this._miniMap.addLayer(L.Util.clone (this._layer));

		//These bools are used to prevent infinite loops of the two maps notifying each other that they've moved.
		this._mainMapMoving = false;
		this._miniMapMoving = false;

		if (this.options.toggleDisplay) {
			this._addToggleButton();
		}

		this._miniMap.whenReady(L.Util.bind(function () {
			this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap);
			this._mainMap.on('moveend', this._onMainMapMoved, this);
			this._mainMap.on('move', this._onMainMapMoving, this);
			this._miniMap.on('moveend', this._onMiniMapMoved, this);
		}, this));

		return this._container;
	},

	addTo: function (map) {
		L.Control.prototype.addTo.call(this, map);
		this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
	},

	onRemove: function (map) {
		this._mainMap.off('moveend', this._onMainMapMoved, this);
		this._mainMap.off('move', this._onMainMapMoving, this);
		this._miniMap.off('moveend', this._onMiniMapMoved, this);

	},

	_addToggleButton: function () {
		this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
		        '', 'Hide', 'leaflet-control-minimap-toggle-display',  this._container, this._toggleDisplay,  this) : undefined;
		this._minimized = false;
	},

	_createButton: function (html, title, className, container, fn, context) {
		var link = L.DomUtil.create('a', className, container);
		link.innerHTML = html;
		link.href = '#';
		link.title = title;

		var stop = L.DomEvent.stopPropagation;

		L.DomEvent
		    .on(link, 'click', stop)
		    .on(link, 'mousedown', stop)
		    .on(link, 'dblclick', stop)
		    .on(link, 'click', L.DomEvent.preventDefault)
		    .on(link, 'click', fn, context);

		return link;
	},

	_toggleDisplay: function () {
		if (!this._minimized) {
			// hide the minimap
			this._container.style.width = '19px';
			this._container.style.height = '19px';
			this._toggleDisplayButton.className += ' minimized';
			this._minimized = true;
		}
		else {
			this._container.style.width = this.options.width + 'px';
			this._container.style.height = this.options.height + 'px';
			this._toggleDisplayButton.className = this._toggleDisplayButton.className
				.replace(/(?:^|\s)minimized(?!\S)/g , '');
			this._minimized = false;
		}
	},

	_onMainMapMoved: function (e) {
		if (!this._miniMapMoving) {
			this._mainMapMoving = true;
			this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
		} else {
			this._miniMapMoving = false;
		}
		this._aimingRect.setBounds(this._mainMap.getBounds());
	},

	_onMainMapMoving: function (e) {
		this._aimingRect.setBounds(this._mainMap.getBounds());
	},

	_onMiniMapMoved: function (e) {
	if (!this._mainMapMoving) {
			this._miniMapMoving = true;
			this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false));
		} else {
			this._mainMapMoving = false;
		}
	},

	_decideZoom: function (fromMaintoMini) {
		if (!this.options.zoomLevelFixed) {
			if (fromMaintoMini)
				return this._mainMap.getZoom() + this.options.zoomLevelOffset;
			else
				return this._miniMap.getZoom() - this.options.zoomLevelOffset;
		} else {
			if (fromMaintoMini)
				return this.options.zoomLevelFixed;
			else
				return this._mainMap.getZoom();
		}
	}
});

L.Map.mergeOptions({
	miniMapControl: false
});

L.Map.addInitHook(function () {
	if (this.options.miniMapControl) {
		this.miniMapControl = (new L.Control.MiniMap()).addTo(this);
	}
});

L.control.minimap = function (options) {
	return new L.Control.MiniMap(options);
};

//Simple helper function for cloning
L.Util.clone = function (o){
	if(o == null || typeof(o) != 'object')
		return o;

	var c = new o.constructor();
	//Deep clone recursively
	for(var k in o)
		c[k] = L.Util.clone(o[k]);

	return c;
};<commit_msg>Return "this" in Control.addTo<commit_after>L.Control.MiniMap = L.Control.extend({
	options: {
		position: 'bottomright',
		toggleDisplay: false,
		zoomLevelOffset: -5,
		zoomLevelFixed: false,
		zoomAnimation: false,
		width: 150,
		height: 150
	},
	//layer is the map layer to be shown in the minimap
	initialize: function (layer, options) {
		L.Util.setOptions(this, options);
		this._layer = layer;
	},

	onAdd: function (map) {

		this._mainMap = map;

		//Creating the container and stopping events from spilling through to the main map.
		this._container = L.DomUtil.create('div', 'leaflet-control-minimap');
		this._container.style.width = this.options.width + 'px';
		this._container.style.height = this.options.height + 'px';
		L.DomEvent.disableClickPropagation(this._container);
		L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation);

		this._miniMap = new L.Map(this._container,
		{
			attributionControl: false,
			zoomControl: false,
			zoomAnimation: this.options.zoomAnimation,
			touchZoom: !this.options.zoomLevelFixed,
			scrollWheelZoom: !this.options.zoomLevelFixed,
			doubleClickZoom: !this.options.zoomLevelFixed,
			boxZoom: !this.options.zoomLevelFixed
		});
		//We make a copy so that the original layer object is untouched, this way we can add/remove multiple times
		this._miniMap.addLayer(L.Util.clone (this._layer));

		//These bools are used to prevent infinite loops of the two maps notifying each other that they've moved.
		this._mainMapMoving = false;
		this._miniMapMoving = false;

		if (this.options.toggleDisplay) {
			this._addToggleButton();
		}

		this._miniMap.whenReady(L.Util.bind(function () {
			this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap);
			this._mainMap.on('moveend', this._onMainMapMoved, this);
			this._mainMap.on('move', this._onMainMapMoving, this);
			this._miniMap.on('moveend', this._onMiniMapMoved, this);
		}, this));

		return this._container;
	},

	addTo: function (map) {
		L.Control.prototype.addTo.call(this, map);
		this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
		return this;
	},

	onRemove: function (map) {
		this._mainMap.off('moveend', this._onMainMapMoved, this);
		this._mainMap.off('move', this._onMainMapMoving, this);
		this._miniMap.off('moveend', this._onMiniMapMoved, this);

	},

	_addToggleButton: function () {
		this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
		        '', 'Hide', 'leaflet-control-minimap-toggle-display',  this._container, this._toggleDisplay,  this) : undefined;
		this._minimized = false;
	},

	_createButton: function (html, title, className, container, fn, context) {
		var link = L.DomUtil.create('a', className, container);
		link.innerHTML = html;
		link.href = '#';
		link.title = title;

		var stop = L.DomEvent.stopPropagation;

		L.DomEvent
		    .on(link, 'click', stop)
		    .on(link, 'mousedown', stop)
		    .on(link, 'dblclick', stop)
		    .on(link, 'click', L.DomEvent.preventDefault)
		    .on(link, 'click', fn, context);

		return link;
	},

	_toggleDisplay: function () {
		if (!this._minimized) {
			// hide the minimap
			this._container.style.width = '19px';
			this._container.style.height = '19px';
			this._toggleDisplayButton.className += ' minimized';
			this._minimized = true;
		}
		else {
			this._container.style.width = this.options.width + 'px';
			this._container.style.height = this.options.height + 'px';
			this._toggleDisplayButton.className = this._toggleDisplayButton.className
				.replace(/(?:^|\s)minimized(?!\S)/g , '');
			this._minimized = false;
		}
	},

	_onMainMapMoved: function (e) {
		if (!this._miniMapMoving) {
			this._mainMapMoving = true;
			this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
		} else {
			this._miniMapMoving = false;
		}
		this._aimingRect.setBounds(this._mainMap.getBounds());
	},

	_onMainMapMoving: function (e) {
		this._aimingRect.setBounds(this._mainMap.getBounds());
	},

	_onMiniMapMoved: function (e) {
	if (!this._mainMapMoving) {
			this._miniMapMoving = true;
			this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false));
		} else {
			this._mainMapMoving = false;
		}
	},

	_decideZoom: function (fromMaintoMini) {
		if (!this.options.zoomLevelFixed) {
			if (fromMaintoMini)
				return this._mainMap.getZoom() + this.options.zoomLevelOffset;
			else
				return this._miniMap.getZoom() - this.options.zoomLevelOffset;
		} else {
			if (fromMaintoMini)
				return this.options.zoomLevelFixed;
			else
				return this._mainMap.getZoom();
		}
	}
});

L.Map.mergeOptions({
	miniMapControl: false
});

L.Map.addInitHook(function () {
	if (this.options.miniMapControl) {
		this.miniMapControl = (new L.Control.MiniMap()).addTo(this);
	}
});

L.control.minimap = function (options) {
	return new L.Control.MiniMap(options);
};

//Simple helper function for cloning
L.Util.clone = function (o){
	if(o == null || typeof(o) != 'object')
		return o;

	var c = new o.constructor();
	//Deep clone recursively
	for(var k in o)
		c[k] = L.Util.clone(o[k]);

	return c;
};<|endoftext|>


<commit_before>var RequestExecutorDataStrategy = function (type) {
    if (typeof this.strategies[type] === 'undefined') {
        this.strategy = this.strategies.json
    } else {
        this.strategy = this.strategies[type];
    }
};

RequestExecutorDataStrategy.prototype.request = function (requestData, successCallbackHandler, failCallbackHandler) {
    return this.strategy.apply(this, Array.prototype.slice.call(arguments));
};

RequestExecutorDataStrategy.prototype.strategies = {

    json: function (requestData, onSuccess, onFail) {
        return $.ajax({
            type: requestData.method || 'post',
            url: requestData.requestUrl,
            xhrFields: {
                withCredentials: true
            },
            beforeSend: this.onBeforeRequest(),
            success: this.onSuccessRequest(onSuccess),
            error: this.onErrorRequest(onFail),
            data: JSON.stringify(requestData.args),
            contentType: "application/json;charset=UTF-8"
        });
    },

    raw: function (requestData, onSuccess, onFail) {
        var method = requestData.method || 'post';
        var processData = method.toUpperCase() === 'GET';
        return $.ajax({
            type: method,
            url: requestData.requestUrl,
            xhrFields: {
                withCredentials: true
            },
            beforeSend: this.onBeforeRequest(),
            success: this.onSuccessRequest(onSuccess),
            error: this.onErrorRequest(onFail),
            processData: processData,
            contentType: false,
            data: requestData.args
        });
    }
};

_.extend(RequestExecutorDataStrategy.prototype, ajaxRequestMixin);

function RequestExecutor(resultCallback, successCallback, failCallback, cache) {

    var successCallbackHandler = function (data) {
        if (successCallback) {
            successCallback(data);
        }
        if (resultCallback) {
            resultCallback(data);
        }
    };

    var failCallbackHandler = function (err) {
        if (failCallback) {
            failCallback(err);
        }
        if (resultCallback) {
            resultCallback(err.responseJSON);
        }
    };

    var cacheRequest = function (requestData, request) {
        if (typeof cache === 'undefined' || cache === null) {
            return request(requestData);
        } else {
            var data = cache.get(requestData);
            if (data !== false) {
                console.log('Fetch from cache');
                var defer = $.Deferred();
                successCallbackHandler(data);
                defer.resolve(data);
                return defer.promise();
            }
            return request(requestData).then(function (data) {
                cache.set(requestData, data);
            });
        }
    };

    var request = function (type, requestData) {
        var strategy = new RequestExecutorDataStrategy(type);
        return strategy.request(requestData, successCallbackHandler, failCallbackHandler);
    };

    this.makeRequest = function (requestData) {
        return cacheRequest(requestData, request.bind(undefined, 'json'))
    };

    this.makeRequestRaw = function (requestData) {
        return cacheRequest(requestData, request.bind(undefined, 'raw'))
    };

}<commit_msg>UI-1622: Невозможно добавить FileBox в массив#resolve<commit_after>var RequestExecutorDataStrategy = function (type) {
    if (typeof this.strategies[type] === 'undefined') {
        this.strategy = this.strategies.json
    } else {
        this.strategy = this.strategies[type];
    }
};

RequestExecutorDataStrategy.prototype.request = function (requestData, successCallbackHandler, failCallbackHandler) {
    return this.strategy.apply(this, Array.prototype.slice.call(arguments));
};

RequestExecutorDataStrategy.prototype.strategies = {

    json: function (requestData, onSuccess, onFail) {
        return $.ajax({
            type: requestData.method || 'post',
            url: requestData.requestUrl,
            xhrFields: {
                withCredentials: true
            },
            beforeSend: this.onBeforeRequest(),
            success: this.onSuccessRequest(onSuccess),
            error: this.onErrorRequest(onFail),
            data: JSON.stringify(requestData.args),
            contentType: "application/json;charset=UTF-8"
        });
    },

    raw: function (requestData, onSuccess, onFail) {
        var method = requestData.method || 'post';
        var processData = method.toUpperCase() === 'GET';
        return $.ajax({
            type: method,
            url: requestData.requestUrl,
            xhrFields: {
                withCredentials: true
            },
            beforeSend: this.onBeforeRequest(),
            success: this.onSuccessRequest(onSuccess),
            error: function (err) {
                if (err.status === 200) {
                    //@TODO Убрать этот костыль. Нужен т.к. запрос на загрузку файла возвращает 200 и пустой ответ!
                    this.onSuccessRequest(onSuccess);
                } else {
                    this.onErrorRequest(onFail);
                }
            }.bind(this),
            processData: processData,
            contentType: false,
            data: requestData.args
        });
    }
};

_.extend(RequestExecutorDataStrategy.prototype, ajaxRequestMixin);

function RequestExecutor(resultCallback, successCallback, failCallback, cache) {

    var successCallbackHandler = function (data) {
        if (successCallback) {
            successCallback(data);
        }
        if (resultCallback) {
            resultCallback(data);
        }
    };

    var failCallbackHandler = function (err) {
        if (failCallback) {
            failCallback(err);
        }
        if (resultCallback) {
            resultCallback(err.responseJSON);
        }
    };

    var cacheRequest = function (requestData, request) {
        if (typeof cache === 'undefined' || cache === null) {
            return request(requestData);
        } else {
            var data = cache.get(requestData);
            if (data !== false) {
                console.log('Fetch from cache');
                var defer = $.Deferred();
                successCallbackHandler(data);
                defer.resolve(data);
                return defer.promise();
            }
            return request(requestData).then(function (data) {
                cache.set(requestData, data);
            });
        }
    };

    var request = function (type, requestData) {
        var strategy = new RequestExecutorDataStrategy(type);
        return strategy.request(requestData, successCallbackHandler, failCallbackHandler);
    };

    this.makeRequest = function (requestData) {
        return cacheRequest(requestData, request.bind(undefined, 'json'))
    };

    this.makeRequestRaw = function (requestData) {
        return cacheRequest(requestData, request.bind(undefined, 'raw'))
    };

}<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { props, t, skinnable } from '../utils';
import { FlexView } from '../flex';

/**
 * A NavBar container built with FlexView:
 * - easy positioning of content (left, center and right columns)
 * - lets you define basic css style from JS
 */
@skinnable()
@props({
  /** Props used to define the NavBar content */
  content: t.struct({
    /** Left content. It doesn't shrink nor grow */
    left: t.maybe(t.ReactNode),
    /** Center content. It grows to use all the available space */
    center: t.maybe(t.ReactNode),
    /** Right content. It doesn't shrink nor grow */
    right: t.maybe(t.ReactNode),
    /** shorthand for css `max-width` */
    maxWidth: t.maybe(t.union([ t.String, t.Number ]))
  }),
  /** To set `position: fixed` */
  fixed: t.maybe(t.Boolean),
  /** shorthand for css `height` */
  height: t.maybe(t.union([ t.String, t.Number ])),
  /** shorthand for css `background` */
  background: t.maybe(t.String),
  className: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class NavBar extends React.Component {

  getLocals() {
    const { className, style, fixed, height, background, ...props } = this.props;
    const valueOrUndefined = (validator, value) => validator ? value : undefined;

    return {
      ...props,
      style: {
        ...style,
        position: valueOrUndefined(fixed, 'fixed'),
        top: valueOrUndefined(fixed, 0),
        zIndex: valueOrUndefined(fixed, 99999),
        width: '100%',
        height,
        background
      },
      className: cx('nav-bar', className),
      flexProps: { hAlignContent: 'center', vAlignContent: 'center' }
    };
  }

  template({ content: { left, center, right, maxWidth }, className, style, flexProps }) {
    return (
      <FlexView {...{ className, style }} {...flexProps}>
        <FlexView grow style={{ maxWidth }} className='content' {...flexProps}>
          <FlexView className='left' marginRight='auto' shrink={false} {...flexProps}>
            {left}
          </FlexView>
          <FlexView className='center' grow {...flexProps}>
            {center}
          </FlexView>
          <FlexView className='right' marginLeft='auto' shrink={false} {...flexProps}>
            {right}
          </FlexView>
        </FlexView>
      </FlexView>
    );
  }
}
<commit_msg>code clean<commit_after>import React from 'react';
import cx from 'classnames';
import { props, t, skinnable } from '../utils';
import { FlexView } from '../flex';

/**
 * A NavBar container built with FlexView:
 * - easy positioning of content (left, center and right columns)
 * - lets you define basic css style from JS
 */
@skinnable()
@props({
  /** Props used to define the NavBar content */
  content: t.struct({
    /** Left content. It doesn't shrink nor grow */
    left: t.maybe(t.ReactNode),
    /** Center content. It grows to use all the available space */
    center: t.maybe(t.ReactNode),
    /** Right content. It doesn't shrink nor grow */
    right: t.maybe(t.ReactNode),
    /** shorthand for css `max-width` */
    maxWidth: t.maybe(t.union([ t.String, t.Number ]))
  }),
  /** To set `position: fixed` */
  fixed: t.maybe(t.Boolean),
  /** shorthand for css `height` */
  height: t.maybe(t.union([ t.String, t.Number ])),
  /** shorthand for css `background` */
  background: t.maybe(t.String),
  className: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class NavBar extends React.Component {

  getLocals() {
    const { className, style, fixed, height, background, ...props } = this.props;
    const valueOrUndefined = (validator, value) => validator ? value : undefined;

    return {
      ...props,
      style: {
        ...style,
        position: valueOrUndefined(fixed, 'fixed'),
        top: valueOrUndefined(fixed, 0),
        zIndex: valueOrUndefined(fixed, 99999),
        width: '100%',
        height,
        background
      },
      className: cx('nav-bar', className),
      flexProps: { hAlignContent: 'center', vAlignContent: 'center' }
    };
  }

  template({ content: { left, center, right, maxWidth }, className, style, flexProps }) {
    return (
      <FlexView {...{ className, style, ...flexProps }}>
        <FlexView {...flexProps} className='content' style={{ maxWidth }} grow>
          <FlexView {...flexProps} className='left' marginRight='auto' shrink={false}>
            {left}
          </FlexView>
          <FlexView {...flexProps} className='center' grow>
            {center}
          </FlexView>
          <FlexView {...flexProps} className='right' marginLeft='auto' shrink={false}>
            {right}
          </FlexView>
        </FlexView>
      </FlexView>
    );
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    // Project error strings
    "ERROR_LOADING_PROJECT"             : "Fehler beim Laden des Projekts",
    "OPEN_DIALOG_ERROR"                 : "Fehler beim Erstellen des Öffnen-Dialogs. (Fehler {0})",
    "REQUEST_NATIVE_FILE_SYSTEM_ERROR"  : "Fehler beim Lesen des Verzeichnisses {0}. (Fehler {1})",
    "READ_DIRECTORY_ENTRIES_ERROR"      : "Fehler beim Lesen der Verzeichnisinhalte von {0}. (Fehler {1})",

    // File open/save error string
    "ERROR_OPENING_FILE_TITLE"          : "Fehler beim Öffnen der Datei",
    "ERROR_OPENING_FILE"                : "Beim Öffnen der Datei {0} ist ein Fehler aufgetreten: {1}",
    "ERROR_RELOADING_FILE_TITLE"        : "Fehler beim Laden der Änderungen",
    "ERROR_RELOADING_FILE"              : "Beim Laden der Änderungen der Datei {0} ist ein Fehler aufgetreten: {1}",
    "ERROR_SAVING_FILE_TITLE"           : "Fehler beim Speichern der Datei",
    "ERROR_SAVING_FILE"                 : "Beim Speichern der Datei {0} ist ein Fehler aufgetreten: {1}",
    "INVALID_FILENAME_TITLE"            : "Ungültiger Dateiname",
    "INVALID_FILENAME_MESSAGE"          : "Dateinamen dürfen folgende Zeichen nicht enthalten: /?*:;{}<>\\|",
    "FILE_ALREADY_EXISTS"               : "Die Datei {0} existiert bereits.",
    "ERROR_CREATING_FILE_TITLE"         : "Fehler beim Erstellen der Datei",
    "ERROR_CREATING_FILE"               : "Beim Erstellen der Datei {0} ist ein Fehler aufgetreten: {1}",

    // Application error strings
    "ERROR_BRACKETS_IN_BROWSER_TITLE"   : "Ups! Brackets läuft derzeit leider nocht nicht im Browser.",
    "ERROR_BRACKETS_IN_BROWSER"         : "Brackets wurde in HTML programmiert aber derzeit läuft es nur als Desktop Anwendung, um damit lokale Dateien zu bearbeiten. Bitte benutzen Sie die Anwendung von github.com/adobe/brackets-app.",

    // FileIndexManager error string
    "ERROR_MAX_FILES_TITLE"             : "Fehler beim Indizieren der Dateien",
    "ERROR_MAX_FILES"                   : "Die maximal mögliche Anzahl indizierbarer Datein wurde überschritten. Funktionen, die auf dem Index beruhen, werden möglicherweise nicht korrekt funktionieren.",

    // CSSManager error strings
    "ERROR_PARSE_TITLE"                 : "Fehler beim Interpretieren der CSS Datei(en):",

    // Live Development error strings
    "ERROR_LAUNCHING_BROWSER_TITLE"     : "Fehler beim Starten des Webbrowsers",
    "ERROR_CANT_FIND_CHROME"            : "Google Chrome konnte nicht gefunden werden. Bitte laden Sie den Browser unter google.de/chrome.",
    "ERROR_LAUNCHING_BROWSER"           : "Beim Starten des Webbrowsers ist ein Fehler aufgetreten: (Fehler {0})",

    "LIVE_DEVELOPMENT_ERROR_TITLE"      : "Fehler bei der Live Entwicklung",
    "LIVE_DEVELOPMENT_ERROR_MESSAGE"    : "Beim Aufbauen einer Live Verbindung zu Chrome ist ein Fehler aufgetreten. "
                                                + "Für die Live Entwicklung muss das Remote Debugger Protokoll von Chrome aktiviert sein."
                                                + "

Soll Chrome neu gestartet werden, um das Remote Debugger Protokoll zu aktivieren?",
    "LIVE_DEV_NEED_HTML_MESSAGE"        : "Öffnen Sie erst eine HTML Datei und aktivieren Sie dann die Live Verbindung.",

    "LIVE_DEV_STATUS_TIP_NOT_CONNECTED" : "Live Entwicklung",
    "LIVE_DEV_STATUS_TIP_PROGRESS1"     : "Live Entwicklung: Verbinden...",
    "LIVE_DEV_STATUS_TIP_PROGRESS2"     : "Live Entwicklung: Initialisieren...",
    "LIVE_DEV_STATUS_TIP_CONNECTED"     : "Trennen der Live Verbindung",

    "SAVE_CLOSE_TITLE"                  : "Ungespeicherte Änderungen",
    "SAVE_CLOSE_MESSAGE"                : "Wollen Sie die Änderungen in dem Dokument {0} speichern?",
    "SAVE_CLOSE_MULTI_MESSAGE"          : "Wollen Sie die Änderungen in den folgenden Dateien speichern?",
    "EXT_MODIFIED_TITLE"                : "Externe Änderungen",
    "EXT_MODIFIED_MESSAGE"              : "{0} wurde extern geändert und hat ungespeicherte Änderungen in Brackets."
                                                + "

"
                                                + "Welche Version wollen Sie erhalten?",
    "EXT_DELETED_MESSAGE"               : "{0} wurde extern gelöscht und hat ungespeicherte Änderungen in Brackets."
                                                + "

"
                                                + "Wollen Sie die Änderungen erhalten?",

    "OPEN_FILE"                         : "Datei öffnen",

    // Switch language
    "LANGUAGE_TITLE"                    : "Sprache wechseln",
    "LANGUAGE_MESSAGE"                  : "Bitte wählen Sie die gewünschte Sprache aus der folgenden Liste aus:",
    "LANGUAGE_SUBMIT"                   : "Brackets neu starten",
    "LANGUAGE_CANCEL"                   : "Abbrechen",

    /**
     * Command Name Constants
     */

    // File menu commands
    "FILE_MENU"                           : "Datei",
    "CMD_FILE_NEW"                        : "Neu",
    "CMD_FILE_OPEN"                       : "Öffnen\u2026",
    "CMD_ADD_TO_WORKING_SET"              : "Zum Projekt hinzufügen",
    "CMD_OPEN_FOLDER"                     : "Ordner öffnen\u2026",
    "CMD_FILE_CLOSE"                      : "Schließen",
    "CMD_FILE_CLOSE_ALL"                  : "Alles schließen",
    "CMD_FILE_SAVE"                       : "Speichern",
    "CMD_LIVE_FILE_PREVIEW"               : "Live Entwicklung",
    "CMD_QUIT"                            : "Beenden",

    // Edit menu commands
    "EDIT_MENU"                           : "Bearbeiten",
    "CMD_SELECT_ALL"                      : "Alles auswählen",
    "CMD_FIND"                            : "Suchen",
    "CMD_FIND_IN_FILES"                   : "Im Projekt suchen",
    "CMD_FIND_NEXT"                       : "Weitersuchen (vorwärts)",
    "CMD_FIND_PREVIOUS"                   : "Weitersuchen (rückwärts)",
    "CMD_REPLACE"                         : "Ersetzen",
    "CMD_INDENT"                          : "Einrücken",
    "CMD_UNINDENT"                        : "Ausrücken",
    "CMD_DUPLICATE"                       : "Duplizieren",
    "CMD_COMMENT"                         : "Zeilen (aus-)kommentieren",
    "CMD_LINE_UP"                         : "Zeilen nach oben verschieben",
    "CMD_LINE_DOWN"                       : "Zeilen nach unten verschieben",

    // View menu commands
    "VIEW_MENU"                           : "Ansicht",
    "CMD_HIDE_SIDEBAR"                    : "Seitenleiste verbergen",
    "CMD_SHOW_SIDEBAR"                    : "Seitenleiste zeigen",
    "CMD_INCREASE_FONT_SIZE"              : "Schriftart vergrößern",
    "CMD_DECREASE_FONT_SIZE"              : "Schriftart verkleinern",
    "CMD_RESTORE_FONT_SIZE"               : "Schriftart zurücksetzen",

    // Navigate menu Commands
    "NAVIGATE_MENU"                       : "Navigation",
    "CMD_QUICK_OPEN"                      : "Schnell öffnen",
    "CMD_GOTO_LINE"                       : "Gehe zu Zeile",
    "CMD_GOTO_DEFINITION"                 : "Gehe zu Definition",
    "CMD_TOGGLE_QUICK_EDIT"               : "Schnell bearbeiten",
    "CMD_QUICK_EDIT_PREV_MATCH"           : "Voriger Treffer",
    "CMD_QUICK_EDIT_NEXT_MATCH"           : "Nächster Treffer",
    "CMD_NEXT_DOC"                        : "Nächstes Dokument",
    "CMD_PREV_DOC"                        : "Voriges Dokument",

    // Debug menu commands
    "DEBUG_MENU"                          : "Debug",
    "CMD_REFRESH_WINDOW"                  : "Brackets neu laden",
    "CMD_SHOW_DEV_TOOLS"                  : "Entwicklungswerkzeuge zeigen",
    "CMD_RUN_UNIT_TESTS"                  : "Tests durchführen",
    "CMD_JSLINT"                          : "JSLint aktivieren",
    "CMD_SHOW_PERF_DATA"                  : "Performance Analyse",
    "CMD_NEW_BRACKETS_WINDOW"             : "Neues Brackets Fenster",
    "CMD_USE_TAB_CHARS"                   : "Mit Tabs einrücken",
    "CMD_SWITCH_LANGUAGE"                 : "Sprache wechseln",

    // Help menu commands
    "CMD_ABOUT"                           : "Über",

    // Special commands invoked by the native shell
    "CMD_CLOSE_WINDOW"                    : "Fenster schließen"

});
<commit_msg>Add General file io error strings in "de" locale<commit_after>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    /**
     * Errors
     */

    // General file io error strings
    "GENERIC_ERROR"                     : "(Fehler {0})",
    "NOT_FOUND_ERR"                     : "Die Datei konnte nicht gefunden werden.",
    "NOT_READABLE_ERR"                  : "Die Datei konnte nicht gelesen werden.",
    "NO_MODIFICATION_ALLOWED_ERR"       : "Das Ziel-Verzeichnis kann nicht verändert werden.",
    "NO_MODIFICATION_ALLOWED_ERR_FILE"  : "Die Berechtigungen erlauben Ihnen nicht, Veränderungen vorzunehmen.",

    // Project error strings
    "ERROR_LOADING_PROJECT"             : "Fehler beim Laden des Projekts",
    "OPEN_DIALOG_ERROR"                 : "Fehler beim Erstellen des Öffnen-Dialogs. (Fehler {0})",
    "REQUEST_NATIVE_FILE_SYSTEM_ERROR"  : "Fehler beim Lesen des Verzeichnisses {0}. (Fehler {1})",
    "READ_DIRECTORY_ENTRIES_ERROR"      : "Fehler beim Lesen der Verzeichnisinhalte von {0}. (Fehler {1})",

    // File open/save error string
    "ERROR_OPENING_FILE_TITLE"          : "Fehler beim Öffnen der Datei",
    "ERROR_OPENING_FILE"                : "Beim Öffnen der Datei {0} ist ein Fehler aufgetreten: {1}",
    "ERROR_RELOADING_FILE_TITLE"        : "Fehler beim Laden der Änderungen",
    "ERROR_RELOADING_FILE"              : "Beim Laden der Änderungen der Datei {0} ist ein Fehler aufgetreten: {1}",
    "ERROR_SAVING_FILE_TITLE"           : "Fehler beim Speichern der Datei",
    "ERROR_SAVING_FILE"                 : "Beim Speichern der Datei {0} ist ein Fehler aufgetreten: {1}",
    "INVALID_FILENAME_TITLE"            : "Ungültiger Dateiname",
    "INVALID_FILENAME_MESSAGE"          : "Dateinamen dürfen folgende Zeichen nicht enthalten: /?*:;{}<>\\|",
    "FILE_ALREADY_EXISTS"               : "Die Datei {0} existiert bereits.",
    "ERROR_CREATING_FILE_TITLE"         : "Fehler beim Erstellen der Datei",
    "ERROR_CREATING_FILE"               : "Beim Erstellen der Datei {0} ist ein Fehler aufgetreten: {1}",

    // Application error strings
    "ERROR_BRACKETS_IN_BROWSER_TITLE"   : "Ups! Brackets läuft derzeit leider nocht nicht im Browser.",
    "ERROR_BRACKETS_IN_BROWSER"         : "Brackets wurde in HTML programmiert aber derzeit läuft es nur als Desktop Anwendung, um damit lokale Dateien zu bearbeiten. Bitte benutzen Sie die Anwendung von github.com/adobe/brackets-app.",

    // FileIndexManager error string
    "ERROR_MAX_FILES_TITLE"             : "Fehler beim Indizieren der Dateien",
    "ERROR_MAX_FILES"                   : "Die maximal mögliche Anzahl indizierbarer Datein wurde überschritten. Funktionen, die auf dem Index beruhen, werden möglicherweise nicht korrekt funktionieren.",

    // CSSManager error strings
    "ERROR_PARSE_TITLE"                 : "Fehler beim Interpretieren der CSS Datei(en):",

    // Live Development error strings
    "ERROR_LAUNCHING_BROWSER_TITLE"     : "Fehler beim Starten des Webbrowsers",
    "ERROR_CANT_FIND_CHROME"            : "Google Chrome konnte nicht gefunden werden. Bitte laden Sie den Browser unter google.de/chrome.",
    "ERROR_LAUNCHING_BROWSER"           : "Beim Starten des Webbrowsers ist ein Fehler aufgetreten: (Fehler {0})",

    "LIVE_DEVELOPMENT_ERROR_TITLE"      : "Fehler bei der Live Entwicklung",
    "LIVE_DEVELOPMENT_ERROR_MESSAGE"    : "Beim Aufbauen einer Live Verbindung zu Chrome ist ein Fehler aufgetreten. "
                                                + "Für die Live Entwicklung muss das Remote Debugger Protokoll von Chrome aktiviert sein."
                                                + "

Soll Chrome neu gestartet werden, um das Remote Debugger Protokoll zu aktivieren?",
    "LIVE_DEV_NEED_HTML_MESSAGE"        : "Öffnen Sie erst eine HTML Datei und aktivieren Sie dann die Live Verbindung.",

    "LIVE_DEV_STATUS_TIP_NOT_CONNECTED" : "Live Entwicklung",
    "LIVE_DEV_STATUS_TIP_PROGRESS1"     : "Live Entwicklung: Verbinden...",
    "LIVE_DEV_STATUS_TIP_PROGRESS2"     : "Live Entwicklung: Initialisieren...",
    "LIVE_DEV_STATUS_TIP_CONNECTED"     : "Trennen der Live Verbindung",

    "SAVE_CLOSE_TITLE"                  : "Ungespeicherte Änderungen",
    "SAVE_CLOSE_MESSAGE"                : "Wollen Sie die Änderungen in dem Dokument {0} speichern?",
    "SAVE_CLOSE_MULTI_MESSAGE"          : "Wollen Sie die Änderungen in den folgenden Dateien speichern?",
    "EXT_MODIFIED_TITLE"                : "Externe Änderungen",
    "EXT_MODIFIED_MESSAGE"              : "{0} wurde extern geändert und hat ungespeicherte Änderungen in Brackets."
                                                + "

"
                                                + "Welche Version wollen Sie erhalten?",
    "EXT_DELETED_MESSAGE"               : "{0} wurde extern gelöscht und hat ungespeicherte Änderungen in Brackets."
                                                + "

"
                                                + "Wollen Sie die Änderungen erhalten?",

    "OPEN_FILE"                         : "Datei öffnen",

    // Switch language
    "LANGUAGE_TITLE"                    : "Sprache wechseln",
    "LANGUAGE_MESSAGE"                  : "Bitte wählen Sie die gewünschte Sprache aus der folgenden Liste aus:",
    "LANGUAGE_SUBMIT"                   : "Brackets neu starten",
    "LANGUAGE_CANCEL"                   : "Abbrechen",

    /**
     * Command Name Constants
     */

    // File menu commands
    "FILE_MENU"                           : "Datei",
    "CMD_FILE_NEW"                        : "Neu",
    "CMD_FILE_OPEN"                       : "Öffnen\u2026",
    "CMD_ADD_TO_WORKING_SET"              : "Zum Projekt hinzufügen",
    "CMD_OPEN_FOLDER"                     : "Ordner öffnen\u2026",
    "CMD_FILE_CLOSE"                      : "Schließen",
    "CMD_FILE_CLOSE_ALL"                  : "Alles schließen",
    "CMD_FILE_SAVE"                       : "Speichern",
    "CMD_LIVE_FILE_PREVIEW"               : "Live Entwicklung",
    "CMD_QUIT"                            : "Beenden",

    // Edit menu commands
    "EDIT_MENU"                           : "Bearbeiten",
    "CMD_SELECT_ALL"                      : "Alles auswählen",
    "CMD_FIND"                            : "Suchen",
    "CMD_FIND_IN_FILES"                   : "Im Projekt suchen",
    "CMD_FIND_NEXT"                       : "Weitersuchen (vorwärts)",
    "CMD_FIND_PREVIOUS"                   : "Weitersuchen (rückwärts)",
    "CMD_REPLACE"                         : "Ersetzen",
    "CMD_INDENT"                          : "Einrücken",
    "CMD_UNINDENT"                        : "Ausrücken",
    "CMD_DUPLICATE"                       : "Duplizieren",
    "CMD_COMMENT"                         : "Zeilen (aus-)kommentieren",
    "CMD_LINE_UP"                         : "Zeilen nach oben verschieben",
    "CMD_LINE_DOWN"                       : "Zeilen nach unten verschieben",

    // View menu commands
    "VIEW_MENU"                           : "Ansicht",
    "CMD_HIDE_SIDEBAR"                    : "Seitenleiste verbergen",
    "CMD_SHOW_SIDEBAR"                    : "Seitenleiste zeigen",
    "CMD_INCREASE_FONT_SIZE"              : "Schriftart vergrößern",
    "CMD_DECREASE_FONT_SIZE"              : "Schriftart verkleinern",
    "CMD_RESTORE_FONT_SIZE"               : "Schriftart zurücksetzen",

    // Navigate menu Commands
    "NAVIGATE_MENU"                       : "Navigation",
    "CMD_QUICK_OPEN"                      : "Schnell öffnen",
    "CMD_GOTO_LINE"                       : "Gehe zu Zeile",
    "CMD_GOTO_DEFINITION"                 : "Gehe zu Definition",
    "CMD_TOGGLE_QUICK_EDIT"               : "Schnell bearbeiten",
    "CMD_QUICK_EDIT_PREV_MATCH"           : "Voriger Treffer",
    "CMD_QUICK_EDIT_NEXT_MATCH"           : "Nächster Treffer",
    "CMD_NEXT_DOC"                        : "Nächstes Dokument",
    "CMD_PREV_DOC"                        : "Voriges Dokument",

    // Debug menu commands
    "DEBUG_MENU"                          : "Debug",
    "CMD_REFRESH_WINDOW"                  : "Brackets neu laden",
    "CMD_SHOW_DEV_TOOLS"                  : "Entwicklungswerkzeuge zeigen",
    "CMD_RUN_UNIT_TESTS"                  : "Tests durchführen",
    "CMD_JSLINT"                          : "JSLint aktivieren",
    "CMD_SHOW_PERF_DATA"                  : "Performance Analyse",
    "CMD_NEW_BRACKETS_WINDOW"             : "Neues Brackets Fenster",
    "CMD_USE_TAB_CHARS"                   : "Mit Tabs einrücken",
    "CMD_SWITCH_LANGUAGE"                 : "Sprache wechseln",

    // Help menu commands
    "CMD_ABOUT"                           : "Über",

    // Special commands invoked by the native shell
    "CMD_CLOSE_WINDOW"                    : "Fenster schließen"

});
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules;
var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules;

function github_embed(tag, prefix) {
    return { // Github style block
        token : "support.function",
        regex : "^```" + tag + "\\s*$",
        next  : prefix + "start"
    };
}

var MarkdownHighlightRules = function() {

    // regexp must not have capturing parentheses
    // regexps are ordered -> the first match is used

    this.$rules = {
        "start" : [ {
            token : "empty_line",
            regex : '^$'
        }, { // code span `
            token : ["support.function", "support.function", "support.function"],
            regex : "(`+)([^\\r]*?[^`])(\\1)"
        }, { // code block
            token : "support.function",
            regex : "^[ ]{4}.+"
        }, { // h1
            token: "markup.heading.1",
            regex: "^=+(?=\\s*$)"
        }, { // h2
            token: "markup.heading.1",
            regex: "^\\-+(?=\\s*$)"
        }, { // header
            token : function(value) {
                return "markup.heading." + value.length;
            },
            regex : "^#{1,6}"
        }, github_embed("(?:javascript|js)", "js-"),
           github_embed("xml", "xml-"),
           github_embed("html", "html-"),
           github_embed("css", "css-"),
        { // Github style block
            token : "support.function",
            regex : "^```[a-zA-Z]+\\s*$",
            next  : "githubblock"
        }, { // block quote
            token : "string",
            regex : "^>[ ].+$",
            next  : "blockquote"
        }, { // reference
            token : ["text", "constant", "text", "url", "string", "text"],
            regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$"
        }, { // link by reference
            token : ["text", "string", "text", "constant", "text"],
            regex : "(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"
        }, { // link by url
            token : ["text", "string", "text", "markup.underline", "string", "text"],
            regex : "(\\[)"+
                    "(\\[[^\\]]*\\]|[^\\[\\]]*)"+
                    "(\\]\\([ \\t]*)"+
                    "(<?(?:(?:[^\\(]*?\\([^\\)]*?\\)\\S*?)|(?:.*?))>?)"+
                    "((?:[ \t]*\"(?:.*?)\"[ \\t]*)?)"+
                    "(\\))"
        }, { // HR *
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"
        }, { // HR -
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"
        }, { // HR _
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"
        }, { // list
            token : "markup.list",
            regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",
            next  : "listblock"
        }, { // strong ** __
            token : ["string", "string", "string"],
            regex : "([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
        }, { // emphasis * _
            token : ["string", "string", "string"],
            regex : "([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
        }, { //
            token : ["text", "url", "text"],
            regex : "(<)("+
                      "(?:https?|ftp|dict):[^'\">\\s]+"+
                      "|"+
                      "(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+"+
                    ")(>)"
        }, {
            token : "text",
            regex : "[^\\*_%$`\\[#<>]+"
        } ],

        "listblock" : [ { // Lists only escape on completely blank lines.
            token : "empty_line",
            regex : "^$",
            next  : "start"
        }, {
            token : "markup.list",
            regex : ".+"
        } ],

        "blockquote" : [ { // BLockquotes only escape on blank lines.
            token : "empty_line",
            regex : "^\\s*$",
            next  : "start"
        }, {
            token : "string",
            regex : ".+"
        } ],

        "githubblock" : [ {
            token : "support.function",
            regex : "^```",
            next  : "start"
        }, {
            token : "support.function",
            regex : ".+"
        } ]
    };

    this.embedRules(JavaScriptHighlightRules, "js-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(HtmlHighlightRules, "html-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(CssHighlightRules, "css-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(XmlHighlightRules, "xml-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);
};
oop.inherits(MarkdownHighlightRules, TextHighlightRules);

exports.MarkdownHighlightRules = MarkdownHighlightRules;
});
<commit_msg>Update lib/ace/mode/markdown_highlight_rules.js<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules;
var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules;

function github_embed(tag, prefix) {
    return { // Github style block
        token : "support.function",
        regex : "^```" + tag + "\\s*$",
        next  : prefix + "start"
    };
}

var MarkdownHighlightRules = function() {

    // regexp must not have capturing parentheses
    // regexps are ordered -> the first match is used

    this.$rules = {
        "start" : [ {
            token : "empty_line",
            regex : '^$'
        }, { // code span `
            token : ["support.function", "support.function", "support.function"],
            regex : "(`+)([^\\r]*?[^`])(\\1)"
        }, { // code block
            token : "support.function",
            regex : "^[ ]{4}.+"
        }, { // h1
            token: "markup.heading.1",
            regex: "^=+(?=\\s*$)"
        }, { // h2
            token: "markup.heading.2",
            regex: "^\\-+(?=\\s*$)"
        }, { // header
            token : function(value) {
                return "markup.heading." + value.length;
            },
            regex : "^#{1,6}"
        }, github_embed("(?:javascript|js)", "js-"),
           github_embed("xml", "xml-"),
           github_embed("html", "html-"),
           github_embed("css", "css-"),
        { // Github style block
            token : "support.function",
            regex : "^```[a-zA-Z]+\\s*$",
            next  : "githubblock"
        }, { // block quote
            token : "string",
            regex : "^>[ ].+$",
            next  : "blockquote"
        }, { // reference
            token : ["text", "constant", "text", "url", "string", "text"],
            regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$"
        }, { // link by reference
            token : ["text", "string", "text", "constant", "text"],
            regex : "(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"
        }, { // link by url
            token : ["text", "string", "text", "markup.underline", "string", "text"],
            regex : "(\\[)"+
                    "(\\[[^\\]]*\\]|[^\\[\\]]*)"+
                    "(\\]\\([ \\t]*)"+
                    "(<?(?:(?:[^\\(]*?\\([^\\)]*?\\)\\S*?)|(?:.*?))>?)"+
                    "((?:[ \t]*\"(?:.*?)\"[ \\t]*)?)"+
                    "(\\))"
        }, { // HR *
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"
        }, { // HR -
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"
        }, { // HR _
            token : "constant",
            regex : "^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"
        }, { // list
            token : "markup.list",
            regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",
            next  : "listblock"
        }, { // strong ** __
            token : ["string", "string", "string"],
            regex : "([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
        }, { // emphasis * _
            token : ["string", "string", "string"],
            regex : "([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
        }, { //
            token : ["text", "url", "text"],
            regex : "(<)("+
                      "(?:https?|ftp|dict):[^'\">\\s]+"+
                      "|"+
                      "(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+"+
                    ")(>)"
        }, {
            token : "text",
            regex : "[^\\*_%$`\\[#<>]+"
        } ],

        "listblock" : [ { // Lists only escape on completely blank lines.
            token : "empty_line",
            regex : "^$",
            next  : "start"
        }, {
            token : "markup.list",
            regex : ".+"
        } ],

        "blockquote" : [ { // BLockquotes only escape on blank lines.
            token : "empty_line",
            regex : "^\\s*$",
            next  : "start"
        }, {
            token : "string",
            regex : ".+"
        } ],

        "githubblock" : [ {
            token : "support.function",
            regex : "^```",
            next  : "start"
        }, {
            token : "support.function",
            regex : ".+"
        } ]
    };

    this.embedRules(JavaScriptHighlightRules, "js-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(HtmlHighlightRules, "html-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(CssHighlightRules, "css-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);

    this.embedRules(XmlHighlightRules, "xml-", [{
       token : "support.function",
       regex : "^```",
       next  : "start"
    }]);
};
oop.inherits(MarkdownHighlightRules, TextHighlightRules);

exports.MarkdownHighlightRules = MarkdownHighlightRules;
});
<|endoftext|>