From b4536988c0141c6eca50647bc69df917d3e773fa Mon Sep 17 00:00:00 2001 From: "stephen@cubedesigners.com" Date: Wed, 4 May 2016 18:57:24 +0000 Subject: [PATCH] #simeox Add news page functionality with infinite scroll, change position of language switcher to header and tidy up layout and styles #372 | #373 @8h --- framework/application/Bootstrap.php | 1 + framework/application/Simeox/News.php | 39 ++++++ .../controllers/AjaxController.php | 4 +- framework/application/forms/CMS/News.php | 15 +++ framework/application/forms/CMS/Sub/News.php | 39 ++++++ framework/application/forms/Element/News.php | 12 ++ framework/application/models/News.php | 21 +++ .../views/scripts/common/body.phtml | 15 +++ .../views/scripts/common/content.phtml | 4 +- .../views/scripts/common/footer.phtml | 4 - .../views/scripts/common/header.phtml | 16 ++- .../views/scripts/templates/home.phtml | 2 + .../views/scripts/templates/news.phtml | 16 +++ .../views/scripts/templates/text.phtml | 2 - js/news.js | 122 ++++++++++++++++++ less/common.less | 4 + less/home.less | 9 ++ less/navigation.less | 23 +++- less/news.less | 122 ++++++++++++++++++ 19 files changed, 453 insertions(+), 17 deletions(-) create mode 100644 framework/application/Simeox/News.php create mode 100644 framework/application/forms/CMS/News.php create mode 100644 framework/application/forms/CMS/Sub/News.php create mode 100644 framework/application/forms/Element/News.php create mode 100644 framework/application/models/News.php create mode 100644 framework/application/views/scripts/common/body.phtml create mode 100644 framework/application/views/scripts/templates/news.phtml create mode 100644 js/news.js create mode 100644 less/home.less create mode 100644 less/news.less diff --git a/framework/application/Bootstrap.php b/framework/application/Bootstrap.php index c8c9a6e..5c81d66 100644 --- a/framework/application/Bootstrap.php +++ b/framework/application/Bootstrap.php @@ -16,6 +16,7 @@ class Bootstrap extends CubeIT_Bootstrap { public function getCMSTemplates() { $templates = parent::getCMSTemplates(); $templates['text'] = 'Page de texte'; + $templates['news'] = 'Actualités'; return $templates; } diff --git a/framework/application/Simeox/News.php b/framework/application/Simeox/News.php new file mode 100644 index 0000000..5b54c57 --- /dev/null +++ b/framework/application/Simeox/News.php @@ -0,0 +1,39 @@ + 1) ? 1 : $page; + //fb('Fetching page #'. $page); + + + $db = Bootstrap::getInstance()->getDb(); + $news_result = $db->select()->from('news') + ->order('date DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->query() + ->fetchAll(); + + $news_result = CubeIT_Util_Cms::unserialize($news_result); + + $news = array(); + + foreach ($news_result as $n) { + + $date = new CubeIT_Date($n->date, CubeIT_Date::MYSQL); + + $news[] = array( + 'date' => $date->toString('dd/MM/YYYY'), + 'headline' => $n->headline, + 'content' => Bootstrap::getInstance()->getView()->markupDotclear($n->content, array(), array('class' => 'news-content')), + 'image' => Bootstrap::getInstance()->getView()->imageProcess($n->image, $n->headline, self::$imageSize, self::$imageSize, array(), 'C', 'C', 'M', false, 'auto', 'transparent') + ); + } + + return CubeIT_Util_Cms::unserialize($news); + } +} \ No newline at end of file diff --git a/framework/application/controllers/AjaxController.php b/framework/application/controllers/AjaxController.php index 7cef670..df33fd3 100644 --- a/framework/application/controllers/AjaxController.php +++ b/framework/application/controllers/AjaxController.php @@ -2,7 +2,9 @@ class AjaxController extends CubeIT_Controller_AjaxController { - + public function news($page = 1, $perPage = 5) { + $this->_datas->addVariable('data', Simeox_News::getNews($page, $perPage)); + } } diff --git a/framework/application/forms/CMS/News.php b/framework/application/forms/CMS/News.php new file mode 100644 index 0000000..3d99ca2 --- /dev/null +++ b/framework/application/forms/CMS/News.php @@ -0,0 +1,15 @@ +setLabel(__('Titre')); + $this->addElement($title); + + $news = new Simeox_Form_Element_News('news_items'); + $news->setLabel(__('Gestion des actualités')); + $this->addElement($news); + } +} \ No newline at end of file diff --git a/framework/application/forms/CMS/Sub/News.php b/framework/application/forms/CMS/Sub/News.php new file mode 100644 index 0000000..969026f --- /dev/null +++ b/framework/application/forms/CMS/Sub/News.php @@ -0,0 +1,39 @@ +addElement($id); + + $date = new CubeIT_Form_Element_Date('date'); + $date->setPrecision(Zend_Date::DAY); + $date->setLabel(__('Date')); + $this->addElement($date); + + $headline = new Zend_Form_Element_Text('headline'); + $headline->setLabel(__('Titre')); + $this->addElementLocalized($headline, $isCompactTrad); + + $content = new Simeox_Form_Element_Markitup('content'); + $content->setLabel(__('Contents')); + $this->addElementLocalized($content, $isCompactTrad); + + $image = new CubeIT_Form_Element_File_Image('image'); + $image->setLabel(__('Image')); + $this->addElement($image); + + $this->setListTitle(__('Actualités')); + $this->setNewTitle(__('Nouvelle actualité')); + $this->setEditTitle(__('Edition de l\'actualité « $headline »')); + $this->setModel('Simeox_Model_News'); + $this->setTitleColumn('headline'); + $this->setAdditionnalColumns(array('date')); + + } + +} diff --git a/framework/application/forms/Element/News.php b/framework/application/forms/Element/News.php new file mode 100644 index 0000000..7d9b4ee --- /dev/null +++ b/framework/application/forms/Element/News.php @@ -0,0 +1,12 @@ +setBaseForm(new Simeox_Form_CMS_Sub_News()); + $this->clearDecorators(); + } + +} \ No newline at end of file diff --git a/framework/application/models/News.php b/framework/application/models/News.php new file mode 100644 index 0000000..f35e99b --- /dev/null +++ b/framework/application/models/News.php @@ -0,0 +1,21 @@ + 'date'); + + public static function getSchema($schema) { + $table = parent::getSchema($schema); + $table->addColumn('date', 'datetime'); + $table->addColumn('headline', 'text'); + $table->addColumn('content', 'text'); + $table->addColumn('image', 'text'); + } + +} \ No newline at end of file diff --git a/framework/application/views/scripts/common/body.phtml b/framework/application/views/scripts/common/body.phtml new file mode 100644 index 0000000..ca65cad --- /dev/null +++ b/framework/application/views/scripts/common/body.phtml @@ -0,0 +1,15 @@ +body_class . ' ' . $this->bodyClass; + +$class = isset($this->navigation()->view->currentPage) ? $this->navigation()->view->currentPage->getName() : ''; // Or should it be label? +$class.=' '.$bodyClass; + +echo '' . "\n"; +echo $this->bannerCookies(); +echo $this->render('admin/mockup.phtml'); +echo $this->render('admin/nav.phtml'); +echo $this->render('common/content.phtml'); +echo $this->render('ajax/loader.phtml'); +echo "\n" . '' . "\n"; \ No newline at end of file diff --git a/framework/application/views/scripts/common/content.phtml b/framework/application/views/scripts/common/content.phtml index 122b225..8b6548c 100644 --- a/framework/application/views/scripts/common/content.phtml +++ b/framework/application/views/scripts/common/content.phtml @@ -1,10 +1,10 @@ layout()->content; +$content = $this->htmlElement($this->layout()->content, 'div', array('class' => 'content content-wrapper')); //$admin = $this->admin ? ' admin' : ''; echo '
'; echo $this->render('common/header.phtml'); -echo $this->htmlElement($c, 'main', array('class' => '')); +echo $this->htmlElement($content, 'main', array('class' => '')); echo $this->render('common/footer.phtml'); \ No newline at end of file diff --git a/framework/application/views/scripts/common/footer.phtml b/framework/application/views/scripts/common/footer.phtml index 2ffdc7a..cc06d6b 100644 --- a/framework/application/views/scripts/common/footer.phtml +++ b/framework/application/views/scripts/common/footer.phtml @@ -1,9 +1,5 @@ \ No newline at end of file diff --git a/framework/application/views/scripts/common/header.phtml b/framework/application/views/scripts/common/header.phtml index 0897677..facb094 100644 --- a/framework/application/views/scripts/common/header.phtml +++ b/framework/application/views/scripts/common/header.phtml @@ -3,7 +3,7 @@ $this->headScript()->addScriptAndStyle('navigation'); // Major nav sections -$sections = array('simeox', 'clinic', 'about', 'contact'); +$sections = array('simeox', 'clinic', 'about', 'news', 'contact'); $data = CubeIT_Util_Cms::getCMSDatasOfPage('home'); @@ -20,10 +20,22 @@ $data = CubeIT_Util_Cms::getCMSDatasOfPage('home'); + + localeNavigation(true, CubeIT_View_Helper_LocaleNavigation::BIGRAMME); ?> + \ No newline at end of file diff --git a/framework/application/views/scripts/templates/home.phtml b/framework/application/views/scripts/templates/home.phtml index 00d88bd..92af6b6 100644 --- a/framework/application/views/scripts/templates/home.phtml +++ b/framework/application/views/scripts/templates/home.phtml @@ -1,5 +1,7 @@ headScript()->addScriptAndStyle('home'); + echo $this->render('home/hero.phtml'); echo $this->render('home/simeox.phtml'); echo $this->render('home/rdclinic.phtml'); diff --git a/framework/application/views/scripts/templates/news.phtml b/framework/application/views/scripts/templates/news.phtml new file mode 100644 index 0000000..0f24290 --- /dev/null +++ b/framework/application/views/scripts/templates/news.phtml @@ -0,0 +1,16 @@ +headScript()->addScriptAndStyle('news'); + +?> + +

