stories.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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->id,
  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->id,
  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. "internal_id"=>$news_item->id,
  58. "comments"=>base64_encode(json_encode($comments))
  59. ]
  60. ]
  61. ];
  62. $index++;
  63. }
  64. return json_encode($data);
  65. },60*5);
  66. ?>
  67. <script>
  68. const get = function (array, what) {
  69. if (array) {
  70. return array[what] || '';
  71. } else {
  72. return '';
  73. }
  74. };
  75. const renderComments = function (comments){
  76. let html = "";
  77. var j;
  78. try{
  79. let commentsArr = JSON.parse(atob(comments));
  80. if("object" === typeof commentsArr && commentsArr.length>0){
  81. html+='<div class="comments">';
  82. for(let i = 0; i < commentsArr.length; i++){
  83. j = commentsArr[i];
  84. html+=`<div class="comment"><div class="message">${j.message}</div><div class="published_at">${j.published_at}</div></div>`
  85. }
  86. html+='</div>';
  87. }
  88. } catch (e){
  89. }
  90. return html;
  91. }
  92. let stories = new Zuck("stories",{
  93. skin: 'snapgram',
  94. avatars: false, // shows user photo instead of last story item preview
  95. list: false, // displays a timeline instead of carousel
  96. openEffect: false, // enables effect when opening story
  97. cubeEffect: false, // enables the 3d cube effect when sliding story
  98. autoFullScreen: false, // enables fullscreen on mobile browsers
  99. backButton: true, // adds a back button to close the story viewer
  100. backNative: false, // uses window history to enable back button on browsers/android
  101. previousTap: true, // use 1/3 of the screen to navigate to previous item when tap the story
  102. localStorage: true, // set true to save "seen" position. Element must have a id to save properly.
  103. reactive: false, // set true if you use frameworks like React to control the timeline (see react.sample.html)
  104. rtl: false, // enable/disable RTL
  105. paginationArrows:false,
  106. stories: <?=$stories?>,
  107. template: {
  108. viewerItemBody: function (index, currentIndex, item) {
  109. console.log(item);
  110. return `<div
  111. class="item ${get(item, 'seen') === true ? 'seen' : ''} ${currentIndex === index ? 'active' : ''}"
  112. data-time="${get(item, 'time')}" data-type="${get(item, 'type')}" data-index="${index}" data-item-id="${get(item, 'internal_id')}" data-story-id="${get(item, 'internal_id')}">
  113. <div class="title"><h2><a href="${item.link}">${item.post_title}</a></h2></div>
  114. ${renderComments(item.comments)}
  115. <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>
  116. <a class="tip link" href="${get(item, 'link')}" rel="noopener" target="_blank">
  117. ${!get(item, 'linkText') || get(item, 'linkText') === '' ? option('language', 'visitLink') : get(item, 'linkText')}
  118. </a>
  119. </div>`;
  120. },
  121. timelineItem: function(itemData) {
  122. lazy = itemData['index'] == 5?'loading="auto" ':'';
  123. lazy = itemData['index'] > 5?'loading="lazy" ':lazy;
  124. return `<div class="story ${itemData['seen'] === true ? 'seen' : ''}">
  125. <a class="item-link" ${
  126. itemData['link'] ? `href="${itemData['link'] || ''}"` : ''
  127. }>
  128. <span class="item-preview">
  129. <img lazy="eager" ${lazy}src="${
  130. itemData['currentPreview']
  131. }" alt=""/>
  132. </span>
  133. <span class="info" itemProp="author" itemScope itemType="http://schema.org/Person">
  134. <strong class="name" itemProp="name">${itemData['name']}</strong>
  135. <span class="time"></span>
  136. </span>
  137. </a>
  138. <ul class="items"></ul>
  139. </div>`;
  140. },
  141. viewerItem: function (storyData, currentStoryItem) {
  142. var date = new Date(storyData.lastUpdated*1000);
  143. return `<div class="story-viewer" data-story-id="${get(currentStoryItem, 'internal_id')}">
  144. <div class="head">
  145. <div class="left">
  146. <a class="back">&lsaquo;</a>
  147. <span class="item-preview">
  148. <img lazy="eager" class="profilePhoto" src="${get(storyData, 'photo')}" alt="${get(storyData, 'name')}" />
  149. </span>
  150. <div class="info">
  151. <strong class="name">${get(storyData, 'name')}</strong>
  152. <span class="time">${date.toLocaleDateString()}</span>
  153. </div>
  154. </div>
  155. <div class="right">
  156. <span class="time">${get(currentStoryItem, 'timeAgo')}</span>
  157. <span class="loading"></span>
  158. <a class="close" tabIndex="2">&times;</a>
  159. </div>
  160. </div>
  161. <div class="slides-pointers">
  162. <div class="wrap"></div>
  163. </div>
  164. <div class="slides-pagination">
  165. <span class="previous"><img src="/js/zuck/dist/img/previous.svg" alt="previous" width="50" height="50"></span>
  166. <span class="next"><img src="/js/zuck/dist/img/next.svg" alt="next" width="50" height="50"></span>
  167. </div>
  168. </div>`;
  169. },
  170. }
  171. });
  172. const getCurrentIndex = function ()
  173. {
  174. return stories.data.filter((story) => story.id==stories.internalData.currentStory)[0].index;
  175. }
  176. stories.back = function ()
  177. {
  178. let previousIndex = getCurrentIndex() - 1;
  179. if( previousIndex < 0) previousIndex = stories.data.length -1;
  180. stories.navigateItem(previousIndex)
  181. }
  182. var stories_container = document.getElementById("stories");
  183. addEventListener('wheel', (event) => {});
  184. stories_container.onwheel = (e) => {
  185. e.preventDefault();
  186. stories_container.scrollLeft+=e.wheelDeltaY
  187. return false;
  188. };
  189. </script>