<commit_before>
var month=new Array();
month[0]="January";
month[1]="February";
month[2]="March";
month[3]="April";
month[4]="May";
month[5]="June";
month[6]="July";
month[7]="August";
month[8]="September";
month[9]="October";
month[10]="November";
month[11]="December";

function get_nth_suffix(date) {
  switch (date) {
    case 1:
    case 21:
    case 31:
       return 'st';
    case 2:
    case 22:
       return 'nd';
    case 3:
    case 23:
       return 'rd';
    default:
       return 'th';
  }
}

/* POST: ajax call
 * TO DO: have other ajax call this generic method instead
 * */
function ajaxPost(data, url, callback, callBackParams)
{
    $.ajax({
        type: 'POST',
        url: url,
        data: data,
        success: function(context, responseText, textStatus) {
            if(callback)
            {
                callback.call(null, responseText, textStatus, callBackParams);
            }
        },
        error: function(response, responseText, textStatus) {
            if(callback)
            {
                callback.call(null, response, responseText, textStatus, callBackParams);
            }
        }
    });
}

function ajaxPageLoad(element, path, itemObj, callback)
{
    $(element).load(path, itemObj, callback);
}

function delFromWishlist(itemObj, callback)
{
    var wishlistItemURL = Routing.generate('WishlistListBundle_wishlistDelete');
    $( "#wishlist" ).load(wishlistItemURL, itemObj, callback);
}

// paramsObj {tags: "cat", tagmode: "any", format: "json"}
function ajaxCall(url, paramsObj, onSuccessMethod)
{
    $.post(url, paramsObj, function(data) {
        if(onSuccessMethod) {
            onSuccessMethod(data);
        }
    });
}

//Browser Support Code
function ajaxFunction(queryString){
    var ajaxRequest;  // The variable that makes Ajax possible!

    try
    {
        // Opera 8.0+, Firefox, Safari
        ajaxRequest = new XMLHttpRequest();
    }
    catch (e)
    {
        try
        {
            // Internet Explorer Browsers
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e)
        {
            try
            {
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e)
            {
                // Something went wrong
                alert("Unable to complete the request.");
                return false;
            }
        }
    }

    // Create a function that will receive data sent from the server
    ajaxRequest.onreadystatechange = function(){
            if(ajaxRequest.readyState == 4){
                    //var ajaxDisplay = document.getElementById('ajaxDiv');
                    //ajaxDisplay.innerHTML = ajaxRequest.responseText;
            }
    }

    //var queryString = "?age=" + age + "&wpm=" + wpm + "&sex=" + sex;
    ajaxRequest.open("GET", "ajax-example.php" + queryString, true);
    ajaxRequest.send(null);
}

// ** Date Validation Functions ****************************
function isValidDate(year, month, day)
{
    var daysInMonth = function (y, m) {return 32-new Date(y, m, 32).getDate(); };
    var char_year = year.toString();
    var d = new Date(); var curr_year = d.getFullYear();

    if(char_year.length != 4 || year > (curr_year+200))
        return false;

    if(month < 0 || month > 11)
        return false;

    if(day < 0 || day > daysInMonth(year, month))
        return false;

    return true;
}

function parseDate(/*string*/ str)
{
    var dtCh = "/";
    var retDate = new Date();
    var pos1=str.indexOf(dtCh);
    var pos2=str.indexOf(dtCh,pos1+1);
    var str_arr = null;

    if(str == ""){
        //string is not defined
        throw "Invalid date.";
    }

    if (pos1==-1 || pos2==-1)
    {
        throw "Invalid date.";
    }
    else
    {
        str_arr = str.split("/");
    }

    var month = parseInt(str_arr[0], 10);
    var day = parseInt(str_arr[1], 10);
    var year = parseInt(str_arr[2], 10);

    //This is quite stupid as monthValue is the only value that begins with an
    //index of zero, subtract one to fix it.
    month--;

    if(!isValidDate(year, month, day))
    {
        throw "Invalid date.";
    }

    retDate.setFullYear(year, month, day);

    return retDate;
}

// ** Date Validation Functions ****************************

function confirm (confirmMessage) {
    var defer = $.Deferred();
    $('
' + confirmMessage + '
').dialog({
            position: 'top',
            height: 300,
            width: 300,
            modal: true,
            autoOpen: true,
            close: function () {
                $(this).dialog('destroy');
            },
            title: 'Continue?',
            buttons: {
                "Yes": function() {
                    defer.resolve(1); //on Yes click, end deferred state successfully with 1 value
                    $( this ).dialog( "close" );
                },
                "No": function() {
                    defer.resolve(0); //on No click end deferred successfully with 0 value
                    $( this ).dialog( "close" );
                }
            }
        });
    return defer.promise(); //important to return the deferred promise
}

function popupMessage(theTitle, message, callback)
{
    $('
' + message + '
').dialog({
             position: 'top',
             autoOpen: true,
             close: function () {
                 $(this).dialog('destroy');
             },
             title: theTitle,
             buttons: {
                 "Ok": function() {
                    if(callback!=null)
                    {
                        callback();
                    }
                    $( this ).dialog( "close" );
                 }
             }
         });
}

function whatIsIt(object) {
    var stringConstructor = "test".constructor;
    var arrayConstructor = [].constructor;
    var objectConstructor = {}.constructor;

    if (object === null) {
        return "null";
    }
    else if (object === undefined) {
        return "undefined";
    }
    else if (object.constructor === stringConstructor) {
        return "String";
    }
    else if (object.constructor === arrayConstructor) {
        return "Array";
    }
    else if (object.constructor === objectConstructor) {
        return "Object";
    }
    else {
        return "don't know";
    }
}

function IsNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function getUrlVars() {
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}
<commit_msg>Fixing a small issue I found with the common ajaxPost function. The data of the request was being confused for the status text of the response.<commit_after>
var month=new Array();
month[0]="January";
month[1]="February";
month[2]="March";
month[3]="April";
month[4]="May";
month[5]="June";
month[6]="July";
month[7]="August";
month[8]="September";
month[9]="October";
month[10]="November";
month[11]="December";

function get_nth_suffix(date) {
  switch (date) {
    case 1:
    case 21:
    case 31:
       return 'st';
    case 2:
    case 22:
       return 'nd';
    case 3:
    case 23:
       return 'rd';
    default:
       return 'th';
  }
}

/* POST: ajax call
 * TO DO: have other ajax call this generic method instead
 * */
function ajaxPost(data, url, callback, callBackParams)
{
    $.ajax({
        type: 'POST',
        url: url,
        data: data,
        success: function(data, textStatus, jqXHR) {
            if(callback)
            {
                callback.call(null, data, textStatus, jqXHR, callBackParams);
            }
        },
        error: function(jqXHR, textStatus, errorThrown) {
            if(callback)
            {
                callback.call(null, jqXHR.responseText, textStatus, jqXHR, callBackParams);
            }
        }
    });
}

function ajaxPageLoad(element, path, itemObj, callback)
{
    $(element).load(path, itemObj, callback);
}

function delFromWishlist(itemObj, callback)
{
    var wishlistItemURL = Routing.generate('WishlistListBundle_wishlistDelete');
    $( "#wishlist" ).load(wishlistItemURL, itemObj, callback);
}

// paramsObj {tags: "cat", tagmode: "any", format: "json"}
function ajaxCall(url, paramsObj, onSuccessMethod)
{
    $.post(url, paramsObj, function(data) {
        if(onSuccessMethod) {
            onSuccessMethod(data);
        }
    });
}

//Browser Support Code
function ajaxFunction(queryString){
    var ajaxRequest;  // The variable that makes Ajax possible!

    try
    {
        // Opera 8.0+, Firefox, Safari
        ajaxRequest = new XMLHttpRequest();
    }
    catch (e)
    {
        try
        {
            // Internet Explorer Browsers
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e)
        {
            try
            {
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e)
            {
                // Something went wrong
                alert("Unable to complete the request.");
                return false;
            }
        }
    }

    // Create a function that will receive data sent from the server
    ajaxRequest.onreadystatechange = function(){
            if(ajaxRequest.readyState == 4){
                    //var ajaxDisplay = document.getElementById('ajaxDiv');
                    //ajaxDisplay.innerHTML = ajaxRequest.responseText;
            }
    }

    //var queryString = "?age=" + age + "&wpm=" + wpm + "&sex=" + sex;
    ajaxRequest.open("GET", "ajax-example.php" + queryString, true);
    ajaxRequest.send(null);
}

// ** Date Validation Functions ****************************
function isValidDate(year, month, day)
{
    var daysInMonth = function (y, m) {return 32-new Date(y, m, 32).getDate(); };
    var char_year = year.toString();
    var d = new Date(); var curr_year = d.getFullYear();

    if(char_year.length != 4 || year > (curr_year+200))
        return false;

    if(month < 0 || month > 11)
        return false;

    if(day < 0 || day > daysInMonth(year, month))
        return false;

    return true;
}

function parseDate(/*string*/ str)
{
    var dtCh = "/";
    var retDate = new Date();
    var pos1=str.indexOf(dtCh);
    var pos2=str.indexOf(dtCh,pos1+1);
    var str_arr = null;

    if(str == ""){
        //string is not defined
        throw "Invalid date.";
    }

    if (pos1==-1 || pos2==-1)
    {
        throw "Invalid date.";
    }
    else
    {
        str_arr = str.split("/");
    }

    var month = parseInt(str_arr[0], 10);
    var day = parseInt(str_arr[1], 10);
    var year = parseInt(str_arr[2], 10);

    //This is quite stupid as monthValue is the only value that begins with an
    //index of zero, subtract one to fix it.
    month--;

    if(!isValidDate(year, month, day))
    {
        throw "Invalid date.";
    }

    retDate.setFullYear(year, month, day);

    return retDate;
}

// ** Date Validation Functions ****************************

function confirm (confirmMessage) {
    var defer = $.Deferred();
    $('
' + confirmMessage + '
').dialog({
            position: 'top',
            height: 300,
            width: 300,
            modal: true,
            autoOpen: true,
            close: function () {
                $(this).dialog('destroy');
            },
            title: 'Continue?',
            buttons: {
                "Yes": function() {
                    defer.resolve(1); //on Yes click, end deferred state successfully with 1 value
                    $( this ).dialog( "close" );
                },
                "No": function() {
                    defer.resolve(0); //on No click end deferred successfully with 0 value
                    $( this ).dialog( "close" );
                }
            }
        });
    return defer.promise(); //important to return the deferred promise
}

function popupMessage(theTitle, message, callback)
{
    $('
' + message + '
').dialog({
             position: 'top',
             autoOpen: true,
             close: function () {
                 $(this).dialog('destroy');
             },
             title: theTitle,
             buttons: {
                 "Ok": function() {
                    if(callback!=null)
                    {
                        callback();
                    }
                    $( this ).dialog( "close" );
                 }
             }
         });
}

