Menu icon Foundation
Enhancing Foundation with Bower Components

Does anyone have a good example, tutorial, or blog written about how to extend Foundation 6 with components from Bower or NPM.

For instance, I would prefer Owl Carousel to the Foundation's Orbitz slider. If I install Owl using Bower I then have to add it to the list of JavaScript files to output in the app.js file (As this wouldn't live in the assets folder). This isn't my desired outcome, as bloating the entire JS isn't the best for performance, especially when you might only use a carousel on one or two pages of your site.

In order to achieve this would I need to create a new task to copy specific JS component files to the assets JS folder?

I am not a newbie to Sass or Foundation, however, with Foundation 6 I have been more focused on keeping the original Gulpfile clean and organized as this is how the Zurb team built the framework. Since Foundation 5 didn't come with gulp.js I built my own Gulpfile.js and was able to extend the framework to my hearts extent. However, I would say my Gulpfile wasn't the best organized or structured.

Any insight or pointers and tutorials would be welcomed!

* Additional components I plan to use are: Animate.css, ScrollMagic, Chart.js, and Video.js

gulpfoundation 6bowercomponentsenhancements

Does anyone have a good example, tutorial, or blog written about how to extend Foundation 6 with components from Bower or NPM.

For instance, I would prefer Owl Carousel to the Foundation's Orbitz slider. If I install Owl using Bower I then have to add it to the list of JavaScript files to output in the app.js file (As this wouldn't live in the assets folder). This isn't my desired outcome, as bloating the entire JS isn't the best for performance, especially when you might only use a carousel on one or two pages of your site.

In order to achieve this would I need to create a new task to copy specific JS component files to the assets JS folder?

I am not a newbie to Sass or Foundation, however, with Foundation 6 I have been more focused on keeping the original Gulpfile clean and organized as this is how the Zurb team built the framework. Since Foundation 5 didn't come with gulp.js I built my own Gulpfile.js and was able to extend the framework to my hearts extent. However, I would say my Gulpfile wasn't the best organized or structured.

Any insight or pointers and tutorials would be welcomed!

* Additional components I plan to use are: Animate.css, ScrollMagic, Chart.js, and Video.js


Rafi Benkual gave the most helpful answer for this post
Rafi Benkual almost 2 years ago

I recently added Owl Carousel to the ZURB stack.

1 - Install with Bower bower install owlcarousel --save (This will place components in the right files for you.)
2 - add to Gulfile.js:

