<commit_before>// Copyright 2002-2015, University of Colorado Boulder

/**
 * Javascript for translate-sim.html
 * @author Michael Kauzmann
 * @author Aaron Davis
 * @author John Blanco
 */
/* eslint-env node */
'use strict';

// constants
var SINGLE_BRACE_PATTERN_REGULAR_EXP = /\{\d+\}/g;
var DOUBLE_BRACE_PATTERN_REGULAR_EXP = /\{\{\w+\}\}/g;

/**
 * Modified from http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity/3866442#3866442
 * @param contentEditableElement
 */
function setEndOfContentEditable( contentEditableElement ) {

  var range;

  // Firefox, Chrome, Opera, Safari, IE 9+
  if ( document.createRange ) {
    range = document.createRange();
    range.selectNodeContents( contentEditableElement );

    // uncomment the following line to move the cursor to the end of the input instead of selecting all
    // range.collapse( false );
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange( range );
  }

  // IE 8 and lower
  else if ( document.selection ) {
    range = document.body.createTextRange();
    range.moveToElementText( contentEditableElement );

    // uncomment the following line to move the cursor to the end of the input instead of selecting all
    // range.collapse( false );
    range.select();
  }
}

$( document ).ready( function() {

  var testButtonTop = document.getElementById( 'testButtonTop' );
  var saveButtonTop = document.getElementById( 'saveButtonTop' );
  var testButtonBottom = document.getElementById( 'testButtonBottom' );
  var saveButtonBottom = document.getElementById( 'saveButtonBottom' );
  var simData = document.getElementById( 'simData' );
  var rtl = simData.getAttribute( 'data-direction' ) === 'rtl';
  var savedSpans = $( '.savedSpan' );

  // Var to help only restore save button once from inputs
  var once = false;

  // selector for content-editable divs (where the user input goes)
  var inputSelector = '.rosetta-table div[contenteditable]';
  var inputs = $( inputSelector );

  /**
   * Copy all of the content-editable text into the hidden inputs to be submitted
   */
  function syncInputs() {
    inputs.each( function( index, element ) {
      var contentEditable = $( element );
      var input = contentEditable.next().get( 0 );
      input.value = contentEditable.text();
    } );
  }

  /**
   * Handler for the "Test" button on the translate page.  This creates a URL with a query parameter that contains all
   * of the translated strings and opens the sim with them so that the user can see how the translation looks.
   */
  function testButtonEventListener() {
    var simUrl = simData.getAttribute( 'data-sim-url' );
    var stringsToReplace = {};
    var inputs = $( '.rosetta-table tr' );
    inputs.each( function( i, row ) {
      var contentEditable = $( $( row ).find( 'div[contenteditable]' ).get( 0 ) );
      if ( contentEditable ) {
        var translation = contentEditable.text();
        var repo = row.getAttribute( 'data-string-repo' );
        if ( repo && translation && translation.length > 0 ) {
          // add RTL embedding markers for RTL strings
          if ( rtl ) {
            translation = '\u202b' + translation + '\u202c';
          }
          else {
            translation = '\u202a' + translation + '\u202c';
          }
          var stringKey = repo.replace( /-/g, '_' ).toUpperCase() + '/' + row.getAttribute( 'data-string-key' );
          stringsToReplace[ stringKey ] = translation;
        }
      }
    } );
    var encodedStrings = encodeURIComponent( JSON.stringify( stringsToReplace ) );
    encodedStrings = encodedStrings.replace( /%5C%5Cn/g, '%5Cn' ); // put back newlines

    var win = window.open( simUrl + '?' + 'strings=' + encodedStrings, '_blank' );
    win.focus();
  }

  testButtonTop.addEventListener( 'click', testButtonEventListener );
  testButtonBottom.addEventListener( 'click', testButtonEventListener );

  function saveButtonEventListener() {
    syncInputs();

    var strings = {};
    $( 'td input' ).each( function( index, item ) {
      strings[ item.name ] = item.value;
    } );

    $.post( '/translate/sim/save/' + simData.getAttribute( 'data-sim-name' ) + '/' + simData.getAttribute( 'data-locale-name' ), strings, function( data ) {
      $( '.saving-gif' ).hide();

      if ( data.success ) {
        // grey out both save buttons, add saved below
        saveButtonTop.style.backgroundColor = 'grey';
        saveButtonTop.style.borderColor = 'black';
        saveButtonTop.disabled = true;
        saveButtonBottom.style.backgroundColor = 'grey';
        saveButtonBottom.style.borderColor = 'black';
        saveButtonBottom.disabled = true;
        savedSpans.attr( 'style', 'visibility: visible; color: green;' );
        savedSpans.html( '

Saved' );
        once = false;
      }
      else {
        savedSpans.attr( 'style', 'visibility: visible; color: red;' );
        savedSpans.html( '

Error Saving' );
      }
    } );
    $( '.saving-gif' ).show();
  }

  saveButtonTop.addEventListener( 'click', saveButtonEventListener );
  saveButtonBottom.addEventListener( 'click', saveButtonEventListener );

  /**
   * Restore a button to its original (non-greyed out) state
   * @param button
   */
  function restoreButton( button ) {
    button.style.backgroundColor = '#2a326a';
    button.style.borderColor = '#1A87B9';
    button.disabled = false;
    $( '#' + button.id ).hover( function() {
        $( this ).css( {
          background: '#6D77BD'
        } );
      },
      function() {
        $( this ).css( {
          background: '#2a326a'
        } );
      } );
  }

  // add highlight to '\n' and '{\d}' so users are aware that this is treated specially
  $( 'td:nth-child(2)' ).each( function( index, element ) {
    $( element ).html( $( element ).html().replace( /(\{\d\}|\\n)/g, '$1' ) );
  } );

  /**
   * Make sure a string that should have pattern fields has the required fields in the translated string
   * @param row - the row of the table, including the english string and the input string
   * @returns {boolean}
   */
  function validateRow( row ) {

    var validated = true;

    // get the data cells for this row
    var tableDataCells = $( row ).find( 'td' );

    // only validate if there is some data (this skips header rows)
    if ( tableDataCells.length > 0 ) {

      // get the non-translated string
      var nonTranslatedString = $( tableDataCells[ 1 ] ).text();

      // get the user-submitted translated string
      var tableDataCell = $( tableDataCells[ 2 ] );
      var input = $( tableDataCell.find( 'div[contenteditable]' ).get( 0 ) );
      var translatedString = input.text();

      // create lists of the placeholders in the non-translated string
      var singleBracePlaceHolders = nonTranslatedString.match( SINGLE_BRACE_PATTERN_REGULAR_EXP ) || [];
      var doubleBracePlaceHolders = nonTranslatedString.match( DOUBLE_BRACE_PATTERN_REGULAR_EXP ) || [];

      // create the arrays where any missing or extra placeholders in the strings will be tracked
      var missingPlaceholders = [];
      var extraPlaceholders = [];

      // it is valid for the string to be empty, i.e. no translation submitted, so only validate if it is NOT empty
      if ( translatedString !== '' ) {

        var singleBracePlaceholdersInTranslation = translatedString.match( SINGLE_BRACE_PATTERN_REGULAR_EXP ) || [];
        var doubleBracePlaceholdersInTranslation = translatedString.match( DOUBLE_BRACE_PATTERN_REGULAR_EXP ) || [];

        var placeHolders = doubleBracePlaceHolders.concat( singleBracePlaceHolders );
        var placeHoldersInTranslation = doubleBracePlaceholdersInTranslation.concat( singleBracePlaceholdersInTranslation );

        // make sure every placeholder that exists in the untranslated string exists in the translation
        for ( var i = 0; i < placeHolders.length; i++ ) {
          if ( translatedString.length > 0 && translatedString.indexOf( placeHolders[ i ] ) === -1 ) {
            validated = false;
            missingPlaceholders.push( placeHolders[ i ] );
          }
          if ( placeHoldersInTranslation ) {
            var index = placeHoldersInTranslation.indexOf( placeHolders[ i ] );
            if ( index !== -1 ) {
              placeHoldersInTranslation.splice( index, 1 );
            }
          }
        }

        // make sure that no extra placeholders exist in the translation
        if ( placeHoldersInTranslation && placeHoldersInTranslation.length ) {
          validated = false;
          extraPlaceholders = placeHoldersInTranslation;
        }
      }

      // remove any previous error message that may be present
      tableDataCell.find( 'img:last-child' ).remove();

      // if the validation failed, add an error message
      if ( missingPlaceholders.length || extraPlaceholders.length ) {
        input.css( { outline: '1px solid red' } );
        var img = $( '', { src: '/translate/img/warning.png', class: 'warning' } );
        tableDataCell.append( img );

        img.click( function() {
          var errorMessage = [ 'Your translation has the following errors:\n' ];
          if ( missingPlaceholders.length ) {
            errorMessage.push( 'missing placeholder(s) in submission: ' + missingPlaceholders.join( ', ' ) );
          }
          if ( extraPlaceholders.length ) {
            errorMessage.push( 'extra placeholder(s) in submission: ' + extraPlaceholders.join( ', ' ) );
          }
          alert( errorMessage.join( '\n' ) );
        } );
      }
      else {
        input.css( { outline: 'initial' } );
      }
    }

    return validated;
  }

  /**
   * Make sure every row has the required patterns
   * @returns {boolean}
   */
  function validatePatterns() {
    var validated = true;
    $( 'tr' ).each( function( index, item ) {
      if ( !validateRow( item ) ) {
        validated = false;
      }
    } );
    return validated;
  }

// validate the inputs before submitting the form
  $( '#strings' ).submit( function( event ) {
    if ( !validatePatterns() ) {
      $( '.validation-message' ).text( 'Your translation has MessageFormat errors. Please correct these before submitting.' );
      event.preventDefault();
    }
    else {
      // TODO: DO NOT COMMIT CHANGES BELOW
      // $( '.validation-message' ).text( '' );
      $( '.validation-message' ).text( 'would submit now if not bypassed' );

      // on submit make sure all of the inputs are synced with the content editable divs
      // syncInputs();
      event.preventDefault();
    }
  } );

// fix dir and text-align for RTL languages
  if ( rtl ) {
    inputs.attr( 'dir', 'rtl' );
    inputs.css( 'text-align', 'right' );
  }

// disable pressing enter in inputs because it complicates things by adding
 and possibly other html
  $( document ).on( 'keypress', inputSelector, function( e ) {
    return e.which !== 13;
  } );

// on every change, copy the content from the editable div to a hidden input so it gets submitted with the form
  $( document ).on( 'keyup paste', inputSelector, function( e ) {
    var contentEditable = $( this );
    var input = contentEditable.next().get( 0 );
    input.value = contentEditable.text();

    // need to set a timeout after pasting in so that the paste has time to take effect
    if ( e.type === 'paste' ) {
      setTimeout( function() {
        input.value = contentEditable.text();
        contentEditable.text( contentEditable.text() );
      }, 50 );
    }

    // undo-gray saved button on any input change
    if ( !once ) {
      $( '.savedSpan' ).attr( 'style', 'visibility: hidden' );
      restoreButton( saveButtonTop );
      restoreButton( saveButtonBottom );
      once = true;
    }
  } );

// on blur, validate the row to make sure it has the correct patterns
  $( document ).on( 'blur', inputSelector, function( e ) {
    var row = this.parentNode.parentNode;
    validateRow( row );
  } );

  $( document ).on( 'focus', inputSelector, function( e ) {
    setEndOfContentEditable( this );
  } );

} )
;
<commit_msg>backed out some debug code that got committed, see #155<commit_after>// Copyright 2002-2015, University of Colorado Boulder

/**
 * Javascript for translate-sim.html
 * @author Michael Kauzmann
 * @author Aaron Davis
 * @author John Blanco
 */
/* eslint-env node */
'use strict';

// constants
var SINGLE_BRACE_PATTERN_REGULAR_EXP = /\{\d+\}/g;
var DOUBLE_BRACE_PATTERN_REGULAR_EXP = /\{\{\w+\}\}/g;

/**
 * Modified from http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity/3866442#3866442
 * @param contentEditableElement
 */
function setEndOfContentEditable( contentEditableElement ) {

  var range;

  // Firefox, Chrome, Opera, Safari, IE 9+
  if ( document.createRange ) {
    range = document.createRange();
    range.selectNodeContents( contentEditableElement );

    // uncomment the following line to move the cursor to the end of the input instead of selecting all
    // range.collapse( false );
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange( range );
  }

  // IE 8 and lower
  else if ( document.selection ) {
    range = document.body.createTextRange();
    range.moveToElementText( contentEditableElement );

    // uncomment the following line to move the cursor to the end of the input instead of selecting all
    // range.collapse( false );
    range.select();
  }
}

$( document ).ready( function() {

  var testButtonTop = document.getElementById( 'testButtonTop' );
  var saveButtonTop = document.getElementById( 'saveButtonTop' );
  var testButtonBottom = document.getElementById( 'testButtonBottom' );
  var saveButtonBottom = document.getElementById( 'saveButtonBottom' );
  var simData = document.getElementById( 'simData' );
  var rtl = simData.getAttribute( 'data-direction' ) === 'rtl';
  var savedSpans = $( '.savedSpan' );

  // Var to help only restore save button once from inputs
  var once = false;

  // selector for content-editable divs (where the user input goes)
  var inputSelector = '.rosetta-table div[contenteditable]';
  var inputs = $( inputSelector );

  /**
   * Copy all of the content-editable text into the hidden inputs to be submitted
   */
  function syncInputs() {
    inputs.each( function( index, element ) {
      var contentEditable = $( element );
      var input = contentEditable.next().get( 0 );
      input.value = contentEditable.text();
    } );
  }

  /**
   * Handler for the "Test" button on the translate page.  This creates a URL with a query parameter that contains all
   * of the translated strings and opens the sim with them so that the user can see how the translation looks.
   */
  function testButtonEventListener() {
    var simUrl = simData.getAttribute( 'data-sim-url' );
    var stringsToReplace = {};
    var inputs = $( '.rosetta-table tr' );
    inputs.each( function( i, row ) {
      var contentEditable = $( $( row ).find( 'div[contenteditable]' ).get( 0 ) );
      if ( contentEditable ) {
        var translation = contentEditable.text();
        var repo = row.getAttribute( 'data-string-repo' );
        if ( repo && translation && translation.length > 0 ) {
          // add RTL embedding markers for RTL strings
          if ( rtl ) {
            translation = '\u202b' + translation + '\u202c';
          }
          else {
            translation = '\u202a' + translation + '\u202c';
          }
          var stringKey = repo.replace( /-/g, '_' ).toUpperCase() + '/' + row.getAttribute( 'data-string-key' );
          stringsToReplace[ stringKey ] = translation;
        }
      }
    } );
    var encodedStrings = encodeURIComponent( JSON.stringify( stringsToReplace ) );
    encodedStrings = encodedStrings.replace( /%5C%5Cn/g, '%5Cn' ); // put back newlines

    var win = window.open( simUrl + '?' + 'strings=' + encodedStrings, '_blank' );
    win.focus();
  }

  testButtonTop.addEventListener( 'click', testButtonEventListener );
  testButtonBottom.addEventListener( 'click', testButtonEventListener );

  function saveButtonEventListener() {
    syncInputs();

    var strings = {};
    $( 'td input' ).each( function( index, item ) {
      strings[ item.name ] = item.value;
    } );

    $.post( '/translate/sim/save/' + simData.getAttribute( 'data-sim-name' ) + '/' + simData.getAttribute( 'data-locale-name' ), strings, function( data ) {
      $( '.saving-gif' ).hide();

      if ( data.success ) {
        // grey out both save buttons, add saved below
        saveButtonTop.style.backgroundColor = 'grey';
        saveButtonTop.style.borderColor = 'black';
        saveButtonTop.disabled = true;
        saveButtonBottom.style.backgroundColor = 'grey';
        saveButtonBottom.style.borderColor = 'black';
        saveButtonBottom.disabled = true;
        savedSpans.attr( 'style', 'visibility: visible; color: green;' );
        savedSpans.html( '

Saved' );
        once = false;
      }
      else {
        savedSpans.attr( 'style', 'visibility: visible; color: red;' );
        savedSpans.html( '

Error Saving' );
      }
    } );
    $( '.saving-gif' ).show();
  }

  saveButtonTop.addEventListener( 'click', saveButtonEventListener );
  saveButtonBottom.addEventListener( 'click', saveButtonEventListener );

  /**
   * Restore a button to its original (non-greyed out) state
   * @param button
   */
  function restoreButton( button ) {
    button.style.backgroundColor = '#2a326a';
    button.style.borderColor = '#1A87B9';
    button.disabled = false;
    $( '#' + button.id ).hover( function() {
        $( this ).css( {
          background: '#6D77BD'
        } );
      },
      function() {
        $( this ).css( {
          background: '#2a326a'
        } );
      } );
  }

  // add highlight to '\n' and '{\d}' so users are aware that this is treated specially
  $( 'td:nth-child(2)' ).each( function( index, element ) {
    $( element ).html( $( element ).html().replace( /(\{\d\}|\\n)/g, '$1' ) );
  } );

  /**
   * Make sure a string that should have pattern fields has the required fields in the translated string
   * @param row - the row of the table, including the english string and the input string
   * @returns {boolean}
   */
  function validateRow( row ) {

    var validated = true;

    // get the data cells for this row
    var tableDataCells = $( row ).find( 'td' );

    // only validate if there is some data (this skips header rows)
    if ( tableDataCells.length > 0 ) {

      // get the non-translated string
      var nonTranslatedString = $( tableDataCells[ 1 ] ).text();

      // get the user-submitted translated string
      var tableDataCell = $( tableDataCells[ 2 ] );
      var input = $( tableDataCell.find( 'div[contenteditable]' ).get( 0 ) );
      var translatedString = input.text();

      // create lists of the placeholders in the non-translated string
      var singleBracePlaceHolders = nonTranslatedString.match( SINGLE_BRACE_PATTERN_REGULAR_EXP ) || [];
      var doubleBracePlaceHolders = nonTranslatedString.match( DOUBLE_BRACE_PATTERN_REGULAR_EXP ) || [];

      // create the arrays where any missing or extra placeholders in the strings will be tracked
      var missingPlaceholders = [];
      var extraPlaceholders = [];

      // it is valid for the string to be empty, i.e. no translation submitted, so only validate if it is NOT empty
      if ( translatedString !== '' ) {

        var singleBracePlaceholdersInTranslation = translatedString.match( SINGLE_BRACE_PATTERN_REGULAR_EXP ) || [];
        var doubleBracePlaceholdersInTranslation = translatedString.match( DOUBLE_BRACE_PATTERN_REGULAR_EXP ) || [];

        var placeHolders = doubleBracePlaceHolders.concat( singleBracePlaceHolders );
        var placeHoldersInTranslation = doubleBracePlaceholdersInTranslation.concat( singleBracePlaceholdersInTranslation );

        // make sure every placeholder that exists in the untranslated string exists in the translation
        for ( var i = 0; i < placeHolders.length; i++ ) {
          if ( translatedString.length > 0 && translatedString.indexOf( placeHolders[ i ] ) === -1 ) {
            validated = false;
            missingPlaceholders.push( placeHolders[ i ] );
          }
          if ( placeHoldersInTranslation ) {
            var index = placeHoldersInTranslation.indexOf( placeHolders[ i ] );
            if ( index !== -1 ) {
              placeHoldersInTranslation.splice( index, 1 );
            }
          }
        }

        // make sure that no extra placeholders exist in the translation
        if ( placeHoldersInTranslation && placeHoldersInTranslation.length ) {
          validated = false;
          extraPlaceholders = placeHoldersInTranslation;
        }
      }

      // remove any previous error message that may be present
      tableDataCell.find( 'img:last-child' ).remove();

      // if the validation failed, add an error message
      if ( missingPlaceholders.length || extraPlaceholders.length ) {
        input.css( { outline: '1px solid red' } );
        var img = $( '', { src: '/translate/img/warning.png', class: 'warning' } );
        tableDataCell.append( img );

        img.click( function() {
          var errorMessage = [ 'Your translation has the following errors:\n' ];
          if ( missingPlaceholders.length ) {
            errorMessage.push( 'missing placeholder(s) in submission: ' + missingPlaceholders.join( ', ' ) );
          }
          if ( extraPlaceholders.length ) {
            errorMessage.push( 'extra placeholder(s) in submission: ' + extraPlaceholders.join( ', ' ) );
          }
          alert( errorMessage.join( '\n' ) );
        } );
      }
      else {
        input.css( { outline: 'initial' } );
      }
    }

    return validated;
  }

  /**
   * Make sure every row has the required patterns
   * @returns {boolean}
   */
  function validatePatterns() {
    var validated = true;
    $( 'tr' ).each( function( index, item ) {
      if ( !validateRow( item ) ) {
        validated = false;
      }
    } );
    return validated;
  }

// validate the inputs before submitting the form
  $( '#strings' ).submit( function( event ) {
    if ( !validatePatterns() ) {
      $( '.validation-message' ).text( 'Your translation has MessageFormat errors. Please correct these before submitting.' );
      event.preventDefault();
    }
    else {
      $( '.validation-message' ).text( '' );

      // on submit make sure all of the inputs are synced with the content editable divs
      syncInputs();
    }
  } );

// fix dir and text-align for RTL languages
  if ( rtl ) {
    inputs.attr( 'dir', 'rtl' );
    inputs.css( 'text-align', 'right' );
  }

// disable pressing enter in inputs because it complicates things by adding
 and possibly other html
  $( document ).on( 'keypress', inputSelector, function( e ) {
    return e.which !== 13;
  } );

// on every change, copy the content from the editable div to a hidden input so it gets submitted with the form
  $( document ).on( 'keyup paste', inputSelector, function( e ) {
    var contentEditable = $( this );
    var input = contentEditable.next().get( 0 );
    input.value = contentEditable.text();

    // need to set a timeout after pasting in so that the paste has time to take effect
    if ( e.type === 'paste' ) {
      setTimeout( function() {
        input.value = contentEditable.text();
        contentEditable.text( contentEditable.text() );
      }, 50 );
    }

    // undo-gray saved button on any input change
    if ( !once ) {
      $( '.savedSpan' ).attr( 'style', 'visibility: hidden' );
      restoreButton( saveButtonTop );
      restoreButton( saveButtonBottom );
      once = true;
    }
  } );

// on blur, validate the row to make sure it has the correct patterns
  $( document ).on( 'blur', inputSelector, function( e ) {
    var row = this.parentNode.parentNode;
    validateRow( row );
  } );

  $( document ).on( 'focus', inputSelector, function( e ) {
    setEndOfContentEditable( this );
  } );

} )
;
<|endoftext|>


<commit_before>$(document).ready(function () {

    // Get all of the clients settings
    get();

    // Save all of the clients settings
    $(".save").click(function () {
        // Setting validation
        if ($("#settings-form").valid()) {
            save();
        }
    });

    // Triggered when the clients settings have been loaded
    $("body").on("settings_loaded", function (event, settings) {
        // Clear the rules div
        $("#rules").html('');

        // Add any custom rules
        $.each(settings.rules, function (key, rule) {
            var template = $("#rule-template").clone();
            template.prop('id', '');
            template.find('.rule-name').text(rule.name);

            $.each(rule, function (k, v) {
                if (k !== "name" && k !== "order") {
                    template.find('.rule-attributes').append('
' + k.capitalizeFirstLetter() + ': ' + v + '
');
                }

                // Append this attribute into a hidden field (used for saving later down the line)
                template.append('<input type="hidden" id="' + k + '" value="' + v + '">');
            });

            template.show();

            $("#rules").append(template);
        });

        // Clear any type select boxes
        $(".types").html('');

        // Add the field types to the dropdowns
        $.each(settingTemplates, function (categoryName, items) {
            // Add the optgroup
            var html = '<optgroup label="' + categoryName + '">';

            // Add each item in this category
            $.each(items, function (key, item) {
                html = html + '<option value="' + key + '">' + item.public_name + '</option>';
            });

            // Close the optgroup
            html = html + '</optgroup>';

            // Append the category and it items to the select
            $(".types").append(html);
        });
    });

    // Show any additional fields after selecting a rule type
    $(".types").change(function () {
        createAdditionalFields($(this));
    });

    // Show the additional fields while the "Add rule" modal opens
    $('#addRuleModal').on('show.bs.modal', function (e) {
        createAdditionalFields($('#addRuleModal').find('.types'));
    });

    // Show the create rule modal
    $("#create-rule").click(function () {
        if ($("#addRuleForm").valid()) {
            var template = $("#rule-template").clone();

            $("#addRuleForm").find('input').each(function () {
                // Append this attribute into a hidden field (used for saving later down the line)
                template.append('<input type="hidden" id="' + $(this).prop('id') + '" value="' + $(this).val() + '">');
            });

            // Append the type (as this is a select and not an input)
            var type = $("#addRuleForm").find('#type').find(":selected").val();
            template.append('<input type="hidden" id="type" value="' + type + '">');

            $("#rules").append(template);

            // Save and reload
            reload();

            // Scroll to the new rule
            $("html, body").animate({scrollTop: $(document).height()}, "slow");

            // Clear the elements in the add rule modal
            var form = $("#addRuleForm");
            form.find('input[id=name]').val('');
            form.find('#type').val('username').trigger('change');

            // Hide the add rule modal
            $("#addRuleModal").modal('hide');
        }
    });

    // Delete a rule
    $('body').on('click', '.delete-rule', function () {
        if (confirm("Are you sure you want to delete this rule?")) {
            // Remove the rule
            $(this).closest('div[data-rule]').remove();

            // Save and reload
            reload();
        }
    });

    // Custom validation rules
    // These rules aren't built to prevent 100% of bad input but to stop anything obviously incorrect being inputted
    // The user should know what they are doing when changing these settings
    $.validator.addMethod('validRegEx', function (value) {
        try {
            new RandExp(value).gen();
        } catch (err) {
            console.log(err.message);
            return false;
        }
        return true;
    }, 'Please enter a valid regular expression');

    // Rule to determine if the value is 4 digits
    $.validator.addMethod('year', function (value) {
        var output = new RandExp(value).gen();
        return /^\d{4}$/.test(output);
    }, 'The value of this expression must return a 4 digit number');

    // Rule to determine a valid time (HH:MM)
    $.validator.addMethod('time', function (value) {
        var output = new RandExp(value).gen();
        return /^([01]\d|2[0-3]):([0-5]\d)$/.test(output);
    }, 'This value of this expression must return a valid time (HH:MM)');

    // Validation
    $("#settings-form").validate({
        rules: {
            date_range: {
                validRegEx: true,
                year: true
            },
            time: {
                validRegEx: true,
                time: true
            }
        },
        onfocusout: function (element) {
            jQuery(element).valid()
        },
        errorElement: "div",
        errorPlacement: function (error, element) {
            error.insertBefore(element);
        }
    });
});

/**
 * Save the clients settings
 */
function save(settings) {
    // Create the rules object
    var rules = [];

    // Get all the rules and add them to our rules object
    $('#rules').find('.mui-panel').each(function () {
        var rule = {};

        $(this).find('input[type=hidden]').each(function () {
            rule[$(this).prop('id')] = $(this).val();
        });

        rules.push(rule);
    });

    if (typeof settings === 'undefined') {
        settings = {
            fill_all_form: $("#fill_all_form").is(':checked'),
            ignore_checkboxes: $("#ignore_checkboxes").is(':checked'),
            date_types: $('#date_types').find(":selected").val(),
            date_range: $("#date_range").val(),
            time: $("#time").val(),
            rules: rules,
            date_now: $("#date_now").is(':checked'),
            time_now: $("#time_now").is(':checked')
        };
    }

    chrome.storage.sync.set(settings, function () {
        // Update status to let user know options were saved.
        $(".save-wrapper p span").fadeIn();
        setTimeout(function () {
            $(".save-wrapper p span").fadeOut('slow');
        }, 850);
    });
}

/**
 * Get the clients settings
 */
function get() {
    chrome.storage.sync.get(defaultSettings, function (items) {
        $("#fill_all_form").prop('checked', items.fill_all_form);
        $("#ignore_checkboxes").prop('checked', items.ignore_checkboxes);
        $("#date_types").val(items.date_types);
        $("#date_range").val(items.date_range);
        $("#time").val(items.time);
        $("#date_now").prop('checked', items.date_now);
        $("#time_now").prop('checked', items.time_now);
        $("body").trigger("settings_loaded", [items]);
    });
}

/**
 * Reload the clients settings
 */
function reload(settings) {
    save(settings);
    get();
}

/**
 * Create the additional fields in the "New rule" modal
 * @param select
 */
function createAdditionalFields(select) {
    // Find the template for this type
    var type = select.find(":selected").val();
    var template = null;
    $.each(settingTemplates, function (categoryName, items) {
        $.each(items, function (key, item) {
            if (key == type) {
                template = item;
                return false;
            }
        });

        // We don't need to continue searching if we found the template
        if (template != null) {
            return false;
        }
    });

    // If we found a template
    if (template) {
        // Clear any previous additional fields
        $("#additional_fields").html('');

        // Add the additional fields
        $.each(template, function (key, value) {
            if (key !== 'public_name') {
                // Determine the type of this field
                var type = jQuery.isNumeric(value) ? 'number' : 'text';

                // Create the input
                var html = '';
                html = html + '
'
                html = html + '' + key.capitalizeFirstLetter() + '';
                html = html + '<input class="form-control" type="' + type + '" id="' + key + '" name="' + key + '" value="' + value + '" required>';
                html = html + '
';

                // Append the input
                $("#additional_fields").append(html);
            }
        });

        // Add the validation
        $("#addRuleForm").validate();
    } else {
        // Fatal error, alert the user
        swal('Error', 'No rule template found for ' + type + '!', 'error');
    }
}<commit_msg>Ability to add helper text to an rule<commit_after>$(document).ready(function () {

    // Get all of the clients settings
    get();

    // Save all of the clients settings
    $(".save").click(function () {
        // Setting validation
        if ($("#settings-form").valid()) {
            save();
        }
    });

    // Triggered when the clients settings have been loaded
    $("body").on("settings_loaded", function (event, settings) {
        // Clear the rules div
        $("#rules").html('');

        // Add any custom rules
        $.each(settings.rules, function (key, rule) {
            var template = $("#rule-template").clone();
            template.prop('id', '');
            template.find('.rule-name').text(rule.name);

            $.each(rule, function (k, v) {
                if (k !== "name" && k !== "order" && !k.includes('_help')) {
                    template.find('.rule-attributes').append('
' + k.capitalizeFirstLetter() + ': ' + v + '
');
                }

                // Append this attribute into a hidden field (used for saving later down the line)
                template.append('<input type="hidden" id="' + k + '" value="' + v + '">');
            });

            template.show();

            $("#rules").append(template);
        });

        // Clear any type select boxes
        $(".types").html('');

        // Add the field types to the dropdowns
        $.each(settingTemplates, function (categoryName, items) {
            // Add the optgroup
            var html = '<optgroup label="' + categoryName + '">';

            // Add each item in this category
            $.each(items, function (key, item) {
                html = html + '<option value="' + key + '">' + item.public_name + '</option>';
            });

            // Close the optgroup
            html = html + '</optgroup>';

            // Append the category and it items to the select
            $(".types").append(html);
        });
    });

    // Show any additional fields after selecting a rule type
    $(".types").change(function () {
        createAdditionalFields($(this));
    });

    // Show the additional fields while the "Add rule" modal opens
    $('#addRuleModal').on('show.bs.modal', function (e) {
        createAdditionalFields($('#addRuleModal').find('.types'));
    });

    // Show the create rule modal
    $("#create-rule").click(function () {
        if ($("#addRuleForm").valid()) {
            var template = $("#rule-template").clone();

            $("#addRuleForm").find('input').each(function () {
                // Append this attribute into a hidden field (used for saving later down the line)
                template.append('<input type="hidden" id="' + $(this).prop('id') + '" value="' + $(this).val() + '">');
            });

            // Append the type (as this is a select and not an input)
            var type = $("#addRuleForm").find('#type').find(":selected").val();
            template.append('<input type="hidden" id="type" value="' + type + '">');

            $("#rules").append(template);

            // Save and reload
            reload();

            // Scroll to the new rule
            $("html, body").animate({scrollTop: $(document).height()}, "slow");

            // Clear the elements in the add rule modal
            var form = $("#addRuleForm");
            form.find('input[id=name]').val('');
            form.find('#type').val('username').trigger('change');

            // Hide the add rule modal
            $("#addRuleModal").modal('hide');
        }
    });

    // Delete a rule
    $('body').on('click', '.delete-rule', function () {
        if (confirm("Are you sure you want to delete this rule?")) {
            // Remove the rule
            $(this).closest('div[data-rule]').remove();

            // Save and reload
            reload();
        }
    });

    // Custom validation rules
    // These rules aren't built to prevent 100% of bad input but to stop anything obviously incorrect being inputted
    // The user should know what they are doing when changing these settings
    $.validator.addMethod('validRegEx', function (value) {
        try {
            new RandExp(value).gen();
        } catch (err) {
            console.log(err.message);
            return false;
        }
        return true;
    }, 'Please enter a valid regular expression');

    // Rule to determine if the value is 4 digits
    $.validator.addMethod('year', function (value) {
        var output = new RandExp(value).gen();
        return /^\d{4}$/.test(output);
    }, 'The value of this expression must return a 4 digit number');

    // Rule to determine a valid time (HH:MM)
    $.validator.addMethod('time', function (value) {
        var output = new RandExp(value).gen();
        return /^([01]\d|2[0-3]):([0-5]\d)$/.test(output);
    }, 'This value of this expression must return a valid time (HH:MM)');

    // Validation
    $("#settings-form").validate({
        rules: {
            date_range: {
                validRegEx: true,
                year: true
            },
            time: {
                validRegEx: true,
                time: true
            }
        },
        onfocusout: function (element) {
            jQuery(element).valid()
        },
        errorElement: "div",
        errorPlacement: function (error, element) {
            error.insertBefore(element);
        }
    });
});

/**
 * Save the clients settings
 */
function save(settings) {
    // Create the rules object
    var rules = [];

    // Get all the rules and add them to our rules object
    $('#rules').find('.mui-panel').each(function () {
        var rule = {};

        $(this).find('input[type=hidden]').each(function () {
            rule[$(this).prop('id')] = $(this).val();
        });

        rules.push(rule);
    });

    if (typeof settings === 'undefined') {
        settings = {
            fill_all_form: $("#fill_all_form").is(':checked'),
            ignore_checkboxes: $("#ignore_checkboxes").is(':checked'),
            date_types: $('#date_types').find(":selected").val(),
            date_range: $("#date_range").val(),
            time: $("#time").val(),
            rules: rules,
            date_now: $("#date_now").is(':checked'),
            time_now: $("#time_now").is(':checked')
        };
    }

    chrome.storage.sync.set(settings, function () {
        // Update status to let user know options were saved.
        $(".save-wrapper p span").fadeIn();
        setTimeout(function () {
            $(".save-wrapper p span").fadeOut('slow');
        }, 850);
    });
}

/**
 * Get the clients settings
 */
function get() {
    chrome.storage.sync.get(defaultSettings, function (items) {
        $("#fill_all_form").prop('checked', items.fill_all_form);
        $("#ignore_checkboxes").prop('checked', items.ignore_checkboxes);
        $("#date_types").val(items.date_types);
        $("#date_range").val(items.date_range);
        $("#time").val(items.time);
        $("#date_now").prop('checked', items.date_now);
        $("#time_now").prop('checked', items.time_now);
        $("body").trigger("settings_loaded", [items]);
    });
}

/**
 * Reload the clients settings
 */
function reload(settings) {
    save(settings);
    get();
}

/**
 * Create the additional fields in the "New rule" modal
 * @param select
 */
function createAdditionalFields(select) {
    // Find the template for this type
    var type = select.find(":selected").val();
    var template = null;
    $.each(settingTemplates, function (categoryName, items) {
        $.each(items, function (key, item) {
            if (key == type) {
                template = item;
                return false;
            }
        });

        // We don't need to continue searching if we found the template
        if (template != null) {
            return false;
        }
    });

    // If we found a template
    if (template) {
        // Clear any previous additional fields
        $("#additional_fields").html('');

        // Add the additional fields
        $.each(template, function (key, value) {
            if (key !== 'public_name' && !key.includes('_help')) {
                // Determine the type of this field
                var type = jQuery.isNumeric(value) ? 'number' : 'text';

                // Create the input
                var html = '';
                html = html + '
'
                html = html + '' + key.capitalizeFirstLetter() + '';
                html = html + '<input class="form-control" type="' + type + '" id="' + key + '" name="' + key + '" value="' + value + '" required>';
                html = html + '
';

                // Append the input
                $("#additional_fields").append(html);
            }

            if (key.includes('_help')) {
                $("#additional_fields").append('
' + value + '
');
            }
        });

        // Add the validation
        $("#addRuleForm").validate();
    } else {
        // Fatal error, alert the user
        swal('Error', 'No rule template found for ' + type + '!', 'error');
    }
}<|endoftext|>


<commit_before>/** Bubbles **/
Flotr.addType('bubbles', {
  options: {
    show: false,      // => setting to true will show radar chart, false will hide
    lineWidth: 2,     // => line width in pixels
    fill: true,       // => true to fill the area from the line to the x axis, false for (transparent) no fill
    fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
    baseRadius: 2     // => ratio of the radar, against the plot size
  },
  draw : function (options) {
    var
      context     = options.context,
      shadowSize  = options.shadowSize;

    context.save();
    context.translate(options.offsetLeft, options.offsetTop);
    context.lineWidth = options.lineWidth;

    // Shadows
    context.fillStyle = 'rgba(0,0,0,0.05)';
    context.strokeStyle = 'rgba(0,0,0,0.05)';
    this.plot(options, shadowSize / 2);
    context.strokeStyle = 'rgba(0,0,0,0.1)';
    this.plot(options, shadowSize / 4);

    // Chart
    context.strokeStyle = options.color;
    context.fillStyle = options.fillStyle;
    this.plot(options);

    context.restore();
  },
  plot : function (options, offset) {

    var
      data    = options.data,
      context = options.context,
      i, x, y, z;

    offset = offset || 0;

    for (i = 0; i < data.length; ++i){

      x = options.xScale(data[i][0]) + offset,
      y = options.yScale(data[i][1]) + offset,
      z = data[i][2] * options.radius;

      context.beginPath();
      context.arc(x, y, z, 0, Math.PI*2, true);
      context.stroke();
      if (options.fill) context.fill();
      context.closePath();
    }
  },
  drawHit: function(n){

    var octx = this.octx,
        s = n.series,
        xa = n.xaxis,
        ya = n.yaxis,
        z = s.data[0][2],
        r = this.options.bubbles.baseRadius;

    octx.save();
    octx.lineWidth = s.points.lineWidth;
    octx.strokeStyle = s.mouse.lineColor;
    octx.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});

    octx.translate(this.plotOffset.left, this.plotOffset.top);
    octx.beginPath();
      octx.arc(xa.d2p(n.x), ya.d2p(n.y), z*r, 0, 2 * Math.PI, true);
      octx.fill();
      octx.stroke();
    octx.closePath();
    octx.restore();
  },
  clearHit: function(){
    var prevHit = this.prevHit,
        plotOffset = this.plotOffset,
        s = prevHit.series,
        lw = s.bars.lineWidth,
        xa = prevHit.xaxis,
        ya = prevHit.yaxis,
        z = s.data[0][2],
        r = this.options.bubbles.baseRadius,
        offset = z*r+lw;

    this.octx.clearRect(
      plotOffset.left + xa.d2p(prevHit.x) - offset,
      plotOffset.top  + ya.d2p(prevHit.y) - offset,
      offset*2,
      offset*2
    );
  }

/*,
  extendXRange: function(axis){
    if(axis.options.max == null){
      var newmin = axis.min,
          newmax = axis.max,
          i, j, c, r, data, d;

      for(i = 0; i < this.series.length; ++i){
        c = this.series[i].bubbles;
        if(c.show && this.series[i].xaxis == axis) {
          data = this.series[i].data;
          if (data)
          for(j = 0; j < data.length; j++) {
            d = data[j];
            r = d[2] * c.baseRadius * (this.plotWidth / (axis.datamax - axis.datamin));
              newmax = Math.max(d[0] + r, newmax);
              newmin = Math.min(d[0] - r, newmin);
          }
        }
      }
      axis.max = newmax;
      axis.min = newmin;
    }
  },
  extendYRange: function(axis){
    if(axis.options.max == null){
      var newmin = axis.min,
          newmax = axis.max,
          i, j, c, r, data, d;

      for(i = 0; i < this.series.length; ++i){
        c = this.series[i].bubbles;
        if(c.show && this.series[i].yaxis == axis) {
          data = this.series[i].data;
          if (data)
          for(j = 0; j < data.length; j++) {
            d = data[j];
            r = d[2] * c.baseRadius;
            newmax = Math.max(d[1] + r, newmax);
            newmin = Math.min(d[1] - r, newmin);
          }
        }
      }
      axis.max = newmax;
      axis.min = newmin;
    }
  }*/
});
<commit_msg>Fixed base radius bug.<commit_after>/** Bubbles **/
Flotr.addType('bubbles', {
  options: {
    show: false,      // => setting to true will show radar chart, false will hide
    lineWidth: 2,     // => line width in pixels
    fill: true,       // => true to fill the area from the line to the x axis, false for (transparent) no fill
    fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
    baseRadius: 2     // => ratio of the radar, against the plot size
  },
  draw : function (options) {
    var
      context     = options.context,
      shadowSize  = options.shadowSize;

    context.save();
    context.translate(options.offsetLeft, options.offsetTop);
    context.lineWidth = options.lineWidth;

    // Shadows
    context.fillStyle = 'rgba(0,0,0,0.05)';
    context.strokeStyle = 'rgba(0,0,0,0.05)';
    this.plot(options, shadowSize / 2);
    context.strokeStyle = 'rgba(0,0,0,0.1)';
    this.plot(options, shadowSize / 4);

    // Chart
    context.strokeStyle = options.color;
    context.fillStyle = options.fillStyle;
    this.plot(options);

    context.restore();
  },
  plot : function (options, offset) {

    var
      data    = options.data,
      context = options.context,
      i, x, y, z;

    offset = offset || 0;

    for (i = 0; i < data.length; ++i){

      x = options.xScale(data[i][0]) + offset,
      y = options.yScale(data[i][1]) + offset,
      z = data[i][2] * options.baseRadius;

      context.beginPath();
      context.arc(x, y, z, 0, Math.PI*2, true);
      context.stroke();
      if (options.fill) context.fill();
      context.closePath();
    }
  },
  drawHit: function(n){

    var octx = this.octx,
        s = n.series,
        xa = n.xaxis,
        ya = n.yaxis,
        z = s.data[0][2],
        r = this.options.bubbles.baseRadius;

    octx.save();
    octx.lineWidth = s.points.lineWidth;
    octx.strokeStyle = s.mouse.lineColor;
    octx.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});

    octx.translate(this.plotOffset.left, this.plotOffset.top);
    octx.beginPath();
      octx.arc(xa.d2p(n.x), ya.d2p(n.y), z*r, 0, 2 * Math.PI, true);
      octx.fill();
      octx.stroke();
    octx.closePath();
    octx.restore();
  },
  clearHit: function(){
    var prevHit = this.prevHit,
        plotOffset = this.plotOffset,
        s = prevHit.series,
        lw = s.bars.lineWidth,
        xa = prevHit.xaxis,
        ya = prevHit.yaxis,
        z = s.data[0][2],
        r = this.options.bubbles.baseRadius,
        offset = z*r+lw;

    this.octx.clearRect(
      plotOffset.left + xa.d2p(prevHit.x) - offset,
      plotOffset.top  + ya.d2p(prevHit.y) - offset,
      offset*2,
      offset*2
    );
  }

/*,
  extendXRange: function(axis){
    if(axis.options.max == null){
      var newmin = axis.min,
          newmax = axis.max,
          i, j, c, r, data, d;

      for(i = 0; i < this.series.length; ++i){
        c = this.series[i].bubbles;
        if(c.show && this.series[i].xaxis == axis) {
          data = this.series[i].data;
          if (data)
          for(j = 0; j < data.length; j++) {
            d = data[j];
            r = d[2] * c.baseRadius * (this.plotWidth / (axis.datamax - axis.datamin));
              newmax = Math.max(d[0] + r, newmax);
              newmin = Math.min(d[0] - r, newmin);
          }
        }
      }
      axis.max = newmax;
      axis.min = newmin;
    }
  },
  extendYRange: function(axis){
    if(axis.options.max == null){
      var newmin = axis.min,
          newmax = axis.max,
          i, j, c, r, data, d;

      for(i = 0; i < this.series.length; ++i){
        c = this.series[i].bubbles;
        if(c.show && this.series[i].yaxis == axis) {
          data = this.series[i].data;
          if (data)
          for(j = 0; j < data.length; j++) {
            d = data[j];
            r = d[2] * c.baseRadius;
            newmax = Math.max(d[1] + r, newmax);
            newmin = Math.min(d[1] - r, newmin);
          }
        }
      }
      axis.max = newmax;
      axis.min = newmin;
    }
  }*/
});
<|endoftext|>


<commit_before>/* global define, sinon */

define([
  'sinon'
], function () {
  'use strict';

  function stubServer (options) {
    var server = sinon.fakeServer.create();
    server.respondWith(
      'GET',
      options.url,
      [options.code, {'Content-Type': 'application/json'}, JSON.stringify(options.response)]
    );

    return server;
  }

  window.stubServer = stubServer;
  return stubServer;
});<commit_msg>Allow passing a verb when stubbing server<commit_after>/* global define, sinon */

define([
  'sinon'
], function () {
  'use strict';

  function stubServer (options) {
    var server = sinon.fakeServer.create();
    server.respondWith(
      options.verb || 'GET',
      options.url,
      [options.code, {'Content-Type': 'application/json'}, JSON.stringify(options.response)]
    );

    return server;
  }

  window.stubServer = stubServer;
  return stubServer;
});<|endoftext|>


<commit_before>'use strict';

const empty = require('../../dist/helpers/empty.js');

module.exports = (it, expect) => {
  it('should return true if the array has no items', () => {
    expect(empty([])).to.eql(true);
    expect(empty([1])).to.eql(false);
  });

  it('should return true if the object has no items', () => {
    expect(empty({})).to.eql(true);
    expect(empty({ Joe: 'doe' })).to.eql(false);
  });
};
<commit_msg>removed helper empty test<commit_after><|endoftext|>


<commit_before>var expect = require('chai').expect;

var getReadableStream = require('../_utilities/getReadableStream.js');
var getDuplexStream = require('../_utilities/getDuplexStream.js');
var runBasicStreamTests = require('../_utilities/runBasicStreamTests.js');
var intersperse = require('../../').intersperse;

describe('[intersperse]', function () {
  var data = ['banana', 'apple', 'orange'];
  var dataObj = [true, true, true];

  function runTest(stream, objectMode, done) {
    var expected = ['banana', '\n', 'apple', '\n', 'orange'];
    var expectedObj = [true, false, true, false, true];
    var actual = [];

    stream
      .pipe(intersperse(objectMode ? false : '\n'))
      .on('data', function (chunk) {

        if (Buffer.isBuffer(chunk)) {
          actual.push(chunk.toString());
        } else {
          actual.push(chunk);
        }
      })
      .on('error', done)
      .on('end', function () {

        if (objectMode) {
          expect(actual).to.deep.equal(expectedObj);
        } else {
          expect(actual).to.deep.equal(expected);
        }

        done();
      });
  }

  runBasicStreamTests(data, dataObj, runTest);
});
<commit_msg>fix lint errors<commit_after>var expect = require('chai').expect;

var runBasicStreamTests = require('../_utilities/runBasicStreamTests.js');
var intersperse = require('../../').intersperse;

describe('[intersperse]', function () {
  var data = ['banana', 'apple', 'orange'];
  var dataObj = [true, true, true];

  function runTest(stream, objectMode, done) {
    var expected = ['banana', '\n', 'apple', '\n', 'orange'];
    var expectedObj = [true, false, true, false, true];
    var actual = [];

    stream
      .pipe(intersperse(objectMode ? false : '\n'))
      .on('data', function (chunk) {

        if (Buffer.isBuffer(chunk)) {
          actual.push(chunk.toString());
        } else {
          actual.push(chunk);
        }
      })
      .on('error', done)
      .on('end', function () {

        if (objectMode) {
          expect(actual).to.deep.equal(expectedObj);
        } else {
          expect(actual).to.deep.equal(expected);
        }

        done();
      });
  }

  runBasicStreamTests(data, dataObj, runTest);
});
<|endoftext|>


<commit_before>var cookie0 = {
    'name' : 'Valid-Cookie-Name',
    'value' : 'Valid-Cookie-Value',
    'domain' : 'localhost',
    'path' : '/foo',
    'httponly' : true,
    'secure' : false
};
var cookie1 = {
    'name' : 'Valid-Cookie-Name-1',
    'value' : 'Valid-Cookie-Value',
    'domain' : 'localhost',
    'path' : '/foo',
    'httponly' : true,
    'secure' : false
};
var cookie2 = {
    'name' : 'Valid-Cookie-Name-2',
    'value' : 'Valid-Cookie-Value',
    'domain' : 'localhost',
    'path' : '/foo',
    'httponly' : true,
    'secure' : false
};
var cookies = [{
    'name' : 'Valid-Cookie-Name',
    'value' : 'Valid-Cookie-Value',
    'domain' : 'localhost',
    'path' : '/foo',
    'httponly' : true,
    'secure' : false
},{
    'name' : 'Valid-Cookie-Name-Sec',
    'value' : 'Valid-Cookie-Value-Sec',
    'domain' : 'localhost',
    'path' : '/foo',
    'httponly' : true,
    'secure' : false,
    'expires' : new Date().getTime() + 3600 //< expires in 1h
}];

var cookiejar, jar1, jar2;
setup(function () {
    cookiejar = require('cookiejar');
    jar1 = cookiejar.create();
    jar2 = cookiejar.create();
});

test(function () {
    assert_type_of(jar1, 'object');
    assert_not_equals(jar1, null);
    assert_type_of(jar1.cookies, 'object');

    assert_type_of(jar1.addCookie, 'function');
    assert_type_of(jar1.deleteCookie, 'function');
    assert_type_of(jar1.clearCookies, 'function');
}, "cookie jar properties");

test(function () {
    assert_equals(jar1.cookies.length, 0);

    jar1.addCookie(cookie0);
    assert_equals(jar1.cookies.length, 1);

    jar1.deleteCookie('Valid-Cookie-Name');
    assert_equals(jar1.cookies.length, 0);
}, "adding and removing cookies");

test(function () {
    assert_equals(jar1.cookies.length, 0);

    jar1.cookies = cookies;
    assert_equals(jar1.cookies.length, 2);

    jar1.clearCookies();
    assert_equals(jar1.cookies.length, 0);
}, "setting and clearing a cookie jar");

test(function () {
    jar1.addCookie(cookie1);
    assert_equals(jar1.cookies.length, 1);
    assert_equals(jar2.cookies.length, 0);

    jar2.addCookie(cookie2);
    jar1.deleteCookie('Valid-Cookie-Name-1');
    assert_equals(jar1.cookies.length, 0);
    assert_equals(jar2.cookies.length, 1);

    jar1.close();
    jar2.close();

}, "cookie jar isolation");
<commit_msg>Align columns of data for readability.<commit_after>var cookie0 = {
    'name':     'Valid-Cookie-Name',
    'value':    'Valid-Cookie-Value',
    'domain':   'localhost',
    'path':     '/foo',
    'httponly': true,
    'secure':   false
};
var cookie1 = {
    'name':     'Valid-Cookie-Name-1',
    'value':    'Valid-Cookie-Value',
    'domain':   'localhost',
    'path':     '/foo',
    'httponly': true,
    'secure':   false
};
var cookie2 = {
    'name':     'Valid-Cookie-Name-2',
    'value':    'Valid-Cookie-Value',
    'domain':   'localhost',
    'path':     '/foo',
    'httponly': true,
    'secure':   false
};
var cookies = [{
    'name':     'Valid-Cookie-Name',
    'value':    'Valid-Cookie-Value',
    'domain':   'localhost',
    'path':     '/foo',
    'httponly': true,
    'secure':   false
},{
    'name':     'Valid-Cookie-Name-Sec',
    'value':    'Valid-Cookie-Value-Sec',
    'domain':   'localhost',
    'path':     '/foo',
    'httponly': true,
    'secure':   false,
    'expires':  new Date().getTime() + 3600 //< expires in 1h
}];

var cookiejar, jar1, jar2;
setup(function () {
    cookiejar = require('cookiejar');
    jar1 = cookiejar.create();
    jar2 = cookiejar.create();
});

test(function () {
    assert_type_of(jar1, 'object');
    assert_not_equals(jar1, null);
    assert_type_of(jar1.cookies, 'object');

    assert_type_of(jar1.addCookie, 'function');
    assert_type_of(jar1.deleteCookie, 'function');
    assert_type_of(jar1.clearCookies, 'function');
}, "cookie jar properties");

test(function () {
    assert_equals(jar1.cookies.length, 0);

    jar1.addCookie(cookie0);
    assert_equals(jar1.cookies.length, 1);

    jar1.deleteCookie('Valid-Cookie-Name');
    assert_equals(jar1.cookies.length, 0);
}, "adding and removing cookies");

test(function () {
    assert_equals(jar1.cookies.length, 0);

    jar1.cookies = cookies;
    assert_equals(jar1.cookies.length, 2);

    jar1.clearCookies();
    assert_equals(jar1.cookies.length, 0);
}, "setting and clearing a cookie jar");

test(function () {
    jar1.addCookie(cookie1);
    assert_equals(jar1.cookies.length, 1);
    assert_equals(jar2.cookies.length, 0);

    jar2.addCookie(cookie2);
    jar1.deleteCookie('Valid-Cookie-Name-1');
    assert_equals(jar1.cookies.length, 0);
    assert_equals(jar2.cookies.length, 1);

    jar1.close();
    jar2.close();

}, "cookie jar isolation");
<|endoftext|>


<commit_before>goog.provide('ol.test.geom.flat');

describe('ol.geom.flat', function() {

  describe('ol.geom.flat.deflateCoordinates', function() {

    var flatCoordinates;
    beforeEach(function() {
      flatCoordinates = [];
    });

    it('flattens coordinates', function() {
      var offset = ol.geom.flat.deflateCoordinates(
          flatCoordinates, 0, [[1, 2], [3, 4]], 2);
      expect(offset).to.be(4);
      expect(flatCoordinates).to.eql([1, 2, 3, 4]);
    });

  });

  describe('ol.geom.flat.deflateCoordinatess', function() {

    var flatCoordinates;
    beforeEach(function() {
      flatCoordinates = [];
    });

    it('flattens arrays of coordinates', function() {
      var ends = ol.geom.flat.deflateCoordinatess(flatCoordinates, 0,
          [[[1, 2], [3, 4]], [[5, 6], [7, 8]]], 2);
      expect(ends).to.eql([4, 8]);
      expect(flatCoordinates).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
    });

  });

  describe('ol.geom.flat.inflateCoordinates', function() {

    it('inflates coordinates', function() {
      var coordinates = ol.geom.flat.inflateCoordinates([1, 2, 3, 4], 0, 4, 2);
      expect(coordinates).to.eql([[1, 2], [3, 4]]);
    });

  });

  describe('ol.geom.flat.flipXY', function() {

    it('can flip XY coordinates', function() {
      var flatCoordinates = ol.geom.flat.flipXY([1, 2, 3, 4], 0, 4, 2);
      expect(flatCoordinates).to.eql([2, 1, 4, 3]);
    });

    it('can flip XY coordinates while preserving other dimensions', function() {
      var flatCoordinates = ol.geom.flat.flipXY(
          [1, 2, 3, 4, 5, 6, 7, 8], 0, 8, 4);
      expect(flatCoordinates).to.eql([2, 1, 3, 4, 6, 5, 7, 8]);
    });

    it('can flip XY coordinates in place', function() {
      var flatCoordinates = [1, 2, 3, 4];
      expect(ol.geom.flat.flipXY(flatCoordinates, 0, 4, 2, flatCoordinates)).
          to.be(flatCoordinates);
      expect(flatCoordinates).to.eql([2, 1, 4, 3]);
    });

    it('can flip XY coordinates in place while preserving other dimensions',
        function() {
          var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9];
          expect(ol.geom.flat.flipXY(
              flatCoordinates, 0, 9, 3, flatCoordinates)).
              to.be(flatCoordinates);
          expect(flatCoordinates).to.eql([2, 1, 3, 5, 4, 6, 8, 7, 9]);
        });

  });

  describe('ol.geom.flat.inflateCoordinatess', function() {

    it('inflates arrays of coordinates', function() {
      var coordinatess = ol.geom.flat.inflateCoordinatess(
          [1, 2, 3, 4, 5, 6, 7, 8], 0, [4, 8], 2);
      expect(coordinatess).to.eql([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
    });

  });

  describe('ol.geom.flat.lineStringInterpolate', function() {

    it('returns the expected value for single points', function() {
      var flatCoordinates = [0, 1];
      var point =
          ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 2, 2, 0.5);
      expect(point).to.eql([0, 1]);
    });

    it('returns the expected value for simple line segments', function() {
      var flatCoordinates = [0, 1, 2, 3];
      var point =
          ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 4, 2, 0.5);
      expect(point).to.eql([1, 2]);
    });

    it('returns the expected value when the mid point is an existing ' +
       'coordinate', function() {
          var flatCoordinates = [0, 1, 2, 3, 4, 5];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 6, 2, 0.5);
          expect(point).to.eql([2, 3]);
        });

    it('returns the expected value when the midpoint falls halfway between ' +
       'two existing coordinates', function() {
          var flatCoordinates = [0, 1, 2, 3, 4, 5, 6, 7];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 8, 2, 0.5);
          expect(point).to.eql([3, 4]);
        });

    it('returns the expected value when the coordinates are not evenly spaced',
        function() {
          var flatCoordinates = [0, 1, 2, 3, 6, 7];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 6, 2, 0.5);
          expect(point).to.eql([3, 4]);
        });

  });

  describe('ol.geom.flat.linearRingIsClockwise', function() {

    it('identifies clockwise rings', function() {
      var flatCoordinates = [0, 1, 1, 4, 4, 3, 3, 0];
      var isClockwise = ol.geom.flat.linearRingIsClockwise(
          flatCoordinates, 0, flatCoordinates.length, 2);
      expect(isClockwise).to.be(true);
    });

    it('identifies anti-clockwise rings', function() {
      var flatCoordinates = [2, 2, 3, 2, 3, 3, 2, 3];
      var isClockwise = ol.geom.flat.linearRingIsClockwise(
          flatCoordinates, 0, flatCoordinates.length, 2);
      expect(isClockwise).to.be(false);
    });

  });

  describe('ol.geom.flat.reverseCoordinates', function() {

    describe('with a stride of 2', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([1, 2]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([3, 4, 1, 2]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([5, 6, 3, 4, 1, 2]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([7, 8, 5, 6, 3, 4, 1, 2]);
      });

    });

    describe('with a stride of 3', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2, 3];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([1, 2, 3]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([4, 5, 6, 1, 2, 3]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([7, 8, 9, 4, 5, 6, 1, 2, 3]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([10, 11, 12, 7, 8, 9, 4, 5, 6, 1, 2, 3]);
      });

    });

    describe('with a stride of 4', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([1, 2, 3, 4]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([5, 6, 7, 8, 1, 2, 3, 4]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates =
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql(
            [13, 14, 15, 16, 9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4]);
      });

    });

  });

});

