From 3610a7e902a7d3a18d5762295f8899dcd9e4f5c3 Mon Sep 17 00:00:00 2001 From: Pawel Sierszen Date: Mon, 2 Jun 2014 14:49:47 +0200 Subject: [PATCH] Updated application sources Change-Id: I3552bf836670676f1e0ef2bdd00e0b4d77ab61d5 Signed-off-by: Pawel Sierszen --- project/config.xml | 38 +- project/css/style.css | 238 +-- project/images/etc.png | Bin 1292 -> 6602 bytes project/images/img.png | Bin 1454 -> 4547 bytes project/images/music.png | Bin 1621 -> 4195 bytes project/images/video.png | Bin 2040 -> 4858 bytes project/index.html | 6 +- project/js/app.clipboard.js | 298 ++-- project/js/app.config.js | 50 +- project/js/app.helpers.js | 338 ++-- project/js/app.js | 582 +++---- project/js/app.model.js | 786 +++++---- project/js/app.systemIO.js | 523 +++--- project/js/app.ui.js | 2050 +++++++++++++----------- project/js/app.ui.templateManager.js | 311 ++-- project/js/app.ui.templateManager.modifiers.js | 86 +- project/js/main.js | 90 +- project/templates/fileRow.tpl | 6 +- project/templates/folderRow.tpl | 8 +- project/templates/levelUpRow.tpl | 2 +- project/templates/main.tpl | 163 +- 21 files changed, 3062 insertions(+), 2513 deletions(-) mode change 100755 => 100644 project/images/etc.png mode change 100755 => 100644 project/images/img.png mode change 100755 => 100644 project/images/music.png mode change 100755 => 100644 project/images/video.png diff --git a/project/config.xml b/project/config.xml index 45f5279..8f6f03c 100644 --- a/project/config.xml +++ b/project/config.xml @@ -1,13 +1,29 @@ - - - - File Manager - - - - - - - + + + + + + File Manager + + + + + + + + diff --git a/project/css/style.css b/project/css/style.css index 94917c0..4cec128 100644 --- a/project/css/style.css +++ b/project/css/style.css @@ -1,245 +1,257 @@ * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } body { - overflow: hidden; + overflow: hidden; + -webkit-user-select: none; } #fileList { - margin: 0; + margin: 0; } #mainTitle { - width: 210px; + width: 210px; } #fileList > li { - padding-top: 0.3rem; - padding-bottom: 0.3rem; - border-top: solid 1px #ddd; + padding-top: 0.3rem; + padding-bottom: 0.3rem; + border-top: solid 1px #ddd; } #fileList > li > span.nodename { - display: inline-block; - position: absolute; - line-height: 32px; - white-space: nowrap; - text-overflow: ellipsis; - width: 75%; - overflow: hidden; - margin-top: 5px; + display: inline-block; + position: absolute; + line-height: 32px; + white-space: pre; + text-overflow: ellipsis; + width: 75%; + overflow: hidden; + margin-top: 5px; + height: 32px; } #fileList > li.gradientBackground > span.nodename { - color: #fff !important; + color: #fff !important; } #fileList > li.file img { - width: 32px; - height: 32px; + width: 32px; + height: 32px; + padding-top: 5px; } #fileList > li.folder img { - margin-top: 0.1rem; + margin-top: 0.1rem; } #fileList > li.levelUp { - padding-left: 47px !important; - height: 32px; + padding-left: 47px !important; + height: 32px; } .selectAll { - padding-left: 6px; - display: inline-block; + padding-left: 6px; + display: inline-block; } .selectAll span.ui-btn-text { - padding-left: 2rem !important; - line-height: 40px; + line-height: 40px; } #navbar { - height: 16px; - padding: 2px 10px; - font-size: 14px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - background-color: rgba(255, 255, 255, 0.5); - border-top: solid 1px #DDD; - text-align: left; + height: 16px; + padding: 2px 10px; + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + background-color: rgba(255, 255, 255, 0.5); + border-top: solid 1px #DDD; + text-align: left; } .ui-pathDiv { - position: absolute; - top: 49px; - left: 0px; - right: 0px; - bottom: 0px; + position: absolute; + top: 49px; + left: 0px; + right: 0px; + bottom: 0px; } #pathDiv { - padding: 2px 0px 0px 5px; - border: 0px; + padding: 2px 0px 0px 5px; + border: 0px; } #pathDiv .ui-li-text-main { - font-size: 18px; + font-size: 18px; } #morePopup td.text a { - color:#FFF; - text-decoration:none; + color:#FFF; + text-decoration:none; } #morePopup td.text { - padding: 5px; + padding: 5px; } #morePopup { - margin: 2px; + margin: 2px; } #alertPopup .text { - text-align:left; - padding:20px; - min-height: 100px !important; + text-align:left; + padding:20px; + min-height: 100px !important; } #alertPopup .alertPopup-button { - padding-bottom: 10px; + padding-bottom: 10px; } #confirmPopup .text { - text-align:left; - padding:20px; - font-size: 18px; + text-align:left; + padding:20px; + font-size: 18px; } .ui-header.ui-bar-s .ui-btn.standard { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } #homeBtn, #levelUpBtn { - top:0px; + top:0px; } .ui-li-1line-bigicon1.ui-li.ui-li-static.ui-body-s.ui-li-has-thumb { - padding-left: 0.7rem; - padding-right: 0rem; + padding-left: 0.7rem; + padding-right: 0rem; } .my-ui-checkbox { - display: inline-block; - margin-top: 0rem; - margin-right: 0rem; - position: relative !important; - top: -0.7rem; - left: -1.5rem; + display: inline-block; + margin-top: 0rem; + margin-right: 0rem; + position: relative !important; + top: -0.7rem; + left: -1.5rem; } ul.ui-listview > li.ui-li-1line-bigicon1 img.ui-li-bigicon { - display: inline-block; - margin-top: 0rem; - margin-right: 0.7rem; - position: relative; - left: 5px; + display: inline-block; + margin-top: 0rem; + margin-right: 0.7rem; + position: relative; + left: 5px; } .ui-checkbox .ui-btn.ui-btn-icon-left .ui-btn-inner { - line-height: 1.1rem; - padding: 0 0 0 0rem; - width: 30px; + line-height: 1.1rem; + padding: 0 5 0 0rem; + width: 30px; } .ui-checkbox .ui-btn.ui-btn-icon-left .ui-btn-inner.ui-btn-hastxt { - width: 100%; + width: 100%; } .ui-btn-corner-all { - -webkit-border-radius: 0px; - bordert-radius: 0px; + -webkit-border-radius: 0px; + bordert-radius: 0px; } .ui-content.ui-scrollview-clip > div.ui-scrollview-view { - padding: 0px; + padding: 0px; } input.ui-input-text.new_folder { - width: 100%; - height: 50px; - padding: 0 0 0 .4em; + width: 100%; + height: 50px; + padding: 0 0 0 .4em; } .gradientBackground { - background: -webkit-linear-gradient(top, #5A99BA 0%, #205473 100%) !important; /* from tizen-white */ + background: -webkit-linear-gradient(top, #5A99BA 0%, #205473 100%) !important; /* from tizen-white */ } .hidden { - display: none !important; + display: none !important; } .vhidden { - visibility: hidden !important; + visibility: hidden !important; } .ui-tabbar a { - color: #999 !important; + color: #999 !important; } #newFolderName { - box-sizing: border-box; - width: 100%; + box-sizing: border-box; + width: 100%; } .ui-header.ui-bar-s > .ui-btn { - width: 2rem; + width: 2rem; } -/** workaround to prevent hiding footer caused by broken softkeyboardupdate event**/ -[data-role="footer"] { - display: block !important; +/** workaround to prevent hiding footer +caused by broken softkeyboardupdate event**/ +[data-role='footer'] { + display: block !important; } .ui-ctxpopup .horizontal a.ui-link { - display: block; + display: block; } .ui-footer .ui-btn-text { - text-transform: uppercase; + text-transform: uppercase; } -.ui-tabbar:not(.ui-tabbar-persist) a.ui-btn-active .ui-btn-text, .ui-tabbar:not(.ui-tabbar-persist) .ui-btn-show-style .ui-btn-text { - border:none; +.ui-tabbar:not(.ui-tabbar-persist) a.ui-btn-active .ui-btn-text, +.ui-tabbar:not(.ui-tabbar-persist) .ui-btn-show-style .ui-btn-text { + border:none; } #overlay { - background-color: rgba(0, 0, 0, 0.5); - width: 100%; - height: 100%; - position: absolute; - left: 0px; - top: 0px; - z-index: 9000; - display: none; + background-color: rgba(0, 0, 0, 0.5); + width: 100%; + height: 100%; + position: absolute; + left: 0px; + top: 0px; + z-index: 9000; + display: none; } #infoPopup { - background-color: #fff; - height: 130px; - padding: 15px 0px; - position: absolute; - text-align: center; - box-shadow: 0px 0px 20px #444; - border-radius: 5px; + background-color: #fff; + height: 130px; + padding: 15px 0px; + position: absolute; + text-align: center; + box-shadow: 0px 0px 20px #444; + border-radius: 5px; } #infoPopup img { - -webkit-animation: rotation 2s infinite linear; + -webkit-animation: rotation 2s infinite linear; } @-webkit-keyframes rotation { - from {-webkit-transform: rotate(0deg);} - to {-webkit-transform: rotate(359deg);} -} \ No newline at end of file + from {-webkit-transform: rotate(0deg);} + to {-webkit-transform: rotate(359deg);} +} + +.white-space-pre { + white-space: pre !important; +} + +#alertPopup p:first-letter { + text-transform: uppercase; +} diff --git a/project/images/etc.png b/project/images/etc.png old mode 100755 new mode 100644 index 26748d83cfa4fee28a125d4dcdb01a77f901102d..4b757e29bb1316d9eb544239acc53430dc771ea3 GIT binary patch literal 6602 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 literal 1454 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 literal 1621 zcmaKrdr%Ws6vh{bVFQ=CP}Gp1CW=B(3JgLUCO!y6g<1?TsHCD!qA00U2UJ9~BSJ-u zC_)-07y)Z)BZh~%6-FD0kA+ej!AKND$wW~RMSQg>6rne)IQ^@4HYdOP-S3`z_MX`T z!uUlVZVWdBK|Ep?$B5wn9LEoJf$`0$=N$;*Tp?T{7L1IHKm`sQvy6esfDs1FgkvTG zGeCyXgyCc)mk5VQkbbB@Ag3nGFv`&Hfd3gEcfrii2BQJf6X3%sq)6%{D?v5{l1U($ z^uTBtTZKR}X~Th%bdo2I)(_wA!vpJt%%y~WR6YU}2~0m$8@v;EA$k~Lwy{XSEBepW z!SI2i7C6#EhTG+6M($`0IMBc)C2-`VBXqbLhdLTV4(K04cpHw}gJ#$isKdyia9|`A zEkKq0qtZ}HD3=mt09pgkh$vAaN}LpxD1p)d z^a@8Ri5_SaK%)l)0km46$v~wNG(&;rY8)&_5kwEP9E24|iJ~JcC4f4#X<^qSs8j>= z5{gI<401F#1I_gf9tnppP_|VRzYMvyBPGSGQkl&vvkeBD%8b)naGEVlMa9ke>Y+L@ zFR!oj;*g7qzl~WtuTBftYP@un8xtjXwHS^ES%`&dtFhqOAzSQ0(XlAyo`00;MiM@G~ zP7^f19abKEd$6uMh-N9&m1}}?=fkh6F*YVjykm8r#gh5ySH4X)w(x}aJ<-XaHh1E| zhjILF)AFLWgc(i7gu-vEC{-hVp`bq%y%>HbfP3F)VQoDR^fwvyU)zwX~c^?N^s*YGC7UVU9iSLHQ@1%LldbWMlVika)9)BDG* zjJ{vAC*9gh;T&%- z%qLiSRi~CUrUw|!^{+eJW+9Tu)Dh+B+q{i~fC}CfE)sLr_w0yBY|m=lSy_LC9atgk z(cw8+N`C(KtjN;wlV46}xkXa6tt}B)@0I}ZbH(9_f#QBw@N5txom#V z#&s2szc8QiXGX{QpNUR_}rkcNY@4q(qs#pL3 diff --git a/project/images/video.png b/project/images/video.png old mode 100755 new mode 100644 index 97864398f702b60a7ca2039beb3c39bee5edcc8a..ca96031f29f106cd55a869973338d6b17ce71ff4 GIT binary patch literal 4858 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 delta 2027 zcmVHvfX)Kkd1rQUV(?+T?g;Z3Di`K?;9f_rB zDP0kytO(O+)Sf8Vtlr)&xrz53ai98T@ksi>K|{VzpN`GT&wuZH=iGbkXR{=q&(p0m zZu@^SP%>09R5DaDR5D~-4}3B-S}uuJ38DuPYZ2=Z1BmAlPa(d7c%UKEddh>Z2G;@Z zKE!IoFd`vNYJLduFnD{RhJ3%Vz7ZPjMCgSg^8r$24+$gq7>p$~Tcz1Y=4a*mMDoez z57z81%9Mi<6MuREz#tS68n{-3nbnfy-v^ievJ31g04IbtGcRw5&w$@Gx^&^c1=W zs?bHMg*xhu`lBOOzh*wtkhM2oZ`3f$8i6{P(JUA4?jQw!hHFSSx7XTniO+lG_;Jj1 zxXpALZB8ptnEj%x1^TmdW5)EzZ4#m>&<0q{gkG3s)Wwz2i=-$J%`7h_zpiS^M*- zJhN{>6=3huug&~9a2e+DI>*6RJ3Kn`C&v(8hYPaqIt-274dq#5){s-(=kT1X`r%k` z=+!U{)0sHAv6qCISfC3TJ)SAvG&d( z!LPdh{Vs@&Sm4j>xB7XBD$DC&j|XR=sxvL3g{x^6oa6O!kw_%L|H6Z>!Zqj64enk!n0qF59x%#= zo-1G$_C6$umI<tY4F)Hr>a36G1>O3lqFaveIK7aZMqJSh*o0A+)LD4M9Pa^&WmAU9mo4KG7 zO6#fiysJp2q>KgND0urC{J%pKJkJFLlK{r7GnN$q3+~Xg22hzGhn$2dREf)^yts)_ zJit{XhGmSW-0^~Q2SOAo>lAJGlK1!t^sktVS1~V%nsk9_ijoZE7HkOB zsfM;d-*+d21^@M~S*QohkNR>u6Ov?BuiJ+lK7XMS9Nt{eXE~Tyb!8hCCf5Uz-0_)Q-w(K{LF zUApx*%|_FAZKC%>WR7V+jZhe!dAU#atp@ZxT<5oirZxWu@ZSRePtBKK;YG!O9Qflt zxvvet>ha+CCB#2NBq>Af*|mg1bs_)VUYmk8GZBD+J>X387+qG^9nrGpO@Hy3iTpr5p%$YB)`ff5qZFlPcjk6} zIX)AgWDe`7N^i}Lu66ek%zsSN{Db+=BeZJ%vgTienOVd!s21W+<+L%kktE5VBljof z-L_%Ga_&abNE=h;;-GPGWR20@iS+|pf+UU*RR)rjJ_I9Q_mOH+bh#Gs*A3*z!%eO)p?7J#%(UEP#D)uaHAHKmfsYU+=wOEn@F2^Q{kz9YL=rH~^!BtDE4C{X|a002ov JPDHLkV1nyd+;;!~ diff --git a/project/index.html b/project/index.html index 9366eb2..e50998a 100644 --- a/project/index.html +++ b/project/index.html @@ -5,9 +5,9 @@ File Manager - - - + + + diff --git a/project/js/app.clipboard.js b/project/js/app.clipboard.js index cee9925..aa5d175 100644 --- a/project/js/app.clipboard.js +++ b/project/js/app.clipboard.js @@ -1,3 +1,19 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true*/ /*global $*/ @@ -5,143 +21,153 @@ * @class Config */ function Clipboard() { - 'use strict'; - this.mode = this.INACTIVE_MODE; + 'use strict'; + this.mode = this.INACTIVE_MODE; } (function () { // strict mode wrapper - 'use strict'; - Clipboard.prototype = { - /** - * Clipboard mode for copying - */ - COPY_MODE_ID: 0, - - /** - * Clipboard mode for moving - */ - MOVE_MODE_ID: 1, - - /** - * Clipbboard inactive mode - */ - INACTIVE_MODE: -1, - - /** - * Clipboard data - */ - data: [], - - /** - * Clipboard mode: [copy | move | inactive] - */ - mode: undefined, - - /** - * Returns all paths in clipboard - * @returns {array} - */ - get: function Clipboard_get() { - return this.data; - }, - - /** - * Add new path to clipboard - * @param {array} paths array of full paths - * @returns {number} current length of clipboard objects - */ - add: function Clipboard_add(paths) { - var len = paths.length, - i; - - // clear clipboard - this.clear(); - for (i = 0; i < len; i += 1) { - if (this.has(paths[i]) === false) { - this.data.push(paths[i]); - } - } - - return this.data.length; - }, - - /** - * Remove specified path is already in clipboard - * @param {string} path full path - * @returns {number} current length of clipboard objects - */ - remove: function Clipboard_remove(path) { - var index = $.inArray(path, this.data); - var length; - if (index >= 0) { - this.data.splice(index, 1); - length = this.data.length; - if (length === 0) { - this.mode = this.INACTIVE_MODE; - } - } - return length; - }, - - /** - * Remove specified path and all children paths if already in clipboard - * @param {string} path full path - * @returns {number} current length of clipboard objects - */ - removeRecursively: function Clipboard_removeRecursively(path) { - var childPattern = new RegExp(path), - index = this.data.length; - while (index--) { - if(childPattern.test(this.data[index])) { - this.data.splice(index, 1); - } - } - return this.data.length; - }, - - /** - * Checks if specified path is already in clipboard - * @param {string} path full path - * @returns {boolean} - */ - has: function Clipboard_has(path) { - return $.inArray(path, this.data) === -1 ? false : true; - }, - - /** - * Clears all clipboard data and resets clipboard mode - */ - clear: function Clipboard_clear() { - this.data = []; - this.mode = this.INACTIVE_MODE; - }, - - /** - * Sets clipboard mode - * @param {number} mode - * @returns {boolean} - */ - setMode: function Clipboard_setMode(mode) { - if ($.inArray(mode, [this.MOVE_MODE_ID, this.COPY_MODE_ID]) === false) { - console.error('Incorrect clipboard mode'); - return false; - } - this.mode = mode; - return true; - }, - - /** - * @returns {number} mode Clipboard mode - */ - getMode: function Clipboard_getMode() { - return this.mode; - }, - - /** - * @returns {boolean} - */ - isEmpty: function Clipboard_isEmpty() { - return this.data.length === 0; - } - }; + 'use strict'; + Clipboard.prototype = { + /** + * Clipboard mode for copying + */ + COPY_MODE_ID: 0, + + /** + * Clipboard mode for moving + */ + MOVE_MODE_ID: 1, + + /** + * Clipbboard inactive mode + */ + INACTIVE_MODE: -1, + + /** + * Clipboard data + */ + data: [], + + /** + * Clipboard mode: [copy | move | inactive] + */ + mode: undefined, + + /** + * Returns all paths in clipboard + * @returns {array} + */ + get: function Clipboard_get() { + return this.data; + }, + + /** + * Add new path to clipboard + * @param {array} paths array of full paths + * @returns {number} current length of clipboard objects + */ + add: function Clipboard_add(paths) { + var len = paths.length, + i; + + // clear clipboard + this.clear(); + for (i = 0; i < len; i += 1) { + if (this.has(paths[i]) === false) { + this.data.push(paths[i]); + } + } + + return this.data.length; + }, + + /** + * Remove specified path is already in clipboard + * @param {string} path full path + * @returns {number} current length of clipboard objects + */ + remove: function Clipboard_remove(path) { + var index = $.inArray(path, this.data), + length; + if (index >= 0) { + this.data.splice(index, 1); + length = this.data.length; + if (length === 0) { + this.mode = this.INACTIVE_MODE; + } + } + return length; + }, + + /** + * Remove specified path and all children paths if already in clipboard + * @param {string} path full path + * @returns {number} current length of clipboard objects + */ + removeRecursively: function Clipboard_removeRecursively(path) { + var escapeRegExp = function (str) { + return str + .replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + childPattern = new RegExp(escapeRegExp(path)), + index = this.data.length - 1; + while (index >= 0) { + if (childPattern.test(this.data[index])) { + this.data.splice(index, 1); + } + index -= 1; + } + return this.data.length; + }, + + /** + * Checks if specified path is already in clipboard + * @param {string} path full path + * @returns {boolean} + */ + has: function Clipboard_has(path) { + return $.inArray(path, this.data) === -1 ? false : true; + }, + + /** + * Clears all clipboard data and resets clipboard mode + */ + clear: function Clipboard_clear() { + this.data = []; + this.mode = this.INACTIVE_MODE; + }, + + /** + * Sets clipboard mode + * @param {number} mode + * @returns {boolean} + */ + setMode: function Clipboard_setMode(mode) { + if ( + $.inArray( + mode, + [this.MOVE_MODE_ID, this.COPY_MODE_ID] + ) === false + ) { + console.error('Incorrect clipboard mode'); + return false; + } + this.mode = mode; + return true; + }, + + /** + * @returns {number} mode Clipboard mode + */ + getMode: function Clipboard_getMode() { + return this.mode; + }, + + /** + * @returns {boolean} + */ + isEmpty: function Clipboard_isEmpty() { + return this.data.length === 0; + } + }; }()); diff --git a/project/js/app.config.js b/project/js/app.config.js index e0332c3..a7681e0 100644 --- a/project/js/app.config.js +++ b/project/js/app.config.js @@ -1,28 +1,44 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** * @class Config */ function Config() { - 'use strict'; + 'use strict'; } (function () { // strict mode wrapper - 'use strict'; - Config.prototype = { + 'use strict'; + Config.prototype = { - properties: { - 'templateDir': 'templates', - 'templateExtension': '.tpl' - }, + properties: { + 'templateDir': 'templates', + 'templateExtension': '.tpl' + }, - /** - * Returns config value - */ - get: function (value, defaultValue) { + /** + * Returns config value + */ + get: function (value, defaultValue) { - if (this.properties.hasOwnProperty(value)) { - return this.properties[value]; - } - return defaultValue; - } - }; + if (this.properties.hasOwnProperty(value)) { + return this.properties[value]; + } + return defaultValue; + } + }; }()); diff --git a/project/js/app.helpers.js b/project/js/app.helpers.js index 12cd314..86c8f5e 100644 --- a/project/js/app.helpers.js +++ b/project/js/app.helpers.js @@ -1,3 +1,19 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true*/ /*global $, jQuery */ @@ -5,158 +21,178 @@ * @class Helpers */ function Helpers() { - 'use strict'; + 'use strict'; } (function () { // strict mode wrapper - 'use strict'; - Helpers.prototype = { - - extensions: { - '.bmp': {mime:'image/*', icon:'img.png'}, - '.gif': {mime:'image/*', icon:'img.png'}, - '.jpeg': {mime:'image/*', icon:'img.png'}, - '.jpg': {mime:'image/*', icon:'img.png'}, - '.png': {mime:'image/*', icon:'img.png'}, - '.tiff': {mime:'image/*', icon:'img.png'}, - '.3ga': {mime:'audio/*', icon:'music.png'}, - '.aac': {mime:'audio/*', icon:'music.png'}, - '.ac3': {mime:'audio/*', icon:'music.png'}, - '.amr': {mime:'audio/*', icon:'music.png'}, - '.awb': {mime:'audio/*', icon:'music.png'}, - '.m4a': {mime:'audio/*', icon:'music.png'}, - '.m4p': {mime:'audio/*', icon:'music.png'}, - '.m4r': {mime:'audio/*', icon:'music.png'}, - '.mp3': {mime:'audio/*', icon:'music.png'}, - '.ogg': {mime:'audio/*', icon:'music.png'}, - '.wav': {mime:'audio/*', icon:'music.png'}, - '.wma': {mime:'audio/*', icon:'music.png'}, - '.3gp': {mime:'video/*', icon:'video.png'}, - '.avc': {mime:'video/*', icon:'video.png'}, - '.avi': {mime:'video/*', icon:'video.png'}, - '.m4v': {mime:'video/*', icon:'video.png'}, - '.mkv': {mime:'video/*', icon:'video.png'}, - '.mov': {mime:'video/*', icon:'video.png'}, - '.mp4': {mime:'video/*', icon:'video.png'}, - '.mpeg': {mime:'video/*', icon:'video.png'}, - '.mpg': {mime:'video/*', icon:'video.png'}, - '.ogv': {mime:'video/*', icon:'video.png'}, - '.vc1': {mime:'video/*', icon:'video.png'}, - '.wmv': {mime:'video/*', icon:'video.png'}, - '.doc': {mime:'', icon:'text.png'}, - '.docx': {mime:'', icon:'text.png'}, - '.odt': {mime:'', icon:'text.png'}, - '.ods': {mime:'', icon:'text.png'}, - '.txt': {mime:'', icon:'text.png'}, - '.xls': {mime:'', icon:'text.png'}, - '.xlsx': {mime:'', icon:'text.png'}, - '.vcard': {mime:'text/vcard', icon:'text.png'}, - '.vcf': {mime:'text/vcard', icon:'text.png'}, - '.icalendar': {mime:'text/calendar', icon:'text.png'}, - '.ical': {mime:'text/calendar', icon:'text.png'}, - '.ics': {mime:'text/calendar', icon:'text.png'}, - '.ifb': {mime:'text/calendar', icon:'text.png'}, - '.pdf': {mime:'', icon:'pdf.png'}, - '.odp': {mime:'', icon:'ppt.png'}, - '.ppt': {mime:'', icon:'ppt.png'}, - '.wgt': {mime:'application/widget', icon:'etc.png'} - }, - - /** - * Capitalise the first letter - * - * @param {string} text - * @returns {string} - */ - UCFirst: function Helpers_UCFirst(text) { - return text.charAt(0).toUpperCase() + text.slice(1); - }, - - /** - * @param {string} fileName - * @returns {string} file name without extension - */ - getFileName: function Helpers_getFileName(fileName) { - var fileNameLen = fileName.indexOf('.'); - if (fileNameLen !== -1) { - fileName = fileName.slice(0, fileNameLen); - } - return fileName; - }, - - /** - * @param {string} fileName - * @returns {string} extension for specified file name - */ - getFileExtension: function Helpers_getFileExtension(fileName) { - var splittedFileName = fileName.split('.'), - ext = ''; - - if (splittedFileName.length > 1) { - ext = '.' + splittedFileName.pop(); - } - return ext; - }, - - /** - * Return icon filename for the given extension. - * For example, for '.mp3' returns 'music.png' - * - * @param {string} ext - * @return {string} - */ - resolveFileIcon: function Helpers_resolveFileIcon(ext) { - ext = ext.toLowerCase(); - var info = this.extensions[ext]; - return info ? info.icon : 'etc.png'; - }, - - /** - * Resolve file extension to MIME type - * - * @param {string} ext File extension - * @returns {string} - */ - resolveMimeType: function Helpers_resolveMimeType(ext) { - ext = ext.toLowerCase(); - var info = this.extensions[ext]; - return info ? info.mime : ''; - }, - - /** - * Returns thumbnail URI for specified file - * @param {string} fileName - * @param {File} node - * @returns {string} - */ - getThumbnailURI: function Helpers_getThumbnailURI(fileName, node) { - var ext = this.getFileExtension(fileName); - - if (!node.thumbnailURIs) { - return 'images/' + this.resolveFileIcon(ext); - } - - if (node.thumbnailURIs[0] && $.inArray(ext, ['.mp4', '.jpg', '.png', '.gif'])) { - return node.thumbnailURIs[0]; - } - - return 'images/etc.png'; - }, - - /** - * File name automatic number increase for copy files - */ - getCopyFileName: function (sourceName, filesList) { - var ext = this.getFileExtension(sourceName), - fileName = this.getFileName(sourceName), - copyFileName = sourceName, - i = 1; - - while ($.inArray(copyFileName, filesList) !== -1) { - i += 1; - copyFileName = fileName + '(' + i + ')' + ext; - } - return copyFileName; - } - }; + 'use strict'; + Helpers.prototype = { + + extensions: { + '.bmp': 'img.png', + '.gif': 'img.png', + '.jpeg': 'img.png', + '.jpg': 'img.png', + '.png': 'img.png', + '.tiff': 'img.png', + '.3ga': 'music.png', + '.aac': 'music.png', + '.ac3': 'music.png', + '.amr': 'music.png', + '.awb': 'music.png', + '.m4a': 'music.png', + '.m4p': 'music.png', + '.m4r': 'music.png', + '.mp3': 'music.png', + '.ogg': 'music.png', + '.wav': 'music.png', + '.wma': 'music.png', + '.3gp': 'video.png', + '.avc': 'video.png', + '.avi': 'video.png', + '.m4v': 'video.png', + '.mkv': 'video.png', + '.mov': 'video.png', + '.mp4': 'video.png', + '.mpeg': 'video.png', + '.mpg': 'video.png', + '.ogv': 'video.png', + '.vc1': 'video.png', + '.wmv': 'video.png', + '.doc': 'text.png', + '.docx': 'text.png', + '.odt': 'text.png', + '.ods': 'text.png', + '.txt': 'text.png', + '.xls': 'text.png', + '.xlsx': 'text.png', + '.vcard': 'text.png', + '.vcf': 'text.png', + '.icalendar': 'text.png', + '.ical': 'text.png', + '.ics': 'text.png', + '.ifb': 'text.png', + '.pdf': 'pdf.png', + '.odp': 'ppt.png', + '.ppt': 'ppt.png', + '.wgt': 'etc.png' + }, + + /** + * Capitalise the first letter + * + * @param {string} text + * @returns {string} + */ + UCFirst: function Helpers_UCFirst(text) { + return text.charAt(0).toUpperCase() + text.slice(1); + }, + + /** + * @param {string} fileName + * @returns {string} file name without extension + */ + getFileName: function Helpers_getFileName(fileName) { + var fileNameLen = fileName.lastIndexOf('.'); + if (fileNameLen !== -1) { + fileName = fileName.slice(0, fileNameLen); + } + return fileName; + }, + + /** + * @param {string} fileName + * @returns {string} extension for specified file name + */ + getFileExtension: function Helpers_getFileExtension(fileName) { + var splittedFileName = fileName.split('.'), + ext = ''; + + if (splittedFileName.length > 1) { + ext = '.' + splittedFileName.pop(); + } + return ext; + }, + + /** + * Return icon filename for the given extension. + * For example, for '.mp3' returns 'music.png' + * + * @param {string} ext + * @return {string} + */ + resolveFileIcon: function Helpers_resolveFileIcon(ext) { + ext = ext.toLowerCase(); + return this.extensions[ext] || 'etc.png'; + }, + + /** + * Returns thumbnail URI for specified file + * @param {string} fileName + * @param {File} node + * @returns {string} + */ + getThumbnailURI: function Helpers_getThumbnailURI(fileName, node) { + var ext = this.getFileExtension(fileName); + + if (!node.thumbnailURIs) { + return 'images/' + this.resolveFileIcon(ext); + } + + if ( + node.thumbnailURIs[0] && + $.inArray(ext, ['.mp4', '.jpg', '.png', '.gif']) + ) { + return node.thumbnailURIs[0]; + } + + return 'images/etc.png'; + }, + + /** + * File name automatic number increase for copy files + */ + getCopyFileName: function Helpers_getCopyFileName( + sourceName, + filesList + ) { + var i = 1, copyFileName = sourceName, + filesNames = filesList.map(function (element) { + return element.name; + }), + index = filesNames.indexOf(copyFileName), + ext = this.getFileExtension(sourceName); + + while (index !== -1) { + if (filesList[index].isDirectory) { + copyFileName = sourceName + '(' + i + ')'; + } else { + copyFileName = this.getFileName( + sourceName + ) + '(' + i + ')' + ext; + } + i += 1; + index = filesNames.indexOf(copyFileName); + } + + return copyFileName; + }, + + /** + * Fixes invalid URI returned by API's File::toURI() method. + * See issue https://bugs.tizendev.org/jira/browse/N_SE-54639 + */ + fixURI: function Helpers_fixURI(invaliduri) { + var scheme, address, k; + invaliduri = invaliduri.split('://'); + scheme = invaliduri[0]; + invaliduri.shift(); + address = invaliduri.join('://').split('/'); + for (k = address.length - 1; k >= 0; k -= 1) { + address[k] = encodeURIComponent(address[k]); + } + return scheme + '://' + address.join('/'); + } + + }; }()); diff --git a/project/js/app.js b/project/js/app.js index 297023b..296356f 100644 --- a/project/js/app.js +++ b/project/js/app.js @@ -1,278 +1,318 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true*/ /*global tizen, $, app, Ui, Model, Helpers, Config, Clipboard*/ var App = null; (function () { // strict mode wrapper - 'use strict'; - - /** - * Creates a new application object - * - * @class Application - * @constructor - */ - App = function App() { - }; - - App.prototype = { - /** - * @type Array - */ - requires: [ - 'js/app.config.js', - 'js/app.model.js', - 'js/app.ui.js', - 'js/app.ui.templateManager.js', - 'js/app.ui.templateManager.modifiers.js', - 'js/app.systemIO.js', - 'js/app.helpers.js', - 'js/app.clipboard.js' - ], - - /** - * @type Model - */ - model: null, - - /** - * @type Ui - */ - ui: null, - - /** - * @type Config - */ - config: null, - - /** - * @type SystemIO - */ - systemIO: null, - - /** - * @type Helpers - */ - helpers: null, - - /** - * @type {string} - */ - currentPath: 'root', - - /** - * - */ - currentDirHandle: null, - - /** - * @type {Clipboard} - */ - clipboard: null, - - /** - * Initialization - */ - init: function App_init() { - this.config = new Config(); - this.model = new Model(); - this.ui = new Ui(); - this.helpers = new Helpers(); - this.clipboard = new Clipboard(); - - this.initUi(); - }, - - /** - * UI initialization - */ - initUi: function App_initUi() { - this.ui.init(this.model.getInternalStorages()); - }, - - /** - * Displays media storages - */ - displayStorages: function App_displayStorages() { - this.currentPath = ''; - if (!this.ui.editMode) { - this.ui.scrollContentTo(0); - } - this.ui.displayStorages(this.model.getInternalStorages()); - }, - - /** - * Displays specified folder - * @param {string} path - * @param {bool} [refresh=false] - */ - displayFolder: function App_displayFolder(path, refresh) { - var self = this; - - refresh = refresh || false; - - // get folder data and push into rendering method - this.model.getFolderData(path, function (dir, nodes) { - // on success - - // update current path - self.currentPath = path; - - // update current dir handle - self.currentDirHandle = dir; - - // display folder UI - if (refresh === undefined) { - self.ui.scrollContentTo(0); - } - self.ui.displayFolder(path, nodes, refresh); - }); - }, - - /** - * Opens specified file - * @params {string} uri File URI - */ - openFile: function App_openFile(uri, fullUri) { - var ext = this.helpers.getFileExtension(uri), - mime = this.helpers.resolveMimeType(ext); - - if (mime !== '') { - this.model.openFile(fullUri, mime); - } else { - console.error('Unsupported mime type for extension ' + ext); - } - }, - - /** - * Displays parent location - */ - goLevelUp: function App_goLevelUp() { - // split current path and get proper path for parent location - var newPath = this.currentPath.split('/').slice(0, -1).join('/'); - - if (newPath !== '') { - this.displayFolder(newPath); - } else { - this.displayStorages(); - } - }, - - /** - * creates new dir in currently viewed dir - * @param {string} dirName - * @return {boolean} return status - */ - createDir: function App_createDir(dirName, callback) { - var status = true; - if (this.currentDirPath !== '') { - try { - this.currentDirHandle.createDirectory(dirName); - } catch (e) { - status = false; - app.ui.alertPopup(e.message, callback); - } - this.refreshCurrentPage(); - } else { - status = false; - app.ui.alertPopup("You can't create new nodes in the main view"); - } - return status; - }, - - /** - * Triggers refresh current page - */ - refreshCurrentPage: function App_refreshCurrentPage(refresh) { - refresh = refresh || false; - if (this.currentPath === 'root') { - return; - } - if (this.currentPath !== '') { - app.model.isStorageExists(this.currentPath, - app.displayFolder.bind(app, app.model.currentPath, refresh), - function () { - $.mobile.popup.active && $.mobile.popup.active.close(); - app.displayStorages(); - setTimeout( - function(){ - app.ui.alertPopup( - 'Path "' + app.model.currentPath + '" does no longer exist' - ); - }, - 200 - ); - }); - } else { - this.displayStorages(); - } - }, - - /** - * Deletes nodes with specified paths - * @param {string[]} nodes nodePaths - */ - deleteNodes: function App_deleteNodes(nodes) { - this.model.deleteNodes(nodes, this.currentDirHandle, this.ui.removeNodeFromList.bind(this.ui)); - }, - - /** - * @param {string[]} paths filepaths - * @param {number} mode clipboard mode - */ - saveToClipboard: function App_saveToClipboard(paths, mode) { - var clipboardLength = this.clipboard.add(paths); - - if (clipboardLength > 0) { - this.clipboard.setMode(mode); - app.ui.alertPopup('Data saved in clipboard'); - this.ui.clearTabbars(); - } else { - app.ui.alertPopup('Error occured. Data has not been saved in clipboard'); - } - - this.ui.refreshPasteActionBtn(this.clipboard.isEmpty()); - }, - - /** - * Paste nodes from clipboard to current dir - */ - pasteClipboard: function App_pasteClipboard() { - var clipboardData = this.clipboard.get(); - - if (clipboardData.length === 0) { - app.ui.alertPopup('Clipboard is empty'); - return false; - } - - if (this.clipboard.getMode() === this.clipboard.COPY_MODE_ID) { - this.model.copyNodes(this.currentDirHandle, clipboardData, this.currentPath, this.onPasteClipboardSuccess.bind(this)); - } else { - this.model.moveNodes(this.currentDirHandle, clipboardData, this.currentPath, this.onPasteClipboardSuccess.bind(this)); - } - - this.ui.refreshPasteActionBtn(this.clipboard.isEmpty()); - - return true; - }, - - emptyClipboard: function App_emptyClipboard() { - return this.clipboard.get().length === 0; - }, - - /** - * Handler for paste clipboard success - */ - onPasteClipboardSuccess: function App_onPasteClipboardSuccess() { - this.clipboard.clear(); - this.refreshCurrentPage(); - }, - - /** - * App exit - */ - exit: function App_exit() { - tizen.application.getCurrentApplication().exit(); - } - }; + 'use strict'; + + /** + * Creates a new application object + * + * @class Application + * @constructor + */ + App = function App() { + }; + + App.prototype = { + /** + * @type Array + */ + requires: [ + 'js/app.config.js', + 'js/app.model.js', + 'js/app.ui.js', + 'js/app.ui.templateManager.js', + 'js/app.ui.templateManager.modifiers.js', + 'js/app.systemIO.js', + 'js/app.helpers.js', + 'js/app.clipboard.js' + ], + + /** + * @type Model + */ + model: null, + + /** + * @type Ui + */ + ui: null, + + /** + * @type Config + */ + config: null, + + /** + * @type SystemIO + */ + systemIO: null, + + /** + * @type Helpers + */ + helpers: null, + + /** + * @type {string} + */ + currentPath: 'root', + + /** + * + */ + currentDirHandle: null, + + /** + * @type {Clipboard} + */ + clipboard: null, + + /** + * Initialization + */ + init: function App_init() { + this.config = new Config(); + this.model = new Model(); + this.ui = new Ui(); + this.helpers = new Helpers(); + this.clipboard = new Clipboard(); + + this.initUi(); + }, + + /** + * UI initialization + */ + initUi: function App_initUi() { + this.ui.init(this.model.getInternalStorages()); + }, + + /** + * Displays media storages + */ + displayStorages: function App_displayStorages() { + this.currentPath = ''; + if (!this.ui.editMode) { + this.ui.scrollContentTo(0); + } + this.ui.displayStorages(this.model.getInternalStorages()); + }, + + /** + * Displays specified folder + * @param {string} path + * @param {bool} [refresh=false] + */ + displayFolder: function App_displayFolder(path, refresh) { + var self = this; + + refresh = refresh || false; + + // get folder data and push into rendering method + this.model.getFolderData(path, function (dir, nodes) { + // on success + + // update current path + self.currentPath = path; + + // update current dir handle + self.currentDirHandle = dir; + + // display folder UI + if (refresh === undefined) { + self.ui.scrollContentTo(0); + } + self.ui.displayFolder(path, nodes, refresh); + }); + }, + + /** + * Opens specified file + * @params {string} uri File URI + */ + openFile: function App_openFile(uri, fullUri) { + tizen.filesystem.resolve( + fullUri, + function (file) { + this.model.openFile(fullUri); + }.bind(this), + function () { + // file doesn't exists + this.ui.alertPopup('File does no longer exist', + this.refreshCurrentPage.bind(this, true)); + }.bind(this) + ); + }, + + /** + * Displays parent location + */ + goLevelUp: function App_goLevelUp() { + // split current path and get proper path for parent location + var newPath = this.currentPath.split('/').slice(0, -1).join('/'); + + if (newPath !== '') { + this.displayFolder(newPath); + } else { + this.displayStorages(); + } + }, + + /** + * creates new dir in currently viewed dir + * @param {string} dirName + * @return {boolean} return status + */ + createDir: function App_createDir(dirName, callback) { + var status = true; + if (this.currentDirPath !== '') { + try { + this.currentDirHandle.createDirectory(dirName); + } catch (e) { + status = false; + app.ui.alertPopup(e.message, callback); + } + this.refreshCurrentPage(); + } else { + status = false; + app.ui.alertPopup( + 'You can\'t create new nodes in the main view' + ); + } + return status; + }, + + /** + * Triggers refresh current page + */ + refreshCurrentPage: function App_refreshCurrentPage(refresh) { + refresh = refresh || false; + if (this.currentPath === 'root') { + this.ui.toggleInfoPopup(); + return; + } + if (this.currentPath !== '') { + app.model.isStorageExists(this.currentPath, + app.displayFolder.bind(app, app.model.currentPath, refresh), + function () { + app.ui.popupHardClose(); + app.displayStorages(); + setTimeout( + function () { + app.ui.alertPopup( + 'Path "' + + app.model.currentPath + + '" does no longer exist' + ); + }, + 200 + ); + }); + } else { + this.displayStorages(); + } + }, + + /** + * Deletes nodes with specified paths + * @param {string[]} nodes nodePaths + */ + deleteNodes: function App_deleteNodes(nodes) { + this.model.deleteNodes( + nodes, + this.currentDirHandle, + this.ui.removeNodeFromList.bind(this.ui) + ); + }, + + /** + * @param {string[]} paths filepaths + * @param {number} mode clipboard mode + */ + saveToClipboard: function App_saveToClipboard(paths, mode) { + var clipboardLength = this.clipboard.add(paths); + + if (clipboardLength > 0) { + this.clipboard.setMode(mode); + app.ui.alertPopup('Data saved in clipboard'); + this.ui.clearTabbars(); + } else { + app.ui.alertPopup( + 'Error occured. Data has not been saved in clipboard' + ); + } + + this.ui.refreshPasteActionBtn(this.clipboard.isEmpty()); + }, + + /** + * Paste nodes from clipboard to current dir + */ + pasteClipboard: function App_pasteClipboard() { + var clipboardData = this.clipboard.get(); + + if (clipboardData.length === 0) { + app.ui.alertPopup('Clipboard is empty'); + return false; + } + + if (this.clipboard.getMode() === this.clipboard.COPY_MODE_ID) { + this.model.copyNodes( + this.currentDirHandle, + clipboardData, + this.currentPath, + this.onPasteClipboardSuccess.bind(this) + ); + } else { + this.model.moveNodes( + this.currentDirHandle, + clipboardData, + this.currentPath, + this.onPasteClipboardSuccess.bind(this) + ); + } + + this.ui.refreshPasteActionBtn(this.clipboard.isEmpty()); + + return true; + }, + + emptyClipboard: function App_emptyClipboard() { + return this.clipboard.get().length === 0; + }, + + /** + * Handler for paste clipboard success + */ + onPasteClipboardSuccess: function App_onPasteClipboardSuccess() { + this.clipboard.clear(); + this.refreshCurrentPage(); + }, + + /** + * App exit + */ + exit: function App_exit() { + tizen.application.getCurrentApplication().exit(); + } + }; }()); diff --git a/project/js/app.model.js b/project/js/app.model.js index 7b2b4a1..6d179fe 100644 --- a/project/js/app.model.js +++ b/project/js/app.model.js @@ -1,3 +1,19 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true*/ /*global tizen, SystemIO, $, app */ @@ -5,348 +21,436 @@ * @class Model */ function Model() { - 'use strict'; - this.init(); + 'use strict'; + this.init(); } (function () { // strict mode wrapper - 'use strict'; - Model.prototype = { - - /** - * file open unlock flag - * @type {boolean} - */ - openFileUnLocked: true, - - /** - * @type SystemIO - */ - systemIO: null, - - /** - * @type Array - */ - storages: [{label: 'root', type: 'INTERNAL'}], - - /** - * @type String - */ - currentPath: '', - - /** - * API module initialisation - */ - init: function Model_init() { - this.systemIO = new SystemIO(); - }, - - /** - * @returns {FileSystemStorage[]} storages - */ - getInternalStorages: function Model_getInternalStorages() { - return this.storages; - }, - - /** - * Saves storages - * @param {function} onSuccess callback - */ - loadInternalStorages: function Model_loadInternalStorages(onSuccess) { - var self = this; - - this.systemIO.getStorages('INTERNAL', function (storages) { - self.storages = storages; - if (typeof onSuccess === 'function') { - onSuccess(); - } - }, 'internal0'); - }, - - /** - * Returns folder data - * @param {string} path Node path - * @param {function} onSuccess Success callback - * @param {function} onError Error callback - */ - getFolderData: function Model_getFolderData(path, onSuccess, onError) { - var self = this, - onOpenSuccess = function (dir) { - dir.listFiles( - function (files) { - self.currentPath = dir.fullPath; - onSuccess(dir, files); - }, - function (e) { - console.error('Model_getFolderData listFiles error', e); - } - ); - }, - onOpenError = function (e) { - console.error('Model_getFolderData openDir error', e); - }; - - this.systemIO.openDir(path, onOpenSuccess, onOpenError); - }, - - isStorageExists: function (nodeName, success, error) { - tizen.filesystem.resolve(nodeName, success, error); - }, - - /** - * Launch a service to open the file - * @param {string} fullUri ext - * @param {string} mime uri - */ - openFile: function Model_openFile(fullUri, mime) { - if (this.openFileUnLocked) { - var self = this, serviceReplyCB = { - onsuccess: function (reply) { - self.openFileUnLocked = true; - }, - onfailure: function () { - self.openFileUnLocked = true; - console.error('Launch service failed'); - } - }; - this.openFileUnLocked = false; - try { - console.log('Launching view for file "' + fullUri + '" (mime="' + mime + '")...'); - tizen.application.launchAppControl(new tizen.ApplicationControl( - 'http://tizen.org/appcontrol/operation/view', - fullUri, - mime - ), - null, - function () { - setTimeout(function () { - self.openFileUnLocked = true; - }, 500); - }, - function (e) { - self.openFileUnLocked = true; - console.error('Service launch failed. Exception message:' + e.message); - }, - serviceReplyCB - ); - } catch (e) { - self.openFileUnLocked = true; - console.error('openFile failed', e); - } - } - }, - - refreshContent: function (path, successCallback, mode) { - successCallback = successCallback || null; - mode = mode || 'copy'; - var isDir = true, - onResolveSuccess; - if(app.helpers.getFileExtension(path) !== '') { - isDir = false; - } - onResolveSuccess = function () {}; - - if(isDir) { - switch (mode) { - case 'delete': - tizen.filesystem.resolve(path, onResolveSuccess, successCallback); - break; - default: - tizen.filesystem.resolve(path, successCallback); - } - } else { - tizen.content.scanFile(path, successCallback); - } - }, - - resolveAndRefresh: function (path, successCallback, mode) { - var self = this; - tizen.filesystem.resolve(path, function (file) { - self.refreshContent(file.toURI(), successCallback); - }, null); - }, - - /** - * @param {File[]} nodes Collection of node objects - * @param {File} dir Directory handle - * @param {function} onSuccess - * @param {function} onError - */ - deleteNodes: function Model_deleteNodes(nodes, dir, onSuccess, onError) { - var len = nodes.length, - self = this, - onDeleteNodeSuccess = function (node, isDir, fileobject) { - try { - this.refreshContent(fileobject.toURI(), function () { - app.clipboard.removeRecursively(node.uri); - app.ui.refreshPasteActionBtn(); - if (typeof onSuccess === 'function') { - onSuccess(node.id); - } - }, 'delete'); - } catch (e) { - console.error(e); - } - }, - onDeleteNodeError = function (e) { - console.error('Folder delete error', e); - if (typeof onError === 'function') { - onError(); - } - }, - i; - - for (i = 0; i < len; i = i + 1) { - tizen.filesystem.resolve( - nodes[i].uri, - function (node, fileobject) { - if (node.folder) { - dir.deleteDirectory( - node.uri, - true, - onDeleteNodeSuccess.bind(this, node, true, fileobject), - onDeleteNodeError - ); - } else { - dir.deleteFile( - node.uri, - onDeleteNodeSuccess.bind(this, node, false, fileobject), - onDeleteNodeError - ); - } - }.bind(this, nodes[i]), - null - ); - } - }, - - /** - * Copy specified files to destination path - * Overwrites existing files - * - * @param {File} dir Directory handle - * @param {string[]} paths Array with absolute virtual file paths - * @param {string} destinationPath - * @param {function} onSuccess callback - */ - copyNodes: function Model_copyNodes(dir, paths, destinationPath, onSuccess) { - var len = paths.length, self = this, - scaned = 0, - scanSuccess = function () { - scaned += 1; - if (scaned === len) { - onSuccess(); - } - }, - onCopyNodeSuccess = function (file) { - self.refreshContent(file.toURI(), scanSuccess, 'copy'); - }, - onCopyNodeFailure = function (e) { - console.error(e); - setTimeout(function () { - app.ui.alertPopup('Copying error'); - }, 200); - }, - i, - sourceName, - decision; - - this.systemIO.getFilesList(dir, function (filesList) { - for (i = 0; i < len; i = i + 1) { - if (destinationPath.indexOf(paths[i]) !== -1) { - setTimeout(function () { - app.ui.alertPopup('Copying error'); - }, 200); - return; - } - } - - for (i = 0; i < len; i = i + 1) { - decision = true; - sourceName = paths[i].split('/').pop(); - sourceName = app.helpers.getCopyFileName(sourceName, filesList); - - try { - dir.copyTo(paths[i], destinationPath + '/' + sourceName, true, onCopyNodeSuccess, onCopyNodeFailure); - self.resolveAndRefresh(paths[i]); - } catch (e) { - console.error(e); - } - } - }); - }, - - /** - * Move specified files to destination path - * Overwrites existing files - * - * @param {File} dir Directory handle - * @param {string[]} paths Array with absolute virtual file paths - * @param {string} destinationPath - * @param {function} onSuccess callback - */ - moveNodes: function Model_moveNodes(dir, paths, destinationPath, onSuccess) { - var len = paths.length, self = this, - scaned = 0, - toScan = len * 2, - illegalMove = false, - scanSuccess = function () { - scaned += 1; - if (scaned === toScan) { - onSuccess(); - } - }, - onMoveNodeSuccess = function (oldfile, file) { - self.refreshContent(oldfile.toURI(), scanSuccess, 'delete'); - self.refreshContent(file.toURI(), scanSuccess, 'copy'); - }, - onMoveNodeFailure = function () { - app.ui.alertPopup('Moving error'); - }, - i, - sourceName, - decision; - - while (len--) { - if (destinationPath.match(paths[len])) { - illegalMove = true; - break; - } - } - - len = paths.length; - - if (illegalMove) { - setTimeout(function () { - app.ui.alertPopup('Can not move catalog into itself.'); - }, 200); - return; - } - - this.systemIO.getFilesList(dir, function (filesList) { - for (i = 0; i < len; i = i + 1) { - if (destinationPath.indexOf(paths[i]) !== -1) { - app.ui.alertPopup('Moving error'); - return; - } - } - - for (i = 0; i < len; i = i + 1) { - decision = true; - sourceName = paths[i].split('/').pop(); - try { - tizen.filesystem.resolve( - paths[i], - function (path, destinationPath, sourceName, oldfile) { - dir.moveTo(path, destinationPath + '/' + sourceName, false, onMoveNodeSuccess.bind(self, oldfile), onMoveNodeFailure); - }.bind(self, paths[i], destinationPath, sourceName), - null - ); - } catch (e) { - console.error(e); - } - } - }); - } - }; + 'use strict'; + Model.prototype = { + + /** + * file open unlock flag + * @type {boolean} + */ + openFileUnLocked: true, + + /** + * @type SystemIO + */ + systemIO: null, + + /** + * @type Array + */ + storages: [{label: 'root', type: 'INTERNAL'}], + + /** + * @type String + */ + currentPath: '', + + /** + * API module initialisation + */ + init: function Model_init() { + this.systemIO = new SystemIO(); + }, + + /** + * @returns {FileSystemStorage[]} storages + */ + getInternalStorages: function Model_getInternalStorages() { + return this.storages; + }, + + /** + * Saves storages + * @param {function} onSuccess callback + */ + loadInternalStorages: function Model_loadInternalStorages(onSuccess) { + var self = this; + + this.systemIO.getStorages('INTERNAL', function (storages) { + self.storages = storages; + if (typeof onSuccess === 'function') { + onSuccess(); + } + }, 'internal0'); + }, + + /** + * Returns folder data + * @param {string} path Node path + * @param {function} onSuccess Success callback + * @param {function} onError Error callback + */ + getFolderData: function Model_getFolderData(path, onSuccess, onError) { + var self = this, + onOpenSuccess = function (dir) { + dir.listFiles( + function (files) { + self.currentPath = dir.fullPath; + onSuccess(dir, files); + }, + function (e) { + console.error( + 'Model_getFolderData listFiles error', + e + ); + } + ); + }, + onOpenError = function (e) { + console.error('Model_getFolderData openDir error', e); + }; + + this.systemIO.openDir(path, onOpenSuccess, onOpenError); + }, + + isStorageExists: function (nodeName, success, error) { + tizen.filesystem.resolve(nodeName, success, error); + }, + + /** + * Launch a service to open the file + * @param {string} fullUri ext + * @param {string} mime uri + */ + openFile: function Model_openFile(fullUri) { + if (this.openFileUnLocked) { + var self = this, serviceReplyCB = { + onsuccess: function (reply) { + self.openFileUnLocked = true; + }, + onfailure: function () { + self.openFileUnLocked = true; + console.error('Launch service failed'); + } + }; + this.openFileUnLocked = false; + try { + console.log('Launching view for file "' + fullUri + '"'); + tizen.application.launchAppControl( + new tizen.ApplicationControl( + 'http://tizen.org/appcontrol/operation/view', + fullUri + ), + null, + function () { + setTimeout(function () { + self.openFileUnLocked = true; + }, 500); + }, + function (e) { + self.openFileUnLocked = true; + console.error( + 'Service launch failed. Exception message:' + + e.message + ); + }, + serviceReplyCB + ); + } catch (e) { + self.openFileUnLocked = true; + console.error('openFile failed', e); + } + } + }, + + refreshContent: function (path, successCallback, mode) { + successCallback = successCallback || null; + mode = mode || 'copy'; + var isDir = true, + onResolveSuccess; + onResolveSuccess = function () {}; + + tizen.filesystem.resolve(path, function (file) { + if (file.isFile) { + tizen.content.scanFile(path, successCallback); + } else { + successCallback(); + } + }, null); + }, + + resolveAndRefresh: function (path, successCallback, mode) { + var self = this; + tizen.filesystem.resolve(path, function (file) { + self.refreshContent(file.toURI(), successCallback); + }, null); + }, + + /** + * @param {File[]} nodes Collection of node objects + * @param {File} dir Directory handle + * @param {function} onSuccess + * @param {function} onError + */ + deleteNodes: function Model_deleteNodes( + nodes, + dir, + onSuccess, + onError + ) { + var len = nodes.length, + self = this, + onDeleteNodeSuccess = function (file) { + try { + app.clipboard.removeRecursively(file.fullPath); + app.ui.refreshPasteActionBtn(); + if (onSuccess instanceof Function) { + onSuccess(file.fullPath); + } + } catch (e) { + console.error(e); + } + }, + onDeleteNodeError = function (e) { + if (typeof onError === 'function') { + onError(); + } + }, + i, + remove = function (file, success, failure) { + var parent = file.parent, fullPath = file.fullPath, + removeSuccess = function () { + if (success instanceof Function) { + success(file); + } + }, + removeFailure = function (error) { + if (failure instanceof Function) { + failure(error, file); + } + }; + + if (file.isFile) { + parent.deleteFile( + fullPath, + function () { + tizen.content.scanFile( + file.toURI(), + removeSuccess, + removeFailure + ); + }, + removeFailure + ); + } else { + file.listFiles( + function (files) { + var len = files.length, + index = len - 1, + counter = 0, + removeEmptyDir = function () { + parent.deleteDirectory( + fullPath, + false, + removeSuccess, + removeFailure + ); + }; + + if (len > 0) { + while (index >= 0) { + remove( + files[index], + function () { + counter += 1; + if (counter === len) { + removeEmptyDir(); + } + }, + removeFailure + ); + index -= 1; + } + } else { + removeEmptyDir(); + } + }, + removeFailure + ); + } + }; + + for (i = 0; i < len; i = i + 1) { + tizen.filesystem.resolve( + nodes[i].uri, + function (file) { + remove(file, onDeleteNodeSuccess, onDeleteNodeError); + }.bind(this), + null + ); + } + }, + + /** + * Copy specified files to destination path + * Overwrites existing files + * + * @param {File} dir Directory handle + * @param {string[]} paths Array with absolute virtual file paths + * @param {string} destinationPath + * @param {function} onSuccess callback + */ + copyNodes: function Model_copyNodes( + dir, + paths, + destinationPath, + onSuccess + ) { + var len = paths.length, self = this, + scaned = 0, + scanSuccess = function () { + scaned += 1; + if (scaned === len) { + onSuccess(); + } + }, + onCopyNodeSuccess = function (file) { + self.refreshContent(file.toURI(), scanSuccess, 'copy'); + }, + onCopyNodeFailure = function (e) { + console.error(e); + setTimeout(function () { + app.refreshCurrentPage(); + app.ui.alertPopup('Copying error'); + }, 200); + }, + i, + sourceName, + decision; + + this.systemIO.getFilesList(dir, function (filesList) { + for (i = 0; i < len; i = i + 1) { + if (destinationPath.indexOf(paths[i]) !== -1) { + setTimeout(function () { + app.ui.alertPopup('Copying error'); + }, 200); + return; + } + } + + for (i = 0; i < len; i = i + 1) { + decision = true; + sourceName = paths[i].split('/').pop(); + sourceName = app.helpers.getCopyFileName( + sourceName, + filesList + ); + + try { + dir.copyTo( + paths[i], + destinationPath + '/' + sourceName, + true, + onCopyNodeSuccess, + onCopyNodeFailure + ); + } catch (e) { + console.error(e); + } + } + }); + }, + + /** + * Move specified files to destination path + * Overwrites existing files + * + * @param {File} dir Directory handle + * @param {string[]} paths Array with absolute virtual file paths + * @param {string} destinationPath + * @param {function} onSuccess callback + */ + moveNodes: function Model_moveNodes( + dir, + paths, + destinationPath, + onSuccess + ) { + var len = paths.length, self = this, + scaned = 0, + toScan = len * 2, + illegalMove = false, + scanSuccess = function () { + scaned += 1; + if (scaned === toScan) { + onSuccess(); + } + }, + onMoveNodeSuccess = function (oldfile, file) { + self.refreshContent(oldfile.toURI(), scanSuccess, 'delete'); + self.refreshContent(file.toURI(), scanSuccess, 'copy'); + }, + onMoveNodeFailure = function () { + app.ui.alertPopup('Moving error'); + }, + i, + sourceName, + decision; + + len -= 1; + while (len >= 0) { + if (destinationPath.match(paths[len])) { + illegalMove = true; + break; + } + len -= 1; + } + + len = paths.length; + + if (illegalMove) { + setTimeout(function () { + app.ui.alertPopup('Can not move catalog into itself.'); + }, 200); + return; + } + + this.systemIO.getFilesList(dir, function (filesList) { + var resolveSuccess = function ( + path, + destinationPath, + sourceName, + oldfile + ) { + dir.moveTo( + path, + destinationPath + '/' + sourceName, + false, + onMoveNodeSuccess.bind(self, oldfile), + onMoveNodeFailure + ); + }; + for (i = 0; i < len; i = i + 1) { + if (destinationPath.indexOf(paths[i]) !== -1) { + app.ui.alertPopup('Moving error'); + return; + } + } + + for (i = 0; i < len; i = i + 1) { + decision = true; + sourceName = paths[i].split('/').pop(); + try { + tizen.filesystem.resolve( + paths[i], + resolveSuccess.bind( + self, + paths[i], + destinationPath, + sourceName + ), + onMoveNodeFailure + ); + } catch (e) { + console.error(e); + } + } + }); + } + }; }()); diff --git a/project/js/app.systemIO.js b/project/js/app.systemIO.js index 4c70377..4aef763 100644 --- a/project/js/app.systemIO.js +++ b/project/js/app.systemIO.js @@ -1,3 +1,19 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true*/ /*global tizen, localStorage */ @@ -5,257 +21,318 @@ * @class SystemIO */ function SystemIO() { - 'use strict'; + 'use strict'; } (function () { // strict mode wrapper - 'use strict'; - SystemIO.prototype = { - /** - * Creates new empty file in specified location - * - * @param {File} directoryHandle - * @param {string} fileName - */ - createFile: function SystemIO_createFile(directoryHandle, fileName) { + 'use strict'; + SystemIO.prototype = { + /** + * Creates new empty file in specified location + * + * @param {File} directoryHandle + * @param {string} fileName + */ + createFile: function SystemIO_createFile(directoryHandle, fileName) { - try { - return directoryHandle.createFile(fileName); - } catch (e) { - console.error('SystemIO_createFile error:' + e.message); - return false; - } - }, + try { + return directoryHandle.createFile(fileName); + } catch (e) { + console.error('SystemIO_createFile error:' + e.message); + return false; + } + }, - /** - * Writes content to file stream - * - * @param {File} fileHandle file handler - * @param {string} fileContent file content - * @param {function} onSuccess on success callback - * @param {function} onError on error callback - * @param {string} content encoding - */ - writeFile: function SystemIO_writeFile(fileHandle, fileContent, onSuccess, onError, contentEncoding) { - onError = onError || function () {}; + /** + * Writes content to file stream + * + * @param {File} fileHandle file handler + * @param {string} fileContent file content + * @param {function} onSuccess on success callback + * @param {function} onError on error callback + * @param {string} content encoding + */ + writeFile: function SystemIO_writeFile( + fileHandle, + fileContent, + onSuccess, + onError, + contentEncoding + ) { + onError = onError || function () {}; - fileHandle.openStream('w', function (fileStream) { - if (contentEncoding === 'base64') { - fileStream.writeBase64(fileContent); - } else { - fileStream.write(fileContent); - } + fileHandle.openStream('w', function (fileStream) { + if (contentEncoding === 'base64') { + fileStream.writeBase64(fileContent); + } else { + fileStream.write(fileContent); + } - fileStream.close(); + fileStream.close(); - // launch onSuccess callback - if (typeof onSuccess === 'function') { - onSuccess(); - } - }, onError, 'UTF-8'); - }, + // launch onSuccess callback + if (typeof onSuccess === 'function') { + onSuccess(); + } + }, onError, 'UTF-8'); + }, - /** - * Opens specified location - * - * @param {string} directory path - * @param {function} on success callback - * @param {function} on error callback - * @param {string} mode - */ - openDir: function SystemIO_openDir(directoryPath, onSuccess, onError, openMode) { - openMode = openMode || 'rw'; - onSuccess = onSuccess || function () {}; + /** + * Opens specified location + * + * @param {string} directory path + * @param {function} on success callback + * @param {function} on error callback + * @param {string} mode + */ + openDir: function SystemIO_openDir( + directoryPath, + onSuccess, + onError, + openMode + ) { + openMode = openMode || 'rw'; + onSuccess = onSuccess || function () {}; - try { - tizen.filesystem.resolve(directoryPath, onSuccess, onError, openMode); - } catch (e) { - } - }, + try { + tizen.filesystem.resolve( + directoryPath, + onSuccess, + onError, + openMode + ); + } catch (e) { + } + }, - /** - * Parse specified filepath and returns data parts - * - * @param {string} filePath - * @returns {array} - */ - getPathData: function SystemIO_getPathData(filePath) { - var path = { - originalPath: filePath, - fileName: '', - dirName: '' - }, - splittedPath = filePath.split('/'); + /** + * Parse specified filepath and returns data parts + * + * @param {string} filePath + * @returns {array} + */ + getPathData: function SystemIO_getPathData(filePath) { + var path = { + originalPath: filePath, + fileName: '', + dirName: '' + }, + splittedPath = filePath.split('/'); - path.fileName = splittedPath.pop(); - path.dirName = splittedPath.join('/') || '/'; + path.fileName = splittedPath.pop(); + path.dirName = splittedPath.join('/') || '/'; - return path; - }, + return path; + }, - /** - * Save specified content to file - * - * @param {string} file path - * @param {string} file content - * @param {string} file encoding - */ - saveFileContent: function SystemIO_saveFileContent(filePath, fileContent, onSaveSuccess, fileEncoding) { - var pathData = this.getPathData(filePath), - self = this, - fileHandle; + /** + * Save specified content to file + * + * @param {string} file path + * @param {string} file content + * @param {string} file encoding + */ + saveFileContent: function SystemIO_saveFileContent( + filePath, + fileContent, + onSaveSuccess, + fileEncoding + ) { + var pathData = this.getPathData(filePath), + self = this, + fileHandle; - function onOpenDirSuccess(dir) { - // create new file - fileHandle = self.createFile(dir, pathData.fileName); - if (fileHandle !== false) { - // save data into this file - self.writeFile(fileHandle, fileContent, onSaveSuccess, false, fileEncoding); - } - } + function onOpenDirSuccess(dir) { + // create new file + fileHandle = self.createFile(dir, pathData.fileName); + if (fileHandle !== false) { + // save data into this file + self.writeFile( + fileHandle, + fileContent, + onSaveSuccess, + false, + fileEncoding + ); + } + } - // open directory - this.openDir(pathData.dirName, onOpenDirSuccess); - }, + // open directory + this.openDir(pathData.dirName, onOpenDirSuccess); + }, - /** - * Deletes node with specified path - * - * @param {string} node path - * @param {function} success callback - */ - deleteNode: function SystemIO_deleteNode(nodePath, onSuccess) { - var pathData = this.getPathData(nodePath), - self = this; + /** + * Deletes node with specified path + * + * @param {string} node path + * @param {function} success callback + */ + deleteNode: function SystemIO_deleteNode(nodePath, onSuccess) { + var pathData = this.getPathData(nodePath), + self = this; - function onDeleteSuccess() { - onSuccess(); - } + function onDeleteSuccess() { + onSuccess(); + } - function onDeleteError(e) { - console.error('SystemIO_deleteNode:_onDeleteError', e); - } + function onDeleteError(e) { + console.error('SystemIO_deleteNode:_onDeleteError', e); + } - function onOpenDirSuccess(dir) { - var onListFiles = function (files) { - if (files.length > 0) { - // file exists; - if (files[0].isDirectory) { - self.deleteDir(dir, files[0].fullPath, onDeleteSuccess, onDeleteError); - } else { - self.deleteFile(dir, files[0].fullPath, onDeleteSuccess, onDeleteError); - } - } else { - onDeleteSuccess(); - } - }; + function onOpenDirSuccess(dir) { + var onListFiles = function (files) { + if (files.length > 0) { + // file exists; + if (files[0].isDirectory) { + self.deleteDir( + dir, + files[0].fullPath, + onDeleteSuccess, + onDeleteError + ); + } else { + self.deleteFile( + dir, + files[0].fullPath, + onDeleteSuccess, + onDeleteError + ); + } + } else { + onDeleteSuccess(); + } + }; - // check file exists; - dir.listFiles(onListFiles, function (e) { - console.error(e); - }, { - name: pathData.fileName - }); - } + // check file exists; + dir.listFiles(onListFiles, function (e) { + console.error(e); + }, { + name: pathData.fileName + }); + } - this.openDir(pathData.dirName, onOpenDirSuccess, function (e) { - console.error('openDir error:' + e.message); - }); - }, + this.openDir(pathData.dirName, onOpenDirSuccess, function (e) { + console.error('openDir error:' + e.message); + }); + }, - /** - * Deletes specified file - * - * @param {File} dir - * @param {string} file path - * @param {function} delete success callback - * @param {function} delete error callback - */ - deleteFile: function SystemIO_deleteFile(dir, filePath, onDeleteSuccess, onDeleteError) { - try { - dir.deleteFile(filePath, onDeleteSuccess, onDeleteError); - } catch (e) { - console.error('SystemIO_deleteFile error: ' + e.message); - return false; - } - }, + /** + * Deletes specified file + * + * @param {File} dir + * @param {string} file path + * @param {function} delete success callback + * @param {function} delete error callback + */ + deleteFile: function SystemIO_deleteFile( + dir, + filePath, + onDeleteSuccess, + onDeleteError + ) { + try { + dir.deleteFile(filePath, onDeleteSuccess, onDeleteError); + } catch (e) { + console.error('SystemIO_deleteFile error: ' + e.message); + return false; + } + }, - /** - * Deletes specified directory - * - * @param {File} dir - * @param {string} dirPath dir path - * @param {function} onDeleteSuccess delete success callback - * @param {function} onDeleteError delete error callback - * @returns {boolean} - */ - deleteDir: function SystemIO_deleteDir(dir, dirPath, onDeleteSuccess, onDeleteError) { - try { - dir.deleteDirectory(dirPath, false, onDeleteSuccess, onDeleteError); - } catch (e) { - console.error('SystemIO_deleteDir error:' + e.message); - return false; - } + /** + * Deletes specified directory + * + * @param {File} dir + * @param {string} dirPath dir path + * @param {function} onDeleteSuccess delete success callback + * @param {function} onDeleteError delete error callback + * @returns {boolean} + */ + deleteDir: function SystemIO_deleteDir( + dir, + dirPath, + onDeleteSuccess, + onDeleteError + ) { + try { + dir.deleteDirectory( + dirPath, + false, + onDeleteSuccess, + onDeleteError + ); + } catch (e) { + console.error('SystemIO_deleteDir error:' + e.message); + return false; + } - return true; - }, + return true; + }, - /** - * @param {string} type storage type - * @param {function} onSuccess on success callback - * @param {string} excluded Excluded storage - */ - getStorages: function SystemIO_getStorages(type, onSuccess, excluded) { - try { - tizen.filesystem.listStorages(function (storages) { - var tmp = [], - len = storages.length, - i; + /** + * @param {string} type storage type + * @param {function} onSuccess on success callback + * @param {string} excluded Excluded storage + */ + getStorages: function SystemIO_getStorages(type, onSuccess, excluded) { + try { + tizen.filesystem.listStorages(function (storages) { + var tmp = [], + len = storages.length, + i; - if (type !== undefined) { - for (i = 0; i < len; i += 1) { - if (storages[i].label !== excluded) { - if (storages[i].type === 0 || storages[i].type === type) { - tmp.push(storages[i]); - } - } - } - } else { - tmp = storages; - } + if (type !== undefined) { + for (i = 0; i < len; i += 1) { + if (storages[i].label !== excluded) { + if ( + storages[i].type === 0 || + storages[i].type === type + ) { + tmp.push(storages[i]); + } + } + } + } else { + tmp = storages; + } - if (typeof onSuccess === 'function') { - onSuccess(tmp); - } - }); - } catch (e) { - console.error('SystemIO_getStorages error:' + e.message); - } - }, + if (typeof onSuccess === 'function') { + onSuccess(tmp); + } + }); + } catch (e) { + console.error('SystemIO_getStorages error:' + e.message); + } + }, - getFilesList: function SystemIO_getFilesList(dir, onSuccess) { - try { - dir.listFiles( - function (files) { - var tmp = [], - len = files.length, - i; + getFilesList: function SystemIO_getFilesList(dir, onSuccess) { + try { + dir.listFiles( + function (files) { + var tmp = [], + len = files.length, + i; - for (i = 0; i < len; i += 1) { - tmp.push(files[i].name); - } + for (i = 0; i < len; i += 1) { + tmp.push({ + name: files[i].name, + isDirectory: files[i].isDirectory + }); + } - if (typeof onSuccess === 'function') { - onSuccess(tmp); - } - }, - function (e) { - console.error('SystemIO_getFilesList dir.listFiles() error:', e); - } - ); - } catch (e) { - console.error('SystemIO_getFilesList error:', e.message); - } - } - }; -}()); \ No newline at end of file + if (typeof onSuccess === 'function') { + onSuccess(tmp); + } + }, + function (e) { + console.error( + 'SystemIO_getFilesList dir.listFiles() error:', + e + ); + } + ); + } catch (e) { + console.error('SystemIO_getFilesList error:', e.message); + } + } + }; +}()); diff --git a/project/js/app.ui.js b/project/js/app.ui.js index b6b30e1..9d94607 100644 --- a/project/js/app.ui.js +++ b/project/js/app.ui.js @@ -1,961 +1,1109 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*jslint devel: true */ -/*global $, app, TemplateManager, Helpers */ +/*global window, tizen, $, app, TemplateManager, Helpers */ /** * @class Ui */ function Ui() { - 'use strict'; + 'use strict'; } (function () { // strict mode wrapper - 'use strict'; - Ui.prototype = { - /** - * root mode - * @type {boolean} - */ - root: true, - - /** - * locked folders - * @type {array} - */ - lockedFolders: ['ringtones'], - - /** - * UI edit mode - * @type {boolean} - */ - editMode: false, - - /** - * @type {bool} block clicks until the page change is completed - */ - nodeTapBlock: false, - - /** - * @type {TemplateManager} - */ - templateManager: null, - - /** - * @type Helpers - */ - helpers: null, - - /** - * @type Info popup lock - */ - infoPopupVisibility: false, - - /** - * @const {number} - */ - PATH_DIV_HEIGHT: 20, - - /** - * @const {number} - */ - SELECT_ALL_HEIGHT: 32, - - /** - * @const {number} header height, set on domReady - */ - HEADER_HEIGHT: 53, - - /** - * name of row gradient class - */ - CSS_GRADIENT_CLASS: 'gradientBackground', - - /** - * Standard tabbar actions - * @type {number} - */ - STD_TABBAR_EDIT_ACTION: 0, - STD_TABBAR_MORE_ACTION: 1, - STD_TABBAR_EXIT_ACTION: 2, - - /** - * Edit tabbar actions - * @type {number} - */ - EDIT_TABBAR_DELETE_ACTION: 0, - EDIT_TABBAR_MOVE_ACTION: 1, - EDIT_TABBAR_COPY_ACTION: 2, - EDIT_TABBAR_CANCEL_ACTION: 3, - - currentHeaderHeight: null, - currentScrollPosition: null, - - /** - * UI Initialization - */ - init: function Ui_init(storages) { - this.templateManager = new TemplateManager(); - this.helpers = new Helpers(); - // Disable text selection - $.mobile.tizen.disableSelection(document); - $(document).ready(this.initDom.bind(this, storages)); - }, - - initDom: function Ui_initDom(storages) { - var self = this, - overlay = $('#overlay'), - popup = $('#infoPopup'), - windowWidth, - windowHeight, - popWidth; - - this.templateManager.loadToCache(['main', 'fileRow', 'folderRow', 'levelUpRow', 'emptyFolder'], function () { - $('#main').append($(self.templateManager.get('main')).children()).trigger('pagecreate'); - self.addEvents(); - self.displayStorages(storages); - }); - - windowWidth = $(window).width(); - windowHeight = $(window).height(); - - overlay.css({ - 'width': windowWidth + 'px', - 'height': windowHeight + 'px' - }); - - popWidth = windowWidth / 2 + 30; - popup.css({ - 'width': popWidth + 'px', - 'left': (windowWidth / 2 - popWidth / 2) + 'px', - 'top': (windowHeight / 2 - popup.height() / 2) + 'px' - }); - }, - - /** - * Add UI events - */ - addEvents: function Ui_addEvents() { - var self = this; - - document.addEventListener('webkitvisibilitychange', function () { - if (document.webkitVisibilityState === 'visible') { - self.refreshSelectAllStatus(); - app.refreshCurrentPage(true); - } - }); - - window.addEventListener('tizenhwkey', function(e) { - var uri = $('#navbar span+span').attr('uri'); - if (e.keyName == "back") { - if (self.infoPopupVisibility) { - return; - } else if ($.mobile.popup.active) { - $.mobile.popup.active.close(); - } else if (self.editMode === true) { - self.handleCancelEditAction(); - } else if (!uri) { - if ( app.ui.root === false ) { - $('#fileList').empty(); - app.ui.prepareFolderRow(0, "root"); - app.ui.root = true; - } else { - tizen.application.getCurrentApplication().exit(); - } - } else { - app.goLevelUp(); - } - } - }); - - $(window).resize( function () { - $.mobile.activePage.page('refresh') - }); - - // touch events for all nodes - $('ul#fileList') - .on('click', 'li.levelUp', function () { - if (self.editMode === true) { - self.handleCancelEditAction(); - } - app.goLevelUp(); - }) - .on('click', 'li.node', function (e) { - e.preventDefault(); - e.stopPropagation(); - self.handleNodeClick($(this), true); - }) - .on('change', 'input[type=checkbox]', function (e) { - self.handleNodeClick($(this).closest('li.node'), false); - }) - .on('touchstart', 'li', function (event) { - $(this).addClass(self.CSS_GRADIENT_CLASS); - }) - .on('touchend touchmove', 'li', function (event) { - $(this).removeClass(self.CSS_GRADIENT_CLASS); - }); - - $('.selectAll input').on('change', this.handleSelectAllChange.bind(this)); - - // navbar - $('#navbar').on('click', 'span', function () { - var uri = $(this).attr('uri'); - if (uri === 'home') { - if (app.currentPath !== '') { - app.displayStorages(); - } - } else if (uri === app.model.currentPath) { - app.displayFolder(uri,true); - } else { - if (self.editMode === true) { - self.handleCancelEditAction(); - } - app.displayFolder(uri); - } - }); - - // level up - $('#levelUpBtn').on('click', function () { - if (self.editMode === true) { - self.handleCancelEditAction(); - } - app.goLevelUp(); - }); - - $('#homeBtn').on('click', app.displayStorages.bind(app)); - - // edit action - $('#editActionBtn').on('click', this.handleEditAction.bind(this)); - - // delete action - $('#deleteActionBtn').on('click', this.handleDeleteAction.bind(this)); - - // cancel edit - $('#cancelActionBtn').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - self.handleCancelEditAction(); - }); - - // copy action - $('#copyActionBtn').on('click', this.handleCopyAction.bind(this)); - - // move action - $('#moveActionBtn').on('click', this.handleMoveAction.bind(this)); - - // paste action - $('a#pasteActionBtn').on('click', function () { - if (!self.infoPopupVisibility) { - self.toggleInfoPopup(); - setTimeout(app.pasteClipboard.bind(app), 100); - } - $("#morePopup").popup('close'); - }); - - // remove active class - $('[data-role = "tabbar"] li > a').on('click', function () { - $(this).removeClass('ui-focus, ui-btn-active'); - }); - // exit - $('.ui-myExit').on('click', app.exit); - - // add folder popup actions - $('#addFolderPopup').on("popupafterclose", function () { - // clear input value - $('#newFolderName').val('New folder'); - }); - - $('#newFolderName').on('click', function () { - if ($(this).attr('value') === 'New folder') { - $(this).attr('value', ''); - } - }); - - $('#saveNewFolder').on('click', this.saveNewFolder.bind(this)); - $('#newFolderForm').on('submit', this.saveNewFolder.bind(this)); - }, - - saveNewFolder: function Ui_saveNewFolder(e) { - var folderName = $('#newFolderName').val().trim(), status = true, - open = function () { - $("#addFolderPopup").popup('open', { - positionTo: "window" - }); - }, - self = this, - buttons = $("#addFolderPopup .ui-popup-button-bg a"), - activePopup; - e.preventDefault(); - e.stopPropagation(); - buttons.addClass('ui-disabled'); - $("#addFolderPopup").one("popupafterclose", function () { - if (folderName === '') { - self.alertPopup("Empty folder name", open); - status = false; - } else if (folderName.match(/[\*\.\/\\\?\"\'\:<>|]/)) { - self.alertPopup("The following special characters " - +"are not allowed: *./\\?:<>|'\"", open); - status = false; - } else { - status = app.createDir(folderName, open); - } - buttons.removeClass('ui-disabled'); - }); - activePopup = $.mobile.popup.active; - if ( - activePopup && - activePopup.element.attr('id') === 'addFolderPopup' - ) { - activePopup.close(); - } - return status; - }, - - toggleInfoPopup: function () { - var overlay = $('#overlay'); - - if (this.infoPopupVisibility) { - overlay.hide(); - document.onkeydown = null; - } else { - document.onkeydown = function(){return false;} - overlay.show(); - } - - this.infoPopupVisibility = !this.infoPopupVisibility; - }, - - alertPopup: function (text, callback) { - $("#alertPopup .text").text(text); - $("#alertPopup").popup('open', {'positionTo': 'window'}); - if (callback instanceof Function) { - $("#alertPopup").one("popupafterclose", function () { - callback(); - }); - } - if (this.infoPopupVisibility) { - this.toggleInfoPopup(); - } - }, - - confirmPopup: function (text, confirmCallback, completeCallback) { - var popup = $("#confirmPopup"); - popup.find(".text").text(text); - popup.popup('open', {positionTo: 'window'}); - popup.find(".confirm").one("click", function () { - if (confirmCallback instanceof Function) { - confirmCallback(); - } - }); - if (completeCallback instanceof Function) { - popup.one('popupafterclose', function () { - completeCallback(); - }); - } - }, - - clearTabbars: function Ui_clearTabbars() { - $('[data-role = "tabbar"] li > a').removeClass('ui-focus, ui-btn-active'); - }, - - /** - * Handler for node click - * @param {File} node - * @param {boolean} toggleCheckbox - */ - handleNodeClick: function Ui_handleNodeClick(node, toggleCheckbox) { - if (this.root) { - app.model.loadInternalStorages(function () { app.displayStorages(); }); - this.root = false; - } else if (this.editMode === true) { - //if edit mode is on toggle checkbox state - if (toggleCheckbox === true) { - this.toggleCheckBoxState(node); // select the checkbox - } - - this.refreshSelectAllStatus(); - this.refreshEditMenu(); - } else if (node.hasClass('folder')) { - // otherwise display folder - app.displayFolder(node.attr('uri')); - } else { - // file - app.openFile(node.attr('uri'), node.attr('fullUri')); - } - }, - - /** - * Handler for edit action - */ - handleEditAction: function Ui_handleEditAction() { - this.editMode = true; - this.clearTabbars(); - $('.standardTabbar').hide(); - $('div.editTabbar').show(); - this.disableControlBarButtons($('div.editTabbar'), [this.EDIT_TABBAR_DELETE_ACTION, this.EDIT_TABBAR_COPY_ACTION, this.EDIT_TABBAR_MOVE_ACTION]); - $('#fileList .folder .nodename, #fileList > li > span.nodename') - .animate({'width': '70%'}); - this.showEditCheckBoxes(); - }, - - /** - * Handler for cancel edit action - */ - handleCancelEditAction: function Ui_handleCancelEditAction() { - this.editMode = false; - this.clearTabbars(); - $('div.editTabbar').hide(); - $('.standardTabbar').show(); - $('#fileList .folder .nodename, #fileList > li > span.nodename') - .animate({'width': '75%'}); - this.hideEditCheckBoxes(); - if (this.isFileListEmpty()) { - $('#editActionBtn').addClass('vhidden').blur(); - } - }, - - /** - * Handler for delete action - */ - handleDeleteAction: function Ui_handleDeleteAction(e) { - var nodesToDelete = [], - $rowElement, - self = this, - conf; - - e.stopPropagation(); - e.preventDefault(); - - this.confirmPopup('Selected nodes will be deleted. Are you sure?', - function () { - $('ul#fileList input:checkbox:checked').each(function (index) { - $rowElement = $(this).closest('li'); - nodesToDelete.push({ - id: $rowElement.attr('id'), - uri: $rowElement.attr('uri'), - name: $rowElement.attr('label'), - folder: $rowElement.hasClass('folder') - }); - }); - if (nodesToDelete.length > 0) { - app.deleteNodes(nodesToDelete); - self.scrollContentTo(0); - $('ul#fileList input:checkbox:checked').remove(); - self.refreshEditMenu(); - } - }, - function () { - self.clearTabbars(); - } - ); - }, - - /** - * Handler for copy action - */ - handleCopyAction: function Ui_handleCopyAction(e) { - var paths = []; - - e.stopPropagation(); - e.preventDefault(); - - if (this.editMode === true) { - $('ul#fileList input:checkbox:checked').each(function (index) { - paths.push($(this).closest('li').attr('uri')); - }); - app.saveToClipboard(paths, app.clipboard.COPY_MODE_ID); - } - }, - - /** - * Handler for move action - */ - handleMoveAction: function Ui_handleMoveAction(e) { - var paths = []; - - e.stopPropagation(); - e.preventDefault(); - - if (this.editMode === true) { - $('ul#fileList input:checkbox:checked').each(function (index) { - paths.push($(this).closest('li').attr('uri')); - }); - app.saveToClipboard(paths, app.clipboard.MOVE_MODE_ID); - } - }, - - /** - * Handler for paste action - */ - handlePasteAction: function Ui_handlePasteAction() { - }, - - /** - * Scrolls content to the specified position - */ - scrollContentTo: function scrollContentTo(value) { - $('#main [data-role="content"]').scrollview('scrollTo', 0, value); - }, - - /** - * @param {FileSystemStorage[]} nodes Storage elements - */ - displayStorages: function Ui_displayStorages(nodes) { - var len = nodes.length, nodeName, i; - - this.updateNavbar(''); - $('#fileList').empty(); - - for (i = 0; i < len; i = i + 1) { - nodeName = nodes[i].label.trim(); - if (nodeName !== '' - && (nodes[i].type === 0 || nodes[i].type === 'INTERNAL') - && nodeName.indexOf('wgt-') === -1 - && $.inArray(nodeName, this.lockedFolders) === -1 - ) { - if (!this.root) { - app.model.isStorageExists(nodeName, - app.ui.prepareFolderRow.bind(app.ui, i, nodeName), null); - } else { - this.prepareFolderRow(i, nodeName); - } - } - } - - $('#levelUpBtn').addClass('vhidden'); - $('#homeBtn').addClass('vhidden'); - - $('#editActionBtn').addClass('vhidden').blur(); - $('#moreActionBtn').addClass('vhidden').blur(); - $('h1#mainTitle').html('Media'); - - if (this.editMode) { - this.scrollContentTo(0); - } - - this.resetDefaultCheckBoxLabelEvents(); - this.hideSelectAllArea(); - this.handleCancelEditAction(); - - if (this.infoPopupVisibility) { - this.toggleInfoPopup(); - } - }, - - prepareFolderRow: function (id, name) { - $(this.templateManager.get('folderRow', { - id: id, - name: name, - uri: name, - fullUri: name, - })).appendTo('#fileList'); - }, - - /** - * File comparison function using their names (case insensitive) - * - * @param {File} x - * @param {File} y - * @returns {Number} - */ - fileComparison: function fileComparison(x, y) { - if(x.isDirectory !== y.isDirectory) { - return x.isDirectory ? -1 : 1; - } - var a = x.name.toLowerCase(), - b = y.name.toLowerCase(); - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - return 0; - }, - - /** - * renders node list for folder - * @param {string} folderName - * @param {File[]} nodes - * @param {bool} [refresh=false] - */ - displayFolder: function Ui_displayFolder(folderName, nodes, refresh) { - var len = nodes.length, - listElements = [this.templateManager.get('levelUpRow')], - nodeName, - checkedRows = [], - checkedRowsLen, - i; - refresh = refresh || false; - - // update title - this.updateTitle(this.templateManager.modifiers.escape(folderName)); - // update navbar - this.updateNavbar(this.templateManager.modifiers.escape(folderName)); - this.refreshPasteActionBtn(); - - nodes.sort(this.fileComparison); - - // render nodes - for (i = 0; i < len; i = i + 1) { - nodeName = nodes[i].name; - if (nodeName !== '') { - if (nodes[i].isDirectory) { - // folder - listElements.push(this.templateManager.get('folderRow', { - id: i, - name: nodeName, - uri: nodes[i].fullPath, - fullUri: nodes[i].toURI() - })); - } else { - // file - listElements.push(this.templateManager.get('fileRow', { - id: i, - name: nodeName, - uri: nodes[i].fullPath, - fullUri: nodes[i].toURI(), - thumbnailURI: this.helpers.getThumbnailURI(nodeName, nodes[i]) - })); - } - } - } - - if (listElements.length === 1) { - // set content for empty folder - listElements.push(this.templateManager.get('emptyFolder')); - // hide edit button for empty content - $('#editActionBtn').addClass('vhidden').blur(); - this.handleCancelEditAction(); - } else { - $('#editActionBtn').removeClass('vhidden'); - } - - // scroll to top of list - this.scrollContentTo(0); - - $('#levelUpBtn').removeClass('vhidden'); - $('#homeBtn').removeClass('vhidden'); - $('#moreActionBtn').removeClass('vhidden'); - - if (refresh === true && this.editMode === true) { - $.each($('#fileList .ui-checkbox input:checked'), function () { - checkedRows.push($(this).closest('li').attr('uri')); - }); - } - - // update file list - $('#fileList').html(listElements.join('')) - .trigger('refresh') - .trigger('create'); - - if (this.editMode === true) { - $('.selectAll').show(); - $('#fileList .folder .nodename, #fileList > li > span.nodename') - .css('width', '70%'); - $('ul#fileList > li').css('paddingLeft', '2rem'); - $('.my-ui-checkbox').removeClass('hidden'); - - if (refresh === true) { - checkedRowsLen = checkedRows.length; - if (checkedRowsLen) { - if (checkedRowsLen !== $('#fileList .ui-checkbox input').length) { - this.setCheckboxValue('.selectAll input', false); - } - // restore checked checkboxes - for (i = 0; i < checkedRowsLen; i += 1) { - this.setCheckboxValue( - '#' + - $('#fileList [uri="' + - checkedRows[i] + - '"]').attr('id') + - ' input:checkbox', - 'checked' - ); - } - - // if there are no checked checkboxes - if (!$('#fileList .ui-checkbox input:checked').length) { - this.clearDeleteMode(); - } - } else { - this.clearDeleteMode(); - } - } - } else { - $('.selectAll').hide(); - $('#fileList .folder .nodename, #fileList > li > span.nodename') - .css('width', '75%'); - $('ul#fileList > li').css('paddingLeft', '0'); - $('.my-ui-checkbox').addClass('hidden'); - this.clearDeleteMode(); - } - if (!refresh) this.hideSelectAllArea(); - - if (this.infoPopupVisibility) { - this.toggleInfoPopup(); - } - - this.refreshSelectAllStatus(); - }, - - /** - * Clear confirm popup and disable action buttons - */ - clearDeleteMode: function Ui_clearDeleteMode () { - if ( - $.mobile.popup.active && - $.mobile.popup.active.element.attr('id') === 'confirmPopup' - ) { - $.mobile.popup.active.close(); - } - this.disableControlBarButtons($('div.editTabbar'), - [this.EDIT_TABBAR_DELETE_ACTION, - this.EDIT_TABBAR_COPY_ACTION, - this.EDIT_TABBAR_MOVE_ACTION] - ); - }, - - /** - * Toggle a checkbox associated with a given list element - * @param {jQuery} listElement - */ - toggleCheckBoxState: function Ui_toggleCheckBoxState(listElement) { - var checkboxInput = null; - - checkboxInput = listElement.find('form > div.ui-checkbox input'); - this.setCheckboxValue(checkboxInput, !checkboxInput.attr('checked')); - }, - - /** - * Shows item checkboxes and topbar with select all option - */ - showEditCheckBoxes: function Ui_showEditCheckBoxes() { - var self = this; - - this.showSelectAllArea(); - - $('ul#fileList > li').animate({paddingLeft: '2rem'}, 500, 'swing', function () { - self.editMode = true; - $('.my-ui-checkbox').removeClass('hidden'); - }); - }, - - /** - * Hides item checkboxes and topbar with select all option - * All checkboxes are auto uncheked - */ - hideEditCheckBoxes: function Ui_hideEditCheckBoxes() { - var self = this; - - this.hideSelectAllArea(); // hide select all option topbar - - $('ul#fileList > li').animate({paddingLeft: '0'}, 200, 'swing', function () { - $('.my-ui-checkbox').addClass('hidden'); - $.mobile.activePage.page('refresh'); - }); - - // uncheck all checkboxes - $('ul#fileList input[type=checkbox]').each(function (index) { - self.setCheckboxValue(this, false); - }); - - //uncheck select all input - this.setCheckboxValue('.ui-header .selectAll input', false); - }, - - /** - * Save current header and content height - */ - saveHeights: function Ui_saveHeights() { - this.currentHeaderHeight = $('#main div[data-role="header"]').height(); - this.currentScrollPosition = $('#main div[data-role="content"]').scrollview('getScrollPosition').y; - }, - - /** - * Changes content scroll position after showing/hiding selectAllArea - */ - changeContentScrollPosition: function Ui_changeContentScrollPosition() { - var diff; - if (this.currentScrollPosition !== 0) { - diff = $('#main div[data-role="header"]').height() - this.currentHeaderHeight; - $('#main div[data-role="content"]').scrollview('scrollTo', 0, -(this.currentScrollPosition + diff)); - } - }, - - /** - * Shows topbar with select all option - */ - showSelectAllArea: function Ui_showSelectAllArea() { - this.saveHeights(); - $('.selectAll').show(); - $.mobile.activePage.page('refresh'); - this.changeContentScrollPosition(); - }, - - /** - * Hides topbar with select all option - */ - hideSelectAllArea: function Ui_hideSelectAllArea() { - this.saveHeights(); - $('.selectAll').hide(); - $.mobile.activePage.page('refresh'); - this.changeContentScrollPosition(); - }, - - /** - * Enable specified options for tabbar - * @param {object} tabbar - * @param {array} enableOptions options to enable - */ - enableControlBarButtons: function Ui_enableControlBarButtons(tabbar, enableOptions) { - var i = 0, - len = enableOptions.length; - - for (i = 0; i < len; i += 1) { - tabbar.tabbar('enable', enableOptions[i]); - } - }, - - /** - * Disable specified options for tabbar - * @param {object} tabbar controlbar - * @param {array} disableOptions options to enable - */ - disableControlBarButtons: function Ui_disableControlBarButtons(tabbar, disableOptions) { - var i = 0, - len = disableOptions.length; - - for (i = 0; i < len; i += 1) { - tabbar.tabbar('disable', disableOptions[i]); - } - }, - - /** - * @param {string} path - */ - updateTitle: function Ui_updateTitle(path) { - var regexp = new RegExp('([^\/])+$', 'g'), - match = path.match(regexp), - lastDir = match[0] || '(dir)'; - $('h1#mainTitle').html(lastDir); - }, - - /** - * @param {string} path - */ - updateNavbar: function Ui_updateNavbar(path) { - var html = ['Media'], - splitted, - len, - i; - - if (typeof path === 'string' && path !== '') { - splitted = path.split('/'); - len = splitted.length; - - for (i = 0; i < len; i = i + 1) { - html.push('' + splitted[i] + ''); - } - } - $('#navbar').html(html.join(' > ')); - }, - - handleSelectAllChange: function Ui_handleSelectAllChange() { - var $selectAllInput = $('.ui-header .selectAll .ui-checkbox input'), - self = this; - $selectAllInput.data('checkboxradio').refresh(); - - if ($selectAllInput.is(':checked')) { - // check all checkboxes - $('ul#fileList input[type=checkbox]').each(function (index) { - self.setCheckboxValue(this, true); - }); - - this.enableControlBarButtons($('.editTabbar'), [this.EDIT_TABBAR_DELETE_ACTION, this.EDIT_TABBAR_COPY_ACTION, this.EDIT_TABBAR_MOVE_ACTION]); - } else { - $('ul#fileList input[type=checkbox]').each(function (index) { - self.setCheckboxValue(this, false); - }); - - this.disableControlBarButtons($('.editTabbar'), [this.EDIT_TABBAR_DELETE_ACTION, this.EDIT_TABBAR_COPY_ACTION, this.EDIT_TABBAR_MOVE_ACTION]); - } - }, - - /** - * - */ - refreshSelectAllStatus: function Ui_refreshSelectAllStatus() { - var $selectAllInput = $('.ui-header .selectAll .ui-checkbox input'); - // update status of select all checkbox - if ($('ul#fileList input:checkbox:not(:checked)').length === 0) { - // all nodes checked - this.setCheckboxValue($selectAllInput, true); - } else { - // some node is not checked - this.setCheckboxValue($selectAllInput, false); - } - }, - - /** - * Refresh activity of edit menu - */ - refreshEditMenu: function () { - if ($('ul#fileList input:checkbox:checked').length > 0) { - this.enableControlBarButtons($('.editTabbar'), - [this.EDIT_TABBAR_DELETE_ACTION, this.EDIT_TABBAR_COPY_ACTION, this.EDIT_TABBAR_MOVE_ACTION]); - } else { - this.disableControlBarButtons($('.editTabbar'), - [this.EDIT_TABBAR_DELETE_ACTION, this.EDIT_TABBAR_COPY_ACTION, this.EDIT_TABBAR_MOVE_ACTION]); - } - }, - - /** - * Unbinds default events for checkbox labels - */ - resetDefaultCheckBoxLabelEvents: function Ui_resetDefaultCheckBoxLabelEvents() { - $('div.ui-checkbox > label') - .unbind('vmousedown') - .unbind('vmouseup') - .unbind('vmouseover') - .unbind('vclick'); - }, - - /** - * Remove html node element from list - * @param {string} nodeId node id - */ - removeNodeFromList: function Ui_removeNodeFromList(nodeId) { - $('ul#fileList > li#' + nodeId).remove(); - - // hide select All checkbox if removed all elements; - if ($('ul#fileList > li.node').length === 0) { - this.hideSelectAllArea(); - } - }, - - /** - * Enable/Disable - */ - refreshPasteActionBtn: function Ui_refreshPasteActionBtn() { - if (app.emptyClipboard()) { - $('#pasteActionBtnRow').addClass('hidden'); - } else { - $('#pasteActionBtnRow').removeClass('hidden'); - } - }, - - isFileListEmpty: function Ui_isFileListEmpty() { - return ($('ul#fileList').children('.node').length < 1); - }, - - setCheckboxValue: function Ui_setCheckboxValue (element, value) { - var $element = $(element), - checkboxradio = $element.data('checkboxradio'); - - $(element).attr('checked', value); - if (checkboxradio) { - checkboxradio.refresh(); - } - - } - }; + 'use strict'; + Ui.prototype = { + /** + * root mode + * @type {boolean} + */ + root: true, + + /** + * locked folders + * @type {array} + */ + lockedFolders: ['ringtones'], + + /** + * UI edit mode + * @type {boolean} + */ + editMode: false, + + /** + * @type {bool} block clicks until the page change is completed + */ + nodeTapBlock: false, + + /** + * @type {TemplateManager} + */ + templateManager: null, + + /** + * @type Helpers + */ + helpers: null, + + /** + * @type Info popup lock + */ + infoPopupVisibility: false, + + /** + * @const {number} + */ + PATH_DIV_HEIGHT: 20, + + /** + * @const {number} + */ + SELECT_ALL_HEIGHT: 32, + + /** + * @const {number} header height, set on domReady + */ + HEADER_HEIGHT: 53, + + /** + * name of row gradient class + */ + CSS_GRADIENT_CLASS: 'gradientBackground', + + /** + * Standard tabbar actions + * @type {number} + */ + STD_TABBAR_EDIT_ACTION: 0, + STD_TABBAR_MORE_ACTION: 1, + STD_TABBAR_EXIT_ACTION: 2, + + /** + * Edit tabbar actions + * @type {number} + */ + EDIT_TABBAR_DELETE_ACTION: 0, + EDIT_TABBAR_MOVE_ACTION: 1, + EDIT_TABBAR_COPY_ACTION: 2, + EDIT_TABBAR_CANCEL_ACTION: 3, + + currentHeaderHeight: null, + currentScrollPosition: null, + + /** + * UI Initialization + */ + init: function Ui_init(storages) { + this.templateManager = new TemplateManager(); + this.helpers = new Helpers(); + // Disable text selection + $.mobile.tizen.disableSelection(document); + $(document).ready(this.initDom.bind(this, storages)); + }, + + initDom: function Ui_initDom(storages) { + var self = this, + overlay = $('#overlay'), + popup = $('#infoPopup'), + windowWidth, + windowHeight, + popWidth; + + this.templateManager.loadToCache( + [ + 'main', + 'fileRow', + 'folderRow', + 'levelUpRow', + 'emptyFolder' + ], + function () { + $('#main') + .append($(self.templateManager.get('main')).children()) + .trigger('pagecreate'); + self.addEvents(); + self.displayStorages(storages); + } + ); + + windowWidth = $(window).width(); + windowHeight = $(window).height(); + + overlay.css({ + 'width': windowWidth + 'px', + 'height': windowHeight + 'px' + }); + + popWidth = windowWidth / 2 + 30; + popup.css({ + 'width': popWidth + 'px', + 'left': (windowWidth / 2 - popWidth / 2) + 'px', + 'top': (windowHeight / 2 - popup.height() / 2) + 'px' + }); + }, + + /** + * Add UI events + */ + addEvents: function Ui_addEvents() { + var self = this; + + document.addEventListener('webkitvisibilitychange', function () { + if (document.webkitVisibilityState === 'visible') { + if (self.infoPopupVisibility) { + return; + } + self.toggleInfoPopup(); + self.refreshSelectAllStatus(); + app.refreshCurrentPage(true); + } + }); + + window.addEventListener('tizenhwkey', function (e) { + var uri = $('#navbar span+span').attr('uri'); + if (e.keyName === 'back') { + if (self.infoPopupVisibility) { + return; + } else if ($.mobile.popup.active) { + $.mobile.popup.active.close(); + } else if (self.editMode === true) { + self.handleCancelEditAction(); + } else if (!uri) { + if (app.ui.root === false) { + app.ui.root = true; + $('#fileList').empty(); + app.ui.prepareFolderRow(0, 'root'); + app.currentPath = 'root'; + } else { + tizen.application.getCurrentApplication().exit(); + } + } else { + if (!app.ui.root) { + app.goLevelUp(); + } + } + } + }); + + $(window).resize(function () { + $.mobile.activePage.page('refresh'); + }); + + // touch events for all nodes + $('ul#fileList') + .on('click', 'li.levelUp', function () { + if (self.editMode === true) { + self.handleCancelEditAction(); + } + app.goLevelUp(); + }) + .on('click', 'li.node', function (e) { + e.preventDefault(); + e.stopPropagation(); + self.handleNodeClick($(this), true); + }) + .on('change', 'input[type=checkbox]', function (e) { + self.handleNodeClick($(this).closest('li.node'), false); + }) + .on('touchstart', 'li', function (event) { + $(this).addClass(self.CSS_GRADIENT_CLASS); + }) + .on('touchend touchmove', 'li', function (event) { + $(this).removeClass(self.CSS_GRADIENT_CLASS); + }); + + $('.selectAll input').on( + 'change', + this.handleSelectAllChange.bind(this) + ); + + // navbar + $('#navbar').on('click', 'span', function () { + var uri = $(this).attr('uri'); + if (uri === 'home') { + if (app.currentPath !== '') { + app.displayStorages(); + } + } else if (uri === app.model.currentPath) { + app.displayFolder(uri, true); + } else { + if (self.editMode === true) { + self.handleCancelEditAction(); + } + app.displayFolder(uri); + } + }); + + // level up + $('#levelUpBtn').on('click', function () { + if (self.editMode === true) { + self.handleCancelEditAction(); + } + app.goLevelUp(); + }); + + $('#homeBtn').on('click', app.displayStorages.bind(app)); + + // edit action + $('#editActionBtn').on('click', this.handleEditAction.bind(this)); + + // delete action + $('#deleteActionBtn').on( + 'click', + this.handleDeleteAction.bind(this) + ); + + // cancel edit + $('#cancelActionBtn').on('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + self.handleCancelEditAction(); + }); + + // copy action + $('#copyActionBtn').on('click', this.handleCopyAction.bind(this)); + + // move action + $('#moveActionBtn').on('click', this.handleMoveAction.bind(this)); + + // paste action + $('a#pasteActionBtn').on('click', function () { + if (!self.infoPopupVisibility) { + self.toggleInfoPopup(app.pasteClipboard.bind(app)); + } + $('#morePopup').popup('close'); + }); + + // remove active class + $('[data-role = "tabbar"] li > a').on('click', function () { + $(this).removeClass('ui-focus, ui-btn-active'); + }); + // exit + $('.ui-myExit').on('click', app.exit); + + // add folder popup actions + $('#addFolderPopup').on('popupafterclose', function () { + // clear input value + $('#newFolderName').val('New folder'); + }); + + $('#newFolderName').on('focus', function () { + if ($(this).attr('value') === 'New folder') { + $(this).attr('value', ''); + } + }); + + $('#saveNewFolder').on('click', this.saveNewFolder.bind(this)); + $('#newFolderForm').on('submit', this.saveNewFolder.bind(this)); + }, + + saveNewFolder: function Ui_saveNewFolder(e) { + var folderName = $('#newFolderName').val(), status = true, + open = function () { + $('#addFolderPopup').popup('open', { + positionTo: 'window' + }); + }, + self = this, + buttons = $('#addFolderPopup .ui-popup-button-bg a'), + aPopup; + e.preventDefault(); + e.stopPropagation(); + buttons.addClass('ui-disabled'); + $('#addFolderPopup').one('popupafterclose', function () { + if (folderName === '') { + self.alertPopup('Empty folder name', open); + status = false; + } else if (folderName.match(/[\*\.\/\\\?\"\'\:<>|]/)) { + self.alertPopup('The following special characters ' + + 'are not allowed: *./\\?:<>|\'"', open); + status = false; + } else { + status = app.createDir(folderName, open); + } + buttons.removeClass('ui-disabled'); + }); + aPopup = $.mobile.popup.active; + if ( + aPopup && aPopup.element.attr('id') === 'addFolderPopup' + ) { + aPopup.close(); + } + return status; + }, + + toggleInfoPopup: function (callback) { + var overlay = $('#overlay'); + if (this.infoPopupVisibility) { + overlay.hide(); + document.onkeydown = null; + } else { + document.onkeydown = function () { return false; }; + overlay.show(); + } + this.infoPopupVisibility = !this.infoPopupVisibility; + if (callback instanceof Function) { + setTimeout(callback, 200); + } + }, + + popupHardClose: function () { + var popup = $.mobile.popup.active; + + if (popup) { + popup.element.off(); + popup.close(); + } + }, + + alertPopup: function (text, callback) { + $('#alertPopup .text').text(text); + $('#alertPopup').popup('open', {'positionTo': 'window'}); + if (callback instanceof Function) { + $('#alertPopup').one('popupafteropen', function () { + callback(); + }); + } + if (this.infoPopupVisibility) { + this.toggleInfoPopup(); + } + }, + + confirmPopup: function (text, confirmCallback, completeCallback) { + var popup = $('#confirmPopup'); + popup.find('.text').text(text); + popup.popup('open', {positionTo: 'window'}); + popup.find('.confirm').one('click', function () { + if (confirmCallback instanceof Function) { + confirmCallback(); + } + }); + if (completeCallback instanceof Function) { + popup.one('popupafterclose', function () { + completeCallback(); + }); + } + }, + + clearTabbars: function Ui_clearTabbars() { + $('[data-role = "tabbar"] li > a') + .removeClass('ui-focus, ui-btn-active'); + }, + + /** + * Handler for node click + * @param {File} node + * @param {boolean} toggleCheckbox + */ + handleNodeClick: function Ui_handleNodeClick(node, toggleCheckbox) { + if (this.root) { + app.model.loadInternalStorages(function () { + app.displayStorages(); + }); + this.root = false; + } else if (this.editMode === true) { + //if edit mode is on toggle checkbox state + if (toggleCheckbox === true) { + this.toggleCheckBoxState(node); // select the checkbox + } + + this.refreshSelectAllStatus(); + this.refreshEditMenu(); + } else if (node.hasClass('folder')) { + // otherwise display folder + app.displayFolder(node.attr('uri')); + } else { + // file + app.openFile(node.attr('uri'), node.attr('fullUri')); + } + }, + + /** + * Handler for edit action + */ + handleEditAction: function Ui_handleEditAction() { + this.editMode = true; + this.clearTabbars(); + $('.standardTabbar').hide(); + $('div.editTabbar').show(); + this.disableControlBarButtons( + $('div.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + $('#fileList .folder .nodename, #fileList > li > span.nodename') + .animate({'width': '70%'}); + this.showEditCheckBoxes(); + }, + + /** + * Handler for cancel edit action + */ + handleCancelEditAction: function Ui_handleCancelEditAction(emptyList) { + this.editMode = false; + this.clearTabbars(); + $('div.editTabbar').hide(); + $('.standardTabbar').show(); + $('#fileList .folder .nodename, #fileList > li > span.nodename') + .animate({'width': '75%'}); + this.hideEditCheckBoxes(); + if (this.isFileListEmpty() || emptyList) { + $('#editActionBtn').addClass('vhidden').blur(); + } + }, + + /** + * Handler for delete action + */ + handleDeleteAction: function Ui_handleDeleteAction(e) { + var nodesToDelete = [], + $rowElement, + self = this, + conf, + listLength = $('ul#fileList li.node').length; + + e.stopPropagation(); + e.preventDefault(); + + this.confirmPopup('Selected nodes will be deleted. Are you sure?', + function () { + $('ul#fileList input:checkbox:checked') + .each(function (index) { + $rowElement = $(this).closest('li'); + nodesToDelete.push({ + id: $rowElement.attr('id'), + uri: $rowElement.attr('uri'), + name: $rowElement.attr('label'), + folder: $rowElement.hasClass('folder') + }); + } + ); + if (nodesToDelete.length > 0) { + app.deleteNodes(nodesToDelete); + self.scrollContentTo(0); + $('ul#fileList input:checkbox:checked').remove(); + if (nodesToDelete.length === listLength) { + self.handleCancelEditAction(true); + } else { + self.refreshEditMenu(); + } + } + }, + function () { + self.clearTabbars(); + }); + }, + + /** + * Handler for copy action + */ + handleCopyAction: function Ui_handleCopyAction(e) { + var paths = []; + + e.stopPropagation(); + e.preventDefault(); + + if (this.editMode === true) { + $('ul#fileList input:checkbox:checked').each(function (index) { + paths.push($(this).closest('li').attr('uri')); + }); + app.saveToClipboard(paths, app.clipboard.COPY_MODE_ID); + } + }, + + /** + * Handler for move action + */ + handleMoveAction: function Ui_handleMoveAction(e) { + var paths = []; + + e.stopPropagation(); + e.preventDefault(); + + if (this.editMode === true) { + $('ul#fileList input:checkbox:checked').each(function (index) { + paths.push($(this).closest('li').attr('uri')); + }); + app.saveToClipboard(paths, app.clipboard.MOVE_MODE_ID); + } + }, + + /** + * Handler for paste action + */ + handlePasteAction: function Ui_handlePasteAction() { + }, + + /** + * Scrolls content to the specified position + */ + scrollContentTo: function scrollContentTo(value) { + $('#main [data-role="content"]').scrollview('scrollTo', 0, value); + }, + + /** + * @param {FileSystemStorage[]} nodes Storage elements + */ + displayStorages: function Ui_displayStorages(nodes) { + var len = nodes.length, nodeName, i; + + this.updateNavbar(''); + $('#fileList').empty(); + + for (i = 0; i < len; i = i + 1) { + nodeName = nodes[i].label; + if (nodeName !== '' + && (nodes[i].type === 0 || nodes[i].type === 'INTERNAL') + && nodeName.indexOf('wgt-') === -1 + && $.inArray(nodeName, this.lockedFolders) === -1) { + if (!this.root) { + app.model.isStorageExists( + nodeName, + app.ui.prepareFolderRow.bind(app.ui, i, nodeName), + null + ); + } else { + this.prepareFolderRow(i, nodeName); + } + } + } + + $('#levelUpBtn').addClass('vhidden'); + $('#homeBtn').addClass('vhidden'); + + $('#editActionBtn').addClass('vhidden').blur(); + $('#moreActionBtn').addClass('vhidden').blur(); + $('h1#mainTitle').html('Media'); + + if (this.editMode) { + this.scrollContentTo(0); + } + + this.resetDefaultCheckBoxLabelEvents(); + this.hideSelectAllArea(); + this.handleCancelEditAction(); + + if (this.infoPopupVisibility) { + this.toggleInfoPopup(); + } + }, + + prepareFolderRow: function (id, name) { + if (!this.root || name === 'root') { + $(this.templateManager.get('folderRow', { + id: id, + name: name, + uri: name, + fullUri: name, + })).appendTo('#fileList'); + } + }, + + /** + * File comparison function using their names (case insensitive) + * + * @param {File} x + * @param {File} y + * @returns {Number} + */ + fileComparison: function fileComparison(x, y) { + if (x.isDirectory !== y.isDirectory) { + return x.isDirectory ? -1 : 1; + } + var a = x.name.toLowerCase(), + b = y.name.toLowerCase(); + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; + }, + + /** + * renders node list for folder + * @param {string} folderName + * @param {File[]} nodes + * @param {bool} [refresh=false] + */ + displayFolder: function Ui_displayFolder(folderName, nodes, refresh) { + var len = nodes.length, + listElements = [this.templateManager.get('levelUpRow')], + nodeName, + checkedRows = [], + checkedRowsLen, + i; + refresh = refresh || false; + + // update title + this.updateTitle( + this.templateManager.modifiers.escape(folderName) + ); + // update navbar + this.updateNavbar( + this.templateManager.modifiers.escape(folderName) + ); + this.refreshPasteActionBtn(); + + nodes.sort(this.fileComparison); + + // render nodes + for (i = 0; i < len; i = i + 1) { + nodeName = nodes[i].name; + if (nodeName !== '') { + if (nodes[i].isDirectory) { + // folder + listElements.push(this.templateManager.get( + 'folderRow', + { + id: i, + name: nodeName, + uri: nodes[i].fullPath, + fullUri: nodes[i].toURI() + } + )); + } else { + // file + listElements.push(this.templateManager.get( + 'fileRow', + { + id: i, + name: nodeName, + uri: nodes[i].fullPath, + fullUri: nodes[i].toURI(), + thumbnailURI: this.helpers.getThumbnailURI( + nodeName, + nodes[i] + ) + } + )); + } + } + } + + if (listElements.length === 1) { + // set content for empty folder + listElements.push(this.templateManager.get('emptyFolder')); + // hide edit button for empty content + $('#editActionBtn').addClass('vhidden').blur(); + this.handleCancelEditAction(); + } else { + $('#editActionBtn').removeClass('vhidden'); + } + + // scroll to top of list + this.scrollContentTo(0); + + $('#levelUpBtn').removeClass('vhidden'); + $('#homeBtn').removeClass('vhidden'); + $('#moreActionBtn').removeClass('vhidden'); + + if (refresh === true && this.editMode === true) { + $.each($('#fileList .ui-checkbox input:checked'), function () { + checkedRows.push($(this).closest('li').attr('uri')); + }); + } + + // update file list + $('#fileList').html(listElements.join('')) + .trigger('refresh') + .trigger('create'); + + if (this.editMode === true) { + $('.selectAll').show(); + $('#fileList .folder .nodename, #fileList > li > span.nodename') + .css('width', '70%'); + $('ul#fileList > li').css('paddingLeft', '2rem'); + $('.my-ui-checkbox').removeClass('hidden'); + + if (refresh === true) { + checkedRowsLen = checkedRows.length; + if (checkedRowsLen) { + if ( + checkedRowsLen !== + $('#fileList .ui-checkbox input').length + ) { + this.setCheckboxValue('.selectAll input', false); + } + // restore checked checkboxes + for (i = 0; i < checkedRowsLen; i += 1) { + this.setCheckboxValue( + '#' + + $('#fileList [uri="' + + checkedRows[i] + + '"]').attr('id') + + ' input:checkbox', + 'checked' + ); + } + + // if there are no checked checkboxes + if (!$('#fileList .ui-checkbox input:checked').length) { + this.clearDeleteMode(); + } + } else { + this.clearDeleteMode(); + } + } + } else { + $('.selectAll').hide(); + $('#fileList .folder .nodename, #fileList > li > span.nodename') + .css('width', '75%'); + $('ul#fileList > li').css('paddingLeft', '0'); + $('.my-ui-checkbox').addClass('hidden'); + this.clearDeleteMode(); + } + if (!refresh) { + this.hideSelectAllArea(); + } + + if (this.infoPopupVisibility) { + this.toggleInfoPopup(); + } + + this.refreshSelectAllStatus(); + }, + + /** + * Clear confirm popup and disable action buttons + */ + clearDeleteMode: function Ui_clearDeleteMode() { + var aPopup = $.mobile.popup.active; + if (aPopup && aPopup.element.attr('id') === 'confirmPopup') { + $.mobile.popup.active.close(); + } + this.disableControlBarButtons( + $('div.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + }, + + /** + * Toggle a checkbox associated with a given list element + * @param {jQuery} listElement + */ + toggleCheckBoxState: function Ui_toggleCheckBoxState(listElement) { + var checkboxInput = null; + + checkboxInput = listElement.find('form > div.ui-checkbox input'); + this.setCheckboxValue( + checkboxInput, + !checkboxInput.attr('checked') + ); + }, + + /** + * Shows item checkboxes and topbar with select all option + */ + showEditCheckBoxes: function Ui_showEditCheckBoxes() { + var self = this; + + this.showSelectAllArea(); + + $('ul#fileList > li').animate( + {paddingLeft: '2rem'}, + 500, + 'swing', + function () { + self.editMode = true; + $('.my-ui-checkbox').removeClass('hidden'); + } + ); + }, + + /** + * Hides item checkboxes and topbar with select all option + * All checkboxes are auto uncheked + */ + hideEditCheckBoxes: function Ui_hideEditCheckBoxes() { + var self = this; + + this.hideSelectAllArea(); // hide select all option topbar + + $('ul#fileList > li').animate( + {paddingLeft: '0'}, + 200, + 'swing', + function () { + $('.my-ui-checkbox').addClass('hidden'); + $.mobile.activePage.page('refresh'); + } + ); + + // uncheck all checkboxes + $('ul#fileList input[type=checkbox]').each(function (index) { + self.setCheckboxValue(this, false); + }); + + //uncheck select all input + this.setCheckboxValue('.ui-header .selectAll input', false); + }, + + /** + * Save current header and content height + */ + saveHeights: function Ui_saveHeights() { + this.currentHeaderHeight = $('#main div[data-role="header"]') + .height(); + this.currentScrollPosition = $('#main div[data-role="content"]') + .scrollview('getScrollPosition').y; + }, + + /** + * Changes content scroll position after showing/hiding selectAllArea + */ + changeContentScrollPosition: function Ui_changeContentScrollPosition() { + var diff, + contentHeight; + if (this.currentScrollPosition !== 0) { + contentHeight = $('#main div[data-role="header"]').height(); + diff = contentHeight - this.currentHeaderHeight; + $('#main div[data-role="content"]') + .scrollview( + 'scrollTo', + 0, + -(this.currentScrollPosition + diff) + ); + } + }, + + /** + * Shows topbar with select all option + */ + showSelectAllArea: function Ui_showSelectAllArea() { + this.saveHeights(); + $('.selectAll').show(); + $.mobile.activePage.page('refresh'); + this.changeContentScrollPosition(); + }, + + /** + * Hides topbar with select all option + */ + hideSelectAllArea: function Ui_hideSelectAllArea() { + this.saveHeights(); + $('.selectAll').hide(); + $.mobile.activePage.page('refresh'); + this.changeContentScrollPosition(); + }, + + /** + * Enable specified options for tabbar + * @param {object} tabbar + * @param {array} enableOptions options to enable + */ + enableControlBarButtons: function Ui_enableControlBarButtons( + tabbar, + enableOptions + ) { + var i = 0, + len = enableOptions.length; + + for (i = 0; i < len; i += 1) { + tabbar.tabbar('enable', enableOptions[i]); + } + }, + + /** + * Disable specified options for tabbar + * @param {object} tabbar controlbar + * @param {array} disableOptions options to enable + */ + disableControlBarButtons: function Ui_disableControlBarButtons( + tabbar, + disableOptions + ) { + var i = 0, + len = disableOptions.length; + + for (i = 0; i < len; i += 1) { + tabbar.tabbar('disable', disableOptions[i]); + } + }, + + /** + * @param {string} path + */ + updateTitle: function Ui_updateTitle(path) { + var regexp = new RegExp('([^\/])+$', 'g'), + match = path.match(regexp), + lastDir = match[0] || '(dir)'; + $('h1#mainTitle').html(lastDir); + }, + + /** + * @param {string} path + */ + updateNavbar: function Ui_updateNavbar(path) { + var html = ['Media'], + splitted, + len, + i; + + if (typeof path === 'string' && path !== '') { + splitted = path.split('/'); + len = splitted.length; + + for (i = 0; i < len; i = i + 1) { + html.push( + '' + + splitted[i] + + '' + ); + } + } + $('#navbar').html(html.join(' > ')); + }, + + handleSelectAllChange: function Ui_handleSelectAllChange() { + var $selectAllInput = $('.ui-header .selectAll .ui-checkbox input'), + self = this; + $selectAllInput.data('checkboxradio').refresh(); + + if ($selectAllInput.is(':checked')) { + // check all checkboxes + $('ul#fileList input[type=checkbox]').each(function (index) { + self.setCheckboxValue(this, true); + }); + + this.enableControlBarButtons( + $('.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + } else { + $('ul#fileList input[type=checkbox]').each(function (index) { + self.setCheckboxValue(this, false); + }); + + this.disableControlBarButtons( + $('.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + } + }, + + /** + * + */ + refreshSelectAllStatus: function Ui_refreshSelectAllStatus() { + var $selectAllInput = $('.ui-header .selectAll .ui-checkbox input'); + // update status of select all checkbox + if ($('ul#fileList input:checkbox:not(:checked)').length === 0) { + // all nodes checked + this.setCheckboxValue($selectAllInput, true); + } else { + // some node is not checked + this.setCheckboxValue($selectAllInput, false); + } + }, + + /** + * Refresh activity of edit menu + */ + refreshEditMenu: function () { + if ($('ul#fileList input:checkbox:checked').length > 0) { + this.enableControlBarButtons( + $('.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + } else { + this.disableControlBarButtons( + $('.editTabbar'), + [ + this.EDIT_TABBAR_DELETE_ACTION, + this.EDIT_TABBAR_COPY_ACTION, + this.EDIT_TABBAR_MOVE_ACTION + ] + ); + } + }, + + /** + * Unbinds default events for checkbox labels + */ + resetDefaultCheckBoxLabelEvents: function Ui_resetLabelEvents() { + $('div.ui-checkbox > label') + .unbind('vmousedown') + .unbind('vmouseup') + .unbind('vmouseover') + .unbind('vclick'); + }, + + /** + * Remove html node element from list + * @param {string} nodeUri node uri + */ + removeNodeFromList: function Ui_removeNodeFromList(nodeUri) { + $('ul#fileList > li[uri="' + nodeUri.replace(/"/g, '\"') + '"]') + .remove(); + + // hide select All checkbox if removed all elements; + if ($('ul#fileList > li.node').length === 0) { + this.hideSelectAllArea(); + } + }, + + /** + * Enable/Disable + */ + refreshPasteActionBtn: function Ui_refreshPasteActionBtn() { + if (app.emptyClipboard()) { + $('#pasteActionBtnRow').addClass('hidden'); + } else { + $('#pasteActionBtnRow').removeClass('hidden'); + } + }, + + isFileListEmpty: function Ui_isFileListEmpty() { + return ($('ul#fileList').children('.node').length < 1); + }, + + setCheckboxValue: function Ui_setCheckboxValue(element, value) { + var $element = $(element), + checkboxradio = $element.data('checkboxradio'); + + $(element).attr('checked', value); + if (checkboxradio) { + checkboxradio.refresh(); + } + + } + }; }()); diff --git a/project/js/app.ui.templateManager.js b/project/js/app.ui.templateManager.js index e2a440a..c880c5e 100644 --- a/project/js/app.ui.templateManager.js +++ b/project/js/app.ui.templateManager.js @@ -1,136 +1,187 @@ +/* +* Copyright 2013 Samsung Electronics Co., Ltd +* +* Licensed under the Flora License, Version 1.1 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://floralicense.org/license/ +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + /*global tizen, $, app, ModifierManager */ + /** - * @class TemplateManager - */ +* @class TemplateManager +*/ function TemplateManager() { - 'use strict'; - this.init(); + 'use strict'; + this.init(); } (function () { // strict mode wrapper - 'use strict'; - TemplateManager.prototype = { - - /** - * Template cache - */ - cache: {}, - - /** - * UI module initialisation - */ - init: function init() { - this.modifiers = new ModifierManager().getAll(); - }, - - /** - * Returns template html (from cache) - * @param {string} tplName - * @param {string} tplParams - */ - get: function TemplateManager_get(tplName, tplParams) { - if (this.cache[tplName] !== undefined) { - return this.getCompleted(this.cache[tplName], tplParams); - } - return ''; - }, - - /** - * Load templates to cache - * @param {string} tplNames - * @param {function} onSuccess - */ - loadToCache: function TemplateManager_loadToCache(tplNames, onSuccess) { - var self = this, - cachedTemplates = 0, - tplName, - tplPath; - - if ($.isArray(tplNames)) { - - // for each template - $.each(tplNames, function (index, fileName) { - - // cache template html - if (self.cache[fileName] === undefined) { - tplName = [fileName, app.config.get('templateExtension')].join(''); - tplPath = [app.config.get('templateDir'), tplName].join('/'); - - $.ajax({ - url: tplPath, - cache: true, - dataType: 'html', - async: true, - success: function (data) { - // increase counter - cachedTemplates += 1; - - // save to cache - self.cache[fileName] = data; - - // if all templates are cached launch callback - if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') { - onSuccess(); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - console.error('templateManagerError: ' + errorThrown); - } - }); - } else { - // template is already cached - cachedTemplates += 1; - // if all templates are cached launch callback - if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') { - onSuccess(); - } - } - }); - - } - }, - - /** - * Returns template completed by specified params - * @param {string} tplHtml - * @param {string} tplParams - */ - getCompleted: function TemplateManager_getCompleted(tplHtml, tplParams) { - var tplParam; - - for (tplParam in tplParams) { - if (tplParams.hasOwnProperty(tplParam)) { - tplHtml = this.passThruModifiers(tplHtml, tplParam, tplParams[tplParam]); - } - } - - return tplHtml; - }, - - passThruModifiers: function (tplHtml, tplParam, content) { - var regModOn = new RegExp('%' + tplParam + '\\|([a-zA-Z]){1,}%', 'g'), - regModOff = new RegExp(['%', tplParam, '%'].join(''), 'g'), - regModGet = new RegExp('%' + tplParam + '\\|(.+?)%'), - specRegExp = new RegExp('\\$','g'), - modifier; - - if (content && (typeof content === 'string')) { - content = content.replace(specRegExp, '$$$$'); - } - - if (regModOn.test(tplHtml)) { - modifier = tplHtml.match(regModGet)[1]; - try { - content = this.modifiers[modifier](content); - } catch (error) { - console.error('unknown modifier: ' + modifier); - } - tplHtml = tplHtml.replace(regModOn, content); - } else { - tplHtml = tplHtml.replace(regModOff, content); - } - return tplHtml; - } - }; - -}()); \ No newline at end of file + 'use strict'; + + TemplateManager.prototype = { + + /** + * Template cache + */ + cache: {}, + + /** + * UI module initialisation + */ + init: function init() { + this.modifiers = new ModifierManager().getAll(); + }, + + /** + * Returns template html (from cache) + * @param {string} tplName + * @param {string} tplParams + */ + get: function TemplateManager_get(tplName, tplParams) { + if (this.cache[tplName] !== undefined) { + return this.getCompleted(this.cache[tplName], tplParams); + } + return ''; + }, + + /** + * Load templates to cache + * @param {string} tplNames + * @param {function} onSuccess + */ + loadToCache: function TemplateManager_loadToCache(tplNames, onSuccess) { + var self = this, + cachedTemplates = 0, + tplName, + tplPath; + + if ($.isArray(tplNames)) { + + // for each template + $.each(tplNames, function (index, fileName) { + + // cache template html + if (self.cache[fileName] === undefined) { + tplName = [ + fileName, + app.config.get('templateExtension') + ].join(''); + tplPath = [ + app.config.get('templateDir'), + tplName + ].join('/'); + + $.ajax({ + url: tplPath, + cache: true, + dataType: 'html', + async: true, + success: function (data) { + // increase counter + cachedTemplates += 1; + + // save to cache + self.cache[fileName] = data; + + // if all templates are cached launch callback + if ( + cachedTemplates >= tplNames.length && + typeof onSuccess === 'function' + ) { + onSuccess(); + } + }, + error: function (jqXHR, textStatus, errorThrown) { + console.error( + 'templateManagerError: ' + + errorThrown + ); + } + }); + } else { + // template is already cached + cachedTemplates += 1; + // if all templates are cached launch callback + if ( + cachedTemplates >= tplNames.length && + typeof onSuccess === 'function' + ) { + onSuccess(); + } + } + }); + + } + }, + + /** + * Returns template completed by specified params + * @param {string} tplHtml + * @param {string} tplParams + */ + getCompleted: function TemplateManager_getCompleted( + tplHtml, + tplParams + ) { + var tplParam; + + for (tplParam in tplParams) { + if (tplParams.hasOwnProperty(tplParam)) { + tplHtml = this.passThruModifiers( + tplHtml, + tplParam, + tplParams[tplParam] + ); + } + } + + return tplHtml; + }, + + /** + * Returns template completed by specified params + * including modifiers + * @param {string} tplHtml + * @param {string} tplParams + * @param {string} content + */ + passThruModifiers: function (tplHtml, tplParam, content) { + var regModOn = new RegExp('%' + tplParam + '(\\|(.+?)){1,}%', 'g'), + regModOff = new RegExp(['%', tplParam, '%'].join(''), 'g'), + regModGet = new RegExp('%' + tplParam + '\\|(.+?)%'), + regModPut = new RegExp('%' + tplParam + '\\|(.+?)%', 'g'), + specRegExp = new RegExp('\\$', 'g'), + modifiers, + i; + + if (content && (typeof content === 'string')) { + content = content.replace(specRegExp, '$$$$'); + } + + if (regModOn.test(tplHtml)) { + modifiers = tplHtml.match(regModGet)[1].split('|'); + for (i in modifiers) { + if (this.modifiers[modifiers[i]] instanceof Function) { + content = this.modifiers[modifiers[i]](content); + } else { + console.error('unknown modifier: ' + modifiers[i]); + } + } + tplHtml = tplHtml.replace(regModPut, content); + } + tplHtml = tplHtml.replace(regModOff, content); + + return tplHtml; + } + }; + +}()); diff --git a/project/js/app.ui.templateManager.modifiers.js b/project/js/app.ui.templateManager.modifiers.js index 95e9d0a..16264a9 100644 --- a/project/js/app.ui.templateManager.modifiers.js +++ b/project/js/app.ui.templateManager.modifiers.js @@ -1,47 +1,63 @@ +/* + * Copyright 2013 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /*global $*/ /** * @class ModifierManager */ function ModifierManager() { - 'use strict'; - this.init(); + 'use strict'; + this.init(); } (function () { - 'use strict'; - ModifierManager.prototype = { + 'use strict'; + ModifierManager.prototype = { - /** - * UI module initialisation - */ - init: function () { - }, + /** + * UI module initialisation + */ + init: function () { + }, - /** - * @return modifiers object - */ - getAll: function () { - return this.modifiers; - }, + /** + * @return modifiers object + */ + getAll: function () { + return this.modifiers; + }, - /** - * modifiers definitions - */ - modifiers: { - escape: function escape(str) { - return $('').text(str).html(); - }, - escapeEncies: function escapeEncies(str) { - var tagsToReplace = { - '&': '&', - '<': '<', - '>': '>', - '"': '"' - }; - return str.replace(/[&<>\"]/g, function(tag) { - return tagsToReplace[tag] || tag; - }); - } - } - }; + /** + * modifiers definitions + */ + modifiers: { + escape: function escape(str) { + return $('').text(str).html(); + }, + escapeEncies: function escapeEncies(str) { + var tagsToReplace = { + '&': '&', + '<': '<', + '>': '>', + '"': '"' + }; + return str.replace(/[&<>\"]/g, function (tag) { + return tagsToReplace[tag] || tag; + }); + } + } + }; }()); \ No newline at end of file diff --git a/project/js/main.js b/project/js/main.js index 360b951..2f53df2 100644 --- a/project/js/main.js +++ b/project/js/main.js @@ -30,49 +30,55 @@ var app = null; (function () { // strict mode wrapper - 'use strict'; + 'use strict'; - ({ - /** - * Loader init - load the App constructor - */ - init: function init() { - var self = this; - $.getScript('js/app.js') - .done(function () { - // once the app is loaded, create the app object - // and load the libraries - app = new App(); - self.loadLibs(); - }) - .fail(this.onGetScriptError); - }, + ({ + /** + * Loader init - load the App constructor + */ + init: function init() { + var self = this; + $.getScript('js/app.js') + .done(function () { + // once the app is loaded, create the app object + // and load the libraries + app = new App(); + self.loadLibs(); + }) + .fail(this.onGetScriptError); + }, - /** - * Load dependencies - */ - loadLibs: function loadLibs() { - var loadedLibs = 0; - if ($.isArray(app.requires)) { - $.each(app.requires, function (index, filename) { - $.getScript(filename) - .done(function () { - loadedLibs += 1; - if (loadedLibs >= app.requires.length) { - // All dependencies are loaded - initialise the app - app.init(); - } - }) - .fail(this.onGetScriptError); - }); - } - }, + /** + * Load dependencies + */ + loadLibs: function loadLibs() { + var loadedLibs = 0; + if ($.isArray(app.requires)) { + $.each(app.requires, function (index, filename) { + $.getScript(filename) + .done(function () { + loadedLibs += 1; + if (loadedLibs >= app.requires.length) { + // All dependencies are loaded + // initialise the app + app.init(); + } + }) + .fail(this.onGetScriptError); + }); + } + }, - /** - * Handle ajax errors - */ - onGetScriptError: function onGetScriptError(e, jqxhr, setting, exception) { - app.ui.alertPopup('An error occurred: ' + e.message); - } - }).init(); // run the loader + /** + * Handle ajax errors + */ + onGetScriptError: function onGetScriptError( + e, + jqxhr, + setting, + exception + ) { + app.ui.alertPopup('An error occurred: ' + e.message); + } + }).init(); // run the loader }()); diff --git a/project/templates/fileRow.tpl b/project/templates/fileRow.tpl index 38f6b03..4374b04 100644 --- a/project/templates/fileRow.tpl +++ b/project/templates/fileRow.tpl @@ -1,5 +1,5 @@
  • - - - %name|escape% + + + %name|escape%
  • \ No newline at end of file diff --git a/project/templates/folderRow.tpl b/project/templates/folderRow.tpl index ba82018..b77ca46 100644 --- a/project/templates/folderRow.tpl +++ b/project/templates/folderRow.tpl @@ -1,6 +1,6 @@
  • - - - %name|escape% - + + + %name|escape% +
  • \ No newline at end of file diff --git a/project/templates/levelUpRow.tpl b/project/templates/levelUpRow.tpl index ddbc7cf..9a71e88 100644 --- a/project/templates/levelUpRow.tpl +++ b/project/templates/levelUpRow.tpl @@ -1,3 +1,3 @@
  • - .. + ..
  • \ No newline at end of file diff --git a/project/templates/main.tpl b/project/templates/main.tpl index d5d17e7..ed01f54 100644 --- a/project/templates/main.tpl +++ b/project/templates/main.tpl @@ -1,83 +1,84 @@ -
    \ No newline at end of file -- 2.7.4
    -
    -

    -
    Home - Up - - -
    +
    +
    +

    + Home + Up + + +
    -
    -
      -
      -
      -

      Add new folder

      -

      -
      -
      - -
      -
      -
      - Cancel - Save -
      -
      -
      -

      -
      - OK -
      -
      -
      -
      -

      -
      -
      - CANCEL - OK -
      -
      -
      +
      +
        +
        +
        +

        Add new folder

        +

        +
        +
        + +
        +
        +
        + Cancel + Save +
        +
        +
        +

        +
        + OK +
        +
        +
        +
        +

        +
        +
        + CANCEL + OK +
        +
        +
        -
        -
        -
        - -
        - -
        -
        - - - - - - - -
        - New folder -
        - Paste to folder -
        -
        -
        -
        \ No newline at end of file +
        +
        +
        + +
        + +
        +
        + + + + + + + +
        + New folder +
        + Paste to folder +
        +
        +
        +