function whatIsIt(object) {
    var stringConstructor = "test".constructor;
    var arrayConstructor = [].constructor;
    var objectConstructor = {}.constructor;

    if (object === null) {
        return "null";
    }
    else if (object === undefined) {
        return "undefined";
    }
    else if (object.constructor === stringConstructor) {
        return "String";
    }
    else if (object.constructor === arrayConstructor) {
        return "Array";
    }
    else if (object.constructor === objectConstructor) {
        return "Object";
    }
    else {
        return "don't know";
    }
}

function IsNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function getUrlVars() {
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}
<|endoftext|>


<commit_before>$(function() {

  // get gallery name
  var gal = $('title').text().split(" / ")[1];

  // get image list
  var images = $('#container').find('img').map(function() { return this.id; }).get();

  // get previews list
  var previews = $('#controls').find('img.preview').map(function() { return this.id; }).get();

  // get id of current image
  var currentImgId = '#' + images[0];

  // place holder for the current image number
  var currentImgNumber = previews[0];
//  var currentImgNumber = $(previews).get(-1);
  currentImgNumber = currentImgNumber.replace('picteria-', '');
  currentImgNumber = currentImgNumber.replace('-prev', '');
  console.log( 'currentImgNumber : ' + currentImgNumber);

  // image mode : screen / image
  var mode = 'image';

  // total number of previews
  var numPreviews = 0;

  // number of previews showed in previous previews screens
  var previewShowed = 0;

  var PreviousNumPreviews = 0;

  // -- show first image on page load -----------------------------------------
  showImage(currentImgId, mode);

  setTimeout(function() {
    PreviousNumPreviews = numPreviews;
    numPreviews = countPreviews(previews);
  }, 60);

  // add active state style
  console.log( 'currentImgId : ' + currentImgId );
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');
//  $(currentImgId + '-prev').css('border', '1px solid white');

  // -- handle screen resize --------------------------------------------------
  $(window).resize(function() {
    showImage(currentImgId, mode);
    showPreviews(previews);
  });

  // -- Handle show image -----------------------------------------------------
  $('.preview').click(function() {

//    $.each(images, function(index, item) {
//      $('#' + item).addClass('hide');
//    });

    $(currentImgId + '-prev').css('border', 'none');

    // get clicked element id
    var id = $(this).attr('id');

    // get corresponding img id
    var img = id.replace('-prev', '');

    currentImgId = '#' + img;

    $(currentImgId + '-prev').css('border', '1px solid white');

    currentImgNumber = img.replace('picteria-', '');

    $.ajax({
      url: '/' + gal + '/' + currentImgNumber,
      type: "get",
      success: function(data){
        $("#container").html(data);
        showImage('#picteria-1', mode);
      },
      error:function(){
        $("#container").html('There is error while submit');
      }
    });

//    $.each(images, function(index, item) {
//      if ( item == img ) {

    showImage('#picteria-1', mode);
    $('#picteria-1').removeClass('hide');

//      }
//      else {
//        $('#' + item).addClass('hide');
//      }
//    });
  });

  // -- Handle next previews --------------------------------------------------
  $('#next').click(function() {

//    console.log('');

//    setTimeout(function() {
//      PreviousNumPreviews = numPreviews;
//      numPreviews = countPreviews(previews);
//    }, 60);
  });

  // -- Handle previous previews ----------------------------------------------
  $('#prev').click(function() {
    setTimeout(function() {
      PreviousNumPreviews = numPreviews;
      numPreviews = countPreviews(previews);
    }, 60);
  });

  // -- Handle mode change ----------------------------------------------------
  $('#mode').click(function() {
    mode = switchMode(currentImgId, mode);
    return mode;
  });

  // -- keyboard shortcuts ----------------------------------------------------
  // r :           switch mode
  // up arrow :    show next previews
  // down arrow :  show previous previews
  // right arrow : show next image
  // left arrow  : show previous image
  // b :           back to galleries index
  $(document).keydown(function(e) {
//    console.log(e.which);
    if ( e.which == 82 ) {
      mode = switchMode(currentImgId, mode);
    }
    else if ( e.which == 38 ) {
      nextPreviews(previews, numPreviews);
    }
    else if ( e.which == 40 ) {
      prevPreviews(previews, numPreviews);
    }
    else if ( e.which == 39 ) {

      if ($('#picteria-' + ( parseInt(currentImgNumber) + 1 ) + '-prev').length == 0) {

        var galItems = $('#controls').attr('data-galItems');

        if ( currentImgNumber == galItems ) {
          return false;
        }

        url = '/' + gal + '/' + getWidth() + '/' + ( parseInt(currentImgNumber) + 1 );

        console.log('url : ' + url);
        $.ajax({
          url: url,
          type: "get",
          success: function(data){
            $("body").html(data);
            console.log('-> currentImgNumber : ' + currentImgNumber)
          },
          error:function() {
            $("#container").html('There is error while submit');
          }
        });
        currentImgNumber++;
      }
      else {
        currentImgNumber = nextImage(gal, currentImgNumber, mode);
      }
    }
    else if ( e.which == 37 ) {

      if ($('#picteria-' + ( parseInt(currentImgNumber) - 1 ) + '-prev').length == 0) {

        if ( currentImgNumber == 1 ) {
          return false;
        }

        url = '/' + gal + '/' + getWidth() + '/' + ( parseInt(currentImgNumber) - 1 );
        window.location.href = url;
      }
      else {
        currentImgNumber = prevImage(gal, currentImgNumber, mode);
      }
    }
    else if ( e.which == 66 ) {
      window.location.href = "http://picteria/index.php/";
    }
  });

});

function countPreviews(previews) {

  var numPreviews = 0;

  $.each(previews, function(index, item) {
   current = $('#' + item).attr('class');
   if ( current.match(/hide/) ) { return true; };
   numPreviews++;
  });
  return numPreviews;
}

function nextImage(gal, currentImgNumber, mode) {

  if ($('#picteria-' + ( parseInt(currentImgNumber) + 1 ) + '-prev').length == 0) {
    return currentImgNumber;
  }

  // remove active state style from previous preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', 'none');

  currentImgNumber++;

  $.ajax({
    url: '/' + gal + '/' + currentImgNumber,
    type: "get",
    success: function(data){
      $("#container").html(data);
      showImage('#picteria-1', mode);
      console.log('currentImgNumber : ' + currentImgNumber)
    },
    error:function() {
      $("#container").html('There is error while submit');
    }
  });

  // add active state style to current preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');
//  console.log('currentImgNumber in next image' + currentImgNumber);
  return currentImgNumber;
}

function prevImage(gal, currentImgNumber, mode) {

  if ($('#picteria-' + ( parseInt(currentImgNumber) - 1 ) + '-prev').length == 0) {
    return currentImgNumber;
  }

  // remove active state style from previous preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', 'none');

  currentImgNumber--;
  if (currentImgNumber < 1) { currentImgNumber = 1; }

  $.ajax({
    url: '/' + gal + '/' + currentImgNumber,
    type: "get",
    success: function(data){
      $("#container").html(data);
      showImage('#picteria-1', mode);
    },
    error:function(){
      $("#container").html('There is error while submit');
    }
  });

  // add active state style to current preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');

  console.log( 'currentImgNumber in prev image : ' + currentImgNumber);

  return currentImgNumber;
}

function nextPreviews(previews, step) {

  offset = parseInt($('#next').attr('data-offset'));
  offset += step;

  if ( offset >= previews.length ) {
    return false;
  }

  showPreviews(previews, offset);
  $('#next').attr('data-offset', offset);
  $('#prev').attr('data-offset', offset);
//  console.log( offset );
}

function prevPreviews(previews, step) {

  offset = parseInt($('#prev').attr('data-offset'));
  offset -= step;

  if ( offset < 0 ) {
    return false;
  }

  showPreviews(previews, offset);
  $('#next').attr('data-offset', offset);
  $('#prev').attr('data-offset', offset);
//  console.log( offset );
}

function switchMode(currentImgId, mode) {

  mode == 'screen' ? mode='image': mode='screen';

  // set icon to display
  var icon = 'resize';
  if ( mode == 'image' ) { icon = 'fullscreen'; }

  // show image
  showImage('#picteria-1', mode, 'resize');

  // show icon
  $('#mode').attr('src', '/img/' + icon + '.png');

  return mode;
}

function showImage(currentImgId, mode, resize) {

  setTimeout(function(){
    mode == 'screen' ? fullScreen(currentImgId, resize) : fullImage(currentImgId, resize);
  }, 50);
}

function fullImage(currentImgId, resize) {

  var item = $(currentImgId);

  if (!resize) {

    var imgPath = item.attr( 'src' );
    var img = new Image();
    img.src = imgPath;

    img.onload = function() {
      _handleFullImageCss(item)
    };
  }
  else {
    _handleFullImageCss(item);
  }
}

function _handleFullImageCss(item) {

  item.css( 'max-width',  '100%' );
  item.css( 'max-height', '100%' );

  item.removeClass('hide');

  var orientation = getOrientation();

  // remove css added by fullScreen
  item.css('width', '');
  item.css('height', '');

  if ( orientation == 'l' ) {
    var leftPos = (getWidth() - item.width()) / 2;
    item.css('left', leftPos);
    item.css('top', 0);
  }
  else {
    var topPos = (getHeight() - item.height()) / 2;
    item.css('top', topPos);
    item.css('left', 0);
  }
}

function fullScreen(currentImgId, resize) {

  var item = $(currentImgId);

  item.addClass('hide');

  if (!resize) {

    var imgPath = item.attr( 'src' );
    var img = new Image();
    img.src = imgPath;

    img.onload = function() {
      _handleFullScreenCss(item);
    };
  }
  else {
    _handleFullScreenCss(item);
  }
  item.removeClass('hide');
}

function _handleFullScreenCss(item) {

  var screenWidth  = getWidth();
  var screenHeight = getHeight();
  var orientation  = getOrientation();

  //remove css added by fullImage
  item.css( 'max-width',  '' );
  item.css( 'max-height', '' );

  item.css('width', '');
  item.css('height', '');

  var OriginalImageWidth = item.width();
  var OriginalImageHeigth = item.height();

  if ( orientation == 'l' ) {
    var imgHeight = screenWidth / OriginalImageWidth * OriginalImageHeigth;
    var topPos = ( screenHeight - imgHeight) / 2;
    item.css('width', screenWidth);
    item.css('height', imgHeight);
    item.css( 'top', topPos );
    item.css( 'left', 0 );

  }
  else {
    var imgWidth = screenHeight / OriginalImageHeigth * OriginalImageWidth;
    var leftPos = ( screenWidth - imgWidth) / 2;
    item.css('height', screenHeight);
    item.css('width', imgWidth);
    item.css( 'left', leftPos );
    item.css( 'top', 0 );
  }
}

