A framework for front (frob) enders (tenders) everywhere
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
source
test
.gitignore
.travis.yml
LICENSE.txt
README.md
gulpfile.js
notify.sh
package.json
wearefine.github.io.manifest.txt

README.md

Frob Core

Build Status Code Climate

Because you're not hardcore.

P.S. The inline code documentation in this pup is rock solid.

JavaScript

  1. Copy source/javascripts/frob_core_helpers.js and source/javascripts/frob_core.js to your project.
  2. Apply the structure of source/javascripts/application.js to your project.
  3. Start Frob Core (usually in application.js): ;(function() { window.FCH = new FrobCoreHelpers(FC); })();

Initialization and Options

The core holder must be passed in as the first argument for initialization, i.e. new FrobCoreHelpers(FC), but all other options are, fittingly, optional. These are passed in via object as the second argument, i.e. new FrobCoreHelpers(FC, { ... }).

Option Type Default Description
mobile_fps boolean true Attach the scroll listener for u-disable-hover
breakpoints function null To set custom breakpoint, pass a function with two args and return a string: boolean object (example below)
preserve_breakpoints boolean true Merge custom breakpoints with default breakpoints. If false, value of breakpoints removes all default breakpoints
window.FCH = new FrobCoreHelpers({}, {
  breakpoints: function(ww) {
    return {
      boot_size: ww < 12
    };
  },
  preserve_breakpoints: false
});

// FCH.bp => { boot_size: <true|false> }

Hooks

Direct descendants of the core holder can access hooks using reserved property names. These are called automagically, avoiding declaring multiple event listeners on the document or window.

FC.ui = {
  ready: {
    if(FCH.exists('.js-slider')) {
      this.mySuperSliderInitialization();
    }
  },

  mySuperSliderInitialization: function() {
    ...
  }
};

For example, use the resize function to change the width of .mydiv to match the window's width.

FC._ui = {
  resize: function() {
    $('.mydiv').width(FCH.dimensions.ww);
  }
};

Hooks can also be added by adding a function to the appropriate FCH array.

var sticky = function($el) {
  $el.css('position', 'fixed');
}
FCH.scroll.push(sticky);
Hook Called on
scroll window scroll
resize window resize
ready DOMContentLoaded
load window onload

Special Note: Using this in a hook function will refer to the parent namespace, not FrobCoreHelper.

FC._ui = {
  boo: function() {
    alert('BOOooooOOoooOO');
  }

  resize: function() {
    this.boo();
  }
}
// a scary alert is triggered every time the window is resized

Debounced Events

Sometimes, a callback function on rapid-firing window events can be resource-intensive. Thanks to pioneering efforts from John Hann, Paul Irish, and Underscore.js, these events can be tricked to fire only once or twice instead of continuously.

Wrap your function in FCH.debounce when adding it to a hook.

FC.nav_listeners = {
  ready: function() {
    FCH.resize.push( FCH.debounce( this.resourceConsumingFunction.bind(this) ) );
  },

  resourceConsumingFunction: function() {
    this.destroy();
  },

  destroy: function() { ... }
};
Param Description
func Callback function
threshold Milliseconds to check between fires (defaults to 250)

Breakpoints

These defaults are available from FCH.bp. Returns boolean. They can be appended, overwritten, or removed entirely when declaring options.

Accessor Description
small window width less than or equal to 767
small_up window width greater than or equal to 768
medium_portrait window width between 768 and 960
medium window width between 768 and 1024
large_down window width less than 1024
large window width greater than 1024
if(FCH.bp.small) {
  FCH.$body.addClass('mobile');
}

Dimensions

Available from FCH.dimensions

Accessor Description
ww window width
wh window height

Cached jQuery Objects

Only available if jQuery is included.

Accessor Description
FCH.$body equivalent to $('body')
FCH.$window equivalent to $(window)

Default Values

Add default values for missing values in functions, similar to Ruby's variable ||= value

function(required_value, missing_value) {
  missing_value = FCH.setDefault(missing_value, 10);
}

addClass

addClass adds a class to an element with vanilla JS.

Param Description
element JS Object
class String of class to be added
var el = document.createElement('div');
FCH.addClass(el, 'foo'); // el.className is now "foo"

removeClass

removeClass removes a class to an element with vanilla JS if the element already has that class.

Param Description
element JS Object
class String of class to be removed
var el = document.createElement('div');
el.className = 'foo';
FCH.removeClass(el, 'foo'); // el.className is now ""

toggleClass

toggleClass adds a class to an element with vanilla JS if the element does not already have the class, removes the class if it does.

Param Description
element JS Object
class String of class to be toggled
var el = document.createElement('div');
FCH.toggleClass(el, 'foo'); // el.className is now "foo"
FCH.toggleClass(el, 'foo'); // el.className is now ""

Loops

loop saves characters on for loops.

Param Description
selector Array, NodeList or DOM selector
callback requires one argument - the current looped item in callback
var titles = '';
FCH.loop('.posts', function(post) {
  titles += post.querySelector('h2').textContent;
});

Local Storage

Read, Update, and Destroy localStorage objects.

Function Description
FCH.localGet(key) retrieve value (returns false if key is not defined)
FCH.localSet(key, value) create or update key
FCH.localClear({optional} key) if key is provided, destroy just that key; otherwise destroy all keys

Existence

Check to see if an element exists on the page

// <div class="henry"></div>

FCH.exists('.henry') // => true

IE

