foundation / foundation-sites

The most advanced responsive front-end framework in the world. Quickly create prototypes and production code for sites that work on any kind of device.
https://get.foundation
MIT License
29.67k stars 5.48k forks source link

Foundation 6: JavaScript feedback #6197

Closed gakimball closed 9 years ago

gakimball commented 9 years ago

The current JavaScript for Foundation 5 is about 18 months old, and for version 6 we're looking to rewrite it all from scratch. This will allow us to follow more recent best practices and generally modernize the codebase.

Here are some requests we've gotten related to JavaScript:

One plan we already have for version 6 is to create a common API for certain components to tap into. While building Foundation for Apps, we realized most UI components are just different ways of opening and closing things, so we built a single API that can transmit open, close, and toggle commands to modals, panels, off-canvas, etc. We're going to take this same approach in Foundation for Sites, so:

<a data-reveal-open="modal">Open Modal</a>

Becomes:

<a data-open="modal">Open Modal</a>

We're also interested in potentially porting the Motion UI library from Foundation for Apps, so that both frameworks have access to the same set of animations.

To jQuery or not?

We've had some internal discussion on if it's worth writing the new plugins in pure JavaScript instead of using jQuery. The main reason is the file size, but jQuery 2 is just 32kB gzipped these days. And to be sure, there will be plenty of cases where we have to work around cross-browser inconsistencies, at which point we could have just used a framework that handles those edge cases for us. You may recall we used Zepto for Foundation 4, but we had to drop it because it wasn't as performant as jQuery, by a

Plugin Structure

Reworking the plugins also gives us the chance to change the way they're accessed in JavaScript. Right now we put every plugin inside a foundation() function on the jQuery object, but there's a few other routes we could take as well.

// Give every plugin its own function, although this could be a namespacing issue
$(document).reveal();
$(document).orbit();

// Use a separate object instead
var modal = new Foundation.Modal();
modal.open();

What we'd like to hear is how we could better structure our JavaScript. If you have feedback on the features of the plugins, we have other discussion topics for that as well.

View our other discussion topics for Foundation 6 here.

r3wt commented 9 years ago

extend jQuery.

$.foundation('reflow').done(function(){ 
     console.log('document reflowed :-]'); 
});
tikot commented 9 years ago

I think we should drop jQuery as a dependency! We should do something like AngularJS does use jQuery if ti's present if not then fallback to jQLite(its own implementation). So it pure JavaScript with a use of jQuery if present.

Also I want to bring up the subject of ES6.

mwq27 commented 9 years ago

+1 for CommonJS style modules. That'll really help us Browserify users out.

izakfilmalter commented 9 years ago

Ya I would heavily back a dual approach. Some people are gonna whine till the sun burns out if you drop jQuery. We've already gone through that. Offer two versions, one that is pure js, and one that is jQuery. A bit more work, but significantly more satisfaction.

ksherman commented 9 years ago

I love the idea of pure js and moving away from jQuery, but in all reality I already have to use jQuery all over the place for other plugins so I almost have to have it loaded everywhere.

LDigital84 commented 9 years ago

While I can understand the reason to use pure JS I personally feel that keeping jQuery is a good thing. I haven't developed a site in the past two years that hasn't used jQuery on it because it is so useful in so many cases for what I am developing.

Also, once you factor in the various cross-browser inconsistencies how much space are you really saving? As you noted jQuery is only 32kb g-zipped and if served from a CDN it most likely will already be cached.

joelkinzel commented 9 years ago

As much as I love jQuery, we maybe getting to a point where the cross browser functionality is less and less of an issue. Especially since we are talking probably a year out, possibly more before this version is released. Assuming Foundation moves to supporting "evergreen" browsers, then it really shouldn't be an issue at all (very minimal). Plus, native JS is going to perform much better on all devices, but especially on mobile.

gakimball commented 9 years ago

@joelkinzel A year out for Foundation 6? Not at all; it'll be out in a few months :)

Our browser support will be pretty much the same as with Foundation 5, but we're still going to mess with more bleeding-edge stuff like an optional flexbox grid.

tsquez commented 9 years ago

I like the two version approach @tikot and @izakfilmalter suggested, especially for those of us who use Foundation mixed with WordPress.

joelkinzel commented 9 years ago

@gakimball Ah! In that case, I could see the benefit of the two pronged approach. I would say for simplicity sake, jQuery version would support pretty much the same as F5, but the JS only version would be for the "evergreen" browsers. Just throwing thoughts out there...

