Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

centered fitRows #1143

Open
mariodermez opened this issue Jul 30, 2016 · 11 comments
Open

centered fitRows #1143

mariodermez opened this issue Jul 30, 2016 · 11 comments

Comments

@mariodermez
Copy link

mariodermez commented Jul 30, 2016

http://jsfiddle.net/desandro/P6JGY/24/

I will use this jsfiddle as it is supposed to be an answer on centering items within isotope.
Well it's not. Centering items means equal space from the sides per row of elements like in the image below. Why is this so hard to be achieved? I've paid almost 2000 euros in senior developers and no one could give me a fixed version of isotope with items centered like this. They were always floating to the left which is visually bad.
fbxcu

@mariodermez
Copy link
Author

mariodermez commented Jul 30, 2016

@desandro in your jsfiffle if you replace html with this below you will see what I mean.

<div id="container">
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
  <div class="item w1 h1"></div>
</div>

@ingedev
Copy link

ingedev commented Oct 5, 2016

I am THIS close to achieving this with a fitRows based layout and the code fragments supplied by genielabs in this thread: #428

I have created a plugin as such:

/*jshint browser: true, strict: true, undef: true, unused: true */

(function (window, factory) {
    'use strict';
    // universal module definition
    if (typeof define === 'function' && define.amd) {
        // AMD
        define([
            'get-size/get-size',
            'isotope/js/layout-mode'
        ],
          factory);
    } else if (typeof module == 'object' && module.exports) {
        // CommonJS
        module.exports = factory(
          require('get-size'),
          require('isotope-layout/js/layout-mode')
        );
    } else {
        // browser global
        factory(
          window.getSize,
          window.Isotope.LayoutMode
        );
    }

}(window, function factory(getSize, LayoutMode) {
    'use strict';

    // -------------------------- definition -------------------------- //

    // create an Outlayer layout class
    var FitRowsCentered = LayoutMode.create('fitRowsCentered');
    var proto = FitRowsCentered.prototype;

    proto._resetLayout = function () {
        // pre-calculate offsets for centering each row
        this.x = 0;
        this.y = 0;
        this.maxY = 0;
        this._getMeasurement('gutter', 'outerWidth');
        this.centerX = [];
        this.currentRow = 0;
        this.initializing = true;

        for (var i = 0, len = this.items.length; i < len; i++) {
            var item = this.items[i];
            this._getItemLayoutPosition(item);
        }

        this.centerX[this.currentRow].offset = (this.isotope.size.innerWidth + this.gutter - this.x) / 2;

        this.initializing = false;
        this.currentRow = 0;

        // centered offsets were calculated, reset layout
        this.x = 0;
        this.y = 0;
        this.maxY = 0;

        this._getMeasurement('gutter', 'outerWidth');
    };

    proto._getItemLayoutPosition = function (item) {
        item.getSize();
        var itemWidth = item.size.outerWidth + this.gutter;
        // if this element cannot fit in the current row
        var containerWidth = this.isotope.size.innerWidth + this.gutter;
        if (this.x !== 0 && itemWidth + this.x > containerWidth) {

            if (this.initializing)
                this.centerX[this.currentRow].offset = (containerWidth - this.x) / 2;
            this.currentRow++;

            this.x = 0;
            this.y = this.maxY;
        }

        if (this.initializing && this.x == 0) {
            this.centerX.push({ offset: 0 });
        }

        var position = {
            x: this.x + (this.initializing ? 0 : this.centerX[this.currentRow].offset),
            y: this.y
        };

        this.maxY = Math.max(this.maxY, this.y + item.size.outerHeight);
        this.x += itemWidth;

        return position;
    };

    proto._getContainerSize = function () {
        return { height: this.maxY };
    };

    return FitRowsCentered;

}));

It works perfectly on initial load. However, I am having issues when I use it with filtering. Once I call

$('#modulesGrid').isotope({ filter: selector, animationOptions: { duration: 300, easing: 'easeOutQuart' } });

the items are initially left-aligned. However, after clicking the same filtering link a second time, the items center perfectly.

Would it be possible to somehow collaborate to make this work? All credits to genielabs for the initial code, by the way, all I did was turn it into a plugin.

@ingedev
Copy link

ingedev commented Oct 7, 2016

I figured out what the issue was with the above solution when used in combination with filters. Instead of looping through the items, I needed to loop through the filtered items. I am attaching a file that works for me.

Please note it has not been tested very thoroughly yet and I am using it in combination with Bootstrap columns. No fixed column widths in my scenario. Other scenarios have not been tested yet. I just wanted to leave it here in case it helps someone else who is looking for a similar solution. And maybe David can have a look at it and see if he can possibly polish it up a bit and see if he can make it available for others.

Again, please note that 95% of this solution was written by genielabs in the other thread I linked to above.

isotope.fitRows.centered.zip

@desandro desandro changed the title Centering elements in isotope centered fitRows Oct 24, 2016
@desandro
Copy link
Member

desandro commented Oct 24, 2016

Add a 👍 reaction to this issue if you would like to see this feature added. Do not add +1 comments — They will be deleted.


@ingedev Thank you so much for your contribution here.

I needed to loop through the filtered items

Unfortunately, Isotope v2 (and now v3) doesn't provide an easy way to do this. That's why I've held off on implementing this kind of layout mode. If others are interested in the layout mode, I can look back into it.

@mightym
Copy link