javascript: [
    'bower_components/jquery/dist/jquery.js',
    'bower_components/what-input/what-input.js',
    'bower_components/owlcarousel/owl-carousel/owl.carousel.js',
    'bower_components/foundation-sites/js/foundation.core.js',

Note: You'll need to re-start Gulp after this change.

3 - Add the CSS - From the download, I copied the CSS into my project. I always add my 3rd party CSS into a vendor file. By default, everything in the SCSS folder will be compiled into CSS. Example: https://notebooks.zurb.com/posts/10027837?t=f6d3b4b6e935e742

It needs to be added in app.scss file:

@charset 'utf-8';

@import 'settings';
@import 'foundation';
@import 'motion-ui';

@import 'vendor/owlcarousel';

@include foundation-global-styles;
@include foundation-grid;
@include foundation-typography;
@include foundation-button;
@include foundation-forms;

4 - Initialize the JS after Foundation is initialized. Open js -> app.js and add

$(document).foundation();

 $("#owl-example").owlCarousel({
  items: 3
 });

That pretty much it. I added the carousel like this in index.html

<div id="owl-example" class="owl-carousel">
  <div><img src="http://placehold.it/1200x300/456" alt=""></div>
  <div><img src="http://placehold.it/1200x300/356" alt=""></div>
  <div><img src="http://placehold.it/1200x300/256" alt=""></div>
  <div><img src="http://placehold.it/1200x300/156" alt=""></div>
  <div><img src="http://placehold.it/1200x300/556" alt=""></div>
  <div><img src="http://placehold.it/1200x300/656" alt=""></div>
  <div><img src="http://placehold.it/1200x300/756" alt=""></div>
</div>

Rafi Benkual almost 2 years ago

I recently added Owl Carousel to the ZURB stack.

1 - Install with Bower bower install owlcarousel --save (This will place components in the right files for you.)
2 - add to Gulfile.js:

javascript: [
    'bower_components/jquery/dist/jquery.js',
    'bower_components/what-input/what-input.js',
    'bower_components/owlcarousel/owl-carousel/owl.carousel.js',
    'bower_components/foundation-sites/js/foundation.core.js',

Note: You'll need to re-start Gulp after this change.

3 - Add the CSS - From the download, I copied the CSS into my project. I always add my 3rd party CSS into a vendor file. By default, everything in the SCSS folder will be compiled into CSS. Example: https://notebooks.zurb.com/posts/10027837?t=f6d3b4b6e935e742

It needs to be added in app.scss file:

@charset 'utf-8';

@import 'settings';
@import 'foundation';
@import 'motion-ui';

@import 'vendor/owlcarousel';

@include foundation-global-styles;
@include foundation-grid;
@include foundation-typography;
@include foundation-button;
@include foundation-forms;

4 - Initialize the JS after Foundation is initialized. Open js -> app.js and add

$(document).foundation();

 $("#owl-example").owlCarousel({
  items: 3
 });

That pretty much it. I added the carousel like this in index.html

<div id="owl-example" class="owl-carousel">
  <div><img src="http://placehold.it/1200x300/456" alt=""></div>
  <div><img src="http://placehold.it/1200x300/356" alt=""></div>
  <div><img src="http://placehold.it/1200x300/256" alt=""></div>
  <div><img src="http://placehold.it/1200x300/156" alt=""></div>
  <div><img src="http://placehold.it/1200x300/556" alt=""></div>
  <div><img src="http://placehold.it/1200x300/656" alt=""></div>
  <div><img src="http://placehold.it/1200x300/756" alt=""></div>
</div>

Glenn Philp almost 2 years ago

Rafi, thank you for the help.

Another quick question, how does Zurb team recommend telling Gulp to only copy files, instead of adding them to app.css and app.js?

For instance using the example above, I would prefer to only copy the owl.carousel.js and create owlcarousel.css. This allows to smaller file sizes and calling the additional components when needed.

Chris almost 2 years ago

Actually i WANT all the css to be in the app.css and all the js in the app.js.

So I have no additional http requests, which slows down my site.

What do others mean?

Glenn Philp almost 2 years ago

Chris, I do understand your concern about making fewer calls. I would love everything to be included in one file, the biggest downside is that JS files are seen as render blocking files. Plus as developers, we should be responsible for making files small as possible. One way of doing this is by only adding scripts when they are required.

Use Google for example. They reduce the number of HTTP request, however if you look at their source code they inline most of the scripts. Meaning the user only makes a few calls for the global scripts and the required pieces are inlined on the page. Google even recommends everything above the fold to be inlined for fastest rendering.

So the best concept would be: require all users to request foundation.min.js and then inline any components needed for that specific page (ie dropdown, accordion, etc). Although making an additional call for components like accordion.js and tabs.js on a page isn't that harmful because the file sizes are so small it would take milliseconds to download, even on a 4G connection.

That is why I would prefer to copy owl.carousel.min.js to dist > assets > js folder using a gulp task. Then I would only require this script when the carousel was used on a page.

Which returns me to, what is the Zurb team's recommendation for extending Gulp task to copy specific bower files from bower_components to dist > assets > CSS or JS?

Something like this:
(DO NOT USE BELOW, ONLY EXAMPLE NOT WORKING)
```
var PATHS = {
bower: [
'bower_components/owl.carousel/*.min.js'
]
}

gulp.task('copy', function() {
gulp.src(PATHS.assets | PATHS.bower)
.pipe(gulp.dest('dist/assets'));
}
```
The issue with this, I am unaware if Gulp allows for or ( | pipe) within the src(). And most importantly how to make sure that the specific JS or CSS from bower ends up in the correct JS or CSS folders under dist > assets

Any advice

Geoff Kimball almost 2 years ago

@Glenn Philp gulp.src can be used in the middle of a stream to add new files.

Here's the existing javascript task in the ZURB template, modified. We add the new files after concat is run, which is the plugin that mashes all the files together.

gulp.task('javascript', function() {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.concat('app.js'))
    // gulp.src is added in the middle of the stream
    .pipe(gulp.src(ARRAY_OF_NEW_FILES))
    // The new files will pass through uglify, but not through concat
    .pipe(uglify)
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    .pipe(gulp.dest('dist/assets/js'));
});

Glenn Philp almost 2 years ago

@Geoff Kimball thank you for the quick follow up. I didn't know this could be done so simply.

!Important Note:

When I added .pipe(gulp.src(['bower_components/owl.carousel/dist/owlcarsouel.js'])) and then ran 'foundation watch'. Gulp ran and browsersync started successfully. However, the final output to the JS file was owlcarousel.js. For some reason, it didn't concat the app.js to dist/assets/js.

My only thinking, I created a conflict between gulp.src and PATHS.javascript. Should I still list 'bower_components/owl.carousel/dist/owlcarsouel.js' in the PATHS above, but tell it not to include this file, like so '!bower_components/owl.carousel/dist/owl.carousel.js'?

This is the code I have in gulpfile.js
```HTML
// Combine JavaScript into one file
// In production, the file is minified
gulp.task('javascript', function() {
var uglify = $.if(isProduction, $.uglify()
.on('error', function (e) {
console.log(e);
}));

return gulp.src(PATHS.javascript)
.pipe($.sourcemaps.init())
.pipe($.concat('app.js'))
.pipe(gulp.src(['bower_components/owl.carousel/dist/owl.carousel.js']))
.pipe(uglify)
.pipe($.if(!isProduction, $.sourcemaps.write()))
.pipe(gulp.dest('dist/assets/js'));
});
```

Geoff Kimball almost 2 years ago

@Glenn Philp You'll want to define one array of "files that should all be combined into app.js", and then separately, "files that should be included as-is".

E. Smythe almost 2 years ago

Glenn,

If you get this worked out, I'd really appreciate it if you could post your final changes here as I'd like to do the same.

Thank you.

Glenn Philp almost 2 years ago

@Geoff Kimball, I would really enjoy your input to my final result. If there is a better way or I am breaking rules please notify me.

@E. Smythe the only way I was able to finally get Gulp to output the app.js and owl.carousel.js to the dist > assets > js folder I did the following.

// Created new PATHS array named js
// I will list any files from bower_components that I want copied
var PATHS = {
  js: [
    'bower_components/owl.carousel/dist/owl.carousel.js'
  ]
}

// I left the javascript task alone and made a copy

// Combine JavaScript into one file
// In production, the file is minified
gulp.task('javascript', function() {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.concat('app.js'))
    .pipe(uglify)
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    .pipe(gulp.dest('dist/assets/js'));
});