coreysyms commented 9 years ago

Honestly I would like us to move to RequireJS since its use of AMD is beautiful in the browser. I have had really good experiences with JS modules in general and would prefer to stop having to hand type < script > tags and have always run in to issues with script dependency ordering. My company exclusively uses Foundation and we build large scale high profile sites. We use a CMS and front-end a framework to build our sites. Using the dependancies however causes bloat or a wild stream of case statements to cut down on pages that do / don't require certain plugins. Switching over to a modular system would boost Foundation to more of an enterprise solution for building sites IMHO.

Also RequireJS doesn't require jQuery, even though I love jQuery, so if F7 moved to something else instead of jQuery it wouldn't require a full rewrite since dependancies are listed and loaded at initialization of the scripts.

Personally I would keep jQuery. They have kept up-to-date with there branches and even support antiquated browsers, so its easy to back port to version 1 if the need arrives to support hush IE8 hush. In addition jQuery 2 utilizes AMD, so double the streamlining.

Finally, I HATE the idea of supporting both native JS and jQuery, just twice the work.

gakimball commented 9 years ago

Yeah, I don't see us actually developing two libraries. Even if we write the codebase in plain JS, that doesn't stop anyone from using jQuery in conjunction with Foundation. We're still probably going to use events to manage component state and trigger callbacks and so forth, so using $.fn.on to tap into the plugins won't be a problem.

@coreysyms The option to revert to jQuery 1.x is a pretty compelling reason to use it. Folks will need some kind of path to get to IE8 support (Foundation 5 has it if you put in the work), and if we write our plugins in plain JS that guarantees we won't be effectively accommodating IE8 in some cases.

tikot commented 9 years ago

What is the point of having jQuery if the Foundation core will only use 10% of jQuery?

@tsquez I meant one version approach without dependency. I agree with @coreysyms Its a bad idea to have two variations.

r3wt commented 9 years ago

@gakimball IE8 support ends this year. its pretty inconceivable that there would be people out there choosing not to upgrade from a 6 year old internet browser. why support IE 8?

tsquez commented 9 years ago

@tikot - Gotcha, I wasn't fully awake or had my first cup of copy when I made my comment...lol - and I think you are right one version would be best.

coreysyms commented 9 years ago

@r3wt My point about antiquated browsers was not that it would be supported, but that there is options to use what is in place and revert to it. Right now Foundation does a fantastic job, as well as jQuery to easily "sniff out and revert" to jQuery 1x and Foundation 4, even when using the latest and greatest. This reason alone has value, and while we are having this conversation today about IE8, soon we will be having a conversation about IE9 and so on. Using jQuery, which I prefer vs native, is really the core of my point, and my argument for, that if jQuery is dropped, we would loose that value in reverting.

michaelBenin commented 9 years ago

1) UMD Compatible - (CommonJS, AMD, Global fallback)

2) Better control of events, having an on/off/reset/destroy methods. Better documentation of all possible config parameters as well as all events to control.

3) I would rather keep jQuery as all the sites I make use it. If you don't include it, you'll be reinventing the wheel. Also I like what they did with Backbone here: https://github.com/inkling/backbone.native. It would be nice if someone made the same thing for Foundation.

4) Better testing. We upgraded to the latest Foundation and found that abide events were firing twice. Instead of using the latest events we relied on events that were deprecated because they worked. If we had better testing we would catch these kinds of bugs.

5) Publish to npm.

6) Don't make configurations that need ids, allow the use of class names. Example in reveal: http://foundation.zurb.com/docs/components/reveal.html

MichalZalecki commented 9 years ago

@tikot Angular is also going to drop jQLite and using jQuery in Angular apps is considered as a bad practice. Plain JS is VERY good idea. Including jQuery specially for UI framework... uhhhh I'm not too keen on doing that. jQuery is a vast library.

michaelBenin commented 9 years ago

Make use of JS code quality tools:

https://github.com/ariya/grunt-jsvalidate https://github.com/gruntjs/grunt-contrib-jshint https://github.com/jscs-dev/grunt-jscs https://www.npmjs.com/package/grunt-jsbeautifier https://www.npmjs.com/package/grunt-eslint

gakimball commented 9 years ago

