You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ol...@apache.org on 2016/04/11 18:14:35 UTC

[21/51] [partial] ambari git commit: AMBARI-15679. Initial commit for LogSearch module (oleewre)

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.js b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.js
new file mode 100644
index 0000000..e65e8cd
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.js
@@ -0,0 +1,1045 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory(require("_"), require("jQuery"), require("Backbone"), require("Backgrid"));
+	else if(typeof define === 'function' && define.amd)
+		define(["underscore", "jquery", "backbone", "backgrid"], factory);
+	else if(typeof exports === 'object')
+		exports["Backgrid.Extension.ColumnManager"] = factory(require("_"), require("jQuery"), require("Backbone"), require("Backgrid"));
+	else
+		root["Backgrid.Extension.ColumnManager"] = factory(root["_"], root["jQuery"], root["Backbone"], root["Backgrid"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__, __WEBPACK_EXTERNAL_MODULE_4__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+	"use strict";
+
+	/**
+	 * A column manager for backgrid
+	 *
+	 * @module Backgrid.ColumnManager
+	 */
+	// Dependencies
+	var _ = __webpack_require__(1);
+	var $ = __webpack_require__(2);
+	var Backbone = __webpack_require__(3);
+	var Backgrid = __webpack_require__(4);
+
+	/**
+	 * Manages visibility of columns.
+	 *
+	 * @class Backgrid.Extension.ColumnManager ColumnManager
+	 * @constructor
+	 * @param {Backgrid.Columns} columns
+	 * @param {Object} [options]
+	 * @param {number} [options.initialColumnCount] Initial amount of columns to show. Default is null (All visible).
+	 * @param {boolean} [options.trackSize]
+	 * @param {boolean} [options.trackOrder]
+	 * @param {boolean} [options.trackVisibility]
+	 * @param {string} [options.stateChecking] can be "strict" or "loose".
+	 * @param {boolean} [options.saveState]
+	 * @param {string} [options.saveStateKey] Storage key. Must be unique for location. Can be left out if this plugin is only used in one place.
+	 * @param {string} [options.saveStateLocation] Can be "localStorage" (default) or "sessionStorage" (be aware, session stored values are lost when window is closed)
+	 * @param {boolean} [options.loadStateOnInit]
+	 * @param {Array} [state]
+	 */
+	Backgrid.Extension.ColumnManager = function (columns, options, state) {
+	  // Bind backbone events
+	  _.extend(this, Backbone.Events);
+
+	  // Save options and merge with defaults
+	  var defaults = {
+	    initialColumnsVisible: null,
+
+	    // State options
+	    trackSize: true,
+	    trackOrder: true,
+	    trackVisibility: true,
+	    stateChecking: "strict",
+	    saveState: false,
+	    saveStateKey: "",
+	    saveStateLocation: "localStorage",
+	    loadStateOnInit: false
+	  };
+	  this.options = _.extend({}, defaults, options);
+	  this.state = [];
+
+	  // Check if columns is instance of Backgrid.Columns
+	  if (columns instanceof Backgrid.Columns) {
+	    // Save columns
+	    this.columns = columns;
+
+	    // Add columnManager to columns (instance)
+	    columns.columnManager = this;
+	    this.addManagerToColumns();
+
+	    // Set state if provided
+	    var storedState = (this.options.loadStateOnInit) ? this.loadState() : false;
+	    if (state && this.checkStateValidity(state)) {
+	      this.setState(state, true);
+	    }
+	    else if (storedState) {
+	      this.setState(storedState, true);
+	    }
+	    else {
+	      // If no initial state is provided, adhere to initial column visibility settings
+	      this.setInitialColumnVisibility();
+
+	      // Set current state
+	      this.setState(this.getStateFromColumns());
+	    }
+
+	    // Listen to column events
+	    if (this.options.trackVisibility || this.options.trackSize || this.options.trackOrder) {
+	      //this.stateUpdateHandler = _.bind(this.stateUpdateHandler, this);
+	      var events = "" +
+	          ((this.options.trackVisibility) ? "change:renderable " : "") +
+	          ((this.options.trackSize) ? "resize " : "") +
+	          ((this.options.trackOrder) ? "ordered" : "");
+	      this.columns.on(events, _.bind(this.stateUpdateHandler, this));
+	    }
+	  }
+	  else {
+	    // Issue warning
+	    console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns");
+	  }
+	};
+
+	/**
+	 * Loops over all columns and sets the visibility according to provided options.
+	 *
+	 * @method setInitialColumnVisibility
+	 */
+	Backgrid.Extension.ColumnManager.prototype.setInitialColumnVisibility = function () {
+	  var self = this;
+
+	  // Loop columns and set renderable property according to settings
+	  var initialColumnsVisible = self.options.initialColumnsVisible;
+
+	  if (initialColumnsVisible) {
+	    self.columns.each(function (col, index) {
+	      col.set("renderable", (col.get("alwaysVisible")) ? true : index < initialColumnsVisible);
+	    });
+	  }
+	};
+
+	/**
+	 * Loops over all columns and adds the columnManager instance to VisibilityHeaderCell columns.
+	 *
+	 * @method addManagerToColumns
+	 */
+	Backgrid.Extension.ColumnManager.prototype.addManagerToColumns = function () {
+	  var self = this;
+
+	  self.columns.each(function (col) {
+	    // Look for header cell
+	    if (col.get("headerCell") === Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) {
+	      col.set("headerCell", col.get("headerCell").extend({
+	        columnManager: self
+	      }));
+	    }
+
+	    if (col.get("headerCell") instanceof Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) {
+	      col.get("headerCell").columnManager = self;
+	    }
+	  });
+	};
+
+	/**
+	 * Convenience function to retrieve a column either directly or by its id.
+	 * Returns false if no column is found.
+	 *
+	 * @method getColumn
+	 * @param {string|number|Backgrid.Column} col
+	 * @return {Backgrid.Column|boolean}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getColumn = function (col) {
+	  // If column is a string or number, try to find a column which has that ID
+	  if (_.isNumber(col) || _.isString(col)) {
+	    col = this.columns.get(col);
+	  }
+	  return (col instanceof Backgrid.Column) ? col : false;
+	};
+
+	/**
+	 * Hides a column
+	 *
+	 * @method hidecolumn
+	 * @param {string|number|Backgrid.Column} col
+	 */
+	Backgrid.Extension.ColumnManager.prototype.hideColumn = function (col) {
+	  // If column is a valid backgrid column, set the renderable property to false
+	  var column = this.getColumn(col);
+	  if (column) {
+	    column.set("renderable", false);
+	  }
+	};
+
+	/**
+	 * Shows a column
+	 *
+	 * @method showColumn
+	 * @param {string|number|Backgrid.Column} col
+	 */
+	Backgrid.Extension.ColumnManager.prototype.showColumn = function (col) {
+	  // If column is a valid backgrid column, set the renderable property to true
+	  var column = this.getColumn(col);
+	  if (column) {
+	    column.set("renderable", true);
+	  }
+	};
+
+	/**
+	 * Toggles a columns' visibility
+	 *
+	 * @method toggleColumnVisibility
+	 * @param {string|number|Backgrid.Column} col
+	 */
+	Backgrid.Extension.ColumnManager.prototype.toggleColumnVisibility = function (col) {
+	  // If column is a valid backgrid column, set the renderable property to true
+	  var column = this.getColumn(col);
+	  if (column) {
+	    if (column.get("renderable")) {
+	      this.hideColumn(column);
+	    }
+	    else {
+	      this.showColumn(column);
+	    }
+	  }
+	};
+
+	/**
+	 * Returns the managed column collection
+	 *
+	 * @method getColumnCollection
+	 * @return {Backgrid.Columns}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getColumnCollection = function () {
+	  return this.columns;
+	};
+
+	/**
+	 *
+	 * @method setState
+	 * @param {Array} state
+	 * @param {boolean} applyState
+	 * @return {boolean}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.setState = function (state, applyState) {
+	  var self = this;
+
+	  // Filter state
+	  _.filter(state, function(columnState) {
+	    if (!_.has(columnState, "name")) {
+	      return false;
+	    }
+
+	    var column = self.columns.findWhere({
+	      name: state.name
+	    });
+
+	    return typeof column !== "undefined";
+	  });
+
+	  // Check if state is valid
+	  if (self.checkStateValidity(state) && state !== self.state) {
+	    // Apply and save state
+	    self.state = state;
+	    self.trigger("state-changed", state);
+
+	    if (applyState) {
+	      return self.applyStateToColumns();
+	    }
+	    else {
+	      return self.saveState();
+	    }
+	  }
+	  return false;
+	};
+
+	/**
+	 * @method getState
+	 * @return {Array}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getState = function () {
+	  return this.state;
+	};
+
+	/**
+	 *
+	 * @method checkStateValidity
+	 * @return {boolean}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.checkStateValidity = function (state) {
+	  // Has to be array
+	  if (!_.isArray(state) && _.isEmpty(state)) {
+	    return false;
+	  }
+
+	  function checkValidityColumnState() {
+	    return _.every(state, function(column) {
+	      var valid = true;
+
+	      // We require a name key
+	      if (!_.has(column, "name")) {
+	        valid = false;
+	      }
+
+	      // If renderable is set, should be boolean
+	      if (_.has(column, "renderable")) {
+	        if (!_.isBoolean(column.renderable)) {
+	          valid = false;
+	        }
+	      }
+
+	      // If displayOrder is set, should be a number
+	      if (_.has(column, "displayOrder")) {
+	        if (!_.isNumber(column.displayOrder)) {
+	          valid = false;
+	        }
+	      }
+
+	      // If width is set, should be a number or a string
+	      if (_.has(column, "width")) {
+	        if (!_.isNumber(column.width) && !_.isString(column.width)) {
+	          valid = false;
+	        }
+	      }
+
+	      return valid;
+	    });
+	  }
+
+	  // Check if state is valid
+	  if (this.options.stateChecking === "loose") {
+	    // At least we require 'name' keys in every objec
+	    return checkValidityColumnState();
+	  }
+	  else {
+	    // Strict check
+	    // Requires same length and valid name keys.
+	    if (state.length !== this.columns.length && !checkValidityColumnState()) {
+	      return false;
+	    }
+
+	    var columnNameKeys = this.columns.map(function (column) {
+	      return column.get("name");
+	    });
+
+	    var newStateNameKeys = _.map(state, function (column) {
+	      return column.name;
+	    });
+
+	    return columnNameKeys.sort().toString() === newStateNameKeys.sort().toString();
+	  }
+	};
+
+
+	/**
+	 *
+	 * @method loadState
+	 * @return {boolean}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.loadState = function () {
+	  // Get state from storage
+	  var state = JSON.parse(this.getStorage().getItem(this.getStorageKey()));
+	  if (this.checkStateValidity(state)) {
+	    return state;
+	  }
+	  return false;
+	};
+
+	/**
+	 *
+	 * @method saveState
+	 * @param {boolean} [force] Override save settings.
+	 * @return {boolean}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.saveState = function (force) {
+	  if (this.options.saveState || force) {
+	    this.getStorage().setItem(this.getStorageKey(), JSON.stringify(this.state));
+	    this.trigger("state-saved");
+	    return true;
+	  }
+	  return false;
+	};
+
+	/**
+	 * @method getStorage
+	 * @return {boolean|Storage}
+	 * @private
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getStorage = function () {
+	  // Check if storage functionality is available
+	  if (typeof Storage !== "undefined") {
+	    return (this.options.saveStateLocation === "sessionStorage") ? sessionStorage : localStorage;
+	  }
+	  else {
+	    console.error("ColMrg: No storage support detected. State won't be saved.");
+	    return false;
+	  }
+	};
+
+	/**
+	 * @method getStorageKey
+	 * @return {string}
+	 * @private
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getStorageKey = function () {
+	  return (this.options.saveStateKey) ? "backgrid-colmgr-" + this.options.saveStateKey : "backgrid-colmgr";
+	};
+
+	/**
+	 * @method stateUpdateHandler
+	 * @return {boolean}
+	 * @private
+	 */
+	Backgrid.Extension.ColumnManager.prototype.stateUpdateHandler = function () {
+	  var state = this.getStateFromColumns();
+	  return this.setState(state);
+	};
+
+	/**
+	 * @method getStateFromColumn
+	 * @return {Array}
+	 */
+	Backgrid.Extension.ColumnManager.prototype.getStateFromColumns = function() {
+	  var self = this;
+
+	  // Map state from columns
+	  return this.columns.map(function(column) {
+	    var columnState = {
+	      name: column.get("name")
+	    };
+
+	    if (self.options.trackVisibility) {
+	      columnState.renderable = column.get("renderable");
+	    }
+	    if (self.options.trackOrder) {
+	      columnState.displayOrder = column.get("displayOrder");
+	    }
+	    if (self.options.trackSize) {
+	      columnState.width = column.get("width");
+	    }
+	    return columnState;
+	  });
+	};
+
+	/**
+	 * @method applyStateToColumns
+	 * @private
+	 */
+	Backgrid.Extension.ColumnManager.prototype.applyStateToColumns = function () {
+	  var self = this;
+
+	  // Loop state
+	  var ordered = false;
+	  _.each(this.state, function(columnState) {
+	    // Find column
+	    var column = self.columns.findWhere({
+	      name: columnState.name
+	    });
+
+	    if (_.has(columnState, "renderable")) {
+	      column.set("renderable", columnState.renderable);
+	    }
+	    if (_.has(columnState, "width")) {
+	      var oldWidth = column.get("width");
+	      column.set("width", columnState.width, {silent: true});
+	      if (oldWidth !== columnState.width) {
+	        column.trigger("resize", column, columnState.width, oldWidth);
+	      }
+	    }
+
+	    if (_.has(columnState, "displayOrder")) {
+	      if (columnState.displayOrder !== column.get("displayOrder")) {
+	        ordered = true;
+	      }
+	      column.set("displayOrder", columnState.displayOrder, {silent: true});
+	    }
+	  });
+
+	  if (ordered) {
+	    self.columns.sort();
+	    self.columns.trigger("ordered");
+	  }
+	};
+
+	//////////////////////////////////////////////
+	/////////////// UI Controls //////////////////
+	//////////////////////////////////////////////
+
+	/**
+	 * A dropdown item view
+	 *
+	 * @class DropDownItemView
+	 * @extends Backbone.View
+	 */
+	var DropDownItemView = Backbone.View.extend({
+	  className: "columnmanager-dropdown-item",
+	  tagName: "li",
+
+	  /**
+	   * @method initialize
+	   * @param {object} opts
+	   * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance.
+	   * @param {Backgrid.Column} opts.column A backgrid column.
+	   */
+	  initialize: function (opts) {
+	    this.columnManager = opts.columnManager;
+	    this.column = opts.column;
+	    this.template = opts.template;
+
+	    _.bindAll(this, "render", "toggleVisibility");
+	    this.column.on("change:renderable", this.render, this);
+	    this.el.addEventListener("click", this.toggleVisibility, true);
+	  },
+
+	  /**
+	   * @method render
+	   * @return {DropDownItemView}
+	   */
+	  render: function () {
+	    this.$el.empty();
+
+	    this.$el.append(this.template({
+	      label: this.column.get("label")
+	    }));
+
+	    if (this.column.get("renderable")) {
+	      this.$el.addClass((this.column.get("renderable")) ? "visible" : null);
+	    }
+	    else {
+	      this.$el.removeClass("visible");
+	    }
+
+	    return this;
+	  },
+
+	  /**
+	   * Toggles visibility of column.
+	   *
+	   * @method toggleVisibility
+	   * @param {object} e
+	   */
+	  toggleVisibility: function (e) {
+	    if (e) {
+	      this.stopPropagation(e);
+	    }
+	    this.columnManager.toggleColumnVisibility(this.column);
+	  },
+
+	  /**
+	   * Convenience function to stop event propagation.
+	   *
+	   * @method stopPropagation
+	   * @param {object} e
+	   * @private
+	   */
+	  stopPropagation: function (e) {
+	    e.stopPropagation();
+	    e.stopImmediatePropagation();
+	    e.preventDefault();
+	  }
+	});
+
+
+	/**
+	 * Dropdown view container.
+	 *
+	 * @class DropDownView
+	 * @extends Backbone.view
+	 */
+	var DropDownView = Backbone.View.extend({
+	  /**
+	   * @property className
+	   * @type String
+	   * @default "columnmanager-dropdown-container"
+	   */
+	  className: "columnmanager-dropdown-container",
+
+	  /**
+	   * @method initialize
+	   * @param {object} opts
+	   * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance.
+	   * @param {Backbone.View} opts.DropdownItemView View to be used for the items.
+	   * @param {Function} opts.dropdownItemTemplate
+	   */
+	  initialize: function (opts) {
+	    this.options = opts;
+	    this.columnManager = opts.columnManager;
+	    this.ItemView = (opts.DropdownItemView instanceof Backbone.View) ? opts.DropdownItemView : DropDownItemView;
+	    this.$dropdownButton = opts.$dropdownButton;
+
+	    this.on("dropdown:opened", this.open, this);
+	    this.on("dropdown:closed", this.close, this);
+	    this.columnManager.columns.on("add remove", this.render, this);
+	  },
+
+	  /**
+	   * @method render
+	   * @return {DropDownView}
+	   */
+	  render: function () {
+	    var view = this;
+	    view.$el.empty();
+
+	    // List all columns
+	    this.columnManager.columns.each(function (col) {
+	      if (!col.get("alwaysVisible")) {
+	        view.$el.append(new view.ItemView({
+	          column: col,
+	          columnManager: view.columnManager,
+	          template: view.options.dropdownItemTemplate
+	        }).render().el);
+	      }
+	    });
+
+	    return this;
+	  },
+
+	  /**
+	   * Opens the dropdown.
+	   *
+	   * @method open
+	   */
+	  open: function () {
+	    this.$el.addClass("open");
+
+	    // Get button
+	    var $button = this.$dropdownButton;
+
+	    // Align
+	    var align;
+	    if (this.options.align === "auto") {
+	      // Determine what alignment fits
+	      var viewPortWidth = document.body.clientWidth || document.body.clientWidth;
+	      align = (($button.offset().left + this.$el.outerWidth()) > viewPortWidth) ? "left" : "right";
+	    }
+	    else {
+	      align = (this.options.align === "left" || this.options.align === "right") ?
+	        (this.options.align === "right" ? "right" : "left") : "right";
+	    }
+
+	    var offset;
+	    if (align === "left") {
+	      // Align right by default
+	      offset = $button.offset().left + $button.outerWidth() - this.$el.outerWidth();
+	      this.$el.css("left", offset + "px");
+	    }
+	    else {
+	      offset = $button.offset().left;
+	      this.$el.css("left", offset + "px");
+	    }
+
+	    // Height position
+	    var offsetHeight = $button.offset().top + $button.outerHeight();
+	    this.$el.css("top", offsetHeight + "px");
+	  },
+
+	  /**
+	   * Closes the dropdown.
+	   *
+	   * @method close
+	   */
+	  close: function () {
+	    this.$el.removeClass("open");
+	  }
+	});
+
+	/**
+	 * UI control which manages visibility of columns.
+	 * Inspired by: https://github.com/kjantzer/backbonejs-dropdown-view.
+	 *
+	 * @class Backgrid.Extension.ColumnManagerVisibilityControl
+	 * @extends Backbone.View
+	 */
+	Backgrid.Extension.ColumnManagerVisibilityControl = Backbone.View.extend({
+	  /**
+	   * @property tagName
+	   * @type String
+	   * @default "div"
+	   */
+	  tagName: "div",
+
+	  /**
+	   * @property className
+	   * @type String
+	   * @default "columnmanager-visibilitycontrol"
+	   */
+	  className: "columnmanager-visibilitycontrol",
+
+	  /**
+	   * @property defaultEvents
+	   * @type Object
+	   */
+	  defaultEvents: {
+	    "click": "stopPropagation"
+	  },
+
+	  /**
+	   * @property defaultOpts
+	   * @type Object
+	   */
+	  defaultOpts: {
+	    width: null,
+	    closeOnEsc: true,
+	    closeOnClick: true,
+	    openOnInit: false,
+	    columnManager: null,
+
+	    // Button
+	    buttonTemplate: _.template("<button class='dropdown-button'>...</button>"),
+
+	    // Container
+	    DropdownView: DropDownView,
+	    dropdownAlign: "auto",
+
+	    // Item view
+	    DropdownItemView: DropDownItemView,
+	    dropdownItemTemplate: _.template("<span class='indicator'></span><span class='column-label'><%= label %></span>")
+	  },
+
+	  /**
+	   * @method initialize
+	   * @param {Object} opts
+	   * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance
+	   */
+	  initialize: function (opts) {
+	    this.options = _.extend({}, this.defaultOpts, opts);
+	    this.events = _.extend({}, this.defaultEvents, this.events || {});
+	    this.columnManager = opts.columnManager;
+
+	    // Option checking
+	    if (!this.columnManager instanceof Backgrid.Extension.ColumnManager) {
+	      console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns");
+	    }
+
+	    // Bind scope to events
+	    _.bindAll(this, "deferClose", "stopDeferClose", "closeOnEsc", "toggle", "render");
+
+	    // UI events
+	    document.body.addEventListener("click", this.deferClose, true);
+	    this.el.addEventListener("click", this.stopDeferClose, true);
+	    if (this.options.closeOnEsc) {
+	      document.body.addEventListener("keyup", this.closeOnEsc, false);
+	    }
+	    this.el.addEventListener("click", this.toggle, false);
+
+	    // Create elements
+	    this.setup();
+
+	    // Listen for dropdown view events indicating to open and/or close
+	    this.view.on("dropdown:close", this.close, this);
+	    this.view.on("dropdown:open", this.open, this);
+	  },
+
+	  /**
+	   * @method delayStart
+	   * @private
+	   */
+	  delayStart: function () {
+	    clearTimeout(this.closeTimeout);
+	    this.delayTimeout = setTimeout(this.open.bind(this), this.options.delay);
+	  },
+
+	  /**
+	   * @method delayEnd
+	   * @private
+	   */
+	  delayEnd: function () {
+	    clearTimeout(this.delayTimeout);
+	    this.closeTimeout = setTimeout(this.close.bind(this), 300);
+	  },
+
+	  /**
+	   * @method setup
+	   * @private
+	   */
+	  setup: function () {
+	    // Override element width
+	    if (this.options.width) {
+	      this.$el.width(this.options.width + "px");
+	    }
+
+	    // Create button element
+	    this.$dropdownButton = $(this.options.buttonTemplate());
+
+	    var viewOptions = {
+	      columnManager: this.columnManager,
+	      DropdownItemView: this.options.DropdownItemView,
+	      dropdownItemTemplate: this.options.dropdownItemTemplate,
+	      align: this.options.dropdownAlign,
+	      $dropdownButton: this.$dropdownButton
+	    };
+
+	    // Check if a different childView has been provided, if not, use default dropdown view
+	    this.view = (this.options.DropdownView instanceof Backbone.View) ?
+	      new this.options.DropdownView(viewOptions) :
+	      new DropDownView(viewOptions);
+	  },
+
+	  /**
+	   * @method setup
+	   */
+	  render: function () {
+	    this.$el.empty();
+
+	    // Render button
+	    this.$el.append(this.$dropdownButton);
+
+	    // Render inner view
+	    this.view.render(); // tell the inner view to render itself
+	    $(document.body).append(this.view.el);
+	    return this;
+	  },
+
+	  /**
+	   * Convenience function to stop event propagation
+	   *
+	   * @method stopPropagation
+	   * @param {object} e
+	   * @private
+	   */
+	  stopPropagation: function (e) {
+	    e.stopPropagation();
+	    e.stopImmediatePropagation();
+	    e.preventDefault();
+	  },
+
+	  /**
+	   * Toggle the dropdown visibility
+	   *
+	   * @method toggle
+	   * @param {object} [e]
+	   */
+	  toggle: function (e) {
+	    if (this.isOpen !== true) {
+	      this.open(e);
+	    }
+	    else {
+	      this.close(e);
+	    }
+	  },
+
+	  /**
+	   * Open the dropdown
+	   *
+	   * @method open
+	   * @param {object} [e]
+	   */
+	  open: function (e) {
+	    clearTimeout(this.closeTimeout);
+	    clearTimeout(this.deferCloseTimeout);
+
+	    if (e) {
+	      if (e.stopPropagation) {
+	        e.stopPropagation();
+	      }
+	      if (e.preventDefault) {
+	        e.preventDefault();
+	      }
+	      e.cancelBubble = true;
+	    }
+
+	    // Don't do anything if already open
+	    if (this.isOpen) {
+	      return;
+	    }
+
+	    this.isOpen = true;
+	    this.$el.addClass("open");
+	    this.trigger("dropdown:opened");
+
+	    // Notify child view
+	    this.view.trigger("dropdown:opened");
+	  },
+
+	  /**
+	   * Close the dropdown
+	   *
+	   * @method close
+	   * @param {object} [e]
+	   */
+	  close: function (e) {
+	    // Don't do anything if already closed
+	    if (!this.isOpen) {
+	      return;
+	    }
+
+	    this.isOpen = false;
+	    this.$el.removeClass("open");
+	    this.trigger("dropdown:closed");
+
+	    // Notify child view
+	    this.view.trigger("dropdown:closed");
+	  },
+
+	  /**
+	   * Close the dropdown on esc
+	   *
+	   * @method closeOnEsc
+	   * @param {object} e
+	   * @private
+	   */
+	  closeOnEsc: function (e) {
+	    if (e.which === 27) {
+	      this.deferClose();
+	    }
+	  },
+
+	  /**
+	   * @method deferClose
+	   * @private
+	   */
+	  deferClose: function () {
+	    this.deferCloseTimeout = setTimeout(this.close.bind(this), 0);
+	  },
+
+	  /**
+	   * @method stopDeferClose
+	   * @private
+	   */
+	  stopDeferClose: function (e) {
+	    clearTimeout(this.deferCloseTimeout);
+	  },
+
+	  /**
+	   * Clean up this control
+	   *
+	   * @method remove
+	   * @chainable
+	   */
+	  remove: function () {
+	    // Remove event listeners
+	    document.body.removeEventListener("click", this.deferClose);
+	    this.el.removeEventListener("click", this.stopDeferClose);
+	    if (this.options.closeOnEsc) {
+	      document.body.removeEventListener("keyup", this.closeOnEsc);
+	    }
+	    this.el.removeEventListener("click", this.toggle);
+
+	    // Remove DOM element
+	    $(this.view.el).remove();
+
+	    // Invoke original backbone methods
+	    return Backbone.View.prototype.remove.apply(this, arguments);
+	  }
+	});
+
+	/**
+	 * Backgrid HeaderCell containing ColumnManagerVisibilityControl
+	 *
+	 * @class Backgrid.Extension.ColumnVisibilityHeaderCell
+	 * @extends Backgrid.HeaderCell
+	 */
+
+	Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell = Backgrid.HeaderCell.extend({
+	  initialize: function (options) {
+	    Backgrid.HeaderCell.prototype.initialize.apply(this, arguments);
+
+	    // Add class
+	    this.$el.addClass(this.column.get("name"));
+	  },
+	  render: function () {
+	    this.$el.empty();
+
+	    // Add control
+	    var colVisibilityControl = this.colVisibilityControl = new Backgrid.Extension.ColumnManagerVisibilityControl({
+	      columnManager: this.columnManager
+	    });
+
+	    // Add to header
+	    this.$el.html(colVisibilityControl.render().el);
+
+	    this.delegateEvents();
+	    return this;
+	  },
+
+	  /**
+	   * Clean up this cell.
+	   *
+	   * @method remove
+	   * @chainable
+	   */
+	  remove: function () {
+	    // Remove UI control
+	    this.colVisibilityControl.remove();
+
+	    // Invoke super
+	    /*eslint no-underscore-dangle:0*/
+	    return Backgrid.HeaderCell.__super__.remove.apply(this, arguments);
+	  }
+	});
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports = __WEBPACK_EXTERNAL_MODULE_3__;
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports = __WEBPACK_EXTERNAL_MODULE_4__;
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.min.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.min.js b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.min.js
new file mode 100644
index 0000000..3312282
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-columnmanager/Backgrid.ColumnManager.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("Backbone"),require("Backgrid"),require("_"),require("jQuery")):"function"==typeof define&&define.amd?define(["Backbone","Backgrid","_","jQuery"],t):"object"==typeof exports?exports["Backgrid.Extension.ColumnManager"]=t(require("Backbone"),require("Backgrid"),require("_"),require("jQuery")):e["Backgrid.Extension.ColumnManager"]=t(e.Backbone,e.Backgrid,e._,e.jQuery)}(this,function(e,t,n,i){return function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";var i=n(3),o=n(4),s=n(1),r=n(2);r.Extension.ColumnManager=function(e,t,n){i.extend(this,s.Events);var o={initialColumnsVisible:null,trackSize:!0,trackOrder:!0,trackVisibility:!0,stateChecking:"strict",saveState:!1,saveStateKey:"",saveStateLocation:"localStorage",loadStateOnInit:!
 1};if(this.options=i.extend({},o,t),this.state=[],e instanceof r.Columns){this.columns=e,e.columnManager=this,this.addManagerToColumns();var a=this.options.loadStateOnInit?this.loadState():!1;if(n&&this.checkStateValidity(n)?this.setState(n,!0):a?this.setState(a,!0):(this.setInitialColumnVisibility(),this.setState(this.getStateFromColumns())),this.options.trackVisibility||this.options.trackSize||this.options.trackOrder){var l=""+(this.options.trackVisibility?"change:renderable ":"")+(this.options.trackSize?"resize ":"")+(this.options.trackOrder?"ordered":"");this.columns.on(l,i.bind(this.stateUpdateHandler,this))}}else console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns")},r.Extension.ColumnManager.prototype.setInitialColumnVisibility=function(){var e=this,t=e.options.initialColumnsVisible;t&&e.columns.each(function(e,n){e.set("renderable",e.get("alwaysVisible")?!0:t>n)})},r.Extension.ColumnManager.prototype.addManagerToColumns=function(){va
 r e=this;e.columns.each(function(t){t.get("headerCell")===r.Extension.ColumnManager.ColumnVisibilityHeaderCell&&t.set("headerCell",t.get("headerCell").extend({columnManager:e})),t.get("headerCell")instanceof r.Extension.ColumnManager.ColumnVisibilityHeaderCell&&(t.get("headerCell").columnManager=e)})},r.Extension.ColumnManager.prototype.getColumn=function(e){return(i.isNumber(e)||i.isString(e))&&(e=this.columns.get(e)),e instanceof r.Column?e:!1},r.Extension.ColumnManager.prototype.hideColumn=function(e){var t=this.getColumn(e);t&&t.set("renderable",!1)},r.Extension.ColumnManager.prototype.showColumn=function(e){var t=this.getColumn(e);t&&t.set("renderable",!0)},r.Extension.ColumnManager.prototype.toggleColumnVisibility=function(e){var t=this.getColumn(e);t&&(t.get("renderable")?this.hideColumn(t):this.showColumn(t))},r.Extension.ColumnManager.prototype.getColumnCollection=function(){return this.columns},r.Extension.ColumnManager.prototype.setState=function(e,t){var n=this;return i.
 filter(e,function(t){if(!i.has(t,"name"))return!1;var o=n.columns.findWhere({name:e.name});return"undefined"!=typeof o}),n.checkStateValidity(e)&&e!==n.state?(n.state=e,n.trigger("state-changed",e),t?n.applyStateToColumns():n.saveState()):!1},r.Extension.ColumnManager.prototype.getState=function(){return this.state},r.Extension.ColumnManager.prototype.checkStateValidity=function(e){function t(){return i.every(e,function(e){var t=!0;return i.has(e,"name")||(t=!1),i.has(e,"renderable")&&(i.isBoolean(e.renderable)||(t=!1)),i.has(e,"displayOrder")&&(i.isNumber(e.displayOrder)||(t=!1)),i.has(e,"width")&&(i.isNumber(e.width)||i.isString(e.width)||(t=!1)),t})}if(!i.isArray(e)&&i.isEmpty(e))return!1;if("loose"===this.options.stateChecking)return t();if(e.length!==this.columns.length&&!t())return!1;var n=this.columns.map(function(e){return e.get("name")}),o=i.map(e,function(e){return e.name});return n.sort().toString()===o.sort().toString()},r.Extension.ColumnManager.prototype.loadState=func
 tion(){var e=JSON.parse(this.getStorage().getItem(this.getStorageKey()));return this.checkStateValidity(e)?e:!1},r.Extension.ColumnManager.prototype.saveState=function(e){return this.options.saveState||e?(this.getStorage().setItem(this.getStorageKey(),JSON.stringify(this.state)),this.trigger("state-saved"),!0):!1},r.Extension.ColumnManager.prototype.getStorage=function(){return"undefined"!=typeof Storage?"sessionStorage"===this.options.saveStateLocation?sessionStorage:localStorage:(console.error("ColMrg: No storage support detected. State won't be saved."),!1)},r.Extension.ColumnManager.prototype.getStorageKey=function(){return this.options.saveStateKey?"backgrid-colmgr-"+this.options.saveStateKey:"backgrid-colmgr"},r.Extension.ColumnManager.prototype.stateUpdateHandler=function(){var e=this.getStateFromColumns();return this.setState(e)},r.Extension.ColumnManager.prototype.getStateFromColumns=function(){var e=this;return this.columns.map(function(t){var n={name:t.get("name")};return
  e.options.trackVisibility&&(n.renderable=t.get("renderable")),e.options.trackOrder&&(n.displayOrder=t.get("displayOrder")),e.options.trackSize&&(n.width=t.get("width")),n})},r.Extension.ColumnManager.prototype.applyStateToColumns=function(){var e=this,t=!1;i.each(this.state,function(n){var o=e.columns.findWhere({name:n.name});if(i.has(n,"renderable")&&o.set("renderable",n.renderable),i.has(n,"width")){var s=o.get("width");o.set("width",n.width,{silent:!0}),s!==n.width&&o.trigger("resize",o,n.width,s)}i.has(n,"displayOrder")&&(n.displayOrder!==o.get("displayOrder")&&(t=!0),o.set("displayOrder",n.displayOrder,{silent:!0}))}),t&&(e.columns.sort(),e.columns.trigger("ordered"))};var a=s.View.extend({className:"columnmanager-dropdown-item",tagName:"li",initialize:function(e){this.columnManager=e.columnManager,this.column=e.column,this.template=e.template,i.bindAll(this,"render","toggleVisibility"),this.column.on("change:renderable",this.render,this),this.el.addEventListener("click",this.
 toggleVisibility,!0)},render:function(){return this.$el.empty(),this.$el.append(this.template({label:this.column.get("label")})),this.column.get("renderable")?this.$el.addClass(this.column.get("renderable")?"visible":null):this.$el.removeClass("visible"),this},toggleVisibility:function(e){e&&this.stopPropagation(e),this.columnManager.toggleColumnVisibility(this.column)},stopPropagation:function(e){e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault()}}),l=s.View.extend({className:"columnmanager-dropdown-container",initialize:function(e){this.options=e,this.columnManager=e.columnManager,this.ItemView=e.DropdownItemView instanceof s.View?e.DropdownItemView:a,this.$dropdownButton=e.$dropdownButton,this.on("dropdown:opened",this.open,this),this.on("dropdown:closed",this.close,this),this.columnManager.columns.on("add remove",this.render,this)},render:function(){var e=this;return e.$el.empty(),this.columnManager.columns.each(function(t){t.get("alwaysVisible")||e.$el.append(n
 ew e.ItemView({column:t,columnManager:e.columnManager,template:e.options.dropdownItemTemplate}).render().el)}),this},open:function(){this.$el.addClass("open");var e,t=this.$dropdownButton;if("auto"===this.options.align){var n=document.body.clientWidth||document.body.clientWidth;e=t.offset().left+this.$el.outerWidth()>n?"left":"right"}else e="left"===this.options.align||"right"===this.options.align?"right"===this.options.align?"right":"left":"right";var i;"left"===e?(i=t.offset().left+t.outerWidth()-this.$el.outerWidth(),this.$el.css("left",i+"px")):(i=t.offset().left,this.$el.css("left",i+"px"));var o=t.offset().top+t.outerHeight();this.$el.css("top",o+"px")},close:function(){this.$el.removeClass("open")}});r.Extension.ColumnManagerVisibilityControl=s.View.extend({tagName:"div",className:"columnmanager-visibilitycontrol",defaultEvents:{click:"stopPropagation"},defaultOpts:{width:null,closeOnEsc:!0,closeOnClick:!0,openOnInit:!1,columnManager:null,buttonTemplate:i.template("<button cl
 ass='dropdown-button'>...</button>"),DropdownView:l,dropdownAlign:"auto",DropdownItemView:a,dropdownItemTemplate:i.template("<span class='indicator'></span><span class='column-label'><%= label %></span>")},initialize:function(e){this.options=i.extend({},this.defaultOpts,e),this.events=i.extend({},this.defaultEvents,this.events||{}),this.columnManager=e.columnManager,!this.columnManager instanceof r.Extension.ColumnManager&&console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns"),i.bindAll(this,"deferClose","stopDeferClose","closeOnEsc","toggle","render"),document.body.addEventListener("click",this.deferClose,!0),this.el.addEventListener("click",this.stopDeferClose,!0),this.options.closeOnEsc&&document.body.addEventListener("keyup",this.closeOnEsc,!1),this.el.addEventListener("click",this.toggle,!1),this.setup(),this.view.on("dropdown:close",this.close,this),this.view.on("dropdown:open",this.open,this)},delayStart:function(){clearTimeout(this.cl
 oseTimeout),this.delayTimeout=setTimeout(this.open.bind(this),this.options.delay)},delayEnd:function(){clearTimeout(this.delayTimeout),this.closeTimeout=setTimeout(this.close.bind(this),300)},setup:function(){this.options.width&&this.$el.width(this.options.width+"px"),this.$dropdownButton=o(this.options.buttonTemplate());var e={columnManager:this.columnManager,DropdownItemView:this.options.DropdownItemView,dropdownItemTemplate:this.options.dropdownItemTemplate,align:this.options.dropdownAlign,$dropdownButton:this.$dropdownButton};this.view=this.options.DropdownView instanceof s.View?new this.options.DropdownView(e):new l(e)},render:function(){return this.$el.empty(),this.$el.append(this.$dropdownButton),this.view.render(),o(document.body).append(this.view.el),this},stopPropagation:function(e){e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault()},toggle:function(e){this.isOpen!==!0?this.open(e):this.close(e)},open:function(e){clearTimeout(this.closeTimeout),clearTimeou
 t(this.deferCloseTimeout),e&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),e.cancelBubble=!0),this.isOpen||(this.isOpen=!0,this.$el.addClass("open"),this.trigger("dropdown:opened"),this.view.trigger("dropdown:opened"))},close:function(e){this.isOpen&&(this.isOpen=!1,this.$el.removeClass("open"),this.trigger("dropdown:closed"),this.view.trigger("dropdown:closed"))},closeOnEsc:function(e){27===e.which&&this.deferClose()},deferClose:function(){this.deferCloseTimeout=setTimeout(this.close.bind(this),0)},stopDeferClose:function(e){clearTimeout(this.deferCloseTimeout)},remove:function(){return document.body.removeEventListener("click",this.deferClose),this.el.removeEventListener("click",this.stopDeferClose),this.options.closeOnEsc&&document.body.removeEventListener("keyup",this.closeOnEsc),this.el.removeEventListener("click",this.toggle),o(this.view.el).remove(),s.View.prototype.remove.apply(this,arguments)}}),r.Extension.ColumnManager.ColumnVisibilityHeader
 Cell=r.HeaderCell.extend({initialize:function(e){r.HeaderCell.prototype.initialize.apply(this,arguments),this.$el.addClass(this.column.get("name"))},render:function(){this.$el.empty();var e=this.colVisibilityControl=new r.Extension.ColumnManagerVisibilityControl({columnManager:this.columnManager});return this.$el.html(e.render().el),this.delegateEvents(),this},remove:function(){return this.colVisibilityControl.remove(),r.HeaderCell.__super__.remove.apply(this,arguments)}})},function(t,n,i){t.exports=e},function(e,n,i){e.exports=t},function(e,t,i){e.exports=n},function(e,t,n){e.exports=i}])});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/css/backgrid-filter.css
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/css/backgrid-filter.css b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/css/backgrid-filter.css
new file mode 100644
index 0000000..4c689d0
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/css/backgrid-filter.css
@@ -0,0 +1,193 @@
+/*
+  backgrid-filter
+  http://github.com/wyuenho/backgrid
+
+  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+  Licensed under the MIT @license.
+*/
+
+/*
+  Search Icon CSS derived from:
+
+  PURE CSS GUI ICONS
+  by Nicolas Gallagher
+  - http://nicolasgallagher.com/pure-css-gui-icons/
+
+  http://nicolasgallagher.com
+  http://twitter.com/necolas
+
+  Created: 29 July 2010
+  Version: 1.0.1
+
+  Dual licensed under MIT and GNU GPLv2 (c) Nicolas Gallagher
+*/
+
+.backgrid-filter.form-search {
+  position: relative;
+  width: 248px;
+  height: 30px;
+  margin: 20px;
+}
+
+/*
+  Search Icon
+*/
+
+.backgrid-filter .search {
+  position: absolute;
+  top: 50%;
+  left: 6px;
+  z-index: 1000;
+  width: 10px;
+  height: 20px;
+  margin-top: -10px;
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+
+.backgrid-filter .search:before {
+  position: absolute;
+  top: 50%;
+  left: 0;
+  width: 6px;
+  height: 6px;
+  margin-top: -6px;
+  background: transparent;
+  border: 3px solid gray;
+  -webkit-border-radius: 12px;
+     -moz-border-radius: 12px;
+          border-radius: 12px;
+  content: "";
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+
+.backgrid-filter .search:after {
+  position: absolute;
+  top: 50%;
+  left: 10px;
+  width: 3px;
+  height: 7px;
+  margin-top: 2px;
+  background-color: gray;
+  content: "";
+  -webkit-transform: rotate(-45deg);
+     -moz-transform: rotate(-45deg);
+      -ms-transform: rotate(-45deg);
+       -o-transform: rotate(-45deg);
+          transform: rotate(-45deg);
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+
+/*
+  Clear button
+ */
+
+.backgrid-filter .clear {
+  position: absolute;
+  top: 50%;
+  right: 8px;
+  z-index: 1000;
+  width: 10px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: sans-serif;
+  font-size: 20px;
+  font-weight: bold;
+  line-height: 20px;
+  color: gray;
+  text-decoration: none;
+}
+
+.backgrid-filter input[type="search"] {
+  position: absolute;
+  display: inline-block;
+  width: 206px;
+  height: 20px;
+  padding: 4px 6px;
+  font-weight: normal;
+  color: #555;
+  vertical-align: middle;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+       -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+          transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+/*
+  Normalize the search input box, with code borrowed from normalize.css.
+
+  https://github.com/necolas/normalize.css/
+
+  Copyright (c) Nicolas Gallagher and Jonathan Neal, MIT @license.
+ */
+
+/*
+ * 1. Correct font family not being inherited in all browsers.
+ * 2. Correct font size not being inherited in all browsers.
+ * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
+ * 4. Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet.
+ */
+
+.backgrid-filter input {
+  margin: 0;
+  font-family: inherit;
+  font-size: 100%;
+  line-height: normal;
+}
+
+/*
+ * Re-set default cursor for disabled elements.
+ */
+
+.backgrid-filter input[disabled] {
+  cursor: default;
+}
+
+/*
+ * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
+ *    (include `-moz` to future-proof).
+ */
+
+.backgrid-filter input[type="search"] {
+  outline: none;
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: none;
+}
+
+/*
+ * Remove the default clear button on IE
+ */
+
+.backgrid-filter input[type="search"]::-ms-clear {
+  display: none;
+}
+
+/*
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+.backgrid-filter input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+.backgrid-filter input[type="search"] {
+  padding-right: 18px;
+  padding-left: 22px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.js b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.js
new file mode 100644
index 0000000..66b1c21
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.js
@@ -0,0 +1,487 @@
+/*
+  backgrid-filter
+  http://github.com/wyuenho/backgrid
+
+  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+  Licensed under the MIT @license.
+*/
+(function (root, factory) {
+
+  // CommonJS
+  if (typeof exports == "object") {
+    (function () {
+      var lunr;
+      try { lunr = require("lunr"); } catch (e) {}
+      module.exports = factory(require("underscore"),
+                               require("backbone"),
+                               require("backgrid"),
+                               lunr);
+    }());
+  }
+  // Browser
+  else {
+    factory(root._, root.Backbone, root.Backgrid, root.lunr);
+  }
+
+}(this, function (_, Backbone, Backgrid, lunr) {
+
+  "use strict";
+
+  /**
+     ServerSideFilter is a search form widget that submits a query to the server
+     for filtering the current collection.
+
+     @class Backgrid.Extension.ServerSideFilter
+  */
+  var ServerSideFilter = Backgrid.Extension.ServerSideFilter = Backbone.View.extend({
+
+    /** @property */
+    tagName: "form",
+
+    /** @property */
+    className: "backgrid-filter form-search",
+
+    /** @property {function(Object, ?Object=): string} template */
+    template: _.template('<span class="search">&nbsp;</span><input type="search" <% if (placeholder) { %> placeholder="<%- placeholder %>" <% } %> name="<%- name %>" /><a class="clear" data-backgrid-action="clear" href="#">&times;</a>', null, {variable: null}),
+
+    /** @property */
+    events: {
+      "keyup input[type=search]": "showClearButtonMaybe",
+      "click a[data-backgrid-action=clear]": "clear",
+      "submit": "search"
+    },
+
+    /** @property {string} [name='q'] Query key */
+    name: "q",
+
+    /**
+       @property {string} [placeholder] The HTML5 placeholder to appear beneath
+       the search box.
+    */
+    placeholder: null,
+
+    /**
+       @param {Object} options
+       @param {Backbone.Collection} options.collection
+       @param {string} [options.name]
+       @param {string} [options.placeholder]
+       @param {function(Object): string} [options.template]
+    */
+    initialize: function (options) {
+      ServerSideFilter.__super__.initialize.apply(this, arguments);
+      this.name = options.name || this.name;
+      this.placeholder = options.placeholder || this.placeholder;
+      this.template = options.template || this.template;
+
+      // Persist the query on pagination
+      var collection = this.collection, self = this;
+      if (Backbone.PageableCollection &&
+          collection instanceof Backbone.PageableCollection &&
+          collection.mode == "server") {
+        collection.queryParams[this.name] = function () {
+          return self.searchBox().val() || null;
+        };
+      }
+    },
+
+    /**
+       Event handler. Show the clear button when the search box has text, hide
+       it otherwise.
+     */
+    showClearButtonMaybe: function () {
+      var $clearButton = this.clearButton();
+      var searchTerms = this.searchBox().val();
+      if (searchTerms) $clearButton.show();
+      else $clearButton.hide();
+    },
+
+    /**
+       Returns the search input box.
+     */
+    searchBox: function () {
+      return this.$el.find("input[type=search]");
+    },
+
+    /**
+       Returns the clear button.
+     */
+    clearButton: function () {
+      return this.$el.find("a[data-backgrid-action=clear]");
+    },
+
+    /**
+       Upon search form submission, this event handler constructs a query
+       parameter object and pass it to Collection#fetch for server-side
+       filtering.
+
+       If the collection is a PageableCollection, searching will go back to the
+       first page.
+    */
+    search: function (e) {
+      if (e) e.preventDefault();
+
+      var data = {};
+      var query = this.searchBox().val();
+      if (query) data[this.name] = query;
+
+      var collection = this.collection;
+
+      // go back to the first page on search
+      if (Backbone.PageableCollection &&
+          collection instanceof Backbone.PageableCollection) {
+        collection.getFirstPage({data: data, reset: true, fetch: true});
+      }
+      else collection.fetch({data: data, reset: true});
+    },
+
+    /**
+       Event handler for the clear button. Clears the search box and refetch the
+       collection.
+
+       If the collection is a PageableCollection, clearing will go back to the
+       first page.
+    */
+    clear: function (e) {
+      if (e) e.preventDefault();
+      this.searchBox().val(null);
+      this.showClearButtonMaybe();
+
+      var collection = this.collection;
+
+      // go back to the first page on clear
+      if (Backbone.PageableCollection &&
+          collection instanceof Backbone.PageableCollection) {
+        collection.getFirstPage({reset: true, fetch: true});
+      }
+      else collection.fetch({reset: true});
+    },
+
+    /**
+       Renders a search form with a text box, optionally with a placeholder and
+       a preset value if supplied during initialization.
+    */
+    render: function () {
+      this.$el.empty().append(this.template({
+        name: this.name,
+        placeholder: this.placeholder,
+        value: this.value
+      }));
+      this.showClearButtonMaybe();
+      this.delegateEvents();
+      return this;
+    }
+
+  });
+
+  /**
+     ClientSideFilter is a search form widget that searches a collection for
+     model matches against a query on the client side. The exact matching
+     algorithm can be overriden by subclasses.
+
+     @class Backgrid.Extension.ClientSideFilter
+     @extends Backgrid.Extension.ServerSideFilter
+  */
+  var ClientSideFilter = Backgrid.Extension.ClientSideFilter = ServerSideFilter.extend({
+
+    /** @property */
+    events: _.extend({}, ServerSideFilter.prototype.events, {
+      "click a[data-backgrid-action=clear]": function (e) {
+        e.preventDefault();
+        this.clear();
+      },
+      "keydown input[type=search]": "search",
+      "submit": function (e) {
+        e.preventDefault();
+        this.search();
+      }
+    }),
+
+    /**
+       @property {?Array.<string>} [fields] A list of model field names to
+       search for matches. If null, all of the fields will be searched.
+    */
+    fields: null,
+
+    /**
+       @property [wait=149] The time in milliseconds to wait since the last
+       change to the search box's value before searching. This value can be
+       adjusted depending on how often the search box is used and how large the
+       search index is.
+    */
+    wait: 149,
+
+    /**
+       Debounces the #search and #clear methods and makes a copy of the given
+       collection for searching.
+
+       @param {Object} options
+       @param {Backbone.Collection} options.collection
+       @param {string} [options.placeholder]
+       @param {string} [options.fields]
+       @param {string} [options.wait=149]
+    */
+    initialize: function (options) {
+      ClientSideFilter.__super__.initialize.apply(this, arguments);
+
+      this.fields = options.fields || this.fields;
+      this.wait = options.wait || this.wait;
+
+      this._debounceMethods(["search", "clear"]);
+
+      var collection = this.collection = this.collection.fullCollection || this.collection;
+      var shadowCollection = this.shadowCollection = collection.clone();
+
+      this.listenTo(collection, "add", function (model, collection, options) {
+        shadowCollection.add(model, options);
+      });
+      this.listenTo(collection, "remove", function (model, collection, options) {
+        shadowCollection.remove(model, options);
+      });
+      this.listenTo(collection, "sort", function (col) {
+        if (!this.searchBox().val()) shadowCollection.reset(col.models);
+      });
+      this.listenTo(collection, "reset", function (col, options) {
+        options = _.extend({reindex: true}, options || {});
+        if (options.reindex && options.from == null && options.to == null) {
+          shadowCollection.reset(col.models);
+        }
+      });
+    },
+
+    _debounceMethods: function (methodNames) {
+      if (_.isString(methodNames)) methodNames = [methodNames];
+
+      this.undelegateEvents();
+
+      for (var i = 0, l = methodNames.length; i < l; i++) {
+        var methodName = methodNames[i];
+        var method = this[methodName];
+        this[methodName] = _.debounce(method, this.wait);
+      }
+
+      this.delegateEvents();
+    },
+
+    /**
+       Constructs a Javascript regular expression object for #makeMatcher.
+
+       This default implementation takes a query string and returns a Javascript
+       RegExp object that matches any of the words contained in the query string
+       case-insensitively. Override this method to return a different regular
+       expression matcher if this behavior is not desired.
+
+       @param {string} query The search query in the search box.
+       @return {RegExp} A RegExp object to match against model #fields.
+     */
+    makeRegExp: function (query) {
+      return new RegExp(query.trim().split(/\s+/).join("|"), "i");
+    },
+
+    /**
+       This default implementation takes a query string and returns a matcher
+       function that looks for matches in the model's #fields or all of its
+       fields if #fields is null, for any of the words in the query
+       case-insensitively using the regular expression object returned from
+       #makeRegExp.
+
+       Most of time, you'd want to override the regular expression used for
+       matching. If so, please refer to the #makeRegExp documentation,
+       otherwise, you can override this method to return a custom matching
+       function.
+
+       Subclasses overriding this method must take care to conform to the
+       signature of the matcher function. The matcher function is a function
+       that takes a model as paramter and returns true if the model matches a
+       search, or false otherwise.
+
+       In addition, when the matcher function is called, its context will be
+       bound to this ClientSideFilter object so it has access to the filter's
+       attributes and methods.
+
+       @param {string} query The search query in the search box.
+       @return {function(Backbone.Model):boolean} A matching function.
+    */
+    makeMatcher: function (query) {
+      var regexp = this.makeRegExp(query);
+      return function (model) {
+        var keys = this.fields || model.keys();
+        for (var i = 0, l = keys.length; i < l; i++) {
+          if (regexp.test(model.get(keys[i]) + "")) return true;
+        }
+        return false;
+      };
+    },
+
+    /**
+       Takes the query from the search box, constructs a matcher with it and
+       loops through collection looking for matches. Reset the given collection
+       when all the matches have been found.
+
+       If the collection is a PageableCollection, searching will go back to the
+       first page.
+    */
+    search: function () {
+      var matcher = _.bind(this.makeMatcher(this.searchBox().val()), this);
+      var col = this.collection;
+      if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
+      col.reset(this.shadowCollection.filter(matcher), {reindex: false});
+    },
+
+    /**
+       Clears the search box and reset the collection to its original.
+
+       If the collection is a PageableCollection, clearing will go back to the
+       first page.
+    */
+    clear: function () {
+      this.searchBox().val(null);
+      this.showClearButtonMaybe();
+      var col = this.collection;
+      if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
+      col.reset(this.shadowCollection.models, {reindex: false});
+    }
+
+  });
+
+  /**
+     LunrFilter is a ClientSideFilter that uses [lunrjs](http://lunrjs.com/) to
+     index the text fields of each model for a collection, and performs
+     full-text searching.
+
+     @class Backgrid.Extension.LunrFilter
+     @extends Backgrid.Extension.ClientSideFilter
+  */
+  var LunrFilter = Backgrid.Extension.LunrFilter = ClientSideFilter.extend({
+
+    /**
+       @property {string} [ref="id"]`lunrjs` document reference attribute name.
+    */
+    ref: "id",
+
+    /**
+       @property {Object} fields A hash of `lunrjs` index field names and boost
+       value. Unlike ClientSideFilter#fields, LunrFilter#fields is _required_ to
+       initialize the index.
+    */
+    fields: null,
+
+    /**
+       Indexes the underlying collection on construction. The index will refresh
+       when the underlying collection is reset. If any model is added, removed
+       or if any indexed fields of any models has changed, the index will be
+       updated.
+
+       @param {Object} options
+       @param {Backbone.Collection} options.collection
+       @param {string} [options.placeholder]
+       @param {string} [options.ref] `lunrjs` document reference attribute name.
+       @param {Object} [options.fields] A hash of `lunrjs` index field names and
+       boost value.
+       @param {number} [options.wait]
+    */
+    initialize: function (options) {
+      LunrFilter.__super__.initialize.apply(this, arguments);
+
+      this.ref = options.ref || this.ref;
+
+      var collection = this.collection = this.collection.fullCollection || this.collection;
+      this.listenTo(collection, "add", this.addToIndex);
+      this.listenTo(collection, "remove", this.removeFromIndex);
+      this.listenTo(collection, "reset", this.resetIndex);
+      this.listenTo(collection, "change", this.updateIndex);
+
+      this.resetIndex(collection);
+    },
+
+    /**
+       Reindex the collection. If `options.reindex` is `false`, this method is a
+       no-op.
+
+       @param {Backbone.Collection} collection
+       @param {Object} [options]
+       @param {boolean} [options.reindex=true]
+    */
+    resetIndex: function (collection, options) {
+      options = _.extend({reindex: true}, options || {});
+
+      if (options.reindex) {
+        var self = this;
+        this.index = lunr(function () {
+          _.each(self.fields, function (boost, fieldName) {
+            this.field(fieldName, boost);
+            this.ref(self.ref);
+          }, this);
+        });
+
+        collection.each(function (model) {
+          this.addToIndex(model);
+        }, this);
+      }
+    },
+
+    /**
+       Adds the given model to the index.
+
+       @param {Backbone.Model} model
+    */
+    addToIndex: function (model) {
+      var index = this.index;
+      var doc = model.toJSON();
+      if (index.documentStore.has(doc[this.ref])) index.update(doc);
+      else index.add(doc);
+    },
+
+    /**
+       Removes the given model from the index.
+
+       @param {Backbone.Model} model
+    */
+    removeFromIndex: function (model) {
+      var index = this.index;
+      var doc = model.toJSON();
+      if (index.documentStore.has(doc[this.ref])) index.remove(doc);
+    },
+
+    /**
+       Updates the index for the given model.
+
+       @param {Backbone.Model} model
+    */
+    updateIndex: function (model) {
+      var changed = model.changedAttributes();
+      if (changed && !_.isEmpty(_.intersection(_.keys(this.fields),
+                                               _.keys(changed)))) {
+        this.index.update(model.toJSON());
+      }
+    },
+
+    /**
+       Takes the query from the search box and performs a full-text search on
+       the client-side. The search result is returned by resetting the
+       underlying collection to the models after interrogating the index for the
+       query answer.
+
+       If the collection is a PageableCollection, searching will go back to the
+       first page.
+    */
+    search: function () {
+      var col = this.collection;
+      if (!this.searchBox().val()) {
+        col.reset(this.shadowCollection.models, {reindex: false});
+        return;
+      }
+
+      var searchResults = this.index.search(this.searchBox().val());
+      var models = [];
+      for (var i = 0; i < searchResults.length; i++) {
+        var result = searchResults[i];
+        models.push(this.shadowCollection.get(result.ref));
+      }
+
+      if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
+      col.reset(models, {reindex: false});
+    }
+
+  });
+
+}));

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.min.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.min.js b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.min.js
new file mode 100644
index 0000000..3d8edfb
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-filter/js/backgrid-filter.min.js
@@ -0,0 +1,8 @@
+/*
+  backgrid-filter
+  http://github.com/wyuenho/backgrid
+
+  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+  Licensed under the MIT @license.
+*/
+!function(a,b){"object"==typeof exports?!function(){var a;try{a=require("lunr")}catch(c){}module.exports=b(require("underscore"),require("backbone"),require("backgrid"),a)}():b(a._,a.Backbone,a.Backgrid,a.lunr)}(this,function(a,b,c,d){"use strict";var e=c.Extension.ServerSideFilter=b.View.extend({tagName:"form",className:"backgrid-filter form-search",template:a.template('<span class="search">&nbsp;</span><input type="search" <% if (placeholder) { %> placeholder="<%- placeholder %>" <% } %> name="<%- name %>" /><a class="clear" data-backgrid-action="clear" href="#">&times;</a>',null,{variable:null}),events:{"keyup input[type=search]":"showClearButtonMaybe","click a[data-backgrid-action=clear]":"clear",submit:"search"},name:"q",placeholder:null,initialize:function(a){e.__super__.initialize.apply(this,arguments),this.name=a.name||this.name,this.placeholder=a.placeholder||this.placeholder,this.template=a.template||this.template;var c=this.collection,d=this;b.PageableCollection&&c instan
 ceof b.PageableCollection&&"server"==c.mode&&(c.queryParams[this.name]=function(){return d.searchBox().val()||null})},showClearButtonMaybe:function(){var a=this.clearButton(),b=this.searchBox().val();b?a.show():a.hide()},searchBox:function(){return this.$el.find("input[type=search]")},clearButton:function(){return this.$el.find("a[data-backgrid-action=clear]")},search:function(a){a&&a.preventDefault();var c={},d=this.searchBox().val();d&&(c[this.name]=d);var e=this.collection;b.PageableCollection&&e instanceof b.PageableCollection?e.getFirstPage({data:c,reset:!0,fetch:!0}):e.fetch({data:c,reset:!0})},clear:function(a){a&&a.preventDefault(),this.searchBox().val(null),this.showClearButtonMaybe();var c=this.collection;b.PageableCollection&&c instanceof b.PageableCollection?c.getFirstPage({reset:!0,fetch:!0}):c.fetch({reset:!0})},render:function(){return this.$el.empty().append(this.template({name:this.name,placeholder:this.placeholder,value:this.value})),this.showClearButtonMaybe(),thi
 s.delegateEvents(),this}}),f=c.Extension.ClientSideFilter=e.extend({events:a.extend({},e.prototype.events,{"click a[data-backgrid-action=clear]":function(a){a.preventDefault(),this.clear()},"keydown input[type=search]":"search",submit:function(a){a.preventDefault(),this.search()}}),fields:null,wait:149,initialize:function(b){f.__super__.initialize.apply(this,arguments),this.fields=b.fields||this.fields,this.wait=b.wait||this.wait,this._debounceMethods(["search","clear"]);var c=this.collection=this.collection.fullCollection||this.collection,d=this.shadowCollection=c.clone();this.listenTo(c,"add",function(a,b,c){d.add(a,c)}),this.listenTo(c,"remove",function(a,b,c){d.remove(a,c)}),this.listenTo(c,"sort",function(a){this.searchBox().val()||d.reset(a.models)}),this.listenTo(c,"reset",function(b,c){c=a.extend({reindex:!0},c||{}),c.reindex&&null==c.from&&null==c.to&&d.reset(b.models)})},_debounceMethods:function(b){a.isString(b)&&(b=[b]),this.undelegateEvents();for(var c=0,d=b.length;d>c;
 c++){var e=b[c],f=this[e];this[e]=a.debounce(f,this.wait)}this.delegateEvents()},makeRegExp:function(a){return new RegExp(a.trim().split(/\s+/).join("|"),"i")},makeMatcher:function(a){var b=this.makeRegExp(a);return function(a){for(var c=this.fields||a.keys(),d=0,e=c.length;e>d;d++)if(b.test(a.get(c[d])+""))return!0;return!1}},search:function(){var b=a.bind(this.makeMatcher(this.searchBox().val()),this),c=this.collection;c.pageableCollection&&c.pageableCollection.getFirstPage({silent:!0}),c.reset(this.shadowCollection.filter(b),{reindex:!1})},clear:function(){this.searchBox().val(null),this.showClearButtonMaybe();var a=this.collection;a.pageableCollection&&a.pageableCollection.getFirstPage({silent:!0}),a.reset(this.shadowCollection.models,{reindex:!1})}}),g=c.Extension.LunrFilter=f.extend({ref:"id",fields:null,initialize:function(a){g.__super__.initialize.apply(this,arguments),this.ref=a.ref||this.ref;var b=this.collection=this.collection.fullCollection||this.collection;this.listenT
 o(b,"add",this.addToIndex),this.listenTo(b,"remove",this.removeFromIndex),this.listenTo(b,"reset",this.resetIndex),this.listenTo(b,"change",this.updateIndex),this.resetIndex(b)},resetIndex:function(b,c){if(c=a.extend({reindex:!0},c||{}),c.reindex){var e=this;this.index=d(function(){a.each(e.fields,function(a,b){this.field(b,a),this.ref(e.ref)},this)}),b.each(function(a){this.addToIndex(a)},this)}},addToIndex:function(a){var b=this.index,c=a.toJSON();b.documentStore.has(c[this.ref])?b.update(c):b.add(c)},removeFromIndex:function(a){var b=this.index,c=a.toJSON();b.documentStore.has(c[this.ref])&&b.remove(c)},updateIndex:function(b){var c=b.changedAttributes();c&&!a.isEmpty(a.intersection(a.keys(this.fields),a.keys(c)))&&this.index.update(b.toJSON())},search:function(){var a=this.collection;if(!this.searchBox().val())return void a.reset(this.shadowCollection.models,{reindex:!1});for(var b=this.index.search(this.searchBox().val()),c=[],d=0;d<b.length;d++){var e=b[d];c.push(this.shadowCo
 llection.get(e.ref))}a.pageableCollection&&a.pageableCollection.getFirstPage({silent:!0}),a.reset(c,{reindex:!1})}})});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/css/backgrid-paginator.css
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/css/backgrid-paginator.css b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/css/backgrid-paginator.css
new file mode 100644
index 0000000..20ebbd2
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/css/backgrid-paginator.css
@@ -0,0 +1,58 @@
+/*
+  backgrid-paginator
+  http://github.com/wyuenho/backgrid
+
+  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+  Licensed under the MIT license.
+*/
+
+.backgrid-paginator {
+  text-align: center;
+  border-top: none;
+  -webkit-border-radius: 0 0 4px 4px;
+     -moz-border-radius: 0 0 4px 4px;
+          border-radius: 0 0 4px 4px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.backgrid-paginator ul {
+  display: inline-block;
+  *display: inline;
+  margin: 5px 0;
+  *zoom: 1;
+}
+
+.backgrid-paginator ul > li {
+  display: inline;
+}
+
+.backgrid-paginator ul > li > a,
+.backgrid-paginator ul > li > span {
+  float: left;
+  width: 30px;
+  height: 30px;
+  padding: 0;
+  line-height: 30px;
+  text-decoration: none;
+}
+
+.backgrid-paginator ul > li > a:hover,
+.backgrid-paginator ul > .active > a,
+.backgrid-paginator ul > .active > span {
+  background-color: #f5f5f5;
+}
+
+.backgrid-paginator ul > .active > a,
+.backgrid-paginator ul > .active > span {
+  color: #999999;
+  cursor: default;
+}
+
+.backgrid-paginator ul > .disabled > span,
+.backgrid-paginator ul > .disabled > a,
+.backgrid-paginator ul > .disabled > a:hover {
+  color: #999999;
+  cursor: default;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39c85bb8/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/js/backgrid-paginator.js
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/js/backgrid-paginator.js b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/js/backgrid-paginator.js
new file mode 100644
index 0000000..a0b3af9
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/webapp/libs/bower/backgrid-paginator/js/backgrid-paginator.js
@@ -0,0 +1,427 @@
+/*
+  backgrid-paginator
+  http://github.com/wyuenho/backgrid
+
+  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+  Licensed under the MIT @license.
+*/
+(function (root, factory) {
+
+  // CommonJS
+  if (typeof exports == "object") {
+    module.exports = factory(require("underscore"),
+                             require("backbone"),
+                             require("backgrid"),
+                             require("backbone-pageable"));
+  }
+  // Browser
+  else {
+    factory(root._, root.Backbone, root.Backgrid);
+  }
+
+}(this, function (_, Backbone, Backgrid) {
+
+  "use strict";
+
+  /**
+     PageHandle is a class that renders the actual page handles and reacts to
+     click events for pagination.
+
+     This class acts in two modes - control or discrete page handle modes. If
+     one of the `is*` flags is `true`, an instance of this class is under
+     control page handle mode. Setting a `pageIndex` to an instance of this
+     class under control mode has no effect and the correct page index will
+     always be inferred from the `is*` flag. Only one of the `is*` flags should
+     be set to `true` at a time. For example, an instance of this class cannot
+     simultaneously be a rewind control and a fast forward control. A `label`
+     and a `title` template or a string are required to be passed to the
+     constuctor under this mode. If a `title` template is provided, it __MUST__
+     accept a parameter `label`. When the `label` is provided to the `title`
+     template function, its result will be used to render the generated anchor's
+     title attribute.
+
+     If all of the `is*` flags is set to `false`, which is the default, an
+     instance of this class will be in discrete page handle mode. An instance
+     under this mode requires the `pageIndex` to be passed from the constructor
+     as an option and it __MUST__ be a 0-based index of the list of page numbers
+     to render. The constuctor will normalize the base to the same base the
+     underlying PageableCollection collection instance uses. A `label` is not
+     required under this mode, which will default to the equivalent 1-based page
+     index calculated from `pageIndex` and the underlying PageableCollection
+     instance. A provided `label` will still be honored however. The `title`
+     parameter is also not required under this mode, in which case the default
+     `title` template will be used. You are encouraged to provide your own
+     `title` template however if you wish to localize the title strings.
+
+     If this page handle represents the current page, an `active` class will be
+     placed on the root list element.
+
+     If this page handle is at the border of the list of pages, a `disabled`
+     class will be placed on the root list element.
+
+     Only page handles that are neither `active` nor `disabled` will respond to
+     click events and triggers pagination.
+
+     @class Backgrid.Extension.PageHandle
+  */
+  var PageHandle = Backgrid.Extension.PageHandle = Backbone.View.extend({
+
+    /** @property */
+    tagName: "li",
+
+    /** @property */
+    events: {
+      "click a": "changePage"
+    },
+
+    /**
+       @property {string|function(Object.<string, string>): string} title
+       The title to use for the `title` attribute of the generated page handle
+       anchor elements. It can be a string or an Underscore template function
+       that takes a mandatory `label` parameter.
+    */
+    title: _.template('Page <%- label %>', null, {variable: null}),
+
+    /**
+       @property {boolean} isRewind Whether this handle represents a rewind
+       control
+    */
+    isRewind: false,
+
+    /**
+       @property {boolean} isBack Whether this handle represents a back
+       control
+    */
+    isBack: false,
+
+    /**
+       @property {boolean} isForward Whether this handle represents a forward
+       control
+    */
+    isForward: false,
+
+    /**
+       @property {boolean} isFastForward Whether this handle represents a fast
+       forward control
+    */
+    isFastForward: false,
+
+    /**
+       Initializer.
+
+       @param {Object} options
+       @param {Backbone.Collection} options.collection
+       @param {number} pageIndex 0-based index of the page number this handle
+       handles. This parameter will be normalized to the base the underlying
+       PageableCollection uses.
+       @param {string} [options.label] If provided it is used to render the
+       anchor text, otherwise the normalized pageIndex will be used
+       instead. Required if any of the `is*` flags is set to `true`.
+       @param {string} [options.title]
+       @param {boolean} [options.isRewind=false]
+       @param {boolean} [options.isBack=false]
+       @param {boolean} [options.isForward=false]
+       @param {boolean} [options.isFastForward=false]
+    */
+    initialize: function (options) {
+      var collection = this.collection;
+      var state = collection.state;
+      var currentPage = state.currentPage;
+      var firstPage = state.firstPage;
+      var lastPage = state.lastPage;
+
+      _.extend(this, _.pick(options,
+                            ["isRewind", "isBack", "isForward", "isFastForward"]));
+
+      var pageIndex;
+      if (this.isRewind) pageIndex = firstPage;
+      else if (this.isBack) pageIndex = Math.max(firstPage, currentPage - 1);
+      else if (this.isForward) pageIndex = Math.min(lastPage, currentPage + 1);
+      else if (this.isFastForward) pageIndex = lastPage;
+      else {
+        pageIndex = +options.pageIndex;
+        pageIndex = (firstPage ? pageIndex + 1 : pageIndex);
+      }
+      this.pageIndex = pageIndex;
+
+      this.label = (options.label || (firstPage ? pageIndex : pageIndex + 1)) + '';
+      var title = options.title || this.title;
+      this.title = _.isFunction(title) ? title({label: this.label}) : title;
+    },
+
+    /**
+       Renders a clickable anchor element under a list item.
+    */
+    render: function () {
+      this.$el.empty();
+      var anchor = document.createElement("a");
+      anchor.href = '#';
+      if (this.title) anchor.title = this.title;
+      anchor.innerHTML = this.label;
+      this.el.appendChild(anchor);
+
+      var collection = this.collection;
+      var state = collection.state;
+      var currentPage = state.currentPage;
+      var pageIndex = this.pageIndex;
+
+      if (this.isRewind && currentPage == state.firstPage ||
+         this.isBack && !collection.hasPrevious() ||
+         this.isForward && !collection.hasNext() ||
+         this.isFastForward && (currentPage == state.lastPage || state.totalPages < 1)) {
+        this.$el.addClass("disabled");
+      }
+      else if (!(this.isRewind ||
+                 this.isBack ||
+                 this.isForward ||
+                 this.isFastForward) &&
+               state.currentPage == pageIndex) {
+        this.$el.addClass("active");
+      }
+
+      this.delegateEvents();
+      return this;
+    },
+
+    /**
+       jQuery click event handler. Goes to the page this PageHandle instance
+       represents. No-op if this page handle is currently active or disabled.
+    */
+    changePage: function (e) {
+      e.preventDefault();
+      var $el = this.$el, col = this.collection;
+      if (!$el.hasClass("active") && !$el.hasClass("disabled")) {
+        if (this.isRewind) col.getFirstPage();
+        else if (this.isBack) col.getPreviousPage();
+        else if (this.isForward) col.getNextPage();
+        else if (this.isFastForward) col.getLastPage();
+        else col.getPage(this.pageIndex, {reset: true});
+      }
+      return this;
+    }
+
+  });
+
+  /**
+     Paginator is a Backgrid extension that renders a series of configurable
+     pagination handles. This extension is best used for splitting a large data
+     set across multiple pages. If the number of pages is larger then a
+     threshold, which is set to 10 by default, the page handles are rendered
+     within a sliding window, plus the rewind, back, forward and fast forward
+     control handles. The individual control handles can be turned off.
+
+     @class Backgrid.Extension.Paginator
+  */
+  var Paginator = Backgrid.Extension.Paginator = Backbone.View.extend({
+
+    /** @property */
+    className: "backgrid-paginator",
+
+    /** @property */
+    windowSize: 10,
+
+    /**
+       @property {number} slideScale the number used by #slideHowMuch to scale
+       `windowSize` to yield the number of pages to slide. For example, the
+       default windowSize(10) * slideScale(0.5) yields 5, which means the window
+       will slide forward 5 pages as soon as you've reached page 6. The smaller
+       the scale factor the less pages to slide, and vice versa.
+
+       Also See:
+
+       - #slideMaybe
+       - #slideHowMuch
+    */
+    slideScale: 0.5,
+
+    /**
+       @property {Object.<string, Object.<string, string>>} controls You can
+       disable specific control handles by setting the keys in question to
+       null. The defaults will be merged with your controls object, with your
+       changes taking precedent.
+    */
+    controls: {
+      rewind: {
+        label: "《",
+        title: "First"
+      },
+      back: {
+        label: "〈",
+        title: "Previous"
+      },
+      forward: {
+        label: "〉",
+        title: "Next"
+      },
+      fastForward: {
+        label: "》",
+        title: "Last"
+      }
+    },
+
+    /** @property */
+    renderIndexedPageHandles: true,
+
+    /**
+       @property {Backgrid.Extension.PageHandle} pageHandle. The PageHandle
+       class to use for rendering individual handles
+    */
+    pageHandle: PageHandle,
+
+    /** @property */
+    goBackFirstOnSort: true,
+
+    /**
+       Initializer.
+
+       @param {Object} options
+       @param {Backbone.Collection} options.collection
+       @param {boolean} [options.controls]
+       @param {boolean} [options.pageHandle=Backgrid.Extension.PageHandle]
+       @param {boolean} [options.goBackFirstOnSort=true]
+    */
+    initialize: function (options) {
+      var self = this;
+      self.controls = _.defaults(options.controls || {}, self.controls,
+                                 Paginator.prototype.controls);
+
+      _.extend(self, _.pick(options || {}, "windowSize", "pageHandle",
+                            "slideScale", "goBackFirstOnSort",
+                            "renderIndexedPageHandles"));
+
+      var col = self.collection;
+      self.listenTo(col, "add", self.render);
+      self.listenTo(col, "remove", self.render);
+      self.listenTo(col, "reset", self.render);
+      self.listenTo(col, "backgrid:sorted", function () {
+        if (self.goBackFirstOnSort) col.getFirstPage({reset: true});
+      });
+    },
+
+    /**
+      Decides whether the window should slide. This method should return 1 if
+      sliding should occur and 0 otherwise. The default is sliding should occur
+      if half of the pages in a window has been reached.
+
+      __Note__: All the parameters have been normalized to be 0-based.
+
+      @param {number} firstPage
+      @param {number} lastPage
+      @param {number} currentPage
+      @param {number} windowSize
+      @param {number} slideScale
+
+      @return {0|1}
+     */
+    slideMaybe: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
+      return Math.round(currentPage % windowSize / windowSize);
+    },
+
+    /**
+      Decides how many pages to slide when sliding should occur. The default
+      simply scales the `windowSize` to arrive at a fraction of the `windowSize`
+      to increment.
+
+      __Note__: All the parameters have been normalized to be 0-based.
+
+      @param {number} firstPage
+      @param {number} lastPage
+      @param {number} currentPage
+      @param {number} windowSize
+      @param {number} slideScale
+
+      @return {number}
+     */
+    slideThisMuch: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
+      return ~~(windowSize * slideScale);
+    },
+
+    _calculateWindow: function () {
+      var collection = this.collection;
+      var state = collection.state;
+
+      // convert all indices to 0-based here
+      var firstPage = state.firstPage;
+      var lastPage = +state.lastPage;
+      lastPage = Math.max(0, firstPage ? lastPage - 1 : lastPage);
+      var currentPage = Math.max(state.currentPage, state.firstPage);
+      currentPage = firstPage ? currentPage - 1 : currentPage;
+      var windowSize = this.windowSize;
+      var slideScale = this.slideScale;
+      var windowStart = Math.floor(currentPage / windowSize) * windowSize;
+      if (currentPage <= lastPage - this.slideThisMuch()) {
+        windowStart += (this.slideMaybe(firstPage, lastPage, currentPage, windowSize, slideScale) *
+                        this.slideThisMuch(firstPage, lastPage, currentPage, windowSize, slideScale));
+      }
+      var windowEnd = Math.min(lastPage + 1, windowStart + windowSize);
+      return [windowStart, windowEnd];
+    },
+
+    /**
+       Creates a list of page handle objects for rendering.
+
+       @return {Array.<Object>} an array of page handle objects hashes
+    */
+    makeHandles: function () {
+
+      var handles = [];
+      var collection = this.collection;
+
+      var window = this._calculateWindow();
+      var winStart = window[0], winEnd = window[1];
+
+      if (this.renderIndexedPageHandles) {
+        for (var i = winStart; i < winEnd; i++) {
+          handles.push(new this.pageHandle({
+            collection: collection,
+            pageIndex: i
+          }));
+        }
+      }
+
+      var controls = this.controls;
+      _.each(["back", "rewind", "forward", "fastForward"], function (key) {
+        var value = controls[key];
+        if (value) {
+          var handleCtorOpts = {
+            collection: collection,
+            title: value.title,
+            label: value.label
+          };
+          handleCtorOpts["is" + key.slice(0, 1).toUpperCase() + key.slice(1)] = true;
+          var handle = new this.pageHandle(handleCtorOpts);
+          if (key == "rewind" || key == "back") handles.unshift(handle);
+          else handles.push(handle);
+        }
+      }, this);
+
+      return handles;
+    },
+
+    /**
+       Render the paginator handles inside an unordered list.
+    */
+    render: function () {
+      this.$el.empty();
+
+      if (this.handles) {
+        for (var i = 0, l = this.handles.length; i < l; i++) {
+          this.handles[i].remove();
+        }
+      }
+
+      var handles = this.handles = this.makeHandles();
+
+      var ul = document.createElement("ul");
+      for (var i = 0; i < handles.length; i++) {
+        ul.appendChild(handles[i].render().el);
+      }
+
+      this.el.appendChild(ul);
+
+      return this;
+    }
+
+  });
+
+}));