function getWidth() {
 return $(document).width();
}

function getHeight() {
  return $(document).height();
}

function getOrientation() {

  if ( getWidth() * 0.80 > getHeight() ) {
    return 'l';
  }
  return 'p';
}

//function getSize() {
//return getWidth() + 'x' + getHeight();
//}
<commit_msg>forward key pic navigation ok<commit_after>$(function() {

  // get gallery name
  var gal = $('title').text().split(" / ")[1];

  // get image list
  var images = $('#container').find('img').map(function() { return this.id; }).get();

  // get previews list
  var previews = $('#controls').find('img.preview').map(function() { return this.id; }).get();

  // get id of current image
  var currentImgId = '#' + images[0];

  // place holder for the current image number
  var currentImgNumber = previews[0];
//  var currentImgNumber = $(previews).get(-1);
  currentImgNumber = currentImgNumber.replace('picteria-', '');
  currentImgNumber = currentImgNumber.replace('-prev', '');
  console.log( 'currentImgNumber : ' + currentImgNumber);

  // image mode : screen / image
  var mode = 'image';

  // total number of previews
  var numPreviews = 0;

  // number of previews showed in previous previews screens
  var previewShowed = 0;

  var PreviousNumPreviews = 0;

  // -- show first image on page load -----------------------------------------
  showImage(currentImgId, mode);

  setTimeout(function() {
    PreviousNumPreviews = numPreviews;
    numPreviews = countPreviews(previews);
  }, 60);

  // add active state style
  console.log( 'currentImgId : ' + currentImgId );
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');

  // -- handle screen resize --------------------------------------------------
  $(window).resize(function() {
    showImage(currentImgId, mode);
    showPreviews(previews);
  });

  // -- Handle show image -----------------------------------------------------
  $('.preview').click(function() {

//    $.each(images, function(index, item) {
//      $('#' + item).addClass('hide');
//    });

    $(currentImgId + '-prev').css('border', 'none');

    // get clicked element id
    var id = $(this).attr('id');

    // get corresponding img id
    var img = id.replace('-prev', '');

    currentImgId = '#' + img;

    $(currentImgId + '-prev').css('border', '1px solid white');

    currentImgNumber = img.replace('picteria-', '');

    $.ajax({
      url: '/' + gal + '/' + currentImgNumber,
      type: "get",
      success: function(data){
        $("#container").html(data);
        showImage('#picteria-1', mode);
      },
      error:function(){
        $("#container").html('There is error while submit');
      }
    });

//    $.each(images, function(index, item) {
//      if ( item == img ) {

    showImage('#picteria-1', mode);
    $('#picteria-1').removeClass('hide');

//      }
//      else {
//        $('#' + item).addClass('hide');
//      }
//    });
  });

  // -- Handle next previews --------------------------------------------------
  $('#next').click(function() {

//    console.log('');

//    setTimeout(function() {
//      PreviousNumPreviews = numPreviews;
//      numPreviews = countPreviews(previews);
//    }, 60);
  });

  // -- Handle previous previews ----------------------------------------------
  $('#prev').click(function() {
    setTimeout(function() {
      PreviousNumPreviews = numPreviews;
      numPreviews = countPreviews(previews);
    }, 60);
  });

  // -- Handle mode change ----------------------------------------------------
  $('#mode').click(function() {
    mode = switchMode(currentImgId, mode);
    return mode;
  });

  // -- keyboard shortcuts ----------------------------------------------------
  // r :           switch mode
  // up arrow :    show next previews
  // down arrow :  show previous previews
  // right arrow : show next image
  // left arrow  : show previous image
  // b :           back to galleries index
  $(document).keydown(function(e) {
//    console.log(e.which);
    if ( e.which == 82 ) {
      mode = switchMode(currentImgId, mode);
    }
    else if ( e.which == 38 ) {
      nextPreviews(previews, numPreviews);
    }
    else if ( e.which == 40 ) {
      prevPreviews(previews, numPreviews);
    }
    else if ( e.which == 39 ) {

      if ($('#picteria-' + ( parseInt(currentImgNumber) + 1 ) + '-prev').length == 0) {

        var galItems = $('#controls').attr('data-galItems');

        if ( currentImgNumber == galItems ) {
          return false;
        }

        url = '/' + gal + '/' + getWidth() + '/' + ( parseInt(currentImgNumber) + 1 );

        console.log('url : ' + url);
        $.ajax({
          url: url,
          type: "get",
          success: function(data){
            $("body").html(data);
            $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');
          },
          error:function() {
            $("#container").html('There is error while submit');
          }
        });
        currentImgNumber++;
      }
      else {
        currentImgNumber = nextImage(gal, currentImgNumber, mode);
      }
    }
    else if ( e.which == 37 ) {

      if ($('#picteria-' + ( parseInt(currentImgNumber) - 1 ) + '-prev').length == 0) {

        if ( currentImgNumber == 1 ) {
          return false;
        }

        url = '/' + gal + '/' + getWidth() + '/' + ( parseInt(currentImgNumber) - 1 );
        window.location.href = url;
      }
      else {
        currentImgNumber = prevImage(gal, currentImgNumber, mode);
      }
    }
    else if ( e.which == 66 ) {
      window.location.href = "http://picteria/index.php/";
    }
  });

});

function countPreviews(previews) {

  var numPreviews = 0;

  $.each(previews, function(index, item) {
   current = $('#' + item).attr('class');
   if ( current.match(/hide/) ) { return true; };
   numPreviews++;
  });
  return numPreviews;
}

function nextImage(gal, currentImgNumber, mode) {

  if ($('#picteria-' + ( parseInt(currentImgNumber) + 1 ) + '-prev').length == 0) {
    return currentImgNumber;
  }

  // remove active state style from previous preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', 'none');

  currentImgNumber++;

  $.ajax({
    url: '/' + gal + '/' + currentImgNumber,
    type: "get",
    success: function(data){
      $("#container").html(data);
      showImage('#picteria-1', mode);
      console.log('currentImgNumber : ' + currentImgNumber)
    },
    error:function() {
      $("#container").html('There is error while submit');
    }
  });

  // add active state style to current preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');
//  console.log('currentImgNumber in next image' + currentImgNumber);
  return currentImgNumber;
}

function prevImage(gal, currentImgNumber, mode) {

  if ($('#picteria-' + ( parseInt(currentImgNumber) - 1 ) + '-prev').length == 0) {
    return currentImgNumber;
  }

  // remove active state style from previous preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', 'none');

  currentImgNumber--;
  if (currentImgNumber < 1) { currentImgNumber = 1; }

  $.ajax({
    url: '/' + gal + '/' + currentImgNumber,
    type: "get",
    success: function(data){
      $("#container").html(data);
      showImage('#picteria-1', mode);
    },
    error:function(){
      $("#container").html('There is error while submit');
    }
  });

  // add active state style to current preview
  $('#picteria-' + currentImgNumber + '-prev').css('border', '1px solid white');

  console.log( 'currentImgNumber in prev image : ' + currentImgNumber);

  return currentImgNumber;
}

function nextPreviews(previews, step) {

  offset = parseInt($('#next').attr('data-offset'));
  offset += step;

  if ( offset >= previews.length ) {
    return false;
  }

  showPreviews(previews, offset);
  $('#next').attr('data-offset', offset);
  $('#prev').attr('data-offset', offset);
//  console.log( offset );
}

function prevPreviews(previews, step) {

  offset = parseInt($('#prev').attr('data-offset'));
  offset -= step;

  if ( offset < 0 ) {
    return false;
  }

  showPreviews(previews, offset);
  $('#next').attr('data-offset', offset);
  $('#prev').attr('data-offset', offset);
//  console.log( offset );
}

function switchMode(currentImgId, mode) {

  mode == 'screen' ? mode='image': mode='screen';

  // set icon to display
  var icon = 'resize';
  if ( mode == 'image' ) { icon = 'fullscreen'; }

  // show image
  showImage('#picteria-1', mode, 'resize');

  // show icon
  $('#mode').attr('src', '/img/' + icon + '.png');

  return mode;
}

function showImage(currentImgId, mode, resize) {

  setTimeout(function(){
    mode == 'screen' ? fullScreen(currentImgId, resize) : fullImage(currentImgId, resize);
  }, 50);
}

function fullImage(currentImgId, resize) {

  var item = $(currentImgId);

  if (!resize) {

    var imgPath = item.attr( 'src' );
    var img = new Image();
    img.src = imgPath;

    img.onload = function() {
      _handleFullImageCss(item)
    };
  }
  else {
    _handleFullImageCss(item);
  }
}

function _handleFullImageCss(item) {

  item.css( 'max-width',  '100%' );
  item.css( 'max-height', '100%' );

  item.removeClass('hide');

  var orientation = getOrientation();

  // remove css added by fullScreen
  item.css('width', '');
  item.css('height', '');

  if ( orientation == 'l' ) {
    var leftPos = (getWidth() - item.width()) / 2;
    item.css('left', leftPos);
    item.css('top', 0);
  }
  else {
    var topPos = (getHeight() - item.height()) / 2;
    item.css('top', topPos);
    item.css('left', 0);
  }
}

function fullScreen(currentImgId, resize) {

  var item = $(currentImgId);

  item.addClass('hide');

  if (!resize) {

    var imgPath = item.attr( 'src' );
    var img = new Image();
    img.src = imgPath;

    img.onload = function() {
      _handleFullScreenCss(item);
    };
  }
  else {
    _handleFullScreenCss(item);
  }
  item.removeClass('hide');
}

function _handleFullScreenCss(item) {

  var screenWidth  = getWidth();
  var screenHeight = getHeight();
  var orientation  = getOrientation();

  //remove css added by fullImage
  item.css( 'max-width',  '' );
  item.css( 'max-height', '' );

  item.css('width', '');
  item.css('height', '');

  var OriginalImageWidth = item.width();
  var OriginalImageHeigth = item.height();

  if ( orientation == 'l' ) {
    var imgHeight = screenWidth / OriginalImageWidth * OriginalImageHeigth;
    var topPos = ( screenHeight - imgHeight) / 2;
    item.css('width', screenWidth);
    item.css('height', imgHeight);
    item.css( 'top', topPos );
    item.css( 'left', 0 );

  }
  else {
    var imgWidth = screenHeight / OriginalImageHeigth * OriginalImageWidth;
    var leftPos = ( screenWidth - imgWidth) / 2;
    item.css('height', screenHeight);
    item.css('width', imgWidth);
    item.css( 'left', leftPos );
    item.css( 'top', 0 );
  }
}

function getWidth() {
 return $(document).width();
}

function getHeight() {
  return $(document).height();
}

function getOrientation() {

  if ( getWidth() * 0.80 > getHeight() ) {
    return 'l';
  }
  return 'p';
}

