2010-10-20 20:11:15 +02:00
/ *
Copyright 2010 , Google Inc .
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
2011-08-04 22:37:14 +02:00
* Redistributions of source code must retain the above copyright
2010-10-20 20:11:15 +02:00
notice , this list of conditions and the following disclaimer .
2011-08-04 22:37:14 +02:00
* Redistributions in binary form must reproduce the above
2010-10-20 20:11:15 +02:00
copyright notice , this list of conditions and the following disclaimer
in the documentation and / or other materials provided with the
distribution .
2011-08-04 22:37:14 +02:00
* Neither the name of Google Inc . nor the names of its
2010-10-20 20:11:15 +02:00
contributors may be used to endorse or promote products derived from
this software without specific prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
2011-08-04 22:37:14 +02:00
* /
2010-10-20 20:11:15 +02:00
2010-02-27 01:16:44 +01:00
function BrowsingEngine ( div , facetConfigs ) {
2011-08-04 22:37:14 +02:00
this . _div = div ;
this . _mode = theProject . recordModel . hasRecords ? 'record-based' : 'row-based' ;
this . _facets = [ ] ;
this . _initializeUI ( ) ;
if ( facetConfigs . length > 0 ) {
for ( var i = 0 ; i < facetConfigs . length ; i ++ ) {
var facetConfig = facetConfigs [ i ] ;
var type = facetConfig . c . type ;
var elmt = this . _createFacetContainer ( ) ;
var facet ;
switch ( type ) {
case "range" :
facet = RangeFacet . reconstruct ( elmt , facetConfig ) ;
break ;
case "timerange" :
facet = TimeRangeFacet . reconstruct ( elmt , facetConfig ) ;
break ;
case "scatterplot" :
facet = ScatterplotFacet . reconstruct ( elmt , facetConfig ) ;
break ;
case "text" :
facet = TextSearchFacet . reconstruct ( elmt , facetConfig ) ;
break ;
default :
facet = ListFacet . reconstruct ( elmt , facetConfig ) ;
}
this . _facets . push ( { elmt : elmt , facet : facet } ) ;
2010-02-27 01:16:44 +01:00
}
2011-08-04 22:37:14 +02:00
}
2010-02-27 01:16:44 +01:00
}
2010-03-22 22:48:36 +01:00
BrowsingEngine . prototype . resize = function ( ) {
2011-08-04 22:37:14 +02:00
if ( this . _facets . length > 0 ) {
var body = this . _div . find ( ".facets-container" ) ;
var bodyPaddings = body . outerHeight ( true ) - body . height ( ) ;
var height =
this . _div . height ( ) -
this . _div . find ( ".browsing-panel-header" ) . outerHeight ( true ) -
bodyPaddings ;
body . css ( "height" , height + "px" ) ;
this . _elmts . facets . sortable ( "refresh" ) ;
}
2010-03-22 22:48:36 +01:00
} ;
2010-02-27 01:16:44 +01:00
BrowsingEngine . prototype . getFacetUIStates = function ( ) {
2011-08-04 22:37:14 +02:00
var f = [ ] ;
for ( var i = 0 ; i < this . _facets . length ; i ++ ) {
var facet = this . _facets [ i ] ;
f . push ( facet . facet . getUIState ( ) ) ;
}
return f ;
2010-04-08 21:52:23 +02:00
} ;
2010-01-29 01:46:15 +01:00
2010-01-30 02:05:30 +01:00
BrowsingEngine . prototype . _initializeUI = function ( ) {
2011-08-04 22:37:14 +02:00
var self = this ;
this . _div . html (
'<div class="browsing-panel-help" bind="help">' +
'<h1>Using facets and filters</h1>' +
'<p>Use facets and filters to select subsets of your data to act on. Choose facet and filter methods from the menus at the top of each data column.</p>' +
'<p>Not sure how to get started?<br /><a href="http://code.google.com/p/google-refine/wiki/Screencasts" target="_blank"><b>Watch these screencasts</b></a></p>' +
'</div>' +
'<div class="browsing-panel-header" bind="header">' +
'<div class="browsing-panel-indicator" bind="indicator">' +
'<img src="images/small-spinner.gif" /> Refreshing facets...' +
'</div>' +
'<div class="browsing-panel-controls" bind="controls">' +
'<div class="browsing-panel-controls-refresh">' +
'<a href="javascript:{}" bind="refreshLink" class="button" title="Update all facets">Refresh</a>' +
'</div>' +
'<a href="javascript:{}" bind="resetLink" class="button button-pill-left" title="Clear selection in all facets">Reset All</a>' +
'<a href="javascript:{}" bind="removeLink" class="button button-pill-right" title="Remove all facets">Remove All</a>' +
'</div>' +
'</div>' +
'<ul bind="facets" class="facets-container"></ul>'
) ;
this . _elmts = DOM . bind ( this . _div ) ;
this . _elmts . facets . sortable ( {
handle : '.facet-title' ,
update : function ( event , ui ) {
self . _updateFacetOrder ( ) ;
}
} ) ;
this . _elmts . refreshLink . click ( function ( ) { self . update ( ) ; } ) ;
this . _elmts . resetLink . click ( function ( ) { self . reset ( ) ; } ) ;
this . _elmts . removeLink . click ( function ( ) { self . remove ( ) ; } ) ;
2010-03-02 23:32:52 +01:00
} ;
BrowsingEngine . prototype . _updateFacetOrder = function ( ) {
2011-08-04 22:37:14 +02:00
var elmts = this . _elmts . facets . children ( ) ;
var newFacets = [ ] ;
for ( var e = 0 ; e < elmts . length ; e ++ ) {
var elmt = elmts [ e ] ;
for ( var f = 0 ; f < this . _facets . length ; f ++ ) {
if ( elmt === this . _facets [ f ] . elmt [ 0 ] ) {
newFacets . push ( this . _facets [ f ] ) ;
break ;
}
2010-03-02 23:32:52 +01:00
}
2011-08-04 22:37:14 +02:00
}
this . _facets = newFacets ;
2010-01-29 01:46:15 +01:00
} ;
2010-07-30 04:25:58 +02:00
BrowsingEngine . prototype . getMode = function ( ) {
2011-08-04 22:37:14 +02:00
return this . _mode ;
2010-10-06 21:15:29 +02:00
} ;
BrowsingEngine . prototype . setMode = function ( mode ) {
2011-08-04 22:37:14 +02:00
if ( this . _mode != mode ) {
this . _mode = mode ;
Refine . update ( { engineChanged : true } ) ;
}
2010-07-30 04:25:58 +02:00
} ;
2010-04-17 07:59:25 +02:00
BrowsingEngine . prototype . getJSON = function ( keepUnrestrictedFacets , except ) {
2011-08-04 22:37:14 +02:00
var a = {
facets : [ ] ,
mode : this . _mode
} ;
for ( var i = 0 ; i < this . _facets . length ; i ++ ) {
var facet = this . _facets [ i ] ;
if ( ( keepUnrestrictedFacets || facet . facet . hasSelection ( ) ) && ( facet . facet !== except ) ) {
a . facets . push ( facet . facet . getJSON ( ) ) ;
2010-01-29 01:46:15 +01:00
}
2011-08-04 22:37:14 +02:00
}
return a ;
2010-01-29 01:46:15 +01:00
} ;
2010-01-30 02:05:30 +01:00
2010-02-02 02:36:02 +01:00
BrowsingEngine . prototype . addFacet = function ( type , config , options ) {
2011-08-04 22:37:14 +02:00
var elmt = this . _createFacetContainer ( ) ;
var facet ;
switch ( type ) {
case "range" :
facet = new RangeFacet ( elmt , config , options ) ;
break ;
case "timerange" :
facet = new TimeRangeFacet ( elmt , config , options ) ;
break ;
case "scatterplot" :
facet = new ScatterplotFacet ( elmt , config , options ) ;
break ;
case "text" :
facet = new TextSearchFacet ( elmt , config , options ) ;
break ;
default :
facet = new ListFacet ( elmt , config , options ) ;
}
this . _facets . push ( { elmt : elmt , facet : facet } ) ;
ui . leftPanelTabs . tabs ( "select" , 0 ) ;
Refine . update ( { engineChanged : true } ) ;
2010-01-30 02:05:30 +01:00
} ;
2010-03-02 23:32:52 +01:00
BrowsingEngine . prototype . _createFacetContainer = function ( ) {
2011-08-04 22:37:14 +02:00
return $ ( '<li></li>' ) . addClass ( "facet-container" ) . attr ( "id" , "facet-" + this . _facets . length ) . hide ( ) . appendTo ( this . _elmts . facets ) ;
2010-03-02 23:32:52 +01:00
} ;
2010-02-01 01:19:41 +01:00
BrowsingEngine . prototype . removeFacet = function ( facet ) {
2011-08-04 22:37:14 +02:00
var update = facet . hasSelection ( ) ;
for ( var i = this . _facets . length - 1 ; i >= 0 ; i -- ) {
var facetRecord = this . _facets [ i ] ;
if ( facetRecord . facet === facet ) {
this . _facets . splice ( i , 1 ) ;
2010-04-24 08:29:30 +02:00
2011-08-04 22:37:14 +02:00
facetRecord . facet . dispose ( ) ;
// This makes really big facet disappear right away. If you just call remove()
// then it takes a while for all the event handlers to get unwired, and the UI
// appear frozen.
facetRecord . elmt . hide ( ) ;
window . setTimeout ( function ( ) {
facetRecord . elmt . remove ( ) ;
} , 300 ) ;
break ;
2010-02-01 01:19:41 +01:00
}
2011-08-04 22:37:14 +02:00
}
for ( var i = 0 ; i < this . _facets . length ; i ++ ) {
if ( typeof this . _facets [ i ] . facet . update == "function" ) {
this . _facets [ i ] . facet . update ( ) ;
2010-02-01 01:19:41 +01:00
}
2011-08-04 22:37:14 +02:00
}
if ( update ) {
Refine . update ( { engineChanged : true } ) ;
2011-10-08 01:44:11 +02:00
} else if ( this . _facets . length === 0 ) {
2011-08-04 22:37:14 +02:00
this . _elmts . help . show ( ) ;
this . _elmts . header . hide ( ) ;
}
2010-02-01 01:19:41 +01:00
} ;
2010-02-26 22:56:41 +01:00
BrowsingEngine . prototype . update = function ( onDone ) {
2011-08-04 22:37:14 +02:00
var self = this ;
this . _elmts . help . hide ( ) ;
this . _elmts . header . show ( ) ;
this . _elmts . controls . css ( "visibility" , "hidden" ) ;
this . _elmts . indicator . css ( "visibility" , "visible" ) ;
$ . post (
2012-10-13 19:47:08 +02:00
"command/core/compute-facets?" + $ . param ( { project : theProject . id } ) ,
2011-08-04 22:37:14 +02:00
{ engine : JSON . stringify ( this . getJSON ( true ) ) } ,
function ( data ) {
var facetData = data . facets ;
for ( var i = 0 ; i < facetData . length ; i ++ ) {
self . _facets [ i ] . facet . updateState ( facetData [ i ] ) ;
}
self . _elmts . indicator . css ( "visibility" , "hidden" ) ;
if ( self . _facets . length > 0 ) {
self . _elmts . header . show ( ) ;
self . _elmts . controls . css ( "visibility" , "visible" ) ;
self . resize ( ) ;
} else {
self . _elmts . help . show ( ) ;
}
if ( onDone ) {
onDone ( ) ;
}
} ,
"json"
) ;
2010-01-30 02:05:30 +01:00
} ;
2010-03-23 19:53:29 +01:00
BrowsingEngine . prototype . reset = function ( ) {
2011-08-04 22:37:14 +02:00
for ( var i = 0 ; i < this . _facets . length ; i ++ ) {
this . _facets [ i ] . facet . reset ( ) ;
}
Refine . update ( { engineChanged : true } ) ;
2010-03-23 19:53:29 +01:00
} ;
BrowsingEngine . prototype . remove = function ( ) {
2011-08-04 22:37:14 +02:00
var oldFacets = this . _facets ;
this . _facets = [ ] ;
for ( var i = 0 ; i < oldFacets . length ; i ++ ) {
var facet = oldFacets [ i ] ;
facet . facet . dispose ( ) ;
facet . elmt . hide ( ) ;
}
window . setTimeout ( function ( ) {
2010-03-23 19:53:29 +01:00
for ( var i = 0 ; i < oldFacets . length ; i ++ ) {
2011-08-04 22:37:14 +02:00
oldFacets [ i ] . elmt . remove ( ) ;
2010-03-23 19:53:29 +01:00
}
2011-08-04 22:37:14 +02:00
} , 300 ) ;
Refine . update ( { engineChanged : true } ) ;
2010-03-23 19:53:29 +01:00
} ;