[SPARK-10873] Support column sort and search for History Server.

[SPARK-10873] Support column sort and search for History Server using jQuery 
DataTable and REST API. Before this commit, the history server was generated 
hard-coded html and can not support search, also, the sorting was disabled if 
there is any application that has more than one attempt. Supporting search and 
sort (over all applications rather than the 20 entries in the current page) in 
any case will greatly improve user experience.

1. Create the historypage-template.html for displaying application information 
in datables.
2. historypage.js uses jQuery to access the data from /api/v1/applications REST 
API, and use DataTable to display each application's information. For 
application that has more than one attempt, the RowsGroup is used to merge such 
entries while at the same time supporting sort and search.
3. "duration" and "lastUpdated" rest API are added to application's "attempts".
4. External javascirpt and css files for datatables, RowsGroup and jquery 
plugins are added with licenses clarified.

Snapshots for how it looks like now:

History page view:
![historypage](https://cloud.githubusercontent.com/assets/11683054/12184383/89bad774-b55a-11e5-84e4-b0276172976f.png)

Search:
![search](https://cloud.githubusercontent.com/assets/11683054/12184385/8d3b94b0-b55a-11e5-869a-cc0ef0a4242a.png)

Sort by started time:
![sort-by-started-time](https://cloud.githubusercontent.com/assets/11683054/12184387/8f757c3c-b55a-11e5-98c8-577936366566.png)

Author: zhuol <zh...@yahoo-inc.com>

Closes #10648 from zhuoliu/10873.


Project: http://git-wip-us.apache.org/repos/asf/spark/repo
Commit: http://git-wip-us.apache.org/repos/asf/spark/commit/e4c1162b
Tree: http://git-wip-us.apache.org/repos/asf/spark/tree/e4c1162b
Diff: http://git-wip-us.apache.org/repos/asf/spark/diff/e4c1162b

Branch: refs/heads/master
Commit: e4c1162b6b3dbc8fc95cfe75c6e0bc2915575fb2
Parents: e51b6ea
Author: zhuol <zh...@yahoo-inc.com>
Authored: Fri Jan 29 11:54:58 2016 -0600
Committer: Tom Graves <tgra...@yahoo-inc.com>
Committed: Fri Jan 29 11:54:58 2016 -0600

----------------------------------------------------------------------
 .rat-excludes                                   |  10 +
 LICENSE                                         |   6 +
 .../spark/ui/static/dataTables.bootstrap.css    | 319 ++++++++++
 .../spark/ui/static/dataTables.bootstrap.min.js |   8 +
 .../spark/ui/static/dataTables.rowsGroup.js     | 224 +++++++
 .../spark/ui/static/historypage-template.html   |  81 +++
 .../org/apache/spark/ui/static/historypage.js   | 159 +++++
 .../spark/ui/static/jquery.blockUI.min.js       |   6 +
 .../spark/ui/static/jquery.cookies.2.2.0.min.js |  18 +
 .../ui/static/jquery.dataTables.1.10.4.min.css  |   1 +
 .../ui/static/jquery.dataTables.1.10.4.min.js   | 157 +++++
 .../apache/spark/ui/static/jquery.mustache.js   | 592 +++++++++++++++++++
 .../spark/ui/static/jsonFormatter.min.css       |   1 +
 .../apache/spark/ui/static/jsonFormatter.min.js |   2 +
 .../spark/deploy/history/HistoryPage.scala      | 193 +-----
 .../status/api/v1/ApplicationListResource.scala |  14 +
 .../org/apache/spark/status/api/v1/api.scala    |   2 +
 .../scala/org/apache/spark/ui/SparkUI.scala     |   2 +
 .../scala/org/apache/spark/ui/UIUtils.scala     |  11 +
 .../application_list_json_expectation.json      |  18 +-
 .../completed_app_list_json_expectation.json    |  18 +-
 .../maxDate2_app_list_json_expectation.json     |   4 +-
 .../maxDate_app_list_json_expectation.json      |   6 +-
 .../minDate_app_list_json_expectation.json      |  14 +-
 .../one_app_json_expectation.json               |   4 +-
 .../one_app_multi_attempt_json_expectation.json |   6 +-
 .../deploy/history/HistoryServerSuite.scala     |  43 +-
 project/MimaExcludes.scala                      |   4 +
 28 files changed, 1721 insertions(+), 202 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/.rat-excludes
----------------------------------------------------------------------
diff --git a/.rat-excludes b/.rat-excludes
index a4f316a..874a6ee 100644
--- a/.rat-excludes
+++ b/.rat-excludes
@@ -25,6 +25,16 @@ graphlib-dot.min.js
 sorttable.js
 vis.min.js
 vis.min.css
+dataTables.bootstrap.css
+dataTables.bootstrap.min.js
+dataTables.rowsGroup.js
+jquery.blockUI.min.js
+jquery.cookies.2.2.0.min.js
+jquery.dataTables.1.10.4.min.css
+jquery.dataTables.1.10.4.min.js
+jquery.mustache.js
+jsonFormatter.min.css
+jsonFormatter.min.js
 .*avsc
 .*txt
 .*json

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 9c944ac..9fc29db 100644
--- a/LICENSE
+++ b/LICENSE
@@ -291,3 +291,9 @@ The text of each license is also included at 
licenses/LICENSE-[project].txt.
      (MIT License) dagre-d3 (https://github.com/cpettitt/dagre-d3)
      (MIT License) sorttable (https://github.com/stuartlangridge/sorttable)
      (MIT License) boto (https://github.com/boto/boto/blob/develop/LICENSE)
+     (MIT License) datatables (http://datatables.net/license)
+     (MIT License) mustache 
(https://github.com/mustache/mustache/blob/master/LICENSE)
+     (MIT License) cookies (http://code.google.com/p/cookies/wiki/License)
+     (MIT License) blockUI (http://jquery.malsup.com/block/)
+     (MIT License) RowsGroup (http://datatables.net/license/mit)
+     (MIT License) jsonFormatter 
(http://www.jqueryscript.net/other/jQuery-Plugin-For-Pretty-JSON-Formatting-jsonFormatter.html)

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.css
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.css 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.css
new file mode 100644
index 0000000..faee0e5
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.css
@@ -0,0 +1,319 @@
+div.dataTables_length label {
+       font-weight: normal;
+       text-align: left;
+       white-space: nowrap;
+}
+
+div.dataTables_length select {
+       width: 75px;
+       display: inline-block;
+}
+
+div.dataTables_filter {
+       text-align: right;
+}
+
+div.dataTables_filter label {
+       font-weight: normal;
+       white-space: nowrap;
+       text-align: left;
+}
+
+div.dataTables_filter input {
+       margin-left: 0.5em;
+       display: inline-block;
+}
+
+div.dataTables_info {
+       padding-top: 8px;
+       white-space: nowrap;
+}
+
+div.dataTables_paginate {
+       margin: 0;
+       white-space: nowrap;
+       text-align: right;
+}
+
+div.dataTables_paginate ul.pagination {
+       margin: 2px 0;
+       white-space: nowrap;
+}
+
+@media screen and (max-width: 767px) {
+       div.dataTables_length,
+       div.dataTables_filter,
+       div.dataTables_info,
+       div.dataTables_paginate {
+               text-align: center;
+       }
+}
+
+
+table.dataTable td,
+table.dataTable th {
+       -webkit-box-sizing: content-box;
+       -moz-box-sizing: content-box;
+       box-sizing: content-box;
+}
+
+
+table.dataTable {
+       clear: both;
+       margin-top: 6px !important;
+       margin-bottom: 6px !important;
+       max-width: none !important;
+}
+
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+       cursor: pointer;
+}
+
+table.dataTable thead .sorting { background: url('../images/sort_both.png') 
no-repeat center right; }
+table.dataTable thead .sorting_asc { background: url('../images/sort_asc.png') 
no-repeat center right; }
+table.dataTable thead .sorting_desc { background: 
url('../images/sort_desc.png') no-repeat center right; }
+
+table.dataTable thead .sorting_asc_disabled { background: 
url('../images/sort_asc_disabled.png') no-repeat center right; }
+table.dataTable thead .sorting_desc_disabled { background: 
url('../images/sort_desc_disabled.png') no-repeat center right; }
+
+table.dataTable thead > tr > th {
+       padding-left: 18px;
+       padding-right: 18px;
+}
+
+table.dataTable th:active {
+       outline: none;
+}
+
+/* Scrolling */
+div.dataTables_scrollHead table {
+       margin-bottom: 0 !important;
+       border-bottom-left-radius: 0;
+       border-bottom-right-radius: 0;
+}
+
+div.dataTables_scrollHead table thead tr:last-child th:first-child,
+div.dataTables_scrollHead table thead tr:last-child td:first-child {
+       border-bottom-left-radius: 0 !important;
+       border-bottom-right-radius: 0 !important;
+}
+
+div.dataTables_scrollBody table {
+       border-top: none;
+       margin-top: 0 !important;
+       margin-bottom: 0 !important;
+}
+
+div.dataTables_scrollBody tbody tr:first-child th,
+div.dataTables_scrollBody tbody tr:first-child td {
+       border-top: none;
+}
+
+div.dataTables_scrollFoot table {
+       margin-top: 0 !important;
+       border-top: none;
+}
+
+/* Frustratingly the border-collapse:collapse used by Bootstrap makes the 
column
+   width calculations when using scrolling impossible to align columns. We have
+   to use separate
+ */
+table.table-bordered.dataTable {
+       border-collapse: separate !important;
+}
+table.table-bordered thead th,
+table.table-bordered thead td {
+       border-left-width: 0;
+       border-top-width: 0;
+}
+table.table-bordered tbody th,
+table.table-bordered tbody td {
+       border-left-width: 0;
+       border-bottom-width: 0;
+}
+table.table-bordered th:last-child,
+table.table-bordered td:last-child {
+       border-right-width: 0;
+}
+div.dataTables_scrollHead table.table-bordered {
+       border-bottom-width: 0;
+}
+
+
+
+
+/*
+ * TableTools styles
+ */
+.table.dataTable tbody tr.active td,
+.table.dataTable tbody tr.active th {
+       background-color: #08C;
+       color: white;
+}
+
+.table.dataTable tbody tr.active:hover td,
+.table.dataTable tbody tr.active:hover th {
+       background-color: #0075b0 !important;
+}
+
+.table.dataTable tbody tr.active th > a,
+.table.dataTable tbody tr.active td > a {
+       color: white;
+}
+
+.table-striped.dataTable tbody tr.active:nth-child(odd) td,
+.table-striped.dataTable tbody tr.active:nth-child(odd) th {
+       background-color: #017ebc;
+}
+
+table.DTTT_selectable tbody tr {
+       cursor: pointer;
+}
+
+div.DTTT .btn {
+       color: #333 !important;
+       font-size: 12px;
+}
+
+div.DTTT .btn:hover {
+       text-decoration: none !important;
+}
+
+ul.DTTT_dropdown.dropdown-menu {
+  z-index: 2003;
+}
+
+ul.DTTT_dropdown.dropdown-menu a {
+       color: #333 !important; /* needed only when demo_page.css is included */
+}
+
+ul.DTTT_dropdown.dropdown-menu li {
+       position: relative;
+}
+
+ul.DTTT_dropdown.dropdown-menu li:hover a {
+       background-color: #0088cc;
+       color: white !important;
+}
+
+div.DTTT_collection_background {
+       z-index: 2002;  
+}
+
+/* TableTools information display */
+div.DTTT_print_info {
+       position: fixed;
+       top: 50%;
+       left: 50%;
+       width: 400px;
+       height: 150px;
+       margin-left: -200px;
+       margin-top: -75px;
+       text-align: center;
+       color: #333;
+       padding: 10px 30px;
+       opacity: 0.95;
+
+       background-color: white;
+       border: 1px solid rgba(0, 0, 0, 0.2);
+       border-radius: 6px;
+       
+       -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);
+               box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);
+}
+
+div.DTTT_print_info h6 {
+       font-weight: normal;
+       font-size: 28px;
+       line-height: 28px;
+       margin: 1em;
+}
+
+div.DTTT_print_info p {
+       font-size: 14px;
+       line-height: 20px;
+}
+
+div.dataTables_processing {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 100%;
+    height: 60px;
+    margin-left: -50%;
+    margin-top: -25px;
+    padding-top: 20px;
+    padding-bottom: 20px;
+    text-align: center;
+    font-size: 1.2em;
+    background-color: white;
+    background: -webkit-gradient(linear, left top, right top, color-stop(0%, 
rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, 
rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));
+    background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, 
rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
+    background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, 
rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
+    background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%, 
rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
+    background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, 
rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
+    background: linear-gradient(to right, rgba(255,255,255,0) 0%, 
rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
+}
+
+
+
+/*
+ * FixedColumns styles
+ */
+div.DTFC_LeftHeadWrapper table,
+div.DTFC_LeftFootWrapper table,
+div.DTFC_RightHeadWrapper table,
+div.DTFC_RightFootWrapper table,
+table.DTFC_Cloned tr.even {
+    background-color: white;
+    margin-bottom: 0;
+}
+ 
+div.DTFC_RightHeadWrapper table ,
+div.DTFC_LeftHeadWrapper table {
+       border-bottom: none !important;
+    margin-bottom: 0 !important;
+    border-top-right-radius: 0 !important;
+    border-bottom-left-radius: 0 !important;
+    border-bottom-right-radius: 0 !important;
+}
+ 
+div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child,
+div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child,
+div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,
+div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {
+    border-bottom-left-radius: 0 !important;
+    border-bottom-right-radius: 0 !important;
+}
+ 
+div.DTFC_RightBodyWrapper table,
+div.DTFC_LeftBodyWrapper table {
+    border-top: none;
+    margin: 0 !important;
+}
+ 
+div.DTFC_RightBodyWrapper tbody tr:first-child th,
+div.DTFC_RightBodyWrapper tbody tr:first-child td,
+div.DTFC_LeftBodyWrapper tbody tr:first-child th,
+div.DTFC_LeftBodyWrapper tbody tr:first-child td {
+    border-top: none;
+}
+ 
+div.DTFC_RightFootWrapper table,
+div.DTFC_LeftFootWrapper table {
+    border-top: none;
+    margin-top: 0 !important;
+}
+
+
+/*
+ * FixedHeader styles
+ */
+div.FixedHeader_Cloned table {
+       margin: 0 !important
+}
+

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.min.js
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.min.js
 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.min.js
new file mode 100644
index 0000000..f0d09b9
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap.min.js
@@ -0,0 +1,8 @@
+/*!
+ DataTables Bootstrap 3 integration
+ ©2011-2014 SpryMedia Ltd - datatables.net/license
+*/
+(function(){var 
f=function(c,b){c.extend(!0,b.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-6'i><'col-sm-6'p>>",renderer:"bootstrap"});c.extend(b.ext.classes,{sWrapper:"dataTables_wrapper
 form-inline dt-bootstrap",sFilterInput:"form-control 
input-sm",sLengthSelect:"form-control 
input-sm"});b.ext.renderer.pageButton.bootstrap=function(g,f,p,k,h,l){var q=new 
b.Api(g),r=g.oClasses,i=g.oLanguage.oPaginate,d,e,o=function(b,f){var 
j,m,n,a,k=function(a){a.preventDefault();
+c(a.currentTarget).hasClass("disabled")||q.page(a.data.action).draw(!1)};j=0;for(m=f.length;j<m;j++)if(a=f[j],c.isArray(a))o(b,a);else{e=d="";switch(a){case
 "ellipsis":d="&hellip;";e="disabled";break;case 
"first":d=i.sFirst;e=a+(0<h?"":" disabled");break;case 
"previous":d=i.sPrevious;e=a+(0<h?"":" disabled");break;case 
"next":d=i.sNext;e=a+(h<l-1?"":" disabled");break;case 
"last":d=i.sLast;e=a+(h<l-1?"":" 
disabled");break;default:d=a+1,e=h===a?"active":""}d&&(n=c("<li>",{"class":r.sPageButton+"
 "+
+e,"aria-controls":g.sTableId,tabindex:g.iTabIndex,id:0===p&&"string"===typeof 
a?g.sTableId+"_"+a:null}).append(c("<a>",{href:"#"}).html(d)).appendTo(b),g.oApi._fnBindAction(n,{action:a},k))}};o(c(f).empty().html('<ul
 
class="pagination"/>').children("ul"),k)};b.TableTools&&(c.extend(!0,b.TableTools.classes,{container:"DTTT
 btn-group",buttons:{normal:"btn 
btn-default",disabled:"disabled"},collection:{container:"DTTT_dropdown 
dropdown-menu",buttons:{normal:"",disabled:"disabled"}},print:{info:"DTTT_print_info"},
+select:{row:"active"}}),c.extend(!0,b.TableTools.DEFAULTS.oTags,{collection:{container:"ul",button:"li",liner:"a"}}))};"function"===typeof
 define&&define.amd?define(["jquery","datatables"],f):"object"===typeof 
exports?f(require("jquery"),require("datatables")):jQuery&&f(jQuery,jQuery.fn.dataTable)})(window,document);

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/dataTables.rowsGroup.js
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.rowsGroup.js 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.rowsGroup.js
new file mode 100644
index 0000000..983c3a5
--- /dev/null
+++ b/core/src/main/resources/org/apache/spark/ui/static/dataTables.rowsGroup.js
@@ -0,0 +1,224 @@
+/*! RowsGroup for DataTables v1.0.0
+ * 2015 Alexey Shildyakov ashl1fut...@gmail.com
+ */
+
+/**
+ * @summary     RowsGroup
+ * @description Group rows by specified columns
+ * @version     1.0.0
+ * @file        dataTables.rowsGroup.js
+ * @author      Alexey Shildyakov (ashl1fut...@gmail.com)
+ * @contact     ashl1fut...@gmail.com
+ * @copyright   Alexey Shildyakov
+ * 
+ * License      MIT - http://datatables.net/license/mit
+ *
+ * This feature plug-in for DataTables automatically merges columns cells
+ * based on it's values equality. It supports multi-column row grouping
+ * in according to the requested order with dependency from each previous 
+ * requested columns. Now it supports ordering and searching. 
+ * Please see the example.html for details.
+ * 
+ * Rows grouping in DataTables can be enabled by using any one of the following
+ * options:
+ *
+ * * Setting the `rowsGroup` parameter in the DataTables initialisation
+ *   to array which contains columns selectors
+ *   (https://datatables.net/reference/type/column-selector) used for 
grouping. i.e.
+ *    rowsGroup = [1, 'columnName:name', ]
+ * * Setting the `rowsGroup` parameter in the DataTables defaults
+ *   (thus causing all tables to have this feature) - i.e.
+ *   `$.fn.dataTable.defaults.RowsGroup = [0]`.
+ * * Creating a new instance: `new $.fn.dataTable.RowsGroup( table, 
columnsForGrouping );`
+ *   where `table` is a DataTable's API instance and `columnsForGrouping` is 
the array
+ *   described above.
+ *
+ * For more detailed information please see:
+ *     
+ */
+
+(function($){
+
+ShowedDataSelectorModifier = {
+       order: 'current',
+       page: 'current',
+       search: 'applied',
+}
+
+GroupedColumnsOrderDir = 'desc'; // change
+
+
+/*
+ * columnsForGrouping: array of DTAPI:cell-selector for columns for which rows 
grouping is applied
+ */
+var RowsGroup = function ( dt, columnsForGrouping )
+{
+       this.table = dt.table();
+       this.columnsForGrouping = columnsForGrouping;
+        // set to True when new reorder is applied by RowsGroup to prevent 
order() looping
+       this.orderOverrideNow = false;
+       this.order = []
+       
+       self = this;
+       $(document).on('order.dt', function ( e, settings) {
+               if (!self.orderOverrideNow) {
+                       self._updateOrderAndDraw()
+               }
+               self.orderOverrideNow = false;
+       })
+       
+       $(document).on('draw.dt', function ( e, settings) {
+               self._mergeCells()
+       })
+
+       this._updateOrderAndDraw();
+};
+
+
+RowsGroup.prototype = {
+       _getOrderWithGroupColumns: function (order, groupedColumnsOrderDir)
+       {
+               if (groupedColumnsOrderDir === undefined)
+                       groupedColumnsOrderDir = GroupedColumnsOrderDir
+                       
+               var self = this;
+               var groupedColumnsIndexes = 
this.columnsForGrouping.map(function(columnSelector){
+                       return self.table.column(columnSelector).index()
+               })
+               var groupedColumnsKnownOrder = 
order.filter(function(columnOrder){
+                       return groupedColumnsIndexes.indexOf(columnOrder[0]) >= 0
+               })
+               var nongroupedColumnsOrder = order.filter(function(columnOrder){
+                       return groupedColumnsIndexes.indexOf(columnOrder[0]) < 0
+               })
+               var groupedColumnsKnownOrderIndexes = 
groupedColumnsKnownOrder.map(function(columnOrder){
+                       return columnOrder[0]
+               })
+               var groupedColumnsOrder = 
groupedColumnsIndexes.map(function(iColumn){
+                       var iInOrderIndexes = 
groupedColumnsKnownOrderIndexes.indexOf(iColumn)
+                       if (iInOrderIndexes >= 0)
+                               return [iColumn, 
groupedColumnsKnownOrder[iInOrderIndexes][1]]
+                       else
+                               return [iColumn, groupedColumnsOrderDir]
+               })
+               
+               groupedColumnsOrder.push.apply(groupedColumnsOrder, 
nongroupedColumnsOrder)
+               return groupedColumnsOrder;
+       },
+ 
+       // Workaround: the DT reset ordering to 'desc' from multi-ordering if 
user order on one column (without shift)
+       // but because we always has multi-ordering due to grouped rows this 
happens every time
+       _getInjectedMonoSelectWorkaround: function(order)
+       {
+               if (order.length === 1) {
+                       // got mono order - workaround here
+                       var orderingColumn = order[0][0]
+                       var previousOrder = this.order.map(function(val){
+                               return val[0]
+                       })
+                       var iColumn = previousOrder.indexOf(orderingColumn);
+                       if (iColumn >= 0) {
+                               // assume change the direction, because we 
already has that in previous order
+                               return [[orderingColumn, 
this._toogleDirection(this.order[iColumn][1])]]
+                       } // else This is the new ordering column. Proceed as 
is.
+               } // else got multi order - work normal
+               return order;
+       },
+       
+       _mergeCells: function()
+       {
+               var columnsIndexes = 
this.table.columns(this.columnsForGrouping, 
ShowedDataSelectorModifier).indexes().toArray()
+               var showedRowsCount = 
this.table.rows(ShowedDataSelectorModifier)[0].length 
+               this._mergeColumn(0, showedRowsCount - 1, columnsIndexes)
+       },
+       
+       // the index is relative to the showed data
+       //    (selector-modifier = {order: 'current', page: 'current', search: 
'applied'}) index
+       _mergeColumn: function(iStartRow, iFinishRow, columnsIndexes)
+       {
+               var columnsIndexesCopy = columnsIndexes.slice()
+               currentColumn = columnsIndexesCopy.shift()
+               currentColumn = this.table.column(currentColumn, 
ShowedDataSelectorModifier)
+               
+               var columnNodes = currentColumn.nodes()
+               var columnValues = currentColumn.data()
+               
+               var newSequenceRow = iStartRow,
+                       iRow;
+               for (iRow = iStartRow + 1; iRow <= iFinishRow; ++iRow) {
+                       
+                       if (columnValues[iRow] === 
columnValues[newSequenceRow]) {
+                               $(columnNodes[iRow]).hide()
+                       } else {
+                               $(columnNodes[newSequenceRow]).show()
+                               $(columnNodes[newSequenceRow]).attr('rowspan', 
(iRow-1) - newSequenceRow + 1)
+                               
+                               if (columnsIndexesCopy.length > 0)
+                                       this._mergeColumn(newSequenceRow, 
(iRow-1), columnsIndexesCopy)
+                               
+                               newSequenceRow = iRow;
+                       }
+                       
+               }
+               $(columnNodes[newSequenceRow]).show()
+               $(columnNodes[newSequenceRow]).attr('rowspan', (iRow-1)- 
newSequenceRow + 1)
+               if (columnsIndexesCopy.length > 0)
+                       this._mergeColumn(newSequenceRow, (iRow-1), 
columnsIndexesCopy)
+       },
+       
+       _toogleDirection: function(dir)
+       {
+               return dir == 'asc'? 'desc': 'asc';
+       },
+ 
+       _updateOrderAndDraw: function()
+       {
+               this.orderOverrideNow = true;
+               
+               var currentOrder = this.table.order();
+               currentOrder = 
this._getInjectedMonoSelectWorkaround(currentOrder);
+               this.order = this._getOrderWithGroupColumns(currentOrder)
+               // this.table.order($.extend(true, Array(), this.order)) // 
disable this line in order to support sorting on non-grouped columns
+               this.table.draw(false)
+       },
+};
+
+
+$.fn.dataTable.RowsGroup = RowsGroup;
+$.fn.DataTable.RowsGroup = RowsGroup;
+
+// Automatic initialisation listener
+$(document).on( 'init.dt', function ( e, settings ) {
+       if ( e.namespace !== 'dt' ) {
+               return;
+       }
+
+       var api = new $.fn.dataTable.Api( settings );
+
+       if ( settings.oInit.rowsGroup ||
+                $.fn.dataTable.defaults.rowsGroup )
+       {
+               options = settings.oInit.rowsGroup?
+                       settings.oInit.rowsGroup:
+                       $.fn.dataTable.defaults.rowsGroup;
+               new RowsGroup( api, options );
+       }
+} );
+
+}(jQuery));
+
+/*
+
+TODO: Provide function which determines the all <tr>s and <td>s with "rowspan" 
html-attribute is parent (groupped) for the specified <tr> or <td>. To use in 
selections, editing or hover styles.
+
+TODO: Feature
+Use saved order direction for grouped columns
+       Split the columns into grouped and ungrouped.
+
+       user = grouped+ungrouped
+       grouped = grouped
+       saved = grouped+ungrouped
+
+       For grouped uses following order: user -> saved (because 'saved' 
include 'grouped' after first initialisation). This should be done with saving 
order like for 'groupedColumns'
+       For ungrouped: uses only 'user' input ordering
+*/
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
new file mode 100644
index 0000000..66d111e
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
@@ -0,0 +1,81 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<script id="history-summary-template" type="text/html">
+<table id="history-summary-table" class="table table-striped compact">
+  <thead>
+    <tr>
+      <th>
+        <span data-toggle="tooltip" data-placement="right" title="ID of the 
application.">
+          App ID
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="above" title="Name of the 
application.">
+          App Name
+        </span>
+      </th>
+      <th class="attemptIDSpan">
+        <span data-toggle="tooltip" data-placement="above" title="The attempt 
ID of this application since one application might be launched several times">
+          Attempt ID
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="right" title="Started time 
of this application.">
+          Started
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="above" title="The 
completed time of this application.">
+          Completed
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="above" title="The duration 
time of this application.">
+          Duration
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="right" title="The Spark 
user of this application">
+          Spark User
+        </span>
+      </th>
+      <th>
+        <span data-toggle="tooltip" data-placement="above" title="The 
timestamp of the last updating on this application">
+          Last Updated
+        </span>
+      </th>
+    </tr>
+  </thead>
+  <tbody>
+  {{#applications}}
+    <tr>
+      <td class="rowGroupColumn"><a 
href="/history/{{id}}/{{num}}/jobs/">{{id}}</a></td>
+      <td class="rowGroupColumn">{{name}}</td>
+      {{#attempts}}
+      <td class="attemptIDSpan"><a 
href="/history/{{id}}/{{attemptId}}/jobs/">{{attemptId}}</a></td>
+      <td>{{startTime}}</td>
+      <td>{{endTime}}</td>
+      <td><span title="{{duration}}" 
class="durationClass">{{duration}}</span></td>
+      <td>{{sparkUser}}</td>
+      <td>{{lastUpdated}}</td>
+      {{/attempts}}
+    </tr>
+  {{/applications}}
+  </tbody>
+</table>
+</script>

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/historypage.js
----------------------------------------------------------------------
diff --git a/core/src/main/resources/org/apache/spark/ui/static/historypage.js 
b/core/src/main/resources/org/apache/spark/ui/static/historypage.js
new file mode 100644
index 0000000..785abe4
--- /dev/null
+++ b/core/src/main/resources/org/apache/spark/ui/static/historypage.js
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// this function works exactly the same as UIUtils.formatDuration
+function formatDuration(milliseconds) {
+  if (milliseconds < 100) {
+    return milliseconds + " ms";
+  }
+  var seconds = milliseconds * 1.0 / 1000;
+  if (seconds < 1) {
+    return seconds.toFixed(1) + " s";
+  }
+  if (seconds < 60) {
+    return seconds.toFixed(0) + " s";
+  }
+  var minutes = seconds / 60;
+  if (minutes < 10) {
+    return minutes.toFixed(1) + " min";
+  } else if (minutes < 60) {
+    return minutes.toFixed(0) + " min";
+  }
+  var hours = minutes / 60;
+  return hours.toFixed(1) + " h";
+}
+
+function formatDate(date) {
+  return date.split(".")[0].replace("T", " ");
+}
+
+function getParameterByName(name, searchString) {
+  var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+  results = regex.exec(searchString);
+  return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, 
" "));
+}
+
+jQuery.extend( jQuery.fn.dataTableExt.oSort, {
+    "title-numeric-pre": function ( a ) {
+        var x = a.match(/title="*(-?[0-9\.]+)/)[1];
+        return parseFloat( x );
+    },
+
+    "title-numeric-asc": function ( a, b ) {
+        return ((a < b) ? -1 : ((a > b) ? 1 : 0));
+    },
+
+    "title-numeric-desc": function ( a, b ) {
+        return ((a < b) ? 1 : ((a > b) ? -1 : 0));
+    }
+} );
+
+$(document).ajaxStop($.unblockUI);
+$(document).ajaxStart(function(){
+    $.blockUI({ message: '<h3>Loading history summary...</h3>'});
+});
+
+$(document).ready(function() {
+    $.extend( $.fn.dataTable.defaults, {
+      stateSave: true,
+      lengthMenu: [[20,40,60,100,-1], [20, 40, 60, 100, "All"]],
+      pageLength: 20
+    });
+
+    historySummary = $("#history-summary");
+    searchString = historySummary["context"]["location"]["search"];
+    requestedIncomplete = getParameterByName("showIncomplete", searchString);
+    requestedIncomplete = (requestedIncomplete == "true" ? true : false);
+
+    $.getJSON("/api/v1/applications", function(response,status,jqXHR) {
+      var array = [];
+      var hasMultipleAttempts = false;
+      for (i in response) {
+        var app = response[i];
+        if (app["attempts"][0]["completed"] == requestedIncomplete) {
+          continue; // if we want to show for Incomplete, we skip the 
completed apps; otherwise skip incomplete ones.
+        }
+        var id = app["id"];
+        var name = app["name"];
+        if (app["attempts"].length > 1) {
+            hasMultipleAttempts = true;
+        }
+        var num = app["attempts"].length;
+        for (j in app["attempts"]) {
+          var attempt = app["attempts"][j];
+          attempt["startTime"] = formatDate(attempt["startTime"]);
+          attempt["endTime"] = formatDate(attempt["endTime"]);
+          attempt["lastUpdated"] = formatDate(attempt["lastUpdated"]);
+          var app_clone = {"id" : id, "name" : name, "num" : num, "attempts" : 
[attempt]};
+          array.push(app_clone);
+        }
+      }
+
+      var data = {"applications": array}
+      $.get("/static/historypage-template.html", function(template) {
+        
historySummary.append(Mustache.render($(template).filter("#history-summary-template").html(),data));
+        var selector = "#history-summary-table";
+        var conf = {
+                    "columns": [
+                        {name: 'first'},
+                        {name: 'second'},
+                        {name: 'third'},
+                        {name: 'fourth'},
+                        {name: 'fifth'},
+                        {name: 'sixth', type: "title-numeric"},
+                        {name: 'seventh'},
+                        {name: 'eighth'},
+                    ],
+        };
+
+        var rowGroupConf = {
+                           "rowsGroup": [
+                               'first:name',
+                               'second:name'
+                           ],
+        };
+
+        if (hasMultipleAttempts) {
+          jQuery.extend(conf, rowGroupConf);
+          var rowGroupCells = 
document.getElementsByClassName("rowGroupColumn");
+          for (i = 0; i < rowGroupCells.length; i++) {
+            rowGroupCells[i].style='background-color: #ffffff';
+          }
+        }
+
+        if (!hasMultipleAttempts) {
+          var attemptIDCells = 
document.getElementsByClassName("attemptIDSpan");
+          for (i = 0; i < attemptIDCells.length; i++) {
+            attemptIDCells[i].style.display='none';
+          }
+        }
+
+        var durationCells = document.getElementsByClassName("durationClass");
+        for (i = 0; i < durationCells.length; i++) {
+          var timeInMilliseconds = parseInt(durationCells[i].title);
+          durationCells[i].innerHTML = formatDuration(timeInMilliseconds);
+        }
+
+        if ($(selector.concat(" tr")).length < 20) {
+          $.extend(conf, {paging: false});
+        }
+
+        $(selector).DataTable(conf);
+        $('#hisotry-summary [data-toggle="tooltip"]').tooltip();
+      });
+    });
+});

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/jquery.blockUI.min.js
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/jquery.blockUI.min.js 
b/core/src/main/resources/org/apache/spark/ui/static/jquery.blockUI.min.js
new file mode 100644
index 0000000..1e84b3e
--- /dev/null
+++ b/core/src/main/resources/org/apache/spark/ui/static/jquery.blockUI.min.js
@@ -0,0 +1,6 @@
+/*
+* jQuery BlockUI; v20131009
+* http://jquery.malsup.com/block/
+* Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL
+*/
+(function(){"use strict";function e(e){function o(o,i){var 
s,h,k=o==window,v=i&&void 0!==i.message?i.message:void 
0;if(i=e.extend({},e.blockUI.defaults,i||{}),!i.ignoreIfBlocked||!e(o).data("blockUI.isBlocked")){if(i.overlayCSS=e.extend({},e.blockUI.defaults.overlayCSS,i.overlayCSS||{}),s=e.extend({},e.blockUI.defaults.css,i.css||{}),i.onOverlayClick&&(i.overlayCSS.cursor="pointer"),h=e.extend({},e.blockUI.defaults.themedCSS,i.themedCSS||{}),v=void
 0===v?i.message:v,k&&b&&t(window,{fadeOut:0}),v&&"string"!=typeof 
v&&(v.parentNode||v.jquery)){var 
y=v.jquery?v[0]:v,m={};e(o).data("blockUI.history",m),m.el=y,m.parent=y.parentNode,m.display=y.style.display,m.position=y.style.position,m.parent&&m.parent.removeChild(y)}e(o).data("blockUI.onUnblock",i.onUnblock);var
 g,I,w,U,x=i.baseZ;g=r||i.forceIframe?e('<iframe class="blockUI" 
style="z-index:'+x++ 
+';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0"
 src="'+i.iframeSrc+'"></iframe>'):e('<di
 v class="blockUI" style="display:none"></div>'),I=i.theme?e('<div 
class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+x++ 
+';display:none"></div>'):e('<div class="blockUI blockOverlay" 
style="z-index:'+x++ 
+';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'),i.theme&&k?(U='<div
 class="blockUI '+i.blockMsgClass+' blockPage ui-dialog ui-widget 
ui-corner-all" 
style="z-index:'+(x+10)+';display:none;position:fixed">',i.title&&(U+='<div 
class="ui-widget-header ui-dialog-titlebar ui-corner-all 
blockTitle">'+(i.title||"&nbsp;")+"</div>"),U+='<div class="ui-widget-content 
ui-dialog-content"></div>',U+="</div>"):i.theme?(U='<div class="blockUI 
'+i.blockMsgClass+' blockElement ui-dialog ui-widget ui-corner-all" 
style="z-index:'+(x+10)+';display:none;position:absolute">',i.title&&(U+='<div 
class="ui-widget-header ui-dialog-titlebar ui-corner-all 
blockTitle">'+(i.title||"&nbsp;")+"</div>"),U+='<div class="ui-widget-content 
ui-dialog-content"></
 div>',U+="</div>"):U=k?'<div class="blockUI '+i.blockMsgClass+' blockPage" 
style="z-index:'+(x+10)+';display:none;position:fixed"></div>':'<div 
class="blockUI '+i.blockMsgClass+' blockElement" 
style="z-index:'+(x+10)+';display:none;position:absolute"></div>',w=e(U),v&&(i.theme?(w.css(h),w.addClass("ui-widget-content")):w.css(s)),i.theme||I.css(i.overlayCSS),I.css("position",k?"fixed":"absolute"),(r||i.forceIframe)&&g.css("opacity",0);var
 
C=[g,I,w],S=k?e("body"):e(o);e.each(C,function(){this.appendTo(S)}),i.theme&&i.draggable&&e.fn.draggable&&w.draggable({handle:".ui-dialog-titlebar",cancel:"li"});var
 
O=f&&(!e.support.boxModel||e("object,embed",k?null:o).length>0);if(u||O){if(k&&i.allowBodyStretch&&e.support.boxModel&&e("html,body").css("height","100%"),(u||!e.support.boxModel)&&!k)var
 E=d(o,"borderTopWidth"),T=d(o,"borderLeftWidth"),M=E?"(0 - "+E+")":0,B=T?"(0 - 
"+T+")":0;e.each(C,function(e,o){var 
t=o[0].style;if(t.position="absolute",2>e)k?t.setExpression("height","Math.max(docume
 nt.body.scrollHeight, document.body.offsetHeight) - 
(jQuery.support.boxModel?0:"+i.quirksmodeOffsetHack+') + 
"px"'):t.setExpression("height",'this.parentNode.offsetHeight + 
"px"'),k?t.setExpression("width",'jQuery.support.boxModel && 
document.documentElement.clientWidth || document.body.clientWidth + 
"px"'):t.setExpression("width",'this.parentNode.offsetWidth + 
"px"'),B&&t.setExpression("left",B),M&&t.setExpression("top",M);else 
if(i.centerY)k&&t.setExpression("top",'(document.documentElement.clientHeight 
|| document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = 
document.documentElement.scrollTop ? document.documentElement.scrollTop : 
document.body.scrollTop) + "px"'),t.marginTop=0;else if(!i.centerY&&k){var 
n=i.css&&i.css.top?parseInt(i.css.top,10):0,s="((document.documentElement.scrollTop
 ? document.documentElement.scrollTop : document.body.scrollTop) + "+n+') + 
"px"';t.setExpression("top",s)}})}if(v&&(i.theme?w.find(".ui-widget-content").append(v):w.append(v),(v.jque
 
ry||v.nodeType)&&e(v).show()),(r||i.forceIframe)&&i.showOverlay&&g.show(),i.fadeIn){var
 
j=i.onBlock?i.onBlock:c,H=i.showOverlay&&!v?j:c,z=v?j:c;i.showOverlay&&I._fadeIn(i.fadeIn,H),v&&w._fadeIn(i.fadeIn,z)}else
 
i.showOverlay&&I.show(),v&&w.show(),i.onBlock&&i.onBlock();if(n(1,o,i),k?(b=w[0],p=e(i.focusableElements,b),i.focusInput&&setTimeout(l,20)):a(w[0],i.centerX,i.centerY),i.timeout){var
 
W=setTimeout(function(){k?e.unblockUI(i):e(o).unblock(i)},i.timeout);e(o).data("blockUI.timeout",W)}}}function
 t(o,t){var 
s,l=o==window,a=e(o),d=a.data("blockUI.history"),c=a.data("blockUI.timeout");c&&(clearTimeout(c),a.removeData("blockUI.timeout")),t=e.extend({},e.blockUI.defaults,t||{}),n(0,o,t),null===t.onUnblock&&(t.onUnblock=a.data("blockUI.onUnblock"),a.removeData("blockUI.onUnblock"));var
 r;r=l?e("body").children().filter(".blockUI").add("body > 
.blockUI"):a.find(">.blockUI"),t.cursorReset&&(r.length>1&&(r[1].style.cursor=t.cursorReset),r.length>2&&(r[2].style.cursor=t.cursorReset)),l&&(
 
b=p=null),t.fadeOut?(s=r.length,r.stop().fadeOut(t.fadeOut,function(){0===--s&&i(r,d,t,o)})):i(r,d,t,o)}function
 i(o,t,i,n){var 
s=e(n);if(!s.data("blockUI.isBlocked")){o.each(function(){this.parentNode&&this.parentNode.removeChild(this)}),t&&t.el&&(t.el.style.display=t.display,t.el.style.position=t.position,t.parent&&t.parent.appendChild(t.el),s.removeData("blockUI.history")),s.data("blockUI.static")&&s.css("position","static"),"function"==typeof
 i.onUnblock&&i.onUnblock(n,i);var 
l=e(document.body),a=l.width(),d=l[0].style.width;l.width(a-1).width(a),l[0].style.width=d}}function
 n(o,t,i){var 
n=t==window,l=e(t);if((o||(!n||b)&&(n||l.data("blockUI.isBlocked")))&&(l.data("blockUI.isBlocked",o),n&&i.bindEvents&&(!o||i.showOverlay))){var
 a="mousedown mouseup keydown keypress keyup touchstart touchend 
touchmove";o?e(document).bind(a,i,s):e(document).unbind(a,s)}}function 
s(o){if("keydown"===o.type&&o.keyCode&&9==o.keyCode&&b&&o.data.constrainTabKey){var
 t=p,i=!o.shiftKey&&o.target===t[t.l
 ength-1],n=o.shiftKey&&o.target===t[0];if(i||n)return 
setTimeout(function(){l(n)},10),!1}var s=o.data,a=e(o.target);return 
a.hasClass("blockOverlay")&&s.onOverlayClick&&s.onOverlayClick(o),a.parents("div."+s.blockMsgClass).length>0?!0:0===a.parents().children().filter("div.blockUI").length}function
 l(e){if(p){var o=p[e===!0?p.length-1:0];o&&o.focus()}}function a(e,o,t){var 
i=e.parentNode,n=e.style,s=(i.offsetWidth-e.offsetWidth)/2-d(i,"borderLeftWidth"),l=(i.offsetHeight-e.offsetHeight)/2-d(i,"borderTopWidth");o&&(n.left=s>0?s+"px":"0"),t&&(n.top=l>0?l+"px":"0")}function
 d(o,t){return parseInt(e.css(o,t),10)||0}e.fn._fadeIn=e.fn.fadeIn;var 
c=e.noop||function(){},r=/MSIE/.test(navigator.userAgent),u=/MSIE 
6.0/.test(navigator.userAgent)&&!/MSIE 
8.0/.test(navigator.userAgent);document.documentMode||0;var 
f=e.isFunction(document.createElement("div").style.setExpression);e.blockUI=function(e){o(window,e)},e.unblockUI=function(e){t(window,e)},e.growlUI=function(o,t,i,n){var
 s=e('<div clas
 
s="growlUI"></div>');o&&s.append("<h1>"+o+"</h1>"),t&&s.append("<h2>"+t+"</h2>"),void
 0===i&&(i=3e3);var 
l=function(o){o=o||{},e.blockUI({message:s,fadeIn:o.fadeIn!==void 
0?o.fadeIn:700,fadeOut:o.fadeOut!==void 
0?o.fadeOut:1e3,timeout:o.timeout!==void 
0?o.timeout:i,centerY:!1,showOverlay:!1,onUnblock:n,css:e.blockUI.defaults.growlCSS})};l(),s.css("opacity"),s.mouseover(function(){l({fadeIn:0,timeout:3e4});var
 
o=e(".blockMsg");o.stop(),o.fadeTo(300,1)}).mouseout(function(){e(".blockMsg").fadeOut(1e3)})},e.fn.block=function(t){if(this[0]===window)return
 e.blockUI(t),this;var i=e.extend({},e.blockUI.defaults,t||{});return 
this.each(function(){var 
o=e(this);i.ignoreIfBlocked&&o.data("blockUI.isBlocked")||o.unblock({fadeOut:0})}),this.each(function(){"static"==e.css(this,"position")&&(this.style.position="relative",e(this).data("blockUI.static",!0)),this.style.zoom=1,o(this,t)})},e.fn.unblock=function(o){return
 this[0]===window?(e.unblockUI(o),this):this.each(function(){t(this,o)})},e.bl
 ockUI.version=2.66,e.blockUI.defaults={message:"<h1>Please 
wait...</h1>",title:null,draggable:!0,theme:!1,css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px
 solid 
#aaa",backgroundColor:"#fff",cursor:"wait"},themedCSS:{width:"30%",top:"40%",left:"35%"},overlayCSS:{backgroundColor:"#000",opacity:.6,cursor:"wait"},cursorReset:"default",growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:.6,cursor:"default",color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px","border-radius":"10px"},iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",forceIframe:!1,baseZ:1e3,centerX:!0,centerY:!0,allowBodyStretch:!0,bindEvents:!0,constrainTabKey:!0,fadeIn:200,fadeOut:400,timeout:0,showOverlay:!0,focusInput:!0,focusableElements:":input:enabled:visible",onBlock:null,onUnblock:null,onOverlayClick:null,quirksmodeOffsetHack:4,blockMsgClass:"blockM
 sg",ignoreIfBlocked:!1};var b=null,p=[]}"function"==typeof 
define&&define.amd&&define.amd.jQuery?define(["jquery"],e):e(jQuery)})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/jquery.cookies.2.2.0.min.js
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/jquery.cookies.2.2.0.min.js
 
b/core/src/main/resources/org/apache/spark/ui/static/jquery.cookies.2.2.0.min.js
new file mode 100644
index 0000000..bd2dacb
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/jquery.cookies.2.2.0.min.js
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2005 - 2010, James Auldridge
+ * All rights reserved.
+ *
+ * Licensed under the BSD, MIT, and GPL (your choice!) Licenses:
+ *  http://code.google.com/p/cookies/wiki/License
+ *
+ */
+var 
jaaulde=window.jaaulde||{};jaaulde.utils=jaaulde.utils||{};jaaulde.utils.cookies=(function(){var
 
resolveOptions,assembleOptionsString,parseCookies,constructor,defaultOptions={expiresAt:null,path:'/',domain:null,secure:false};resolveOptions=function(options){var
 returnValue,expireDate;if(typeof 
options!=='object'||options===null){returnValue=defaultOptions;}else
+{returnValue={expiresAt:defaultOptions.expiresAt,path:defaultOptions.path,domain:defaultOptions.domain,secure:defaultOptions.secure};if(typeof
 options.expiresAt==='object'&&options.expiresAt instanceof 
Date){returnValue.expiresAt=options.expiresAt;}else if(typeof 
options.hoursToLive==='number'&&options.hoursToLive!==0){expireDate=new 
Date();expireDate.setTime(expireDate.getTime()+(options.hoursToLive*60*60*1000));returnValue.expiresAt=expireDate;}if(typeof
 
options.path==='string'&&options.path!==''){returnValue.path=options.path;}if(typeof
 
options.domain==='string'&&options.domain!==''){returnValue.domain=options.domain;}if(options.secure===true){returnValue.secure=options.secure;}}return
 
returnValue;};assembleOptionsString=function(options){options=resolveOptions(options);return((typeof
 options.expiresAt==='object'&&options.expiresAt instanceof Date?'; 
expires='+options.expiresAt.toGMTString():'')+'; path='+options.path+(typeof 
options.domain==='string'?'; domain='+options.domain:'
 ')+(options.secure===true?'; secure':''));};parseCookies=function(){var 
cookies={},i,pair,name,value,separated=document.cookie.split(';'),unparsedValue;for(i=0;i<separated.length;i=i+1){pair=separated[i].split('=');name=pair[0].replace(/^\s*/,'').replace(/\s*$/,'');try
+{value=decodeURIComponent(pair[1]);}catch(e1){value=pair[1];}if(typeof 
JSON==='object'&&JSON!==null&&typeof JSON.parse==='function'){try
+{unparsedValue=value;value=JSON.parse(value);}catch(e2){value=unparsedValue;}}cookies[name]=value;}return
 
cookies;};constructor=function(){};constructor.prototype.get=function(cookieName){var
 returnValue,item,cookies=parseCookies();if(typeof 
cookieName==='string'){returnValue=(typeof 
cookies[cookieName]!=='undefined')?cookies[cookieName]:null;}else if(typeof 
cookieName==='object'&&cookieName!==null){returnValue={};for(item in 
cookieName){if(typeof 
cookies[cookieName[item]]!=='undefined'){returnValue[cookieName[item]]=cookies[cookieName[item]];}else
+{returnValue[cookieName[item]]=null;}}}else
+{returnValue=cookies;}return 
returnValue;};constructor.prototype.filter=function(cookieNameRegExp){var 
cookieName,returnValue={},cookies=parseCookies();if(typeof 
cookieNameRegExp==='string'){cookieNameRegExp=new 
RegExp(cookieNameRegExp);}for(cookieName in 
cookies){if(cookieName.match(cookieNameRegExp)){returnValue[cookieName]=cookies[cookieName];}}return
 
returnValue;};constructor.prototype.set=function(cookieName,value,options){if(typeof
 options!=='object'||options===null){options={};}if(typeof 
value==='undefined'||value===null){value='';options.hoursToLive=-8760;}else 
if(typeof value!=='string'){if(typeof JSON==='object'&&JSON!==null&&typeof 
JSON.stringify==='function'){value=JSON.stringify(value);}else
+{throw new Error('cookies.set() received non-string value and could not 
serialize.');}}var 
optionsString=assembleOptionsString(options);document.cookie=cookieName+'='+encodeURIComponent(value)+optionsString;};constructor.prototype.del=function(cookieName,options){var
 allCookies={},name;if(typeof 
options!=='object'||options===null){options={};}if(typeof 
cookieName==='boolean'&&cookieName===true){allCookies=this.get();}else 
if(typeof cookieName==='string'){allCookies[cookieName]=true;}for(name in 
allCookies){if(typeof 
name==='string'&&name!==''){this.set(name,null,options);}}};constructor.prototype.test=function(){var
 
returnValue=false,testName='cT',testValue='data';this.set(testName,testValue);if(this.get(testName)===testValue){this.del(testName);returnValue=true;}return
 returnValue;};constructor.prototype.setOptions=function(options){if(typeof 
options!=='object'){options=null;}defaultOptions=resolveOptions(options);};return
 new constructor();})();(function(){if(window.jQuery){(funct
 ion($){$.cookies=jaaulde.utils.cookies;var 
extensions={cookify:function(options){return this.each(function(){var 
i,nameAttrs=['name','id'],name,$this=$(this),value;for(i in 
nameAttrs){if(!isNaN(i)){name=$this.attr(nameAttrs[i]);if(typeof 
name==='string'&&name!==''){if($this.is(':checkbox, 
:radio')){if($this.attr('checked')){value=$this.val();}}else 
if($this.is(':input')){value=$this.val();}else
+{value=$this.html();}if(typeof 
value!=='string'||value===''){value=null;}$.cookies.set(name,value,options);break;}}}});},cookieFill:function(){return
 this.each(function(){var 
n,getN,nameAttrs=['name','id'],name,$this=$(this),value;getN=function(){n=nameAttrs.pop();return!!n;};while(getN()){name=$this.attr(n);if(typeof
 
name==='string'&&name!==''){value=$.cookies.get(name);if(value!==null){if($this.is(':checkbox,
 :radio')){if($this.val()===value){$this.attr('checked','checked');}else
+{$this.removeAttr('checked');}}else 
if($this.is(':input')){$this.val(value);}else
+{$this.html(value);}}break;}}});},cookieBind:function(options){return 
this.each(function(){var 
$this=$(this);$this.cookieFill().change(function(){$this.cookify(options);});});}};$.each(extensions,function(i){$.fn[i]=this;});})(window.jQuery);}})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/spark/blob/e4c1162b/core/src/main/resources/org/apache/spark/ui/static/jquery.dataTables.1.10.4.min.css
----------------------------------------------------------------------
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/jquery.dataTables.1.10.4.min.css
 
b/core/src/main/resources/org/apache/spark/ui/static/jquery.dataTables.1.10.4.min.css
new file mode 100644
index 0000000..a2c5489
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/jquery.dataTables.1.10.4.min.css
@@ -0,0 +1 @@
+table.dataTable{width:100%;margin:0 
auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead 
th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead 
th,table.dataTable thead td{padding:10px 18px;border-bottom:1px solid 
#111}table.dataTable thead th:active,table.dataTable thead 
td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot 
td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.dataTable thead 
.sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead 
.sorting{cursor:pointer;*cursor:hand}table.dataTable thead 
.sorting{background:url("../images/sort_both.png") no-repeat center 
right}table.dataTable thead 
.sorting_asc{background:url("../images/sort_asc.png") no-repeat center 
right}table.dataTable thead 
.sorting_desc{background:url("../images/sort_desc.png") no-repeat center 
right}table.dataTable thead 
.sorting_asc_disabled{background:url("../images/sort_asc_disabled.png") 
no-repeat center right}table.dataTable 
 thead 
.sorting_desc_disabled{background:url("../images/sort_desc_disabled.png") 
no-repeat center right}table.dataTable tbody 
tr{background-color:#fff}table.dataTable tbody 
tr.selected{background-color:#b0bed9}table.dataTable tbody th,table.dataTable 
tbody td{padding:8px 10px}table.dataTable.row-border tbody 
th,table.dataTable.row-border tbody td,table.dataTable.display tbody 
th,table.dataTable.display tbody td{border-top:1px solid 
#ddd}table.dataTable.row-border tbody tr:first-child 
th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display 
tbody tr:first-child th,table.dataTable.display tbody tr:first-child 
td{border-top:none}table.dataTable.cell-border tbody 
th,table.dataTable.cell-border tbody td{border-top:1px solid 
#ddd;border-right:1px solid #ddd}table.dataTable.cell-border tbody tr 
th:first-child,table.dataTable.cell-border tbody tr 
td:first-child{border-left:1px solid #ddd}table.dataTable.cell-border tbody 
tr:first-child th,table.dataTable.cell-border tbod
 y tr:first-child td{border-top:none}table.dataTable.stripe tbody 
tr.odd,table.dataTable.display tbody 
tr.odd{background-color:#f9f9f9}table.dataTable.stripe tbody 
tr.odd.selected,table.dataTable.display tbody 
tr.odd.selected{background-color:#abb9d3}table.dataTable.hover tbody 
tr:hover,table.dataTable.hover tbody tr.odd:hover,table.dataTable.hover tbody 
tr.even:hover,table.dataTable.display tbody tr:hover,table.dataTable.display 
tbody tr.odd:hover,table.dataTable.display tbody 
tr.even:hover{background-color:#f5f5f5}table.dataTable.hover tbody 
tr:hover.selected,table.dataTable.hover tbody 
tr.odd:hover.selected,table.dataTable.hover tbody 
tr.even:hover.selected,table.dataTable.display tbody 
tr:hover.selected,table.dataTable.display tbody 
tr.odd:hover.selected,table.dataTable.display tbody 
tr.even:hover.selected{background-color:#a9b7d1}table.dataTable.order-column 
tbody tr>.sorting_1,table.dataTable.order-column tbody 
tr>.sorting_2,table.dataTable.order-column tbody tr>.sorting_3,tabl
 e.dataTable.display tbody tr>.sorting_1,table.dataTable.display tbody 
tr>.sorting_2,table.dataTable.display tbody 
tr>.sorting_3{background-color:#f9f9f9}table.dataTable.order-column tbody 
tr.selected>.sorting_1,table.dataTable.order-column tbody 
tr.selected>.sorting_2,table.dataTable.order-column tbody 
tr.selected>.sorting_3,table.dataTable.display tbody 
tr.selected>.sorting_1,table.dataTable.display tbody 
tr.selected>.sorting_2,table.dataTable.display tbody 
tr.selected>.sorting_3{background-color:#acbad4}table.dataTable.display tbody 
tr.odd>.sorting_1,table.dataTable.order-column.stripe tbody 
tr.odd>.sorting_1{background-color:#f1f1f1}table.dataTable.display tbody 
tr.odd>.sorting_2,table.dataTable.order-column.stripe tbody 
tr.odd>.sorting_2{background-color:#f3f3f3}table.dataTable.display tbody 
tr.odd>.sorting_3,table.dataTable.order-column.stripe tbody 
tr.odd>.sorting_3{background-color:#f5f5f5}table.dataTable.display tbody 
tr.odd.selected>.sorting_1,table.dataTable.order-column.s
 tripe tbody 
tr.odd.selected>.sorting_1{background-color:#a6b3cd}table.dataTable.display 
tbody tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody 
tr.odd.selected>.sorting_2{background-color:#a7b5ce}table.dataTable.display 
tbody tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody 
tr.odd.selected>.sorting_3{background-color:#a9b6d0}table.dataTable.display 
tbody tr.even>.sorting_1,table.dataTable.order-column.stripe tbody 
tr.even>.sorting_1{background-color:#f9f9f9}table.dataTable.display tbody 
tr.even>.sorting_2,table.dataTable.order-column.stripe tbody 
tr.even>.sorting_2{background-color:#fbfbfb}table.dataTable.display tbody 
tr.even>.sorting_3,table.dataTable.order-column.stripe tbody 
tr.even>.sorting_3{background-color:#fdfdfd}table.dataTable.display tbody 
tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody 
tr.even.selected>.sorting_1{background-color:#acbad4}table.dataTable.display 
tbody tr.even.selected>.sorting_2,table.dataTable
 .order-column.stripe tbody 
tr.even.selected>.sorting_2{background-color:#adbbd6}table.dataTable.display 
tbody tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody 
tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display 
tbody tr:hover>.sorting_1,table.dataTable.display tbody 
tr.odd:hover>.sorting_1,table.dataTable.display tbody 
tr.even:hover>.sorting_1,table.dataTable.order-column.hover tbody 
tr:hover>.sorting_1,table.dataTable.order-column.hover tbody 
tr.odd:hover>.sorting_1,table.dataTable.order-column.hover tbody 
tr.even:hover>.sorting_1{background-color:#eaeaea}table.dataTable.display tbody 
tr:hover>.sorting_2,table.dataTable.display tbody 
tr.odd:hover>.sorting_2,table.dataTable.display tbody 
tr.even:hover>.sorting_2,table.dataTable.order-column.hover tbody 
tr:hover>.sorting_2,table.dataTable.order-column.hover tbody 
tr.odd:hover>.sorting_2,table.dataTable.order-column.hover tbody 
tr.even:hover>.sorting_2{background-color:#ebebeb}table.dataTa
 ble.display tbody tr:hover>.sorting_3,table.dataTable.display tbody 
tr.odd:hover>.sorting_3,table.dataTable.display tbody 
tr.even:hover>.sorting_3,table.dataTable.order-column.hover tbody 
tr:hover>.sorting_3,table.dataTable.order-column.hover tbody 
tr.odd:hover>.sorting_3,table.dataTable.order-column.hover tbody 
tr.even:hover>.sorting_3{background-color:#eee}table.dataTable.display tbody 
tr:hover.selected>.sorting_1,table.dataTable.display tbody 
tr.odd:hover.selected>.sorting_1,table.dataTable.display tbody 
tr.even:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody 
tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody 
tr.odd:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody 
tr.even:hover.selected>.sorting_1{background-color:#a1aec7}table.dataTable.display
 tbody tr:hover.selected>.sorting_2,table.dataTable.display tbody 
tr.odd:hover.selected>.sorting_2,table.dataTable.display tbody 
tr.even:hover.selected>.sorting_2,table.dataTable.orde
 r-column.hover tbody 
tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody 
tr.odd:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody 
tr.even:hover.selected>.sorting_2{background-color:#a2afc8}table.dataTable.display
 tbody tr:hover.selected>.sorting_3,table.dataTable.display tbody 
tr.odd:hover.selected>.sorting_3,table.dataTable.display tbody 
tr.even:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody 
tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody 
tr.odd:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody 
tr.even:hover.selected>.sorting_3{background-color:#a4b2cb}table.dataTable.no-footer{border-bottom:1px
 solid #111}table.dataTable.nowrap th,table.dataTable.nowrap 
td{white-space:nowrap}table.dataTable.compact thead th,table.dataTable.compact 
thead td{padding:5px 9px}table.dataTable.compact tfoot 
th,table.dataTable.compact tfoot td{padding:5px 9px 3px 
9px}table.dataTable.compact tbody th,table.dataTa
 ble.compact tbody td{padding:4px 5px}table.dataTable 
th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable 
th.dt-center,table.dataTable td.dt-center,table.dataTable 
td.dataTables_empty{text-align:center}table.dataTable 
th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable 
th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable 
th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable 
thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable 
tfoot th.dt-head-left,table.dataTable tfoot 
td.dt-head-left{text-align:left}table.dataTable thead 
th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot 
th.dt-head-center,table.dataTable tfoot 
td.dt-head-center{text-align:center}table.dataTable thead 
th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot 
th.dt-head-right,table.dataTable tfoot 
td.dt-head-right{text-align:right}table.dataTable thead th.dt-he
 ad-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot 
th.dt-head-justify,table.dataTable tfoot 
td.dt-head-justify{text-align:justify}table.dataTable thead 
th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot 
th.dt-head-nowrap,table.dataTable tfoot 
td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody 
th.dt-body-left,table.dataTable tbody 
td.dt-body-left{text-align:left}table.dataTable tbody 
th.dt-body-center,table.dataTable tbody 
td.dt-body-center{text-align:center}table.dataTable tbody 
th.dt-body-right,table.dataTable tbody 
td.dt-body-right{text-align:right}table.dataTable tbody 
th.dt-body-justify,table.dataTable tbody 
td.dt-body-justify{text-align:justify}table.dataTable tbody 
th.dt-body-nowrap,table.dataTable tbody 
td.dt-body-nowrap{white-space:nowrap}table.dataTable,table.dataTable 
th,table.dataTable 
td{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.dataTables_wrapper{position:relative;clear:
 both;*zoom:1;zoom:1}.dataTables_wrapper 
.dataTables_length{float:left}.dataTables_wrapper 
.dataTables_filter{float:right;text-align:right}.dataTables_wrapper 
.dataTables_filter input{margin-left:0.5em}.dataTables_wrapper 
.dataTables_info{clear:both;float:left;padding-top:0.755em}.dataTables_wrapper 
.dataTables_paginate{float:right;text-align:right;padding-top:0.25em}.dataTables_wrapper
 .dataTables_paginate 
.paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:0.5em
 1em;margin-left:2px;text-align:center;text-decoration:none 
!important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid 
transparent}.dataTables_wrapper .dataTables_paginate 
.paginate_button.current,.dataTables_wrapper .dataTables_paginate 
.paginate_button.current:hover{color:#333 !important;border:1px solid 
#cacaca;background-color:#fff;background:-webkit-gradient(linear, left top, 
left bottom, color-stop(0%, #fff), color-stop(100%, 
#dcdcdc));background:-webkit-linear-gradien
 t(top, #fff 0%, #dcdcdc 100%);background:-moz-linear-gradient(top, #fff 0%, 
#dcdcdc 100%);background:-ms-linear-gradient(top, #fff 0%, #dcdcdc 
100%);background:-o-linear-gradient(top, #fff 0%, #dcdcdc 
100%);background:linear-gradient(to bottom, #fff 0%, #dcdcdc 
100%)}.dataTables_wrapper .dataTables_paginate 
.paginate_button.disabled,.dataTables_wrapper .dataTables_paginate 
.paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate 
.paginate_button.disabled:active{cursor:default;color:#666 
!important;border:1px solid 
transparent;background:transparent;box-shadow:none}.dataTables_wrapper 
.dataTables_paginate .paginate_button:hover{color:white !important;border:1px 
solid #111;background-color:#585858;background:-webkit-gradient(linear, left 
top, left bottom, color-stop(0%, #585858), color-stop(100%, 
#111));background:-webkit-linear-gradient(top, #585858 0%, #111 
100%);background:-moz-linear-gradient(top, #585858 0%, #111 
100%);background:-ms-linear-gradient(top, #585858 0
 %, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 
100%);background:linear-gradient(to bottom, #585858 0%, #111 
100%)}.dataTables_wrapper .dataTables_paginate 
.paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear,
 left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, 
#0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 
100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 
100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 
100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 
100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 
100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper 
.dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear,
 left top, right top, color-stop(0%, rgba(255,255,255,0)), c
 olor-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), 
color-stop(100%, rgba(255,255,255,0)));background:-webkit-linear-gradient(left, 
rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, 
rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left, 
rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, 
rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left, 
rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, 
rgba(255,255,255,0) 100%);background:-o-linear-gradient(left, 
rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, 
rgba(255,255,255,0) 100%);background:linear-gradient(to right, 
rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, 
rgba(255,255,255,0) 100%)}.dataTables_wrapper 
.dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper 
.dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_
 wrapper .dataTables_paginate{color:#333}.dataTables_wrapper 
.dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll 
div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.dataTables_wrapper
 .dataTables_scroll div.dataTables_scrollBody 
th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll 
div.dataTables_scrollBody 
td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 
!important}.dataTables_wrapper.no-footer 
.dataTables_scrollBody{border-bottom:1px solid 
#111}.dataTables_wrapper.no-footer div.dataTables_scrollHead 
table,.dataTables_wrapper.no-footer div.dataTables_scrollBody 
table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media
 screen and (max-width: 767px){.dataTables_wrapper 
.dataTables_info,.dataTables_wrapper 
.dataTables_paginate{float:none;text-align:center}.dataTables_wrapper 
.dataTables_paginate{margin-top:0.5em}}@media screen and (max-width:
  640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper 
.dataTables_filter{float:none;text-align:center}.dataTables_wrapper 
.dataTables_filter{margin-top:0.5em}}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org
For additional commands, e-mail: commits-h...@spark.apache.org

Reply via email to