Test for IE versions. Returns boolean. Only use in the most trying of times. Agent strings are unreliable.

Accessor Description
FCH.IE10 true if browser is IE10
FCH.IE9 true if browser is IE9
FCH.anyIE true if browser is Internet Explorer

SCSS

  1. Copy source/stylesheets to your project (usually replacing app/assets/stylesheets)

Variables

Variable Description
$em-base font-size (must be in pixels) used for emCalc and remCalc.
$f-sans font stack for sans-serif fonts
$f-serif font stack for serif fonts
$f-script font stack for script fonts
$f-monospace font stack for monospaced fonts
$f-international font fallback stack for multilingual fonts
$c-white vanilla palette for #fff
$c-black vanilla palette for #000

Font-stack variables are designed to be applied after custom font names.

$f-opensans: 'Open Sans', $f-sans;
$f-content: $f-opensans;

Mixins

hover

Quick shortcut for &:hover { ... }. Accepts color value or block.

@include hover($c-white)

@include hover {
  background: $c-white;
}

stack

Make z-indexing easy. Create an ordered list of your classes and call it inside your class.

$lightbox: (
  'lightbox-bg',
  'lightbox-content'
);

.lightbox {
  &-bg {
    @include stack($lightbox); // z-index: 1
  }
  &-content {
    @include stack($lightbox); // z-index: 2
  }
}

If you want to name your ordered list different from your classes, pass a key as the second argument.

.lightbox {
  &-bg {
    @include stack($lightbox, 'lightbox-content'); // z-index: 2
  }
  &-content {
    @include stack($lightbox, 'lightbox-bg'); // z-index: 1
  }
}

bp

Param Accepts Default
$name string required
$breakpoint_list map $breakpoints
$additional_breakpoints arglist null

Put a block of content within a media breakpoint using the $breakpoints list defined in _variables.scss.

.show--mobile {
  display: none;
  @include bp(small) {
    display: block;
  }
}

To use a custom set of breakpoints, pass the list in the second argument (default is $breakpoints).

$tweakpoints: (
  'really-specific-nav-size': ( min-width: 438px )
);
@include bp(really-specific-nav-size, $tweakpoints) { ... }

Multiple breakpoints can be combined with an arglist starting at the third argument. Note that proper order should be obeyed and will not be automatically corrected (i.e. including print or screen as the third argument).

.narrow-print {
  // Prints `@media only print and (min-width: 421px) and (max-width: 767px)`
  @include bp(print, $breakpoints, small, medium-down) { ... }
}

triangle

Apply a CSS triangle to an element.

Param Accepts Default
$direction top, bottom, left, right top
$color hex $c-black
$size px 30px
$shadow boolean false
.nav-dropdown {
  @include triangle(bottom, $c-white);
}

placeholder

Pass a block to apply properties to input placeholder styles. Strongly recommended to be used only at root-level. Accepts block.

@include placeholder {
  color: $c-gray;
  text-shadow: 1px 1px 0 $c-black;
}

ie

Target specific Internet Explorer versions, and optionally pass in a version number. Only use this mixin as a last resort. Feature detection is strongly preferred. Accepts block.

.animated-element {
  @include ie { ... } // .ie .animated-element
  @include ie(9) { ... } // .ie9 .animated-element
}

touch

Target touch devices using Modernizr. Accepts block.

.nav {
  @include touch { ... } // .touch .nav
}

clearfix

Use a Nicolas Gallagher clearfix. A .clearfix class is available in _utilities.scss

.cf {
  @include clearfix;
}

vertical-center

Vertically align an object without vertical-align.

.center-between {
  @include vertical-center;
}

Functions

emCalc

Convert px to em. Relies on $em-base in _fine_variables.scss, but this can be overwritten in your own _variables.scss

body {
  font-size: emCalc(16px);
}

remCalc

Convert px to rem. Relies on $em-base in _fine_variables.scss, but this can be overwritten in your own _variables.scss

body {
  font-size: remCalc(16px);
}

match

Find pair of value or key in map. If value/key cannot be found, returns false

$descriptions: (
  'big' : 'blue',
  'wet' : 'wide'
);

.whats-the-sea-like {
  &:before {
    background: match($descriptions, 'big'); // 'blue'
    content: match($descriptions, 'wet'); // 'wide'
  }
}

negate

Invert a number.

.upside-down {
  top: negate(10px);
}

gray

Use a gray color from the $grays map.

$grays: (
  30: #777
);

a {
  color: gray(30); // #777
}

File Structure and Naming Conventions

JavaScript

Child files should have declarations in the following order:

  1. Scoped variables
  2. FCH hooks
  3. Public functions
  4. Protected functions

Example:

FC.ui = {
  logo_height: 100,

  ready: function() {
    this.setLogoHeight();
  },

  load: function() {
    this.setLogoHeight();
  },

  resize: function() {
    this.setLogoHeight();
  },

  setLogoHeight: function() {
    var logo = this._getLogo();
    this.logo_height = logo.innerHeight;
  },

  _getLogo: function() {
    return document.querySelector('.logo');
  }
}

Functions should be lowerCamelCase; variables should be lower_underscore. All functions must include a short description and should be documented using JSDoc standards.

/**
 * Update value of scoped `logo_height` var
 * @fires _getLogo
 */
setLogoHeight: function() { ... },

/**
 * Find the logo element
 * @protected
 * @return {Node}
 */
_getLogo: function() { ... }

Testing

Install all dependencies:

npm install --save-dev