build.coffee 10 KB

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