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.65k stars 5.48k forks source link

jQuery.foundation() is not a function #10336

Closed syntax-punk closed 6 years ago

syntax-punk commented 7 years ago

I am using foundation-sites plugins in my existing project, and after updating foundation to 6.4.1 $(document).foundation(); returns an 'is not a function error'. But issue was solved by callingFoundation.addToJquery($); beforehand. So question: is it a bug or a feature?

ghost commented 7 years ago

I've the same issue, your fix doesn't work either @voogieJames.

syntax-punk commented 7 years ago

@klloe, before that I've updated jQuery to make sure its version is >= 3.. and also 'npm update -g'

ghost commented 7 years ago

@voogieJames Already use the CDN version

kball commented 7 years ago

Hey @voogieJames @klloe I'd like to help track this down - how are you downloading and installing Foundation? What does your build look like? And are you using the built dist files or importing from the sourcefiles?

ghost commented 7 years ago

@kball I'm using the basic template and load all the necessary scripts via CDN

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/what-input/4.2.0/what-input.min.js" integrity="sha256-7wGy9IEPmo9Jk/I86siWbZFPeclfjFitAAfmvxBUc7k=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.1/js/foundation.min.js" integrity="sha256-Nd2xznOkrE9HkrAMi4xWy/hXkQraXioBg9iYsBrcFrs=" crossorigin="anonymous"></script>

  <script>
    $(document).foundation();
  </script>
kball commented 7 years ago

Hi @klloe,

Using that exact pasted script, I see the following error:

Failed to find a valid digest in the 'integrity' attribute for resource 'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.1/js/foundation.min.js' with computed SHA-256 integrity 'ssuvZ7clQBE8C6fdKygrQfRqIx5bFb/F/Abeqq1dr/w='. The resource has been blocked.

If I cut out the integrity hash it loads and works fine... I'm not an expert in how the integrity pieces work, but it seems like the issue is the foundation JS isn't loading at all

syntax-punk commented 7 years ago

Hi @kball So I am using npm(npm v. 5.1.0) for installing foundation-sites. Below is a part of my packages.json file:

...
"dependencies": {
    "foundation-sites": "^6.4.0",
    "jquery": "^2.2.4"
  },
  "browser": {
    "jquery": "./node_modules/jquery/dist/jquery.min.js",
    "foundation": "./node_modules/foundation-sites/dist/foundation.js"
  },
  "browserify-shim": {
    "jquery": "jQuery",
    "foundation": "foundation"
  },
  "browserify": {
    "transform": [
      "babelify",
      "browserify-shim"
    ]
  },
...

In my index.js file I import all necessary foundation modules, like so:

...
import $ from 'jquery';
import 'foundation-sites';
import 'foundation-sites/js/foundation.core';
import 'foundation-sites/js/foundation.util.mediaQuery';
import 'foundation-sites/js/foundation.toggler';
import 'foundation-sites/js/foundation.sticky';
...

And the mentioned problem (foundation is not a function) occurs when I try to call $(document).foundation(); function.

But as I mentioned before, if I run Foundation.addToJquery($); function first, then I can initiate foundation framework.

kball commented 7 years ago

Hi @voogieJames I think this is a documentation problem, that we need to figure out how to address... and possibly improve on. I'd love your feedback and help to figure out how to best document this, or if there's a better way to approach this...

