stories.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php
  2. /**
  3. * @var $this \yii\web\View
  4. */
  5. $this->registerJsFile('/js/zuck/dist/zuck.min.js',["position"=>$this::POS_HEAD]);
  6. $this->registerCssFile("/js/zuck/dist/zuck.min.css");
  7. $this->registerCssFile("/js/zuck/dist/skins/snapgram.min.css");
  8. ?>
  9. <div class="stories_cont">
  10. <div id="stories"></div>
  11. </div>
  12. <?php use app\models\News;
  13. $stories = Yii::$app->cache->getOrSet("site-stories",function (){
  14. $data = [];
  15. $news = \app\models\front\News::find()->alias('news')
  16. ->joinWith('topics t')
  17. ->groupBy('news.id')
  18. ->andWhere(['t.id'=>157])->limit(10);
  19. $index = 0;
  20. foreach ($news->all() as $news_item)
  21. {
  22. /**
  23. * @var $news_item News
  24. */
  25. $comments = [];
  26. foreach ($news_item->getCommentsAll()->limit(5)->all() as $comment){
  27. /**
  28. * @var $comment \app\models\base\Comments
  29. */
  30. $comments[]=[
  31. "message"=>$comment->message,
  32. "published_at"=>$comment->publishedAt
  33. ];
  34. }
  35. $data[]=[
  36. "id"=>$news_item->uid,
  37. "index"=>$index,
  38. "photo"=>$news_item->preview->getUrl(\app\models\base\Image::SIZE_680x383),
  39. "name"=>str_replace( '"',"&quot;",$news_item->title),
  40. "link"=>$news_item->url,
  41. "lastUpdated"=>strtotime($news_item->dt_pub),
  42. "seen"=>false,
  43. "published_at"=>$news_item->publishedAt,
  44. "items"=>[
  45. [
  46. "id"=>$news_item->preview->getUrl(\app\models\base\Image::SIZE_680x383),
  47. "type"=>"photo",
  48. "length"=>100,
  49. "lastUpdated"=>strtotime($news_item->dt_pub),
  50. "src"=>$news_item->preview->getUrl(\app\models\base\Image::SIZE_1040x586),
  51. "preview"=>$news_item->preview->getUrl(\app\models\base\Image::SIZE_320x180),
  52. "link"=>$news_item->url,
  53. "linkText"=>str_replace( '"',"'",$news_item->lid),
  54. "seen"=> false,
  55. "lid"=>str_replace( '"',"'",$news_item->lid),
  56. "post_title"=>str_replace( '"',"'",$news_item->title),
  57. "comments"=>base64_encode(json_encode($comments))
  58. ]
  59. ]
  60. ];
  61. $index++;
  62. }
  63. return json_encode($data);
  64. },60*5);
  65. ?>
  66. <script>
  67. const get = function (array, what) {
  68. if (array) {
  69. return array[what] || '';
  70. } else {
  71. return '';
  72. }
  73. };
  74. const renderComments = function (comments){
  75. let html = "";
  76. var j;
  77. try{
  78. let commentsArr = JSON.parse(atob(comments));
  79. if("object" === typeof commentsArr && commentsArr.length>0){
  80. html+='<div class="comments">';
  81. for(let i = 0; i < commentsArr.length; i++){
  82. j = commentsArr[i];
  83. html+=`<div class="comment"><div class="message">${j.message}</div><div class="published_at">${j.published_at}</div></div>`
  84. }
  85. html+='</div>';
  86. }
  87. } catch (e){
  88. }
  89. return html;
  90. }
  91. let stories = new Zuck("stories",{
  92. skin: 'snapgram',
  93. avatars: false, // shows user photo instead of last story item preview
  94. list: false, // displays a timeline instead of carousel
  95. openEffect: true, // enables effect when opening story
  96. cubeEffect: false, // enables the 3d cube effect when sliding story
  97. autoFullScreen: false, // enables fullscreen on mobile browsers
  98. backButton: true, // adds a back button to close the story viewer
  99. backNative: false, // uses window history to enable back button on browsers/android
  100. previousTap: true, // use 1/3 of the screen to navigate to previous item when tap the story
  101. localStorage: true, // set true to save "seen" position. Element must have a id to save properly.
  102. reactive: false, // set true if you use frameworks like React to control the timeline (see react.sample.html)
  103. rtl: false, // enable/disable RTL
  104. paginationArrows:false,
  105. "stories": <?=$stories?>,
  106. template: {
  107. viewerItemBody: function (index, currentIndex, item) {
  108. return `<div
  109. class="item ${get(item, 'seen') === true ? 'seen' : ''} ${currentIndex === index ? 'active' : ''}"
  110. data-time="${get(item, 'time')}" data-type="${get(item, 'type')}" data-index="${index}" data-item-id="${get(item, 'id')}">
  111. <div class="title"><h2><a href="${item.link}">${item.post_title}</a></h2></div>
  112. ${renderComments(item.comments)}
  113. ${
  114. get(item, 'type') === 'video'
  115. ? `<video class="media" muted webkit-playsinline playsinline preload="auto" src="${get(item, 'src')}" ${get(item, 'type')}></video>
  116. <b class="tip muted">${option('language', 'unmute')}</b>`
  117. : `<div class="blur-bg" style="background-image: url('${get(item, 'src')}') "></div><div class="image-container" ><img loading="auto" class="media" src="${get(item, 'src')}" ${get(item, 'type')} alt=""/></div>
  118. `}
  119. ${
  120. get(item, 'link')
  121. ? `<a class="tip link" href="${get(item, 'link')}" rel="noopener" target="_blank">
  122. ${!get(item, 'linkText') || get(item, 'linkText') === '' ? option('language', 'visitLink') : get(item, 'linkText')}
  123. </a>`
  124. : ''
  125. }
  126. </div>`;
  127. },
  128. timelineItem: function(itemData) {
  129. lazy = itemData['index'] == 5?'loading="auto" ':'';
  130. lazy = itemData['index'] > 5?'loading="lazy" ':lazy;
  131. return `<div class="story ${itemData['seen'] === true ? 'seen' : ''}">
  132. <a class="item-link" ${
  133. itemData['link'] ? `href="${itemData['link'] || ''}"` : ''
  134. }>
  135. <span class="item-preview">
  136. <img lazy="eager" ${lazy}src="${
  137. itemData['currentPreview']
  138. }" alt=""/>
  139. </span>
  140. <span class="info" itemProp="author" itemScope itemType="http://schema.org/Person">
  141. <strong class="name" itemProp="name">${itemData['name']}</strong>
  142. <span class="time"></span>
  143. </span>
  144. </a>
  145. <ul class="items"></ul>
  146. </div>`;
  147. },
  148. viewerItem: function (storyData, currentStoryItem) {
  149. var date = new Date(storyData.lastUpdated*1000);
  150. return `<div class="story-viewer">
  151. <div class="head">
  152. <div class="left">
  153. <a class="back">&lsaquo;</a>
  154. <span class="item-preview">
  155. <img lazy="eager" class="profilePhoto" src="${get(storyData, 'photo')}" alt="${get(storyData, 'name')}" />
  156. </span>
  157. <div class="info">
  158. <strong class="name">${get(storyData, 'name')}</strong>
  159. <span class="time">${date.toLocaleDateString()}</span>
  160. </div>
  161. </div>
  162. <div class="right">
  163. <span class="time">${get(currentStoryItem, 'timeAgo')}</span>
  164. <span class="loading"></span>
  165. <a class="close" tabIndex="2">&times;</a>
  166. </div>
  167. </div>
  168. <div class="slides-pointers">
  169. <div class="wrap"></div>
  170. </div>
  171. <div class="slides-pagination">
  172. <span class="previous">&lsaquo;</span>
  173. <span class="next">&rsaquo;</span>
  174. </div>
  175. </div>`;
  176. },
  177. }
  178. });
  179. var stories_container = document.getElementById("stories");
  180. addEventListener('wheel', (event) => {});
  181. stories_container.onwheel = (e) => {
  182. e.preventDefault();
  183. stories_container.scrollLeft+=e.wheelDeltaY
  184. return false;
  185. };
  186. </script>