<commit_before>var show_list;
var sort_type = 'alphabetic';

$(document).ready(function () {
  bootbox.setDefaults({locale:lang['locale-bootbox']});
  loadFolders();
  performLfmRequest('errors')
    .done(function (data) {
      var response = JSON.parse(data);
      for (var i = 0; i < response.length; i++) {
        $('#alerts').append(
          $('
').addClass('alert alert-warning')
            .append($('').addClass('fa fa-exclamation-circle'))
            .append(' ' + response[i])
        );
      }
    });
});

// ======================
// ==  Navbar actions  ==
// ======================

$('#nav-buttons a').click(function (e) {
  e.preventDefault();
});

$('#to-previous').click(function () {
  var previous_dir = getPreviousDir();
  if (previous_dir == '') return;
  goTo(previous_dir);
});

$('#add-folder').click(function () {
  bootbox.prompt(lang['message-name'], function (result) {
    if (result == null) return;
    createFolder(result);
  });
});

$('#upload').click(function () {
  $('#uploadModal').modal('show');
});

$('#upload-btn').click(function () {
  $(this).html('')
    .append($('').addClass('fa fa-refresh fa-spin'))
    .append(" " + lang['btn-uploading'])
    .addClass('disabled');

  function resetUploadForm() {
    $('#uploadModal').modal('hide');
    $('#upload-btn').html(lang['btn-upload']).removeClass('disabled');
    $('input#upload').val('');
  }

  $('#uploadForm').ajaxSubmit({
    success: function (data, statusText, xhr, $form) {
      resetUploadForm();
      refreshFoldersAndItems(data);
    },
    error: function (jqXHR, textStatus, errorThrown) {
      displayErrorResponse(jqXHR);
      resetUploadForm();
    }
  });
});

$('#thumbnail-display').click(function () {
  show_list = 0;
  loadItems();
});

$('#list-display').click(function () {
  show_list = 1;
  loadItems();
});

$('#list-sort-alphabetic').click(function() {
  sort_type = 'alphabetic';
  loadItems();
});

$('#list-sort-time').click(function() {
  sort_type = 'time';
  loadItems();
});

// ======================
// ==  Folder actions  ==
// ======================

$(document).on('click', '.file-item', function (e) {
  useFile($(this).data('id'));
});

$(document).on('click', '.folder-item', function (e) {
  goTo($(this).data('id'));
});

function goTo(new_dir) {
  $('#working_dir').val(new_dir);
  loadItems();
}

function getPreviousDir() {
  var ds = '/';
  var working_dir = $('#working_dir').val();
  var last_ds = working_dir.lastIndexOf(ds);
  var previous_dir = working_dir.substring(0, last_ds);
  return previous_dir;
}

function dir_starts_with(str) {
  return $('#working_dir').val().indexOf(str) === 0;
}

function setOpenFolders() {
  var folders = $('.folder-item');

  for (var i = folders.length - 1; i >= 0; i--) {
    // close folders that are not parent
    if (! dir_starts_with($(folders[i]).data('id'))) {
      $(folders[i]).children('i').removeClass('fa-folder-open').addClass('fa-folder');
    } else {
      $(folders[i]).children('i').removeClass('fa-folder').addClass('fa-folder-open');
    }
  }
}

// ====================
// ==  Ajax actions  ==
// ====================

function performLfmRequest(url, parameter, type) {
  var data = defaultParameters();

  if (parameter != null) {
    $.each(parameter, function (key, value) {
      data[key] = value;
    });
  }

  return $.ajax({
    type: 'GET',
    dataType: type || 'text',
    url: lfm_route + '/' + url,
    data: data,
    cache: false
  }).fail(function (jqXHR, textStatus, errorThrown) {
    displayErrorResponse(jqXHR);
  });
}

function displayErrorResponse(jqXHR) {
  notify('
' + jqXHR.responseText + '
');
}

var refreshFoldersAndItems = function (data) {
  loadFolders();
  if (data != 'OK') {
    data = Array.isArray(data) ? data.join('
') : data;
    notify(data);
  }
};

var hideNavAndShowEditor = function (data) {
  $('#nav-buttons > ul').addClass('hidden');
  $('#content').html(data);
}

function loadFolders() {
  performLfmRequest('folders', {}, 'html')
    .done(function (data) {
      $('#tree').html(data);
      loadItems();
    });
}

function loadItems() {
  performLfmRequest('jsonitems', {show_list: show_list, sort_type: sort_type}, 'html')
    .done(function (data) {
      var response = JSON.parse(data);
      $('#content').html(response.html);
      $('#nav-buttons > ul').removeClass('hidden');
      $('#working_dir').val(response.working_dir);
      $('#current_dir').text(response.working_dir);
      console.log('Current working_dir : ' + $('#working_dir').val());
      if (getPreviousDir() == '') {
        $('#to-previous').addClass('hide');
      } else {
        $('#to-previous').removeClass('hide');
      }
      setOpenFolders();
    });
}

function createFolder(folder_name) {
  performLfmRequest('newfolder', {name: folder_name})
    .done(refreshFoldersAndItems);
}

function rename(item_name) {
  bootbox.prompt({
    title: lang['message-rename'],
    value: item_name,
    callback: function (result) {
      if (result == null) return;
      performLfmRequest('rename', {
        file: item_name,
        new_name: result
      }).done(refreshFoldersAndItems);
    }
  });
}

function trash(item_name) {
  bootbox.confirm(lang['message-delete'], function (result) {
    if (result == true) {
      performLfmRequest('delete', {items: item_name})
        .done(refreshFoldersAndItems);
    }
  });
}

function cropImage(image_name) {
  performLfmRequest('crop', {img: image_name})
    .done(hideNavAndShowEditor);
}

function resizeImage(image_name) {
  performLfmRequest('resize', {img: image_name})
    .done(hideNavAndShowEditor);
}

function download(file_name) {
  var data = defaultParameters();
  data['file'] = file_name;
  location.href = lfm_route + '/download?' + $.param(data);
}

// ==================================
// ==  Ckeditor, Bootbox, preview  ==
// ==================================

function useFile(file_url) {

  function getUrlParam(paramName) {
    var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
    var match = window.location.search.match(reParam);
    return ( match && match.length > 1 ) ? match[1] : null;
  }

  function useTinymce3(url) {
    var win = tinyMCEPopup.getWindowArg("window");
    win.document.getElementById(tinyMCEPopup.getWindowArg("input")).value = url;
    if (typeof(win.ImageDialog) != "undefined") {
      // Update image dimensions
      if (win.ImageDialog.getImageData) {
        win.ImageDialog.getImageData();
      }

      // Preview if necessary
      if (win.ImageDialog.showPreviewImage) {
        win.ImageDialog.showPreviewImage(url);
      }
    }
    tinyMCEPopup.close();
  }

  function useTinymce4AndColorbox(url, field_name) {
    parent.document.getElementById(field_name).value = url;

    if(typeof parent.tinyMCE !== "undefined") {
      parent.tinyMCE.activeEditor.windowManager.close();
    }
    if(typeof parent.$.fn.colorbox !== "undefined") {
      parent.$.fn.colorbox.close();
    }
  }

  function useCkeditor3(url) {
    if (window.opener) {
      // Popup
      window.opener.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
    } else {
      // Modal (in iframe)
      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorCleanUpFuncNum'));
    }
  }

  function useFckeditor2(url) {
    var p = url;
    var w = data['Properties']['Width'];
    var h = data['Properties']['Height'];
    window.opener.SetUrl(p,w,h);
  }

  var url = file_url;
  var field_name = getUrlParam('field_name');
  var is_ckeditor = getUrlParam('CKEditor');
  var is_fcke = typeof data != 'undefined' && data['Properties']['Width'] != '';
  var file_path = url.replace(route_prefix, '');

  if (window.opener || window.tinyMCEPopup || field_name || getUrlParam('CKEditorCleanUpFuncNum') || is_ckeditor) {
    if (window.tinyMCEPopup) { // use TinyMCE > 3.0 integration method
      useTinymce3(url);
    } else if (field_name) {   // tinymce 4 and colorbox
      useTinymce4AndColorbox(url, field_name);
    } else if(is_ckeditor) {   // use CKEditor 3.0 + integration method
      useCkeditor3(url);
    } else if (is_fcke) {      // use FCKEditor 2.0 integration method
      useFckeditor2(url);
    } else {                   // standalone button or other situations
      window.opener.SetUrl(url, file_path);
    }

    if (window.opener) {
      window.close();
    }
  } else {
    // No WYSIWYG editor found, use custom method.
    window.opener.SetUrl(url, file_path);
  }
}
//end useFile

function defaultParameters() {
  return {
    working_dir: $('#working_dir').val(),
    type: $('#type').val()
  };
}

function notImp() {
  bootbox.alert('Not yet implemented!');;
}

function notify(message) {
  bootbox.alert(message);
}

function fileView(file_url, timestamp) {
  var rnd = makeRandom();
  bootbox.dialog({
    title: lang['title-view'],
    message: $('')
      .addClass('img img-responsive center-block')
      .attr('src', file_url + '?timestamp=' + timestamp),
    size: 'large',
    onEscape: true,
    backdrop: true
  });
}

function makeRandom() {
  var text = '';
  var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (var i = 0; i < 20; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}
<commit_msg>Open files without editor If the file manager is implemented without an editor and does not open a new popup window (ie. just using as a file browser/upload/download app), open files using browser's default method instead of trying to access window.opener (which does not exist).<commit_after>var show_list;
var sort_type = 'alphabetic';

$(document).ready(function () {
  bootbox.setDefaults({locale:lang['locale-bootbox']});
  loadFolders();
  performLfmRequest('errors')
    .done(function (data) {
      var response = JSON.parse(data);
      for (var i = 0; i < response.length; i++) {
        $('#alerts').append(
          $('
').addClass('alert alert-warning')
            .append($('').addClass('fa fa-exclamation-circle'))
            .append(' ' + response[i])
        );
      }
    });
});

// ======================
// ==  Navbar actions  ==
// ======================

$('#nav-buttons a').click(function (e) {
  e.preventDefault();
});

$('#to-previous').click(function () {
  var previous_dir = getPreviousDir();
  if (previous_dir == '') return;
  goTo(previous_dir);
});

$('#add-folder').click(function () {
  bootbox.prompt(lang['message-name'], function (result) {
    if (result == null) return;
    createFolder(result);
  });
});

$('#upload').click(function () {
  $('#uploadModal').modal('show');
});

$('#upload-btn').click(function () {
  $(this).html('')
    .append($('').addClass('fa fa-refresh fa-spin'))
    .append(" " + lang['btn-uploading'])
    .addClass('disabled');

  function resetUploadForm() {
    $('#uploadModal').modal('hide');
    $('#upload-btn').html(lang['btn-upload']).removeClass('disabled');
    $('input#upload').val('');
  }

  $('#uploadForm').ajaxSubmit({
    success: function (data, statusText, xhr, $form) {
      resetUploadForm();
      refreshFoldersAndItems(data);
    },
    error: function (jqXHR, textStatus, errorThrown) {
      displayErrorResponse(jqXHR);
      resetUploadForm();
    }
  });
});

$('#thumbnail-display').click(function () {
  show_list = 0;
  loadItems();
});

$('#list-display').click(function () {
  show_list = 1;
  loadItems();
});

$('#list-sort-alphabetic').click(function() {
  sort_type = 'alphabetic';
  loadItems();
});

$('#list-sort-time').click(function() {
  sort_type = 'time';
  loadItems();
});

// ======================
// ==  Folder actions  ==
// ======================

$(document).on('click', '.file-item', function (e) {
  useFile($(this).data('id'));
});

$(document).on('click', '.folder-item', function (e) {
  goTo($(this).data('id'));
});

function goTo(new_dir) {
  $('#working_dir').val(new_dir);
  loadItems();
}

function getPreviousDir() {
  var ds = '/';
  var working_dir = $('#working_dir').val();
  var last_ds = working_dir.lastIndexOf(ds);
  var previous_dir = working_dir.substring(0, last_ds);
  return previous_dir;
}

function dir_starts_with(str) {
  return $('#working_dir').val().indexOf(str) === 0;
}

function setOpenFolders() {
  var folders = $('.folder-item');

  for (var i = folders.length - 1; i >= 0; i--) {
    // close folders that are not parent
    if (! dir_starts_with($(folders[i]).data('id'))) {
      $(folders[i]).children('i').removeClass('fa-folder-open').addClass('fa-folder');
    } else {
      $(folders[i]).children('i').removeClass('fa-folder').addClass('fa-folder-open');
    }
  }
}

// ====================
// ==  Ajax actions  ==
// ====================

function performLfmRequest(url, parameter, type) {
  var data = defaultParameters();

  if (parameter != null) {
    $.each(parameter, function (key, value) {
      data[key] = value;
    });
  }

  return $.ajax({
    type: 'GET',
    dataType: type || 'text',
    url: lfm_route + '/' + url,
    data: data,
    cache: false
  }).fail(function (jqXHR, textStatus, errorThrown) {
    displayErrorResponse(jqXHR);
  });
}

function displayErrorResponse(jqXHR) {
  notify('
' + jqXHR.responseText + '
');
}

var refreshFoldersAndItems = function (data) {
  loadFolders();
  if (data != 'OK') {
    data = Array.isArray(data) ? data.join('
') : data;
    notify(data);
  }
};

var hideNavAndShowEditor = function (data) {
  $('#nav-buttons > ul').addClass('hidden');
  $('#content').html(data);
}

function loadFolders() {
  performLfmRequest('folders', {}, 'html')
    .done(function (data) {
      $('#tree').html(data);
      loadItems();
    });
}

function loadItems() {
  performLfmRequest('jsonitems', {show_list: show_list, sort_type: sort_type}, 'html')
    .done(function (data) {
      var response = JSON.parse(data);
      $('#content').html(response.html);
      $('#nav-buttons > ul').removeClass('hidden');
      $('#working_dir').val(response.working_dir);
      $('#current_dir').text(response.working_dir);
      console.log('Current working_dir : ' + $('#working_dir').val());
      if (getPreviousDir() == '') {
        $('#to-previous').addClass('hide');
      } else {
        $('#to-previous').removeClass('hide');
      }
      setOpenFolders();
    });
}

function createFolder(folder_name) {
  performLfmRequest('newfolder', {name: folder_name})
    .done(refreshFoldersAndItems);
}

function rename(item_name) {
  bootbox.prompt({
    title: lang['message-rename'],
    value: item_name,
    callback: function (result) {
      if (result == null) return;
      performLfmRequest('rename', {
        file: item_name,
        new_name: result
      }).done(refreshFoldersAndItems);
    }
  });
}

function trash(item_name) {
  bootbox.confirm(lang['message-delete'], function (result) {
    if (result == true) {
      performLfmRequest('delete', {items: item_name})
        .done(refreshFoldersAndItems);
    }
  });
}

function cropImage(image_name) {
  performLfmRequest('crop', {img: image_name})
    .done(hideNavAndShowEditor);
}

function resizeImage(image_name) {
  performLfmRequest('resize', {img: image_name})
    .done(hideNavAndShowEditor);
}

function download(file_name) {
  var data = defaultParameters();
  data['file'] = file_name;
  location.href = lfm_route + '/download?' + $.param(data);
}

// ==================================
// ==  Ckeditor, Bootbox, preview  ==
// ==================================

function useFile(file_url) {

  function getUrlParam(paramName) {
    var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
    var match = window.location.search.match(reParam);
    return ( match && match.length > 1 ) ? match[1] : null;
  }

  function useTinymce3(url) {
    var win = tinyMCEPopup.getWindowArg("window");
    win.document.getElementById(tinyMCEPopup.getWindowArg("input")).value = url;
    if (typeof(win.ImageDialog) != "undefined") {
      // Update image dimensions
      if (win.ImageDialog.getImageData) {
        win.ImageDialog.getImageData();
      }

      // Preview if necessary
      if (win.ImageDialog.showPreviewImage) {
        win.ImageDialog.showPreviewImage(url);
      }
    }
    tinyMCEPopup.close();
  }

  function useTinymce4AndColorbox(url, field_name) {
    parent.document.getElementById(field_name).value = url;

    if(typeof parent.tinyMCE !== "undefined") {
      parent.tinyMCE.activeEditor.windowManager.close();
    }
    if(typeof parent.$.fn.colorbox !== "undefined") {
      parent.$.fn.colorbox.close();
    }
  }

  function useCkeditor3(url) {
    if (window.opener) {
      // Popup
      window.opener.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
    } else {
      // Modal (in iframe)
      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorCleanUpFuncNum'));
    }
  }

  function useFckeditor2(url) {
    var p = url;
    var w = data['Properties']['Width'];
    var h = data['Properties']['Height'];
    window.opener.SetUrl(p,w,h);
  }

  var url = file_url;
  var field_name = getUrlParam('field_name');
  var is_ckeditor = getUrlParam('CKEditor');
  var is_fcke = typeof data != 'undefined' && data['Properties']['Width'] != '';
  var file_path = url.replace(route_prefix, '');

  if (window.opener || window.tinyMCEPopup || field_name || getUrlParam('CKEditorCleanUpFuncNum') || is_ckeditor) {
    if (window.tinyMCEPopup) { // use TinyMCE > 3.0 integration method
      useTinymce3(url);
    } else if (field_name) {   // tinymce 4 and colorbox
      useTinymce4AndColorbox(url, field_name);
    } else if(is_ckeditor) {   // use CKEditor 3.0 + integration method
      useCkeditor3(url);
    } else if (is_fcke) {      // use FCKEditor 2.0 integration method
      useFckeditor2(url);
    } else {                   // standalone button or other situations
      window.opener.SetUrl(url, file_path);
    }

    if (window.opener) {
      window.close();
    }
  } else {
    // No editor found, open/download file using browser's default method
    window.open(url);
  }
}
//end useFile

function defaultParameters() {
  return {
    working_dir: $('#working_dir').val(),
    type: $('#type').val()
  };
}

function notImp() {
  bootbox.alert('Not yet implemented!');;
}

function notify(message) {
  bootbox.alert(message);
}

function fileView(file_url, timestamp) {
  var rnd = makeRandom();
  bootbox.dialog({
    title: lang['title-view'],
    message: $('')
      .addClass('img img-responsive center-block')
      .attr('src', file_url + '?timestamp=' + timestamp),
    size: 'large',
    onEscape: true,
    backdrop: true
  });
}

function makeRandom() {
  var text = '';
  var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (var i = 0; i < 20; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}
<|endoftext|>


<commit_before>/**
 * Represents Buffer API error.
 */
class BufferError extends Error {

	/**
	 * Constructs Buffer API error.
	 * @param {number} httpStatusCode HTTP status code
	 * @param {number} code Error code
	 * @param {string} message Error description
	 */
	constructor(httpStatusCode, code, message) {
		super(message);

		this.httpStatusCode = httpStatusCode;
		this.code = code;
		this.message = message;
	}
}

module.exports = BufferError;
<commit_msg>Add helper methods to error object for most common errors<commit_after>/**
 * Represents Buffer API error.
 */
class BufferError extends Error {

	/**
	 * Constructs Buffer API error.
	 * @param {number} httpStatusCode HTTP status code
	 * @param {number} code Error code
	 * @param {string} message Error description
	 */
	constructor(httpStatusCode, code, message) {
		super(message);

		this.httpStatusCode = httpStatusCode;
		this.code = code;
		this.message = message;
	}

	/**
	 * Checks if unauthorized error.
	 * @return {boolean}
	 */
	isUnauthorized() {
		return (this.code === 401
			&& this.httpStatusCode === 401);
	}

	/**
	 * Checks if permission denied error.
	 * @return {boolean}
	 */
	isPermissionDenied() {
		return (this.code === 403
			&& this.httpStatusCode === 403);
	}

	/**
	 * Checks if endpoint not found error.
	 * @return {boolean}
	 */
	isEndpointNotFound() {
		return (this.code === 404
			&& this.httpStatusCode === 404);
	}

	/**
	 * Checks if method not allowed error.
	 * @return {boolean}
	 */
	isMethodNotAllowed() {
		return (this.code === 405
			&& this.httpStatusCode === 405);
	}

	/**
	 * Checks if too many requests error.
	 * @return {boolean}
	 */
	isTooManyRequests() {
		return (this.code === 429
			&& this.httpStatusCode === 429);
	}

	/**
	 * Checks if unknown error.
	 * @return {boolean}
	 */
	isUnknown() {
		return (this.code === 1000
			&& this.httpStatusCode === 500);
	}
}

module.exports = BufferError;
<|endoftext|>


<commit_before>angular.module( 'angularUtils.filters.ordinalDate', [] )

    .filter('ordinalDate', ['$filter', function($filter) {

        var getOrdinalSuffix = function(number) {
            var suffixes = ["'th'", "'st'", "'nd'", "'rd'"];
            var relevantDigits = (number < 30) ? number % 20 : number % 30;
            return "d" + ((relevantDigits <= 3) ? suffixes[relevantDigits] : suffixes[0]);
        };

        return function(timestamp, format) {
            var regex = /d+((?!\w*(?=')))|d$/g;
            var date = new Date(timestamp);
            var dayOfMonth = date.getDate();
            var suffix = getOrdinalSuffix(dayOfMonth);

            format = format.replace(regex, (match) => {
                return match === "d" ? suffix : match;
            });
            return $filter('date')(date, format);
        };
    }]);<commit_msg>ordinalDate: replace arrow function with anonymous functions.<commit_after>angular.module( 'angularUtils.filters.ordinalDate', [] )

    .filter('ordinalDate', ['$filter', function($filter) {

        var getOrdinalSuffix = function(number) {
            var suffixes = ["'th'", "'st'", "'nd'", "'rd'"];
            var relevantDigits = (number < 30) ? number % 20 : number % 30;
            return "d" + ((relevantDigits <= 3) ? suffixes[relevantDigits] : suffixes[0]);
        };

        return function(timestamp, format) {
            var regex = /d+((?!\w*(?=')))|d$/g;
            var date = new Date(timestamp);
            var dayOfMonth = date.getDate();
            var suffix = getOrdinalSuffix(dayOfMonth);

            format = format.replace(regex, function (match) {
                return match === "d" ? suffix : match;
            });
            return $filter('date')(date, format);
        };
    }]);<|endoftext|>


<commit_before>Travis.Views.Jobs = Backbone.View.extend({
  initialize: function(args) {
    _.bindAll(this, 'element', 'bind', 'unbind', 'render', 'renderItems', 'renderItem', 'jobAdded', 'jobRemoved', 'updateEmpty');

    this.jobs = args.app.jobs;
    this.templates = {
      list: args.app.templates['jobs/list'],
      item: args.app.templates['jobs/_item']
    }
  },
  element: function() {
    return $('#jobs');
  },
  bind: function() {
    Backbone.Events.bind.apply(this, arguments);
    this.jobs.bind('add', this.jobAdded);
    this.jobs.bind('remove', this.jobRemoved);
  },
  unbind: function() {
    Backbone.Events.unbind.apply(this, arguments);
    if(this.jobs) {
      this.jobs.unbind('add', this.jobAdded);
      this.jobs.unbind('remove', this.jobRemoved);
    }
  },
  render: function() {
    this.bind();
    this.element().empty();
    this.element().append($(this.templates.list({ workers: [] })));
    $('.loading', this.element()).show();
    this.renderItems(this.jobs);
  },
  renderItems: function(jobs) {
    $('.loading', this.element).hide();
    this.updateEmpty();
    _.each(jobs.models, function(job) { this.renderItem(job) }.bind(this));
    // Travis.Helpers.Util.updateTimes(this.element);
  },
  renderItem: function(job) {
    $('ul', this.element()).prepend($(this.templates.item(job.toJSON())));
  },
  jobAdded: function(job) {
    this.updateEmpty();
    this.renderItem(job);
  },
  jobRemoved: function(job) {
    this.updateEmpty();
    $('#job_' + job.get('meta_id'), this.element()).remove();
  },
  updateEmpty: function() {
    var element = $('.empty', this.element());
    this.jobs.length == 0 ? element.show() : element.hide();
  }
});
<commit_msg>fix mysterious #main element hiding bug<commit_after>Travis.Views.Jobs = Backbone.View.extend({
  initialize: function(args) {
    _.bindAll(this, 'element', 'bind', 'unbind', 'render', 'renderItems', 'renderItem', 'jobAdded', 'jobRemoved', 'updateEmpty');

    this.jobs = args.app.jobs;
    this.templates = {
      list: args.app.templates['jobs/list'],
      item: args.app.templates['jobs/_item']
    }
  },
  element: function() {
    return $('#jobs');
  },
  bind: function() {
    Backbone.Events.bind.apply(this, arguments);
    this.jobs.bind('add', this.jobAdded);
    this.jobs.bind('remove', this.jobRemoved);
  },
  unbind: function() {
    Backbone.Events.unbind.apply(this, arguments);
    if(this.jobs) {
      this.jobs.unbind('add', this.jobAdded);
      this.jobs.unbind('remove', this.jobRemoved);
    }
  },
  render: function() {
    this.bind();
    this.element().empty();
    this.element().append($(this.templates.list({ workers: [] })));
    $('.loading', this.element()).show();
    this.renderItems(this.jobs);
  },
  renderItems: function(jobs) {
    $('.loading', this.element()).hide();
    this.updateEmpty();
    _.each(jobs.models, function(job) { this.renderItem(job) }.bind(this));
    // Travis.Helpers.Util.updateTimes(this.element);
  },
  renderItem: function(job) {
    $('ul', this.element()).prepend($(this.templates.item(job.toJSON())));
  },
  jobAdded: function(job) {
    this.updateEmpty();
    this.renderItem(job);
  },
  jobRemoved: function(job) {
    this.updateEmpty();
    $('#job_' + job.get('meta_id'), this.element()).remove();
  },
  updateEmpty: function() {
    var element = $('.empty', this.element());
    this.jobs.length == 0 ? element.show() : element.hide();
  }
});
<|endoftext|>


<commit_before>import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { checkA11y } from 'storybook-addon-a11y';
import { withInfo } from '@storybook/addon-info';
import styles from '@sambego/storybook-styles';
import { IconAddMediumOutline, IconMagicMediumOutline } from '@teamleader/ui-icons';
import { Button, ButtonGroup, IconButton, Island, Box } from '../components';
import { baseStyles, centerStyles } from '../.storybook/styles';

storiesOf('Buttons', module)
  .addDecorator((story, context) => withInfo('')(story)(context))
  .addDecorator(checkA11y)
  .addDecorator(styles({ ...baseStyles, ...centerStyles }))
  .add('with text', () => (
    <ButtonGroup>
      <Button onClick={action('clicked button 1')}>Button 1</Button>
      <Button onClick={action('clicked button 2')}>Button 2</Button>
    </ButtonGroup>
  ))
  .add('with icon', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} />
      <Button icon={<IconMagicMediumOutline />} onClick={action('clicked button 2')} />
    </ButtonGroup>
  ))
  .add('with text and icon', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')}>
        Button
      </Button>
      <Button icon={<IconAddMediumOutline />} iconPlacement="right" onClick={action('clicked button 2')}>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('segmented', () => (
    <ButtonGroup segmented>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked')} />
      <Button onClick={action('clicked button 1')}>Button 1</Button>
      <Button onClick={action('clicked button 2')}>Button 2</Button>
    </ButtonGroup>
  ))
  .add('disabled', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} disabled/>
      <Button onClick={action('clicked button 2')} disabled>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('processing', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} processing />
      <Button onClick={action('clicked button 2')} processing>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('size', () => (
    <ButtonGroup>
      <Button onClick={action('clicked button small')} size="small">
        Button small
      </Button>
      <Button onClick={action('clicked button medium')} size="medium">
        Button medium
      </Button>
      <Button onClick={action('clicked button large')} size="large">
        Button large
      </Button>
    </ButtonGroup>
  ))
  .add('level', () => (
    <ButtonGroup>
      <Button onClick={action('clicked primary button')} level="primary">
        Primary button
      </Button>
      <Button onClick={action('clicked secondary button')} level="secondary">
        Secondary button
      </Button>
      <Button onClick={action('clicked ouline button')} level="outline">
        Outline button
      </Button>
      <Button onClick={action('clicked destructive button')} level="destructive">
        Destructive button
      </Button>
    </ButtonGroup>
  ))
  .add('inverse', () => (
    <Button inverse level="outline" onClick={action('clicked button outline')}>
      Button outline inverse
    </Button>
  ))
  .add('icon button', () => (
    <Box>
      <Island color="neutral" marginBottom={2}>
        <IconButton icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="mint" marginBottom={2}>
        <IconButton color="mint" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="violet" marginBottom={2}>
        <IconButton color="violet" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="ruby" marginBottom={2}>
        <IconButton color="ruby" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="gold" marginBottom={2}>
        <IconButton color="gold" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="aqua" marginBottom={2}>
        <IconButton color="aqua" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="neutral" marginBottom={2} style={{backgroundColor: '#2a3b4d'}}> {/* There is no teal island, so just changing the background with inline style */}
        <IconButton color="white" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
    </Box>
  ));
<commit_msg>Added extra IconButton variation to the stories<commit_after>import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { checkA11y } from 'storybook-addon-a11y';
import { withInfo } from '@storybook/addon-info';
import styles from '@sambego/storybook-styles';
import { IconAddMediumOutline, IconMagicMediumOutline } from '@teamleader/ui-icons';
import { Button, ButtonGroup, IconButton, Island, Box } from '../components';
import { baseStyles, centerStyles } from '../.storybook/styles';

storiesOf('Buttons', module)
  .addDecorator((story, context) => withInfo('')(story)(context))
  .addDecorator(checkA11y)
  .addDecorator(styles({ ...baseStyles, ...centerStyles }))
  .add('with text', () => (
    <ButtonGroup>
      <Button onClick={action('clicked button 1')}>Button 1</Button>
      <Button onClick={action('clicked button 2')}>Button 2</Button>
    </ButtonGroup>
  ))
  .add('with icon', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} />
      <Button icon={<IconMagicMediumOutline />} onClick={action('clicked button 2')} />
    </ButtonGroup>
  ))
  .add('with text and icon', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')}>
        Button
      </Button>
      <Button icon={<IconAddMediumOutline />} iconPlacement="right" onClick={action('clicked button 2')}>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('segmented', () => (
    <ButtonGroup segmented>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked')} />
      <Button onClick={action('clicked button 1')}>Button 1</Button>
      <Button onClick={action('clicked button 2')}>Button 2</Button>
    </ButtonGroup>
  ))
  .add('disabled', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} disabled/>
      <Button onClick={action('clicked button 2')} disabled>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('processing', () => (
    <ButtonGroup>
      <Button icon={<IconAddMediumOutline />} onClick={action('clicked button 1')} processing />
      <Button onClick={action('clicked button 2')} processing>
        Button
      </Button>
    </ButtonGroup>
  ))
  .add('size', () => (
    <ButtonGroup>
      <Button onClick={action('clicked button small')} size="small">
        Button small
      </Button>
      <Button onClick={action('clicked button medium')} size="medium">
        Button medium
      </Button>
      <Button onClick={action('clicked button large')} size="large">
        Button large
      </Button>
    </ButtonGroup>
  ))
  .add('level', () => (
    <ButtonGroup>
      <Button onClick={action('clicked primary button')} level="primary">
        Primary button
      </Button>
      <Button onClick={action('clicked secondary button')} level="secondary">
        Secondary button
      </Button>
      <Button onClick={action('clicked ouline button')} level="outline">
        Outline button
      </Button>
      <Button onClick={action('clicked destructive button')} level="destructive">
        Destructive button
      </Button>
    </ButtonGroup>
  ))
  .add('inverse', () => (
    <Button inverse level="outline" onClick={action('clicked button outline')}>
      Button outline inverse
    </Button>
  ))
  .add('icon button', () => (
    <Box>
      <Island color="white" marginBottom={2}>
        <IconButton icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="neutral" marginBottom={2}>
        <IconButton icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="mint" marginBottom={2}>
        <IconButton color="mint" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="violet" marginBottom={2}>
        <IconButton color="violet" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="ruby" marginBottom={2}>
        <IconButton color="ruby" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="gold" marginBottom={2}>
        <IconButton color="gold" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="aqua" marginBottom={2}>
        <IconButton color="aqua" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
      <Island color="neutral" marginBottom={2} style={{backgroundColor: '#2a3b4d'}}> {/* There is no teal island, so just changing the background with inline style */}
        <IconButton color="white" icon={<IconAddMediumOutline />} onClick={action('clicked icon button')} />
      </Island>
    </Box>
  ));
<|endoftext|>


<commit_before>function scanStatus()
{
	$('.status').each(function()
	{
		$(this).click(function()
		{
			$.getJSON(this.href + '?format=json&jsoncallback=?', function(data)
			{
				$('.status_links_' + data.id).each(function()
				{
					$(this).replaceWith(data.status);
				})
				scanStatus();
			})
			return false;
		})
	})
}

function scanIMDB(server)
{
	var query = '';
	var list = new Array();
	$("a[href*='title/tt']").each(function()
	{

		regexp = /www\.imdb\.com\/title\/tt(\d{7})\/$/;
		if (regexp.test(this.href))
		{
			var array = regexp.exec(this.href);
			var id = array[1];
			if (list[id] == null)
			{
				list[id] = new Array();
				query += id + ',';
			}
			list[id].push(this);
		}

	})

	if (query == '')
		return;

	var url = server + "status/list/movies/" + query + "?format=json&jsoncallback=?";
	$.getJSON(url, function(data)
	{
		$.each(data.status, function(id, status)
		{
			q = "a[href*='/title/tt" + id.split('_')[0] + "']";

			$(q).before(status);
		});

		scanStatus();
	});
}

$(document).ready(function()
{
	scanStatus();
})
<commit_msg>ADD support for main movie page on IMDB (status is next to title)<commit_after>function scanStatus()
{
	$('.status').each(function()
	{
		$(this).click(function()
		{
			$.getJSON(this.href + '?format=json&jsoncallback=?', function(data)
			{
				$('.status_links_' + data.id).each(function()
				{
					$(this).replaceWith(data.status);
				})
				scanStatus();
			})
			return false;
		})
	})
}

function scanIMDB(server)
{
	var query = '';
	var list = new Array();

	// Find every references to any movies
	$("a[href*='title/tt'], link[rel='canonical']").each(function()
	{
		regexp = /www\.imdb\.com\/title\/tt(\d{7})\/$/;
		if (regexp.test(this.href))
		{
			var array = regexp.exec(this.href);
			var id = array[1];
			if (list[id] == null)
			{
				list[id] = new Array();
				query += id + ',';
			}
			list[id].push(this);
		}

	})

	if (query == '')
		return;

	// Get statuses from server
	var url = server + "status/list/movies/" + query + "?format=json&jsoncallback=?";
	$.getJSON(url, function(data)
	{
		$.each(data.status, function(id, status)
		{
			// Add status beside main title if on the main page of movie
			if ($("link[rel='canonical'][href*=" + id.split('_')[0] + "]").length != 0)
				$("#tn15title>h1").before(status);
			// Add status on every links concerning that movie
			else
				$("a[href*='/title/tt" + id.split('_')[0] + "']").before(status);
		});

		scanStatus();
	});
}

$(document).ready(function()
{
	scanStatus();
})
<|endoftext|>


<commit_before>'use strict';

let fieldsHaveAllKeys = (mapKeys, fields) => {
  return mapKeys.reduce((hasAllKeys, key) => {
              return hasAllKeys && (key in fields);
            }, true);
};

let mapFirstName = (value) => {
  return value;
};

let mapLastName = (value) => {
  return value;
};

let mapEmail = (value) => {
  return value;
};

let mapPrimaryPhoneNumber = (value) => {
  return value;
};

let mapDateOfBirth = (value) => {
  return `01/01/${value}`;
};

let mapSchoolType = (value) => {
  return value;
};

let mapContactFirstName = (value) => {
  return value;
};

let mapContactLastName = (value) => {
  return value;
};

let mapBranch = (value) => {
  return value;
};

let mapAdditionalInfo = (value) => {
  return value;
};

let prepareNewMemberPayload = (fields) => {

  let map = {
    participantName: 'firstName',
    participantLastName: 'lastName',
    contactEmail: 'email',
    contactNumber: 'primaryPhoneNumber',
    participantBirthYear: 'dateOfBirth',
    schoolType: 'schoolType',
    contactName: 'contactFirstName',
    contactLastName : 'contactLastName',
    labSelection : 'branch',
    additionalInfo: 'additionalInfo'
  };

  if (!fieldsHaveAllKeys(Object.keys(map), fields)) {
    return {};
  }

  return {
    firstName: mapFirstName(fields.participantName),
    lastName: mapLastName(fields.participantLastName),
    email: mapEmail(fields.contactEmail),
    primaryPhoneNumber: mapPrimaryPhoneNumber(fields.contactNumber),
    dateOfBirth: mapDateOfBirth(fields.participantBirthYear),
    schoolType: mapSchoolType(fields.schoolType),
    contactFirstName: mapContactFirstName(fields.contactName),
    contactLastName: mapContactLastName(fields.contactLastName),
    branchId: mapBranch(fields.labSelection),
    additionalInfo: mapAdditionalInfo(fields.additionalInfo)
  };
};

export default {
    prepareNewMemberPayload: prepareNewMemberPayload
};
<commit_msg>Relax constraint so that missing fields are parsed as empty<commit_after>'use strict';

let fieldsHaveAllKeys = (mapKeys, fields) => {
  return mapKeys.reduce((hasAllKeys, key) => {
              return hasAllKeys && (key in fields);
            }, true);
};

let mapFirstName = (value) => {
  return value;
};

let mapLastName = (value) => {
  return value;
};

let mapEmail = (value) => {
  return value;
};

let mapPrimaryPhoneNumber = (value) => {
  return value;
};

let mapDateOfBirth = (value) => {
  return `01/01/${value}`;
};

let mapSchoolType = (value) => {
  return value;
};

let mapContactFirstName = (value) => {
  return value;
};

let mapContactLastName = (value) => {
  return value;
};

let mapBranch = (value) => {
  return value;
};

let mapAdditionalInfo = (value) => {
  return value;
};

let prepareNewMemberPayload = (fields) => {
  let map = {
    participantName: 'firstName',
    participantLastName: 'lastName',
    contactEmail: 'email',
    contactNumber: 'primaryPhoneNumber',
    participantBirthYear: 'dateOfBirth',
    schoolType: 'schoolType',
    contactName: 'contactFirstName',
    contactLastName : 'contactLastName',
    labSelection : 'branch',
    additionalInfo: 'additionalInfo'
  };

  return {
    firstName: mapFirstName(fields.participantName),
    lastName: mapLastName(fields.participantLastName),
    email: mapEmail(fields.contactEmail),
    primaryPhoneNumber: mapPrimaryPhoneNumber(fields.contactNumber),
    dateOfBirth: mapDateOfBirth(fields.participantBirthYear),
    schoolType: mapSchoolType(fields.schoolType),
    contactFirstName: mapContactFirstName(fields.contactName),
    contactLastName: mapContactLastName(fields.contactLastName),
    branchId: mapBranch(fields.labSelection),
    additionalInfo: mapAdditionalInfo(fields.additionalInfo)
  };
};

export default {
    prepareNewMemberPayload: prepareNewMemberPayload
};
<|endoftext|>


<commit_before>//     Zepto.js
//     (c) 2010-2014 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var _zid = 1, undefined,
      slice = Array.prototype.slice,
      isFunction = $.isFunction,
      isString = function(obj){ return typeof obj == 'string' },
      handlers = {},
      specialEvents={},
      focusinSupported = 'onfocusin' in window,
      focus = { focus: 'focusin', blur: 'focusout' },
      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }

  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'

  function zid(element) {
    return element._zid || (element._zid = _zid++)
  }
  function findHandlers(element, event, fn, selector) {
    event = parse(event)
    if (event.ns) var matcher = matcherFor(event.ns)
    return (handlers[zid(element)] || []).filter(function(handler) {
      return handler
        && (!event.e  || handler.e == event.e)
        && (!event.ns || matcher.test(handler.ns))
        && (!fn       || zid(handler.fn) === zid(fn))
        && (!selector || handler.sel == selector)
    })
  }
  function parse(event) {
    var parts = ('' + event).split('.')
    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
  }
  function matcherFor(ns) {
    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
  }

  function eventCapture(handler, captureSetting) {
    return handler.del &&
      (!focusinSupported && (handler.e in focus)) ||
      !!captureSetting
  }

  function realEvent(type) {
    return hover[type] || (focusinSupported && focus[type]) || type
  }

  function add(element, events, fn, data, selector, delegator, capture){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []))
    events.split(/\s/).forEach(function(event){
      if (event == 'ready') return $(document).ready(fn)
      var handler   = parse(event)
      handler.fn    = fn
      handler.sel   = selector
      // emulate mouseenter, mouseleave
      if (handler.e in hover) fn = function(e){
        var related = e.relatedTarget
        if (!related || (related !== this && !$.contains(this, related)))
          return handler.fn.apply(this, arguments)
      }
      handler.del   = delegator
      var callback  = delegator || fn
      handler.proxy = function(e){
        e = compatible(e)
        if (e.isImmediatePropagationStopped()) return
        e.data = data
        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
        if (result === false) e.preventDefault(), e.stopPropagation()
        return result
      }
      handler.i = set.length
      set.push(handler)
      if ('addEventListener' in element)
        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
    })
  }
  function remove(element, events, fn, selector, capture){
    var id = zid(element)
    ;(events || '').split(/\s/).forEach(function(event){
      findHandlers(element, event, fn, selector).forEach(function(handler){
        delete handlers[id][handler.i]
      if ('removeEventListener' in element)
        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
      })
    })
  }

  $.event = { add: add, remove: remove }

  $.proxy = function(fn, context) {
    var args = (2 in arguments) && slice.call(arguments, 2)
    if (isFunction(fn)) {
      var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
      proxyFn._zid = zid(fn)
      return proxyFn
    } else if (isString(context)) {
      if (args) {
        args.unshift(fn[context], fn)
        return $.proxy.apply(null, args)
      } else {
        return $.proxy(fn[context], fn)
      }
    } else {
      throw new TypeError("expected function")
    }
  }

  $.fn.bind = function(event, data, callback){
    return this.on(event, data, callback)
  }
  $.fn.unbind = function(event, callback){
    return this.off(event, callback)
  }
  $.fn.one = function(event, selector, data, callback){
    return this.on(event, selector, data, callback, 1)
  }

  var returnTrue = function(){return true},
      returnFalse = function(){return false},
      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/,
      eventMethods = {
        preventDefault: 'isDefaultPrevented',
        stopImmediatePropagation: 'isImmediatePropagationStopped',
        stopPropagation: 'isPropagationStopped'
      }

  function compatible(event, source) {
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          'returnValue' in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

  function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

  $.fn.delegate = function(selector, event, callback){
    return this.on(event, selector, callback)
  }
  $.fn.undelegate = function(selector, event, callback){
    return this.off(event, selector, callback)
  }

  $.fn.live = function(event, callback){
    $(document.body).delegate(this.selector, event, callback)
    return this
  }
  $.fn.die = function(event, callback){
    $(document.body).undelegate(this.selector, event, callback)
    return this
  }

  $.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    if (isFunction(data) || data === false)
      callback = data, data = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }

      if (selector) delegator = function(e){
        var evt, match = $(e.target).closest(selector, element).get(0)
        if (match && match !== element) {
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }

      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }
  $.fn.off = function(event, selector, callback){
    var $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.off(type, selector, fn)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = selector, selector = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(){
      remove(this, event, callback, selector)
    })
  }

  $.fn.trigger = function(event, args){
    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
    event._args = args
    return this.each(function(){
      // items in the collection might not be DOM elements
      if('dispatchEvent' in this) this.dispatchEvent(event)
      else $(this).triggerHandler(event, args)
    })
  }

  // triggers event handlers on current element just as if an event occurred,
  // doesn't trigger an actual event, doesn't bubble
  $.fn.triggerHandler = function(event, args){
    var e, result
    this.each(function(i, element){
      e = createProxy(isString(event) ? $.Event(event) : event)
      e._args = args
      e.target = element
      $.each(findHandlers(element, event.type || event), function(i, handler){
        result = handler.proxy(e)
        if (e.isImmediatePropagationStopped()) return false
      })
    })
    return result
  }

  // shortcut methods for `.bind(event, fn)` for each event type
  ;('focusin focusout load resize scroll unload click dblclick '+
  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
    $.fn[event] = function(callback) {
      return callback ?
        this.bind(event, callback) :
        this.trigger(event)
    }
  })

  ;['focus', 'blur'].forEach(function(name) {
    $.fn[name] = function(callback) {
      if (callback) this.bind(name, callback)
      else this.each(function(){
        try { this[name]() }
        catch(e) {}
      })
      return this
    }
  })

  $.Event = function(type, props) {
    if (!isString(type)) props = type, type = props.type
    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
    event.initEvent(type, bubbles, true)
    return compatible(event)
  }

})(Zepto)
<commit_msg>Actually focus & blur elements when these events are triggered<commit_after>//     Zepto.js
//     (c) 2010-2014 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var _zid = 1, undefined,
      slice = Array.prototype.slice,
      isFunction = $.isFunction,
      isString = function(obj){ return typeof obj == 'string' },
      handlers = {},
      specialEvents={},
      focusinSupported = 'onfocusin' in window,
      focus = { focus: 'focusin', blur: 'focusout' },
      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }

  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'

  function zid(element) {
    return element._zid || (element._zid = _zid++)
  }
  function findHandlers(element, event, fn, selector) {
    event = parse(event)
    if (event.ns) var matcher = matcherFor(event.ns)
    return (handlers[zid(element)] || []).filter(function(handler) {
      return handler
        && (!event.e  || handler.e == event.e)
        && (!event.ns || matcher.test(handler.ns))
        && (!fn       || zid(handler.fn) === zid(fn))
        && (!selector || handler.sel == selector)
    })
  }
  function parse(event) {
    var parts = ('' + event).split('.')
    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
  }
  function matcherFor(ns) {
    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
  }

  function eventCapture(handler, captureSetting) {
    return handler.del &&
      (!focusinSupported && (handler.e in focus)) ||
      !!captureSetting
  }

  function realEvent(type) {
    return hover[type] || (focusinSupported && focus[type]) || type
  }

  function add(element, events, fn, data, selector, delegator, capture){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []))
    events.split(/\s/).forEach(function(event){
      if (event == 'ready') return $(document).ready(fn)
      var handler   = parse(event)
      handler.fn    = fn
      handler.sel   = selector
      // emulate mouseenter, mouseleave
      if (handler.e in hover) fn = function(e){
        var related = e.relatedTarget
        if (!related || (related !== this && !$.contains(this, related)))
          return handler.fn.apply(this, arguments)
      }
      handler.del   = delegator
      var callback  = delegator || fn
      handler.proxy = function(e){
        e = compatible(e)
        if (e.isImmediatePropagationStopped()) return
        e.data = data
        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
        if (result === false) e.preventDefault(), e.stopPropagation()
        return result
      }
      handler.i = set.length
      set.push(handler)
      if ('addEventListener' in element)
        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
    })
  }
  function remove(element, events, fn, selector, capture){
    var id = zid(element)
    ;(events || '').split(/\s/).forEach(function(event){
      findHandlers(element, event, fn, selector).forEach(function(handler){
        delete handlers[id][handler.i]
      if ('removeEventListener' in element)
        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
      })
    })
  }

  $.event = { add: add, remove: remove }

  $.proxy = function(fn, context) {
    var args = (2 in arguments) && slice.call(arguments, 2)
    if (isFunction(fn)) {
      var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
      proxyFn._zid = zid(fn)
      return proxyFn
    } else if (isString(context)) {
      if (args) {
        args.unshift(fn[context], fn)
        return $.proxy.apply(null, args)
      } else {
        return $.proxy(fn[context], fn)
      }
    } else {
      throw new TypeError("expected function")
    }
  }

  $.fn.bind = function(event, data, callback){
    return this.on(event, data, callback)
  }
  $.fn.unbind = function(event, callback){
    return this.off(event, callback)
  }
  $.fn.one = function(event, selector, data, callback){
    return this.on(event, selector, data, callback, 1)
  }

  var returnTrue = function(){return true},
      returnFalse = function(){return false},
      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/,
      eventMethods = {
        preventDefault: 'isDefaultPrevented',
        stopImmediatePropagation: 'isImmediatePropagationStopped',
        stopPropagation: 'isPropagationStopped'
      }

  function compatible(event, source) {
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          'returnValue' in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

  function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

  $.fn.delegate = function(selector, event, callback){
    return this.on(event, selector, callback)
  }
  $.fn.undelegate = function(selector, event, callback){
    return this.off(event, selector, callback)
  }

  $.fn.live = function(event, callback){
    $(document.body).delegate(this.selector, event, callback)
    return this
  }
  $.fn.die = function(event, callback){
    $(document.body).undelegate(this.selector, event, callback)
    return this
  }

  $.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    if (isFunction(data) || data === false)
      callback = data, data = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }

      if (selector) delegator = function(e){
        var evt, match = $(e.target).closest(selector, element).get(0)
        if (match && match !== element) {
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }

      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }
  $.fn.off = function(event, selector, callback){
    var $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.off(type, selector, fn)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = selector, selector = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(){
      remove(this, event, callback, selector)
    })
  }

  $.fn.trigger = function(event, args){
    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
    event._args = args
    return this.each(function(){
      // handle focus(), blur() by calling them directly
      if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
      // items in the collection might not be DOM elements
      else if ('dispatchEvent' in this) this.dispatchEvent(event)
      else $(this).triggerHandler(event, args)
    })
  }

  // triggers event handlers on current element just as if an event occurred,
  // doesn't trigger an actual event, doesn't bubble
  $.fn.triggerHandler = function(event, args){
    var e, result
    this.each(function(i, element){
      e = createProxy(isString(event) ? $.Event(event) : event)
      e._args = args
      e.target = element
      $.each(findHandlers(element, event.type || event), function(i, handler){
        result = handler.proxy(e)
        if (e.isImmediatePropagationStopped()) return false
      })
    })
    return result
  }

  // shortcut methods for `.bind(event, fn)` for each event type
  ;('focusin focusout focus blur load resize scroll unload click dblclick '+
  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
    $.fn[event] = function(callback) {
      return callback ?
        this.bind(event, callback) :
        this.trigger(event)
    }
  })

  $.Event = function(type, props) {
    if (!isString(type)) props = type, type = props.type
    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
    event.initEvent(type, bubbles, true)
    return compatible(event)
  }

})(Zepto)
<|endoftext|>


