From 9c94ce2ec0be8f9f170d039b06cd01858a83db8b Mon Sep 17 00:00:00 2001 From: Piotr Dabrowski Date: Wed, 2 Oct 2013 10:19:12 +0200 Subject: [PATCH] application sources from tizen_2.2 Change-Id: I29cf7c8e5cf2861cb9e924981263e6de99c54e7d --- description.xml | 10 + description.xsl | 97 +++ filemanager-snapshot.png | Bin 0 -> 10000 bytes project/.project | 54 ++ project/AUTHORS | 6 + project/LICENSE.Flora | 206 ++++++ project/NOTICE | 4 + project/config.xml | 13 + project/css/style.css | 245 +++++++ project/icon.png | Bin 0 -> 15199 bytes project/images/00_winset_Back.png | Bin 0 -> 3225 bytes project/images/etc.png | Bin 0 -> 1292 bytes project/images/folder.png | Bin 0 -> 743 bytes project/images/img.png | Bin 0 -> 1454 bytes project/images/loader.png | Bin 0 -> 1552 bytes project/images/music.png | Bin 0 -> 1621 bytes project/images/pdf.png | Bin 0 -> 4794 bytes project/images/ppt.png | Bin 0 -> 5417 bytes project/images/text.png | Bin 0 -> 4023 bytes project/images/video.png | Bin 0 -> 2040 bytes project/index.html | 24 + project/js/app.clipboard.js | 147 ++++ project/js/app.config.js | 28 + project/js/app.helpers.js | 162 +++++ project/js/app.js | 278 +++++++ project/js/app.model.js | 352 +++++++++ project/js/app.systemIO.js | 261 +++++++ project/js/app.ui.js | 961 +++++++++++++++++++++++++ project/js/app.ui.templateManager.js | 136 ++++ project/js/app.ui.templateManager.modifiers.js | 47 ++ project/js/main.js | 78 ++ project/templates/emptyFolder.tpl | 1 + project/templates/fileRow.tpl | 5 + project/templates/folderRow.tpl | 6 + project/templates/levelUpRow.tpl | 3 + project/templates/main.tpl | 83 +++ tizen-app-template.xml | 12 + tizen_32.png | Bin 0 -> 4563 bytes tizen_64.png | Bin 0 -> 6849 bytes 39 files changed, 3219 insertions(+) create mode 100755 description.xml create mode 100755 description.xsl create mode 100644 filemanager-snapshot.png create mode 100644 project/.project create mode 100644 project/AUTHORS create mode 100644 project/LICENSE.Flora create mode 100644 project/NOTICE create mode 100644 project/config.xml create mode 100644 project/css/style.css create mode 100644 project/icon.png create mode 100644 project/images/00_winset_Back.png create mode 100755 project/images/etc.png create mode 100755 project/images/folder.png create mode 100755 project/images/img.png create mode 100644 project/images/loader.png create mode 100755 project/images/music.png create mode 100755 project/images/pdf.png create mode 100755 project/images/ppt.png create mode 100755 project/images/text.png create mode 100755 project/images/video.png create mode 100644 project/index.html create mode 100644 project/js/app.clipboard.js create mode 100644 project/js/app.config.js create mode 100644 project/js/app.helpers.js create mode 100644 project/js/app.js create mode 100644 project/js/app.model.js create mode 100644 project/js/app.systemIO.js create mode 100644 project/js/app.ui.js create mode 100644 project/js/app.ui.templateManager.js create mode 100644 project/js/app.ui.templateManager.modifiers.js create mode 100644 project/js/main.js create mode 100644 project/templates/emptyFolder.tpl create mode 100644 project/templates/fileRow.tpl create mode 100644 project/templates/folderRow.tpl create mode 100644 project/templates/levelUpRow.tpl create mode 100644 project/templates/main.tpl create mode 100755 tizen-app-template.xml create mode 100644 tizen_32.png create mode 100644 tizen_64.png diff --git a/description.xml b/description.xml new file mode 100755 index 0000000..1b1d5c1 --- /dev/null +++ b/description.xml @@ -0,0 +1,10 @@ + + + + FileManager + 2.1.0 + filemanager-snapshot.png + + A sample application demonstrating the tizen device API usage. + + diff --git a/description.xsl b/description.xsl new file mode 100755 index 0000000..1f4f57f --- /dev/null +++ b/description.xsl @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Type: JavaScript +