//function getSize() {
//return getWidth() + 'x' + getHeight();
//}
<|endoftext|>


<commit_before>app.game = {

  start: function() {

    this.entities = new ENGINE.Entities;
    this.collisions = new ENGINE.Collisions(this.entities);
    this.collisions.callback = this.collisionHandler.bind(this);

    this.players = [];

    this.addPlayer(app.center.x, app.center.y, 0);

    this.spawnAsteroid();
    this.spawnAsteroid();
    this.spawnAsteroid();
    this.spawnAsteroid();

  },

  collisionHandler: function(a, b) {

  },

  spawnAsteroid: function() {

    var angle = Math.random() * 6;

    var x = Math.cos(angle) * app.width;
    var y = Math.sin(angle) * app.width;

    this.entities.add(ENGINE.Asteroid, {
      x: x,
      y: y,
      direction: angle
    });

  },

  addPlayer: function(x, y, team) {

    var player = this.entities.add(ENGINE.Player, {
      team: team,
      x: x,
      y: y
    });

    this.players.push(player);

    return player;
  },

  wrap: function(entity) {

    entity.x = Utils.wrap(entity.x, -entity.radius, app.width + entity.radius);
    entity.y = Utils.wrap(entity.y, -entity.radius, app.height + entity.radius);

  },

  /* events */

  enter: function() {

  },

  step: function(delta) {

    this.entities.step(delta);
    this.collisions.step(delta);

  },

  render: function(delta) {

    app.layer.clear("#003");

    this.entities.render(delta);

    this.hud.render(delta);

  },

  keydown: function(e) {
    switch (e.key) {
      case "space":
        this.players[0].shooting = true;
        break;
      case "left":
        this.players[0].left = true;
        break;
      case "right":
        this.players[0].right = true;
        break;
      case "up":
        this.players[0].up = true;
        break;
    }
  },

  keyup: function(e) {
    switch (e.key) {
      case "space":
        this.players[0].shooting = false;
        break;
      case "left":
        this.players[0].left = false;
        break;
      case "right":
        this.players[0].left = false  ;
        break;
      case "up":
        this.players[0].up = false;
        break;
    }
  }

};<commit_msg>right arrow action fixed<commit_after>app.game = {

  start: function() {

    this.entities = new ENGINE.Entities;
    this.collisions = new ENGINE.Collisions(this.entities);
    this.collisions.callback = this.collisionHandler.bind(this);

    this.players = [];

    this.addPlayer(app.center.x, app.center.y, 0);

    this.spawnAsteroid();
    this.spawnAsteroid();
    this.spawnAsteroid();
    this.spawnAsteroid();

  },

  collisionHandler: function(a, b) {

  },

  spawnAsteroid: function() {

    var angle = Math.random() * 6;

    var x = Math.cos(angle) * app.width;
    var y = Math.sin(angle) * app.width;

    this.entities.add(ENGINE.Asteroid, {
      x: x,
      y: y,
      direction: angle
    });

  },

  addPlayer: function(x, y, team) {

    var player = this.entities.add(ENGINE.Player, {
      team: team,
      x: x,
      y: y
    });

    this.players.push(player);

    return player;
  },

  wrap: function(entity) {

    entity.x = Utils.wrap(entity.x, -entity.radius, app.width + entity.radius);
    entity.y = Utils.wrap(entity.y, -entity.radius, app.height + entity.radius);

  },

  /* events */

  enter: function() {

  },

  step: function(delta) {

    this.entities.step(delta);
    this.collisions.step(delta);

  },

  render: function(delta) {

    app.layer.clear("#003");

    this.entities.render(delta);

    this.hud.render(delta);

  },

  keydown: function(e) {
    switch (e.key) {
      case "space":
        this.players[0].shooting = true;
        break;
      case "left":
        this.players[0].left = true;
        break;
      case "right":
        this.players[0].right = true;
        break;
      case "up":
        this.players[0].up = true;
        break;
    }
  },

  keyup: function(e) {
    switch (e.key) {
      case "space":
        this.players[0].shooting = false;
        break;
      case "left":
        this.players[0].left = false;
        break;
      case "right":
        this.players[0].right = false;
        break;
      case "up":
        this.players[0].up = false;
        break;
    }
  }

};<|endoftext|>


<commit_before>import { barelyServe } from "barely-a-dev-server";
import { build } from "esbuild";
import { readFileSync } from "fs";
import { chmod } from "fs/promises";

build({
  entryPoints: ["src/webauthn-json/index.ts"],
  format: "cjs",
  target: "es2015",
  bundle: true,
  sourcemap: true,
  outfile: "dist/cjs/webauthn-json.cjs",
});

build({
  entryPoints: ["src/webauthn-json/extended.ts"],
  format: "cjs",
  target: "es2015",
  bundle: true,
  sourcemap: true,
  outfile: "dist/cjs/webauthn-json.extended.cjs",
});

build({
  entryPoints: ["src/webauthn-json/index.ts"],
  format: "esm",
  target: "es2020",
  bundle: true,
  sourcemap: true,
  outfile: "dist/esm/webauthn-json.js",
});

build({
  entryPoints: ["src/webauthn-json/extended.ts"],
  format: "esm",
  target: "es2020",
  bundle: true,
  sourcemap: true,
  outfile: "dist/esm/webauthn-json.extended.js",
});

build({
  entryPoints: ["src/webauthn-json/browser-global.ts"],
  format: "cjs",
  target: "es6",
  bundle: true,
  sourcemap: true,
  outfile: "dist/browser-global/webauthn-json.browser-global.js",
});

build({
  entryPoints: ["src/dev/inspector/inspector.ts"],
  format: "iife",
  target: "es6",
  bundle: true,
  sourcemap: true,
  outfile: "dist/inspector/inspector.js",
});

const { version } = JSON.parse(
  readFileSync(new URL("../package.json", import.meta.url)),
);
await build({
  entryPoints: ["src/bin/main.ts"],
  format: "esm",
  target: "es2020",
  bundle: true,
  sourcemap: true,
  define: { WEBAUTHN_JSON_VERSION: JSON.stringify(version) },
  banner: { js: "#!/usr/bin/env node" },
  outfile: "dist/bin/main.js",
});
chmod("dist/bin/main.js", 0o755);
<commit_msg>Compile ESM to ES2019.<commit_after>import { barelyServe } from "barely-a-dev-server";
import { build } from "esbuild";
import { readFileSync } from "fs";
import { chmod } from "fs/promises";

build({
  entryPoints: ["src/webauthn-json/index.ts"],
  format: "cjs",
  target: "es2015",
  bundle: true,
  sourcemap: true,
  outfile: "dist/cjs/webauthn-json.cjs",
});

build({
  entryPoints: ["src/webauthn-json/extended.ts"],
  format: "cjs",
  target: "es2015",
  bundle: true,
  sourcemap: true,
  outfile: "dist/cjs/webauthn-json.extended.cjs",
});

build({
  entryPoints: ["src/webauthn-json/index.ts"],
  format: "esm",
  target: "es2019",
  bundle: true,
  sourcemap: true,
  outfile: "dist/esm/webauthn-json.js",
});

build({
  entryPoints: ["src/webauthn-json/extended.ts"],
  format: "esm",
  target: "es2019",
  bundle: true,
  sourcemap: true,
  outfile: "dist/esm/webauthn-json.extended.js",
});

build({
  entryPoints: ["src/webauthn-json/browser-global.ts"],
  format: "cjs",
  target: "es6",
  bundle: true,
  sourcemap: true,
  outfile: "dist/browser-global/webauthn-json.browser-global.js",
});

build({
  entryPoints: ["src/dev/inspector/inspector.ts"],
  format: "iife",
  target: "es6",
  bundle: true,
  sourcemap: true,
  outfile: "dist/inspector/inspector.js",
});

const { version } = JSON.parse(
  readFileSync(new URL("../package.json", import.meta.url)),
);
await build({
  entryPoints: ["src/bin/main.ts"],
  format: "esm",
  target: "es2019",
  bundle: true,
  sourcemap: true,
  define: { WEBAUTHN_JSON_VERSION: JSON.stringify(version) },
  banner: { js: "#!/usr/bin/env node" },
  outfile: "dist/bin/main.js",
});
chmod("dist/bin/main.js", 0o755);
<|endoftext|>


<commit_before>'use strict';
import _ from 'lodash';
import {EOL} from 'os';
import indentString from 'indent-string';
import fs from 'fs';
import funcHasParam from 'func-has-param';
import {join} from 'path';
import newlineRegex from 'newline-regex';
import {start} from 'count-spaces';

/**
 * Returns whether the module's config function is injecting parameter
 * @param {String} fileContents - file contents of module
 * @param {Object} config - user's config
 * @return {Boolean} - does module have param?
 */
function hasParam(fileContents, config) {
  const param = config.ngRoute ? '$routeProvider' : '$stateProvider';

  let opts = config.appScript === 'ts' ? {language: 'ts'} : null;

  if (config.appScript === 'coffee') {
    return new RegExp('\\(.*' + param + '.*\\) ->').test(fileContents);
  }

  return funcHasParam(fileContents, 'config', param, opts);
}

/**
 * Line includes config function
 * @param {String} line - line to check for config function existence
 * @param {Boolean} isCoffeeScript - is the line written in CoffeeScript?
 * @return {Boolean} - line has config function
 */
function lineHasConfigFunction(line, isCoffeeScript) {
  if (isCoffeeScript) {
    return line.indexOf('config') > -1 && line.indexOf('->') > -1;
  }

  return line.indexOf('function config(') > -1;
}

/**
 * Add param to config function line
 * @param {String} line - line to add parameter to
 * @param {String} param - parameter to add
 * @param {String} lang - which language is line written in? (coffee, es6, js, or ts)
 * @param {String} [type] - when lang === ts then insert type
 * @return {String} - config function line with parameter added
 */
function addParamToConfigFunction(line, param, lang, type) {
  let paramToInsert = `$${param}`;

  // config line ending will be stripped
  // this will add it back
  if (lang === 'ts') {
    paramToInsert += `: ${type}) {`;
  } else if (lang === 'coffee') {
    paramToInsert += ') ->';
  } else {
    paramToInsert += ') {';
  }

  // previous state had no parameters - config()
  if (line.lastIndexOf('(') === line.lastIndexOf(')') - 1) {
    return line.slice(0, line.lastIndexOf(')')) + paramToInsert;
  }

  // CoffeScript && previous state had no existing parameters - config ->
  if (lang === 'coffee' && line.lastIndexOf('(') === -1 && line.lastIndexOf(')') === -1) {
    return line.slice(0, line.lastIndexOf('g')) + 'g (' + paramToInsert;
  }

  // previous state had existing parameters - config()
  return line.slice(0, line.lastIndexOf(')')) + ', ' + paramToInsert;
}