A few people have mentioned it, but linting is definitely a priority for this new codebase. Since we're rewriting a lot of stuff, we have the opportunity to have it turned on from the start, instead of having to go back and fix a bunch of formatting issues.

stevetrask commented 9 years ago

I agree with the approach of dropping jQuery and using Require.js as we have to remember the mantra of mobile first and these will better for performance and a level above other popular frameworks. If people require it they can add it on but you are also keeping Foundation JS lean for those who want it. So overall no jQuery but so it can fit nicely on if people require it :)

On the IE8 issue a lot of products are dropping support and companies and schools in my area of the UK have upgraded away from it already. If IE8 is required F5 and F4 will still be available.

doertedev commented 9 years ago

Why not creating tags and use web components? Until finished, shadow Dom will be widely available...

chrisrhymes commented 9 years ago

In an ideal world the new foundation would work, albeit simplified, without JavaScript. That way older browsers would be "supported" by getting a basic usable site but modern browsers would get an awesome version.

doertedev commented 9 years ago

Also: I'd like to note that it's been quite some time now since we require modernizr in the dependencies. But do we really use it within our libraries? Nope. In my opinion we need to step away from letting people copy _settings.scss (and scribble around with the variables) and get them to include the modules and extend them accordingly. Just for the sake of decoupled modules being awesome.

gakimball commented 9 years ago

@chrisrhymes Some of the JS libraries do have fallbacks (every tab's content in a tabstrip will display, Interchange basically has a <noscript> feature built-in, etc.) but we can look at that again and make sure as many of the plugins have decent fallbacks as possible.

@doertedev Do you mean not use variables at all, and just have people override the selectors themselves? To be sure, we have decided to drastically cut down on the number of settings variables, reducing it to core structural and visual styles only. The reason is, as soon as you can't find a settings variable for something you need, you're going to have to write your own CSS anyway. If we're consistent with what kinds of properties get variable, we can keep the list trim and predictable.

doertedev commented 9 years ago

@gakimball and (IMPORTANT!!!) consistency across modules plx :) Nope, I didn't mean that. I mean to point the user to including style sets, which are predefined, rather than have him/her/it scribble around in a copied _settings.scss. Also: have the docs tell it/her/him HOW to import scss style definitions and default values for style definitions as the bottom of the docs of the single modules on the docspage does. It's good to have 'em in one place to look for, but I'd rather open the file to look for instead of clicking around in a page and waiting for it to load tbh (devdocs ftw! Foundation is still not listed :( ). Big :+1: on stripping them down. It is a good thing to do. And looking up smth. get's easier that way.

gakimball commented 9 years ago

@doertedev Ah okay, so if you're thinking that the user should open each component's Sass file directly and just edit the values there, that makes sense. The issue, however, is that frameworks are typically loaded as dependencies, which means they aren't checked into version control.

In terms of documentation, we're working on making it better. Every component's page should have an automatically-generated list of Sass variables and mixins, complete with type, default value, parameters, all that. If we can figure it out we'd also like to make those values searchable across the entire documentation.

doertedev commented 9 years ago

What the hell? No.

I am talking of doing less this:

// ... project.scss
@import "../../bower_components/foundation/scss/normalize";
@import "../../bower_components/foundation/scss/foundation/functions";
@import "settings";
@import "../../bower_components/foundation/scss/foundation/components/global";
@import "../../bower_components/foundation/scss/foundation/components/grid";
@import "../../bower_components/foundation/scss/foundation/components/type";
@import "../../bower_components/foundation/scss/foundation/components/visibility";
// .... _settings.scss, copied from bower_components/... to project land
// $button-tny: rem-calc(10);
// $button-sml: rem-calc(14);
$button-med: #FFFFFF;
// $button-lrg: rem-calc(18);

.... And more this:

// ... project.scss
@import "../../bower_components/foundation/scss/normalize";
@import "../../bower_components/foundation/scss/foundation/functions";
@import "../../bower_components/foundation/scss/foundation/settings";
@import "../../bower_components/foundation/scss/foundation/components/global";
@import "../../bower_components/foundation/scss/foundation/components/grid";
@import "../../bower_components/foundation/scss/foundation/components/type";
@import "../../bower_components/foundation/scss/foundation/components/visibility";

@import "app-module-sidebar";
@import "app-module-buttonsorsomeothercrap";
// ... _app-module-sidebar.scss
.app .sidebar {
  $zf-sidebar-color1: #123456;
  $zf-somepadding: 3px;
  $zf-link-color: #CB341F;
  @include zf-sidebar(); // <<<<<<<<<<<<<<<< !!!!!!!!!!!
}

Why even use SCSS when we're not using their features? What's the point in creating reusable modules if we have to change variables in one file and have the changes triggered EVERYHWERE in the project? That's exactly why SASS / SCSS has mixins. If I wish to have a certain change triggered everywhere on the project, I can simply searcH/replace file's occurrances of ONE setting, overwriting it once. Otherwise, if I whant one of 40 buttons being diff. than others, I can just create another button definition, importing all other functionality via mixin. I will blog about this soon, because I had too many sites written in ZF5 which I fell on the face with. Having EXACTLY this problem. But it's part of the docs to lead the user into not falling on his face. So tell them to decouple.

End of the song: I need a new type of button, which unlike all other buttons have a diff. color & font setting? Create a new class, import all the other crap directly from this kickass framework, and just change the two variables from the _settings.scss in Userland instead of "for every occurrance of a button". You'll end up with zero changes to variables, zero changes of functionality for every button, you just create a class, set a var, import and you're good to go. :)