title ?>

+ +
+
+ +
+
Loading...
+
\ No newline at end of file diff --git a/framework/application/views/scripts/templates/text.phtml b/framework/application/views/scripts/templates/text.phtml index e48956c..c61f059 100644 --- a/framework/application/views/scripts/templates/text.phtml +++ b/framework/application/views/scripts/templates/text.phtml @@ -1,5 +1,3 @@ headScript()->addScriptAndStyle('text'); -echo '
'; echo $this->markupDotclear($this->text); -echo '
'; diff --git a/js/news.js b/js/news.js new file mode 100644 index 0000000..fb19d31 --- /dev/null +++ b/js/news.js @@ -0,0 +1,122 @@ +registerLoader(load_newsfeed); + +var currentPage = 1, + scrollBufferTrigger = $(window).height() / 5, // How many pixels from bottom before next AJAX event is fired + isLoading = false, + allDataLoaded = false; + +//--- INIT ---// +function load_newsfeed() { + + $('.loader').hide(); + + // Initial load of data via AJAX + loadMoreContent(fillPage); + + + //-- Infinite Scroll: track scroll position and load more data when needed --// + $(window).scroll(function () { + + var dh = $(document).height(), + wh = $(window).height(), + top = $(window).scrollTop(); + + // Trigger will be true {scrollBufferTrigger}px above bottom of page + var triggerPoint = (dh < wh) || (top >= dh - wh - scrollBufferTrigger); + + if (!allDataLoaded && !isLoading && triggerPoint) { + loadMoreContent(); + } + }); + + + //-- Handle show/hide link clicks + $(document).on('click', 'a.read-more', function() { + + var content = $(this).siblings('.news-content'); + + if (content.hasClass('open')) { + content.removeClass('open'); + $(this).text($(this).data('closed')); + } else { + content.addClass('open'); + $(this).text($(this).data('open')); + } + + return false; + }); +} + +// Ensure we have loaded enough to be able to scroll +function fillPage() { + // If we don't have a full window of content, the scroll + // trigger won't fire, so load more content until it can + if ($(document).height() <= $(window).height()) { + console.info('fillpage ' + currentPage); + loadMoreContent(fillPage); + } +} + +//-----------------------// + +function loadMoreContent(callback) { + + var $container = $('#newsFeed'), + readMoreClosed = $container.data('read-more-closed'), + readMoreOpen = $container.data('read-more-open'); + + var dataURL = '/ajax/news/' + currentPage; + + isLoading = true; + $('.loader').show(); + + $.getJSON(dataURL, function (result) { + + if (result.vars.data.length == 0) { // No more data + fb('End of data.'); + allDataLoaded = true; + + } else { + + var elems = []; + + $.each(result.vars.data, function (key, data) { + + fb('loaded page #' + currentPage); + + var res, image; + + res = '
' + data.image + '
'; + res += '
'; + res += ''; + res += '

