From 5bb91c440c18ea2bea56aba633f01a33e53decfe Mon Sep 17 00:00:00 2001 From: "stephen@cubedesigners.com" Date: Thu, 17 Jan 2019 16:08:18 +0000 Subject: [PATCH] WIP #2033 @5.5 --- .../views/helpers/CategoriesDropdown.php | 50 ++++ .../views/scripts/templates/casestudies.phtml | 4 +- js/isotope-select.js | 213 ++++++++++++++++++ less/casestudies.less | 5 + less/common.less | 11 + 5 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 framework/application/views/helpers/CategoriesDropdown.php create mode 100644 js/isotope-select.js diff --git a/framework/application/views/helpers/CategoriesDropdown.php b/framework/application/views/helpers/CategoriesDropdown.php new file mode 100644 index 0000000..7c81a3d --- /dev/null +++ b/framework/application/views/helpers/CategoriesDropdown.php @@ -0,0 +1,50 @@ +headScript()->addIsotope(); + $this->addScriptAndStyle('isotope-select'); + + $is_admin = Bootstrap::getInstance()->isAllowed("edition"); + $db = Zend_Db_Table::getDefaultAdapter(); + + // Get distinct list of categories present in the table + $select = $db->select() + ->from($table, [$table.'.categories']) + ->joinInner('categories', $table.'.categories = categories.id', ['categories.name']) + ->group($table.'.categories') + ->order('categories.sort_order ASC'); + + if (!$is_admin) { + $select->where($table.'.online = ?', 1); + } + + //echo 'QUERY: '. (string) $select; + + $query = $select->query(); + + $categories = [ + '' => __('Choisir un domaine...'), + '0' => __('Tout voir') + ]; + while ($row = $query->fetch()) { + $categories[$row->categories] = CubeIT_Util_Cms::unserialize($row->name); + } + + return $this->formSelect( + $listID . '-filter', // Select element's name + null, // Value + [ + // Attributes + 'class' => 'category-dropdown form-select', + 'data-container-id' => $listID, + 'data-column-width' => $columnWidth, + 'data-gutter' => $gutterSize + ], + $categories // Options + ); + } + +} diff --git a/framework/application/views/scripts/templates/casestudies.phtml b/framework/application/views/scripts/templates/casestudies.phtml index 5e52e0c..19253bf 100644 --- a/framework/application/views/scripts/templates/casestudies.phtml +++ b/framework/application/views/scripts/templates/casestudies.phtml @@ -6,9 +6,9 @@ $this->headScript()->addScriptAndStyle('casestudies');
markupDotclear($this->titre); ?>
-
+
CategoriesList('casestudies', 'casestudies-list', 512, 96); + echo $this->CategoriesDropdown('casestudies', 'casestudies-list', 512, 96); ?>
diff --git a/js/isotope-select.js b/js/isotope-select.js new file mode 100644 index 0000000..197a9a3 --- /dev/null +++ b/js/isotope-select.js @@ -0,0 +1,213 @@ +(function ($) { + function JQFilterList(element) { + + // Store name of the list + this.filterID = $(element).attr('id'); + this.storageID = this.filterID; + + + this.element = element; + this.columnWidth = parseInt(this.element.data('column-width')); + this.gutter = parseInt(this.element.data('gutter')); + //this.list = $(this.element.data('list')); + this.container = $('#' + this.element.data('container-id')); + + // Store font size for headings - used to scale fonts in resize function + this.headingSize = parseInt($(this.container).find('h2').css('font-size')); + + + // Persist filter settings + var initFilter = ''; // This will select the empty item the dropdown. Set to 0 to set it to the "all" label + if (Modernizr.sessionstorage) { + var f = sessionStorage.getItem(this.storageID); + if (f !== null) { + initFilter = f; + } + } + + this.init(initFilter); + } + + JQFilterList.prototype = { + init: function (initFilter) { + var $this = this; + + // Clear filter first... + $this.filter('none'); // Dummy value so nothing is selected + + // Set up Isotope + this.container.isotope({ + itemSelector: 'a', + layoutMode: 'masonry', + masonry: { + columnWidth: this.columnWidth, + gutter: this.gutter + }, + + transitionDuration: 0 // Disable isotope animations because they interfere with WOW.js + // animationOptions: { + // duration: 0, + // easing: 'linear', + // queue: false + // } + // hiddenStyle: { + // opacity: 0, + // transform: 'scale(2)' + // }, + // visibleStyle: { + // opacity: 1, + // transform: 'scale(1)' + // } + }); + + // Show the container now Isotope is active + this.container.css('display', 'block'); + + // Now run filter based on any previous settings + $this.filter(initFilter); + + // Reveal all items after init for onload animation + // https://github.com/metafizzy/isotope/issues/733#issuecomment-52868221 + //var iso = this.container.data('isotope'); + //this.container.isotope( 'reveal', iso.items ); + + // Also handle resizing of the window + $(window).on('cubeitresize', function () { + $this.resize(); + }); + $this.resize(); + window.setTimeout(function () { + $this.resize(); + }, 500); + + // Make sure grid is sized properly once page has loaded fully + $(window).on('load', function () { + $this.resize(); + }); + + + // Handle dropdown change + $(document).on('change', '#' + this.filterID, function () { + + var filterID = $(this).val(); + + if (filterID === '') return false; + + // Reset animations on elements for WOW.js when re-filtering + // Ref: https://github.com/matthieua/WOW/issues/46#issuecomment-133760823 + $this.container.find('a').each(function() { + + $(this).css({ + 'visibility' : 'hidden', + 'animation-name' : 'none' + }); + + $(this).removeClass('animated'); + + wow.addBox(this); + }); + + // Bump scroll so WOW.js runs... There must be a better way to do this + window.scrollTo(window.scrollX, window.scrollY + 1); + window.scrollTo(window.scrollX, window.scrollY - 1); + + $this.filter(filterID); + + return false; + }); + + }, + filter: function (id) { + + //fb('Filter ID: ' + id); + + // Select correct item in dropdown (useful when filter is updated programmatically) + this.element.val(id); + + var filterClass; + + if (id == 0) { + filterClass = '*'; + } else { + filterClass = '[data-cat="' + id + '"]'; + } + + //fb('Filtering... ' + filterClass); + this.container.isotope({ + filter: filterClass + }); + + // Save filter for future sessions + if (Modernizr.sessionstorage) { + sessionStorage.setItem(this.storageID, id); + } + }, + resize: function () { + + //fb('Running resize...'); + + var container = this.container + var margin = this.gutter; + var naturalWidth = this.columnWidth; + var scaleFactor = 1; + + var ww = Math.min($(window).width(), 1920); + + ww *= 0.8; // Remove margins (10% each side) + + // Handle extra padding that is added for small screens + //if ($('html').hasClass('small')) { + // ww = ww - parseInt($('#main .content').css('paddingLeft')) - parseInt($('#main .content').css('paddingRight')); + // ww = ww - 68; + //} + + var nbcol = Math.ceil(ww / (naturalWidth + margin)); + var ew = Math.floor((ww - (margin * (nbcol - 1))) / nbcol); + if (ew > naturalWidth) { + nbcol++; // Add a column when elements are too big + ew = Math.floor((ww - (margin * (nbcol - 1))) / nbcol); + } + + // Dynamically size text based on element width + if (ew < naturalWidth) { + scaleFactor = ew / naturalWidth; + $(container).find('h2').css('font-size', Math.ceil(scaleFactor * this.headingSize)); + } + + // Resize elements + var a = $(container).find('a'); + $(a).css('width', ew); + //var naturalHeight = $(a).find('img').attr('height'); + //var imageRatio = naturalWidth / naturalHeight; + //$(a).find('img').css({width: ew, height: ew / imageRatio}); + //$(a).find('.img-wrapper').css({width: ew, height: ew / imageRatio}); + + // Reset isotope grid + $(container).isotope({ + masonry: { + columnWidth: ew, + gutter: margin + } + }); + + } + + }; + + jQuery.fn.filterlist = function () { + return this.each(function () { + var $this = $(this); + $(this).data('filterlist', new JQFilterList($this)); + }); + }; +})(jQuery); + + +registerLoader(load_filterlist); + +function load_filterlist() { + + $('#main').css('overflow-y', 'hidden'); // Stops extra scrollbars appearing + + $('.category-dropdown').filterlist(); +} diff --git a/less/casestudies.less b/less/casestudies.less index 2f034ee..649ac1d 100644 --- a/less/casestudies.less +++ b/less/casestudies.less @@ -1,5 +1,10 @@ @import "00-constants"; +.casestudies-filter { + margin-bottom: 2em; + text-align: right; +} + .casestudies-list { //min-width: 980px; //max-width: 980px; diff --git a/less/common.less b/less/common.less index 6641cd5..836a233 100644 --- a/less/common.less +++ b/less/common.less @@ -191,3 +191,14 @@ a { } } + +// Standard select dropdown +.form-select { + appearance: none; + padding-right: 1.5em; + background: url('data:image/svg+xml;utf8,') center right no-repeat; + background-size: auto 0.4em; + border: none; + border-radius: 0; + font-size: 18px; +} -- 2.39.5