| 
/*
Program Name: File Picker
 Program URI: http://code.google.com/p/file-picker/
 Description: Display and choose files from your website.
 
 Copyright (c) 2008 Hpyer (hpyer[at]yahoo.cn)
 Dual licensed under the MIT (MIT-LICENSE.txt)
 and GPL (GPL-LICENSE.txt) licenses.
 */
 
 var FilePicker = {
 
 params: {
 uri: '.',
 key: 'FP_RESULT',
 multi: true,
 access: 'file-picker.php',
 unicode: true,
 delay: 300
 },
 last_click: null,
 timer: null,
 
 
 /*
 @desc    Initialization
 @since    1.0.2
 @return    void
 */
 init: function(params) {
 $.extend(this.params, params);
 $.base64.is_unicode = this.params.use_unicode;
 $.ajaxSetup({
 url: this.params.access,
 dataType: 'json'
 });
 this.do_translate_options();
 this.events_binder();
 this.get_list();
 },
 
 /*
 @desc    Operation completed, return the JSON string like: {uri:"/path/to/folder", files:["file_1.txt", "file_2.jpg"]}
 @return    void
 */
 do_complete: function() {
 var self = FilePicker;
 var obj = '{' +
 'uri:"' + self.get_uri() + '", ' +
 'files:[' + self.get_selected(true) + ']' +
 '}';
 self.do_close(obj);
 },
 
 /*
 @desc    Close window, and return the JSON string
 @param    string    obj
 @return    void
 */
 do_close: function(obj) {
 var self = FilePicker;
 if (typeof(obj) != 'string') obj = '';
 eval('window.opener.' + self.params.key + '=\'' + obj + '\';');
 window.close();
 },
 
 /*
 @desc    Get the URI of current folder
 @return    string
 */
 get_uri: function() {
 var uri;
 uri = $.base64.decode($('#folders_tree').val());
 uri = uri == '/' ? '' : uri;
 return this.params.uri + uri;
 },
 
 /*
 @desc    Get JSON string that be translated with all the selected file(s)
 @return    string
 */
 get_selected: function(with_quote) {
 var t = $('li.selected');
 if (t.length == 1){
 return with_quote ? '"' + t.text() + '"' : t.text();
 }
 return $.map(t, function(li){return '"' + li.innerHTML + '"';}).join(', ');
 },
 
 /*
 @desc    select the file/folder
 @param    object    obj
 @param    boolean    set_filename    [default:false]
 @return    void
 */
 do_select: function(obj, set_filename) {
 set_filename = set_filename || false;
 obj.addClass('selected');
 $('#filename_box').val(set_filename ? this.get_selected() : '');
 },
 
 /*
 @desc    Unselect all file(s)/folder(s), and clear the information
 @return    void
 */
 do_unselect: function() {
 $('li.selected').removeClass('selected');
 $('#filename_box').val('');
 FilePicker.do_hide_info();
 $('#filename_box').focus();
 },
 
 /*
 @desc    Show the information box
 @param    object    evt
 @return    void
 */
 do_show_info: function(evt) {
 var box = $('#info_box').addClass('info_box')
 .css("top", (evt.pageY + 10) + "px")
 .css("left",(evt.pageX + 10) + "px").fadeIn('fast');
 },
 
 /*
 @desc    Hide the information box
 @param    boolean    without_box
 @return    void
 */
 do_hide_info: function(without_box) {
 var box = $('#info_box').empty();
 if (!without_box){
 box.hide();
 }
 },
 
 /*
 @desc    Get JSON string that be translated with all the selected file(s)
 @return    string
 */
 do_translate_options: function() {
 $('#folders_tree option').each(function(){
 $(this).text($.base64.decode($(this).text()));
 });
 },
 
 /*
 @desc    Change the current folder to it parent
 @return    void
 */
 do_up: function() {
 var dir = $.base64.decode($('#folders_tree').val());
 var p = dir.lastIndexOf('/');
 if (p < 0 || dir == '/') return false;
 var s = dir.substr(0,p);
 s = (s == '') ? '/' : $.base64.encode(s);
 $('#folders_tree').val(s);
 FilePicker.get_list();
 },
 
 /*
 @desc    Deal with the incident of double-clicking on the file/folder
 @return    void
 */
 do_dblclick: function(){
 var self = FilePicker;
 clearTimeout(self.timer);
 var elmt = $(this);
 if (elmt.attr('ftype') == 'folder'){
 var dir = $.base64.decode($('#folders_tree').val());
 if (dir != '/') dir += '/';
 $('#folders_tree').val($.base64.encode(dir + elmt.text()));
 self.get_list();
 } else {
 self.do_select(elmt);
 self.do_complete();
 }
 },
 
 /*
 @desc    Deal with the incident of clicking on the file/folder
 @param    object    event
 @return    void
 */
 do_click: function(evt) {
 var self = FilePicker;
 var elmt = $(this);
 self.do_hide_info();
 $('#filename_box').focus();
 if (!self.params.multi){
 self.do_unselect();
 }
 if (self.params.multi && elmt.attr('ftype') == 'folder'){
 if (!evt.shiftKey){
 // Don't remember this item, if SHIFT key was pushed down
 self.last_click = elmt.attr('id');
 }
 if (evt.ctrlKey){
 // Only one folder can be selected
 return false;
 }
 var t = $('li.selected').removeClass('selected');
 if (t.length == 1 && t.attr('id') == elmt.attr('id')){
 // Unselect current folder if it was selected
 self.do_unselect();
 return false;
 }
 self.do_select(elmt);
 } else {    // files
 if (evt.ctrlKey){
 self.last_click = elmt.attr('id');
 // Unselect folder(s)
 $('li.selected[ftype=folder]').removeClass('selected');
 // Select/Unselect current file
 $(this).toggleClass('selected');
 $('#filename_box').val(self.get_selected());
 } else if (self.params.multi && evt.shiftKey){
 // To delay the operation
 } else {
 self.last_click = elmt.attr('id');
 var t = $('li.selected').removeClass('selected');
 if (t.length == 1 && t.attr('id') == elmt.attr('id')){
 // Unselect current file if it was selected
 self.do_unselect();
 return false;
 }
 self.do_select(elmt, true);
 }
 }
 if (self.params.multi && evt.shiftKey){
 if (!self.last_click){
 // Select current item, if no one selected
 self.last_click = elmt.attr('id');
 self.do_select(elmt);
 } else {
 self.do_unselect();
 var first_id = parseInt(self.last_click.split('_')[1]);
 var this_id = parseInt(elmt.attr('id').split('_')[1]);
 if (first_id > this_id){
 $('#list > li').slice(this_id, first_id + 1).each(function(){
 FilePicker.do_select($(this));
 });
 } else {
 $('#list > li').slice(first_id, this_id + 1).each(function(){
 FilePicker.do_select($(this));
 });
 }
 }
 // Unselect Folder(s)
 $('li.selected[ftype=folder]').removeClass('selected');
 $('#filename_box').val(self.get_selected());
 }
 
 /*
 @desc    Make sure the click/dblclick works alone.
 Click will be disabled if the event was dblclick
 @since    1.0.2
 */
 clearTimeout(self.timer);
 self.timer = setTimeout(function () {
 self.get_info(evt);
 }, self.params.delay);
 return false;
 },
 
 /*
 @desc    Get infomation of the selected file/folder
 @return    void
 */
 get_info: function(evt) {
 this.do_hide_info(true);
 var t = $('li.selected');
 if (t.length == 1){
 // Initialize the information box
 this.do_show_info(evt);
 $('<img />').attr('id', 'info_loading_img').attr('src', $('#loading_img')
 .attr('src')).appendTo('#info_box');
 $.ajax({
 data:{
 action: 'info',
 dir: $('#folders_tree').val(),
 file: $.base64.encode(t.text())
 },
 success: function(json){
 var self = FilePicker;
 $('#info_box').html($('<label></label>').attr('id', 'btn_close')
 .text('X').click(function(){self.do_hide_info(false);}));
 var i = 0;
 $.each(json, function(i, item){
 if ($('#info_box').css('display') == 'none') return false;
 if (item.key == 'preview'){
 var src = self.get_uri() + '/' + $.base64.decode(item.value);
 $('<img />').attr('id', 'preview_img')
 .attr('alt', item.trans).attr('src', src)
 .click(function(){window.open(this.src,'_blank','');})
 .prependTo('#info_box');
 } else {
 if (i == 0){
 item.value = $.base64.decode(item.value);
 }
 $('#info_box').append(
 '<strong>' + item.trans + '</strong>:<br />' +
 '   ' + item.value + '<br />'
 );
 }
 i++;
 });
 }
 });
 }
 },
 
 /*
 @desc    Get file(s)/folder(s) list of current directory
 @param    boolean    read_cache    [default:true]
 @return    void
 */
 get_list: function(read_cache) {
 if ( typeof(read_cache) == 'undefined' ) read_cache = true;
 // Clean memory when the list was change
 this.last_click = null;
 this.do_hide_info();
 $('#loading_img').show();
 $('#list').empty();
 $('#filename_box').val('');
 $.ajax({
 cache: read_cache,
 data: {
 action: 'list',
 dir: $('#folders_tree').val(),
 filter: $('#filter_box').val()
 },
 success: function(json){
 var self = FilePicker;
 $('#loading_img').hide();
 // To store filename(s) that be used for Auto-Complete
 var files = [];
 $.each(json, function(i,item){
 item.name = $.base64.decode(item.name);
 $('<li></li>').attr('id','item_'+i).attr('ftype',item.type)
 .attr('title', item.name).html(item.name)
 .addClass(item.type).click(self.do_click)
 .dblclick(self.do_dblclick).appendTo('#list');
 if (item.type != 'folder') {
 files.push(item.name);
 }
 });
 $('#filename_box').autocompleteArray(files, {onItemSelect: function(){
 // `Click` the file that selected from the list of Auto-Complete
 $('li:not(li[ftyp:folder])').each(function(){
 if ($(this).html() == $('#filename_box').val()){
 $(this).click();
 return false;
 }
 });
 }});
 self.do_unselect();
 }
 });
 },
 
 /*
 @desc    Bind all events that we need
 @return    void
 */
 events_binder: function() {
 var self = FilePicker;
 $('body').bind('selectstart', function(){return false;});
 $('#file_picker_form').bind('submit', function(){return false;});
 $('#list_box').bind('click', self.do_unselect);
 $('#folders_tree').bind('change', function(){self.get_list(true);});
 $('#btn_refresh').bind('click', function(){self.get_list(false);});
 $('#btn_up').bind('click', self.do_up);
 $('#btn_complete').bind('click', self.do_complete);
 $('#btn_cancel').bind('click', self.do_close);
 $('#info_box').ppdrag();
 }
 
 }
 
 |