goog.require('ol.geom.flat');
<commit_msg>Order test cases alphabetically<commit_after>goog.provide('ol.test.geom.flat');

describe('ol.geom.flat', function() {

  describe('ol.geom.flat.deflateCoordinates', function() {

    var flatCoordinates;
    beforeEach(function() {
      flatCoordinates = [];
    });

    it('flattens coordinates', function() {
      var offset = ol.geom.flat.deflateCoordinates(
          flatCoordinates, 0, [[1, 2], [3, 4]], 2);
      expect(offset).to.be(4);
      expect(flatCoordinates).to.eql([1, 2, 3, 4]);
    });

  });

  describe('ol.geom.flat.deflateCoordinatess', function() {

    var flatCoordinates;
    beforeEach(function() {
      flatCoordinates = [];
    });

    it('flattens arrays of coordinates', function() {
      var ends = ol.geom.flat.deflateCoordinatess(flatCoordinates, 0,
          [[[1, 2], [3, 4]], [[5, 6], [7, 8]]], 2);
      expect(ends).to.eql([4, 8]);
      expect(flatCoordinates).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
    });

  });

  describe('ol.geom.flat.flipXY', function() {

    it('can flip XY coordinates', function() {
      var flatCoordinates = ol.geom.flat.flipXY([1, 2, 3, 4], 0, 4, 2);
      expect(flatCoordinates).to.eql([2, 1, 4, 3]);
    });

    it('can flip XY coordinates while preserving other dimensions', function() {
      var flatCoordinates = ol.geom.flat.flipXY(
          [1, 2, 3, 4, 5, 6, 7, 8], 0, 8, 4);
      expect(flatCoordinates).to.eql([2, 1, 3, 4, 6, 5, 7, 8]);
    });

    it('can flip XY coordinates in place', function() {
      var flatCoordinates = [1, 2, 3, 4];
      expect(ol.geom.flat.flipXY(flatCoordinates, 0, 4, 2, flatCoordinates)).
          to.be(flatCoordinates);
      expect(flatCoordinates).to.eql([2, 1, 4, 3]);
    });

    it('can flip XY coordinates in place while preserving other dimensions',
        function() {
          var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9];
          expect(ol.geom.flat.flipXY(
              flatCoordinates, 0, 9, 3, flatCoordinates)).
              to.be(flatCoordinates);
          expect(flatCoordinates).to.eql([2, 1, 3, 5, 4, 6, 8, 7, 9]);
        });

  });

  describe('ol.geom.flat.inflateCoordinates', function() {

    it('inflates coordinates', function() {
      var coordinates = ol.geom.flat.inflateCoordinates([1, 2, 3, 4], 0, 4, 2);
      expect(coordinates).to.eql([[1, 2], [3, 4]]);
    });

  });

  describe('ol.geom.flat.inflateCoordinatess', function() {

    it('inflates arrays of coordinates', function() {
      var coordinatess = ol.geom.flat.inflateCoordinatess(
          [1, 2, 3, 4, 5, 6, 7, 8], 0, [4, 8], 2);
      expect(coordinatess).to.eql([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
    });

  });

  describe('ol.geom.flat.lineStringInterpolate', function() {

    it('returns the expected value for single points', function() {
      var flatCoordinates = [0, 1];
      var point =
          ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 2, 2, 0.5);
      expect(point).to.eql([0, 1]);
    });

    it('returns the expected value for simple line segments', function() {
      var flatCoordinates = [0, 1, 2, 3];
      var point =
          ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 4, 2, 0.5);
      expect(point).to.eql([1, 2]);
    });

    it('returns the expected value when the mid point is an existing ' +
       'coordinate', function() {
          var flatCoordinates = [0, 1, 2, 3, 4, 5];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 6, 2, 0.5);
          expect(point).to.eql([2, 3]);
        });

    it('returns the expected value when the midpoint falls halfway between ' +
       'two existing coordinates', function() {
          var flatCoordinates = [0, 1, 2, 3, 4, 5, 6, 7];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 8, 2, 0.5);
          expect(point).to.eql([3, 4]);
        });

    it('returns the expected value when the coordinates are not evenly spaced',
        function() {
          var flatCoordinates = [0, 1, 2, 3, 6, 7];
          var point =
              ol.geom.flat.lineStringInterpolate(flatCoordinates, 0, 6, 2, 0.5);
          expect(point).to.eql([3, 4]);
        });

  });

  describe('ol.geom.flat.linearRingIsClockwise', function() {

    it('identifies clockwise rings', function() {
      var flatCoordinates = [0, 1, 1, 4, 4, 3, 3, 0];
      var isClockwise = ol.geom.flat.linearRingIsClockwise(
          flatCoordinates, 0, flatCoordinates.length, 2);
      expect(isClockwise).to.be(true);
    });

    it('identifies anti-clockwise rings', function() {
      var flatCoordinates = [2, 2, 3, 2, 3, 3, 2, 3];
      var isClockwise = ol.geom.flat.linearRingIsClockwise(
          flatCoordinates, 0, flatCoordinates.length, 2);
      expect(isClockwise).to.be(false);
    });

  });

  describe('ol.geom.flat.reverseCoordinates', function() {

    describe('with a stride of 2', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([1, 2]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([3, 4, 1, 2]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([5, 6, 3, 4, 1, 2]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 2);
        expect(flatCoordinates).to.eql([7, 8, 5, 6, 3, 4, 1, 2]);
      });

    });

    describe('with a stride of 3', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2, 3];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([1, 2, 3]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([4, 5, 6, 1, 2, 3]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([7, 8, 9, 4, 5, 6, 1, 2, 3]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 3);
        expect(flatCoordinates).to.eql([10, 11, 12, 7, 8, 9, 4, 5, 6, 1, 2, 3]);
      });

    });

    describe('with a stride of 4', function() {

      it('can reverse empty flat coordinates', function() {
        var flatCoordinates = [];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.be.empty();
      });

      it('can reverse one flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([1, 2, 3, 4]);
      });

      it('can reverse two flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([5, 6, 7, 8, 1, 2, 3, 4]);
      });

      it('can reverse three flat coordinates', function() {
        var flatCoordinates = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql([9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4]);
      });

      it('can reverse four flat coordinates', function() {
        var flatCoordinates =
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
        ol.geom.flat.reverseCoordinates(
            flatCoordinates, 0, flatCoordinates.length, 4);
        expect(flatCoordinates).to.eql(
            [13, 14, 15, 16, 9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4]);
      });

    });

  });

});

