Skip to content

Instantly share code, notes, and snippets.

@zrod
Created November 9, 2012 03:01
Show Gist options
  • Save zrod/246c2165e673572d7bd9 to your computer and use it in GitHub Desktop.
Save zrod/246c2165e673572d7bd9 to your computer and use it in GitHub Desktop.
/**
* st/filemanager.js
* FileManager
*
* Dependencies:
* - jQuery
* - StoryTroop (st/storytroop)
* - StoryTroop.ui (st/ui)
* - Mustache (lib/mustache-wp)
*/
define( function( require ) {
var $ = require( 'jquery' ),
storytroop = require( 'st/storytroop' ),
ui = require( 'st/ui' ),
Mustache = require( 'lib/mustache-wp' );
var proto,
FM_URI = '/imagefilemanager/list';
function FileManager() {
this.collection = {};
this.settings = {};
if ( arguments[0] ) {
this.context = ( arguments[0] instanceof jQuery ) ? arguments[0] : $( arguments[0] );
if ( arguments[1] && typeof( arguments[1] ) === 'object' ) {
this.setSettings( arguments[1] );
}
watchEvents.call( this );
}
}
proto = FileManager.prototype;
/**
* setSettings
* -
* @param opt Object
*/
proto.setSettings = function( opt ) {
var defaultSettings = {
selectCmd: '[data-filemanager-cmd="select"]',
removeCmd: '[data-filemanager-cmd="remove"]',
templates: {
collection: '<ul class="thumbnails">{{#items}}<li class="alignCenter" data-filemanager-type="{{type}}" data-filemanager-path="{{path}}">{{#file}}<a href="/imagefilemanager/delete?path={{path}}" data-filemanager-cmd="remove"><i class="icon-remove"></i></a>{{/file}}<a href="/imagefilemanager/list?path={{path}}" class="thumbnail" title="{{name}}" data-filemanager-obj="item"><div class="img"><img src="{{preview}}" alt="{{name}}" /></div> {{name}} </a> </li>{{/items}}</ul>'
},
i18n: {
remove: 'Are you sure you want to remove this file?'
}
};
this.settings = $.extend( {}, defaultSettings, opt );
};
/**
* init
*/
proto.init = function() {
if ( Object.size( this.collection ) === 0 ) {
this.fetchCollection();
}
};
/**
* fetchCollection
* -
* @param path String
*/
proto.fetchCollection = function( path ) {
var that = this,
path = path ? path : '',
cacheIndex,// = getCacheEntryKey.call( that, path ),
colUrl = FM_URI + ( path && typeof( path ) === 'string' ? '?path=' + encodeURIComponent( path ) : '' ),
loadingEl,
loadingCallback;
if ( cacheIndex ) {
// Read from cache
console.warn('present in cache');
renderCollection.call( that, that.collection[cacheIndex][1] );
that.context.data( 'activePath', path );
} else {
// Fetch from server
loadingEl = that.context.find( '[data-filemanager-obj="loading"]' );
ui.loading( 'show', { el: loadingEl, cursor: true } );
$.ajax({
url: colUrl
}).done( function( col ) {
if ( col && typeof( col ) === 'object' ) {
if ( Object.size( col ) > 0 ) {
renderCollection.call( that, col );
that.context.data( 'activePath', path );
// Store object in cache
path = path === '' ? '/' : path;
//that.collection.push( [path, col] );
cacheItem.apply( that, [path, col] );
} else {
// Empty
loadingCallback = function() {
that.context.find( '[data-filemanager-status="empty"]' ).show();
};
}
} else {
loadingCallback = function() {
that.context.find( '[data-filemanager-status="error"]' ).show();
};
}
}).fail( function() {
loadingCallback = function() {
that.context.find( '[data-filemanager-status="error"]' ).show();
};
}).always( function() {
ui.loading( 'hide', { el: loadingEl, callback: loadingCallback } );
});
}
};
/**
* addItem
* -
* @param obj Object
*/
proto.addItem = function( obj ) {
if ( obj && typeof( obj ) === 'Object' ) {
updateCollection( obj );
}
};
function cacheItem() {
var path = arguments[0],
obj = arguments[1],
o,
key = getCacheEntryKey.call( this, path ),
keyLen,
keyPath = '',
i = 0;
if ( key && key instanceof Array ) {
keyLen = key.length;
keyPath = this.collection;
for ( ; i < keyLen; i++ ) {
keyPath = keyPath[key[i]];
}
// store item in 'data' and its child's path in 'child.path' --> {/path = data, child.path}
for ( o in obj ) {
//this.collection[key][path][o] = {};
//this.collection[key][path].data = obj[o];
keyPath[path][o] = {};
keyPath[path].data = obj[o]; // !!!
}
console.log( keyPath );
} else {
// Store in root
this.collection[path] = {};
for ( o in obj ) {
this.collection[path][o] = {};
this.collection[path].data = obj[o];
}
}
console.log( this.collection );
}
/**
* getCacheEntryKey
* -
* @return Int
*/
function getCacheEntryKey() {
var key,
path = arguments[0],
c = arguments[1] ? arguments[1] : this.collection,
tree = arguments[2] ? arguments[2] : [];
if ( typeof( c ) === 'object' && Object.size( c ) > 0 ) {
for ( key in c ) {
if ( key === path ) {
//console.log( 'found a match', key );
//tree.push( key );
return tree;
} else {
tree.push( key );
return getCacheEntryKey.apply( this, [path, c[key], tree] );
}
}
}
return null;
}
/**
* renderCollection
* -
* @param col Object
*/
function renderCollection( col ) {
var container = this.context.find( '[data-filemanager-obj="container"]' ),
path,
outputObj = { items: [] },
output;
if ( container[0] && this.settings.templates.collection ) {
for ( path in col ) {
outputObj.items.push({
type: col[path]['File Type'],
preview: col[path]['Preview'],
name: col[path]['Filename'],
path: col[path]['Path'],
file: ( col[path]['File Type'] === 'STANDARD' ? true : false )
});
}
output = Mustache.render( this.settings.templates.collection, outputObj );
container[0].innerHTML = output;
//console.warn( 'current path: ' + this.context.data( 'activePath' ) );
}
}
/**
* updateCollection
* Update local cache with added / deleted images
* Or just populate the collection cache obj, considering this is the first request
* -
* @param items Object
*/
function updateCollection( items ) {
/*if ( this.collection && Object.size( this.collection ) > 0 ) {
console.log( this.collection );
console.log( items );
} else {*/
// Collection was empty, populating for the first time
this.collection = items;
//}
}
/**
* history
* -
* @param dir String
*/
function history( dir ) {
var that = this,
current = that.context.data( 'activePath' ),
cIndex,
nIndex,
next,
total = that.collection.length,
removeBtn = that.settings.removeCmd ? $( that.settings.removeCmd ) : null;
if ( current && total > 1 ) {
cIndex = getCacheEntryKey.call( that, current );
if ( cIndex !== -1 ) {
total = total - 1;
switch ( dir ) {
case 'down':
if ( cIndex + 1 <= total ) {
nIndex = cIndex + 1;
}
break;
default:
if ( cIndex - 1 !== -1 ) {
nIndex = cIndex - 1;
}
}
}
}
if ( typeof( nIndex ) === 'number' ) {
next = that.collection[nIndex][1];
that.context.data( 'activePath', that.collection[nIndex][0] );
renderCollection.call( that, next );
// Disable removeBtn
if ( removeBtn ) {
removeBtn.addClass( 'disabled' );
}
}
}
/**
* watchEvents
*/
function watchEvents() {
var that = this,
removeBtn = that.settings.removeCmd ? $( that.settings.removeCmd ) : null,
selectedItems = [];
/*
* Either go a directory down or select image/file
*/
that.context.on( 'click', 'a[data-filemanager-obj="item"]', function( e ) {
var $this = $( this ),
mType = $this.parent().data( 'filemanager-type' ),
path = $this.parent().data( 'filemanager-path' ),
pathIndex;
if ( path && typeof( path ) === 'string' ) {
switch ( mType ) {
case 'STANDARD':
if ( $this.attr( 'data-filemanager-selected' ) ) {
pathIndex = selectedItems.indexOf( path );
if ( pathIndex !== -1 ) {
selectedItems.splice( pathIndex, 1 );
$this.removeAttr( 'data-filemanager-selected' );
}
} else {
selectedItems.unshift( path );
$this.attr( 'data-filemanager-selected', 'selected' );
}
break;
default:
// Render next directory
that.fetchCollection( path );
}
}
e.preventDefault();
});
/*
* Insert selected image(s)
*/
$( that.settings.selectCmd ).click( function( e ) {
var sILen = selectedItems.length,
item;
if ( sILen > 0 && that.settings.selectCallback && typeof( that.settings.selectCallback ) === 'function' ) {
while ( sILen-- ) {
item = selectedItems.pop();
if ( item ) {
that.settings.selectCallback.call( this, item );
}
}
// Restore default state (filemanager-selected may have been used to style the element)
that.context.find( 'a[data-filemanager-selected]' ).removeAttr( 'data-filemanager-selected' );
}
});
/*
* Browse through collection
*/
that.context.on( 'click', '[data-filemanager-nav="up"]', function( e ) {
history.call( that, 'up' );
selectedItems = [];
e.preventDefault();
});
that.context.on( 'click', '[data-filemanager-nav="down"]', function( e ) {
history.call( that, 'down' );
selectedItems = [];
e.preventDefault();
});
/*
* Remove an item
*/
$( document ).on( 'click', that.settings.removeCmd, function( e ) {
var $this = $( this ),
ok = confirm( that.settings.i18n.remove ),
act,
cacheIndex,
path,
pathIndex;
if ( ok ) {
path = $this.parent().data( 'filemanager-path' );
act = $this.attr( 'href' );
ui.loading( 'show', { cursor: true } );
$.ajax({
url: act
}).done( function( r ) {
// If the current item had been selected, remove it from selectedItems array
pathIndex = selectedItems.indexOf( path );
if ( pathIndex !== -1 ) {
selectedItems.splice( pathIndex, 1 );
}
// Remove from cache !!!
cacheIndex = getCacheEntryKey.call( that, path );
that.collection = []; // INVALDATING CACHE - As soon as the bug with cache's tree is fixed, remove parent node of current cacheIndex
// RE-RENDER !!! on next modal show(), render previous pointer
//that.fetchCollection( that.context.data( 'activePath' ) );
$this.parent().remove();
}).always( function() {
ui.loading( 'hide' );
// Callback?!
if ( that.settings.removeCallback && typeof( that.settings.removeCallback ) === 'function' ) {
that.settings.removeCallback.call( this );
}
});
}
e.preventDefault();
});
// User must select a file before hitting 'upload'
/*that.context.find( '[data-filemanager-obj="form"]' ).submit( function( e ) {
var frm = $( this ),
file = frm.find( 'input[type="file"]' ),
errMsg;
if ( !file || !file.val() ) {
errMsg = frm.find( 'input[type="submit"]' ).data( 'filemanager-error-nofile' );
if ( errMsg ) {
ui.notify( errMsg, { type: 'error' } );
}
e.preventDefault();
return false; // IE
}
});*/
}
return FileManager;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment