2013-06-11 09:50:56 +00:00
/ * *
* @ fileoverview Entry point for the blob browser UI .
*
* /
goog . provide ( 'camlistore.IndexPage' ) ;
2012-11-09 18:35:59 +00:00
2013-06-11 09:50:56 +00:00
goog . require ( 'goog.array' ) ;
goog . require ( 'goog.dom' ) ;
goog . require ( 'goog.dom.classes' ) ;
goog . require ( 'goog.events.EventHandler' ) ;
goog . require ( 'goog.events.EventType' ) ;
2013-10-14 01:12:53 +00:00
goog . require ( 'goog.string' ) ;
2013-10-17 06:45:36 +00:00
goog . require ( 'goog.Uri' ) ;
2013-06-11 09:50:56 +00:00
goog . require ( 'goog.ui.Component' ) ;
goog . require ( 'goog.ui.Textarea' ) ;
goog . require ( 'camlistore.BlobItemContainer' ) ;
2013-12-17 02:55:38 +00:00
goog . require ( 'camlistore.Nav' ) ;
2013-06-11 09:50:56 +00:00
goog . require ( 'camlistore.ServerConnection' ) ;
goog . require ( 'camlistore.ServerType' ) ;
2012-11-09 18:35:59 +00:00
2013-06-11 09:50:56 +00:00
camlistore . IndexPage = function ( config , opt _domHelper ) {
2013-12-20 17:59:47 +00:00
goog . base ( this , opt _domHelper ) ;
this . config _ = config ;
this . connection _ = new camlistore . ServerConnection ( config ) ;
this . eh _ = new goog . events . EventHandler ( this ) ;
// We have to store this because Firefox and Chrome disagree about whether to fire the popstate event at page load or not. Because of this we need to detect duplicate calls to handleUrl_().
this . currentUrl _ = '' ;
this . blobItemContainer _ = new camlistore . BlobItemContainer ( this . connection _ , opt _domHelper ) ;
this . blobItemContainer _ . isSelectionEnabled = true ;
this . blobItemContainer _ . isFileDragEnabled = true ;
this . nav _ = new camlistore . Nav ( opt _domHelper , this ) ;
this . searchNavItem _ = new camlistore . Nav . SearchItem ( this . dom _ , 'magnifying_glass.svg' , 'Search' ) ;
this . newPermanodeNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'new_permanode.svg' , 'New permanode' ) ;
this . searchRootsNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'icon_27307.svg' , 'Search roots' ) ;
this . selectAsCurrentSetNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'target.svg' , 'Select as current set' ) ;
this . selectAsCurrentSetNavItem _ . setVisible ( false ) ;
this . addToSetNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'icon_16716.svg' , 'Add to set' ) ;
this . addToSetNavItem _ . setVisible ( false ) ;
this . createSetWithSelectionNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'circled_plus.svg' , 'Create set with 5 items' ) ;
this . createSetWithSelectionNavItem _ . setVisible ( false ) ;
this . clearSelectionNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'clear.svg' , 'Clear selection' ) ;
this . clearSelectionNavItem _ . setVisible ( false ) ;
this . embiggenNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'up.svg' , 'Moar bigger' ) ;
this . ensmallenNavItem _ = new camlistore . Nav . Item ( this . dom _ , 'down.svg' , 'Less bigger' ) ;
this . logoNavItem _ = new camlistore . Nav . LinkItem ( this . dom _ , '/favicon.ico' , 'Camlistore' , '/ui/' ) ;
this . logoNavItem _ . addClassName ( 'cam-logo' ) ;
2012-12-12 03:33:15 +00:00
} ;
2013-06-11 09:50:56 +00:00
goog . inherits ( camlistore . IndexPage , goog . ui . Component ) ;
2013-12-17 02:55:38 +00:00
camlistore . IndexPage . prototype . onNavOpen = function ( ) {
2013-12-20 17:59:47 +00:00
var currentWidth = this . getElement ( ) . offsetWidth - 36 ;
var desiredWidth = currentWidth - ( 275 - 36 ) ;
var scale = desiredWidth / currentWidth ;
var currentHeight = goog . dom . getDocumentHeight ( ) ;
var currentScroll = goog . dom . getDocumentScroll ( ) . y ;
var potentialScroll = currentHeight - goog . dom . getViewportSize ( ) . height ;
var originY = currentHeight * currentScroll / potentialScroll ;
console . log ( 'origin y is: %f' , originY ) ;
goog . style . setStyle ( this . blobItemContainer _ . getElement ( ) ,
{ 'transform' : goog . string . subs ( 'scale(%s)' , scale ) ,
'transform-origin' : goog . string . subs ( 'right %spx' , originY ) } ) ;
2013-12-17 02:55:38 +00:00
} ;
camlistore . IndexPage . prototype . onNavClose = function ( ) {
2013-12-20 17:59:47 +00:00
if ( ! this . blobItemContainer _ . getElement ( ) ) {
return ;
}
this . searchNavItem _ . setText ( '' ) ;
this . searchNavItem _ . blur ( ) ;
goog . style . setStyle ( this . blobItemContainer _ . getElement ( ) ,
{ 'transform' : '' } ) ;
2013-12-17 02:55:38 +00:00
} ;
2013-10-14 01:12:53 +00:00
camlistore . IndexPage . SEARCH _PREFIX _ = {
2013-12-20 17:59:47 +00:00
RAW : 'raw'
2013-10-14 01:12:53 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . createDom = function ( ) {
2013-12-20 17:59:47 +00:00
this . decorateInternal ( this . dom _ . createElement ( 'div' ) ) ;
2012-12-12 03:33:15 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . decorateInternal = function ( element ) {
2013-12-20 17:59:47 +00:00
camlistore . IndexPage . superClass _ . decorateInternal . call ( this , element ) ;
var el = this . getElement ( ) ;
goog . dom . classes . add ( el , 'cam-index-page' ) ;
document . title = this . config _ . ownerName + '\'s Vault' ;
this . nav _ . addChild ( this . searchNavItem _ , true ) ;
this . nav _ . addChild ( this . newPermanodeNavItem _ , true ) ;
this . nav _ . addChild ( this . searchRootsNavItem _ , true ) ;
this . nav _ . addChild ( this . selectAsCurrentSetNavItem _ , true ) ;
this . nav _ . addChild ( this . addToSetNavItem _ , true ) ;
this . nav _ . addChild ( this . createSetWithSelectionNavItem _ , true ) ;
this . nav _ . addChild ( this . clearSelectionNavItem _ , true ) ;
this . nav _ . addChild ( this . embiggenNavItem _ , true ) ;
this . nav _ . addChild ( this . ensmallenNavItem _ , true ) ;
this . nav _ . addChild ( this . logoNavItem _ , true ) ;
this . addChild ( this . nav _ , true ) ;
this . addChild ( this . blobItemContainer _ , true ) ;
2012-12-12 03:33:15 +00:00
} ;
2012-12-12 01:45:15 +00:00
2013-12-17 02:55:38 +00:00
camlistore . IndexPage . prototype . updateNavButtonsForSelection _ = function ( ) {
2013-12-20 17:59:47 +00:00
var blobItems = this . blobItemContainer _ . getCheckedBlobItems ( ) ;
var count = blobItems . length ;
if ( count ) {
var txt = 'Create set with ' + count + ' item' + ( count > 1 ? 's' : '' ) ;
this . createSetWithSelectionNavItem _ . setContent ( txt ) ;
this . createSetWithSelectionNavItem _ . setVisible ( true ) ;
this . clearSelectionNavItem _ . setVisible ( true ) ;
} else {
this . createSetWithSelectionNavItem _ . setContent ( '' ) ;
this . createSetWithSelectionNavItem _ . setVisible ( false ) ;
this . clearSelectionNavItem _ . setVisible ( false ) ;
}
if ( this . blobItemContainer _ . currentCollec _ && this . blobItemContainer _ . currentCollec _ != "" && blobItems . length > 0 ) {
this . addToSetNavItem _ . setVisible ( true ) ;
} else {
this . addToSetNavItem _ . setVisible ( false ) ;
}
if ( blobItems . length == 1 && blobItems [ 0 ] . isCollection ( ) ) {
this . selectAsCurrentSetNavItem _ . setVisible ( true ) ;
} else {
this . selectAsCurrentSetNavItem _ . setVisible ( false ) ;
}
2013-12-17 02:55:38 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . disposeInternal = function ( ) {
2013-12-20 17:59:47 +00:00
camlistore . IndexPage . superClass _ . disposeInternal . call ( this ) ;
this . eh _ . dispose ( ) ;
2012-12-12 03:06:47 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . enterDocument = function ( ) {
2013-12-20 17:59:47 +00:00
camlistore . IndexPage . superClass _ . enterDocument . call ( this ) ;
this . connection _ . serverStatus ( goog . bind ( function ( resp ) {
this . handleServerStatus _ ( resp ) ;
} , this ) ) ;
this . eh _ . listen ( window , goog . events . EventType . POPSTATE , this . handleUrl _ ) ;
this . searchNavItem _ . onSearch = this . setUrlSearch _ . bind ( this ) ;
this . embiggenNavItem _ . onClick = function ( ) {
if ( this . blobItemContainer _ . bigger ( ) ) {
var force = true ;
this . blobItemContainer _ . layout _ ( force ) ;
}
} . bind ( this ) ;
this . ensmallenNavItem _ . onClick = function ( ) {
if ( this . blobItemContainer _ . smaller ( ) ) {
// Don't run a query. Let the browser do the image resizing on its own.
var force = true ;
this . blobItemContainer _ . layout _ ( force ) ;
// Since things got smaller, we may need to fetch more content.
this . blobItemContainer _ . handleScroll _ ( ) ;
}
} . bind ( this ) ;
this . createSetWithSelectionNavItem _ . onClick = function ( ) {
var blobItems = this . blobItemContainer _ . getCheckedBlobItems ( ) ;
this . createNewSetWithItems _ ( blobItems ) ;
} . bind ( this ) ;
this . clearSelectionNavItem _ . onClick = this . blobItemContainer _ . unselectAll . bind ( this . blobItemContainer _ ) ;
this . newPermanodeNavItem _ . onClick = function ( ) {
this . connection _ . createPermanode ( function ( p ) {
window . location = './?p=' + p ;
} , function ( failMsg ) {
console . error ( 'Failed to create permanode: ' + failMsg ) ;
} ) ;
} . bind ( this ) ;
this . addToSetNavItem _ . onClick = function ( ) {
var blobItems = this . blobItemContainer _ . getCheckedBlobItems ( ) ;
this . addItemsToSet _ ( blobItems ) ;
} . bind ( this ) ;
this . selectAsCurrentSetNavItem _ . onClick = function ( ) {
var blobItems = this . blobItemContainer _ . getCheckedBlobItems ( ) ;
// there should be only one item selected
if ( blobItems . length != 1 ) {
alert ( "Cannet set multiple items as current collection" ) ;
return ;
}
this . blobItemContainer _ . currentCollec _ = blobItems [ 0 ] . blobRef _ ;
this . blobItemContainer _ . unselectAll ( ) ;
this . updateNavButtonsForSelection _ ( ) ;
} . bind ( this ) ;
this . searchRootsNavItem _ . onClick = this . setUrlSearch _ . bind ( this , {
permanode : {
attr : 'camliRoot' ,
numValue : {
min : 1
}
}
} ) ;
2013-12-29 07:54:08 +00:00
this . logoNavItem _ . onClick = this . navigate _ . bind ( this ) ;
2013-12-20 17:59:47 +00:00
this . eh _ . listen ( this . blobItemContainer _ , camlistore . BlobItemContainer . EventType . SELECTION _CHANGED , this . updateNavButtonsForSelection _ . bind ( this ) ) ;
this . eh _ . listen ( this . getElement ( ) , 'keypress' , function ( e ) {
if ( String . fromCharCode ( e . charCode ) == '/' ) {
this . nav _ . open ( ) ;
this . searchNavItem _ . focus ( ) ;
e . preventDefault ( ) ;
}
} ) ;
this . handleUrl _ ( ) ;
2012-12-12 03:06:47 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . exitDocument = function ( ) {
2013-12-20 17:59:47 +00:00
camlistore . IndexPage . superClass _ . exitDocument . call ( this ) ;
// Clear event handlers here
2012-12-12 03:06:47 +00:00
} ;
2012-11-09 18:35:59 +00:00
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . createNewSetWithItems _ = function ( blobItems ) {
2013-12-20 17:59:47 +00:00
this . connection _ . createPermanode ( goog . bind ( this . addMembers _ , this , true , blobItems ) ) ;
2012-12-12 03:33:15 +00:00
} ;
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . addItemsToSet _ = function ( blobItems ) {
2013-12-20 17:59:47 +00:00
if ( ! this . blobItemContainer _ . currentCollec _ || this . blobItemContainer _ . currentCollec _ == "" ) {
alert ( "no destination collection selected" ) ;
}
this . addMembers _ ( false , blobItems , this . blobItemContainer _ . currentCollec _ ) ;
2013-06-11 09:50:56 +00:00
} ;
2013-12-20 17:59:47 +00:00
camlistore . IndexPage . prototype . addMembers _ = function ( newSet , blobItems , permanode ) {
var deferredList = [ ] ;
var complete = goog . bind ( this . addItemsToSetDone _ , this , permanode ) ;
var callback = function ( ) {
deferredList . push ( 1 ) ;
if ( deferredList . length == blobItems . length ) {
complete ( ) ;
}
} ;
// TODO(mpl): newSet is a lame trick. Do better.
if ( newSet ) {
this . connection _ . newSetAttributeClaim ( permanode , 'title' , 'My new set' , function ( ) { } ) ;
}
goog . array . forEach ( blobItems , function ( blobItem , index ) {
this . connection _ . newAddAttributeClaim ( permanode , 'camliMember' , blobItem . getBlobRef ( ) , callback ) ;
} , this ) ;
2013-06-11 09:50:56 +00:00
} ;
2012-12-07 01:14:18 +00:00
2013-06-11 09:50:56 +00:00
camlistore . IndexPage . prototype . addItemsToSetDone _ = function ( permanode ) {
2013-12-20 17:59:47 +00:00
this . blobItemContainer _ . unselectAll ( ) ;
this . updateNavButtonsForSelection _ ( ) ;
this . blobItemContainer _ . showRecent ( ) ;
2013-06-11 09:50:56 +00:00
} ;
2012-12-07 01:14:18 +00:00
2013-10-04 02:28:13 +00:00
camlistore . IndexPage . prototype . handleServerStatus _ = function ( resp ) {
2013-12-20 17:59:47 +00:00
if ( resp && resp . version ) {
// TODO(aa): Argh
//this.toolbar_.setStatus('v' + resp.version);
}
2012-12-12 03:06:47 +00:00
} ;
2012-11-09 18:35:59 +00:00
2013-12-08 08:58:38 +00:00
camlistore . IndexPage . prototype . setUrlSearch _ = function ( search ) {
2013-12-20 17:59:47 +00:00
var searchText = goog . isString ( search ) ? goog . string . trim ( search ) :
goog . string . subs ( '%s:%s' , this . constructor . SEARCH _PREFIX _ . RAW , JSON . stringify ( search ) ) ;
var uri = new goog . Uri ( location . href ) ;
uri . setParameterValue ( 'q' , searchText ) ;
2013-12-29 07:54:08 +00:00
this . navigate _ ( uri . toString ( ) ) ;
} ;
camlistore . IndexPage . prototype . navigate _ = function ( url ) {
2013-12-20 17:59:47 +00:00
if ( history . pushState ) {
2013-12-29 07:54:08 +00:00
history . pushState ( null , '' , url ) ;
2013-12-20 17:59:47 +00:00
this . handleUrl _ ( ) ;
} else {
2013-12-29 07:54:08 +00:00
location . href = url ;
2013-12-20 17:59:47 +00:00
}
2013-10-17 06:45:36 +00:00
} ;
camlistore . IndexPage . prototype . handleUrl _ = function ( ) {
2013-12-20 17:59:47 +00:00
if ( location . href == this . currentUrl _ ) {
console . log ( 'Dropping duplicate handleUrl_ for %s' , this . currentUrl _ ) ;
return ;
}
this . currentUrl _ = location . href ;
var uri = new goog . Uri ( location . href ) ;
2013-12-22 05:02:12 +00:00
var query = uri . getParameterValue ( 'q' ) ;
if ( ! query ) {
2013-12-20 17:59:47 +00:00
this . blobItemContainer _ . showRecent ( ) ;
return ;
}
2013-12-22 05:02:12 +00:00
// TODO(aa): Remove this when the server can do something like the 'raw' operator.
if ( goog . string . startsWith ( query , this . constructor . SEARCH _PREFIX _ . RAW + ':' ) ) {
query = JSON . parse ( query . substring ( this . constructor . SEARCH _PREFIX _ . RAW . length + 1 ) ) ;
2013-12-20 17:59:47 +00:00
}
2013-12-22 05:02:12 +00:00
this . blobItemContainer _ . search ( query ) ;
2013-10-14 01:12:53 +00:00
} ;