// Created new task called bowerJS and pasted javascript task
// Removed sourcemaps.init, concat
gulp.task('bowerJS', function() {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function(e) {
      console.log(e);
    }));

  return gulp.src(PATHS.js)
    .pipe(uglify)
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    .pipe(gulp.dest('dist/assets/js'));
}); 

// Build the "dist" folder by running all of the above tasks
gulp.task('build', function(done) {
  // Added bowerJS to the build task
  sequence('clean', ['pages', 'sass', 'javascript', 'bowerJS', 'images', 'copy'], 'styleguide', done);
});

// Build the site, run the server, and watch for file changes
gulp.task('default', ['build', 'server'], function() {
  gulp.watch(PATHS.assets, ['copy', browser.reload]);
  gulp.watch(['src/pages/**/*.html'], ['pages', browser.reload]);
  gulp.watch(['src/{layouts,partials}/**/*.html'], ['pages:reset', browser.reload]);
  gulp.watch(['src/assets/scss/**/*.scss'], ['sass', browser.reload]);
  gulp.watch(['src/assets/js/**/*.js'], ['javascript', browser.reload]);

// Added the PATHS js array and bowerJS to the watch task
  gulp.watch(PATHS.js, ['bowerJS', browser.reload]);

  gulp.watch(['src/assets/img/**/*'], ['images', browser.reload]);
  gulp.watch(['src/styleguide/**'], ['styleguide', browser.reload]);
});


Geoff Kimball almost 2 years ago

@Glenn Philp This approach definitely works. We do something very similar in the Foundation for Sites build process, which you can see here.

My only suggestion to make the tasks easier to group/read is to namespace them. For example, instead of naming the task bowerJS, make it javascript:bower. Then all of your JS-related tasks start with the word javascript. We also do this in the F4S build process, with groups like docs, sass, deploy, and so on.

Kevin Ball 11 months ago

One quick update to the answers here is that now we're using babel to compile the javascript in the ZURB stack because the Foundation JavaScript has been updated to ES2016.  The challenge here is that while in theory ES2016 is backwards compatible, in practice sometimes older javascript libraries don't seem to work properly when Babel compiles them.

 

You can tell babel to ignore/not parse certain files by passing an ignore option to babel in the build process.  Example:

 