<commit_before>var itemDetailView = {
    productID: null,
    item: null,
    prevPage: null,

    init: function () {
        $("#response").text("");
        this.productID = window.args.ProductID || window.args.pageKey || window.state.ProductID;
        this.prevPage = window.args.PreviousPage || window.state.PreviousPage;

        if (window.args.ProductID) {
            navigation.saveState(window.args);
        }

        var self = this;

        navigation.hit("/itemDetail/" + this.productID, function (response) {
            if (response && response.length) {
                self.item = jQuery.parseJSON(response)[0];
                //console.log(self.item);
                self.productName = self.item.Name;
                self.displayItem();
            } else {
                self.renderError("No inventory found");
            }
        })/*.fail(function (response) {
            self.renderError("Failed to load inventory: " + response);
        })*/;

        navigation.hit("/GetRunsByProduct/" + this.productID, function (response) {
           if (response && response.length) {
               self.runs = jQuery.parseJSON(response);
               //console.log(response);
               self.displayRuns();
           } else {
               self.renderError("No runs to display");
           }
        });
    },

    displayItem: function () {
        $("#response").text("");
        $("#product_name").text(this.item.Name);
        $("#details").append("
Total Available: " + this.item.TotalAvailable + "
" +
        "
Total Reserved: " + this.item.TotalReserved + "
" +
        "
Last run: " + this.item.MostRecent + "
");
    },

    displayRuns: function () {
        //this.runs.forEach(function (run) {
        // using for loop instead of forEach to reverse order
        for (var i = this.runs.length - 1; i > 0; --i) {
            var run = this.runs[i];
            $("#runs").append("
" + "RunID:" + run.RunID + "   Location:" + run.Location + "DateCreated:" + run.DateCreated + "   InitialQuantity:" + run.InitialQuantity + "   QuantityAvailable:" + run.QuantityAvailable + "   QuantityReserved:" + run.QuantityReserved + "
");
        }
    },

    renderError: function (error) {
        $("#response").text("Error: " + error);
    },

    add: function () {
        if (!this.productID || !this.item) return;
        navigation.go("AddInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    pull: function () {
        if (!this.productID || !this.item) return;
        navigation.go("PullInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            TotalQuantity: this.item.TotalAvailable,
            PreviousPage: "ItemDetailView.html"
        });
    },

    edit: function () {
        if (!this.productID || !this.item) return;
        navigation.go("EditProduct.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    qrCode: function () {
        if (!this.productID || !this.item) return;
        navigation.go("ShowQRCode.html", {
            Text: window.location.protocol + "//" + window.location.hostname + "/" + "ItemDetailView-" + this.productID,
            PreviousPage: "ItemDetailView.html"
        });
    },

    Delete: function() {
        var productID = window.args.ProductID;
        navigation.hit( "/DeleteProductByID/" + productID, function (resp) {
            var r = jQuery.parseJSON(resp);
            if (r[0].message == 'Success') {
                alert("Product " + $("#product_name").text() + " is deleted.");
                navigation.go("DisplayInventory.html",{ProductID: window.args.ProductID, PreviousPage:"ItemDetailView"});
            }
            else {
                alert(r[0].message);
                //$("#response").append("
" + "Deleting Product is only available to system admin.");
                //$("#response").append("
" + "Please go through the following checklist before deleting product.");
                //$("#response").append("
" + "1. Inventory of the product is 0.");
                //$("#response").append("
" + "2. De-associate all customers from the product");
            }
        })/*.fail(function (res) {
            $("#response").text( "Fail to delete product: Error --- " + res );
        })*/;
    },

    back: function () {
        if (this.prevPage)
            navigation.go(this.prevPage);
    }
};
<commit_msg>trimmed date to exclude time<commit_after>var itemDetailView = {
    productID: null,
    item: null,
    prevPage: null,

    init: function () {
        $("#response").text("");
        this.productID = window.args.ProductID || window.args.pageKey || window.state.ProductID;
        this.prevPage = window.args.PreviousPage || window.state.PreviousPage;

        if (window.args.ProductID) {
            navigation.saveState(window.args);
        }

        var self = this;

        navigation.hit("/itemDetail/" + this.productID, function (response) {
            if (response && response.length) {
                self.item = jQuery.parseJSON(response)[0];
                //console.log(self.item);
                self.productName = self.item.Name;
                self.displayItem();
            } else {
                self.renderError("No inventory found");
            }
        })/*.fail(function (response) {
            self.renderError("Failed to load inventory: " + response);
        })*/;

        navigation.hit("/GetRunsByProduct/" + this.productID, function (response) {
           if (response && response.length) {
               self.runs = jQuery.parseJSON(response);
               //console.log(response);
               self.displayRuns();
           } else {
               self.renderError("No runs to display");
           }
        });
    },

    displayItem: function () {
        $("#response").text("");
        $("#product_name").text(this.item.Name);
        $("#details").append("
Total Available: " + this.item.TotalAvailable + "
" +
        "
Total Reserved: " + this.item.TotalReserved + "
" +
        "
Last run: " + this.item.MostRecent + "
");
    },

    displayRuns: function () {
        //this.runs.forEach(function (run) {
        // using for loop instead of forEach to reverse order
        for (var i = this.runs.length - 1; i > 0; --i) {
            var run = this.runs[i];
            var dateRegex = /\d\d\d\d-\d\d-\d\d/;
            $("#runs").append("
" + "RunID:" + run.RunID + "Location:" + run.Location + "DateCreated:" + dateRegex.exec(run.DateCreated) + "
" + "InitialQuantity:" + run.InitialQuantity + "QuantityAvailable:" + run.QuantityAvailable + "QuantityReserved:" + run.QuantityReserved + "

" + "
");
        }
    },

    renderError: function (error) {
        $("#response").text("Error: " + error);
    },

    add: function () {
        if (!this.productID || !this.item) return;
        navigation.go("AddInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    pull: function () {
        if (!this.productID || !this.item) return;
        navigation.go("PullInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            TotalQuantity: this.item.TotalAvailable,
            PreviousPage: "ItemDetailView.html"
        });
    },

    edit: function () {
        if (!this.productID || !this.item) return;
        navigation.go("EditProduct.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    qrCode: function () {
        if (!this.productID || !this.item) return;
        navigation.go("ShowQRCode.html", {
            Text: window.location.protocol + "//" + window.location.hostname + "/" + "ItemDetailView-" + this.productID,
            PreviousPage: "ItemDetailView.html"
        });
    },

    Delete: function() {
        var productID = window.args.ProductID;
        navigation.hit( "/DeleteProductByID/" + productID, function (resp) {
            var r = jQuery.parseJSON(resp);
            if (r[0].message == 'Success') {
                alert("Product " + $("#product_name").text() + " is deleted.");
                navigation.go("DisplayInventory.html",{ProductID: window.args.ProductID, PreviousPage:"ItemDetailView"});
            }
            else {
                alert(r[0].message);
                //$("#response").append("
" + "Deleting Product is only available to system admin.");
                //$("#response").append("
" + "Please go through the following checklist before deleting product.");
                //$("#response").append("
" + "1. Inventory of the product is 0.");
                //$("#response").append("
" + "2. De-associate all customers from the product");
            }
        })/*.fail(function (res) {
            $("#response").text( "Fail to delete product: Error --- " + res );
        })*/;
    },

    back: function () {
        if (this.prevPage)
            navigation.go(this.prevPage);
    }
};
<|endoftext|>


<commit_before>var searchResults = [];

var search = function() {
    var searchTerms = $("#search-terms").val();
    $("#search-button").prop('disabled', true);

    $.ajax('/search/' + searchTerms).done(function(data) {
        searchResults = JSON.parse(data);
        $("#search-results").empty();
        $("#search-results-text").removeClass('hidden');
        $("#search-button").prop('disabled', false);

        for (var i = 0; i < searchResults.length; i++) {
            $.tmpl( "searchTemplate", {
                title: searchResults[i].title,
                artist: searchResults[i].artist,
                duration: searchResults[i].duration,
                searchID: i
            }).appendTo("#search-results");
        }
    }).fail(function() {
        $("#search-button").prop('disabled', false);
    });
};

var vote = function(id, vote) {
    var upArrow = $("#uparrow" + id);
    var downArrow = $("#downarrow" + id);
    if(vote > 0) {
        // is already upvoted: remove upvote
        if(upArrow.hasClass("active")) {
            $("#uparrow" + id).removeClass("active");
            vote = 0;
        // upvote
        } else {
            $("#uparrow" + id).addClass("active");
        }
        $("#downarrow" + id).removeClass("active");
    } else if(vote < 0) {
        // is already downvoted: remove downvote
        if(downArrow.hasClass("active")) {
            $("#downarrow" + id).removeClass("active");
            vote = 0;
        // downvote
        } else {
            $("#downarrow" + id).addClass("active");
        }
        $("#uparrow" + id).removeClass("active");
    }

    $.ajax({
        type: 'POST',
        url: '/vote/' + id,
        data: JSON.stringify({
            vote: vote,
            userID: $.cookie('userID')
        }),
        contentType: 'application/json',
        success: updateQueue
    });
};

var appendQueue = function(searchID) {
    $.ajax({
        type: 'POST',
        url: '/queue',
        data: JSON.stringify({
            song: searchResults[searchID],
            userID: $.cookie('userID')
        }),
        contentType: 'application/json',
        success: updateQueue
    });

    $("#search-results").empty();
    $("#search-results-text").addClass('hidden');
};

var pad = function(number, length) {
    var str = '' + number;

    while (str.length < length) {
        str = '0' + str;
    }

    return str;
}

var updateQueue = function() {
    console.log('updating');
    $.ajax('/queue').done(function(data) {
        var newQueue = JSON.parse(data);
        $("#queue").empty();

        // now playing
        if(newQueue.length)
            $.tmpl( "nowPlayingTemplate", newQueue[0]).appendTo("#queue");

        // rest of queue
        for(var i = 1; i < newQueue.length; i++) {
            $.tmpl( "queueTemplate", newQueue[i]).appendTo("#queue");
            var numUpVotes = Object.keys(newQueue[i].upVotes).length;
            var numDownVotes = Object.keys(newQueue[i].downVotes).length;
            var totalVotes = numUpVotes + numDownVotes;

            console.log('DEBUG: ' + numUpVotes + '/' + numDownVotes + ': ' + totalVotes);
            var weightedUp = 1 - (totalVotes - numUpVotes) / totalVotes;
            var weightedDown = 1 - (totalVotes - numDownVotes) / totalVotes;

            var r = 'f0', g = 'f0', b = 'f0';

            if(totalVotes) {
                if(numUpVotes > numDownVotes) {
                    r = pad(Number(255 - Math.round(40 * weightedUp)).toString(16), 2);
                    b = pad(Number(255 - Math.round(40 * weightedUp)).toString(16), 2);
                } else if(numUpVotes < numDownVotes) {
                    g = pad(Number(255 - Math.round(40 * weightedDown)).toString(16), 2);
                    b = pad(Number(255 - Math.round(40 * weightedDown)).toString(16), 2);
                }
            }

            var color = "#" + r + g + b;
            console.log(color);

            $("#" + newQueue[i].id).css('background-color', color);
        }

        var userID = $.cookie('userID');
        // update votes
        for(var i = 0; i < newQueue.length; i++) {
            if(newQueue[i].upVotes[userID]) {
                $("#uparrow" + newQueue[i].id).addClass("active");
            } else if(newQueue[i].downVotes[userID]) {
                $("#downarrow" + newQueue[i].id).addClass("active");
            }
        }
    });
};

$(document).ready(function() {
    // generate a user ID if there is not one yet
    if(!$.cookie('userID')) {
        var s4 = function() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        var guid = s4() + s4() + '-' + s4() + '-' + s4() + '-' +
                s4() + '-' + s4() + s4() + s4();
        $.cookie('userID', guid);
    }

    var nowPlayingMarkup = '
'
        + '
'
        + ''
        + '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "nowPlayingTemplate", nowPlayingMarkup );

    var queueMarkup = '
'
        + '
'
        + '
'
        + ''
        + '
'
        + '
'
        + ''
        + '
'
        + '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "queueTemplate", queueMarkup );

    var searchResultMarkup = '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "searchTemplate", searchResultMarkup );

    $("#search-terms").keyup(function(e) {
        if(e.keyCode === 13)
            search();
    });

    updateQueue();
    setInterval(updateQueue, 5000);
});
<commit_msg>client: remove a few debug prints<commit_after>var searchResults = [];

var search = function() {
    var searchTerms = $("#search-terms").val();
    $("#search-button").prop('disabled', true);

    $.ajax('/search/' + searchTerms).done(function(data) {
        searchResults = JSON.parse(data);
        $("#search-results").empty();
        $("#search-results-text").removeClass('hidden');
        $("#search-button").prop('disabled', false);

        for (var i = 0; i < searchResults.length; i++) {
            $.tmpl( "searchTemplate", {
                title: searchResults[i].title,
                artist: searchResults[i].artist,
                duration: searchResults[i].duration,
                searchID: i
            }).appendTo("#search-results");
        }
    }).fail(function() {
        $("#search-button").prop('disabled', false);
    });
};

var vote = function(id, vote) {
    var upArrow = $("#uparrow" + id);
    var downArrow = $("#downarrow" + id);
    if(vote > 0) {
        // is already upvoted: remove upvote
        if(upArrow.hasClass("active")) {
            $("#uparrow" + id).removeClass("active");
            vote = 0;
        // upvote
        } else {
            $("#uparrow" + id).addClass("active");
        }
        $("#downarrow" + id).removeClass("active");
    } else if(vote < 0) {
        // is already downvoted: remove downvote
        if(downArrow.hasClass("active")) {
            $("#downarrow" + id).removeClass("active");
            vote = 0;
        // downvote
        } else {
            $("#downarrow" + id).addClass("active");
        }
        $("#uparrow" + id).removeClass("active");
    }

    $.ajax({
        type: 'POST',
        url: '/vote/' + id,
        data: JSON.stringify({
            vote: vote,
            userID: $.cookie('userID')
        }),
        contentType: 'application/json',
        success: updateQueue
    });
};

var appendQueue = function(searchID) {
    $.ajax({
        type: 'POST',
        url: '/queue',
        data: JSON.stringify({
            song: searchResults[searchID],
            userID: $.cookie('userID')
        }),
        contentType: 'application/json',
        success: updateQueue
    });

    $("#search-results").empty();
    $("#search-results-text").addClass('hidden');
};

var pad = function(number, length) {
    var str = '' + number;

    while (str.length < length) {
        str = '0' + str;
    }

    return str;
}

var updateQueue = function() {
    console.log('updating');
    $.ajax('/queue').done(function(data) {
        var newQueue = JSON.parse(data);
        $("#queue").empty();

        // now playing
        if(newQueue.length)
            $.tmpl( "nowPlayingTemplate", newQueue[0]).appendTo("#queue");

        // rest of queue
        for(var i = 1; i < newQueue.length; i++) {
            $.tmpl( "queueTemplate", newQueue[i]).appendTo("#queue");
            var numUpVotes = Object.keys(newQueue[i].upVotes).length;
            var numDownVotes = Object.keys(newQueue[i].downVotes).length;
            var totalVotes = numUpVotes + numDownVotes;

            var weightedUp = 1 - (totalVotes - numUpVotes) / totalVotes;
            var weightedDown = 1 - (totalVotes - numDownVotes) / totalVotes;

            var r = 'f0', g = 'f0', b = 'f0';

            if(totalVotes) {
                if(numUpVotes > numDownVotes) {
                    r = pad(Number(255 - Math.round(40 * weightedUp)).toString(16), 2);
                    b = pad(Number(255 - Math.round(40 * weightedUp)).toString(16), 2);
                } else if(numUpVotes < numDownVotes) {
                    g = pad(Number(255 - Math.round(40 * weightedDown)).toString(16), 2);
                    b = pad(Number(255 - Math.round(40 * weightedDown)).toString(16), 2);
                }
            }

            var color = "#" + r + g + b;

            $("#" + newQueue[i].id).css('background-color', color);
        }

        var userID = $.cookie('userID');
        // update votes
        for(var i = 0; i < newQueue.length; i++) {
            if(newQueue[i].upVotes[userID]) {
                $("#uparrow" + newQueue[i].id).addClass("active");
            } else if(newQueue[i].downVotes[userID]) {
                $("#downarrow" + newQueue[i].id).addClass("active");
            }
        }
    });
};

$(document).ready(function() {
    // generate a user ID if there is not one yet
    if(!$.cookie('userID')) {
        var s4 = function() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        var guid = s4() + s4() + '-' + s4() + '-' + s4() + '-' +
                s4() + '-' + s4() + s4() + s4();
        $.cookie('userID', guid);
    }

    var nowPlayingMarkup = '
'
        + '
'
        + ''
        + '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "nowPlayingTemplate", nowPlayingMarkup );

    var queueMarkup = '
'
        + '
'
        + '
'
        + ''
        + '
'
        + '
'
        + ''
        + '
'
        + '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "queueTemplate", queueMarkup );

    var searchResultMarkup = '
'
        + '
${title}
'
        + '
${artist}
'
        + '
';

    $.template( "searchTemplate", searchResultMarkup );

    $("#search-terms").keyup(function(e) {
        if(e.keyCode === 13)
            search();
    });

    updateQueue();
    setInterval(updateQueue, 5000);
});
<|endoftext|>