/**
 * Injects the parameter into the module's config function
 * @param {Array} lines - lines to modify
 * @param {Object} config - user's config
 * @return {Array} - modified lines
 */
function addParam(lines, config) {
  const param = config.ngRoute ? 'routeProvider' : 'stateProvider'
    , type = config.ngRoute ? 'ng.route.IRouteProvider' : 'ng.ui.IStateProvider';

  return lines.map(line => {
    if (lineHasConfigFunction(line, config.appScript === 'coffee')) {
      return addParamToConfigFunction(line, param, config.appScript, type);
    }

    return line;
  });
}

/**
 * Analyzes lines to determine where to insert new route
 * @param {Array} lines - lines to analyze
 * @param {Object} config - user's config
 * @return {Object} - info regarding insertion points
 */
function analyzeLines(lines, config) {
  const newRoute = config.ngRoute ? 'when' : 'state';

  let braceCount = 0
    , analysis;

  analysis = {
    routeStartIndex: -1,
    routeEndIndex: -1,
    configFunctionIndex: -1
  };

  lines.forEach((line, i) => {
    if (config.appScript === 'ts' || config.appScript === 'js' || config.appScript === 'es6') {
      if (line.indexOf('function config(') > -1) {
        analysis.configFunctionIndex = i;
      }

      // look for .state and set routeStartIndex
      if (line.indexOf('.' + newRoute + '(') > -1) {
        analysis.routeStartIndex = i;
      }

      // open braces add to braceCount
      if (analysis.routeStartIndex > -1 && line.indexOf('{') > -1) {
        braceCount++;
      }

      // close braces subract from braceCount
      if (analysis.routeStartIndex > -1 && line.indexOf('}') > -1) {
        braceCount--;
      }

      // when braceCount = 0 the end of the state has been reached
      // set routeEndIndex
      if (analysis.routeStartIndex > -1 && braceCount === 0) {
        analysis.routeEndIndex = i;
      }
    } else {
      if (line.indexOf('.config') > -1 && line.indexOf('->') > -1) {
        analysis.configFunctionIndex = i;
      }

      // look for .state and set routeStartIndex
      if (line.indexOf('.' + newRoute) > -1) {
        analysis.routeStartIndex = i;
      }
    }
  });

  analysis.existingRouteFound = analysis.routeStartIndex !== -1;

  return analysis;
}

/**
 * Returns new state to add
 * @param {Object} state - state info to format
 * @param {Object} analysis - information for insertion
 * @param {Object} config - user's config
 * @return {String[]} - lines of new state
 */
function prepareState(state, analysis, config) {
  let context, templateFile;

  context = {
    analysis,
    config,
    state
  };

  templateFile = join(__dirname, 'templates', `_${(config.ngRoute ? 'ngroute' : 'uirouter')}.`);
  // js, es6, ts files all use the same templates
  templateFile += config.appScript === 'coffee' ? 'coffee' : 'js';

  return _.template(fs.readFileSync(templateFile))(context).split(newlineRegex);
}

/**
 * Adds state to lines
 * @param {Array} lines - lines to modify with state
 * @param {Object} state - state info to add to lines
 * @param {Object} analysis - insertion info
 * @param {Object} config - user's config
 * @return {Array} - modified lines with added state
 */
function addState(lines, state, analysis, config) {
  let insertLine, lineToCheck, numOfSpaces, numOfSpacesCounter;

  // count spaces to prepend to state
  lineToCheck = lines[analysis.existingRouteFound ? analysis.routeStartIndex : analysis.configFunctionIndex];

  numOfSpaces = start(lineToCheck);

  // if there is an existing route, remove 2 more spaces from indent to line up with existing routes
  // else add 2 spaces
  if (analysis.existingRouteFound) {
    numOfSpaces -= 2;
  } else {
    numOfSpaces += 2;
  }

  // prepend spaces
  state = state.map(function (stateLine) {
    return indentString(stateLine, ' ', numOfSpaces);
  });

  if (config.appScript !== 'coffee') {
    insertLine = analysis.existingRouteFound ? analysis.routeEndIndex : analysis.configFunctionIndex + 1;
  } else if (analysis.existingRouteFound) {
    // determine where last state ends by examining spaces
    // insert new route on first line to have less spaces at the start
    numOfSpaces = start(lines[analysis.routeStartIndex]);
    numOfSpacesCounter = numOfSpaces;
    insertLine = analysis.routeStartIndex;
    while (numOfSpacesCounter >= numOfSpaces) {
      insertLine++;
      numOfSpacesCounter = start(lines[insertLine]);
    }
  } else {
    insertLine = analysis.configFunctionIndex + 1;
  }

  lines.splice(insertLine, 0, state.map(stateline => stateline).join(EOL));

  return lines.join(EOL);
}

/**
 * Adds route to module's config
 * @param {String} fileContents - file contents of module
 * @param {Object} state - state info to add
 * @param {Object} config - user's config
 * @return {String} - modified file contents with added state
 */
exports.addRoute = function (fileContents, state, config) {
  // checking if provider is used
  let needsParam = !hasParam(fileContents, config)

    // split fileContents
    , lines

    // new state insertion info
    , analysis
    , newState;

  lines = fileContents.split(newlineRegex);
  analysis = analyzeLines(lines, config);

  // if file needs parameter, add it
  if (needsParam) {
    lines = addParam(lines, config);
  }

  newState = prepareState(state, analysis, config);

  return addState(lines, newState, analysis, config);
};
<commit_msg>style(utils-route): use lambda<commit_after>'use strict';
import _ from 'lodash';
import {EOL} from 'os';
import indentString from 'indent-string';
import fs from 'fs';
import funcHasParam from 'func-has-param';
import {join} from 'path';
import newlineRegex from 'newline-regex';
import {start} from 'count-spaces';

/**
 * Returns whether the module's config function is injecting parameter
 * @param {String} fileContents - file contents of module
 * @param {Object} config - user's config
 * @return {Boolean} - does module have param?
 */
function hasParam(fileContents, config) {
  const param = config.ngRoute ? '$routeProvider' : '$stateProvider';

  let opts = config.appScript === 'ts' ? {language: 'ts'} : null;

  if (config.appScript === 'coffee') {
    return new RegExp('\\(.*' + param + '.*\\) ->').test(fileContents);
  }

  return funcHasParam(fileContents, 'config', param, opts);
}

/**
 * Line includes config function
 * @param {String} line - line to check for config function existence
 * @param {Boolean} isCoffeeScript - is the line written in CoffeeScript?
 * @return {Boolean} - line has config function
 */
function lineHasConfigFunction(line, isCoffeeScript) {
  if (isCoffeeScript) {
    return line.indexOf('config') > -1 && line.indexOf('->') > -1;
  }

  return line.indexOf('function config(') > -1;
}

/**
 * Add param to config function line
 * @param {String} line - line to add parameter to
 * @param {String} param - parameter to add
 * @param {String} lang - which language is line written in? (coffee, es6, js, or ts)
 * @param {String} [type] - when lang === ts then insert type
 * @return {String} - config function line with parameter added
 */
function addParamToConfigFunction(line, param, lang, type) {
  let paramToInsert = `$${param}`;

  // config line ending will be stripped
  // this will add it back
  if (lang === 'ts') {
    paramToInsert += `: ${type}) {`;
  } else if (lang === 'coffee') {
    paramToInsert += ') ->';
  } else {
    paramToInsert += ') {';
  }

  // previous state had no parameters - config()
  if (line.lastIndexOf('(') === line.lastIndexOf(')') - 1) {
    return line.slice(0, line.lastIndexOf(')')) + paramToInsert;
  }

  // CoffeScript && previous state had no existing parameters - config ->
  if (lang === 'coffee' && line.lastIndexOf('(') === -1 && line.lastIndexOf(')') === -1) {
    return line.slice(0, line.lastIndexOf('g')) + 'g (' + paramToInsert;
  }

  // previous state had existing parameters - config()
  return line.slice(0, line.lastIndexOf(')')) + ', ' + paramToInsert;
}

/**
 * Injects the parameter into the module's config function
 * @param {Array} lines - lines to modify
 * @param {Object} config - user's config
 * @return {Array} - modified lines
 */
function addParam(lines, config) {
  const param = config.ngRoute ? 'routeProvider' : 'stateProvider'
    , type = config.ngRoute ? 'ng.route.IRouteProvider' : 'ng.ui.IStateProvider';

  return lines.map(line => {
    if (lineHasConfigFunction(line, config.appScript === 'coffee')) {
      return addParamToConfigFunction(line, param, config.appScript, type);
    }

    return line;
  });
}

/**
 * Analyzes lines to determine where to insert new route
 * @param {Array} lines - lines to analyze
 * @param {Object} config - user's config
 * @return {Object} - info regarding insertion points
 */
function analyzeLines(lines, config) {
  const newRoute = config.ngRoute ? 'when' : 'state';

  let braceCount = 0
    , analysis;

  analysis = {
    routeStartIndex: -1,
    routeEndIndex: -1,
    configFunctionIndex: -1
  };

  lines.forEach((line, i) => {
    if (config.appScript === 'ts' || config.appScript === 'js' || config.appScript === 'es6') {
      if (line.indexOf('function config(') > -1) {
        analysis.configFunctionIndex = i;
      }

      // look for .state and set routeStartIndex
      if (line.indexOf('.' + newRoute + '(') > -1) {
        analysis.routeStartIndex = i;
      }

      // open braces add to braceCount
      if (analysis.routeStartIndex > -1 && line.indexOf('{') > -1) {
        braceCount++;
      }

      // close braces subract from braceCount
      if (analysis.routeStartIndex > -1 && line.indexOf('}') > -1) {
        braceCount--;
      }

      // when braceCount = 0 the end of the state has been reached
      // set routeEndIndex
      if (analysis.routeStartIndex > -1 && braceCount === 0) {
        analysis.routeEndIndex = i;
      }
    } else {
      if (line.indexOf('.config') > -1 && line.indexOf('->') > -1) {
        analysis.configFunctionIndex = i;
      }

      // look for .state and set routeStartIndex
      if (line.indexOf('.' + newRoute) > -1) {
        analysis.routeStartIndex = i;
      }
    }
  });

  analysis.existingRouteFound = analysis.routeStartIndex !== -1;

  return analysis;
}

/**
 * Returns new state to add
 * @param {Object} state - state info to format
 * @param {Object} analysis - information for insertion
 * @param {Object} config - user's config
 * @return {String[]} - lines of new state
 */
function prepareState(state, analysis, config) {
  let context, templateFile;

  context = {
    analysis,
    config,
    state
  };

  templateFile = join(__dirname, 'templates', `_${(config.ngRoute ? 'ngroute' : 'uirouter')}.`);
  // js, es6, ts files all use the same templates
  templateFile += config.appScript === 'coffee' ? 'coffee' : 'js';

  return _.template(fs.readFileSync(templateFile))(context).split(newlineRegex);
}