function javascript() {
  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.babel({ignore: ['node_modules/my_es5_module/*.js']}))
    .pipe($.concat('app.js'))
    .pipe($.if(PRODUCTION, $.uglify()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

Sergey Kruglikov 9 months ago

i specified in config.yml

- "node_modules/snapsvg/dist/snap.svg.js"

in gulpfile.babel.js

function javascript() {
  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.babel({ignore: ["what-input.js", "node_modules/snapsvg/dist/snap.svg.js"]}))
    .pipe($.concat('app.js'))
    .pipe($.if(PRODUCTION, $.uglify()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

the result is still error message

Uncaught ReferenceError: eve is not defined
    at app.js:9491
    at app.js:9873

Michelle Child 8 months ago

+1 to Sergey..

 

I specified in config.yml -- 

    - "bower_components/footable/compiled/footable.js"

 

In Gulpfile.babel.js --

function javascript() {
  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.babel({ignore: [
      'what-input.js',
      'footable.js'
    ]}))
    .pipe($.concat('app.js'))
    .pipe($.if(PRODUCTION, $.uglify()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
    
}

 

The result is still this error message: 

app.js:19876 Uncaught ReferenceError: FooTable is not defined
    at app.js:19876

 

Glenn Philp 8 months ago

Michelle,

I added FooTable using the bower install without any build issue. One item I forgot to mention is adding the bable preset to your package.json file.

The following is my setup and how I work everyday.

Let's run through versions.

  • NodeJS v6.9.2
  • npm v4.0.5
  • Bower v1.8.0
  • Gulp CLI v3.9.1
  • Gulp Local v4.0.0-alpha.2
  • Foundation v6.3.0

My Package.json file (Important piece here is babel presets)

{
  "name": "foundation-zurb-template",
  "version": "1.0.0",
  "description": "Official ZURB Template for Foundation for Sites.",
  "main": "gulpfile.js",
  "scripts": {
    "start": "gulp",
    "build": "gulp build --production"
  },
  "author": "ZURB <foundation@zurb.com>",
  "license": "MIT",
  "devDependencies": {
    "babel-preset-es2015": "^6.3.13",
    "babel-register": "^6.7.2",
    "browser-sync": "^2.10.0",
    "gulp": "gulpjs/gulp#4.0",
    "gulp-autoprefixer": "^3.1.0",
    "gulp-babel": "^6.1.2",
    "gulp-cli": "^1.2.1",
    "gulp-combine-mq": "^0.4.0",
    "gulp-concat": "^2.5.2",
    "gulp-cssnano": "^2.1.0",
    "gulp-extname": "^0.2.0",
    "gulp-if": "^2.0.0",
    "gulp-imagemin": "^2.2.1",
    "gulp-inline-source": "^3.0.0",
    "gulp-load-plugins": "^1.1.0",
    "gulp-sass": "^2.1.0",
    "gulp-sourcemaps": "^1.6.0",
    "gulp-uglify": "^1.2.0",
    "gulp-uncss": "^1.0.1",
    "js-yaml": "^3.4.6",
    "panini": "^1.3.0",
    "rimraf": "^2.4.3",
    "style-sherpa": "^1.0.0",
    "yargs": "^3.8.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/zurb/foundation-zurb-template.git"
  },
  "bugs": {
    "url": "https://github.com/zurb/foundation-sites/issues",
    "email": "foundation@zurb.com"
  },
  "babel": {
    "presets": [
      "es2015"
    ]
  },
  "private": true
}

Gulp file:

'use strict';

import plugins          from 'gulp-load-plugins';
import yargs            from 'yargs';
import browser          from 'browser-sync';
import gulp             from 'gulp';
import inlinesource     from 'gulp-inline-source';
import combineMq        from 'gulp-combine-mq';
import panini           from 'panini';
import rimraf           from 'rimraf';
import sherpa           from 'style-sherpa';
import yaml             from 'js-yaml';
import fs               from 'fs';

// Load all Gulp plugins into one variable
const $ = plugins();

// Check for --production flag
const PRODUCTION = !!(yargs.argv.production);

// Load settings from settings.yml
const { COMPATIBILITY, TARGET, PORT, BROWSER, UNCSS_OPTIONS, PATHS, COPY, STYLES, JS, PROJECT } = loadConfig();

function loadConfig() {
  let ymlFile = fs.readFileSync('config.yml', 'utf8');
  return yaml.load(ymlFile);
}

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
 gulp.series(clean, sass, jsFoundation, gulp.parallel(pages, copyPhp, copyParts, copyIncludes, images, copyAssets, copyJS, copyFonts, copyScreenshot), styleGuide));

// Build the site, run the server, and watch for file changes
gulp.task('default',
  gulp.series('build', server, watch));

// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
  rimraf(PATHS.dist, done);
}

// Copy files out of the assets folder
// This task skips over the "img", "js", and "scss" folders, which are parsed separately
function copyAssets() {
  return gulp.src(COPY.assets)
    .pipe(gulp.dest(PATHS.dist + '/assets'));
}

function copyJS() {
  return gulp.src(COPY.js)
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

function copyFonts() {
  return gulp.src(COPY.fonts)
    .pipe(gulp.dest(PATHS.dist + '/fonts'));
}

function copyParts() {
  return gulp.src(COPY.parts)
    .pipe(gulp.dest(PATHS.dist + '/template-parts'));
}

function copyIncludes() {
  return gulp.src(COPY.inc)
    .pipe(gulp.dest(PATHS.dist + '/inc'));
}

function copyPhp() {
  return gulp.src(COPY.php)
    .pipe($.if(PRODUCTION, inlinesource({
      rootpath: ('../')
    })))
    .pipe($.if(PRODUCTION, gulp.dest(PATHS.wp)))
    .pipe($.if(!PRODUCTION, gulp.dest(PATHS.dist)));
}

function copyScreenshot() {
  return gulp.src(COPY.screenshot)
    .pipe(gulp.dest(PATHS.dist));
}

// Copy page templates into finished HTML files
function pages() {
  return gulp.src('src/pages/**/*.{html,hbs,handlebars}')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/layouts/',
      partials: 'src/partials/',
      data: 'src/data/',
      helpers: 'src/helpers/'
    }))
    .pipe(gulp.dest(PATHS.dist));
}

// Load updated HTML templates and partials into Panini
function resetPages(done) {
  panini.refresh();
  done();
}

// Generate a style guide from the Markdown content and HTML template in styleguide/
function styleGuide(done) {
  sherpa('src/styleguide/index.md', {
    output: PATHS.dist + '/styleguide.html',
    template: 'src/styleguide/template.html'
  }, done);
}

// Compile Sass into CSS
// In production, the CSS is compressed
function sass() {
  return gulp.src(STYLES.core)
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      outputStyle: 'expanded',
      includePaths: STYLES.include
    })
      .on('error', $.sass.logError))
    .pipe($.autoprefixer({
      browsers: COMPATIBILITY
    }))
    // Comment in the pipe below to run UnCSS in production
    .pipe($.if(PRODUCTION, $.uncss(UNCSS_OPTIONS)))
    .pipe($.if(PRODUCTION, combineMq({ beautify: false })))
    .pipe($.if(PRODUCTION, $.cssnano()))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist))
    .pipe(browser.reload({ stream: true }));
}

