Index: openacs-4/packages/ajax-filestorage-ui/www/resources/ajaxfs.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajax-filestorage-ui/www/resources/ajaxfs.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajax-filestorage-ui/www/resources/ajaxfs.js 25 Dec 2006 16:23:26 -0000 1.2 +++ openacs-4/packages/ajax-filestorage-ui/www/resources/ajaxfs.js 8 Sep 2007 14:32:55 -0000 1.3 @@ -1,312 +1,1497 @@ -/* loadJs -helper that executes anything that is between script tags - in a responseText returned by an ajax call */ +/* + Ajax File Storage + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2007-06-03 +*/ -function loadJs(responseText) { - var re=/(?:.*<\/script>)|(?:([\S\s]*?)<\/script>)/ig; - var match; - while (match = re.exec(responseText)) { - var s0 = document.createElement("script"); - if (match[1]) - s0.src = match[1]; - else if (match[2]) - s0.text = match[2]; - else - continue; - document.getElementsByTagName("head")[0].appendChild(s0); +/********** UTILS *********************/ + +/* readCookie +read value of a cookie */ +function readCookie(name) { + var ca = document.cookie.split(';'); + var nameEQ = name + "="; + for(var i=0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1, c.length); //delete spaces + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); + } + return null; +} + +/* createCookie +used to maintain state, e.g. when login expires */ +function createCookie(name, value, days){ + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + } + else var expires = ""; + document.cookie = name+"="+value+expires+"; path=/"; +} + +/* read query string +read the value of a querystring */ +function readQs(q) { + var query = window.location.search.substring(1); + var parms = query.split('&'); + for (var i=0; i 0) { + var key = parms[i].substring(0,pos); + var val = parms[i].substring(pos+1); + if (key == q) { + return val; + } } + } + return null; } -/* trimString -helper to remove trailing and leading spaces from a string */ -function trimString (str) { - str = this != window? this : str; - return str.replace(/^\s+/g, '').replace(/\s+$/g, ''); +/* check Flash Version */ +function checkFlashVersion() { + + var x; + var pluginversion; + + if(navigator.plugins && navigator.mimeTypes.length){ + x = navigator.plugins["Shockwave Flash"]; + if(x && x.description) x = x.description; + } else if (Ext.isIE){ + try { + x = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); + x = x.GetVariable("$version"); + } catch(e){} + } + + pluginVersion = (typeof(x) == 'string') ? parseInt(x.match(/\d+/)[0]) : 0; + + return pluginVersion; } -/* editInPlace -dynamically make the properties_name element editable*/ +// check if the string argument is a url +function isURL(argvalue) { -function editInPlace (objid,namediv,controldiv,type) { - this.objid = objid - this.namediv = document.getElementById(namediv); - this.controldiv = document.getElementById(controldiv); - this.oldnamediv_value = this.namediv.innerHTML; - this.oldcontroldiv_value = this.controldiv.innerHTML; - this.form_textbox = 'edip_name'; - this.form_ok = 'edip_save'; - this.form_cancel = 'edip_cancel'; - this.type = type; - this.setvalues = function (nameval,controlval) { - this.namediv.innerHTML = nameval; - this.controldiv.innerHTML = controlval; + if (argvalue.indexOf(" ") != -1) + return false; + else if (argvalue.indexOf("http://") == -1) + return false; + else if (argvalue == "http://") + return false; + else if (argvalue.indexOf("http://") > 0) + return false; + + argvalue = argvalue.substring(7, argvalue.length); + if (argvalue.indexOf(".") == -1) + return false; + else if (argvalue.indexOf(".") == 0) + return false; + else if (argvalue.charAt(argvalue.length - 1) == ".") + return false; + + if (argvalue.indexOf("/") != -1) { + argvalue = argvalue.substring(0, argvalue.indexOf("/")); + if (argvalue.charAt(argvalue.length - 1) == ".") + return false; + } + + if (argvalue.indexOf(":") != -1) { + if (argvalue.indexOf(":") == (argvalue.length - 1)) + return false; + else if (argvalue.charAt(argvalue.indexOf(":") + 1) == ".") + return false; + argvalue = argvalue.substring(0, argvalue.indexOf(":")); + if (argvalue.charAt(argvalue.length - 1) == ".") + return false; + } + + return true; + +} + +/********** FLASH UPLOAD *********/ + + +function FileProgress(fileObj, target_id) { + this.file_progress_id = fileObj.id; + + this.opacity = 100; + this.height = 0; + + this.fileProgressWrapper = document.getElementById(this.file_progress_id); + if (!this.fileProgressWrapper) { + this.fileProgressWrapper = document.createElement("div"); + this.fileProgressWrapper.className = "progressWrapper"; + this.fileProgressWrapper.id = this.file_progress_id; + + this.fileProgressElement = document.createElement("div"); + this.fileProgressElement.className = "progressContainer"; + + var progressCancel = document.createElement("a"); + progressCancel.className = "progressCancel"; + progressCancel.href = "#"; + progressCancel.style.visibility = "hidden"; + progressCancel.appendChild(document.createTextNode(" ")); + + var progressText = document.createElement("div"); + progressText.className = "progressName"; + progressText.appendChild(document.createTextNode(fileObj.name)); + + var progressBar = document.createElement("div"); + progressBar.className = "progressBarInProgress"; + + var progressStatus = document.createElement("div"); + progressStatus.className = "progressBarStatus"; + progressStatus.innerHTML = " "; + + this.fileProgressElement.appendChild(progressCancel); + this.fileProgressElement.appendChild(progressText); + this.fileProgressElement.appendChild(progressStatus); + this.fileProgressElement.appendChild(progressBar); + + this.fileProgressWrapper.appendChild(this.fileProgressElement); + + document.getElementById(target_id).appendChild(this.fileProgressWrapper); + } else { + this.fileProgressElement = this.fileProgressWrapper.firstChild; } - this.addListeners = function() { - thisobj =this; - YAHOO.util.Event.addListener(this.form_ok, "click", this.saveedit,thisobj); - YAHOO.util.Event.addListener(this.form_cancel, "click", this.canceledit,thisobj); + + this.height = this.fileProgressWrapper.offsetHeight; + +} +FileProgress.prototype.SetProgress = function(percentage) { + this.fileProgressElement.className = "progressContainer green"; + this.fileProgressElement.childNodes[3].className = "progressBarInProgress"; + this.fileProgressElement.childNodes[3].style.width = percentage + "%"; +} +FileProgress.prototype.SetComplete = function() { + this.fileProgressElement.className = "progressContainer blue"; + this.fileProgressElement.childNodes[3].className = "progressBarComplete"; + this.fileProgressElement.childNodes[3].style.width = ""; + + var oSelf = this; + setTimeout(function() { oSelf.Disappear(); }, 10000); +} +FileProgress.prototype.SetError = function() { + this.fileProgressElement.className = "progressContainer red"; + this.fileProgressElement.childNodes[3].className = "progressBarError"; + this.fileProgressElement.childNodes[3].style.width = ""; + + var oSelf = this; + setTimeout(function() { oSelf.Disappear(); }, 5000); +} +FileProgress.prototype.SetCancelled = function() { + this.fileProgressElement.className = "progressContainer"; + this.fileProgressElement.childNodes[3].className = "progressBarError"; + this.fileProgressElement.childNodes[3].style.width = ""; + + var oSelf = this; + setTimeout(function() { oSelf.Disappear(); }, 2000); +} +FileProgress.prototype.SetStatus = function(status) { + this.fileProgressElement.childNodes[2].innerHTML = status; +} + +FileProgress.prototype.ToggleCancel = function(show, upload_obj) { + this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden"; + if (upload_obj) { + var file_id = this.file_progress_id; + this.fileProgressElement.childNodes[0].onclick = function() { upload_obj.cancelUpload(file_id); return false; }; } - this.rmListeners = function() { - thisobj =this; - YAHOO.util.Event.removeListener(this.form_ok, "click", this.saveedit,thisobj); - YAHOO.util.Event.removeListener(this.form_cancel, "click", this.canceledit,thisobj); +} + +FileProgress.prototype.Disappear = function() { + + var reduce_opacity_by = 15; + var reduce_height_by = 4; + var rate = 30; // 15 fps + + if (this.opacity > 0) { + this.opacity -= reduce_opacity_by; + if (this.opacity < 0) this.opacity = 0; + + if (this.fileProgressWrapper.filters) { + try { + this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = this.opacity; + } catch (e) { + // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. + this.fileProgressWrapper.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + this.opacity + ')'; + } + } else { + this.fileProgressWrapper.style.opacity = this.opacity / 100; + } } - this.createform = function() { - var editform = ""; - editform = editform + " "; - editform = editform + ""; - this.setvalues(editform,''); - document.getElementById('edip_name').select(); - this.addListeners(); + + if (this.height > 0) { + this.height -= reduce_height_by; + if (this.height < 0) this.height = 0; + + this.fileProgressWrapper.style.height = this.height + "px"; } - this.canceledit = function(el,obj) { - obj.rmListeners(); - obj.setvalues(obj.oldnamediv_value,obj.oldcontroldiv_value); + + if (this.height > 0 || this.opacity > 0) { + var oSelf = this; + setTimeout(function() { oSelf.Disappear(); }, rate); + } else { + this.fileProgressWrapper.style.display = "none"; } - this.saveedit = function(el,obj) { - // save the new name - var postData ='type='+obj.type+'&object_id='+obj.objid+'&newname='+document.getElementById(obj.form_textbox).value; - var callback = { - success: function(o) { - obj.namediv.innerHTML=o.responseText; - obj.controldiv.innerHTML=obj.oldcontroldiv_value; +} - // check if node exists in tree - if ( tree != 'undefined') { - var node = tree.getNodeByProperty('id',obj.objid); - // update node name - if ( node != null) { - document.getElementById(node.getLabelEl().id).innerHTML=o.responseText; - } - } +function uploadStart(fileObj,ajaxfsobj) { + var upload_txt = acs_lang_text.for_upload_to || "for upload to"; + var zip_txt = acs_lang_text.zip_extracted || "Zip File (Will be extracted after upload)"; + try { + // You might include code here that prevents the form from being submitted while the upload is in + // progress. Then you'll want to put code in the Queue Complete handler to "unblock" the form + var folderid = ajaxfsobj.currentfolder; + var foldername = ajaxfsobj.treepanel.getNodeById(folderid).text; + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetStatus( upload_txt + ""+foldername+"
"+ zip_txt); + progress.ToggleCancel(true, this); + this.addFileParam(fileObj.id, "folder_id", folderid); + ajaxfsobj.upldDialog.buttons[0].enable(); + } catch (ex) { this.debugMessage(ex); } +} - }, argument: { thisobj:obj } +function uploadProgress(fileObj, bytesLoaded) { + try { + var percent = Math.ceil((bytesLoaded / fileObj.size) * 100) + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetProgress(percent); + progress.SetStatus(acs_lang_text.uploading || "Uploading..."); + } catch (ex) { this.debugMessage(ex); } +} + +function uploadFileComplete(fileObj) { + try { + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetComplete(); + progress.SetStatus(acs_lang_text.complete || "Complete."); + progress.ToggleCancel(false); + + } catch (ex) { this.debugMessage(ex); } +} + +function uploadComplete(fileObj) { + try { + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetComplete(); + progress.SetStatus(acs_lang_text.complete || "Complete."); + progress.ToggleCancel(false); + + } catch (ex) { this.debugMessage(ex); } +} + +function uploadQueueComplete(fileidx,ajaxfsobj) { + ajaxfsobj.upldDialog.buttons[0].disable(); + var currentTreeNode = ajaxfsobj.treepanel.getNodeById(ajaxfsobj.currentfolder); + currentTreeNode.fireEvent("click",currentTreeNode); +} + +function uploadError(error_code, fileObj, message) { + try { + if (error_code == SWFUpload.ERROR_CODE_QUEUE_LIMIT_EXCEEDED) { + Ext.Msg.alert(acs_lang_text.alert || "Alert","You have attempted to queue too many files.\n" + (message == 0 ? "You have reached the upload limit." : "You may select " + (message > 1 ? "up to " + message + " files." : "one file."))); + return; } - YAHOO.util.Connect.asyncRequest('POST', '/ajaxfs/xmlhttp/editname', callback, postData); + + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetError(); + progress.ToggleCancel(false); + + switch(error_code) { + case SWFUpload.ERROR_CODE_HTTP_ERROR: + progress.SetStatus("Upload Error"); + this.debugMessage("Error Code: HTTP Error, File name: " + file.name + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_MISSING_UPLOAD_TARGET: + progress.SetStatus("Configuration Error"); + this.debugMessage("Error Code: No backend file, File name: " + file.name + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_UPLOAD_FAILED: + progress.SetStatus("Upload Failed."); + this.debugMessage("Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_IO_ERROR: + progress.SetStatus("Server (IO) Error"); + this.debugMessage("Error Code: IO Error, File name: " + file.name + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_SECURITY_ERROR: + progress.SetStatus("Security Error"); + this.debugMessage("Error Code: Security Error, File name: " + file.name + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT: + progress.SetStatus("File is too big."); + this.debugMessage("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_ZERO_BYTE_FILE: + progress.SetStatus("Cannot upload Zero Byte files."); + this.debugMessage("Error Code: Zero byte file, File name: " + file.name + ", File size: " + file.size + ", Message: " + message); + break; + case SWFUpload.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED: + progress.SetStatus("Upload limit exceeded."); + this.debugMessage("Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message); + break; + default: + progress.SetStatus("Unhandled Error"); + this.debugMessage("Error Code: " + error_code + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message); + break; + } + } catch (ex) { + this.debugMessage(ex); } - this.createform(); } -/* showFolderContents -Called when a folder is clicked, fetches all the files and folders in a node */ +function uploadCancel(fileObj) { + try { + var progress = new FileProgress(fileObj, this.getSetting("progress_target")); + progress.SetCancelled(); + progress.SetStatus(acs_lang_text.uploadcancel || "Cancelled (This item will be removed shortly)"); + progress.ToggleCancel(false); -function showFolderContents(folder_id,tree,sort) { + } + catch (ex) { + this.debugMessage(ex); + } +} - // show 'loading...' - document.getElementById('files').innerHTML = '


Loading . . . . .
'; +/********** AjaxFS Objects ***********/ - // expand the tree on click - var thenode = tree.getNodeByProperty('id',folder_id); +function ajaxfs(configObj) { - // remove highlight from the last folder - if ( document.getElementById('lastfolder').value != "" ) { - if (tree.getNodeByProperty('id',document.getElementById('lastfolder').value) != null ) { - var oldnode = tree.getNodeByProperty('id',document.getElementById('lastfolder').value); - YAHOO.util.Dom.removeClass(oldnode.getLabelEl().id,'folderselected'); - } - } + // ** configObj ** + // ajaxFs expects a config object that may have the following properites + // configObj.package_ids : the package_id or a comma separated list of package_ids of the current ajaxFs Instance + // configObj.initOpenFolder : if this value is not null, it should contain the folder id to open when object is instantiated + // configOjb.layoutdiv : the div container where we put the layout, if none is provided then document.body is used - // open or close the node - thenode.toggle(); + // ** properties ** - // write this node's id to the hidden field - document.getElementById('lastfolder').value = folder_id; + // where to get - // let's highlight the new selected folder - var newnode = tree.getNodeByProperty('id',document.getElementById('lastfolder').value); - YAHOO.util.Dom.addClass(newnode.getLabelEl().id,'folderselected'); + // url of xmlhttp files from ajaxfs + this.xmlhttpurl = '/ajaxfs2/xmlhttp/'; - // empty the items in the fsList object_id - fileList.emptyItems(); + // holds an object with configruation settings for this instance + // of ajaxfs, this variable is set only if configObj exists and is passed + this.config = null; - // fetch contents via ajax - var postData ='folder_id='+folder_id+'&orderby='+sort; - var callback = { - success: function(o) { - document.getElementById('files').innerHTML=o.responseText; - loadJs(o.responseText); - } - } - YAHOO.util.Connect.asyncRequest('POST', '/ajaxfs/xmlhttp/showfoldercontents', callback, postData); + // holds a reference to the layout for the center page + this.layout = null; - showProperties(folder_id,'folder'); -} + // holds a reference to the tree panel + this.treepanel = null; -/* showProperties -Populates the action and properties panel with more information and actions*/ + // holds a reference to the tree editor + this.te = null; -function showProperties (object_id,type) { + // holds a reference to the root of the tree + this.rootfolder = null; - var southpanel = innerLayout.getRegion('south'); - southpanel.setActivePanel('properties'); + // the grid that lists the files + this.filegrid = null; - // fetch contents of properites - var postData ='object_id='+object_id+'&type='+type; - var callback = { - success: function(o) { - loadJs(o.responseText); - document.getElementById('properties').innerHTML=o.responseText; + // holds a reference to the toolbar + this.toolbar = null; + + // holds the id of the currently selected node in the tree + this.currentfolder = null; + + // reusable aync data connection + this.asyncCon = new Ext.data.Connection(); + + // reference to messagebox + this.msgbox = Ext.MessageBox; + + // create upload dialog + this.upldDialog = null; + + // create ur dialog + this.createurlDialog = null; + + // permissions dialog + this.permsDialog = null; + + /// revisions dialog + this.revisionsDialog = null; + + // reference to contextmenu + this.contextmenu = null; + + // reference to an instance of the swfuploader + // used for ajaxfs + this.swfu = null; + + // ** methods ** + + // check if the string has the login form + // redirects to login form if true, does nothing if not + this.isSessionExpired = function() { + // check if the string has method="post" name="login" + if ( readCookie("ad_user_login") == null ) { + Ext.get(document.body).mask(acs_lang_text.sessionexpired || "Your session has expired. You need to login again.
You will be redirected to a login page shortly"); + var params = "package_id="+this.config.package_id; + if(this.currentfolder != null) { + params = params + "&folder_id="+this.currentfolder; + } + window.location="/register/?return_url="+window.location; + return 1 } + return 0 } - YAHOO.util.Connect.asyncRequest('POST', '/ajaxfs/xmlhttp/showproperties', callback, postData); - if (type === "folder" ) { - southpanel.hidePanel('revisions'); - } else { - southpanel.unhidePanel('revisions'); - // TODO : use ajax to fetch revisions table of the object + // check the permissions, returns either true or false + this.isPermitted = function(objid,perm) { + + var callback = function(option,success,response) { + if(success) { + return response.responseText; + } else { + return 0; + } + } + + this.asyncCon.request({url:this.xmlhttpurl+"checkperms", + params: "object_id="+objid+"&perm="+perm, + method:"POST", + callback: callback, + scope: this + }); + } -} -/* loadDataForNode -Dynamically loads the child nodes of a given parent node*/ + // creates a gridpanel + this.createGridPanel = function(grid,region,configObj) { + // create the grid panel + gridPanel = new Ext.GridPanel(grid, configObj) + this.layout.add(region, gridPanel); + } -function loadDataForNode(node, onCompleteCallback) { + // generates a url to the currently selected file storage item + // if it's a file : download + // if it's a folder : append folder_id to the current url + this.linkCopy = function() { + var node = this.filegrid.getSelectionModel().getSelected(); + var nodetype = node.get("type"); + if (nodetype === "folder") { + // generate the url to a folder + var copytext = window.location.protocol+"//"+window.location.hostname+":"+window.location.port+this.config.package_url+"?package_id="+this.config.package_id+"&folder_id="+node.get("id"); + } else if (nodetype === "url") { + var copytext = node.get("url"); + } else { + var copytext = window.location.protocol+"//"+window.location.hostname+node.get("url"); + } + if(Ext.isIE) { + window.clipboardData.setData("text",copytext); + } else { + var copyprompt = Ext.Msg.show({ + title: acs_lang_text.linkaddress || 'Copy Link Address', + prompt: true, + msg: acs_lang_text.copyhighlighted || 'Copy the highlighted text to your clipboard.', + value: copytext, + buttons: Ext.Msg.OK + }); + var prompt_text_el = YAHOO.util.Dom.getElementsByClassName('ext-mb-input', 'input','x-msg-box'); + prompt_text_el[0].select(); + } + } - var postData ='parentfolderid='+node.data.id; - var callback = { - success: function(o) { - eval(o.responseText); - onCompleteCallback(); - }, failure: function(o) { - alert('Error ' + o.status + ' -- ' + o.statusText); - onCompleteCallback(); - } - } + // rename a file or folder in the right panel + this.fileRename = function() { - YAHOO.util.Connect.asyncRequest('POST', '/ajaxfs/xmlhttp/loadchildnodes', callback, postData); -} + var node = this.filegrid.getSelectionModel().getSelected(); + var nodeurl = node.get("url"); + var nodetype = node.get("type"); + var nodeid = node.get("id"); + var nodesubtitle = node.get("filename"); -/* openfolder -Opens a node in the folder tree */ + var handleRename = function(btn, text) { + if(btn=='ok') { + if(text != '') { + if(text.length > 100) { + Ext.Msg.alert(acs_lang_text.alert || "Alert",acs_lang_text.limitto100 || "Please limit your name to 100 characters or less."); + return false; + } else { + var callback = function(option,success,response) { + var err_msg_txt = acs_lang_text.an_error_occurred || "An error occurred"; + var err_msg_txt2 = acs_lang_text.reverted || "Your changes have been reverted"; + if (success) { + if (response.responseText != 1) { + Ext.Msg.alert(acs_lang_text.error || "Error",err_msg_txt + ":

"+response.responseText+"

"+err_msg_txt2); + } else { + if(nodetype!="folder"&&nodesubtitle===" ") { nodesubtitle = node.get("title") } + if(nodetype=="folder") { this.treepanel.getNodeById(nodeid).setText(text) } + node.set("title",text); + node.set("title_and_name",""+text+"
"+nodesubtitle+"") + node.commit(); + } + } else { + Ext.Msg.alert(acs_lang_text.error || "Error",err_msg_text+":

"+response.responseText+"

"+err_msg_txt2); + } + } + + this.asyncCon.request({url:this.xmlhttpurl+"editname", + params: "newname="+text+"&object_id="+nodeid+"&type="+nodetype+"&url="+nodeurl, + method:"POST", + callback: callback, + scope: this + }); + } + } else { + Ext.Msg.alert(acs_lang_text.alert || "Alert",acs_lang_text.enter_new_name || "Please enter a new name."); + return false; + } + } + } -function openfolder(object_id) { - // get a reference to the node for the given object_id - var thenode = tree.getNodeByProperty('id',object_id); - thenode.parent.expand(); - showFolderContents(object_id,tree,'name'); -} + // Ext.MessageBox.prompt('Rename', 'Please enter a new name for
'+view.jsonData[node.nodeIndex].title+':', handleRename.createDelegate(this)); + Ext.Msg.show({ + title: acs_lang_text.rename || 'Rename', + prompt: true, + msg: acs_lang_text.enter_new_name || 'Please enter a new name for ... ', + value: node.get("title"), + buttons: Ext.Msg.OKCANCEL, + fn: handleRename.createDelegate(this) + }); + var prompt_text_el = YAHOO.util.Dom.getElementsByClassName('ext-mb-input', 'input','x-msg-box'); + prompt_text_el[0].select(); + } -/* ajaxFsLayout -Prototype Object to generate the layout */ + // permissions dialog + this.permsRedirect = function() { + var node = this.filegrid.getSelectionModel().getSelected(); + var object_id = node.get("id"); + var newwindow = window.open(window.location.protocol+"//"+window.location.hostname+":"+window.location.port+this.config.package_url+"permissions?object_id="+object_id+"&return_url="+window.location.pathname+"?package_id="+this.config.package_id+"&folder_id="+this.currentfolder); + newwindow.focus(); + } -var layout; -var innerLayout; + // redirect to file properties + this.propertiesRedirect = function() { + var node = this.filegrid.getSelectionModel().getSelected(); + var object_id = node.get("id"); + var newwindow = window.open(window.location.protocol+"//"+window.location.hostname+":"+window.location.port+this.config.package_url+"file?file_id="+object_id); + newwindow.focus(); + } -ajaxFsLayout = function() { - return { - init : function() { - layout = new YAHOO.ext.BorderLayout(document.body, { - hideOnLayout: true, - north: { - split:false, - initialSize: 25, - titlebar: false - }, - west: { - split:true, - initialSize: 300, - titlebar: true, - collapsible: true, - minSize: 100, - maxSize: 400 - }, - center: { - autoScroll: false + // generate a context bar + this.showContext = function(grid,i,e) { + e.stopEvent(); + if(this.contextmenu == null) { + // create the menus + this.contextmenu = new Ext.menu.Menu({ + id: 'rightclickmenu', + items: [ + new Ext.menu.Item({ + text: acs_lang_text.deletefs || 'Delete', + icon: '/resources/ajax-filestorage-ui/icons/delete.png', + handler: this.confirmDel.createDelegate(this) + }), + new Ext.menu.Item({ + text: acs_lang_text.rename || 'Rename', + icon: '/resources/ajax-filestorage-ui/icons/page_edit.png', + handler: this.fileRename.createDelegate(this) + }), + new Ext.menu.Item({ + text: acs_lang_text.linkaddress || 'Copy Link Address', + icon: '/resources/ajax-filestorage-ui/icons/page_copy.png', + handler: this.linkCopy.createDelegate(this) + }), + new Ext.menu.Item({ + text: acs_lang_text.permissions || 'Permissions', + icon: '/resources/ajax-filestorage-ui/icons/group_key.png', + handler: this.permsRedirect.createDelegate(this) + }), + new Ext.menu.Item({ + text: acs_lang_text.properties || 'Properties', + icon: '/resources/ajax-filestorage-ui/icons/page_edit.png', + handler: this.propertiesRedirect.createDelegate(this) + }) ] + }); + + } + // disable rename, copy link, permissions and revisions if more than one node item from the view is selected + if (grid.getSelectionModel().getCount() > 1) { + this.contextmenu.items.items[1].disable(); + this.contextmenu.items.items[2].disable(); + this.contextmenu.items.items[3].disable(); + this.contextmenu.items.items[4].disable(); + } else { + this.contextmenu.items.items[1].enable(); + this.contextmenu.items.items[2].enable(); + this.contextmenu.items.items[3].enable(); + var node = this.filegrid.getSelectionModel().getSelected(); + var object_type = node.get("type"); + if (object_type == "folder" || object_type == "url") { + this.contextmenu.items.items[4].disable(); + } else { + this.contextmenu.items.items[4].enable(); + } + } + + var coords = e.getXY(); + this.contextmenu.rowid = i; + this.contextmenu.showAt([coords[0], coords[1]]); + } + + // handle file upload + this.uploadFile = function(e) { + + if(document.getElementById("upload_file").value != "" && document.getElementById("filetitle").value != "") { + + var callback = { + success: function() { + }, upload: function() { + this.treepanel.getSelectionModel().getSelectedNode().loaded=false; + this.treepanel.getSelectionModel().getSelectedNode().fireEvent("click",this.treepanel.getSelectionModel().getSelectedNode()); + this.upldDialog.getEl().unmask(); + this.upldDialog.hide(); + }, failure: function() { + Ext.Msg.alert(acs_lang_text.error || "Error", acs_lang_text.upload_failed || "Upload failed, please try again later."); + }, scope: this + } + + var loading_msg = acs_lang_text.loading || "One moment. This may take a while depending on how large your upload is." + this.upldDialog.getEl().mask(" "+loading_msg); + + YAHOO.util.Connect.setForm("newfileform", true, true); + + var cObj = YAHOO.util.Connect.asyncRequest("POST", this.xmlhttpurl+"file-add", callback); + + } else { + + Ext.Msg.alert(acs_lang_text.alert || "Alert", acs_lang_text.file_required || "Title and File to upload are required."); + + } + } + + // create the url + this.createUrl = function(e) { + if(document.getElementById("fsurl").value != "" && document.getElementById("fstitle").value != "") { + if (isURL(document.getElementById("fsurl").value)) { + var callback = { + success: function() { + this.treepanel.getSelectionModel().getSelectedNode().loaded=false; + this.treepanel.getSelectionModel().getSelectedNode().fireEvent("click",this.treepanel.getSelectionModel().getSelectedNode()); + this.createurlDialog.getEl().unmask(); + this.createurlDialog.hide(); + },failure: function() { + this.createurlDialog.getEl().unmask(); + Ext.Msg.alert(acs_lang_text.error || "Error",acs_lang_text.createurl_failed || "Create URL failed, please try again later."); + }, scope: this } + + this.createurlDialog.getEl().mask(" One moment."); + + YAHOO.util.Connect.setForm("simple-add"); + + var cObj = YAHOO.util.Connect.asyncRequest("POST", this.xmlhttpurl+"url-add", callback); + } else { + Ext.Msg.alert(acs_lang_text.alert || "Alert", acs_lang_text.invalid_url || "URL is not a valid url."); + } + } else { + + Ext.Msg.alert(acs_lang_text.alert || "Alert", acs_lang_text.invalid_url || "Title and URL are required."); + + } + } + + // shows the create url dialog + this.showCreateUrldialog = function() { + if(!this.createurlDialog.buttons) { + this.createurlDialog.addButton({text:acs_lang_text.ok || 'Ok',icon:"/resources/ajax-filestorage-ui/icons/page_add.png",cls:"x-btn-text-icon"}, this.createUrl, this); + this.createurlDialog.addButton({text:acs_lang_text.cancel ||'Cancel',icon:"/resources/ajax-filestorage-ui/icons/cancel.png",cls:"x-btn-text-icon"}, this.createurlDialog.hide, this.createurlDialog); + } + this.createurlDialog.setTitle(acs_lang_text.createurl || "Create URL"); + this.createurlDialog.body.update("

Title


URL


Description :

"); + this.createurlDialog.body.setStyle("font","normal 12px tahoma, arial, helvetica, sans-serif"); + this.createurlDialog.body.setStyle("background-color","#ffffff"); + this.createurlDialog.body.setStyle("border","1px solid #e2e2e2"); + this.createurlDialog.body.setStyle("padding","3px"); + this.createurlDialog.show(); + } + + // shows the upload dialog, + // check if user has flash 8 or higher + // creates the upload form or + // shows the flash upload dialog + this.showUplddialog = function() { + this.upldDialog.setTitle(acs_lang_text.uploadfile || "Upload Files"); + if(checkFlashVersion() < 8) { + var msg1=acs_lang_text.file_to_upload || "File to upload"; + var msg2=acs_lang_text.file_title || "Title"; + var msg3=acs_lang_text.file_description || "Description"; + var msg4=acs_lang_text.multiple_files || "Multiple Files"; + var msg5=acs_lang_text.multiple_files_msg || "This is a ZIPfile containing multiple files."; + this.upldDialog.body.update("

"+msg1+"


"+msg2+"


"+msg3+" :

"+msg4+" :

"+msg5+"

"); + if(!this.upldDialog.buttons) { + this.upldDialog.addButton({text:acs_lang_text.upload || 'Upload',icon:"/resources/ajax-filestorage-ui/icons/page_add.png",cls:"x-btn-text-icon"}, this.uploadFile, this); + this.upldDialog.addButton({text:acs_lang_text.cancel || 'Cancel',icon:"/resources/ajax-filestorage-ui/icons/cancel.png",cls:"x-btn-text-icon"}, this.upldDialog.hide, this.upldDialog); + } + } else { + if(this.swfu == null) { + var err_msg_txt = acs_lang_text.upload_intro || "Click Browse to select a file to upload to the selected folder."; + this.upldDialog.body.update("
"+err_msg_txt+"
"); + var package_id = String(this.config.package_id); + var user_id = String(this.config.user_id); + var folder_id = String(this.currentfolder); + var max_file_size = String(this.config.max_file_size) || 5000000; + this.swfu = new SWFUpload({ + debug: false, + upload_target_url: "/ajaxfs2/xmlhttp/file-add-flash", + upload_params: {user_id:user_id,package_id:package_id}, + file_types : "*.*", + file_size_limit : max_file_size, + file_queue_limit : 3, + begin_upload_on_queue: false, + file_progress_handler : uploadProgress, + file_cancelled_handler : uploadCancel, + file_complete_handler : uploadComplete, + queue_complete_handler : uploadQueueComplete, + error_handler : uploadError, + flash_url : "/resources/ajax-filestorage-ui/swfupload/swfupload.swf" + }); + this.swfu.fileQueued = uploadStart.createDelegate(this.swfu,[this],true); + this.swfu.fileProgress = uploadProgress.createDelegate(this.swfu,[this],true); + this.swfu.fileComplete = uploadComplete.createDelegate(this.swfu,[this],true); + this.swfu.fileCancelled = uploadCancel.createDelegate(this.swfu,[this],true); + this.swfu.queueComplete = uploadQueueComplete.createDelegate(this.swfu,[this],true); + this.swfu.addSetting("progress_target", "fsuploadprogress"); + this.upldDialog.addButton({text:acs_lang_text.upload || 'Upload',disabled:true,icon:"/resources/ajax-filestorage-ui/icons/arrow_up.png",cls:"x-btn-text-icon"}, this.swfu.startUpload.createDelegate(this.swfu,[null,this],false), this); + this.upldDialog.addButton({text:acs_lang_text.browse || 'Browse',icon:"/resources/ajax-filestorage-ui/icons/page_add.png",cls:"x-btn-text-icon"}, this.swfu.browse, this.swfu); + this.upldDialog.addButton({text:acs_lang_text.close || 'Close',icon:"/resources/ajax-filestorage-ui/icons/cross.png",cls:"x-btn-text-icon"}, this.upldDialog.hide, this.upldDialog); + } + } + this.upldDialog.body.setStyle("font","normal 12px tahoma, arial, helvetica, sans-serif"); + this.upldDialog.body.setStyle("background-color","#ffffff"); + this.upldDialog.body.setStyle("border","1px solid #e2e2e2"); + this.upldDialog.body.setStyle("padding","3px"); + this.upldDialog.show(); + } + + // determine whether to delete from the jsonview or from the tree + this.confirmDel = function() { + var err_msg_txt = acs_lang_text.confirm_delete || "Are you sure you want to delete" + var err_msg_txt2 = acs_lang_text.foldercontains || "This folder contains" + // check if there is a selected file in the jsonview + var selectedRows = this.filegrid.getSelectionModel().getSelections(); + if (selectedRows.length > 0) { + // ** delete from grid ** + if (selectedRows.length == 1) { + var filetodel = selectedRows[0].get("title"); + if(selectedRows[0].get("type") === "folder") { + var msg = err_msg_txt2 + " "+selectedRows[0].get("size")+".
" + } else { + var msg = ""; + } + var msg = msg + err_msg_txt+" "+filetodel+" ?"; + } else { + var msg = err_msg_txt + ":

" + for(var x=0; x" + selectedRows[x].get("title") + " "; + if(selectedRows[x].get("type") === "folder") { + msg=msg+"("+selectedRows[x].get("size")+")"; + } + msg=msg+"
"; + } + } + this.msgbox.confirm(acs_lang_text.confirm || 'Confirm', msg, this.delFsitems,this); + } else { + // ** delete from tree ** + // we can't delete the root node + var selectednode = this.treepanel.getSelectionModel().getSelectedNode(); + var rootnode = this.treepanel.getRootNode(); + if(selectednode.attributes["id"] == rootnode.attributes["id"]) { + Ext.Msg.alert(acs_lang_text.alert || "Alert",acs_lang_text.cant_del_root || "The root folder can not be deleted."); + } else { + // return a confirmation message + this.msgbox.confirm(acs_lang_text.confirm || 'Confirm', err_msg_txt+' '+selectednode.attributes["text"]+'?', this.delFolder,this); + } + } + } + + // delete one or more folder or files + this.delFsitems = function(choice) { + + // get the rows to delete + var selectedRows = this.filegrid.getSelectionModel().getSelections(); + + // arrays for use later + var object_id = []; + + // get all node id's from json view into array + for(var x=0; x
"+response.responseText+""); + } + this.filegrid.container.unmask(); + } + + var params = "object_id="+object_id + var url = this.xmlhttpurl+"delete"; + + if (choice === "yes") { + this.filegrid.container.mask('Deleting'); + this.asyncCon.request({url:url, + params: params, + method:"POST", + callback: callback, + scope: this }); - layout.beginUpdate(); - layout.add('north', new YAHOO.ext.ContentPanel('header', '')); - layout.add('west', new YAHOO.ext.ContentPanel('folders', {title: 'Folders', fitToFrame:true, closable:false})); - innerLayout = new YAHOO.ext.BorderLayout('content', { - south: { - split:true, - initialSize: 200, - minSize: 100, - maxSize: 400, - autoScroll:true, - collapsible:true, - titlebar: true - }, - center: { - autoScroll:true + } + } + + // deletes a folder + this.delFolder = function(choice) { + + var selectednode = this.treepanel.getSelectionModel().getSelectedNode(); + var parentnode = selectednode.parentNode; + var id = selectednode.attributes["id"]; + + var callback = function(option,success,response) { + var err_msg_txt = acs_lang_text.delete_error || "Sorry, there was an error trying to delete this item." + if(success) { + if (response.responseText != "1") { + Ext.Msg.alert(acs_lang_text.error || "Error",err_msg_txt + "

"+response.responseText+""); + } else { + parentnode.fireEvent("click",parentnode); + parentnode.removeChild(selectednode); } + } else { + // delete didn't work, return error + Ext.Msg.alert(acs_lang_text.error || "Error",err_msg_txt+"

"+response.responseText+""); + } + } + + if (choice === "yes") { + this.asyncCon.request({url:this.xmlhttpurl+"delete", + params: "object_id="+id, + method:"POST", + callback: callback, + scope: this }); - innerLayout.add('south', new YAHOO.ext.ContentPanel('revisions', {title: 'Revisions', closable: false})); - innerLayout.add('south', new YAHOO.ext.ContentPanel('properties', {title: 'Properties', closable: false})); - innerLayout.add('center', new YAHOO.ext.ContentPanel('filepane')); - layout.add('center', new YAHOO.ext.NestedLayoutPanel(innerLayout)); - layout.endUpdate(); } + } -}(); -YAHOO.ext.EventManager.onDocumentReady(ajaxFsLayout.init, ajaxFsLayout, true); -/* fsList -object that manages fsItem objects*/ + // creates a new folder in the db + // inserts a blank folder in the ui ready for user to enter name + this.newFolder = function() { -function fsList() { - //properties - // array of fsItems - this.items = []; - //methods - // adds an fsItem to the array of items - this.push = function(obj) { - this.items.push(obj); + // get currently selected folder + var te = this.te; + var tree = this.treepanel; + var currentTreeNode = tree.getSelectionModel().getSelectedNode(); + currentTreeNode.expand(); + + var callback = function(option,success,response) { + var error_msg_txt = acs_lang_text.new_folder_error || "Sorry, there was an error trying to create your new folder."; + if(success) { + if (!isNaN(parseInt(response.responseText))) { + if(parseInt(response.responseText) != 0) { + // create a new blank node on the currently selected one + var newnode = currentTreeNode.appendChild(new Ext.tree.TreeNode({text:acs_lang_text.new_folder_label || 'New Folder',id:response.responseText,iconCls:'folder',singleClickExpand:true,attributes:{write_p:'t'}})); + tree.getSelectionModel().select(newnode); + newnode.loaded=true; + newnode.fireEvent("click",newnode); + setTimeout(function(){ + te.editNode = newnode; + te.startEdit(newnode.ui.textNode); + }, 10); + } else { + Ext.Msg.alert(acs_lang_text.error || "Error",error_msg_txt + "

"+response.responseText+""); + } + } + } else { + Ext.Msg.alert(acs_lang_text.error || "Error",error_msg_txt + "

"+response.responseText+""); + } + } + + this.asyncCon.request({url:this.xmlhttpurl+"newblankfolder", + params: "folder_id="+currentTreeNode.attributes["id"], + method:"POST", + callback: callback, + scope: this + }); } - // retrieves an fsItem from array given the id - this.getItem = function(id) { - var x=0; - for (x=0;x
"+response.responseText+"

"+err_msg_txt2); + node.editNode.setText(oldval); + } + } else { + // ajax failed, revert value + Ext.Msg.alert(acs_lang_text.error || "Error",err_msg_txt+":

"+response.responseText+"

"+err_msg_txt2); + node.editNode.setText(oldval); + } + } + this.asyncCon.request({url:this.xmlhttpurl+"editname", + params: "newname="+newval+"&object_id="+node.editNode.id+"&type=folder", + method:"POST", + callback: callback, + scope: this + }); + }, this, true); + + // ********** CLICK ***************** + + // assign a listener to listen for node clicks + // this will fire the proc to load the right panel + // to fetch the fs items in that folder + this.treepanel.on("click",this.loadFoldercontents,this,true) + + // ********** Grid Row DRAGDROP **************** + + // check if the file/folder can be dropped on a node + + this.treepanel.on("nodedragover",function(e){ + // DO NOT ALLOW DROP TO CURRENT FOLDER + // check if the id of target node to be dropped + // is the same as the currently selected tree node + if (e.target.id == this.treepanel.getSelectionModel().getSelectedNode().id) { + return false; + } + // DO NOT ALLOW TO DROP A NODE TO ITSELF + // check if the id of any of the nodes to be dropped + // is the same as the id on the tree + if(e.source.dragData.selections) { + for (var x=0; x
"+response.responseText+"

"+err_msg_txt2); + error = true; + } + } else { + // ajax failed, revert value + Ext.Msg.alert(acs_lang_text.error || "Error", acs_lang_text.error_and_reverted || "An error occurred. Your changes have been reverted"); + error = true; + } + // if move encountered an error, revert the change + if (error) { + option.target.removeChild(option.thenode); + option.parent.appendChild(option.thenode); + option.parent.loaded=false; + option.parent.expand(); + } else { + option.target.loaded=false; + option.target.fireEvent("click",option.target); + option.target.expand(); + } + } + + var params = "file_ids="+draggedObj+"&folder_target_id="+target; + var url = this.xmlhttpurl+"move"; + + this.asyncCon.request({url:url, + params: params, + method:"POST", + callback: callback, + scope: this, + target: t, + parent: p, + thenode: n + }); + + } else { + + // we dropped a row from the grid + var folder_target_id = ddobj.target.id; + var file_ids = []; + for(var x=0;x