/**
 * Adds state to lines
 * @param {Array} lines - lines to modify with state
 * @param {Object} state - state info to add to lines
 * @param {Object} analysis - insertion info
 * @param {Object} config - user's config
 * @return {Array} - modified lines with added state
 */
function addState(lines, state, analysis, config) {
  let insertLine, lineToCheck, numOfSpaces, numOfSpacesCounter;

  // count spaces to prepend to state
  lineToCheck = lines[analysis.existingRouteFound ? analysis.routeStartIndex : analysis.configFunctionIndex];

  numOfSpaces = start(lineToCheck);

  // if there is an existing route, remove 2 more spaces from indent to line up with existing routes
  // else add 2 spaces
  if (analysis.existingRouteFound) {
    numOfSpaces -= 2;
  } else {
    numOfSpaces += 2;
  }

  // prepend spaces
  state = state.map(stateLine => indentString(stateLine, ' ', numOfSpaces));

  if (config.appScript !== 'coffee') {
    insertLine = analysis.existingRouteFound ? analysis.routeEndIndex : analysis.configFunctionIndex + 1;
  } else if (analysis.existingRouteFound) {
    // determine where last state ends by examining spaces
    // insert new route on first line to have less spaces at the start
    numOfSpaces = start(lines[analysis.routeStartIndex]);
    numOfSpacesCounter = numOfSpaces;
    insertLine = analysis.routeStartIndex;
    while (numOfSpacesCounter >= numOfSpaces) {
      insertLine++;
      numOfSpacesCounter = start(lines[insertLine]);
    }
  } else {
    insertLine = analysis.configFunctionIndex + 1;
  }

  lines.splice(insertLine, 0, state.map(stateline => stateline).join(EOL));

  return lines.join(EOL);
}

/**
 * Adds route to module's config
 * @param {String} fileContents - file contents of module
 * @param {Object} state - state info to add
 * @param {Object} config - user's config
 * @return {String} - modified file contents with added state
 */