// Combine JavaScript into one file
// In production, the file is minified
function jsFoundation() {
  return gulp.src(JS.zf)
    .pipe($.sourcemaps.init())
    .pipe($.babel({ignore: ['what-input.js']}))
    .pipe($.concat('core.js'))
    .pipe($.if(PRODUCTION, $.uglify()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

// Copy images to the "dist" folder
// In production, the images are compressed
function images() {
  return gulp.src('src/assets/img/**/*')
    .pipe($.if(PRODUCTION, $.imagemin({
      progressive: true
    })))
    .pipe(gulp.dest(PATHS.dist + '/assets/img'));
}

// Start a server with BrowserSync to preview the site in
function server(done) {
  browser.init({
    proxy: TARGET,
    browser: BROWSER
    //server: PATHS.dist, port: PORT
  });
  done();
}

// Reload the browser with BrowserSync
function reload(done) {
  browser.reload();
  done();
}

// Watch for changes to static assets, pages, Sass, and JavaScript
function watch() {
  gulp.watch(COPY.js, copyJS);
  gulp.watch(COPY.fonts, copyFonts);
  gulp.watch(COPY.assets, copyAssets);
  gulp.watch('src/{template-parts,inc}/**/*.php').on('all', gulp.series(copyParts, copyIncludes, browser.reload));
  gulp.watch('src/pages/**/*.{php,html}').on('all', gulp.series(pages, copyPhp, browser.reload));
  gulp.watch('src/{layouts,partials}/**/*.{php,html}').on('all', gulp.series(resetPages, pages, browser.reload));
  gulp.watch('src/assets/scss/**/*.scss').on('all', gulp.series(sass, browser.reload));
  gulp.watch('src/assets/js/**/*.js').on('all', gulp.series(jsFoundation, browser.reload));
  gulp.watch('src/assets/img/**/*').on('all', gulp.series(images, browser.reload));
  gulp.watch('src/styleguide/**').on('all', gulp.series(styleGuide, browser.reload));
}

Config file:

# Your project's server will run on localhost:xxxx at this port
TARGET: "www.localhost.dev"
BROWSER: ["google chrome"]
PORT: 8000

# Autoprefixer will make sure your CSS works with these browsers
COMPATIBILITY:
  - "last 2 versions"
  - "ie >= 9"
  - "ios >= 7"

# UnCSS will use these settings
UNCSS_OPTIONS:
  html:
    - "src/**/*.php"
  ignore:
    - !!js/regexp .foundation-mq
    - !!js/regexp ^\.is-.*
    - !!js/regexp ^\.show-.*

# Gulp will reference these paths when it copies files
PATHS:
  # Path to dist folder
  dist: "../wp-content/themes/themeName"
  wp: "../wp-content/themes/themeName"
COPY:
  # Paths to static assets that aren't images, CSS, or JavaScript
  assets:
    - "src/assets/**/*"
    - "!src/assets/{img,js,scss,fonts}/**/*"
  fonts:
    - "bower_components/foundation-icon-fonts/foundation-icons.eot"
    - "bower_components/foundation-icon-fonts/foundation-icons.svg"
    - "bower_components/foundation-icon-fonts/foundation-icons.ttf"
    - "bower_components/foundation-icon-fonts/foundation-icons.woff"
    - "src/assets/fonts/**/*"
  js:
    # Individual Foundation components
    # If you aren't using a component, just remove it from the list
    - "bower_components/foundation-sites/js/foundation.abide.js"
    - "bower_components/foundation-sites/js/foundation.accordion.js"
    - "bower_components/foundation-sites/js/foundation.accordionMenu.js"
    - "bower_components/foundation-sites/js/foundation.drilldown.js"
    - "bower_components/foundation-sites/js/foundation.dropdown.js"
    - "bower_components/foundation-sites/js/foundation.dropdownMenu.js"
    - "bower_components/foundation-sites/js/foundation.equalizer.js"
    - "bower_components/foundation-sites/js/foundation.interchange.js"
    - "bower_components/foundation-sites/js/foundation.magellan.js"
    - "bower_components/foundation-sites/js/foundation.offcanvas.js"
    - "bower_components/foundation-sites/js/foundation.orbit.js"
    - "bower_components/foundation-sites/js/foundation.responsiveMenu.js"
    - "bower_components/foundation-sites/js/foundation.responsiveToggle.js"
    - "bower_components/foundation-sites/js/foundation.reveal.js"
    - "bower_components/foundation-sites/js/foundation.slider.js"
    - "bower_components/foundation-sites/js/foundation.sticky.js"
    - "bower_components/foundation-sites/js/foundation.tabs.js"
    - "bower_components/foundation-sites/js/foundation.toggler.js"
    - "bower_components/foundation-sites/js/foundation.tooltip.js"
    - "bower_components/foundation-sites/js/foundation.zf.responsiveAccordionTabs.js"
    # Waypoints
    - "bower_components/gsap/src/uncompressed/TweenMax.js"
    - "bower_components/scrollmagic/scrollmagic/uncompressed/**/*"
    # - "bower_components/waypoints/lib/jquery.waypoints.js"
    # - "bower_components/headroom.js/dist/headroom.js"
    # Lightboxes
    # - "bower_components/fancyBox/source/jquery.fancybox.pack.js"
    # Improve images for hidef
    - "bower_components/retinajs/dist/retina.js"
    # JS CSS
    - "bower_components/eqcss/EQCSS.js"
    # Slider
    - "bower_components/owl.carousel/dist/owl.carousel.js"
    - "bower_components/swiper/dist/js/swiper.js"
    # - "bower_components/flickity/js/flickity.js"
    # LocalStorage loader
    - "bower_components/basket.js/dist/basket.js"
    # Custom JS
    - "src/assets/js/wp-includes/**/*"
    # Paths to your own project code are here
    - "src/assets/js/triggers.js"
  php:
    - "src/pages/**/*"
  parts:
    - "src/template-parts/**/*"
  inc:
    - "src/inc/**/*"
  screenshot:
    - "src/wp-required/screenshot.png"
STYLES:
  # Paths to Sass libraries, which can then be loaded with @import
  core:
    - "src/assets/scss/style.scss"
    - "src/assets/scss/style-desktop.scss"
    - "src/assets/scss/style-tablet.scss"
  include:
    - "bower_components/foundation-sites/scss"
    - "bower_components/foundation-icon-fonts"
    - "bower_components/foundation-font-awesome-buttons/src"
    - "bower_components/motion-ui/src"
    - "bower_components/animate.css/source"
    - "bower_components/fontawesome/scss"
    - "bower_components/megatype"
    - "bower_components/modular-scale/stylesheets/"
    - "bower_components/magnific-popup/src/css"
JS:
  # Paths to JavaScript libraries, which are combined into one file
  zf:
    # Libraries required by Foundation
    - "bower_components/jquery/dist/jquery.js"
    - "bower_components/what-input/dist/what-input.js"
    # Core Foundation files
    - "bower_components/foundation-sites/js/foundation.core.js"
    - "bower_components/foundation-sites/js/foundation.util.*.js"
    # 3rd Party Frameworks
    - "bower_components/footable/compiled/footable.js"

Michelle Child 8 months ago

 Glenn,

Thank you for your help, I really, really appreciate it. I'm doing my best to follow along, but I'm new to Foundation and Gulp and I'm following you only up to a certain point. 

Among the differences in our gulpfiles, I can't tell which parts I'd need to implement & which parts are custom to your build. I'll include my files below. Do I need to add to the section below, as you've done?

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
 gulp.series(clean, gulp.parallel(pages, sass, javascript, images, copy), styleGuide));
// Copy files out of the assets folder
// This task skips over the "img", "js", and "scss" folders, which are parsed separately
function copy() {
  return gulp.src(PATHS.assets)
    .pipe(gulp.dest(PATHS.dist + '/assets'));
}

We also have a some version differences. I'm using the latest version of the Foundation for Sites ZURB template and here are the versions I have running out of the box:

  • Node: v4.6.0
  • npm v2.15.9
  • Bower v1.8.0
  • Gulp CLI v1.2.2
  • Gulp Local v4.0.0-alpha.2
  • FoundationCLI v2.1.0

I'm nervous to update these because this is how they come out of the box, and I don't want to move too far from how Foundation is set to work. Is this the issue?

Files:

My package.json file already had the babel presets line, so I'm good there.

{
  "name": "foundation-zurb-template",
  "version": "1.0.0",
  "description": "Official ZURB Template for Foundation for Sites.",
  "main": "gulpfile.js",
  "scripts": {
    "start": "gulp",
    "build": "gulp build --production"
  },
  "author": "ZURB <foundation@zurb.com>",
  "license": "MIT",
  "devDependencies": {
    "babel-preset-es2015": "^6.3.13",
    "babel-register": "^6.7.2",
    "browser-sync": "^2.10.0",
    "gulp": "gulpjs/gulp#4.0",
    "gulp-autoprefixer": "^3.1.0",
    "gulp-babel": "^6.1.2",
    "gulp-cli": "^1.2.1",
    "gulp-concat": "^2.5.2",
    "gulp-cssnano": "^2.1.0",
    "gulp-extname": "^0.2.0",
    "gulp-if": "^2.0.0",
    "gulp-imagemin": "^2.2.1",
    "gulp-load-plugins": "^1.1.0",
    "gulp-sass": "^2.1.0",
    "gulp-sourcemaps": "^1.6.0",
    "gulp-uglify": "^1.2.0",
    "gulp-uncss": "^1.0.1",
    "js-yaml": "^3.4.6",
    "panini": "^1.3.0",
    "rimraf": "^2.4.3",
    "style-sherpa": "^1.0.0",
    "yargs": "^3.8.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/zurb/foundation-zurb-template.git"
  },
  "bugs": {
    "url": "https://github.com/zurb/foundation-sites/issues",
    "email": "foundation@zurb.com"
  },
  "babel": {
    "presets": ["es2015"]
  },
  "private": true
}

 

My gulpfile.babel.js :

 

'use strict';

import plugins  from 'gulp-load-plugins';
import yargs    from 'yargs';
import browser  from 'browser-sync';
import gulp     from 'gulp';
import panini   from 'panini';
import rimraf   from 'rimraf';
import sherpa   from 'style-sherpa';
import yaml     from 'js-yaml';
import fs       from 'fs';

// Load all Gulp plugins into one variable
const $ = plugins();

// Check for --production flag
const PRODUCTION = !!(yargs.argv.production);

// Load settings from settings.yml
const { COMPATIBILITY, PORT, UNCSS_OPTIONS, PATHS } = loadConfig();

function loadConfig() {
  let ymlFile = fs.readFileSync('config.yml', 'utf8');
  return yaml.load(ymlFile);
}

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
 gulp.series(clean, gulp.parallel(pages, sass, javascript, images, copy), styleGuide));

// Build the site, run the server, and watch for file changes
gulp.task('default',
  gulp.series('build', server, watch));

// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
  rimraf(PATHS.dist, done);
}