+ +

+
+ + + + + +
+ + +
+ +
diff --git a/filemanager-snapshot.png b/filemanager-snapshot.png new file mode 100644 index 0000000000000000000000000000000000000000..85a5c9bf2f14ec9e7f4988f2ebd5d4f8e89481de GIT binary patch literal 10000 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 + + FileManager + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + json.validation.builder + + + + + org.tizen.web.jslint.nature.JSLintBuilder + + + + + org.tizen.web.css.nature.CSSBuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.tizen.web.project.builder.WebBuilder + + + + + org.tizen.web.editor.css.nature.CSSBuilder + + + + + + json.validation.nature + org.tizen.web.jslint.nature.JSLintNature + org.tizen.web.css.nature.CSSNature + org.eclipse.wst.jsdt.core.jsNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.tizen.web.project.builder.WebNature + org.tizen.web.editor.css.nature.CSSNature + + diff --git a/project/AUTHORS b/project/AUTHORS new file mode 100644 index 0000000..a447a9f --- /dev/null +++ b/project/AUTHORS @@ -0,0 +1,6 @@ +Pawel Sierszen +Piotr Wronski +Dariusz Paziewski +Tomasz Lukawski +Tomasz Paciorek +Aniela Rudy-Gawecka diff --git a/project/LICENSE.Flora b/project/LICENSE.Flora new file mode 100644 index 0000000..4a0af40 --- /dev/null +++ b/project/LICENSE.Flora @@ -0,0 +1,206 @@ +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and +all other entities that control, are controlled by, or are +under common control with that entity. For the purposes of +this definition, "control" means (i) the power, direct or indirect, +to cause the direction or management of such entity, +whether by contract or otherwise, or (ii) ownership of fifty percent (50%) +or more of the outstanding shares, or (iii) beneficial ownership of +such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice +that is included in or attached to the work (an example is provided +in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, +or merely link (or bind by name) to the interfaces of, the Work and +Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor +for inclusion in the Work by the copyright owner or by an individual or +Legal Entity authorized to submit on behalf of the copyright owner. +For the purposes of this definition, "submitted" means any form of +electronic, verbal, or written communication sent to the Licensor or +its representatives, including but not limited to communication on +electronic mailing lists, source code control systems, and issue +tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding +communication that is conspicuously marked or otherwise designated +in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +"Tizen Certified Platform" shall mean a software platform that complies +with the standards set forth in the Tizen Compliance Specification +and passes the Tizen Compliance Tests as defined from time to time +by the Tizen Technical Steering Group and certified by the Tizen +Association or its designated agent. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work +solely as incorporated into a Tizen Certified Platform, where such +license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work solely +as incorporated into a Tizen Certified Platform to which such +Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent infringement, +then any patent licenses granted to You under this License for that +Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof pursuant to the copyright license +above, in any medium, with or without modifications, and in Source or +Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works + a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + 3. You must retain, in the Source form of any Derivative Works that + You distribute, all copyright, patent, trademark, and attribution + notices from the Source form of the Work, excluding those notices + that do not pertain to any part of the Derivative Works; and + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of + the Derivative Works, in at least one of the following places: + within a NOTICE text file distributed as part of the Derivative Works; + within the Source form or documentation, if provided along with the + Derivative Works; or, within a display generated by the Derivative Works, + if and wherever such third-party notices normally appear. + The contents of the NOTICE file are for informational purposes only + and do not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an addendum + to the NOTICE text from the Work, provided that such additional attribution + notices cannot be construed as modifying the License. You may add Your own + copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or + distribution of Your modifications, or for any such Derivative Works + as a whole, provided Your use, reproduction, and distribution of + the Work otherwise complies with the conditions stated in this License + and your own copyright statement or terms and conditions do not conflict + the conditions stated in the License including section 3. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Flora License to your work + +To apply the Flora License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/project/NOTICE b/project/NOTICE new file mode 100644 index 0000000..092bc04 --- /dev/null +++ b/project/NOTICE @@ -0,0 +1,4 @@ +Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Flora License, Version 1.1 +Please, see the LICENSE.Flora file for Flora License, Version 1.1 terms and conditions. + diff --git a/project/config.xml b/project/config.xml new file mode 100644 index 0000000..45f5279 --- /dev/null +++ b/project/config.xml @@ -0,0 +1,13 @@ + + + + + File Manager + + + + + + + + diff --git a/project/css/style.css b/project/css/style.css new file mode 100644 index 0000000..94917c0 --- /dev/null +++ b/project/css/style.css @@ -0,0 +1,245 @@ +* { + margin: 0px; + padding: 0px; +} + +body { + overflow: hidden; +} + +#fileList { + margin: 0; +} + +#mainTitle { + width: 210px; +} + +#fileList > li { + 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; +} + +#fileList > li.gradientBackground > span.nodename { + color: #fff !important; +} + +#fileList > li.file img { + width: 32px; + height: 32px; +} + +#fileList > li.folder img { + margin-top: 0.1rem; +} + +#fileList > li.levelUp { + padding-left: 47px !important; + height: 32px; +} + +.selectAll { + padding-left: 6px; + display: inline-block; +} + +.selectAll span.ui-btn-text { + padding-left: 2rem !important; + 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; +} + +.ui-pathDiv { + position: absolute; + top: 49px; + left: 0px; + right: 0px; + bottom: 0px; +} + +#pathDiv { + padding: 2px 0px 0px 5px; + border: 0px; +} + +#pathDiv .ui-li-text-main { + font-size: 18px; +} + +#morePopup td.text a { + color:#FFF; + text-decoration:none; +} + +#morePopup td.text { + padding: 5px; +} +#morePopup { + margin: 2px; +} +#alertPopup .text { + text-align:left; + padding:20px; + min-height: 100px !important; +} + +#alertPopup .alertPopup-button { + padding-bottom: 10px; +} + +#confirmPopup .text { + text-align:left; + padding:20px; + font-size: 18px; +} + +.ui-header.ui-bar-s .ui-btn.standard { + width: 100%; + height: 100%; +} + +#homeBtn, +#levelUpBtn { + 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; +} + +.my-ui-checkbox { + 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; +} + +.ui-checkbox .ui-btn.ui-btn-icon-left .ui-btn-inner { + line-height: 1.1rem; + padding: 0 0 0 0rem; + width: 30px; +} + +.ui-checkbox .ui-btn.ui-btn-icon-left .ui-btn-inner.ui-btn-hastxt { + width: 100%; +} + +.ui-btn-corner-all { + -webkit-border-radius: 0px; + bordert-radius: 0px; +} + +.ui-content.ui-scrollview-clip > div.ui-scrollview-view { + padding: 0px; +} + +input.ui-input-text.new_folder { + width: 100%; + height: 50px; + padding: 0 0 0 .4em; +} + +.gradientBackground { + background: -webkit-linear-gradient(top, #5A99BA 0%, #205473 100%) !important; /* from tizen-white */ +} + +.hidden { + display: none !important; +} + +.vhidden { + visibility: hidden !important; +} + +.ui-tabbar a { + color: #999 !important; +} + +#newFolderName { + box-sizing: border-box; + width: 100%; +} + +.ui-header.ui-bar-s > .ui-btn { + width: 2rem; +} +/** workaround to prevent hiding footer caused by broken softkeyboardupdate event**/ +[data-role="footer"] { + display: block !important; +} + +.ui-ctxpopup .horizontal a.ui-link { + display: block; +} + +.ui-footer .ui-btn-text { + 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; +} + +#overlay { + 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; +} + +#infoPopup img { + -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 diff --git a/project/icon.png b/project/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..59347574ba0838cfba30bf3293894f3c750538d0 GIT binary patch literal 15199 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 LNkvXXu0mjfzQ*#c literal 0 HcmV?d00001 diff --git a/project/images/etc.png b/project/images/etc.png new file mode 100755 index 0000000000000000000000000000000000000000..26748d83cfa4fee28a125d4dcdb01a77f901102d GIT binary patch literal 1292 zcmXX_4NMbf82%72CqH@+lifgL83s7xUn4kb2m%%b4_HAR0;?NfOL0M?fWN^EDrmWZ zWy)=3p!|qJnXozNCQ%1o4yIBDC@|4AgDu@C!HGx=0^Z&axP15A^Zq^W`@Ly(ikMxl zP99DOA=k(Vc^rKG@k`hPzPdj46rm+iim1Keq9}p~9@z^~YFXr{RHO$)$wQGcEqZ`2 zM8N}`sKO!Ah!50)iOYvD(k11x5lrAf2%K~`Rs$rJha|eo*lEGZfHK>Bv=3)W?u*nt zTm^_vE9N-Iin$atZ8(j*g*||9u-Pa|O0EGy4mRgUf+|UeNYr8v{m=>~Ob8qvBI?W{ zslZba6^njk5NQ}=9tnd8f`G6G@Zee?rMNH3w=O6HqL55z0b?%+;`v*#DFxXoyctk{ zTT?JMz}}`zTLu3pb>7NWTBm;N}w{d$UhOcP_W1W$zXLO zqNG-k7zMPCCH!czN+fg^M3As9VxKk?7FZ;p^}7*4P^AKyFGxEqWHKuoctI#w>L^PV z33Q`CDp@j}C3S+NLZE8}B7voEK`)lb70@X&sbXo9nM~JG1_)`1QjyFRNR?LFYDU>+ zszg8vt<+?ujRI_dOxB`=aw1vVU4~>Z=aH1EF`5q$TK__edCE*w+NGh29$nazH~aews|Vu zxibu}UIr>4$unIMlfGO%u-nZ{Y!SEWtQCIWOHiadbnnRn@~SZ zzbWIHsVMV+#~Qb4pmUw4?^#r5wr;s?%kufF?mbX z_B@|X&$@$!Jubt4cI-<2X=LICpRY+AZD>kUTQ8I;KR&+cYa;1Ed(g0YP4P>g{{Fe5 zrOOZJHoshPC_ZV%wR$4*PVJ*xeuf}NMQ^3terhZ-qDej?4avE$=(v%Byl#d~uMHVH zDErPme&hKQuL8f~k9|?_)T9hQmth)r(&=xSTw{+Y2i=~;4_-a$zjttr-IJloAcvNz z*MqCFU*GwVyxqup4d&>>8=ZUYxESw$NhWRkhLq9I(Q4I~UK)qgO|ot6l-zrDXK0V6 zbGogU>YR4z*}t34v&NmiRHM6WajbJK-nQqhwr2U|0|kC56jeyQ`Oz;W$U$Rt6MC|| z-?BCD?_60u&Z)dKoJti~mYOhVXEPet<+aw?l8UVjwwaw(zU~QaE3VjQ_4r3SY}gw8 zZuHj^kGs~_U))9)=2adpJeK&uqu^==GIaV` z*J;mo^`-0S#87qmr-AOx(axKjcQ_jbOFe)!9*clvqyM!=M3Q?<0t&rNN_|Ch+{7?P)00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*Y| z4FVjzHBMOo000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0006)Nkl)yf6okK#$FQXemh5sL&XS|#I#jWS6*nMNELczk$H9v1NHg=A#f<+TB$knX zrpi?s$un+s_vqBmivu8m}@DuHOc(Dg`tA zu=W-oQ{Fs9L(=wdxivvs^M8=|=5bhu?Sa*rT4jFi~U->YAbMrnHNAy0={u z-sWGkcyWSKbFk<5Ubqar)n78O(dhwgNvR^G&IeaEzok(A#5f;dX5bffZXs25UckUsq literal 0 HcmV?d00001 diff --git a/project/images/img.png b/project/images/img.png new file mode 100755 index 0000000000000000000000000000000000000000..4dd3be3b1bbeef29bb56a19a9de7184919ceec6e GIT binary patch literal 1454 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 literal 0 HcmV?d00001 diff --git a/project/images/pdf.png b/project/images/pdf.png new file mode 100755 index 0000000000000000000000000000000000000000..2480d818341a660d16797b59ef59121484cf9aa0 GIT binary patch literal 4794 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 Wcsr)1CMZz=0000h7 literal 0 HcmV?d00001 diff --git a/project/index.html b/project/index.html new file mode 100644 index 0000000..9366eb2 --- /dev/null +++ b/project/index.html @@ -0,0 +1,24 @@ + + + + + + + File Manager + + + + + + + + +
+
+
+ +

Operation in progress.

+
+
+ + \ No newline at end of file diff --git a/project/js/app.clipboard.js b/project/js/app.clipboard.js new file mode 100644 index 0000000..cee9925 --- /dev/null +++ b/project/js/app.clipboard.js @@ -0,0 +1,147 @@ +/*jslint devel: true*/ +/*global $*/ + +/** + * @class Config + */ +function Clipboard() { + '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; + } + }; +}()); diff --git a/project/js/app.config.js b/project/js/app.config.js new file mode 100644 index 0000000..e0332c3 --- /dev/null +++ b/project/js/app.config.js @@ -0,0 +1,28 @@ +/** + * @class Config + */ +function Config() { + 'use strict'; +} + +(function () { // strict mode wrapper + 'use strict'; + Config.prototype = { + + properties: { + 'templateDir': 'templates', + 'templateExtension': '.tpl' + }, + + /** + * Returns config value + */ + get: function (value, 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 new file mode 100644 index 0000000..12cd314 --- /dev/null +++ b/project/js/app.helpers.js @@ -0,0 +1,162 @@ +/*jslint devel: true*/ +/*global $, jQuery */ + +/** + * @class Helpers + */ +function Helpers() { + '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; + } + }; +}()); diff --git a/project/js/app.js b/project/js/app.js new file mode 100644 index 0000000..297023b --- /dev/null +++ b/project/js/app.js @@ -0,0 +1,278 @@ +/*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(); + } + }; +}()); diff --git a/project/js/app.model.js b/project/js/app.model.js new file mode 100644 index 0000000..7b2b4a1 --- /dev/null +++ b/project/js/app.model.js @@ -0,0 +1,352 @@ +/*jslint devel: true*/ +/*global tizen, SystemIO, $, app */ + +/** + * @class Model + */ +function Model() { + '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); + } + } + }); + } + }; +}()); diff --git a/project/js/app.systemIO.js b/project/js/app.systemIO.js new file mode 100644 index 0000000..4c70377 --- /dev/null +++ b/project/js/app.systemIO.js @@ -0,0 +1,261 @@ +/*jslint devel: true*/ +/*global tizen, localStorage */ + +/** + * @class SystemIO + */ +function SystemIO() { + '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) { + + 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 () {}; + + fileHandle.openStream('w', function (fileStream) { + if (contentEncoding === 'base64') { + fileStream.writeBase64(fileContent); + } else { + fileStream.write(fileContent); + } + + fileStream.close(); + + // 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 () {}; + + 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('/'); + + path.fileName = splittedPath.pop(); + path.dirName = splittedPath.join('/') || '/'; + + 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; + + 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); + }, + + /** + * 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 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(); + } + }; + + // 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); + }); + }, + + /** + * 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; + } + + 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; + + 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); + } + }, + + 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); + } + + 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 diff --git a/project/js/app.ui.js b/project/js/app.ui.js new file mode 100644 index 0000000..b6b30e1 --- /dev/null +++ b/project/js/app.ui.js @@ -0,0 +1,961 @@ +/*jslint devel: true */ +/*global $, app, TemplateManager, Helpers */ + +/** + * @class Ui + */ +function Ui() { + '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(); + } + + } + }; +}()); diff --git a/project/js/app.ui.templateManager.js b/project/js/app.ui.templateManager.js new file mode 100644 index 0000000..e2a440a --- /dev/null +++ b/project/js/app.ui.templateManager.js @@ -0,0 +1,136 @@ +/*global tizen, $, app, ModifierManager */ +/** + * @class TemplateManager + */ +function TemplateManager() { + '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 diff --git a/project/js/app.ui.templateManager.modifiers.js b/project/js/app.ui.templateManager.modifiers.js new file mode 100644 index 0000000..95e9d0a --- /dev/null +++ b/project/js/app.ui.templateManager.modifiers.js @@ -0,0 +1,47 @@ +/*global $*/ +/** + * @class ModifierManager + */ +function ModifierManager() { + 'use strict'; + this.init(); +} + +(function () { + 'use strict'; + ModifierManager.prototype = { + + /** + * UI module initialisation + */ + init: function () { + }, + + /** + * @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; + }); + } + } + }; +}()); \ No newline at end of file diff --git a/project/js/main.js b/project/js/main.js new file mode 100644 index 0000000..360b951 --- /dev/null +++ b/project/js/main.js @@ -0,0 +1,78 @@ +/* + * 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 */ + +/** + * This file acts as a loader for the application and its dependencies + * + * First, the 'app.js' script is loaded . + * Then, scripts defined in 'app.requires' are loaded. + * Finally, the app is initialised - the app is instantiated ('app = new App()') + * and 'app.init()' is called. + */ + + +var app = null; + +(function () { // strict mode wrapper + '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); + }, + + /** + * 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 +}()); diff --git a/project/templates/emptyFolder.tpl b/project/templates/emptyFolder.tpl new file mode 100644 index 0000000..da09356 --- /dev/null +++ b/project/templates/emptyFolder.tpl @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/project/templates/fileRow.tpl b/project/templates/fileRow.tpl new file mode 100644 index 0000000..38f6b03 --- /dev/null +++ b/project/templates/fileRow.tpl @@ -0,0 +1,5 @@ +
  • + + + %name|escape% +
  • \ No newline at end of file diff --git a/project/templates/folderRow.tpl b/project/templates/folderRow.tpl new file mode 100644 index 0000000..ba82018 --- /dev/null +++ b/project/templates/folderRow.tpl @@ -0,0 +1,6 @@ +
  • + + + %name|escape% + +
  • \ No newline at end of file diff --git a/project/templates/levelUpRow.tpl b/project/templates/levelUpRow.tpl new file mode 100644 index 0000000..ddbc7cf --- /dev/null +++ b/project/templates/levelUpRow.tpl @@ -0,0 +1,3 @@ +
  • + .. +
  • \ No newline at end of file diff --git a/project/templates/main.tpl b/project/templates/main.tpl new file mode 100644 index 0000000..d5d17e7 --- /dev/null +++ b/project/templates/main.tpl @@ -0,0 +1,83 @@ +
    +
    +

    + Home + Up + + +
    + +
    +
      +
      +
      +

      Add new folder

      +

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

      +
      + OK +
      +
      +
      +
      +

      +
      +
      + CANCEL + OK +
      +
      +
      + +
      +
      +
      + +
      + +
      +
      + + + + + + + +
      + New folder +
      + Paste to folder +
      +
      +
      +
      \ No newline at end of file diff --git a/tizen-app-template.xml b/tizen-app-template.xml new file mode 100755 index 0000000..19897f8 --- /dev/null +++ b/tizen-app-template.xml @@ -0,0 +1,12 @@ + + + FileManager + TIZEN + + description.xml + + + + + + diff --git a/tizen_32.png b/tizen_32.png new file mode 100644 index 0000000000000000000000000000000000000000..61f35c0507d8a7275c92019e8dcc399148d7e1d9 GIT binary patch literal 4563 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 literal 0 HcmV?d00001 diff --git a/tizen_64.png b/tizen_64.png new file mode 100644 index 0000000000000000000000000000000000000000..b1880832b1ee1bf80498667f1dde9b8b744761ec GIT binary patch literal 6849 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 literal 0 HcmV?d00001 -- 2.7.4