You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

js.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /**
  2. * Disable console output unless DEBUG mode is enabled.
  3. * Add
  4. * define('DEBUG', true);
  5. * To the end of config/config.php to enable debug mode.
  6. * The undefined checks fix the broken ie8 console
  7. */
  8. if (oc_debug !== true || typeof console === "undefined" || typeof console.log === "undefined") {
  9. if (!window.console) {
  10. window.console = {};
  11. }
  12. var methods = ['log', 'debug', 'warn', 'info', 'error', 'assert'];
  13. for (var i = 0; i < methods.length; i++) {
  14. console[methods[i]] = function () { };
  15. }
  16. }
  17. /**
  18. * translate a string
  19. * @param app the id of the app for which to translate the string
  20. * @param text the string to translate
  21. * @return string
  22. */
  23. function t(app,text, vars){
  24. if( !( t.cache[app] )){
  25. $.ajax(OC.filePath('core','ajax','translations.php'),{
  26. async:false,//todo a proper sollution for this without sync ajax calls
  27. data:{'app': app},
  28. type:'POST',
  29. success:function(jsondata){
  30. t.cache[app] = jsondata.data;
  31. }
  32. });
  33. // Bad answer ...
  34. if( !( t.cache[app] )){
  35. t.cache[app] = [];
  36. }
  37. }
  38. var _build = function (text, vars) {
  39. return text.replace(/{([^{}]*)}/g,
  40. function (a, b) {
  41. var r = vars[b];
  42. return typeof r === 'string' || typeof r === 'number' ? r : a;
  43. }
  44. );
  45. };
  46. if( typeof( t.cache[app][text] ) !== 'undefined' ){
  47. if(typeof vars === 'object') {
  48. return _build(t.cache[app][text], vars);
  49. } else {
  50. return t.cache[app][text];
  51. }
  52. }
  53. else{
  54. if(typeof vars === 'object') {
  55. return _build(text, vars);
  56. } else {
  57. return text;
  58. }
  59. }
  60. }
  61. t.cache={};
  62. /*
  63. * Sanitizes a HTML string
  64. * @param string
  65. * @return Sanitized string
  66. */
  67. function escapeHTML(s) {
  68. return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
  69. }
  70. /**
  71. * Get the path to download a file
  72. * @param file The filename
  73. * @param dir The directory the file is in - e.g. $('#dir').val()
  74. * @return string
  75. */
  76. function fileDownloadPath(dir, file) {
  77. return OC.filePath('files', 'ajax', 'download.php')+'?files='+encodeURIComponent(file)+'&dir='+encodeURIComponent(dir);
  78. }
  79. var OC={
  80. PERMISSION_CREATE:4,
  81. PERMISSION_READ:1,
  82. PERMISSION_UPDATE:2,
  83. PERMISSION_DELETE:8,
  84. PERMISSION_SHARE:16,
  85. webroot:oc_webroot,
  86. appswebroots:(typeof oc_appswebroots !== 'undefined') ? oc_appswebroots:false,
  87. currentUser:(typeof oc_current_user!=='undefined')?oc_current_user:false,
  88. coreApps:['', 'admin','log','search','settings','core','3rdparty'],
  89. /**
  90. * get an absolute url to a file in an appen
  91. * @param app the id of the app the file belongs to
  92. * @param file the file path relative to the app folder
  93. * @return string
  94. */
  95. linkTo:function(app,file){
  96. return OC.filePath(app,'',file);
  97. },
  98. /**
  99. * Creates an url for remote use
  100. * @param string $service id
  101. * @return string the url
  102. *
  103. * Returns a url to the given service.
  104. */
  105. linkToRemoteBase:function(service) {
  106. return OC.webroot + '/remote.php/' + service;
  107. },
  108. /**
  109. * @brief Creates an absolute url for remote use
  110. * @param string $service id
  111. * @param bool $add_slash
  112. * @return string the url
  113. *
  114. * Returns a absolute url to the given service.
  115. */
  116. linkToRemote:function(service) {
  117. return window.location.protocol + '//' + window.location.host + OC.linkToRemoteBase(service);
  118. },
  119. /**
  120. * get the absolute url for a file in an app
  121. * @param app the id of the app
  122. * @param type the type of the file to link to (e.g. css,img,ajax.template)
  123. * @param file the filename
  124. * @return string
  125. */
  126. filePath:function(app,type,file){
  127. var isCore=OC.coreApps.indexOf(app)!==-1,
  128. link=OC.webroot;
  129. if((file.substring(file.length-3) === 'php' || file.substring(file.length-3) === 'css') && !isCore){
  130. link+='/index.php/apps/' + app;
  131. if (file != 'index.php') {
  132. link+='/';
  133. if(type){
  134. link+=encodeURI(type + '/');
  135. }
  136. link+= file;
  137. }
  138. }else if(file.substring(file.length-3) !== 'php' && !isCore){
  139. link=OC.appswebroots[app];
  140. if(type){
  141. link+= '/'+type+'/';
  142. }
  143. if(link.substring(link.length-1) !== '/'){
  144. link+='/';
  145. }
  146. link+=file;
  147. }else{
  148. if ((app == 'settings' || app == 'core' || app == 'search') && type == 'ajax') {
  149. link+='/index.php/';
  150. }
  151. else {
  152. link+='/';
  153. }
  154. if(!isCore){
  155. link+='apps/';
  156. }
  157. if (app !== '') {
  158. app+='/';
  159. link+=app;
  160. }
  161. if(type){
  162. link+=type+'/';
  163. }
  164. link+=file;
  165. }
  166. return link;
  167. },
  168. /**
  169. * get the absolute path to an image file
  170. * @param app the app id to which the image belongs
  171. * @param file the name of the image file
  172. * @return string
  173. *
  174. * if no extension is given for the image, it will automatically decide between .png and .svg based on what the browser supports
  175. */
  176. imagePath:function(app,file){
  177. if(file.indexOf('.')==-1){//if no extension is given, use png or svg depending on browser support
  178. file+=(SVGSupport())?'.svg':'.png';
  179. }
  180. return OC.filePath(app,'img',file);
  181. },
  182. /**
  183. * load a script for the server and load it
  184. * @param app the app id to which the script belongs
  185. * @param script the filename of the script
  186. * @param ready event handeler to be called when the script is loaded
  187. *
  188. * if the script is already loaded, the event handeler will be called directly
  189. */
  190. addScript:function(app,script,ready){
  191. var deferred, path=OC.filePath(app,'js',script+'.js');
  192. if(!OC.addScript.loaded[path]){
  193. if(ready){
  194. deferred=$.getScript(path,ready);
  195. }else{
  196. deferred=$.getScript(path);
  197. }
  198. OC.addScript.loaded[path]=deferred;
  199. }else{
  200. if(ready){
  201. ready();
  202. }
  203. }
  204. return OC.addScript.loaded[path];
  205. },
  206. /**
  207. * load a css file and load it
  208. * @param app the app id to which the css style belongs
  209. * @param style the filename of the css file
  210. */
  211. addStyle:function(app,style){
  212. var path=OC.filePath(app,'css',style+'.css');
  213. if(OC.addStyle.loaded.indexOf(path)===-1){
  214. OC.addStyle.loaded.push(path);
  215. style=$('<link rel="stylesheet" type="text/css" href="'+path+'"/>');
  216. $('head').append(style);
  217. }
  218. },
  219. basename: function(path) {
  220. return path.replace(/\\/g,'/').replace( /.*\//, '' );
  221. },
  222. dirname: function(path) {
  223. return path.replace(/\\/g,'/').replace(/\/[^\/]*$/, '');
  224. },
  225. /**
  226. * do a search query and display the results
  227. * @param query the search query
  228. */
  229. search:function(query){
  230. if(query){
  231. OC.addStyle('search','results');
  232. $.getJSON(OC.filePath('search','ajax','search.php')+'?query='+encodeURIComponent(query), function(results){
  233. OC.search.lastResults=results;
  234. OC.search.showResults(results);
  235. });
  236. }
  237. },
  238. dialogs:OCdialogs,
  239. mtime2date:function(mtime) {
  240. mtime = parseInt(mtime,10);
  241. var date = new Date(1000*mtime);
  242. return date.getDate()+'.'+(date.getMonth()+1)+'.'+date.getFullYear()+', '+date.getHours()+':'+date.getMinutes();
  243. },
  244. /**
  245. * Opens a popup with the setting for an app.
  246. * @param appid String. The ID of the app e.g. 'calendar', 'contacts' or 'files'.
  247. * @param loadJS boolean or String. If true 'js/settings.js' is loaded. If it's a string
  248. * it will attempt to load a script by that name in the 'js' directory.
  249. * @param cache boolean. If true the javascript file won't be forced refreshed. Defaults to true.
  250. * @param scriptName String. The name of the PHP file to load. Defaults to 'settings.php' in
  251. * the root of the app directory hierarchy.
  252. */
  253. appSettings:function(args) {
  254. if(typeof args === 'undefined' || typeof args.appid === 'undefined') {
  255. throw { name: 'MissingParameter', message: 'The parameter appid is missing' };
  256. }
  257. var props = {scriptName:'settings.php', cache:true};
  258. $.extend(props, args);
  259. var settings = $('#appsettings');
  260. if(settings.length == 0) {
  261. throw { name: 'MissingDOMElement', message: 'There has be be an element with id "appsettings" for the popup to show.' };
  262. }
  263. var popup = $('#appsettings_popup');
  264. if(popup.length == 0) {
  265. $('body').prepend('<div class="popup hidden" id="appsettings_popup"></div>');
  266. popup = $('#appsettings_popup');
  267. popup.addClass(settings.hasClass('topright') ? 'topright' : 'bottomleft');
  268. }
  269. if(popup.is(':visible')) {
  270. popup.hide().remove();
  271. } else {
  272. var arrowclass = settings.hasClass('topright') ? 'up' : 'left';
  273. var jqxhr = $.get(OC.filePath(props.appid, '', props.scriptName), function(data) {
  274. popup.html(data).ready(function() {
  275. popup.prepend('<span class="arrow '+arrowclass+'"></span><h2>'+t('core', 'Settings')+'</h2><a class="close svg"></a>').show();
  276. popup.find('.close').bind('click', function() {
  277. popup.remove();
  278. });
  279. if(typeof props.loadJS !== 'undefined') {
  280. var scriptname;
  281. if(props.loadJS === true) {
  282. scriptname = 'settings.js';
  283. } else if(typeof props.loadJS === 'string') {
  284. scriptname = props.loadJS;
  285. } else {
  286. throw { name: 'InvalidParameter', message: 'The "loadJS" parameter must be either boolean or a string.' };
  287. }
  288. if(props.cache) {
  289. $.ajaxSetup({cache: true});
  290. }
  291. $.getScript(OC.filePath(props.appid, 'js', scriptname))
  292. .fail(function(jqxhr, settings, e) {
  293. throw e;
  294. });
  295. }
  296. }).show();
  297. }, 'html');
  298. }
  299. }
  300. };
  301. OC.search.customResults={};
  302. OC.search.currentResult=-1;
  303. OC.search.lastQuery='';
  304. OC.search.lastResults={};
  305. OC.addStyle.loaded=[];
  306. OC.addScript.loaded=[];
  307. OC.Notification={
  308. getDefaultNotificationFunction: null,
  309. setDefault: function(callback) {
  310. OC.Notification.getDefaultNotificationFunction = callback;
  311. },
  312. hide: function(callback) {
  313. $("#notification").text('');
  314. $('#notification').fadeOut('400', function(){
  315. if (OC.Notification.isHidden()) {
  316. if (OC.Notification.getDefaultNotificationFunction) {
  317. OC.Notification.getDefaultNotificationFunction.call();
  318. }
  319. }
  320. if (callback) {
  321. callback.call();
  322. }
  323. });
  324. },
  325. showHtml: function(html) {
  326. var notification = $('#notification');
  327. notification.hide();
  328. notification.html(html);
  329. notification.fadeIn().css("display","inline");
  330. },
  331. show: function(text) {
  332. var notification = $('#notification');
  333. notification.hide();
  334. notification.text(text);
  335. notification.fadeIn().css("display","inline");
  336. },
  337. isHidden: function() {
  338. return ($("#notification").text() === '');
  339. }
  340. };
  341. OC.Breadcrumb={
  342. container:null,
  343. crumbs:[],
  344. push:function(name, link){
  345. if(!OC.Breadcrumb.container){//default
  346. OC.Breadcrumb.container=$('#controls');
  347. }
  348. var crumb=$('<div/>');
  349. crumb.addClass('crumb').addClass('last');
  350. crumb.attr('style','background-image:url("'+OC.imagePath('core','breadcrumb')+'")');
  351. var crumbLink=$('<a/>');
  352. crumbLink.attr('href',link);
  353. crumbLink.text(name);
  354. crumb.append(crumbLink);
  355. var existing=OC.Breadcrumb.container.find('div.crumb');
  356. if(existing.length){
  357. existing.removeClass('last');
  358. existing.last().after(crumb);
  359. }else{
  360. OC.Breadcrumb.container.append(crumb);
  361. }
  362. OC.Breadcrumb.crumbs.push(crumb);
  363. return crumb;
  364. },
  365. pop:function(){
  366. if(!OC.Breadcrumb.container){//default
  367. OC.Breadcrumb.container=$('#controls');
  368. }
  369. OC.Breadcrumb.container.find('div.crumb').last().remove();
  370. OC.Breadcrumb.container.find('div.crumb').last().addClass('last');
  371. OC.Breadcrumb.crumbs.pop();
  372. },
  373. clear:function(){
  374. if(!OC.Breadcrumb.container){//default
  375. OC.Breadcrumb.container=$('#controls');
  376. }
  377. OC.Breadcrumb.container.find('div.crumb').remove();
  378. OC.Breadcrumb.crumbs=[];
  379. }
  380. };
  381. if(typeof localStorage !=='undefined' && localStorage !== null){
  382. //user and instance aware localstorage
  383. OC.localStorage={
  384. namespace:'oc_'+OC.currentUser+'_'+OC.webroot+'_',
  385. hasItem:function(name){
  386. return OC.localStorage.getItem(name)!==null;
  387. },
  388. setItem:function(name,item){
  389. return localStorage.setItem(OC.localStorage.namespace+name,JSON.stringify(item));
  390. },
  391. getItem:function(name){
  392. var item = localStorage.getItem(OC.localStorage.namespace+name);
  393. if(item===null) {
  394. return null;
  395. } else if (typeof JSON === 'undefined') {
  396. //fallback to jquery for IE6/7/8
  397. return $.parseJSON(item);
  398. } else {
  399. return JSON.parse(item);
  400. }
  401. }
  402. };
  403. }else{
  404. //dummy localstorage
  405. OC.localStorage={
  406. hasItem:function(){
  407. return false;
  408. },
  409. setItem:function(){
  410. return false;
  411. },
  412. getItem:function(){
  413. return null;
  414. }
  415. };
  416. }
  417. /**
  418. * implement Array.filter for browsers without native support
  419. */
  420. if (!Array.prototype.filter) {
  421. Array.prototype.filter = function(fun /*, thisp*/) {
  422. var len = this.length >>> 0;
  423. if (typeof fun !== "function"){
  424. throw new TypeError();
  425. }
  426. var res = [];
  427. var thisp = arguments[1];
  428. for (var i = 0; i < len; i++) {
  429. if (i in this) {
  430. var val = this[i]; // in case fun mutates this
  431. if (fun.call(thisp, val, i, this))
  432. res.push(val);
  433. }
  434. }
  435. return res;
  436. };
  437. }
  438. /**
  439. * implement Array.indexOf for browsers without native support
  440. */
  441. if (!Array.prototype.indexOf){
  442. Array.prototype.indexOf = function(elt /*, from*/)
  443. {
  444. var len = this.length;
  445. var from = Number(arguments[1]) || 0;
  446. from = (from < 0) ? Math.ceil(from) : Math.floor(from);
  447. if (from < 0){
  448. from += len;
  449. }
  450. for (; from < len; from++)
  451. {
  452. if (from in this && this[from] === elt){
  453. return from;
  454. }
  455. }
  456. return -1;
  457. };
  458. }
  459. /**
  460. * check if the browser support svg images
  461. */
  462. function SVGSupport() {
  463. return SVGSupport.checkMimeType.correct && !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect;
  464. }
  465. SVGSupport.checkMimeType=function(){
  466. $.ajax({
  467. url: OC.imagePath('core','breadcrumb.svg'),
  468. success:function(data,text,xhr){
  469. var headerParts=xhr.getAllResponseHeaders().split("\n");
  470. var headers={};
  471. $.each(headerParts,function(i,text){
  472. if(text){
  473. var parts=text.split(':',2);
  474. if(parts.length===2){
  475. var value=parts[1].trim();
  476. if(value[0]==='"'){
  477. value=value.substr(1,value.length-2);
  478. }
  479. headers[parts[0]]=value;
  480. }
  481. }
  482. });
  483. if(headers["Content-Type"]!=='image/svg+xml'){
  484. replaceSVG();
  485. SVGSupport.checkMimeType.correct=false;
  486. }
  487. }
  488. });
  489. };
  490. SVGSupport.checkMimeType.correct=true;
  491. //replace all svg images with png for browser compatibility
  492. function replaceSVG(){
  493. $('img.svg').each(function(index,element){
  494. element=$(element);
  495. var src=element.attr('src');
  496. element.attr('src',src.substr(0,src.length-3)+'png');
  497. });
  498. $('.svg').each(function(index,element){
  499. element=$(element);
  500. var background=element.css('background-image');
  501. if(background){
  502. var i=background.lastIndexOf('.svg');
  503. if(i>=0){
  504. background=background.substr(0,i)+'.png'+background.substr(i+4);
  505. element.css('background-image',background);
  506. }
  507. }
  508. element.find('*').each(function(index,element) {
  509. element=$(element);
  510. var background=element.css('background-image');
  511. if(background){
  512. var i=background.lastIndexOf('.svg');
  513. if(i>=0){
  514. background=background.substr(0,i)+'.png'+background.substr(i+4);
  515. element.css('background-image',background);
  516. }
  517. }
  518. });
  519. });
  520. }
  521. /**
  522. * prototypal inharitence functions
  523. *
  524. * usage:
  525. * MySubObject=object(MyObject)
  526. */
  527. function object(o) {
  528. function F() {}
  529. F.prototype = o;
  530. return new F();
  531. }
  532. /**
  533. * Fills height of window. (more precise than height: 100%;)
  534. */
  535. function fillHeight(selector) {
  536. if (selector.length === 0) {
  537. return;
  538. }
  539. var height = parseFloat($(window).height())-selector.offset().top;
  540. selector.css('height', height + 'px');
  541. if(selector.outerHeight() > selector.height()){
  542. selector.css('height', height-(selector.outerHeight()-selector.height()) + 'px');
  543. }
  544. console.warn("This function is deprecated! Use CSS instead");
  545. }
  546. /**
  547. * Fills height and width of window. (more precise than height: 100%; or width: 100%;)
  548. */
  549. function fillWindow(selector) {
  550. if (selector.length === 0) {
  551. return;
  552. }
  553. fillHeight(selector);
  554. var width = parseFloat($(window).width())-selector.offset().left;
  555. selector.css('width', width + 'px');
  556. if(selector.outerWidth() > selector.width()){
  557. selector.css('width', width-(selector.outerWidth()-selector.width()) + 'px');
  558. }
  559. console.warn("This function is deprecated! Use CSS instead");
  560. }
  561. $(document).ready(function(){
  562. if(!SVGSupport()){ //replace all svg images with png images for browser that dont support svg
  563. replaceSVG();
  564. }else{
  565. SVGSupport.checkMimeType();
  566. }
  567. $('form.searchbox').submit(function(event){
  568. event.preventDefault();
  569. });
  570. $('#searchbox').keyup(function(event){
  571. if(event.keyCode===13){//enter
  572. if(OC.search.currentResult>-1){
  573. var result=$('#searchresults tr.result a')[OC.search.currentResult];
  574. window.location = $(result).attr('href');
  575. }
  576. }else if(event.keyCode===38){//up
  577. if(OC.search.currentResult>0){
  578. OC.search.currentResult--;
  579. OC.search.renderCurrent();
  580. }
  581. }else if(event.keyCode===40){//down
  582. if(OC.search.lastResults.length>OC.search.currentResult+1){
  583. OC.search.currentResult++;
  584. OC.search.renderCurrent();
  585. }
  586. }else if(event.keyCode===27){//esc
  587. OC.search.hide();
  588. }else{
  589. var query=$('#searchbox').val();
  590. if(OC.search.lastQuery!==query){
  591. OC.search.lastQuery=query;
  592. OC.search.currentResult=-1;
  593. if(query.length>2){
  594. OC.search(query);
  595. }else{
  596. if(OC.search.hide){
  597. OC.search.hide();
  598. }
  599. }
  600. }
  601. }
  602. });
  603. // 'show password' checkbox
  604. $('#pass2').showPassword();
  605. //use infield labels
  606. $("label.infield").inFieldLabels();
  607. var checkShowCredentials = function() {
  608. var empty = false;
  609. $('input#user, input#password').each(function() {
  610. if ($(this).val() === '') {
  611. empty = true;
  612. }
  613. });
  614. if(empty) {
  615. $('#submit').fadeOut();
  616. $('#remember_login').hide();
  617. $('#remember_login+label').fadeOut();
  618. } else {
  619. $('#submit').fadeIn();
  620. $('#remember_login').show();
  621. $('#remember_login+label').fadeIn();
  622. }
  623. };
  624. // hide log in button etc. when form fields not filled
  625. // commented out due to some browsers having issues with it
  626. // checkShowCredentials();
  627. // $('input#user, input#password').keyup(checkShowCredentials);
  628. $('#settings #expand').keydown(function(event) {
  629. if (event.which === 13 || event.which === 32) {
  630. $('#expand').click()
  631. }
  632. });
  633. $('#settings #expand').click(function(event) {
  634. $('#settings #expanddiv').slideToggle();
  635. event.stopPropagation();
  636. });
  637. $('#settings #expanddiv').click(function(event){
  638. event.stopPropagation();
  639. });
  640. $(window).click(function(){//hide the settings menu when clicking outside it
  641. if($('body').attr("id")==="body-user"){
  642. $('#settings #expanddiv').slideUp();
  643. }
  644. });
  645. // all the tipsy stuff needs to be here (in reverse order) to work
  646. $('.jp-controls .jp-previous').tipsy({gravity:'nw', fade:true, live:true});
  647. $('.jp-controls .jp-next').tipsy({gravity:'n', fade:true, live:true});
  648. $('.password .action').tipsy({gravity:'se', fade:true, live:true});
  649. $('#upload').tipsy({gravity:'w', fade:true});
  650. $('.selectedActions a').tipsy({gravity:'s', fade:true, live:true});
  651. $('a.delete').tipsy({gravity: 'e', fade:true, live:true});
  652. $('a.action').tipsy({gravity:'s', fade:true, live:true});
  653. $('#headerSize').tipsy({gravity:'s', fade:true, live:true});
  654. $('td.filesize').tipsy({gravity:'s', fade:true, live:true});
  655. $('td .modified').tipsy({gravity:'s', fade:true, live:true});
  656. $('input').tipsy({gravity:'w', fade:true});
  657. $('input[type=text]').focus(function(){
  658. this.select();
  659. });
  660. });
  661. if (!Array.prototype.map){
  662. Array.prototype.map = function(fun /*, thisp */){
  663. "use strict";
  664. if (this === void 0 || this === null){
  665. throw new TypeError();
  666. }
  667. var t = Object(this);
  668. var len = t.length >>> 0;
  669. if (typeof fun !== "function"){
  670. throw new TypeError();
  671. }
  672. var res = new Array(len);
  673. var thisp = arguments[1];
  674. for (var i = 0; i < len; i++){
  675. if (i in t){
  676. res[i] = fun.call(thisp, t[i], i, t);
  677. }
  678. }
  679. return res;
  680. };
  681. }
  682. /**
  683. * Filter Jquery selector by attribute value
  684. */
  685. $.fn.filterAttr = function(attr_name, attr_value) {
  686. return this.filter(function() { return $(this).attr(attr_name) === attr_value; });
  687. };
  688. function humanFileSize(size) {
  689. var humanList = ['B', 'kB', 'MB', 'GB', 'TB'];
  690. // Calculate Log with base 1024: size = 1024 ** order
  691. var order = size?Math.floor(Math.log(size) / Math.log(1024)):0;
  692. // Stay in range of the byte sizes that are defined
  693. order = Math.min(humanList.length - 1, order);
  694. var readableFormat = humanList[order];
  695. var relativeSize = (size / Math.pow(1024, order)).toFixed(1);
  696. if(relativeSize.substr(relativeSize.length-2,2)=='.0'){
  697. relativeSize=relativeSize.substr(0,relativeSize.length-2);
  698. }
  699. return relativeSize + ' ' + readableFormat;
  700. }
  701. function simpleFileSize(bytes) {
  702. var mbytes = Math.round(bytes/(1024*1024/10))/10;
  703. if(bytes == 0) { return '0'; }
  704. else if(mbytes < 0.1) { return '< 0.1'; }
  705. else if(mbytes > 1000) { return '> 1000'; }
  706. else { return mbytes.toFixed(1); }
  707. }
  708. function formatDate(date){
  709. if(typeof date=='number'){
  710. date=new Date(date);
  711. }
  712. return $.datepicker.formatDate(datepickerFormatDate, date)+' '+date.getHours()+':'+((date.getMinutes()<10)?'0':'')+date.getMinutes();
  713. }
  714. /**
  715. * takes an absolute timestamp and return a string with a human-friendly relative date
  716. * @param int a Unix timestamp
  717. */
  718. function relative_modified_date(timestamp) {
  719. var timediff = Math.round((new Date()).getTime() / 1000) - timestamp;
  720. var diffminutes = Math.round(timediff/60);
  721. var diffhours = Math.round(diffminutes/60);
  722. var diffdays = Math.round(diffhours/24);
  723. var diffmonths = Math.round(diffdays/31);
  724. if(timediff < 60) { return t('core','seconds ago'); }
  725. else if(timediff < 120) { return t('core','1 minute ago'); }
  726. else if(timediff < 3600) { return t('core','{minutes} minutes ago',{minutes: diffminutes}); }
  727. else if(timediff < 7200) { return t('core','1 hour ago'); }
  728. else if(timediff < 86400) { return t('core','{hours} hours ago',{hours: diffhours}); }
  729. else if(timediff < 86400) { return t('core','today'); }
  730. else if(timediff < 172800) { return t('core','yesterday'); }
  731. else if(timediff < 2678400) { return t('core','{days} days ago',{days: diffdays}); }
  732. else if(timediff < 5184000) { return t('core','last month'); }
  733. else if(timediff < 31556926) { return t('core','{months} months ago',{months: diffmonths}); }
  734. //else if(timediff < 31556926) { return t('core','months ago'); }
  735. else if(timediff < 63113852) { return t('core','last year'); }
  736. else { return t('core','years ago'); }
  737. }
  738. /**
  739. * get a variable by name
  740. * @param string name
  741. */
  742. OC.get=function(name) {
  743. var namespaces = name.split(".");
  744. var tail = namespaces.pop();
  745. var context=window;
  746. for(var i = 0; i < namespaces.length; i++) {
  747. context = context[namespaces[i]];
  748. if(!context){
  749. return false;
  750. }
  751. }
  752. return context[tail];
  753. };
  754. /**
  755. * set a variable by name
  756. * @param string name
  757. * @param mixed value
  758. */
  759. OC.set=function(name, value) {
  760. var namespaces = name.split(".");
  761. var tail = namespaces.pop();
  762. var context=window;
  763. for(var i = 0; i < namespaces.length; i++) {
  764. if(!context[namespaces[i]]){
  765. context[namespaces[i]]={};
  766. }
  767. context = context[namespaces[i]];
  768. }
  769. context[tail]=value;
  770. };