// Copy files out of the assets folder
// This task skips over the "img", "js", and "scss" folders, which are parsed separately
function copy() {
  return gulp.src(PATHS.assets)
    .pipe(gulp.dest(PATHS.dist + '/assets'));
}

// Copy page templates into finished HTML files
function pages() {
  return gulp.src('src/pages/**/*.{html,hbs,handlebars}')
    .pipe(panini({
      root: 'src/pages/',
      layouts: 'src/layouts/',
      partials: 'src/partials/',
      data: 'src/data/',
      helpers: 'src/helpers/'
    }))
    .pipe(gulp.dest(PATHS.dist));
}

// Load updated HTML templates and partials into Panini
function resetPages(done) {
  panini.refresh();
  done();
}

// Generate a style guide from the Markdown content and HTML template in styleguide/
function styleGuide(done) {
  sherpa('src/styleguide/index.md', {
    output: PATHS.dist + '/styleguide.html',
    template: 'src/styleguide/template.html'
  }, done);
}

// Compile Sass into CSS
// In production, the CSS is compressed
function sass() {
  return gulp.src('src/assets/scss/app.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      includePaths: PATHS.sass
    })
      .on('error', $.sass.logError))
    .pipe($.autoprefixer({
      browsers: COMPATIBILITY
    }))
    // Comment in the pipe below to run UnCSS in production
    //.pipe($.if(PRODUCTION, $.uncss(UNCSS_OPTIONS)))
    .pipe($.if(PRODUCTION, $.cssnano()))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/css'))
    .pipe(browser.reload({ stream: true }));
}