The root of the issue is that we wanted the module imports to be side effect free (for the backstory, see the discussion starting here: https://github.com/zurb/foundation-sites/issues/9438#issuecomment-266933957), but what that means is that when using the imports there is now an initialization step if you want to add them to the foundation jquery helpers.

For our built distfiles we do all of this invisibly to maintain backwards compatibility, but since you're using a module bundler you'll probably need to do more. For an example see this entry file that we ship with the new starter template: https://github.com/zurb/foundation-zurb-template/blob/master/src/assets/js/lib/foundation-explicit-pieces.js

You could also look at our default entry port for folks who just want to import foundation: https://github.com/zurb/foundation-sites/blob/develop/dist/js/npm.js

justrhysism commented 7 years ago

@kball So as an example, if we just wanted to initialise a single plugin, e.g. "Reveal", what are the required steps when using a module bundler?

Also, how could this be done on the fly? Many of us are now leveraging Webpack's code-splitting feature to only load the modules we need. We may need to initialise a plugin after page load. There's a likely scenario where two independent modules use the same Foundation plugin - how can we avoid initialising these plugins multiple times? Or do we not need to worry about this?

kball commented 7 years ago

@justrhysism You can import a single plugin straight from that plugin's file (e.g. import { Reveal } from 'foundation-sites/js/foundation.reveal';

If you're doing stuff by hand, it may well be straightforward for you to do the instantiation yourself using a direct constructor (e.g. var thisReveal = new Reveal($('#my-reveal'), options)).

Or if you want to use the jquery helper (e.g. $(document).foundation()) you'd want to do something like:

// import jQuery
import $ from 'jquery';
// import core foundation (possibly misnamed due to legacy) 
// to allow global bookkeeping & jquery helper
import { Foundation } from 'foundation-sites/js/foundation.core';
// import component
import { Reveal } from 'foundation-sites/js/foundation.reveal';

// set up the $.fn.foundation helper so you can just grab 
// DOM elements and call foundation on them
Foundation.addToJquery($);

// Tell Foundation global bookkeeping/jquery helper about Reveal plugin
Foundation.plugin(Reveal, 'Reveal');

Let me know if this makes sense or what doesn't... really want to make the docs for this better.

justrhysism commented 7 years ago

Thanks for you timely response @kball, much appreciated.

Ah right - yes, being able to use the plugin directly is much nicer.

For thread followers:

import $ from 'jquery';
import { Reveal } from 'foundation-sites/js/foundation.reveal';

const options = { /* Reveal Options, if any */ };
const $myRevealElement = $('#my-reveal-selector');
const myReveal = new Reveal($myRevealElement, options);

I'm using Foundation with Vue, and it's good practice (particularly for event listeners) to "clean up" in Vue's beforeDestroy() lifecycle method. I noticed that there's a _destroy() method on the class, but being prefixed with an underscore _ seems to indicate that it's private. Is there any reason this method is private? Or is this something which involves greater discussion and I should open another Github issue?

justrhysism commented 7 years ago

With respect to the docs, I think there needs to be a couple of versions depending on use case. Anyone using a bundler such as Webpack would greatly benefit from the new simplicity of being able to instantiate a component directly, without having to manually import the required dependencies. Big win.

But I think you'll probably also need docs for people upgrading to 6.4 from an older version, demonstrating the "quick fix" approach to keep people's projects going, but also maybe a side-by-side demonstration of the old-vs-new methods - because the changes are pretty significant (but definitely for the better).

kball commented 7 years ago

Definitely agree on the multiple versions - @justrhysism would you be interested in helping write those docs? I'm unfortunately extremely slammed for time which has limited my ability to keep iterating on the docs, am looking for help to improve them.

Pharserror commented 6 years ago

@kball I've added some documentation here: https://github.com/zurb/foundation-sites/pull/10782.

soukicz commented 6 years ago

I am having the same issue with "dist" packages. jQuery, Foundation 6.4.3 and my code are all in one JS file and it sometimes (mostly on back button) fails on "$(document).foundation();"

Pharserror commented 6 years ago

if you are reading this please check #10782 for instructions on how to fix this issue.

dungle-scrubs commented 6 years ago

Thank you! I've been trying to figure this out for weeks and Foundation.addToJquery($); finally did the job.

I have a question. In bower_components/foundation-sites/js, there is a folder called "entries" with "foundation.js" and "foundation.plugins.js". How are these meant to be used?

I'm new to module bundling, and my setup is basically Gulp, Browserify, and Babelify. Been having a pretty hard time understanding how to approach bundling as the documentation already assumes a solid understanding. Help in this area would be really great.

ncoden commented 6 years ago

Fixed in https://github.com/zurb/foundation-sites/pull/10864. This sould be released in v6.4.4.

michaelaflores commented 6 years ago

@ncoden I see #10864 has Milestone 6.4.4 set. I'm not familiar with how this translates to the release candidates – I installed 6.4.4-rc1 and don't see this working yet. Is that expected?

When I try to run it in a create-react-app setup, I get the following output during build:

Failed to compile.

Failed to minify the code from this file:

        ./node_modules/foundation-sites/js/foundation.util.core.js:24

Read more here: http://bit.ly/2tRViJ9
DanielRuf commented 6 years ago

https://github.com/zurb/foundation-sites/pull/10864 was after RC1.

DanielRuf commented 6 years ago

Also the error in your create-react-app project is not complete as there is no full stacktrace or error message. Or do you mean the error fixed by https://github.com/zurb/foundation-sites/pull/10864?

michaelaflores commented 6 years ago

@DanielRuf makes sense, will keep an eye out then.

The output I pasted is the beginning of the JavaScript minification portion of the build, so everything before it is a bunch of lines about CSS files being generated. I'll update my comment with those if that's helpful.

flyingL123 commented 6 years ago

Hey @justrhysism did you ever get an answer about your _destroy() question? I am in almost exactly the same use case as you. I'm importing the Equalizer plugin directly and instantiating it myself, and I'm wondering if there is any reason I can't call equalizer._destroy() when I need to remove the plugin from the element.

How did you end up handling this?

DanielRuf commented 6 years ago

It should be Foundation.destroy() or $('.tooltip').foundation('_destroy')

Please open a new issue as this is not about the initial issue.

flyingL123 commented 6 years ago

In case anyone is wondering, the base Plugin class defines the public destroy method, so you actually can and should call destroy() on the equalizer instance.

lessless commented 5 years ago

Still biting me with webpack --mode production when included through import 'script-loader!foundation-sites/dist/js/foundation'; in the entrypoint file.

Foundation.addToJquery($); leads to Foundation.addToJquery($);

  externals: {
    foundation: 'Foundation'
  },

is not of any help too

DanielRuf commented 5 years ago

@lessless not sure what you mean. Please open a new issues with more derails.