exports.addRoute = function (fileContents, state, config) {
  // checking if provider is used
  let needsParam = !hasParam(fileContents, config)

    // split fileContents
    , lines

    // new state insertion info
    , analysis
    , newState;

  lines = fileContents.split(newlineRegex);
  analysis = analyzeLines(lines, config);

  // if file needs parameter, add it
  if (needsParam) {
    lines = addParam(lines, config);
  }

  newState = prepareState(state, analysis, config);

  return addState(lines, newState, analysis, config);
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name		Booru Mass Uploader
// @description	Add ability to bulk upload images to your booru
// @version     1.3
// @author		Seedmanc
// @include     http://*.booru.org/index.php*
// @include 	http://gelbooru.com/index.php*
// @include     http://safebooru.org/index.php*
// @include		https://moe.dev.myconan.net/*
// @include		http://behoimi.org/*
// @include		https://chan.sankakucomplex.com/*
// @include		http://atfbooru.ninja/*
// @include		http://danbooru.donmai.us/*

// you can add any boorus of your choice by following the pattern

// @grant 		none
// @run-at		document-end
// @noframes
// ==/UserScript==

if (window.top != window.self) {
	throw 'no iframes';
}

if (~document.location.href.indexOf('s=mass_upload')) {
	var xhr = new XMLHttpRequest();

	xhr.open('GET', location.protocol + '//crossorigin.me/http://seedmanc.github.io/Booru-mass-uploader/index.html?r=' + Math.random(), true);
	xhr.onreadystatechange = function () {
		var scripts;

		if (this.readyState != 4 || this.status != 200) {
			return;
		}

		document.getElementsByTagName('body')[0].innerHTML = this.responseText;
		scripts = document.getElementsByTagName('script');

		for (var i = 0; i < scripts.length; i++) {
			var node = scripts[i], parent = node.parentElement, d = document.createElement('script');

			d.async = node.async;
			d.src = node.src;
			parent.insertBefore(d, node);
			parent.removeChild(node);
		}
	};
	xhr.send();

} else {
	var navbar = document.getElementById('navbar') ||
		document.getElementsByClassName('flat-list2')[0] ||
		document.querySelector('#main-menu > ul') ||
		document.querySelector('nav > menu');
	var li = document.createElement("li");
	var a = document.createElement("a");
	var token = document.querySelector('meta[name="csrf-token"]');

	token = token && token.content;
	if (token) {
		localStorage.setItem('auth_token', token);
	}

	if (document.querySelector('[src*="moe-legacy"]') || document.querySelector('html.action-post') || document.querySelector('[href*="/post/upload"]')) {
		localStorage.setItem('current', 'moebooru');
	} else if (document.querySelector('[href*="/uploads/new"]') || ~document.documentElement.innerHTML.indexOf('Running Danbooru')) {
		localStorage.setItem('current', 'danbooru');
	}

	if (!navbar) {
		throw "can't link the uploader";
	}

	a.style.fontWeight = 'bold';
	a.appendChild(document.createTextNode('Mass Upload'));
	a.href = document.location.protocol + '//' + document.location.hostname + '/index.php?page=post&s=mass_upload';
	li.appendChild(a);
	navbar.appendChild(li);
}
<commit_msg>fixing little problem<commit_after>// ==UserScript==
// @name		Booru Mass Uploader
// @description	Add ability to bulk upload images to your booru
// @version     1.3
// @author		Seedmanc
// @include     http://*.booru.org/index.php*
// @include 	http://gelbooru.com/index.php*
// @include     http://safebooru.org/index.php*
// @include		https://moe.dev.myconan.net/*
// @include		http://behoimi.org/*
// @include		https://chan.sankakucomplex.com/*
// @include		http://atfbooru.ninja/*
// @include		http://danbooru.donmai.us/*

// you can add any boorus of your choice by following the pattern

// @grant 		none
// @run-at		document-end
// @noframes
// ==/UserScript==

if (window.top != window.self) {
	throw 'no iframes';
}

if (~document.location.href.indexOf('s=mass_upload')) {
	var xhr = new XMLHttpRequest();

	xhr.open('GET', location.protocol + '//crossorigin.me/http://seedmanc.github.io/Booru-mass-uploader/index.html?r=' + Math.random(), true);
	xhr.onreadystatechange = function () {
		var scripts;

		if (this.readyState != 4 || this.status != 200) {
			return;
		}

		document.getElementsByTagName('body')[0].innerHTML = this.responseText;
		scripts = document.getElementsByTagName('script');

		for (var i = 0; i < scripts.length; i++) {
			var node = scripts[i], parent = node.parentElement, d = document.createElement('script');

			d.async = node.async;
			d.src = node.src;
			parent.insertBefore(d, node);
			parent.removeChild(node);
		}
	};
	xhr.send();

} else {
	var navbar = document.getElementById('navbar') ||
		document.getElementsByClassName('flat-list2')[0] ||
		document.querySelector('#main-menu > ul') ||
		document.querySelector('nav > menu');
	var li = document.createElement("li");
	var a = document.createElement("a");
	var token = document.querySelector('meta[name="csrf-token"]');

	token = token && token.content;
	if (token) {
		localStorage.setItem('auth_token', token);
	}

	if (document.querySelector('[src*="moe-legacy"]') || document.querySelector('html.action-post') || document.querySelector('[href*="/post/upload"]')) {
		localStorage.setItem('current', 'moebooru');
	} else if (document.querySelector('[href*="/uploads/new"]') || ~document.documentElement.innerHTML.indexOf('Running Danbooru')) {
		localStorage.setItem('current', 'danbooru');
	}

	if (!navbar) {
		throw "can't link the uploader";
	}

	a.style.fontWeight = 'bold';
	a.appendChild(document.createTextNode('Mass Upload'));
	a.href = document.location.protocol + '//' + document.location.hostname + '/index.php?page=post&s=mass_upload';
	li.appendChild(a);
	navbar.appendChild(li);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Quildreen Motta <quildreen@gmail.com>
//
// 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.

/**
 * Provides common validation functions.
 *
 * @module lib/validations
 */

// -- Dependencies -----------------------------------------------------
var curry            = require('core.lambda').curry
var deepEqual        = require('deep-equal')
var Validation       = require('data.validation')
var singleDivergence = require('./divergence').divergence
var divergence       = require('./divergence').invertibleDivergence

// -- Aliases ----------------------------------------------------------
var Success        = Validation.Success
var Failure        = Validation.Failure
var classOf        = Function.call.bind(Object.prototype.toString)

// -- Helpers ----------------------------------------------------------

/**
 * Makes an assertion about a piece of data.
 *
 * This is a low-level method, and should be only used as a basis for
 * constructing higher-level validations, not as a validation itself.
 *
 * @method
 * @summary Boolean → Divergence → Object → Validation[Divergence, Divergence]
 */
exports.assert = curry(2, assert)
function assert(thing, divergence) {
  return thing?           Success(divergence)
  :      /* otherwise */  Failure(divergence)
}

/**
 * Checks if an exception matches an expected type.
 *
 * @summary
 * Error → Void → Boolean
 * Error → String → Boolean
 * Error → RegExp → Boolean
 * Error → Function → Boolean
 */
function matchErrorType(error, type) {
  return type == null?      true
  :      isString(type)?    error.message === type
  :      isTestable(type)?  type.test(error)
  :      /* otherwise */    error instanceof type
}

/**
 * Checks if something is a String.
 *
 * @summary α → Boolean
 */
function isString(a) {
  return classOf(a) === '[object String]'
}

/**
 * Checks if something is testable.
 *
 * @summary α → Boolean
 */
function isTestable(a) {
  return a.test && typeof a.test === 'function'
}

// -- Validations ------------------------------------------------------

/**
 * Asserts structural (deep) equality between two values.
 *
 * @method
 * @summary α → β → Validation[Divergence, Divergence]
 */
exports.equal = curry(2, equal)
function equal(a, b) {
  return assert( deepEqual(a, b)
               , divergence( '{:actual} to structurally equal {:expected}'
                           , '{:actual} to not structurally equal {:expected}'
                           ).make({ expected: a, actual: b }))
}

/**
 * Asserts that something is truthy.
 *
 * @method
 * @summary α → Validation[Divergence, Divergence]
 */
exports.ok = ok
function ok(a) {
  return assert( !!a
               , divergence( '{:actual} to be ok'
                           , '{:actual} to not be ok'
                           ).make({ actual: a }))
}

/**
 * Asserts strict equality (===) between two values.
 *
 * @method
 * @summary α → β → Validation[Divergence, Divergence]
 */
exports.strictEqual = curry(2, strictEqual)
function strictEqual(a, b) {
  return assert( a === b
               , divergence( '{:actual} to structurally equal {:expected}'
                           , '{:actual} to not structurally equal {:expected}'
                           ).make({ expected: a, actual: b }))
}

/**
 * Asserts that something is of a certain type (according to `typeof`).
 *
 * @method
 * @summary String → α → Validation[Divergence, Divergence]
 */
exports.beOfType = curry(2, beOfType)
function beOfType(type, a) {
  return assert( typeof a === type
               , divergence( '{:actual} to be of type "{:type}"'
                           , '{:actual} to not be of type "{:type}"'
                           ).make({ type: type, actual: a }))
}

/**
 * Asserts that something has a certain internal `[[Class]]`.
 *
 * @method
 * @summary String → α → Validation[Divergence, Divergence]
 */
exports.beOfClass = curry(2, beOfClass)
function beOfClass(className, a) {
  var actualClass = classOf(a).slice(8, -1)
  return assert( className === actualClass
               , divergence( '{:actual} to be of class "{:class}," got "{:actualClass}"'
                           , '{:actual} to not be of class "{:class}"'
                           ).make({ actual      : a
                                  , 'class'     : className
                                  , actualClass : actualClass }))
}

/**
 * Asserts that a contains something as a value.
 *
 * @method
 * @summary α → Sequence[α] → Validation[Divergence, Divergence]
 */
exports.contain = curry(2, contain)
function contain(x, xs) {
  return assert( xs.indexOf(x) != -1
               , divergence( '{:actual} to contain {:thing}'
                           , '{:actual} to not contain {:thing}'
                           ).make({ actual: xs, thing: x }))
}

/**
 * Asserts that a value matches a regular expression.
 *
 * @method
 * @summary RegExp → String → Validation[Divergence, Divergence]
 */
exports.match = curry(2, match)
function match(re, text) {
  return assert( re.test(text)
               , divergence( '{:text} to match {:re}'
                           , '{:text} to not match {:re}'
                           ).make({ text: text, re: re }))
}

/**
 * Asserts that a value has a certain property.
 *
 * @method
 * @summary String → Object → Validation[Divergence, Divergence]
 */
exports.have = curry(2, have)
function have(name, object) {
  return assert( name in object
               , divergence( '{:actual} to have property "{:name}"'
                           , '{:actual} to not have property "{:name}"'
                           ).make({ actual: object, name: name }))
}

/**
 * Asserts that a computation throws a particular exception.
 *
 * @method
 * @summary (Void → Void :: partial) → Function → Validation[Divergence, Divergence]
 */
exports.raise = curry(2, raise)
function raise(errorType, computation) {
  var _divergence = divergence( 'to throw an error {:errorType}'
                              , 'to not throw an error {:errorType}'
                              ).make({ errorType: errorType || '' })

  try {
    computation()
    return assert(true, _divergence)
  } catch(e) {
    return assert(matchErrorType(e, errorType), _divergence)
  }
}<commit_msg>Don't allow nulls.<commit_after>// Copyright (c) 2014 Quildreen Motta <quildreen@gmail.com>
//
// 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.

/**
 * Provides common validation functions.
 *
 * @module lib/validations
 */

// -- Dependencies -----------------------------------------------------
var curry            = require('core.lambda').curry
var deepEqual        = require('deep-equal')
var Validation       = require('data.validation')
var singleDivergence = require('./divergence').divergence
var divergence       = require('./divergence').invertibleDivergence

// -- Aliases ----------------------------------------------------------
var Success        = Validation.Success
var Failure        = Validation.Failure
var classOf        = Function.call.bind(Object.prototype.toString)

// -- Helpers ----------------------------------------------------------

/**
 * Makes an assertion about a piece of data.
 *
 * This is a low-level method, and should be only used as a basis for
 * constructing higher-level validations, not as a validation itself.
 *
 * @method
 * @summary Boolean → Divergence → Object → Validation[Divergence, Divergence]
 */
exports.assert = curry(2, assert)
function assert(thing, divergence) {
  return thing?           Success(divergence)
  :      /* otherwise */  Failure(divergence)
}

/**
 * Checks if an exception matches an expected type.
 *
 * @summary
 * Error → Void → Boolean
 * Error → String → Boolean
 * Error → RegExp → Boolean
 * Error → Function → Boolean
 */
function matchErrorType(error, type) {
  return type == null?      false
  :      isString(type)?    error.message === type
  :      isTestable(type)?  type.test(error)
  :      /* otherwise */    error instanceof type
}

/**
 * Checks if something is a String.
 *
 * @summary α → Boolean
 */
function isString(a) {
  return classOf(a) === '[object String]'
}

/**
 * Checks if something is testable.
 *
 * @summary α → Boolean
 */
function isTestable(a) {
  return a.test && typeof a.test === 'function'
}

// -- Validations ------------------------------------------------------

/**
 * Asserts structural (deep) equality between two values.
 *
 * @method
 * @summary α → β → Validation[Divergence, Divergence]
 */
exports.equal = curry(2, equal)
function equal(a, b) {
  return assert( deepEqual(a, b)
               , divergence( '{:actual} to structurally equal {:expected}'
                           , '{:actual} to not structurally equal {:expected}'
                           ).make({ expected: a, actual: b }))
}

/**
 * Asserts that something is truthy.
 *
 * @method
 * @summary α → Validation[Divergence, Divergence]
 */
exports.ok = ok
function ok(a) {
  return assert( !!a
               , divergence( '{:actual} to be ok'
                           , '{:actual} to not be ok'
                           ).make({ actual: a }))
}

/**
 * Asserts strict equality (===) between two values.
 *
 * @method
 * @summary α → β → Validation[Divergence, Divergence]
 */
exports.strictEqual = curry(2, strictEqual)
function strictEqual(a, b) {
  return assert( a === b
               , divergence( '{:actual} to structurally equal {:expected}'
                           , '{:actual} to not structurally equal {:expected}'
                           ).make({ expected: a, actual: b }))
}

/**
 * Asserts that something is of a certain type (according to `typeof`).
 *
 * @method
 * @summary String → α → Validation[Divergence, Divergence]
 */
exports.beOfType = curry(2, beOfType)
function beOfType(type, a) {
  return assert( typeof a === type
               , divergence( '{:actual} to be of type "{:type}"'
                           , '{:actual} to not be of type "{:type}"'
                           ).make({ type: type, actual: a }))
}

/**
 * Asserts that something has a certain internal `[[Class]]`.
 *
 * @method
 * @summary String → α → Validation[Divergence, Divergence]
 */
exports.beOfClass = curry(2, beOfClass)
function beOfClass(className, a) {
  var actualClass = classOf(a).slice(8, -1)
  return assert( className === actualClass
               , divergence( '{:actual} to be of class "{:class}," got "{:actualClass}"'
                           , '{:actual} to not be of class "{:class}"'
                           ).make({ actual      : a
                                  , 'class'     : className
                                  , actualClass : actualClass }))
}

/**
 * Asserts that a contains something as a value.
 *
 * @method
 * @summary α → Sequence[α] → Validation[Divergence, Divergence]
 */
exports.contain = curry(2, contain)
function contain(x, xs) {
  return assert( xs.indexOf(x) != -1
               , divergence( '{:actual} to contain {:thing}'
                           , '{:actual} to not contain {:thing}'
                           ).make({ actual: xs, thing: x }))
}

/**
 * Asserts that a value matches a regular expression.
 *
 * @method
 * @summary RegExp → String → Validation[Divergence, Divergence]
 */
exports.match = curry(2, match)
function match(re, text) {
  return assert( re.test(text)
               , divergence( '{:text} to match {:re}'
                           , '{:text} to not match {:re}'
                           ).make({ text: text, re: re }))
}

/**
 * Asserts that a value has a certain property.
 *
 * @method
 * @summary String → Object → Validation[Divergence, Divergence]
 */
exports.have = curry(2, have)
function have(name, object) {
  return assert( name in object
               , divergence( '{:actual} to have property "{:name}"'
                           , '{:actual} to not have property "{:name}"'
                           ).make({ actual: object, name: name }))
}

/**
 * Asserts that a computation throws a particular exception.
 *
 * @method
 * @summary (Void → Void :: partial) → Function → Validation[Divergence, Divergence]
 */
exports.raise = curry(2, raise)
function raise(errorType, computation) {
  var _divergence = divergence( 'to throw an error {:errorType}'
                              , 'to not throw an error {:errorType}'
                              ).make({ errorType: errorType || '' })

  try {
    computation()
    return assert(true, _divergence)
  } catch(e) {
    return assert(matchErrorType(e, errorType), _divergence)
  }
}<|endoftext|>


<commit_before>var get = Ember.get, set = Ember.set;

/**
@module ember
@submodule ember-states
*/

/**
  @class State
  @namespace Ember
  @extends Ember.Object
  @uses Ember.Evented
*/
Ember.State = Ember.Object.extend(Ember.Evented,
/** @scope Ember.State.prototype */{
  /**
    A reference to the parent state.

    @property parentState
    @type Ember.State
  */
  parentState: null,
  start: null,

  /**
    The name of this state.

    @property name
    @type String
  */
  name: null,

  /**
    The full path to this state.

    @property path
    @type String
  */
  path: Ember.computed(function() {
    var parentPath = get(this, 'parentState.path'),
        path = get(this, 'name');

    if (parentPath) {
      path = parentPath + '.' + path;
    }

    return path;
  }),

  /**
    @private

    Override the default event firing from `Ember.Evented` to
    also call methods with the given name.

    @method trigger
    @param name
  */
  trigger: function(name) {
    if (this[name]) {
      this[name].apply(this, [].slice.call(arguments, 1));
    }
    this._super.apply(this, arguments);
  },

  init: function() {
    var states = get(this, 'states');
    set(this, 'childStates', Ember.A());
    set(this, 'eventTransitions', get(this, 'eventTransitions') || {});

    var name, value, transitionTarget;

    // As a convenience, loop over the properties
    // of this state and look for any that are other
    // Ember.State instances or classes, and move them
    // to the `states` hash. This avoids having to
    // create an explicit separate hash.

    if (!states) {
      states = {};

      for (name in this) {
        if (name === "constructor") { continue; }

        if (value = this[name]) {
          if (transitionTarget = value.transitionTarget) {
            this.eventTransitions[name] = transitionTarget;
          }

          this.setupChild(states, name, value);
        }
      }

      set(this, 'states', states);
    } else {
      for (name in states) {
        this.setupChild(states, name, states[name]);
      }
    }

    // pathsCaches is a nested hash of the form:
    //   pathsCaches[stateManagerTypeGuid][path] == transitions_hash
    set(this, 'pathsCaches', {});
  },

  setPathsCache: function(stateManager, path, transitions) {
    var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
      pathsCaches = get(this, 'pathsCaches'),
      pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};

    pathsCacheForManager[path] = transitions;
    pathsCaches[stateManagerTypeGuid] = pathsCacheForManager;
  },

  getPathsCache: function(stateManager, path) {
    var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
      pathsCaches = get(this, 'pathsCaches'),
      pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};

    return pathsCacheForManager[path];
  },

  setupChild: function(states, name, value) {
    if (!value) { return false; }
    var instance;

    if (value instanceof Ember.State) {
      set(value, 'name', name);
      instance = value;
      instance.container = this.container;
    } else if (Ember.State.detect(value)) {
      instance = value.create({
        name: name,
        container: this.container
      });
    }

    if (instance instanceof Ember.State) {
      set(instance, 'parentState', this);
      get(this, 'childStates').pushObject(instance);
      states[name] = instance;
      return instance;
    }
  },

  lookupEventTransition: function(name) {
    var path, state = this;

    while(state && !path) {
      path = state.eventTransitions[name];
      state = state.get('parentState');
    }

    return path;
  },

  /**
    A Boolean value indicating whether the state is a leaf state
    in the state hierarchy. This is `false` if the state has child
    states; otherwise it is true.

    @property isLeaf
    @type Boolean
  */
  isLeaf: Ember.computed(function() {
    return !get(this, 'childStates').length;
  }),

  /**
    A boolean value indicating whether the state takes a context.
    By default we assume all states take contexts.

    @property hasContext
    @default true
  */
  hasContext: true,

  /**
    This is the default transition event.

    @event setup
    @param {Ember.StateManager} manager
    @param context
    @see Ember.StateManager#transitionEvent
  */
  setup: Ember.K,

  /**
    This event fires when the state is entered.

    @event enter
    @param {Ember.StateManager} manager
  */
  enter: Ember.K,

  /**
    This event fires when the state is exited.

    @event exit
    @param {Ember.StateManager} manager
  */
  exit: Ember.K
});