// Combine JavaScript into one file
// In production, the file is minified
function javascript() {
  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.babel({ignore: [
      'what-input.js',
      'footable.js'
    ]}))
    .pipe($.concat('app.js'))
    .pipe($.if(PRODUCTION, $.uglify()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
    
}

// Copy images to the "dist" folder
// In production, the images are compressed
function images() {
  return gulp.src('src/assets/img/**/*')
    .pipe($.if(PRODUCTION, $.imagemin({
      progressive: true
    })))
    .pipe(gulp.dest(PATHS.dist + '/assets/img'));
}

// Start a server with BrowserSync to preview the site in
function server(done) {
  browser.init({
    server: PATHS.dist, port: PORT
  });
  done();
}

// Reload the browser with BrowserSync
function reload(done) {
  browser.reload();
  done();
}

// Watch for changes to static assets, pages, Sass, and JavaScript
function watch() {
  gulp.watch(PATHS.assets, copy);
  gulp.watch('src/pages/**/*.html').on('all', gulp.series(pages, browser.reload));
  gulp.watch('src/{layouts,partials}/**/*.html').on('all', gulp.series(resetPages, pages, browser.reload));
  gulp.watch('src/assets/scss/**/*.scss').on('all', gulp.series(sass, browser.reload));
  gulp.watch('src/assets/js/**/*.js').on('all', gulp.series(javascript, browser.reload));
  gulp.watch('src/assets/img/**/*').on('all', gulp.series(images, browser.reload));
  gulp.watch('src/styleguide/**').on('all', gulp.series(styleGuide, browser.reload));
}

My Config.yml 

# Your project's server will run on localhost:xxxx at this port
PORT: 8000

# Autoprefixer will make sure your CSS works with these browsers
COMPATIBILITY:
  - "last 2 versions"
  - "ie >= 9"
  - "ios >= 7"

# UnCSS will use these settings
UNCSS_OPTIONS:
  html:
    - "src/**/*.html"
  ignore:
    - !!js/regexp .foundation-mq
    - !!js/regexp ^\.is-.*

# Gulp will reference these paths when it copies files
PATHS:
  # Path to dist folder
  dist: "dist"  
  # Paths to static assets that aren't images, CSS, or JavaScript
  assets:
    - "src/assets/**/*"
    - "!src/assets/{img,js,scss}/**/*"
  # Paths to Sass libraries, which can then be loaded with @import
  sass:
    - "bower_components/foundation-sites/scss"
    - "bower_components/motion-ui/src"
  # Paths to JavaScript libraries, which are combined into one file
  javascript:
    # Libraries required by Foundation
    - "bower_components/jquery/dist/jquery.js"
    - "bower_components/what-input/dist/what-input.js"
    # Core Foundation files
    - "bower_components/foundation-sites/js/foundation.core.js"
    - "bower_components/foundation-sites/js/foundation.util.*.js"
    # Individual Foundation components
    # If you aren't using a component, just remove it from the list
    - "bower_components/foundation-sites/js/foundation.abide.js"
    - "bower_components/foundation-sites/js/foundation.accordion.js"
    - "bower_components/foundation-sites/js/foundation.accordionMenu.js"
    - "bower_components/foundation-sites/js/foundation.drilldown.js"
    - "bower_components/foundation-sites/js/foundation.dropdown.js"
    - "bower_components/foundation-sites/js/foundation.dropdownMenu.js"
    - "bower_components/foundation-sites/js/foundation.equalizer.js"
    - "bower_components/foundation-sites/js/foundation.interchange.js"
    - "bower_components/foundation-sites/js/foundation.magellan.js"
    - "bower_components/foundation-sites/js/foundation.offcanvas.js"
    - "bower_components/foundation-sites/js/foundation.orbit.js"
    - "bower_components/foundation-sites/js/foundation.responsiveMenu.js"
    - "bower_components/foundation-sites/js/foundation.responsiveToggle.js"
    - "bower_components/foundation-sites/js/foundation.reveal.js"
    - "bower_components/foundation-sites/js/foundation.slider.js"
    - "bower_components/foundation-sites/js/foundation.sticky.js"
    - "bower_components/foundation-sites/js/foundation.tabs.js"
    - "bower_components/foundation-sites/js/foundation.toggler.js"
    - "bower_components/foundation-sites/js/foundation.tooltip.js"
    - "bower_components/foundation-sites/js/foundation.zf.responsiveAccordionTabs.js"
    
    # 3rd Party Frameworks 
    - "bower_components/footable/compiled/footable.js"

    # Paths to your own project code are here
    - "src/assets/js/!(app).js"
    - "src/assets/js/app.js"

And I'm calling it on my app.js with 

$(document).foundation()

jQuery(function($){
	$('.table').footable();
});

Thanks again.

Glenn Philp 8 months ago

Michelle,

Bad news, I am unable to get FooTable to work with the Foundation 6.3 build out-of-the-box. If this is a requirement and you cannot switch responsive table plugins I would reach out to the Foundation team on Twitter. As they are usually quick to help. Send them a link to your Forum post.

Good news, if you can switch. I was able to install Tablesaw from Filament group `bower install tablesaw --save` and then replace the footable.js with the tablesaw.jquery.js and tablesaw-init.js without any issue.

It is apparent that FooTable has more features like AJAX calls and pagination for dynamic data that makes it definitely better than Tablesaw.

The other quick solution would be to use FooTable as a standalone plugin. This would mean removing jQuery from being included in the app.js file.

<!-- HTML file -->
<script src="jquery.js"></script>
<script src="footable.js"></script>
<script src="app.js"></script>
<!-- CONFIG.YML file -->
# Libraries required by Foundation
    # Remove the jQuery path below
    # - "bower_components/jquery/dist/jquery.js"
    - "bower_components/what-input/dist/what-input.js"
    # Core Foundation files
    - "bower_components/foundation-sites/js/foundation.core.js"
    - "bower_components/foundation-sites/js/foundation.util.*.js"
    # Individual Foundation components
    # If you aren't using a component, just remove it from the list
    - "bower_components/foundation-sites/js/foundation.abide.js"
    - "bower_components/foundation-sites/js/foundation.accordion.js"
    - "bower_components/foundation-sites/js/foundation.accordionMenu.js"
    - "bower_components/foundation-sites/js/foundation.drilldown.js"
    - "bower_components/foundation-sites/js/foundation.dropdown.js"
    - "bower_components/foundation-sites/js/foundation.dropdownMenu.js"
    - "bower_components/foundation-sites/js/foundation.equalizer.js"
    - "bower_components/foundation-sites/js/foundation.interchange.js"
    - "bower_components/foundation-sites/js/foundation.magellan.js"
    - "bower_components/foundation-sites/js/foundation.offcanvas.js"
    - "bower_components/foundation-sites/js/foundation.orbit.js"
    - "bower_components/foundation-sites/js/foundation.responsiveMenu.js"
    - "bower_components/foundation-sites/js/foundation.responsiveToggle.js"
    - "bower_components/foundation-sites/js/foundation.reveal.js"
    - "bower_components/foundation-sites/js/foundation.slider.js"
    - "bower_components/foundation-sites/js/foundation.sticky.js"
    - "bower_components/foundation-sites/js/foundation.tabs.js"
    - "bower_components/foundation-sites/js/foundation.toggler.js"
    - "bower_components/foundation-sites/js/foundation.tooltip.js"
    - "bower_components/foundation-sites/js/foundation.zf.responsiveAccordionTabs.js"
    # Paths to your own project code are here
    - "src/assets/js/!(app).js"
    - "src/assets/js/app.js"

 

Michelle Child about 2 months ago

Hi Glenn, 

Better late than never? Thank you so much for your help.