' + data.headline + '

'; + res += data.content; // MarkupDotClear view helper already wraps content in a div + + // Add the open/close link + res += ''+ readMoreClosed +''; + + res += '
'; // .news-body + + // Add items + var elem = document.createElement('article'); + elem.innerHTML = res; + elem.className = 'news-item'; + elems.push(elem); + }); + + // Add new items to container and update Masonry + $container.append(elems); + + currentPage++; + + if (typeof callback === "function") { + callback(); + } + } + + //fb('finished loading'); + isLoading = false; + $('.loader').hide(); + + }); +} \ No newline at end of file diff --git a/less/common.less b/less/common.less index cf03d8b..4ee1b31 100644 --- a/less/common.less +++ b/less/common.less @@ -50,6 +50,10 @@ p { line-height: 1.5; } +.content-wrapper { + padding-bottom: 20px; +} + .content { width: 960px; margin: 0 auto; diff --git a/less/home.less b/less/home.less new file mode 100644 index 0000000..297aa09 --- /dev/null +++ b/less/home.less @@ -0,0 +1,9 @@ +body.home { + + .content-wrapper { + width: 100%; + margin: 0; + padding: 0; + } + +} \ No newline at end of file diff --git a/less/navigation.less b/less/navigation.less index d72877e..4cd7aef 100644 --- a/less/navigation.less +++ b/less/navigation.less @@ -26,8 +26,8 @@ nav.primary { } li { - margin-left: 68px; - &[data-i='0'] { + margin-left: 30px; + &:first-of-type { margin-left: 0; } } @@ -36,18 +36,29 @@ nav.primary { nav.locale { font-size: 11px; font-weight: 300; - float: right; + position: absolute; + right: 0; + top: 15px; + opacity: 1; + transition: opacity 0.1s ease-in; + backface-visibility: hidden; + + .small & { + //display: none; + opacity: 0; + top: -100%; + } a { display: inline-block; - margin: 8px 0 0 5px; + margin-left: 5px; width: 28px; height: 28px; line-height: 28px; text-align: center; border-radius: 50%; - background-color: #444; - color: #999; + background-color: #ececec; + color: #818181; text-transform: uppercase; &:hover, &.active { diff --git a/less/news.less b/less/news.less new file mode 100644 index 0000000..bc4e5e6 --- /dev/null +++ b/less/news.less @@ -0,0 +1,122 @@ +.page-heading { + margin-bottom: 110px; +} + +.news-item { + overflow: hidden; + padding-bottom: 55px; + border-bottom: 1px solid #dadada; + margin-bottom: 55px; +} + +.news-image { + float: left; + margin-right: 45px; + img { + border-radius: 100%; + } +} + +.news-body { + overflow: hidden; +} + +.news-date { + font-size: 12px; + font-weight: 300; +} + +.news-headline { + font-size: 32px; + font-weight: 300; + margin: 15px 0 25px; +} + +.news-content { + overflow: hidden; + max-height: 3em; // Line height is 1.5 so 3em = 2 lines visible + + &.open { + max-height: none; + } + + p { + &:first-of-type { + padding-top: 0; + } + } +} + +.read-more { + font-size: 16px; + font-weight: 600; + color: #000; + display: block; + margin-top: 1em; +} + + +//--------- Loading Animation ---------// +// Credit: http://projects.lukehaas.me/css-loaders/ + +.loader-container { + opacity: 0.2; + overflow: hidden; +} + +.loader:before, +.loader:after, +.loader { + border-radius: 50%; + width: 2.5em; + height: 2.5em; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation: load7 1.8s infinite ease-in-out; + animation: load7 1.8s infinite ease-in-out; +} +.loader { + margin: 1em auto 6em auto; + font-size: 10px; + position: relative; + text-indent: -9999em; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation-delay: -0.16s; + animation-delay: -0.16s; +} +.loader:before { + left: -3.5em; + -webkit-animation-delay: -0.32s; + animation-delay: -0.32s; +} +.loader:after { + left: 3.5em; +} +.loader:before, +.loader:after { + content: ''; + position: absolute; + top: 0; +} +@-webkit-keyframes load7 { + 0%, + 80%, + 100% { + box-shadow: 0 2.5em 0 -1.3em #000; + } + 40% { + box-shadow: 0 2.5em 0 0 #000; + } +} +@keyframes load7 { + 0%, + 80%, + 100% { + box-shadow: 0 2.5em 0 -1.3em #000; + } + 40% { + box-shadow: 0 2.5em 0 0 #000; + } +} \ No newline at end of file -- 2.39.5