goog.require('ol.geom.flat');
<|endoftext|>


<commit_before>define(['require', 'js/core/Base', 'srv/handler/rest/ResourceHandler', 'flow'], function (require, Base, ResourceHandler, flow) {

    return Base.inherit('srv.handler.rest.ResourceRouter', {

        ctor: function(restHandler) {
            this.$restHandler = restHandler;
        },

        /***
         *
         * @param {srv.core.Context} context
         * @param {Function} callback - function(err, resource)
         *
         */
        getResource: function(context, callback) {

            var path = context.request.urlInfo.pathname,
                relativePath = this.$restHandler.$.path;

            if (path.indexOf(relativePath) !== 0) {
                callback(new Error("Handler path '" + relativePath + "' not at start of " + path));
                return;
            }

            // remove relative handler path from path
            path = path.substring(relativePath.length);

            var pathElements = path.split('/');

            // remove first empty path
            pathElements.shift();

            try {
                callback(null, this._getResourceForPath(pathElements));
            } catch (e) {
                callback(e);
            }
        },

        /***
         *
         * @param {Array} pathElements
         * @param {Function} callback
         * @callback {srv.handler.rest.Resource}
         *
         * @private
         */
        _getResourceForPath: function(pathElements) {
            var configuration = this.$restHandler.$resourceConfiguration,
                parentResourceHandler = null,
                resourceStack = [],
                i;

            // build a stack of configurations
            for (i = 0; i < pathElements.length; i += 2) {
                var path = pathElements[i];
                configuration = configuration.getConfigurationForPath(path);

                if (!configuration) {
                    throw new Error("Configuration for '" + pathElements.slice(0, i + 1).join('/') + "' not found.");
                }

                if(this.$restHandler.$modelClassResourceHandler[configuration.$.modelClassName]){
                    configuration.$.resourceHandler = this.$restHandler.$modelClassResourceHandler[configuration.$.modelClassName];
                }

                if (!configuration.$.resourceHandler) {
                    // no resource handler assigned to resource, use a default resource handler
                    configuration.$.resourceHandler = new ResourceHandler();
                }

                resourceStack.push({
                    resourceHandler: configuration.$.resourceHandler,
                    configuration: configuration,
                    id: pathElements[i + 1]
                });

            }

            for (i = 0; i < resourceStack.length; i++) {
                var resourceEntry = resourceStack[i],
                    resourceHandler = resourceEntry.resourceHandler;

                // clone or get same instance
                resourceHandler = resourceHandler.getResourceHandlerInstance();

                // initialize handler
                resourceHandler.init(this.$restHandler, resourceEntry.configuration, resourceEntry.id, parentResourceHandler);
                parentResourceHandler = resourceHandler;

                if (!(resourceHandler instanceof ResourceHandler)) {
                    throw "Returned resource not an instance of Resource";
                }
            }

            // return top mose resourceHandler
            return parentResourceHandler;

        }
    });
});<commit_msg>if no configuration is found for resource -> HttpError 404 is returned<commit_after>define(['require', 'js/core/Base', 'srv/handler/rest/ResourceHandler', 'flow', 'srv/core/HttpError'], function (require, Base, ResourceHandler, flow, HttpError) {

    return Base.inherit('srv.handler.rest.ResourceRouter', {

        ctor: function(restHandler) {
            this.$restHandler = restHandler;
        },

        /***
         *
         * @param {srv.core.Context} context
         * @param {Function} callback - function(err, resource)
         *
         */
        getResource: function(context, callback) {

            var path = context.request.urlInfo.pathname,
                relativePath = this.$restHandler.$.path;

            if (path.indexOf(relativePath) !== 0) {
                callback(new Error("Handler path '" + relativePath + "' not at start of " + path));
                return;
            }

            // remove relative handler path from path
            path = path.substring(relativePath.length);

            var pathElements = path.split('/');

            // remove first empty path
            pathElements.shift();

            try {
                callback(null, this._getResourceForPath(pathElements));
            } catch (e) {
                callback(e);
            }
        },

        /***
         *
         * @param {Array} pathElements
         * @param {Function} callback
         * @callback {srv.handler.rest.Resource}
         *
         * @private
         */
        _getResourceForPath: function(pathElements) {
            var configuration = this.$restHandler.$resourceConfiguration,
                parentResourceHandler = null,
                resourceStack = [],
                i;

            // build a stack of configurations
            for (i = 0; i < pathElements.length; i += 2) {
                var path = pathElements[i];
                configuration = configuration.getConfigurationForPath(path);

                if (!configuration) {
                    throw new HttpError("Configuration for '" + pathElements.slice(0, i + 1).join('/') + "' not found.", 404);
                }

                if(this.$restHandler.$modelClassResourceHandler[configuration.$.modelClassName]){
                    configuration.$.resourceHandler = this.$restHandler.$modelClassResourceHandler[configuration.$.modelClassName];
                }

                if (!configuration.$.resourceHandler) {
                    // no resource handler assigned to resource, use a default resource handler
                    configuration.$.resourceHandler = new ResourceHandler();
                }

                resourceStack.push({
                    resourceHandler: configuration.$.resourceHandler,
                    configuration: configuration,
                    id: pathElements[i + 1]
                });

            }

            for (i = 0; i < resourceStack.length; i++) {
                var resourceEntry = resourceStack[i],
                    resourceHandler = resourceEntry.resourceHandler;

                // clone or get same instance
                resourceHandler = resourceHandler.getResourceHandlerInstance();

                // initialize handler
                resourceHandler.init(this.$restHandler, resourceEntry.configuration, resourceEntry.id, parentResourceHandler);
                parentResourceHandler = resourceHandler;

                if (!(resourceHandler instanceof ResourceHandler)) {
                    throw "Returned resource not an instance of Resource";
                }
            }

            // return top mose resourceHandler
            return parentResourceHandler;

        }
    });
});<|endoftext|>