Ember.State.reopenClass({

  /**
    Creates an action function for transitioning to the named state while
    preserving context.

    The following example StateManagers are equivalent:

    ```javascript
    aManager = Ember.StateManager.create({
      stateOne: Ember.State.create({
        changeToStateTwo: Ember.State.transitionTo('stateTwo')
      }),
      stateTwo: Ember.State.create({})
    })

    bManager = Ember.StateManager.create({
      stateOne: Ember.State.create({
        changeToStateTwo: function(manager, context) {
          manager.transitionTo('stateTwo', context)
        }
      }),
      stateTwo: Ember.State.create({})
    })
    ```

    @method transitionTo
    @static
    @param {String} target
  */

  transitionTo: function(target) {

    var transitionFunction = function(stateManager, contextOrEvent) {
      var contexts = [],
          Event = Ember.$ && Ember.$.Event;

      if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
        if (contextOrEvent.hasOwnProperty('contexts')) {
          contexts = contextOrEvent.contexts.slice();
        }
      }
      else {
        contexts = [].slice.call(arguments, 1);
      }

      contexts.unshift(target);
      stateManager.transitionTo.apply(stateManager, contexts);
    };

    transitionFunction.transitionTarget = target;

    return transitionFunction;
  }

});
<commit_msg>documentation audit added more API docs to state.js<commit_after>var get = Ember.get, set = Ember.set;

/**
@module ember
@submodule ember-states
*/

/**
  The State class allows you to define individual states within a finite state machine
  inside your Ember application.

  ### How States Work

  When you setup a finite state machine this means you are setting up a mechanism to precisely
  manage the change within a system. You can control the various states or modes that your
  application can be in at any given time. Additionally, you can manage what specific states
  are allowed to transition to other states.

  The state machine is in only one state at a time. This state is known as the current state.
  It is possible to change from one state to another by a triggering event or condition.
  This is called a transition.

  Finite state machines are important because they allow the application developer to be
  deterministic about the the sequence of events that can happen within a system. Some states
  cannot be entered when the application is a given state.

  For example:

  A door that is in the `locked` state cannot be `opened` (you must transition to the `unlocked`
  state first).

  A door that is in the `open` state cannot be `locked` (you must transition to the `closed`
  state first).

  Each state instance has the following characteristics:

  - Zero or more parent states
  - A start state
  - A name
  - A path (a computed value that prefixes parent states and the complete hierarchy to itself )

  A state is known as a "leafState" when it is the last item on the path and has no children
  beneath it.

  The isLeaf property returns a boolean.

  Each state can emit the following transition events

  - setup
  - enter
  - exit

  A state object is ususally created in the context of a state manager.

  ```javascript
  doorStateManager = Ember.StateManager.create({
    locked: Ember.State.create(),
    closed: Ember.State.create(),
    unlocked: Ember.State.create(),
    open: Ember.State.create()
  });
  ```

  @class State
  @namespace Ember
  @extends Ember.Object
  @uses Ember.Evented
*/
Ember.State = Ember.Object.extend(Ember.Evented,
/** @scope Ember.State.prototype */{
  /**
    A reference to the parent state.

    @property parentState
    @type Ember.State
  */
  parentState: null,
  start: null,

  /**
    The name of this state.

    @property name
    @type String
  */
  name: null,

  /**
    The full path to this state.

    @property path
    @type String
  */
  path: Ember.computed(function() {
    var parentPath = get(this, 'parentState.path'),
        path = get(this, 'name');

    if (parentPath) {
      path = parentPath + '.' + path;
    }

    return path;
  }),

  /**
    @private

    Override the default event firing from `Ember.Evented` to
    also call methods with the given name.

    @method trigger
    @param name
  */
  trigger: function(name) {
    if (this[name]) {
      this[name].apply(this, [].slice.call(arguments, 1));
    }
    this._super.apply(this, arguments);
  },

  /**
    Initialize Ember.State object
    Sets childStates to Ember.NativeArray
    Sets eventTransitions to empty object unless already defined.
    Loops over properties of this state and ensures that any property that
    is an instance of Ember.State is moved to `states` hash.

    @method init
  */
  init: function() {
    var states = get(this, 'states');
    set(this, 'childStates', Ember.A());
    set(this, 'eventTransitions', get(this, 'eventTransitions') || {});

    var name, value, transitionTarget;

    // As a convenience, loop over the properties
    // of this state and look for any that are other
    // Ember.State instances or classes, and move them
    // to the `states` hash. This avoids having to
    // create an explicit separate hash.

    if (!states) {
      states = {};

      for (name in this) {
        if (name === "constructor") { continue; }

        if (value = this[name]) {
          if (transitionTarget = value.transitionTarget) {
            this.eventTransitions[name] = transitionTarget;
          }

          this.setupChild(states, name, value);
        }
      }

      set(this, 'states', states);
    } else {
      for (name in states) {
        this.setupChild(states, name, states[name]);
      }
    }

    // pathsCaches is a nested hash of the form:
    //   pathsCaches[stateManagerTypeGuid][path] == transitions_hash
    set(this, 'pathsCaches', {});
  },

  /**
    Sets a cached instance of the state. Ember.guidFor is used
    to find the guid of the associated state manager. If a cache can be found
    the state path is added to that cache, otherwise an empty JavaScript object
    is created. And the state path is appended to that instead.

    @method setPathsCache
    @param stateManager
    @param path
    @param transitions
  */
  setPathsCache: function(stateManager, path, transitions) {
    var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
      pathsCaches = get(this, 'pathsCaches'),
      pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};

    pathsCacheForManager[path] = transitions;
    pathsCaches[stateManagerTypeGuid] = pathsCacheForManager;
  },

  /**
    Returns a cached path for the state instance. Each state manager
    has a GUID and this is used to look up a cached path if it has already
    been created. If a cached path is not found an empty JavaScript object
    is returned instead.

    @method getPathsCache
    @param stateManager
    @param path
  */
  getPathsCache: function(stateManager, path) {
    var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
      pathsCaches = get(this, 'pathsCaches'),
      pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};

    return pathsCacheForManager[path];
  },

  /**
    @private

    Create the child instance and ensure that it is an instance of Ember.State

    @method setupChild
    @param states
    @param name
    @param value
  */
  setupChild: function(states, name, value) {
    if (!value) { return false; }
    var instance;

    if (value instanceof Ember.State) {
      set(value, 'name', name);
      instance = value;
      instance.container = this.container;
    } else if (Ember.State.detect(value)) {
      instance = value.create({
        name: name,
        container: this.container
      });
    }

    if (instance instanceof Ember.State) {
      set(instance, 'parentState', this);
      get(this, 'childStates').pushObject(instance);
      states[name] = instance;
      return instance;
    }
  },

  /**
    @private

    @method lookupEventTransition
    @param name
  */
  lookupEventTransition: function(name) {
    var path, state = this;

    while(state && !path) {
      path = state.eventTransitions[name];
      state = state.get('parentState');
    }

    return path;
  },

  /**
    A Boolean value indicating whether the state is a leaf state
    in the state hierarchy. This is `false` if the state has child
    states; otherwise it is true.

    @property isLeaf
    @type Boolean
  */
  isLeaf: Ember.computed(function() {
    return !get(this, 'childStates').length;
  }),

  /**
    A boolean value indicating whether the state takes a context.
    By default we assume all states take contexts.

    @property hasContext
    @default true
  */
  hasContext: true,

  /**
    This is the default transition event.

    @event setup
    @param {Ember.StateManager} manager
    @param context
    @see Ember.StateManager#transitionEvent
  */
  setup: Ember.K,

  /**
    This event fires when the state is entered.

    @event enter
    @param {Ember.StateManager} manager
  */
  enter: Ember.K,

  /**
    This event fires when the state is exited.

    @event exit
    @param {Ember.StateManager} manager
  */
  exit: Ember.K
});

Ember.State.reopenClass({

  /**
    Creates an action function for transitioning to the named state while
    preserving context.

    The following example StateManagers are equivalent:

    ```javascript
    aManager = Ember.StateManager.create({
      stateOne: Ember.State.create({
        changeToStateTwo: Ember.State.transitionTo('stateTwo')
      }),
      stateTwo: Ember.State.create({})
    })

    bManager = Ember.StateManager.create({
      stateOne: Ember.State.create({
        changeToStateTwo: function(manager, context) {
          manager.transitionTo('stateTwo', context)
        }
      }),
      stateTwo: Ember.State.create({})
    })
    ```

    @method transitionTo
    @static
    @param {String} target
  */

  transitionTo: function(target) {

    var transitionFunction = function(stateManager, contextOrEvent) {
      var contexts = [],
          Event = Ember.$ && Ember.$.Event;

      if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
        if (contextOrEvent.hasOwnProperty('contexts')) {
          contexts = contextOrEvent.contexts.slice();
        }
      }
      else {
        contexts = [].slice.call(arguments, 1);
      }

      contexts.unshift(target);
      stateManager.transitionTo.apply(stateManager, contexts);
    };

    transitionFunction.transitionTarget = target;

    return transitionFunction;
  }

});
<|endoftext|>