main.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * @description Used to view single photos with view.php
  3. * @copyright 2015 by Tobias Reich
  4. */
  5. // Sub-implementation of lychee -------------------------------------------------------------- //
  6. let lychee = {}
  7. lychee.content = $('.content')
  8. lychee.escapeHTML = function(html = '') {
  9. // Ensure that html is a string
  10. html += ''
  11. // Escape all critical characters
  12. html = html.replace(/&/g, '&')
  13. .replace(/</g, '&lt;')
  14. .replace(/>/g, '&gt;')
  15. .replace(/"/g, '&quot;')
  16. .replace(/'/g, '&#039;')
  17. .replace(/`/g, '&#96;')
  18. return html
  19. }
  20. lychee.html = function(literalSections, ...substs) {
  21. // Use raw literal sections: we don’t want
  22. // backslashes (\n etc.) to be interpreted
  23. let raw = literalSections.raw
  24. let result = ''
  25. substs.forEach((subst, i) => {
  26. // Retrieve the literal section preceding
  27. // the current substitution
  28. let lit = raw[i]
  29. // If the substitution is preceded by a dollar sign,
  30. // we escape special characters in it
  31. if (lit.slice(-1)==='$') {
  32. subst = lychee.escapeHTML(subst)
  33. lit = lit.slice(0, -1)
  34. }
  35. result += lit
  36. result += subst
  37. })
  38. // Take care of last literal section
  39. // (Never fails, because an empty template string
  40. // produces one literal section, an empty string)
  41. result += raw[raw.length - 1]
  42. return result
  43. }
  44. lychee.getEventName = function() {
  45. let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement)
  46. let eventName = (touchendSupport===true ? 'touchend' : 'click')
  47. return eventName
  48. }
  49. // Sub-implementation of photo -------------------------------------------------------------- //
  50. let photo = {}
  51. photo.share = function(photoID, service) {
  52. let url = location.toString()
  53. switch (service) {
  54. case 'twitter':
  55. window.open(`https://twitter.com/share?url=${ encodeURI(url) }`)
  56. break
  57. case 'facebook':
  58. window.open(`http://www.facebook.com/sharer.php?u=${ encodeURI(url) }`)
  59. break
  60. case 'mail':
  61. location.href = `mailto:?subject=&body=${ encodeURI(url) }`
  62. break
  63. }
  64. }
  65. photo.getDirectLink = function() {
  66. return $('#imageview img').attr('src').replace(/"/g,'').replace(/url\(|\)$/ig, '')
  67. }
  68. // Sub-implementation of contextMenu -------------------------------------------------------------- //
  69. let contextMenu = {}
  70. contextMenu.sharePhoto = function(photoID, e) {
  71. let iconClass = 'ionicons'
  72. let items = [
  73. { title: build.iconic('twitter', iconClass) + 'Twitter', fn: () => photo.share(photoID, 'twitter') },
  74. { title: build.iconic('facebook', iconClass) + 'Facebook', fn: () => photo.share(photoID, 'facebook') },
  75. { title: build.iconic('envelope-closed') + 'Mail', fn: () => photo.share(photoID, 'mail') },
  76. { title: build.iconic('link-intact') + 'Direct Link', fn: () => window.open(photo.getDirectLink(), '_newtab') }
  77. ]
  78. basicContext.show(items, e.originalEvent)
  79. }
  80. // Main -------------------------------------------------------------- //
  81. let loadingBar = { show() {}, hide() {} }
  82. let imageview = $('#imageview')
  83. $(document).ready(function() {
  84. // Save ID of photo
  85. let photoID = gup('p')
  86. // Set API error handler
  87. api.onError = error
  88. // Share
  89. header.dom('#button_share').on('click', function(e) {
  90. contextMenu.sharePhoto(photoID, e)
  91. })
  92. // Infobox
  93. header.dom('#button_info').on('click', sidebar.toggle)
  94. // Load photo
  95. loadPhotoInfo(photoID)
  96. })
  97. const loadPhotoInfo = function(photoID) {
  98. let params = {
  99. photoID,
  100. albumID : 0,
  101. password : ''
  102. }
  103. api.post('Photo::get', params, function(data) {
  104. if (data==='Warning: Photo private!' || data==='Warning: Wrong password!') {
  105. $('body').append(build.no_content('question-mark'))
  106. $('body').removeClass('view')
  107. header.dom().remove()
  108. return false
  109. }
  110. // Set title
  111. if (!data.title) data.title = 'Untitled'
  112. document.title = 'Lychee - ' + data.title
  113. header.dom('.header__title').html(lychee.escapeHTML(data.title))
  114. // Render HTML
  115. imageview.html(build.imageview(data, true))
  116. imageview.find('.arrow_wrapper').remove()
  117. imageview.addClass('fadeIn').show()
  118. // Render Sidebar
  119. let structure = sidebar.createStructure.photo(data)
  120. let html = sidebar.render(structure)
  121. sidebar.dom('.sidebar__wrapper').html(html)
  122. sidebar.bind()
  123. })
  124. }
  125. const error = function(errorThrown, params, data) {
  126. console.error({
  127. description : errorThrown,
  128. params : params,
  129. response : data
  130. })
  131. loadingBar.show('error', errorThrown)
  132. }