(EDIT: re-reading this I see I have really big problems explaining what I mean :-/ )

gakimball commented 9 years ago

@doertedev Alright, I think I know what you're getting at, and Foundation does this currently. We write all of our components as mixins, which means you can selectively override the default settings of a component.

For example, if you use the button() mixin with no parameters, it just pulls values from the settings file.

.default-button {
  @include button;
}

However, it's also possible to call the mixin with parameters that override the defaults.

.different-custom-button {
  @include button($bg: pink, $radius: 5px);
}

Foundation 4 and 5 both have this functionality, but for 6 we're going to better structure our documentation to make the mixins and settings variables easier to find and understand.

So I think that's what you're getting at, but let me know if I'm wrong :)

doertedev commented 9 years ago

Nope this is exactly what I meant :)

Just letting the user know how to extend the modules, and why to do so, is a big step we need to get into. Back then I introduced some sass function for iterations, and some versions broke due to sass version changes in the library. A good CI might detect version/function incompatibilities with libsass p.e... Who knows what the io.js guys are up to....

So:

:+1: for continueing to provide mixins HUGE :+1: for testing against environments and libraries that are neither OSX nor ruby-only BIGGEST :+1: for showing the user how to not fall on his face and decouple all the things :)

gakimball commented 9 years ago

@doertedev We can definitely look into better educating people on why using the Sass version of Foundation is important, and how to use it to its highest potential.

Like I said before, in the next version of the docs we should be documenting mixins as thoroughly as a typical Sass library would. (See Neat for an example.)

And to your point about Sass versions, Libsass is definitely a priority, and we're reworking the CLI to use Node instead of Ruby. Right now the new CLI only works with Foundation for Apps, but eventually it will work with our other two frameworks as well.

doertedev commented 9 years ago

Keep up the good work guys. And as I've mentioned earlier: :+1: for using modernizr more :)

karland commented 9 years ago

The discussion is interesting. I think it is usefull to look at the individual categories that make software successful before taking any decision concerning changes. For me the most relevant are:

  1. Speed
  2. Size
  3. Extensability and modularity
  4. Error Freeness
  5. Documentation (HTML and in the code)
  6. Code and Code maintainability
  7. Compatibility (to other packages, browsers, etc)

Now most of the disucssion in this thread is about 1.-3. However, when it comes down to the question jQuery or not one should also take into account, who is maintaining the code base. The success of Foundation apart from its clever design and huge functionality is the user base who is regularly providing PRs to remove errors. After a complete re-write of the JS code base there will be errors and I think it is important to make the source code as readable, understandable and maintainable as possible. If this means jQuery I would probably go for it.

moondawg69 commented 9 years ago

A real world scenario. A global web app, as in multilingual, over 4 continents, many under developed countries who run XP and IE9 and will do for some time to come. A 6 million+ user base of which 20% are running IE9. We are going to rebuild the web app. We cannot really use Foundation for Apps because of IE10+ requirements.

So back to looking about at Angular UI/UX solutions in general... and all you see is Bootstrap and a solid set of directives ported from BS into Angular natively, time and time again. There are 'some' other frameworks in place, but none as 'clean' as Foundation.

There is the Pinecone port: http://pineconellc.github.io/angular-foundation/ that has been rewritten to native AngularJS directives without any dependency on jQuery or Foundation's JS.