mightym commented Nov 15, 2016

Absolutely interested in. Something I often needed in the past and sadly couldn't achieve 100% by using isotope

@lukedanielson
Copy link

Hey @ingedev, may I ask how you load up Isotope/Masonry and your plugin? I am loading via Webpack, and have everything working via:

   "plugins":  [
     "./../node_modules/isotope-layout/dist/isotope.pkgd.js",
     "./../node_modules/imagesloaded/imagesloaded.pkgd.js",
    ],

But when I add your plugin like so:

   "plugins":  [
     "./../node_modules/isotope-layout/dist/isotope.pkgd.js",
     "./../node_modules/imagesloaded/imagesloaded.pkgd.js",
     "./scripts/util/isotope.FitRows.centered.js"
    ],

I get the error thrown from the base isotope package:

Uncaught Error: No layout mode: fitRowsCentered

(isotope.pkgd.js:3392):

throw new Error( 'No layout mode: ' + layoutMode );

A little new to webpack and js modules; any and all help greatly appreciated!

@metafizzy metafizzy deleted a comment from n8-dev Aug 4, 2017
@metafizzy metafizzy deleted a comment from cdkth Dec 21, 2017
@metafizzy metafizzy deleted a comment from pixedelic Dec 21, 2017
@metafizzy metafizzy deleted a comment from sube1even Dec 21, 2017
@FrancesCoronel
Copy link

@ingedev Thank you so much - your solution worked for me. 🥇

@HandHugs
Copy link

HandHugs commented Mar 8, 2018

I have some code that initiates isotope a few times on a page and is triggered by one filter. Similar to this example: #1026

This works for this example on page load, but when the filter is triggered, my solution for hiding empty sections stops working and the filter doesn't work properly either.

Here are two codepens:
WORKING - with fitRows
https://codepen.io/anon/pen/pLzOWO

ERROR - with fitRowsCentered
https://codepen.io/anon/pen/OvLodQ

Any ideas on how to get the centered layout to work for my case? Thank you!

-edit- it seems to only have the issue when the filter is applied to more than one iteration of a container on a page. Still stumped on where the error is though. Any ideas?

@lofcz
Copy link

lofcz commented Jul 17, 2019

@ingedev's solution does not work with ajax loaded elements.

@lofcz
Copy link

lofcz commented Jul 17, 2019

Fixed @ingedev's solution to work with ajax loaded content

(function (window, factory) {
    'use strict';
    // universal module definition
    if (typeof define === 'function' && define.amd) {
        // AMD
        define([
            'get-size/get-size',
            'isotope/js/layout-mode'
        ],
          factory);
    } else if (typeof module == 'object' && module.exports) {
        // CommonJS
        module.exports = factory(
          require('get-size'),
          require('isotope-layout/js/layout-mode')
        );
    } else {
        // browser global
        factory(
          window.getSize,
          window.Isotope.LayoutMode
        );
    }

}(window, function factory(getSize, LayoutMode) {
    'use strict';

    // -------------------------- definition -------------------------- //

    // create an Outlayer layout class
    var FitRowsCentered = LayoutMode.create('fitRowsCentered');
    var proto = FitRowsCentered.prototype;

    proto._resetLayout = function () {
        // pre-calculate offsets for centering each row
        this.x = 0;
        this.y = 0;
        this.maxY = 0;
        this._getMeasurement('gutter', 'outerWidth');
        this.centerX = [];
        this.currentRow = 0;
        this.initializing = true;

        console.log(this.isotope);

        for (var i = 0, len = this.isotope.items.length; i < len; i++) {
            var item = this.isotope.items[i];
            this._getItemLayoutPosition(item);
        }

        //alert(this.isotope.filteredItems.length);

        this.centerX[this.currentRow].offset = (this.isotope.size.innerWidth + this.gutter - this.x) / 2;

        this.initializing = false;
        this.currentRow = 0;

        // centered offsets were calculated, reset layout
        this.x = 0;
        this.y = 0;
        this.maxY = 0;

        this._getMeasurement('gutter', 'outerWidth');
    };

    proto._getItemLayoutPosition = function (item) {
        item.getSize();
        var itemWidth = item.size.outerWidth + this.gutter;
        // if this element cannot fit in the current row
        var containerWidth = this.isotope.size.innerWidth + this.gutter;
        if (this.x !== 0 && itemWidth + this.x > containerWidth) {

            if (this.initializing)
                this.centerX[this.currentRow].offset = (containerWidth - this.x) / 2;
            this.currentRow++;

            this.x = 0;
            this.y = this.maxY;
        }

        if (this.initializing && this.x == 0) {
            this.centerX.push({ offset: 0 });
          //  alert("kokot");
        }

        var position;

        if (typeof this.centerX[this.currentRow] !== 'undefined') {
             position = {
                x: this.x + (this.initializing ? 0 : this.centerX[this.currentRow].offset),
                y: this.y
            };
        } else {
             position = {
                x: this.x,
                y: this.y
            };
        }

       

        this.maxY = Math.max(this.maxY, this.y + item.size.outerHeight);
        this.x += itemWidth;

        return position;
    };

    proto._getContainerSize = function () {
        return { height: this.maxY };
    };

    return FitRowsCentered;

}));

Save yourself a headache and use this.

@PlopTheReal
Copy link

Any idea on doing the same centering but with the masonry layout (not fixed width items) @lofcz ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

9 participants