build.coffee 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. ###
  2. # @description This module is used to generate HTML-Code.
  3. # @copyright 2014 by Tobias Reich
  4. ###
  5. window.build = {}
  6. build.divider = (title) ->
  7. "<div class='divider fadeIn'><h1>#{ title }</h1></div>"
  8. build.editIcon = (id) ->
  9. "<div id='#{ id }' class='edit'><a class='icon-pencil'></a></div>"
  10. build.multiselect = (top, left) ->
  11. "<div id='multiselect' style='top: #{ top }px; left: #{ left }px;'></div>"
  12. build.album = (data) ->
  13. return '' if not data?
  14. title = data.title
  15. longTitle = ''
  16. typeThumb = ''
  17. if title? and title.length > 18
  18. title = data.title.substr(0, 18) + '...'
  19. longTitle = data.title
  20. if data.thumb0.split('.').pop() is 'svg' then typeThumb = 'nonretina'
  21. html = """
  22. <div class='album' data-id='#{ data.id }' data-password='#{ data.password }'>
  23. <img src='#{ data.thumb2 }' width='200' height='200' alt='thumb' data-type='nonretina'>
  24. <img src='#{ data.thumb1 }' width='200' height='200' alt='thumb' data-type='nonretina'>
  25. <img src='#{ data.thumb0 }' width='200' height='200' alt='thumb' data-type='#{ typeThumb }'>
  26. <div class='overlay'>
  27. """
  28. if data.password and lychee.publicMode is false
  29. html += "<h1 title='#{ longTitle }'><span class='icon-lock'></span> #{ title }</h1>";
  30. else
  31. html += "<h1 title='#{ longTitle }'>#{ title }</h1>"
  32. html += """
  33. <a>#{ data.sysdate }</a>
  34. </div>
  35. """
  36. if lychee.publicMode is false
  37. if data.star is '1' then html += "<a class='badge red icon-star'></a>"
  38. if data.public is '1' then html += "<a class='badge red icon-share'></a>"
  39. if data.unsorted is '1' then html += "<a class='badge red icon-reorder'></a>"
  40. if data.recent is '1' then html += "<a class='badge red icon-time'></a>"
  41. html += "</div>"
  42. return html
  43. build.photo = (data) ->
  44. return '' if not data?
  45. title = data.title
  46. longTitle = ''
  47. if title? and title.length > 18
  48. title = data.title.substr(0, 18) + '...'
  49. longTitle = data.title
  50. html = """
  51. <div class='photo' data-album-id='#{ data.album }' data-id='#{ data.id }'>
  52. <img src='#{ data.thumbUrl }' width='200' height='200' alt='thumb'>
  53. <div class='overlay'>
  54. <h1 title='#{ longTitle }'>#{ title }</h1>
  55. """
  56. if data.cameraDate is '1'
  57. html += "<a><span class='icon-camera' title='Photo Date'></span>#{ data.sysdate }</a>"
  58. else
  59. html += "<a>#{ data.sysdate }</a>"
  60. html += "</div>"
  61. if data.star is '1' then html += "<a class='badge red icon-star'></a>"
  62. if lychee.publicMode is false and data.public is '1' and album.json.public isnt '1' then html += "<a class='badge red icon-share'></a>"
  63. html += "</div>"
  64. return html
  65. build.imageview = (data, size, visibleControls) ->
  66. return '' if not data?
  67. html = """
  68. <div class='arrow_wrapper previous'><a id='previous' class='icon-caret-left'></a></div>
  69. <div class='arrow_wrapper next'><a id='next' class='icon-caret-right'></a></div>
  70. """
  71. if size is 'big'
  72. if visibleControls is true
  73. html += "<div id='image' style='background-image: url(#{ data.url })'></div>"
  74. else
  75. html += "<div id='image' style='background-image: url(#{ data.url });' class='full'></div>"
  76. else if size is 'medium'
  77. if visibleControls is true
  78. html += "<div id='image' style='background-image: url(#{ data.medium })'></div>"
  79. else
  80. html += "<div id='image' style='background-image: url(#{ data.medium });' class='full'></div>"
  81. else if size is 'small'
  82. if visibleControls is true
  83. html += "<div id='image' class='small' style='background-image: url(#{ data.url }); width: #{ data.width }px; height: #{ data.height }px; margin-top: -#{ parseInt(data.height/2-20) }px; margin-left: -#{ data.width/2 }px;'></div>"
  84. else
  85. html += "<div id='image' class='small' style='background-image: url(#{ data.url }); width: #{ data.width }px; height: #{ data.height }px; margin-top: -#{ parseInt(data.height/2) }px; margin-left: -#{ data.width/2 }px;'></div>"
  86. return html
  87. build.no_content = (typ) ->
  88. html = """
  89. <div class='no_content fadeIn'>
  90. <a class='icon icon-#{ typ }'></a>
  91. """
  92. switch typ
  93. when 'search' then html += "<p>No results</p>"
  94. when 'share' then html += "<p>No public albums</p>"
  95. when 'cog' then html += "<p>No configuration</p>"
  96. html += "</div>"
  97. return html
  98. build.modal = (title, text, button, marginTop, closeButton) ->
  99. if marginTop? then custom_style = "style='margin-top: #{ marginTop }px;'"
  100. else custom_style = ''
  101. html = """
  102. <div class='message_overlay fadeIn'>
  103. <div class='message center' #{ custom_style }>
  104. <h1>#{ title }</h1>
  105. """
  106. if closeButton isnt false then html += "<a class='close icon-remove-sign'></a>"
  107. html += "<p>#{ text }</p>"
  108. $.each button, (index) ->
  109. if this[0] isnt ''
  110. if index is 0 then html += "<a class='button active'>#{ this[0] }</a>"
  111. else html += "<a class='button'>#{ this[0] }</a>"
  112. html += """
  113. </div>
  114. </div>
  115. """
  116. return html
  117. build.signInModal = ->
  118. html = """
  119. <div class='message_overlay'>
  120. <div class='message center'>
  121. <h1><a class='icon-lock'></a> Sign In</h1>
  122. <a class='close icon-remove-sign'></a>
  123. <div class='sign_in'>
  124. <input id='username' type='text' value='' placeholder='username' autocapitalize='off' autocorrect='off'>
  125. <input id='password' type='password' value='' placeholder='password'>
  126. </div>
  127. <div id='version'>Version #{ lychee.version }<span> &#8211; <a target='_blank' href='#{ lychee.updateURL }'>Update available!</a><span></div>
  128. <a onclick='lychee.login()' class='button active'>Sign in</a>
  129. </div>
  130. </div>
  131. """
  132. return html
  133. build.uploadModal = (title, files) ->
  134. html = """
  135. <div class='upload_overlay fadeIn'>
  136. <div class='upload_message center'>
  137. <h1>#{ title }</h1>
  138. <a class='close icon-remove-sign'></a>
  139. <div class='rows'>
  140. """
  141. i = 0
  142. file = null
  143. while i < files.length
  144. file = files[i]
  145. if file.name.length > 40
  146. file.name = file.name.substr(0, 17) + '...' + file.name.substr(file.name.length-20, 20)
  147. html += """
  148. <div class='row'>
  149. <a class='name'>#{ lychee.escapeHTML(file.name) }</a>
  150. """
  151. if file.supported is true then html += "<a class='status'></a>"
  152. else html += "<a class='status error'>Not supported</a>"
  153. html += """
  154. <p class='notice'></p>
  155. </div>
  156. """
  157. i++
  158. html += """
  159. </div>
  160. </div>
  161. </div>
  162. """
  163. return html
  164. build.contextMenu = (items) ->
  165. html = """
  166. <div class='contextmenu_bg'></div>
  167. <div class='contextmenu'>
  168. <table>
  169. <tbody>
  170. """
  171. items.forEach (item, i, items) ->
  172. if item[0] is 'separator' and item[1] is -1
  173. html += "<tr class='separator'></tr>"
  174. else if item[1] is -1
  175. html += "<tr class='no_hover'><td>#{ item[0] }</td></tr>"
  176. else if item[2]?
  177. html += "<tr><td onclick='#{ item[2] }; window.contextMenu.close();'>#{ item[0] }</td></tr>"
  178. else
  179. html += "<tr><td onclick='window.contextMenu.fns[#{ item[1] }](); window.contextMenu.close();'>#{ item[0] }</td></tr>";
  180. html += """
  181. </tbody>
  182. </table>
  183. </div>
  184. """
  185. return html
  186. build.tags = (tags, forView) ->
  187. html = ''
  188. if forView is true or lychee.publicMode is true then editTagsHTML = ''
  189. else editTagsHTML = ' ' + build.editIcon('edit_tags')
  190. if tags isnt ''
  191. tags = tags.split ','
  192. tags.forEach (tag, index, array) ->
  193. html += "<a class='tag'>#{ tag }<span class='icon-remove' data-index='#{ index }'></span></a>"
  194. html += editTagsHTML
  195. else
  196. html = "<div class='empty'>No Tags#{ editTagsHTML }</div>"
  197. return html
  198. build.infoboxPhoto = (data, forView) ->
  199. html = """
  200. <div class='header'><h1>About</h1><a class='icon-remove-sign'></a></div>
  201. <div class='wrapper'>
  202. """
  203. switch data.public
  204. when '0' then visible = 'No'
  205. when '1' then visible = 'Yes'
  206. when '2' then visible = 'Yes (Album)'
  207. else visible = '-'
  208. if forView is true or lychee.publicMode is true then editTitleHTML = ''
  209. else editTitleHTML = ' ' + build.editIcon('edit_title')
  210. if forView is true or lychee.publicMode is true then editDescriptionHTML = ''
  211. else editDescriptionHTML = ' ' + build.editIcon('edit_description')
  212. infos = [
  213. ['', 'Basics']
  214. ['Title', data.title + editTitleHTML]
  215. ['Uploaded', data.sysdate]
  216. ['Description', data.description + editDescriptionHTML]
  217. ['', 'Image']
  218. ['Size', data.size]
  219. ['Format', data.type]
  220. ['Resolution', data.width + ' x ' + data.height]
  221. ['Tags', build.tags(data.tags, forView)]
  222. ]
  223. exifHash = data.takestamp+data.make+data.model+data.shutter+data.aperture+data.focal+data.iso
  224. if exifHash isnt '0' or exifHash isnt '0'
  225. infos = infos.concat [
  226. ['', 'Camera']
  227. ['Captured', data.takedate]
  228. ['Make', data.make]
  229. ['Type/Model', data.model]
  230. ['Shutter Speed', data.shutter]
  231. ['Aperture', data.aperture]
  232. ['Focal Length', data.focal]
  233. ['ISO', data.iso]
  234. ]
  235. infos = infos.concat [
  236. ['', 'Share']
  237. ['Public', visible]
  238. ]
  239. infos.forEach (info, i, items) ->
  240. if info[1] is '' or
  241. not info[1]?
  242. info[1] = '-'
  243. switch info[0]
  244. when ''
  245. # Separator
  246. html += """
  247. </table>
  248. <div class='separator'><h1>#{ info[1] }</h1></div>
  249. <table>
  250. """
  251. when 'Tags'
  252. # Tags
  253. if forView isnt true and lychee.publicMode is false
  254. html += """
  255. </table>
  256. <div class='separator'><h1>#{ info[0] }</h1></div>
  257. <div id='tags'>#{ info[1] }</div>
  258. """
  259. else
  260. # Item
  261. html += """
  262. <tr>
  263. <td>#{ info[0] }</td>
  264. <td class='attr_#{ info[0].toLowerCase() }'>#{ info[1] }</td>
  265. </tr>
  266. """
  267. html += """
  268. </table>
  269. <div class='bumper'></div>
  270. </div>
  271. """
  272. return html
  273. build.infoboxAlbum = (data, forView) ->
  274. html = """
  275. <div class='header'><h1>About</h1><a class='icon-remove-sign'></a></div>
  276. <div class='wrapper'>
  277. """
  278. switch data.public
  279. when '0' then visible = 'No'
  280. when '1' then visible = 'Yes'
  281. else visible = '-'
  282. switch data.password
  283. when false then password = 'No'
  284. when true then password = 'Yes'
  285. else password = '-'
  286. switch data.downloadable
  287. when '0' then downloadable = 'No'
  288. when '1' then downloadable = 'Yes'
  289. else downloadable = '-'
  290. if forView is true or lychee.publicMode is true then editTitleHTML = ''
  291. else editTitleHTML = ' ' + build.editIcon('edit_title_album')
  292. if forView is true or lychee.publicMode is true then editDescriptionHTML = ''
  293. else editDescriptionHTML = ' ' + build.editIcon('edit_description_album')
  294. infos = [
  295. ['', 'Basics']
  296. ['Title', data.title + editTitleHTML]
  297. ['Description', data.description + editDescriptionHTML]
  298. ['', 'Album']
  299. ['Created', data.sysdate]
  300. ['Images', data.num]
  301. ['', 'Share']
  302. ['Public', visible]
  303. ['Downloadable', downloadable]
  304. ['Password', password]
  305. ]
  306. infos.forEach (info, i, items) ->
  307. if info[0] is ''
  308. # Separator
  309. html += """
  310. </table>
  311. <div class='separator'><h1>#{ info[1] }</h1></div>
  312. <table id='infos'>
  313. """
  314. else
  315. # Item
  316. html += """
  317. <tr>
  318. <td>#{ info[0] }</td>
  319. <td class='attr_#{ info[0].toLowerCase() }'>#{ info[1] }</td>
  320. </tr>
  321. """
  322. html += """
  323. </table>
  324. <div class='bumper'></div>
  325. </div>
  326. """
  327. return html