jquery.filechooser.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. /*
  17. * jHue fileChooser plugin
  18. */
  19. ;
  20. (function ($, window, document, undefined) {
  21. var pluginName = "jHueFileChooser",
  22. // global variables (jHueFileChooserGlobals, useful for i18n) can be set on
  23. // desktop/templates/common_header.mako
  24. defaults = {
  25. initialPath:"",
  26. forceRefresh:false,
  27. errorRedirectPath:"",
  28. createFolder:true,
  29. uploadFile:true,
  30. selectFolder:false,
  31. labels: {
  32. BACK: "Back",
  33. SELECT_FOLDER: "Select this folder",
  34. CREATE_FOLDER: "Create folder",
  35. FOLDER_NAME: "Folder name",
  36. CANCEL: "Cancel",
  37. FILE_NOT_FOUND: "The file has not been found",
  38. UPLOAD_FILE: "Upload a file",
  39. FAILED: "Failed"
  40. },
  41. user: "",
  42. onFileChoose:function () {
  43. },
  44. onFolderChoose:function () {
  45. },
  46. onFolderChange:function () {
  47. },
  48. onError:function () {
  49. }
  50. },
  51. STORAGE_PREFIX = "hueFileBrowserLastPathForUser_";
  52. function Plugin(element, options) {
  53. this.element = element;
  54. if (typeof jHueFileChooserGlobals != 'undefined') {
  55. var extendedDefaults = $.extend({}, defaults, jHueFileChooserGlobals);
  56. extendedDefaults.labels = $.extend({}, defaults.labels, jHueFileChooserGlobals.labels);
  57. this.options = $.extend({}, extendedDefaults, options);
  58. if (options != null){
  59. this.options.labels = $.extend({}, extendedDefaults.labels, options.labels);
  60. }
  61. }
  62. else {
  63. this.options = $.extend({}, defaults, options);
  64. if (options != null){
  65. this.options.labels = $.extend({}, defaults.labels, options.labels);
  66. }
  67. }
  68. this._defaults = defaults;
  69. this._name = pluginName;
  70. this.previousPath = "";
  71. this.init();
  72. }
  73. Plugin.prototype.setOptions = function (options) {
  74. this.options = $.extend({}, defaults, options);
  75. if (this.options.forceRefresh){
  76. if ($.trim(this.options.initialPath) != "") {
  77. this.navigateTo(this.options.initialPath);
  78. }
  79. else if ($.totalStorage(STORAGE_PREFIX + this.options.user) != null) {
  80. this.navigateTo($.totalStorage(STORAGE_PREFIX + this.options.user));
  81. }
  82. else {
  83. this.navigateTo("/?default_to_home");
  84. }
  85. }
  86. else {
  87. if ($.trim(this.options.initialPath) != "") {
  88. this.navigateTo(this.options.initialPath);
  89. }
  90. }
  91. };
  92. Plugin.prototype.navigateTo = function (path) {
  93. var _parent = this;
  94. $(_parent.element).empty();
  95. $.getJSON("/filebrowser/chooser" + path, function (data) {
  96. path = data.current_dir_path; // use real path.
  97. var _flist = $("<ul>").addClass("unstyled");
  98. if (data.title != null && data.title == "Error") {
  99. var _errorMsg = $("<div>").addClass("alert").addClass("alert-error").text(data.message);
  100. _errorMsg.appendTo($(_parent.element));
  101. var _previousLink = $("<a>").addClass("btn").addClass("bnt-small").text(_parent.options.labels.BACK).click(function () {
  102. _parent.options.onFolderChange(_parent.previousPath);
  103. _parent.navigateTo(_parent.previousPath);
  104. });
  105. _previousLink.appendTo($(_parent.element));
  106. }
  107. else {
  108. if (data.type == "file") {
  109. _parent.navigateTo(data.view.dirname);
  110. return;
  111. }
  112. $.totalStorage(STORAGE_PREFIX + _parent.options.user, path);
  113. _parent.previousPath = path;
  114. var _breadcrumbs = $("<ul>").addClass("hueBreadcrumb").css("padding", "0");
  115. var _home = $("<li>");
  116. var _homelink = $("<a>").addClass("nounderline").html('<i class="icon-home"></i> Home').css("cursor", "pointer").click(function () {
  117. _parent.navigateTo("/?default_to_home");
  118. });
  119. _homelink.appendTo(_home);
  120. $("<span>").addClass("divider").css("margin-right", "20px").appendTo(_home);
  121. _home.appendTo(_breadcrumbs);
  122. var _bLength = data.breadcrumbs.length;
  123. $(data.breadcrumbs).each(function (cnt, crumb) {
  124. var _crumb = $("<li>");
  125. var _crumbLink = $("<a>");
  126. var _crumbLabel = (crumb.label != null && crumb.label != "") ? crumb.label : "/";
  127. _crumbLink.attr("href", "javascript:void(0)").text(_crumbLabel).appendTo(_crumb);
  128. if (cnt < _bLength - 1) {
  129. if (cnt > 0) {
  130. $("<span>").addClass("divider").text("/").appendTo(_crumb);
  131. }
  132. else {
  133. $("<span>").html("&nbsp;").appendTo(_crumb);
  134. }
  135. }
  136. _crumb.click(function () {
  137. var _url = (crumb.url != null && crumb.url != "") ? crumb.url : "/";
  138. _parent.options.onFolderChange(_url);
  139. _parent.navigateTo(_url);
  140. });
  141. _crumb.appendTo(_breadcrumbs);
  142. });
  143. _breadcrumbs.appendTo($(_parent.element));
  144. $(data.files).each(function (cnt, file) {
  145. var _f = $("<li>");
  146. var _flink = $("<a>");
  147. _flink.attr("href", "javascript:void(0)").text(" " + file.name).appendTo(_f);
  148. if (file.type == "dir") {
  149. $("<i class='icon-folder-close'></i>").prependTo(_flink);
  150. _f.click(function () {
  151. _parent.options.onFolderChange(file.path);
  152. _parent.navigateTo(file.path);
  153. });
  154. }
  155. if (file.type == "file") {
  156. $("<i class='icon-file-alt'></i>").prependTo(_flink);
  157. _f.click(function () {
  158. _parent.options.onFileChoose(file.path);
  159. });
  160. }
  161. _f.appendTo(_flist);
  162. });
  163. _flist.appendTo($(_parent.element));
  164. var _actions = $("<div>").addClass("jHueFilechooserActions");
  165. var _showActions = false;
  166. var _uploadFileBtn;
  167. var _createFolderBtn;
  168. var _selectFolderBtn;
  169. if (_parent.options.uploadFile) {
  170. _uploadFileBtn = $("<div>").attr("id", "file-uploader");
  171. _uploadFileBtn.appendTo(_actions);
  172. _showActions = true;
  173. initUploader(path, _parent, _uploadFileBtn, _parent.options.labels);
  174. }
  175. if (_parent.options.selectFolder) {
  176. _selectFolderBtn = $("<a>").addClass("btn").addClass("small").text(_parent.options.labels.SELECT_FOLDER);
  177. if (_parent.options.uploadFile){
  178. _selectFolderBtn.css("margin-top", "10px");
  179. }
  180. _selectFolderBtn.appendTo(_actions);
  181. _showActions = true;
  182. _selectFolderBtn.click(function () {
  183. _parent.options.onFolderChoose(path);
  184. });
  185. }
  186. $("<span> </span>").appendTo(_actions);
  187. if (_parent.options.createFolder) {
  188. _createFolderBtn = $("<a>").addClass("btn").addClass("small").text(_parent.options.labels.CREATE_FOLDER);
  189. if (_parent.options.uploadFile){
  190. _createFolderBtn.css("margin-top", "10px");
  191. }
  192. _createFolderBtn.appendTo(_actions);
  193. _showActions = true;
  194. var _createFolderDetails = $("<form>").css("margin-top", "10px").addClass("well form-inline");
  195. _createFolderDetails.hide();
  196. var _folderName = $("<input>").attr("type", "text").attr("placeholder", _parent.options.labels.FOLDER_NAME).appendTo(_createFolderDetails);
  197. $("<span> </span>").appendTo(_createFolderDetails);
  198. var _folderBtn = $("<input>").attr("type", "button").attr("value", _parent.options.labels.CREATE_FOLDER).addClass("btn primary").appendTo(_createFolderDetails);
  199. $("<span> </span>").appendTo(_createFolderDetails);
  200. var _folderCancel = $("<input>").attr("type", "button").attr("value", _parent.options.labels.CANCEL).addClass("btn").appendTo(_createFolderDetails);
  201. _folderCancel.click(function () {
  202. if (_uploadFileBtn) {
  203. _uploadFileBtn.removeClass("disabled");
  204. }
  205. _createFolderBtn.removeClass("disabled");
  206. _createFolderDetails.slideUp();
  207. });
  208. _folderBtn.click(function () {
  209. $.ajax({
  210. type:"POST",
  211. url:"/filebrowser/mkdir",
  212. data:{
  213. name:_folderName.val(),
  214. path:path
  215. },
  216. beforeSend:function (xhr) {
  217. xhr.setRequestHeader("X-Requested-With", "Hue"); // need to override the default one because otherwise Django returns HTTP 500
  218. },
  219. success:function (xhr, status) {
  220. if (status == "success") {
  221. _parent.navigateTo(path);
  222. if (_uploadFileBtn) {
  223. _uploadFileBtn.removeClass("disabled");
  224. }
  225. _createFolderBtn.removeClass("disabled");
  226. _createFolderDetails.slideUp();
  227. }
  228. }
  229. });
  230. });
  231. _createFolderDetails.appendTo(_actions);
  232. _createFolderBtn.click(function () {
  233. if (_uploadFileBtn) {
  234. _uploadFileBtn.addClass("disabled");
  235. }
  236. _createFolderBtn.addClass("disabled");
  237. _createFolderDetails.slideDown();
  238. });
  239. }
  240. if (_showActions){
  241. _actions.appendTo($(_parent.element));
  242. }
  243. }
  244. }).error(function(){
  245. _parent.options.onError();
  246. _parent.navigateTo(_parent.options.errorRedirectPath != "" ? _parent.options.errorRedirectPath : "/?default_to_home");
  247. if ($.jHueNotify) {
  248. $.jHueNotify.info(_parent.options.labels.FILE_NOT_FOUND);
  249. }
  250. });
  251. };
  252. var num_of_pending_uploads = 0;
  253. function initUploader(path, _parent, el, labels) {
  254. var uploader = new qq.FileUploader({
  255. element:el[0],
  256. action:'/filebrowser/upload/file',
  257. params:{
  258. dest:path,
  259. fileFieldLabel:'hdfs_file'
  260. },
  261. onComplete:function (id, fileName, responseJSON) {
  262. num_of_pending_uploads--;
  263. if(num_of_pending_uploads == 0){
  264. _parent.navigateTo(path);
  265. }
  266. },
  267. onSubmit: function(id, fileName){
  268. num_of_pending_uploads++;
  269. },
  270. template: '<div class="qq-uploader">' +
  271. '<div class="qq-upload-drop-area"><span></span></div>' +
  272. '<div class="qq-upload-button">' + labels.UPLOAD_FILE + '</div>' +
  273. '<ul class="qq-upload-list"></ul>' +
  274. '</div>',
  275. fileTemplate: '<li>' +
  276. '<span class="qq-upload-file"></span>' +
  277. '<span class="qq-upload-spinner"></span>' +
  278. '<span class="qq-upload-size"></span>' +
  279. '<a class="qq-upload-cancel" href="#">' + labels.CANCEL + '</a>' +
  280. '<span class="qq-upload-failed-text">' + labels.FAILED + '</span>' +
  281. '</li>',
  282. debug:false
  283. });
  284. }
  285. Plugin.prototype.init = function () {
  286. if ($.trim(this.options.initialPath) != "") {
  287. this.navigateTo(this.options.initialPath);
  288. }
  289. else if ($.totalStorage(STORAGE_PREFIX + this.options.user) != null) {
  290. this.navigateTo($.totalStorage(STORAGE_PREFIX + this.options.user));
  291. }
  292. else {
  293. this.navigateTo("/?default_to_home");
  294. }
  295. };
  296. $.fn[pluginName] = function (options) {
  297. return this.each(function () {
  298. if (!$.data(this, 'plugin_' + pluginName)) {
  299. $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
  300. }
  301. else {
  302. $.data(this, 'plugin_' + pluginName).setOptions(options);
  303. }
  304. });
  305. }
  306. })(jQuery, window, document);