<commit_before>var placeholder = "Search, drag and drop video, or paste its URL...";

var playImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-play-4x.png";
var removeImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/x-4x.png";

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = 0;
var videoIteration = 0;

var videoPaused;
var stayPaused;
var backRestart;

var timer;

function Timer(callback, delay) {
  var timerId, start, remaining = delay;

  this.pause = function() {
      window.clearTimeout(timerId);
      remaining -= new Date() - start;
  };

  this.resume = function() {
      start = new Date();
      window.clearTimeout(timerId);
      timerId = window.setTimeout(callback, remaining);
  };

  this.resume();
}

function msConversion(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}

function highlight(i) {
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

function addVideoToList(name, time) {
  name = decodeURIComponent(name);
  $("#videosTable").append("
" + name + "<button class=\"tableButton removeButton\" onclick=\"actionRemoveVideo(this);\"></button>" +
  "<button class=\"tableButton playButton\" onclick=\"actionPlayVideo(this);\"></button>	" + time + "
");
}

function playVideo() {
  highlight(videoIteration);
  document.title = "Streamly - " + decodeURIComponent(videos[videoIteration]["name"]);
  var embedUrl = videos[videoIteration]["url"];

  var autoplay = "";
  if (!stayPaused) {
    autoplay = "?autoplay=1";
  }

  if (embedUrl.search(/file:\/\//i) == -1) {
    embedUrl = "https://www.youtube.com/embed/" + videos[videoIteration]["url"] + autoplay;
  }
  $("#youtube").attr("src", embedUrl);

  backRestart = false;
  window.setTimeout(function() {
    backRestart = true;
  }, 3000);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  timer = new Timer(function() {
    if (videoIteration < videoCounter) {
      loopVideo();
    }
    else {
      timer.pause();
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, videos[videoIteration]["time"] + 2000);
  if (stayPaused) {
    timer.pause();
  }
}

function pauseVideo() {
  if (!videoPaused) {
    timer.pause();
    videoPaused = true;
  }
  else {
    timer.resume();
    videoPaused = false;
    stayPaused = false;
  }
  $("#pauseOverlay").css("display", "none");
  setTimeout(function(){
    $("#pauseOverlay").css("display", "block");
    $("#youtube").blur();
  }, 500);
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;

    if (videoPaused) {
      stayPaused = true;
    }
    loopVideo();
  }
}

function backVideo() {
  if (!backRestart) {
    if (videoIteration - 2 > -1) {
      videoIteration = videoIteration - 2;
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;

      if (videoPaused) {
        stayPaused = true;
      }
      loopVideo();
    }
  }
  else {
    videoIteration = videoIteration - 1;
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 1) {
    var playlist = JSON.stringify(videos);
    playlist = window.btoa(playlist);
    playlist = encodeURIComponent(playlist);
    window.location.hash = playlist;
  }
  else {
    window.location.hash = "";
  }
}

function getPlaylist() {
  if (window.location.hash.substr(1) !== "") {
    var playlist = window.location.hash.substr(1);
    playlist = decodeURIComponent(playlist);
    playlist = window.atob(playlist);
    playlist = JSON.parse(playlist);
    videos = playlist;

    if (videos[0] != undefined) {
      $("#playlistNameBox").val(decodeURIComponent(videos[0]));
    }

    for (i = 1; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"]);
      addVideoToList(videos[videoCounter]["name"], printTime);
    }
    loopVideo();
  }
}

function getVideoData() {
  $.ajax({
    url: videoUrl,
    type: 'GET',
    success: function(res) {
      var data = $(res.responseText);
      try {
        videoName = data.find("span#eow-title");
        videoName = videoName[0].textContent;
        videoName = $("
").html(videoName).text();
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      videoName = encodeURIComponent(videoName).replace(/%20/g, " ");
      try {
        videoTime = null;
        for (iteration in data) {
          var str = data[iteration].innerHTML;
          if (videoTime == null && typeof str != "undefined") {
            videoTime = str.match(/,"length_seconds":"\d+",/g);
          }
        }
        videoTime = videoTime[0];
        videoTime = videoTime.replace(/,"length_seconds":"/g, "").replace(/",/g, "");
        videoTime = +videoTime * 1000;
      } catch(err) {
        videoTime = prompt("Please enter the length of the video", "3:00");
        videoTime = videoTime.split(":");
        videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
        videoTime = videoTime * 1000;
      }
    },
    complete: function(jqXHR, textStatus) {
      $("#inputBox").val("").attr("placeholder", placeholder);
      addVideo();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      videoName = prompt("Please enter the name of the video", "");

      videoTime = prompt("Please enter the length of the video", "3:00");
      videoTime = videoTime.split(":");
      videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
      videoTime = videoTime * 1000;
    }
  });
}

function addVideo() {
  videoCounter++;
  var video = {};
  video["name"] = videoName;
  video["time"] = videoTime;
  video["url"] = videoUrl.replace(/^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=/i, "");
  videos[videoCounter] = video;

  var printTime = msConversion(videos[videoCounter]["time"]);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 1 || timer == 0) {
    loopVideo();
  }
}

function actionPlayVideo(element) {
  var index = $(".playButton").index(element);
  videoIteration = index;
  if (timer != 0) {
    timer.pause();
  }
  timer = 0;
  loopVideo();
}

function actionRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function urlValidate(url) {
  var isValidYouTube = /^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=.+$/i;
  var isValidFile = /^file:\/\/.+$/i;

  url = url.trim();
  url = url.replace(/&list=.+/g, "");

  if (url.search(isValidYouTube) > -1 || url.search(isValidFile) > -1) {
    return url;
  }
  else {
    return false;
  }
}

function input(type) {
  var inputBox = $("#inputBox").val();
  var playlistNameBox = $("#playlistNameBox").val();
  switch (type) {
    case 0:
      if (inputBox != "") {
        window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
      }
      break;
    case 1:
      if (inputBox != "") {
        inputBox = urlValidate(inputBox);
        if (inputBox) {
          videoUrl = inputBox;
          $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
          getVideoData();
        }
        else {
          alert("That video's URL seems broken\n\nTry copying it again, or drag and drop the video directly");
        }
      }
      break;
    case 2:
      if (playlistNameBox != "") {
        videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
        setPlaylist();
      }
      else {
        videos[0] = undefined;
      }
      break;
  }
}

document.addEventListener("drop", function(event) {
  event.preventDefault();
  var data = event.dataTransfer.getData("URL");

  $("#inputBox").val(data);
  input(1);
});

document.addEventListener("dragover", function(event) {
  event.preventDefault();
});
<commit_msg>just cleaning up the code<commit_after>var placeholder = "Search, drag and drop video, or paste its URL...";

var playImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-play-4x.png";
var removeImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/x-4x.png";

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = 0;
var videoIteration = 0;

var videoPaused;
var stayPaused;
var backRestart;

var timer;

function Timer(callback, delay) {
  var timerId, start, remaining = delay;

  this.pause = function() {
      window.clearTimeout(timerId);
      remaining -= new Date() - start;
  };

  this.resume = function() {
      start = new Date();
      window.clearTimeout(timerId);
      timerId = window.setTimeout(callback, remaining);
  };

  this.resume();
}

function msConversion(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}

function highlight(i) {
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

function addVideoToList(name, time) {
  name = decodeURIComponent(name);
  $("#videosTable").append("
" + name + "<button class=\"tableButton removeButton\" onclick=\"actionRemoveVideo(this);\"></button>" +
  "<button class=\"tableButton playButton\" onclick=\"actionPlayVideo(this);\"></button>	" + time + "
");
}

function playVideo() {
  highlight(videoIteration);
  document.title = "Streamly - " + decodeURIComponent(videos[videoIteration]["name"]);
  var embedUrl = videos[videoIteration]["url"];

  var autoplay = "";
  if (!stayPaused) {
    autoplay = "?autoplay=1";
  }

  if (embedUrl.search(/file:\/\//i) == -1) {
    embedUrl = "https://www.youtube.com/embed/" + videos[videoIteration]["url"] + autoplay;
  }
  $("#youtube").attr("src", embedUrl);

  backRestart = false;
  window.setTimeout(function() {
    backRestart = true;
  }, 3000);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  timer = new Timer(function() {
    if (videoIteration < videoCounter) {
      loopVideo();
    }
    else {
      timer.pause();
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, videos[videoIteration]["time"] + 2000);
  if (stayPaused) {
    timer.pause();
  }
}

function pauseVideo() {
  if (!videoPaused) {
    timer.pause();
    videoPaused = true;
  }
  else {
    timer.resume();
    videoPaused = false;
    stayPaused = false;
  }
  $("#pauseOverlay").css("display", "none");
  setTimeout(function(){
    $("#pauseOverlay").css("display", "block");
    $("#youtube").blur();
  }, 500);
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;

    if (videoPaused) {
      stayPaused = true;
    }
    loopVideo();
  }
}

function backVideo() {
  if (!backRestart) {
    if (videoIteration - 2 > -1) {
      videoIteration = videoIteration - 2;
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;

      if (videoPaused) {
        stayPaused = true;
      }
      loopVideo();
    }
  }
  else {
    videoIteration = videoIteration - 1;
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 1) {
    var playlist = JSON.stringify(videos);
    playlist = window.btoa(playlist);
    playlist = encodeURIComponent(playlist);
    window.location.hash = playlist;
  }
  else {
    window.location.hash = "";
  }
}

function getPlaylist() {
  if (window.location.hash.substr(1) !== "") {
    var playlist = window.location.hash.substr(1);
    playlist = decodeURIComponent(playlist);
    playlist = window.atob(playlist);
    playlist = JSON.parse(playlist);
    videos = playlist;

    if (videos[0] !== undefined) {
      $("#playlistNameBox").val(decodeURIComponent(videos[0]));
    }

    for (i = 1; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"]);
      addVideoToList(videos[videoCounter]["name"], printTime);
    }
    loopVideo();
  }
}

function getVideoData() {
  $.ajax({
    url: videoUrl,
    type: 'GET',
    success: function(res) {
      var data = $(res.responseText);
      try {
        videoName = data.find("span#eow-title");
        videoName = videoName[0].textContent;
        videoName = $("
").html(videoName).text();
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      videoName = encodeURIComponent(videoName).replace(/%20/g, " ");
      try {
        videoTime = null;
        for (iteration in data) {
          var str = data[iteration].innerHTML;
          if (videoTime == null && typeof str !== undefined) {
            videoTime = str.match(/,"length_seconds":"\d+",/g);
          }
        }
        videoTime = videoTime[0];
        videoTime = videoTime.replace(/,"length_seconds":"/g, "").replace(/",/g, "");
        videoTime = +videoTime * 1000;
      } catch(err) {
        videoTime = prompt("Please enter the length of the video", "3:00");
        videoTime = videoTime.split(":");
        videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
        videoTime = videoTime * 1000;
      }
    },
    complete: function(jqXHR, textStatus) {
      $("#inputBox").val("").attr("placeholder", placeholder);
      addVideo();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      videoName = prompt("Please enter the name of the video", "");

      videoTime = prompt("Please enter the length of the video", "3:00");
      videoTime = videoTime.split(":");
      videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
      videoTime = videoTime * 1000;
    }
  });
}

function addVideo() {
  videoCounter++;
  var video = {};
  video["name"] = videoName;
  video["time"] = videoTime;
  video["url"] = videoUrl.replace(/^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=/i, "");
  videos[videoCounter] = video;

  var printTime = msConversion(videos[videoCounter]["time"]);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 1 || timer == 0) {
    loopVideo();
  }
}

function actionPlayVideo(element) {
  var index = $(".playButton").index(element);
  videoIteration = index;
  if (timer != 0) {
    timer.pause();
  }
  timer = 0;
  loopVideo();
}

function actionRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function urlValidate(url) {
  var isValidYouTube = /^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=.+$/i;
  var isValidFile = /^file:\/\/.+$/i;

  url = url.trim();
  url = url.replace(/&list=.+/g, "");

  if (url.search(isValidYouTube) > -1 || url.search(isValidFile) > -1) {
    return url;
  }
  else {
    return false;
  }
}

function input(type) {
  var inputBox = $("#inputBox").val();
  var playlistNameBox = $("#playlistNameBox").val();
  switch (type) {
    case 0:
      if (inputBox != "") {
        window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
      }
      break;
    case 1:
      if (inputBox != "") {
        inputBox = urlValidate(inputBox);
        if (inputBox) {
          videoUrl = inputBox;
          $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
          getVideoData();
        }
        else {
          alert("That video's URL seems broken\n\nTry copying it again, or drag and drop the video directly");
        }
      }
      break;
    case 2:
      if (playlistNameBox != "") {
        videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
        setPlaylist();
      }
      else {
        videos[0] = undefined;
      }
      break;
  }
}

document.addEventListener("drop", function(event) {
  event.preventDefault();
  var data = event.dataTransfer.getData("URL");

  $("#inputBox").val(data);
  input(1);
});

document.addEventListener("dragover", function(event) {
  event.preventDefault();
});
<|endoftext|>


<commit_before>$(document).ready(function() {
    /**
     * TinyMCE instance from the top level window object
     * @type object
     */
    var tinymce = top.tinymce;

    /**
     * Window modal object created by tinymce object
     * @type {Object}
     */
    var mcemodal = tinymce.activeEditor.windowManager.getWindows()[0];

    /**
     * @type {Object}
     */
    var options = tinymce.activeEditor.windowManager.getParams();

    /**
     * @type object|null
     */
    var previousCall = null;

    /**
     * Render result lists into thumbnail container
     * @param {object} images Collection retreived from the API
     */
    function render (images) {
        var regex = /\{\{[a-z]+\}\}/gi;
        var rowTemplate = '
{{thumbnails}}
';
        var container       = $('#thumbnail-container');
        var temporaryHtml   = '';
        var temporaryThumb  = '';

        for(var i = 0; i < images.length; i++){
            // Grab the item html
            var item = renderItem(images[i]);

            // Grab the route
            images[i].source = Routing.generate(
                'integrated_storage_file',
                {
                    id: images[i].id,
                    ext: images[i].extension
                },
                true
            );

            // Parse values
            var match = [];
            while (null != (match = regex.exec(item))) {
                item = item.replace(
                    match[0],
                    images[i][match[0].substr(2, (match[0].length-4))]
                );
            }

            // Add it
            temporaryThumb += item;

            if(i % 4 == 3 || i == images.length - 1){
                temporaryHtml  += rowTemplate.replace(/\{\{thumbnails\}\}/g, temporaryThumb);
                temporaryThumb  = '';
            }
        }

        if(images.length == 0){
            temporaryHtml = '
No content found.
';
        }

        container.html(temporaryHtml);
    }

    /**
     * @param {object} item
     * @returns {string}
     */
    function renderItem(item)
    {
        var html = '

';

        if (item.mimeType.match('^video\/(.*)$')) {
            html += '<video poster="{{poster}}" controls class="img-responsive click-insert"><source src="{{source}}" type="{{mimeType}}"></video>';
        } else if (item.mimeType.match('^image\/(.*)$')) {
            html += '';
        } else {
            html += '
Not supported content type
'
        }

        html += '

';

        return html;
    }

    /**
     * Render pagination part of the image browser
     * @param {object} page Pagination data retrieved from the API
     */
    function renderPagination(page){
        var paginationTemplate =
            ''+
            '
'+
            '{{page-prev}}'+
            '{{page-num}}'+
            '{{page-next}}'+
            '
'+
            '';

        var container = $('#pagination-container');
        var thumbnailContainer = $('#thumbnail-container');
        var temporaryHtml = '';
        var pageNum = '';

        /** hide the pagination if only one page found and return immediately */
        if(page.pageCount == 1) {
            container.html('');
            thumbnailContainer.css('height', '520px');
            return;
        } else {
            thumbnailContainer.removeAttr('style');
        }

        /** process the template to render pagination link */
        for(
            var i = page.page - 2 - (page.pageCount - page.page < 2 ? 2 - (page.pageCount - page.page) : 0);
            i <= page.page + 2 + (page.page <= 2 ? 3 - page.page : 0);
            i++
        ) {
            if(typeof page.pages[i] != 'undefined'){
                pageNum +=  '
'+
                    ''+i+''+
                    '
';
            }
        }

        temporaryHtml = paginationTemplate.replace(
            '{{page-prev}}',
            '
'+
            ''+
            '«'+
            ''+
            '
'
        ).replace(
            '{{page-next}}',
            '
'+
            ''+
            '»'+
            ''+
            '
'
        ).replace(
            '{{page-num}}', pageNum
        );

        container.html(temporaryHtml);
    }

    /**
     * Refresh the content
     */
    function refresh () {
        $('#thumbnail-container').loader('show');

        var params = {
            "contenttypes[]": $('#type-search').val(),
            "q": $('#txt-search').val(),
            "_format": "json"
        };

        if(previousCall !== null){
            previousCall.abort();
            previousCall = null;
        }

        previousCall =
            $.get(Routing.generate('integrated_content_content_index', params), function(data) {
                render(data.items);
                renderPagination(data.pagination);
            }, 'json')
                .error(function(xhr, status){
                    if(status !== 'abort'){
                        $('#thumbnail-container').html('
Error occured while loading content
');
                    }
                }).done(function () {
                $('#thumbnail-container').loader('hide');
            })
        ;
    };

    /**
     * Type ahead search handler
     */
    $(document).on('keyup', '#txt-search', function () {
        refresh();
    });

    /**
     * Content type switcher
     */
    $(document).on('change', '#type-search', function () {
        refresh();
    });

    /**
     * Pagination link click handler
     */
    $('#pagination-container').on('click', 'a', function(e){
        e.preventDefault();
        $('#thumbnail-container').loader('show');

        var href = $(this).attr('href');

        if(href !== '#'){
            $.get(href, function(data){
                render(data.items);
                renderPagination(data.pagination);
            }, 'json')
                .error(function(){
                    $('#thumbnail-container').html('
Error occured while loading content
')
                })
                .done(function() {
                    $('#thumbnail-container').loader('hide');
                });
        }
    });

    /**
     * Image thumbnail click handler
     * insert the image into editor and close the window
     */
    $('#thumbnail-container').on('click', '.click-insert', function(e){
        e.preventDefault();

        var item = $(this);
        item.removeClass('click-insert');

        // Inject the image
        tinymce.activeEditor.insertContent(item[0].outerHTML);
        mcemodal.close();
    });

    /**
     * Here the plugin begins
     */
    $.get(Routing.generate('integrated_content_content_media_types', {'filter': options['mode']}), function (contentTypes) {
        var buttonHtml = '';

        if (contentTypes.length == 1) {
            buttonHtml = 'Upload new '+ contentTypes[0].name +'';
        } else if (contentTypes.length > 1) {
            buttonHtml =
                '<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' +
                'Upload new image </button>' +
                '
';

            for (var i in contentTypes) {
                buttonHtml += '
'+ contentTypes[i].name +'
';
            }

            buttonHtml += '
';
        }

        $('#button_wrap').html(buttonHtml);

        var searchHtml = '';
        for (var i in contentTypes) {
            searchHtml += '<option value="'+ contentTypes[i].id +'">'+ contentTypes[i].name +'</option>';
        }

        $('#type-search').html(searchHtml);
        refresh();

        $('.btn-content-add').click(function(e) {
            e.preventDefault();

            tinymce.activeEditor.windowManager.open({
                title: 'Add a new '+ $(this).text(),
                url: $(this).attr('href') + '&_format=iframe.html',
                width: 800,
                height: 600
            }).on('close', function () {
                refresh();
            });
        });
    }).error(function() {
        $('#add_image_wrapper').html('
Failed to retrieve content types.
');
    }).done(function (){
        $('#add_image_wrapper').css('opacity',1);
    });
});
<commit_msg>Added data id.<commit_after>$(document).ready(function() {
    /**
     * TinyMCE instance from the top level window object
     * @type object
     */
    var tinymce = top.tinymce;

    /**
     * Window modal object created by tinymce object
     * @type {Object}
     */
    var mcemodal = tinymce.activeEditor.windowManager.getWindows()[0];

    /**
     * @type {Object}
     */
    var options = tinymce.activeEditor.windowManager.getParams();

    /**
     * @type object|null
     */
    var previousCall = null;

    /**
     * Render result lists into thumbnail container
     * @param {object} images Collection retreived from the API
     */
    function render (images) {
        var regex = /\{\{[a-z]+\}\}/gi;
        var rowTemplate = '
{{thumbnails}}
';
        var container       = $('#thumbnail-container');
        var temporaryHtml   = '';
        var temporaryThumb  = '';

        for(var i = 0; i < images.length; i++){
            // Grab the item html
            var item = renderItem(images[i]);

            // Grab the route
            images[i].source = Routing.generate(
                'integrated_storage_file',
                {
                    id: images[i].id,
                    ext: images[i].extension
                },
                true
            );

            // Parse values
            var match = [];
            while (null != (match = regex.exec(item))) {
                item = item.replace(
                    match[0],
                    images[i][match[0].substr(2, (match[0].length-4))]
                );
            }

            // Add it
            temporaryThumb += item;

            if(i % 4 == 3 || i == images.length - 1){
                temporaryHtml  += rowTemplate.replace(/\{\{thumbnails\}\}/g, temporaryThumb);
                temporaryThumb  = '';
            }
        }

        if(images.length == 0){
            temporaryHtml = '
No content found.
';
        }

        container.html(temporaryHtml);
    }

    /**
     * @param {object} item
     * @returns {string}
     */
    function renderItem(item)
    {
        var html = '

';

        if (item.mimeType.match('^video\/(.*)$')) {
            html += '<video poster="{{poster}}" controls class="img-responsive click-insert" data-integrated-id="{{id}}"><source src="{{source}}" type="{{mimeType}}"></video>';
        } else if (item.mimeType.match('^image\/(.*)$')) {
            html += '';
        } else {
            html += '
Not supported content type
'
        }

        html += '

';

        return html;
    }

    /**
     * Render pagination part of the image browser
     * @param {object} page Pagination data retrieved from the API
     */
    function renderPagination(page){
        var paginationTemplate =
            ''+
            '
'+
            '{{page-prev}}'+
            '{{page-num}}'+
            '{{page-next}}'+
            '
'+
            '';

        var container = $('#pagination-container');
        var thumbnailContainer = $('#thumbnail-container');
        var temporaryHtml = '';
        var pageNum = '';

        /** hide the pagination if only one page found and return immediately */
        if(page.pageCount == 1) {
            container.html('');
            thumbnailContainer.css('height', '520px');
            return;
        } else {
            thumbnailContainer.removeAttr('style');
        }

        /** process the template to render pagination link */
        for(
            var i = page.page - 2 - (page.pageCount - page.page < 2 ? 2 - (page.pageCount - page.page) : 0);
            i <= page.page + 2 + (page.page <= 2 ? 3 - page.page : 0);
            i++
        ) {
            if(typeof page.pages[i] != 'undefined'){
                pageNum +=  '
'+
                    ''+i+''+
                    '
';
            }
        }

        temporaryHtml = paginationTemplate.replace(
            '{{page-prev}}',
            '
'+
            ''+
            '«'+
            ''+
            '
'
        ).replace(
            '{{page-next}}',
            '
'+
            ''+
            '»'+
            ''+
            '
'
        ).replace(
            '{{page-num}}', pageNum
        );

        container.html(temporaryHtml);
    }

    /**
     * Refresh the content
     */
    function refresh () {
        $('#thumbnail-container').loader('show');

        var params = {
            "contenttypes[]": $('#type-search').val(),
            "q": $('#txt-search').val(),
            "_format": "json"
        };

        if(previousCall !== null){
            previousCall.abort();
            previousCall = null;
        }

        previousCall =
            $.get(Routing.generate('integrated_content_content_index', params), function(data) {
                render(data.items);
                renderPagination(data.pagination);
            }, 'json')
                .error(function(xhr, status){
                    if(status !== 'abort'){
                        $('#thumbnail-container').html('
Error occured while loading content
');
                    }
                }).done(function () {
                $('#thumbnail-container').loader('hide');
            })
        ;
    };

    /**
     * Type ahead search handler
     */
    $(document).on('keyup', '#txt-search', function () {
        refresh();
    });

    /**
     * Content type switcher
     */
    $(document).on('change', '#type-search', function () {
        refresh();
    });

    /**
     * Pagination link click handler
     */
    $('#pagination-container').on('click', 'a', function(e){
        e.preventDefault();
        $('#thumbnail-container').loader('show');

        var href = $(this).attr('href');

        if(href !== '#'){
            $.get(href, function(data){
                render(data.items);
                renderPagination(data.pagination);
            }, 'json')
                .error(function(){
                    $('#thumbnail-container').html('
Error occured while loading content
')
                })
                .done(function() {
                    $('#thumbnail-container').loader('hide');
                });
        }
    });

    /**
     * Image thumbnail click handler
     * insert the image into editor and close the window
     */
    $('#thumbnail-container').on('click', '.click-insert', function(e){
        e.preventDefault();

        var item = $(this);
        item.removeClass('click-insert');

        // Inject the image
        tinymce.activeEditor.insertContent(item[0].outerHTML);
        mcemodal.close();
    });

    /**
     * Here the plugin begins
     */
    $.get(Routing.generate('integrated_content_content_media_types', {'filter': options['mode']}), function (contentTypes) {
        var buttonHtml = '';

        if (contentTypes.length == 1) {
            buttonHtml = 'Upload new '+ contentTypes[0].name +'';
        } else if (contentTypes.length > 1) {
            buttonHtml =
                '<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' +
                'Upload new image </button>' +
                '
';

            for (var i in contentTypes) {
                buttonHtml += '
'+ contentTypes[i].name +'
';
            }

            buttonHtml += '
';
        }

        $('#button_wrap').html(buttonHtml);

        var searchHtml = '';
        for (var i in contentTypes) {
            searchHtml += '<option value="'+ contentTypes[i].id +'">'+ contentTypes[i].name +'</option>';
        }

        $('#type-search').html(searchHtml);
        refresh();

        $('.btn-content-add').click(function(e) {
            e.preventDefault();

            tinymce.activeEditor.windowManager.open({
                title: 'Add a new '+ $(this).text(),
                url: $(this).attr('href') + '&_format=iframe.html',
                width: 800,
                height: 600
            }).on('close', function () {
                refresh();
            });
        });
    }).error(function() {
        $('#add_image_wrapper').html('
Failed to retrieve content types.
');
    }).done(function (){
        $('#add_image_wrapper').css('opacity',1);
    });
});
<|endoftext|>


<commit_before>//test.js

var fin = require("./finQuery");
//NASDAQ%3AAAPL
var appl = fin.query("NASDAQ%3AAAPL") // ,function(err,data){
/*
	if(err)
	{
		console.log("test.js callback error: " + err);
	}
	else
	{
		console.log("\n---------------------------------------\ncallback in TEST.JS")

		Object.keys(data).forEach(function(element, key, _array) {
			console.log("" + element + "=" + data[element]);
		});
	}

});
*/
console.log("the finish test.js file");
<commit_msg>updated error handling different scenarios<commit_after>//test.js

var fin = require("./finQuery");
//NASDAQ%3AAAPL
console.log("call 1st fin");
var appl = fin.query("NASDAQ%3AAAPL","all" ,function(err,data){
	if(err)
	{
		console.log("test.js callback error: " + err);
	}
	else
	{
		console.log("\n---------------------------------------\ncallback in TEST.JS")

		Object.keys(data).forEach(function(element, key, _array) {
			console.log("" + element + "=" + data[element]);
		});
	}

});
console.log("call 2nd fin");
var appl = fin.query("NYSE%3AF","price" ,function(err,data){
	if(err)
	{
		console.log("test.js callback error: " + err);
	}
	else
	{
		console.log("\n---------------------------------------\ncallback in TEST.JS")

		Object.keys(data).forEach(function(element, key, _array) {
			console.log("" + element + "=" + data[element]);
		});
	}

});
console.log("call 3rd fin");
var appl = fin.query("NxxAF","price" ,function(err,data){
	if(err)
	{
		console.log("test.js callback error: " + err);
	}
	else
	{
		console.log("\n---------------------------------------\ncallback in TEST.JS")

		Object.keys(data).forEach(function(element, key, _array) {
			console.log("" + element + "=" + data[element]);
		});
	}

});

console.log("the finish test.js file");
<|endoftext|>


<commit_before>var request = require('request');
var crypto = require('crypto');
var qs = require('querystring');
var http = require('http');
var https = require('https');

var SIGNATURE_METHOD  = 'HmacSHA256';
var SIGNATURE_VERSION = '2';
var SIGNATURE_TTL = 150*1000;
var VERSION = '2012-11-05';
var DEFAULT_REGION = 'us-east-1';

var text = function(xml, tag) {
	var i = xml.indexOf('<'+tag+'>');
	if (i === -1) return null;
	i += tag.length+2;

	return xml.substring(i, xml.indexOf('</', i));
};

var unscape = function(xml) {
	return xml.replace(/"/g, '"').replace(/$apos;/g, "'").replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
};

var range = function(num) {
	return Array(num).join(',').split(',');
};

module.exports = function(options) {
	options = options || {};

	options.access = options.access || process.env.SQS_ACCESS_KEY;
	options.secret = options.secret || process.env.SQS_SECRET_KEY;
	options.region = options.region || process.env.SQS_REGION || DEFAULT_REGION;

	if (!options.access || !options.secret) throw new Error('options.access and options.secret are required');

	var queues = {};
	var closed = false;
	var proto = options.https ? 'https://' : 'http://';
	var host = 'sqs.'+options.region+'.amazonaws.com';
	var namespace = options.namespace ? options.namespace+'-' : '';

	namespace = namespace.replace(/[^a-zA-Z0-9]/g, '-').replace(/\-+/g, '-');

	var queryURL = function(action, path, params) {
		params = params || {};

		params.Action = action;
		params.AWSAccessKeyId = options.access;
		params.SignatureMethod = SIGNATURE_METHOD;
		params.SignatureVersion = SIGNATURE_VERSION;
		params.Expires = new Date(Date.now()+SIGNATURE_TTL).toISOString();
		params.Version = VERSION;

		var stringToSign = 'GET\n'+host+'\n'+path+'\n'+Object.keys(params).sort().map(function(name) {
			return name+'='+encodeURIComponent(params[name]).replace(/[!'()]/g, escape).replace(/\*/g, '%2A');
		}).join('&');

		params.Signature = crypto.createHmac('sha256',options.secret).update(stringToSign).digest('base64');

		return proto+host+path+'?'+qs.stringify(params);
	};

	var retry = function(req, url, callback) {
		var retries = 0;
		var action = function() {
			req(url, {timeout:10000}, function(err, res) {
				if (!err && res.statusCode >= 500) err = new Error('invalid status-code: '+res.statusCode);
				if (callback) return callback(err);
				if (!err) return;
				retries++;
				if (retries > 15) return that.emit('error', new Error('could not send '+url));
				setTimeout(action, retries*1000);
			});
		};

		action();
	};

	var queueURL = function(name, callback) {
		if (queues[name]) return queues[name](callback);

		var stack = [callback];

		queues[name] = function(callback) {
			stack.push(callback);
		};

		var onresult = function(err, url) {
			if (err) return that.emit('error', err);

			queues[name] = function(callback) {
				callback(url);
			};

			while (stack.length) {
				stack.shift()(url);
			}
		};

		request(queryURL('CreateQueue', '/', {QueueName:name}), function(err) {
			if (err) return onresult(err);
			request(queryURL('GetQueueUrl', '/', {QueueName:name}), function(err, res) {
				if (err || res.statusCode !== 200) return onresult(err || new Error('invalid status code from GetQueueUrl: '+res.statusCode));
				onresult(null, '/'+text(res.body, 'QueueUrl').split('/').slice(3).join('/'));
			});
		});
	};

	var that = new process.EventEmitter();

	that.push = function(name, message, callback) {
		name = namespace+name;

		queueURL(name, function(url) {
			retry(request, queryURL('SendMessage', url, {MessageBody:JSON.stringify(message)}), callback);
		});
	};

	that.delete = that.del = function(name, callback) {
		name = namespace+name;

		queueURL(name, function(url) {
			retry(request, queryURL('DeleteQueue', url), callback);
		});
	};

	that.pull = function(name, workers, onmessage) {
		if (typeof workers === 'function') return that.pull(name, options.workers || 1, workers);

		name = namespace+name;

		var agent =  options.https ? new https.Agent({maxSockets:workers}) : new http.Agent({maxSockets:workers}); // long poll should use its own agent
		var req = request.defaults({agent:agent});

		range(workers).forEach(function() {
			var next = function() {
				if (closed) return;

				queueURL(name, function(url) {
					req(queryURL('ReceiveMessage', url, {WaitTimeSeconds:20}), function(err, res) {
						if (err || res.statusCode !== 200) return setTimeout(next, 2000);

						var body = text(res.body, 'Body');

						if (!body) return next();

						var receipt = text(res.body, 'ReceiptHandle');

						try {
							body = JSON.parse(unscape(body));
						} catch (err) {
							return next();
						}

						// Callback takes an arbitrary error and a `stop` attribute to stop
						// polling for messages
						onmessage(body, function(err, ctx) {
							if (err) return next();
							retry(request, queryURL('DeleteMessage', url, {ReceiptHandle:receipt}));
							if (ctx && ctx.stop === true) return;
							next();
						});

					});
				});
			};

			next();
		});
	};

	that.close = function() {
		closed = true;
	};

	return that;
};
<commit_msg>Make it possible to poll every X seconds, instead of indefinitely<commit_after>var request = require('request');
var crypto = require('crypto');
var qs = require('querystring');
var http = require('http');
var https = require('https');

var SIGNATURE_METHOD  = 'HmacSHA256';
var SIGNATURE_VERSION = '2';
var SIGNATURE_TTL = 150*1000;
var VERSION = '2012-11-05';
var DEFAULT_REGION = 'us-east-1';

var text = function(xml, tag) {
	var i = xml.indexOf('<'+tag+'>');
	if (i === -1) return null;
	i += tag.length+2;

	return xml.substring(i, xml.indexOf('</', i));
};

var unscape = function(xml) {
	return xml.replace(/"/g, '"').replace(/$apos;/g, "'").replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
};

var range = function(num) {
	return Array(num).join(',').split(',');
};

module.exports = function(options) {
	options = options || {};

	options.access = options.access || process.env.SQS_ACCESS_KEY;
	options.secret = options.secret || process.env.SQS_SECRET_KEY;
	options.region = options.region || process.env.SQS_REGION || DEFAULT_REGION;

	if (!options.access || !options.secret) throw new Error('options.access and options.secret are required');

	var queues = {};
	var closed = false;
	var proto = options.https ? 'https://' : 'http://';
	var host = 'sqs.'+options.region+'.amazonaws.com';
	var namespace = options.namespace ? options.namespace+'-' : '';

	namespace = namespace.replace(/[^a-zA-Z0-9]/g, '-').replace(/\-+/g, '-');

	var queryURL = function(action, path, params) {
		params = params || {};

		params.Action = action;
		params.AWSAccessKeyId = options.access;
		params.SignatureMethod = SIGNATURE_METHOD;
		params.SignatureVersion = SIGNATURE_VERSION;
		params.Expires = new Date(Date.now()+SIGNATURE_TTL).toISOString();
		params.Version = VERSION;

		var stringToSign = 'GET\n'+host+'\n'+path+'\n'+Object.keys(params).sort().map(function(name) {
			return name+'='+encodeURIComponent(params[name]).replace(/[!'()]/g, escape).replace(/\*/g, '%2A');
		}).join('&');

		params.Signature = crypto.createHmac('sha256',options.secret).update(stringToSign).digest('base64');

		return proto+host+path+'?'+qs.stringify(params);
	};

	var retry = function(req, url, callback) {
		var retries = 0;
		var action = function() {
			req(url, {timeout:10000}, function(err, res) {
				if (!err && res.statusCode >= 500) err = new Error('invalid status-code: '+res.statusCode);
				if (callback) return callback(err);
				if (!err) return;
				retries++;
				if (retries > 15) return that.emit('error', new Error('could not send '+url));
				setTimeout(action, retries*1000);
			});
		};

		action();
	};

	var queueURL = function(name, callback) {
		if (queues[name]) return queues[name](callback);

		var stack = [callback];

		queues[name] = function(callback) {
			stack.push(callback);
		};

		var onresult = function(err, url) {
			if (err) return that.emit('error', err);

			queues[name] = function(callback) {
				callback(url);
			};

			while (stack.length) {
				stack.shift()(url);
			}
		};

		request(queryURL('CreateQueue', '/', {QueueName:name}), function(err) {
			if (err) return onresult(err);
			request(queryURL('GetQueueUrl', '/', {QueueName:name}), function(err, res) {
				if (err || res.statusCode !== 200) return onresult(err || new Error('invalid status code from GetQueueUrl: '+res.statusCode));
				onresult(null, '/'+text(res.body, 'QueueUrl').split('/').slice(3).join('/'));
			});
		});
	};

	var that = new process.EventEmitter();

	that.push = function(name, message, callback) {
		name = namespace+name;

		queueURL(name, function(url) {
			retry(request, queryURL('SendMessage', url, {MessageBody:JSON.stringify(message)}), callback);
		});
	};

	that.delete = that.del = function(name, callback) {
		name = namespace+name;

		queueURL(name, function(url) {
			retry(request, queryURL('DeleteQueue', url), callback);
		});
	};

	var pullIntervalSeconds = options.pullIntervalSeconds || 2;

	that.pull = function(name, workers, onmessage) {
		if (typeof workers === 'function') return that.pull(name, options.workers || 1, workers);

		name = namespace+name;

		var agent =  options.https ? new https.Agent({maxSockets:workers}) : new http.Agent({maxSockets:workers}); // long poll should use its own agent
		var req = request.defaults({agent:agent});

		range(workers).forEach(function() {
			var next = function() {
				if (closed) return;

				queueURL(name, function(url) {
					req(queryURL('ReceiveMessage', url, {WaitTimeSeconds:20}), function(err, res) {
						if (err || res.statusCode !== 200) {
							return setTimeout(next, pullIntervalSeconds * 1000);
						}

						var body = text(res.body, 'Body');

						if (!body)
							return options.pullIntervalSeconds
								? setTimeout(next, pullIntervalSeconds * 1000)
								: next();

						var receipt = text(res.body, 'ReceiptHandle');

						try {
							body = JSON.parse(unscape(body));
						} catch (err) {
							return next();
						}

						// Callback takes an arbitrary error and a `stop` attribute to stop
						// polling for messages
						onmessage(body, function(err, ctx) {
							if (err) return next();
							retry(request, queryURL('DeleteMessage', url, {ReceiptHandle:receipt}));
							if (ctx && ctx.stop === true) return;
							next();
						});

					});
				});
			};

			next();
		});
	};

	that.close = function() {
		closed = true;
	};

	return that;
};
<|endoftext|>


<commit_before>
var App = function() {

	// create nodes
	var	win = $(window),
		body = $(document.body),
		container = $('

').appendTo(body),
		header = $('

').appendTo(container),
		main = $('

').appendTo(container),
		footer = $('

').appendTo(container),
		settingsKey = 'app-windows',
		ext = {};

	function init() {

		var mainMenu = new MainMenu(header);

		// create objects
		var windowManager = new WindowManager(main);

		ext.windowManager = windowManager;

		// combine nodes and objects
		win.on('resize', resize);
		win.on('orientationchange', resize);
		resize();

		var settings = getWindowSettings(),
			windowWidth = win.width();
		//console.log('settings',settings, settings.length);

		if (windowWidth < 768 && settings.windows.length >= 3) {
			settings.windows = settings.windows.slice(0,2);
		}
		if (windowWidth < 480 && settings.windows.length >= 2) {
			settings.windows = settings.windows.slice(0,1);
		}

		// create windows
		for (var i=0, il=settings.windows.length; i<il; i++) {
			var setting = settings.windows[i],
				windowClassName = setting.windowType;

			// try to find ClassName by the parameter
			if (!windowClassName) {
				var param = setting.type,
					filteredWindowTypes = sofia.windowTypes.filter(function(wt) {
						return wt.param == param;
					});

				if (filteredWindowTypes.length == 1) {
					windowClassName = filteredWindowTypes[0].className;
				}
			}

			//console.log('create window', setting, windowClassName);
			windowManager.add(windowClassName, setting.data);
		}

		// get first window
		var bibleWindows = settings.windows.filter(function(s) { return s.windowType == 'BibleWindow'; }),
			firstBibleWindow = bibleWindows.length > 0 ? bibleWindows[0] : null,
			firstFragmentid = firstBibleWindow != null && firstBibleWindow.data != null ? firstBibleWindow.data.fragmentid : null;

		if (firstFragmentid != null) {
			TextNavigation.firstState( firstFragmentid );
		}

		var settingsTimer = new Timer(storeSettings, 1000);

		windowManager.on('settingschange', function(e) {

			// title to show active window's position
			if (e.data && e.data.label && e.data.hasFocus) {
				document.title = e.data.labelLong;
			}

			settingsTimer.start();

		});

		var plugins = []
		ext.plugins = plugins;
		// run plugins
		for (var x in sofia.plugins) {
			plugin = new window[ sofia.plugins[x] ](this);
			plugins.push(plugin);

			if (plugin.on) {

				plugin.on('globalmessage', handleGlobalMessage);
			}
		}
	}

	function resize() {
		console.log('app resize');

		PlaceKeeper.storePlace();

		// get window size
		var width = win.width(),
			height = win.height(),

			// calculate size
			areaHeight = height - header.outerHeight() + footer.outerHeight(),
			areaWidth = width - parseInt(main.css('margin-left'), 10) - parseInt(main.css('margin-right'), 10);

		if (width < 410) {
			header.hide();
			areaHeight = height;
		} else {
			header.show();
		}

		// set height
		main.height(areaHeight);
		main.width(areaWidth);

		// pass new size down to area
		ext.windowManager.size(areaWidth, areaHeight);

		PlaceKeeper.restorePlace();
	}

	function getWindowSettings() {

		// (1) get default settings
		var settings = {
			windows: sofia.config.windows
		};

		// (2) replace defaults with user settings
		settings = AppSettings.getValue(settingsKey, settings);

		// (3) overwrite with QueryString when present
		var queryData = stringUtility.parseQuerystring();
		if (queryData["w1"]) {

			var tempSettings = [];

			for (var i=1; i<=4; i++) {
				var winTypeName = queryData["w" + i.toString()],
					winTypeInfo = sofia.windowTypes.filter(function(winType) { return winType.param == winTypeName; })[0],
					winTypeParamKeys = typeof winTypeInfo != 'undefined' ? Object.keys(winTypeInfo.paramKeys) : [],
					setting = {
						type: winTypeName,
						data: {}
					};

				if (typeof winTypeName != 'undefined') {
					// go though all querystring values, and anything that ends with '1' goes with this data
					for (var q in queryData) {
						var key = q.substring(0, q.length-1),
							number = q.substring(q.length-1),
							value = queryData[q];

						if (key != 'w' && number == i.toString()) {

							// convert short querystring key to longer one if needed
							var longParamKey = winTypeParamKeys.filter(function(lpk) {
								console.log(key, lpk, winTypeInfo.paramKeys[lpk]);
								return key == winTypeInfo.paramKeys[lpk] || key == lpk;
							})[0];

							setting.data[longParamKey] = value;
						}
					}

					tempSettings.push(setting);
				}
			}

			// overwrite settings
			if (tempSettings.length > 0) {
				settings.windows = tempSettings;
			}

		}
		return settings;
	}

	function storeSettings() {

			// get settings from al windows
		var windowSettings = ext.windowManager.getSettings(),
			// later we'll need these
			headerSettings = {},
			settings = {
				windows: windowSettings
			};

		//console.log('storeSettings', settings);

		// store
		AppSettings.setValue(settingsKey, settings );
	}

	function handleGlobalMessage(e) {
		// give to other windows
		var windows = ext.windowManager.getWindows();

		for (var i=0, il=windows.length; i<il; i++) {
			var w = windows[i];

			if (w.id != e.id) {
		 		// pass message down
		 		w.trigger('message', e);
			}
		}

		// plugins
		for (var i=0, il=ext.plugins.length; i<il; i++) {
			var p = sofia.app.plugins[i];

			if (p.trigger) {
				// pass message down
				p.trigger('message', e);
			}
		}

	}

	ext.init = init;
	ext.handleGlobalMessage = handleGlobalMessage;

	i18n.init({fallbackLng: 'en', resStore: sofia.resources});

	setTimeout(function() {

		var lang = i18n.lng(),
			langSelector = $('#config-language');

		langSelector.val( lang );

		if (lang != langSelector.val() ) {
			langSelector.val(  lang.split('-')[0] );
		}

	},50);

	return ext;
};
<commit_msg>use same width to trigger mobile template in CSS + JS<commit_after>
var App = function() {

	// create nodes
	var	win = $(window),
		body = $(document.body),
		container = $('

').appendTo(body),
		header = $('

').appendTo(container),
		main = $('

').appendTo(container),
		footer = $('

').appendTo(container),
		settingsKey = 'app-windows',
		ext = {};

	function init() {

		var mainMenu = new MainMenu(header);

		// create objects
		var windowManager = new WindowManager(main);

		ext.windowManager = windowManager;

		// combine nodes and objects
		win.on('resize', resize);
		win.on('orientationchange', resize);
		resize();

		var settings = getWindowSettings(),
			windowWidth = win.width();
		//console.log('settings',settings, settings.length);

		if (windowWidth < 768 && settings.windows.length >= 3) {
			settings.windows = settings.windows.slice(0,2);
		}
		if (windowWidth < 480 && settings.windows.length >= 2) {
			settings.windows = settings.windows.slice(0,1);
		}

		// create windows
		for (var i=0, il=settings.windows.length; i<il; i++) {
			var setting = settings.windows[i],
				windowClassName = setting.windowType;

			// try to find ClassName by the parameter
			if (!windowClassName) {
				var param = setting.type,
					filteredWindowTypes = sofia.windowTypes.filter(function(wt) {
						return wt.param == param;
					});

				if (filteredWindowTypes.length == 1) {
					windowClassName = filteredWindowTypes[0].className;
				}
			}

			//console.log('create window', setting, windowClassName);
			windowManager.add(windowClassName, setting.data);
		}

		// get first window
		var bibleWindows = settings.windows.filter(function(s) { return s.windowType == 'BibleWindow'; }),
			firstBibleWindow = bibleWindows.length > 0 ? bibleWindows[0] : null,
			firstFragmentid = firstBibleWindow != null && firstBibleWindow.data != null ? firstBibleWindow.data.fragmentid : null;

		if (firstFragmentid != null) {
			TextNavigation.firstState( firstFragmentid );
		}

		var settingsTimer = new Timer(storeSettings, 1000);

		windowManager.on('settingschange', function(e) {

			// title to show active window's position
			if (e.data && e.data.label && e.data.hasFocus) {
				document.title = e.data.labelLong;
			}

			settingsTimer.start();

		});

		var plugins = []
		ext.plugins = plugins;
		// run plugins
		for (var x in sofia.plugins) {
			plugin = new window[ sofia.plugins[x] ](this);
			plugins.push(plugin);

			if (plugin.on) {

				plugin.on('globalmessage', handleGlobalMessage);
			}
		}
	}

	function resize() {
		console.log('app resize');

		PlaceKeeper.storePlace();

		// get window size
		var width = win.width(),
			height = win.height(),

			// calculate size
			areaHeight = height - header.outerHeight() + footer.outerHeight(),
			areaWidth = width - parseInt(main.css('margin-left'), 10) - parseInt(main.css('margin-right'), 10);

		if (width < 460) {
			header.hide();
			areaHeight = height;
		} else {
			header.show();
		}

		// set height
		main.height(areaHeight);
		main.width(areaWidth);

		// pass new size down to area
		ext.windowManager.size(areaWidth, areaHeight);

		PlaceKeeper.restorePlace();
	}

	function getWindowSettings() {

		// (1) get default settings
		var settings = {
			windows: sofia.config.windows
		};

		// (2) replace defaults with user settings
		settings = AppSettings.getValue(settingsKey, settings);

		// (3) overwrite with QueryString when present
		var queryData = stringUtility.parseQuerystring();
		if (queryData["w1"]) {

			var tempSettings = [];

			for (var i=1; i<=4; i++) {
				var winTypeName = queryData["w" + i.toString()],
					winTypeInfo = sofia.windowTypes.filter(function(winType) { return winType.param == winTypeName; })[0],
					winTypeParamKeys = typeof winTypeInfo != 'undefined' ? Object.keys(winTypeInfo.paramKeys) : [],
					setting = {
						type: winTypeName,
						data: {}
					};

				if (typeof winTypeName != 'undefined') {
					// go though all querystring values, and anything that ends with '1' goes with this data
					for (var q in queryData) {
						var key = q.substring(0, q.length-1),
							number = q.substring(q.length-1),
							value = queryData[q];

						if (key != 'w' && number == i.toString()) {

							// convert short querystring key to longer one if needed
							var longParamKey = winTypeParamKeys.filter(function(lpk) {
								console.log(key, lpk, winTypeInfo.paramKeys[lpk]);
								return key == winTypeInfo.paramKeys[lpk] || key == lpk;
							})[0];

							setting.data[longParamKey] = value;
						}
					}

					tempSettings.push(setting);
				}
			}

			// overwrite settings
			if (tempSettings.length > 0) {
				settings.windows = tempSettings;
			}

		}
		return settings;
	}

	function storeSettings() {

			// get settings from al windows
		var windowSettings = ext.windowManager.getSettings(),
			// later we'll need these
			headerSettings = {},
			settings = {
				windows: windowSettings
			};

		//console.log('storeSettings', settings);

		// store
		AppSettings.setValue(settingsKey, settings );
	}

	function handleGlobalMessage(e) {
		// give to other windows
		var windows = ext.windowManager.getWindows();

		for (var i=0, il=windows.length; i<il; i++) {
			var w = windows[i];

			if (w.id != e.id) {
		 		// pass message down
		 		w.trigger('message', e);
			}
		}

		// plugins
		for (var i=0, il=ext.plugins.length; i<il; i++) {
			var p = sofia.app.plugins[i];

			if (p.trigger) {
				// pass message down
				p.trigger('message', e);
			}
		}

	}

	ext.init = init;
	ext.handleGlobalMessage = handleGlobalMessage;

	i18n.init({fallbackLng: 'en', resStore: sofia.resources});

	setTimeout(function() {

		var lang = i18n.lng(),
			langSelector = $('#config-language');

		langSelector.val( lang );

		if (lang != langSelector.val() ) {
			langSelector.val(  lang.split('-')[0] );
		}

	},50);

	return ext;
};
<|endoftext|>


<commit_before>#!/usr/bin/env nodejs

////////////////////////////////////////////////////////////////////////////////
/// Libraries and database driver
////////////////////////////////////////////////////////////////////////////////

var fs = require("fs");
var Promise = require("promise");
var Database = require("arangojs");
var concat = require("concat-stream");
var db = new Database("http://localhost:8529");          // configure server
var collectionName = "dev_guesser_questions";            // configure collection

var collectionPromise = new Promise(function(resolve, reject) {
    db.collection(collectionName, false, function(err, res) {
        if (err) {
            reject(err);
        }
        else {
            resolve(res);
        }
    });
});
collectionPromise.then(null, function(err) {
    console.log("Cannot contact the database! Terminating...");
    process.exit(1);
});

////////////////////////////////////////////////////////////////////////////////
/// An express app:
////////////////////////////////////////////////////////////////////////////////

var express = require('express');
var app = express();

////////////////////////////////////////////////////////////////////////////////
/// Static content:
////////////////////////////////////////////////////////////////////////////////

app.use(express.static(__dirname + "/static"));

////////////////////////////////////////////////////////////////////////////////
/// AJAX services:
////////////////////////////////////////////////////////////////////////////////

app.get("/get/:key", function (req, res) {
  var key = req.params["key"];
  collectionPromise.then(function(collection) {
      collection.document(key, function(err, x) {
          if (err) {
              // for production we should implement more sophisticated handling here. Like logging where appropriate etc.
              res.status(err.code);
              res.json(err);
          }
          else {
              res.json(x);
          }
      });
  }, null);  // if this were rejected, we would be out already
});

// This is just a trampoline to the Foxx app:
var ep = db.endpoint();
app.put("/put", function (req, res) {
  req.pipe(concat( function(body) {
    // check out body-parser for a express middleware which handles json automatically
    ep.put("/dev/guesser/put", JSON.parse(body.toString()),
      function(err, x) {
        if (err) {
          err.error = true;
          res.send(err);
        }
        else {
          res.send(x);
        }
      });
  } ));
});

////////////////////////////////////////////////////////////////////////////////
/// Now finally make the server:
////////////////////////////////////////////////////////////////////////////////

var server = app.listen(8000, function () {
  var host = server.address().address
  var port = server.address().port
  console.log('Guesser app server listening at http://%s:%s', host, port)
});
<commit_msg>Step 10<commit_after>#!/usr/bin/env nodejs

////////////////////////////////////////////////////////////////////////////////
/// Libraries and database driver
////////////////////////////////////////////////////////////////////////////////

var fs = require("fs");
var Promise = require("promise");
var concat = require("concat-stream");

var Database = require("arangojs");
var db = new Database("http://localhost:8529");          // configure server

////////////////////////////////////////////////////////////////////////////////
/// An express app:
////////////////////////////////////////////////////////////////////////////////

var express = require('express');
var app = express();

// leverage NODE_ENV to determine collectionName
var collectionName = "guesser_questions";            // configure collection
var putRoute = "/guesser/put";
if (app.get('env') == "development") {
    putRoute = "/dev" + putRoute;
    collectionName = "dev_" + collectionName;
}

var collectionPromise = new Promise(function(resolve, reject) {
    db.collection(collectionName, false, function(err, res) {
        if (err) {
            reject(err);
        }
        else {
            resolve(res);
        }
    });
});
collectionPromise.then(null, function(err) {
    console.log("Cannot contact the database! Terminating...");
    process.exit(1);
});

////////////////////////////////////////////////////////////////////////////////
/// Static content:
////////////////////////////////////////////////////////////////////////////////

app.use(express.static(__dirname + "/static"));

////////////////////////////////////////////////////////////////////////////////
/// AJAX services:
////////////////////////////////////////////////////////////////////////////////

app.get("/get/:key", function (req, res) {
  var key = req.params["key"];
  collectionPromise.then(function(collection) {
      collection.document(key, function(err, x) {
          if (err) {
              // for production we should implement more sophisticated handling here. Like logging where appropriate etc.
              res.status(err.code);
              res.json(err);
          }
          else {
              res.json(x);
          }
      });
  }, null);  // if this were rejected, we would be out already
});

// This is just a trampoline to the Foxx app:
var ep = db.endpoint();
app.put("/put", function (req, res) {
  req.pipe(concat( function(body) {
    // check out body-parser for a express middleware which handles json automatically
    ep.put(putRoute, JSON.parse(body.toString()),
      function(err, x) {
        if (err) {
          err.error = true;
          res.send(err);
        }
        else {
          res.send(x);
        }
      });
  } ));
});

////////////////////////////////////////////////////////////////////////////////
/// Now finally make the server:
////////////////////////////////////////////////////////////////////////////////

var server = app.listen(8000, function () {
  var host = server.address().address
  var port = server.address().port
  console.log('Guesser app server listening at http://%s:%s', host, port)
});
<|endoftext|>


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

var parse = require('./parse');

describe('Lexer', function() {
  var lex = parse.lex;

  describe('individual symbols', function() {
    it('should detect the right type of token', function() {
      assert.propertyVal(lex(' ')[0], 'type', 'space', 'spaces are spaces');
      assert.propertyVal(lex('0')[0], 'type', 'literal', 'zero is a literal');
      assert.propertyVal(lex('1.5')[0], 'type', 'literal', '1.5 is a literal');
      assert.propertyVal(lex('a')[0], 'type', 'name', '"a" is a name');
      assert.propertyVal(lex('+')[0], 'type', 'operator', 'plus is an operator');
      assert.propertyVal(lex('-')[0], 'type', 'operator', 'minus is an operator');
      assert.propertyVal(lex('*')[0], 'type', 'operator', 'multiply is an operator');
      assert.propertyVal(lex('/')[0], 'type', 'operator', 'divide is an operator');
      assert.propertyVal(lex('^')[0], 'type', 'operator', 'caret is an operator');
      assert.propertyVal(lex('<')[0], 'type', 'operator', 'less than is an operator');
      assert.propertyVal(lex('>')[0], 'type', 'operator', 'greater than is an operator');
      assert.propertyVal(lex('(')[0], 'type', 'paren', 'open parenthesis is a paren');
      assert.propertyVal(lex(')')[0], 'type', 'paren', 'close parenthesis is a paren');
      assert.propertyVal(lex('[')[0], 'type', 'paren', 'open bracket is a paren');
      assert.propertyVal(lex(']')[0], 'type', 'paren', 'close bracket is a paren');
    });
    it('should keep the right value', function() {
      assert.propertyVal(lex(' ')[0], 'value', ' ');
      assert.propertyVal(lex('a')[0], 'value', 'a');
      assert.propertyVal(lex('foo')[0], 'value', 'foo');
      assert.propertyVal(lex('+')[0], 'value', '+');
      assert.propertyVal(lex('(')[0], 'value', '(');
      // and on and on...
    });
  });
  describe('multi-symbol expressions', function() {
    it('should return an empty list for an empty expression', function() {
      assert.lengthOf(lex(''), 0, 'empty expressions are empty');
    });
    it('should return one symbol', function() {
      assert.lengthOf(lex(' '), 1, 'space is one symbol');
      assert.lengthOf(lex('  '), 1, 'spaces are grouped');
      assert.lengthOf(lex('a'), 1, 'a name is one symbol');
      assert.lengthOf(lex('foo'), 1, 'a name chan have multiple chars');
    });
    it('should return many symbols', function() {
      assert.lengthOf(lex('a b'), 3);
      assert.lengthOf(lex('a + b'), 5);
      assert.lengthOf(lex('a+b'), 3);
      assert.lengthOf(lex('2a'), 2, 'leading numbers are not part of a name');
      assert.lengthOf(lex('a2'), 1, 'names can have numbers after the first character');
      assert.lengthOf(lex('a2b'), 1, 'letters can follow numbers in names');
      assert.lengthOf(lex('a+'), 2, 'operators are not part of names');
      assert.lengthOf(lex('(1)'), 3);
      assert.lengthOf(lex('f()'), 3);
      assert.lengthOf(lex('.5'), 1, 'decimal numbers are one symbol');
      assert.lengthOf(lex('1.5'), 1, 'decimal numbers are one symbol');
      assert.lengthOf(lex('1.5.5'), 2, 'one number cannot have two dots.');
    });
  });
  describe('data structure', function() {
    it('should be defined for empty expressions', function() {
      assert.deepEqual(lex(''), [], 'empty expression -> empty list');
    });
    it('should otherswise be an array of objects', function() {
      assert.deepEqual(lex(' '), [{type: 'space', value: ' '}]);
      assert.deepEqual(
        lex('2 + sin(t)'),
        [{type: 'literal', value: '2'},
         {type: 'space', value: ' '},
         {type: 'operator', value: '+'},
         {type: 'space', value: ' '},
         {type: 'name', value: 'sin'},
         {type: 'paren', value: '('},
         {type: 'name', value: 't'},
         {type: 'paren', value: ')'}]);
    });
  });
  describe('invalid tokens', function() {
    it('should give 1-char tokens of type "null"', function() {
      assert.deepEqual(lex('!'), [{type: null, value: '!'}]);
      assert.deepEqual(
        lex('!@&'),
        [{type: null, value: '!'},
         {type: null, value: '@'},
         {type: null, value: '&'}]);
      assert.deepEqual(
        lex('abc!def'),
        [{type: 'name', value: 'abc'},
         {type: null, value: '!'},
         {type: 'name', value: 'def'}]);
    });
  });
});

describe('Parser', function() {

  describe('edge cases', function() {
    it('should error on empty expression', function() {
      assert.throws(function() { parse(''); }, parse.ParseError);
      assert.throws(function() { parse('()'); }, parse.ParseError);
      assert.throws(function() { parse('f()'); }, parse.ParseError);
      assert.throws(function() { parse('1+()'); }, parse.ParseError);
    });
  });
  describe('simple cases', function() {
    it('should parse a simple literal value', function() {
      assert.equal(parse('1').expr.type, 'literal');
    });
    it('should parse a simple name', function() {
      assert.equal(parse('a').expr.type, 'name');
    });
    it('should parse a function call', function() {
      assert.equal(parse('f(x)').expr.type, 'func');
    });
    it('should parse operators', function() {
      assert.equal(parse('-1').expr.type, 'operator');
      assert.equal(parse('1-2').expr.type, 'operator');
      assert.equal(parse('1+2').expr.type, 'operator');
      assert.equal(parse('1*2').expr.type, 'operator');
      assert.equal(parse('1/2').expr.type, 'operator');
      assert.equal(parse('1^2').expr.type, 'operator');
    });
  });
  describe('parens', function() {
    it('should complain about mismatched parens', function() {
      assert.throws(function() { parse('('); }, parse.ParseError);
      assert.throws(function() { parse(')'); }, parse.ParseError);
      assert.throws(function() { parse('(()'); }, parse.ParseError);
      assert.throws(function() { parse('())'); }, parse.ParseError);
    });
    it('should parse contents as a subexpression', function() {
      assert.equal(parse('(1)').expr.type, 'expr');
      assert.equal(parse('(1)').expr.expr.type, 'literal');
    });
    it('should treat function expressions as subexpressions', function() {
      assert.equal(parse('sin(t)').expr.type, 'func');
      assert.equal(parse('sin(t)').expr.args[0].type, 'expr');
    });
  });
  describe('operators', function() {
    it('should error for trailing operators', function() {
      assert.throws(function() { parse('1+'); }, parse.ParseError);
    });
    it('should error for leading non-unary operators', function() {
      assert.throws(function() { parse('/1'); }, parse.ParseError);
    });
  });
  describe('plus', function() {
    it('should turn unary + into a noop', function() {
      assert.equal(parse('+1').expr.type, 'literal');
      assert.equal(parse('++1').expr.type, 'literal');
    });
    it('should pull minus into plus unary-minus', function() {
      assert.equal(parse('1-2').expr.op, 'plus');
      assert.equal(parse('1-2').expr.args[1].type, 'operator');
    });
    it('should group plusses', function() {
      assert.equal(parse('1+2+3').expr.args.length, 3);
      assert.equal(parse('1+2-3').expr.args.length, 3);
      assert.equal(parse('1-2+3').expr.args.length, 3);
      assert.equal(parse('1-2-3').expr.args.length, 3);
      assert.equal(parse('1-2-3').expr.op, 'plus');
    });
  });
});
<commit_msg>add failing test for #2<commit_after>require('mocha');
var assert = require('chai').assert;

var parse = require('./parse');

describe('Lexer', function() {
  var lex = parse.lex;

  describe('individual symbols', function() {
    it('should detect the right type of token', function() {
      assert.propertyVal(lex(' ')[0], 'type', 'space', 'spaces are spaces');
      assert.propertyVal(lex('0')[0], 'type', 'literal', 'zero is a literal');
      assert.propertyVal(lex('1.5')[0], 'type', 'literal', '1.5 is a literal');
      assert.propertyVal(lex('a')[0], 'type', 'name', '"a" is a name');
      assert.propertyVal(lex('+')[0], 'type', 'operator', 'plus is an operator');
      assert.propertyVal(lex('-')[0], 'type', 'operator', 'minus is an operator');
      assert.propertyVal(lex('*')[0], 'type', 'operator', 'multiply is an operator');
      assert.propertyVal(lex('/')[0], 'type', 'operator', 'divide is an operator');
      assert.propertyVal(lex('^')[0], 'type', 'operator', 'caret is an operator');
      assert.propertyVal(lex('<')[0], 'type', 'operator', 'less than is an operator');
      assert.propertyVal(lex('>')[0], 'type', 'operator', 'greater than is an operator');
      assert.propertyVal(lex('(')[0], 'type', 'paren', 'open parenthesis is a paren');
      assert.propertyVal(lex(')')[0], 'type', 'paren', 'close parenthesis is a paren');
      assert.propertyVal(lex('[')[0], 'type', 'paren', 'open bracket is a paren');
      assert.propertyVal(lex(']')[0], 'type', 'paren', 'close bracket is a paren');
    });
    it('should keep the right value', function() {
      assert.propertyVal(lex(' ')[0], 'value', ' ');
      assert.propertyVal(lex('a')[0], 'value', 'a');
      assert.propertyVal(lex('foo')[0], 'value', 'foo');
      assert.propertyVal(lex('+')[0], 'value', '+');
      assert.propertyVal(lex('(')[0], 'value', '(');
      // and on and on...
    });
  });
  describe('multi-symbol expressions', function() {
    it('should return an empty list for an empty expression', function() {
      assert.lengthOf(lex(''), 0, 'empty expressions are empty');
    });
    it('should return one symbol', function() {
      assert.lengthOf(lex(' '), 1, 'space is one symbol');
      assert.lengthOf(lex('  '), 1, 'spaces are grouped');
      assert.lengthOf(lex('a'), 1, 'a name is one symbol');
      assert.lengthOf(lex('foo'), 1, 'a name chan have multiple chars');
    });
    it('should return many symbols', function() {
      assert.lengthOf(lex('a b'), 3);
      assert.lengthOf(lex('a + b'), 5);
      assert.lengthOf(lex('a+b'), 3);
      assert.lengthOf(lex('2a'), 2, 'leading numbers are not part of a name');
      assert.lengthOf(lex('a2'), 1, 'names can have numbers after the first character');
      assert.lengthOf(lex('a2b'), 1, 'letters can follow numbers in names');
      assert.lengthOf(lex('a+'), 2, 'operators are not part of names');
      assert.lengthOf(lex('(1)'), 3);
      assert.lengthOf(lex('f()'), 3);
      assert.lengthOf(lex('.5'), 1, 'decimal numbers are one symbol');
      assert.lengthOf(lex('1.5'), 1, 'decimal numbers are one symbol');
      assert.lengthOf(lex('1.5.5'), 2, 'one number cannot have two dots.');
    });
  });
  describe('data structure', function() {
    it('should be defined for empty expressions', function() {
      assert.deepEqual(lex(''), [], 'empty expression -> empty list');
    });
    it('should otherswise be an array of objects', function() {
      assert.deepEqual(lex(' '), [{type: 'space', value: ' '}]);
      assert.deepEqual(
        lex('2 + sin(t)'),
        [{type: 'literal', value: '2'},
         {type: 'space', value: ' '},
         {type: 'operator', value: '+'},
         {type: 'space', value: ' '},
         {type: 'name', value: 'sin'},
         {type: 'paren', value: '('},
         {type: 'name', value: 't'},
         {type: 'paren', value: ')'}]);
    });
  });
  describe('invalid tokens', function() {
    it('should give 1-char tokens of type "null"', function() {
      assert.deepEqual(lex('!'), [{type: null, value: '!'}]);
      assert.deepEqual(
        lex('!@&'),
        [{type: null, value: '!'},
         {type: null, value: '@'},
         {type: null, value: '&'}]);
      assert.deepEqual(
        lex('abc!def'),
        [{type: 'name', value: 'abc'},
         {type: null, value: '!'},
         {type: 'name', value: 'def'}]);
    });
  });
});

describe('Parser', function() {

  describe('edge cases', function() {
    it('should error on empty expression', function() {
      assert.throws(function() { parse(''); }, parse.ParseError);
      assert.throws(function() { parse('()'); }, parse.ParseError);
      assert.throws(function() { parse('f()'); }, parse.ParseError);
      assert.throws(function() { parse('1+()'); }, parse.ParseError);
    });
  });
  describe('simple cases', function() {
    it('should parse a simple literal value', function() {
      assert.equal(parse('1').expr.type, 'literal');
    });
    it('should parse a simple name', function() {
      assert.equal(parse('a').expr.type, 'name');
    });
    it('should parse a function call', function() {
      assert.equal(parse('f(x)').expr.type, 'func');
    });
    it('should parse operators', function() {
      assert.equal(parse('-1').expr.type, 'operator');
      assert.equal(parse('1-2').expr.type, 'operator');
      assert.equal(parse('1+2').expr.type, 'operator');
      assert.equal(parse('1*2').expr.type, 'operator');
      assert.equal(parse('1/2').expr.type, 'operator');
      assert.equal(parse('1^2').expr.type, 'operator');
    });
  });
  describe('parens', function() {
    it('should complain about mismatched parens', function() {
      assert.throws(function() { parse('('); }, parse.ParseError);
      assert.throws(function() { parse(')'); }, parse.ParseError);
      assert.throws(function() { parse('(()'); }, parse.ParseError);
      assert.throws(function() { parse('())'); }, parse.ParseError);
    });
    it('should parse contents as a subexpression', function() {
      assert.equal(parse('(1)').expr.type, 'expr');
      assert.equal(parse('(1)').expr.expr.type, 'literal');
    });
    it('should treat function expressions as subexpressions', function() {
      assert.equal(parse('sin(t)').expr.type, 'func');
      assert.equal(parse('sin(t)').expr.args[0].type, 'expr');
    });
  });
  describe('operators', function() {
    it('should error for trailing operators', function() {
      assert.throws(function() { parse('1+'); }, parse.ParseError);
    });
    it('should error for leading non-unary operators', function() {
      assert.throws(function() { parse('/1'); }, parse.ParseError);
    });
  });
  describe('plus', function() {
    it('should turn unary + into a noop', function() {
      assert.equal(parse('+1').expr.type, 'literal');
      assert.equal(parse('++1').expr.type, 'literal');
    });
    it('should pull minus into plus unary-minus', function() {
      assert.equal(parse('1-2').expr.op, 'plus');
      assert.equal(parse('1-2').expr.args[1].type, 'operator');
    });
    it('should group plusses', function() {
      assert.equal(parse('1+2+3').expr.args.length, 3);
      assert.equal(parse('1+2-3').expr.args.length, 3);
      assert.equal(parse('1-2+3').expr.args.length, 3);
      assert.equal(parse('1-2-3').expr.args.length, 3);
      assert.equal(parse('1-2-3').expr.op, 'plus');
    });
  });
  describe('regressions', function() {
    it('should work for x^2-y^2+time*3000', function() {
      assert.doesNotThrow(function() { parse('x^2-y^2+time*3000'); }, parse.ParseError);
    });
  });
});
<|endoftext|>


<commit_before>angular.module('ngCordova.plugins.geolocation', [])

.factory('$cordovaGeolocation', ['$q', function($q) {

  return {
    getCurrentPosition: function(options) {
      var q = $q.defer();

      navigator.geolocation.getCurrentPosition(function(result) {
        // Do any magic you need
        q.resolve(result);
      }, function(err) {
        q.reject(err);
      }, options);

      return q.promise;
    },
    watchPosition: function(options) {
      var q = $q.defer();

      watchId = navigator.geolocation.watchPosition(function(result) {
        // Do any magic you need
        q.resolve(watchID);
        q.notify(result);

      }, function(err) {
        q.reject(err);
      }, options);

      return q.promise;
    },

    clearWatch: function(watchID) {
      return navigator.geolocation.clearWatch(watchID);
    }
  }
}]);
<commit_msg>Just set watchID as a locale variable.<commit_after>angular.module('ngCordova.plugins.geolocation', [])

.factory('$cordovaGeolocation', ['$q', function($q) {

  return {
    getCurrentPosition: function(options) {
      var q = $q.defer();

      navigator.geolocation.getCurrentPosition(function(result) {
        // Do any magic you need
        q.resolve(result);
      }, function(err) {
        q.reject(err);
      }, options);

      return q.promise;
    },
    watchPosition: function(options) {
      var q = $q.defer();

      var watchId = navigator.geolocation.watchPosition(function(result) {
        // Do any magic you need
        q.resolve(watchID);
        q.notify(result);

      }, function(err) {
        q.reject(err);
      }, options);

      return q.promise;
    },

    clearWatch: function(watchID) {
      return navigator.geolocation.clearWatch(watchID);
    }
  }
}]);
<|endoftext|>


<commit_before>/*
Name:           requestbin - test.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-requestbin
Feedback:       https://github.com/fvdm/nodejs-requestbin/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-requestbin/raw/develop/UNLICENSE)
*/

var http = require ('httpreq');
var dotest = require ('dotest');
var app = require ('./');

// Setup
var timeout = process.env.REQUESTBIN_TIMEOUT || 5000;
var iface = process.env.REQUESTBIN_INTERFACE || null;

var cache = {
  bin: null,
  request: null,
  post: {
    nodejs: process.versions.node
  }
};

app.config ({
  timeout: timeout,
  iface: iface
});

dotest.add ('Error: request failed', function () {
  app.config ({ timeout: 1 });
  app.create ('invalid', function (err) {
    dotest.test ()
      .isError ('fail', 'err', err)
      .isExactly ('fail', 'err.message', err && err.message, 'request failed')
      .isError ('fail', 'err.error', err && err.error)
      .done ();
  });
});

dotest.add ('.create', function () {
  app.config ({ timeout: timeout });
  app.create (false, function (err, data) {
    cache.bin = data || null;

    if (data) {
      http.post ('http://requestb.in/' + data.name, { parameters: cache.post }, function () {});
      dotest.log ('info', 'http://requestb.in/' + data.name + '?inspect');
    }

    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isString ('warn', 'data.name', data && data.name)
      .done ();
  });
});

dotest.add ('.get', function () {
  if (!cache.bin) {
    console.log ('skip - .get');
    return;
  }

  app.get (cache.bin.name, function (err, data) {
    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isExactly ('warn', 'data.name', data && data.name, cache.bin.name)
      .done ();
  });
});

dotest.add ('.requests', function () {
  if (!cache.bin) {
    console.log ('skip - .requests');
    return;
  }

  app.requests (cache.bin.name, function (err, data) {
    cache.request = data && data [0] || null;
    dotest.test (err)
      .isArray ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isObject ('warn', 'data[0]', data && data [0])
      .done ();
  });
});

dotest.add ('.request', function () {
  if (!cache.request) {
    console.log ('skip - .request');
    return;
  }

  app.request (cache.bin.name, cache.request.id, function (err, data) {
    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isExactly ('warn', 'data.id', data && data.id, cache.request.id)
      .done ();
  });
});

dotest.run ();
<commit_msg>Test: wait one second between tests<commit_after>/*
Name:           requestbin - test.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-requestbin
Feedback:       https://github.com/fvdm/nodejs-requestbin/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-requestbin/raw/develop/UNLICENSE)
*/

var http = require ('httpreq');
var dotest = require ('dotest');
var app = require ('./');

// Setup
var timeout = process.env.REQUESTBIN_TIMEOUT || 5000;
var iface = process.env.REQUESTBIN_INTERFACE || null;

var cache = {
  bin: null,
  request: null,
  post: {
    nodejs: process.versions.node
  }
};

app.config ({
  timeout: timeout,
  iface: iface
});

dotest.add ('Error: request failed', function () {
  app.config ({ timeout: 1 });
  app.create ('invalid', function (err) {
    dotest.test ()
      .isError ('fail', 'err', err)
      .isExactly ('fail', 'err.message', err && err.message, 'request failed')
      .isError ('fail', 'err.error', err && err.error)
      .done ();
  });
});

dotest.add ('.create', function () {
  app.config ({ timeout: timeout });
  app.create (false, function (err, data) {
    cache.bin = data || null;

    if (data) {
      http.post ('http://requestb.in/' + data.name, { parameters: cache.post }, function () {});
      dotest.log ('info', 'http://requestb.in/' + data.name + '?inspect');
    }

    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isString ('warn', 'data.name', data && data.name)
      .done ();
  });
});

dotest.add ('.get', function () {
  if (!cache.bin) {
    console.log ('skip - .get');
    return;
  }

  app.get (cache.bin.name, function (err, data) {
    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isExactly ('warn', 'data.name', data && data.name, cache.bin.name)
      .done ();
  });
});

dotest.add ('.requests', function () {
  if (!cache.bin) {
    console.log ('skip - .requests');
    return;
  }

  app.requests (cache.bin.name, function (err, data) {
    cache.request = data && data [0] || null;
    dotest.test (err)
      .isArray ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isObject ('warn', 'data[0]', data && data [0])
      .done ();
  });
});

dotest.add ('.request', function () {
  if (!cache.request) {
    console.log ('skip - .request');
    return;
  }

  app.request (cache.bin.name, cache.request.id, function (err, data) {
    dotest.test (err)
      .isObject ('fail', 'data', data)
      .isExactly ('warn', 'data.id', data && data.id, cache.request.id)
      .done ();
  });
});

dotest.run (1000);
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var Me = require('./lib/me');
var Site = require('./lib/site');
var debug = require('debug')('wpcom');

/**
 * WordPress.com REST API class.
 *
 * @api public
 */

function WPCOM(request){
  if (!(this instanceof WPCOM)) return new WPCOM(request);
  if ('function' !== typeof request) {
    throw new TypeError('a `request` WP.com function must be passed in');
  }
  this.request = request;
}

/**
 * Get me object instance
 *
 * @api public
 */

WPCOM.prototype.me = function(){
  return new Me(this);
};

/**
 * Get site object instance
 *
 * @param {String} id
 * @api public
 */

WPCOM.prototype.site = function(id){
  return new Site(id, this);
};

/**
 * List Freshly Pressed Posts
 *
 * @param {Object} params (optional)
 * @param {Function} fn callback function
 * @api public
 */

WPCOM.prototype.freshlyPressed = function(params, fn){
  this.sendRequest('freshly-pressed.get', null, params, fn);
};

/**
 * Request to WordPress REST API
 *
 * @param {String||Object} params
 * @param {Object} [query]
 * @param {Object} [body]
 * @param {Function} fn
 * @api private
 */

WPCOM.prototype.sendRequest = function (params, query, body, fn){
  // `params` can be just the path (String)
  if ('string' == typeof params) {
    params = { path: params };
  }

  debug('sendRequest("%s")', params.path);

  // set `method` request param
  params.method = (params.method || 'get').toUpperCase();

  // `query` is optional
  if ('function' == typeof query) {
    fn = query;
    query = null;
  }

  // `body` is optional
  if ('function' == typeof body) {
    fn = body;
    body = null;
  }

  // pass `query` and/or `body` to request params
  if (query) params.query = query;

  if (body) {
    // get `formData` from body
    if (body.formData) {
      params.formData = body.formData;
      delete body.formData;
    }

    // pass `body` if it has keys
    if (Object.keys(body).length) {
      params.body = body;
    }
  }

  // callback `fn` function is optional
  if (!fn) fn = function(err){ if (err) throw err; };

  // request method
  this.request(params, fn);
};

/**
 * Expose `WPCOM` module
 */

module.exports = WPCOM;
<commit_msg>core: remove pass formData in the body param<commit_after>
/**
 * Module dependencies.
 */

var Me = require('./lib/me');
var Site = require('./lib/site');
var debug = require('debug')('wpcom');

/**
 * WordPress.com REST API class.
 *
 * @api public
 */

function WPCOM(request){
  if (!(this instanceof WPCOM)) return new WPCOM(request);
  if ('function' !== typeof request) {
    throw new TypeError('a `request` WP.com function must be passed in');
  }
  this.request = request;
}

/**
 * Get me object instance
 *
 * @api public
 */

WPCOM.prototype.me = function(){
  return new Me(this);
};

/**
 * Get site object instance
 *
 * @param {String} id
 * @api public
 */

WPCOM.prototype.site = function(id){
  return new Site(id, this);
};

/**
 * List Freshly Pressed Posts
 *
 * @param {Object} params (optional)
 * @param {Function} fn callback function
 * @api public
 */

WPCOM.prototype.freshlyPressed = function(params, fn){
  this.sendRequest('freshly-pressed.get', null, params, fn);
};

/**
 * Request to WordPress REST API
 *
 * @param {String||Object} params
 * @param {Object} [query]
 * @param {Object} [body]
 * @param {Function} fn
 * @api private
 */

WPCOM.prototype.sendRequest = function (params, query, body, fn){
  // `params` can be just the path (String)
  if ('string' == typeof params) {
    params = { path: params };
  }

  debug('sendRequest("%s")', params.path);

  // set `method` request param
  params.method = (params.method || 'get').toUpperCase();

  // `query` is optional
  if ('function' == typeof query) {
    fn = query;
    query = null;
  }

  // `body` is optional
  if ('function' == typeof body) {
    fn = body;
    body = null;
  }

  // pass `query` and/or `body` to request params
  if (query) params.query = query;
  if (body) params.body = body;

  // callback `fn` function is optional
  if (!fn) fn = function(err){ if (err) throw err; };

  // request method
  this.request(params, fn);
};

/**
 * Expose `WPCOM` module
 */

module.exports = WPCOM;
<|endoftext|>