So my vote would be for the Foundation for Sites team to please create native Angular library of the For Sites javascript whichever route you take, jQuery or plain JS.

And web apps are just going to keep on coming... might as well be served by the mighty Yeti.

michaelBenin commented 9 years ago

@moondawg69 I'm confused, why is Foundation so tied to Angular as a front end framework? Angular 2.0 will be a complete rewrite and won't be backwards compatible.

I would like to see Foundation be decoupled from any other framework in the future.

When I mean framework, I mean any of the JS MVC/MVT.

michaelBenin commented 9 years ago

Also here is an example of how Foundation needs to better it's JS in terms of controlling the plugins.

https://github.com/zurb/foundation/issues/3339

https://github.com/zurb/foundation/issues/6127

gakimball commented 9 years ago

@michaelBenin There are definitely a lot of examples where plugins need more programmatic manipulation. Should we keep doing it "the jQuery plugin way" ($('#thing').foundation('plugin', 'method')) or might there be a better method? Maybe use event handlers instead? Most plugins already use events but they might be indirectly triggered (with $.fn.foundation) versus just triggering them directly (with $.fn.trigger).

michaelBenin commented 9 years ago

From my experience, I really enjoy working with jQuery plugins that do the following:

There's more too I can update this, I'm sorry I'm at work. I want to help with all of this stuff. There should also be a full on test suite for each plugin with unit tests and utilizing some kind of acceptance/functional testing framework with Saucelabs to ensure no releases go out with broken functionality.

kevinquillen commented 9 years ago

Here is what I would want to see after putting Reveal through it's paces within a platform like Drupal:

gakimball commented 9 years ago

You guys think we should keep doing the data-options thing, where you pass all of a plugin's options in one attribute, or should we look at segmenting them into individual attributes? Or allow for both?

ghost commented 9 years ago

+1 for doing it "the jQuery way", because in some cases we can't use data attributes.

For example in Wordpress projects where a lot of the HTML is generated by WP itself, and requires additional coding which could potentially break layouts in future versions.

oller commented 9 years ago

+1 for UMD compatible modules. Save us shimming all the components.

FWIW, I think the data-options attribute to pass in an options object is very useful, and see no real need to change that.

vforge commented 9 years ago

+1 for dropping jQuery and moving towards ES6

hassanbazzi commented 9 years ago

I disagree with vforge. I think working with something like jqLite makes a lot of sense still for DOM changes.

pdlug commented 9 years ago

I'm a little late to the game but agree with a number of items above. I'd like to see jQuery dropped (add my +50 to this). I also really like the idea of embracing mixins along the lines of what Neat and related libraries are doing. Using CommonJS (or UMD) is a must along with providing an npm package. Foundation is currently the only bower package we're using along with some less than graceful hacks to get it work with webpack.

shreyasmm commented 9 years ago

+1 use JQuery, RequireJS i use it every time +1 Drop IE8 +1 using data-options

joelkinzel commented 9 years ago

I know this is somewhat late, but will F4S6 use any ES6 (maybe with a babel step)? Or are you guys going to stick with ES5 until ES6 is more widely supported?

hassanbazzi commented 9 years ago

Where do you think ES6 is helpful?

joelkinzel commented 9 years ago

Thinking about the modularization of the code and some of the nicer ES6 syntax and things of that nature. Not that it can't be done without ES6. It was more of a curiosity thing.

gakimball commented 9 years ago

ES6 transpilers have come a long way, but we won't be using ES6 for this version of the framework for a few reasons. The main one is that our needs aren't very complex in the grand scheme of things. There are a lot of little things that would be super nice (fat arrows, template strings, classes, to name a few), but we weren't willing to use any Babel features that required the polyfill. (The file size of our CSS and JavaScript is a big concern in this version.) And ultimately, our basic UI plugins aren't nearly as complicated as the libraries folks are building with ES6. Sticking with ES5 also keeps the barrier to contributing lower, and community engagement is very important to us.

That being said, we might be getting our feet wet with ES6 and TypeScript in a future version of Foundation for Apps, seeing as Angular 2.0 is around the corner. So look forward to that!

Also @joelkinzel, to your point about modules, we are trying to be smarter about how our code is structured. For example, Magellan is being split into two plugins: one for sticky headers, and one for navigation tracking. Certain core elements of the framework will also be split into smaller libraries, like motion and media query management.