FrenchDipJS

FrenchDipJS

FrenchDipJS

A flexible, light-weight module for creating custom components

Download View on Github

Not every project needs the full arsenal of a front-end framework.

Why FrenchDip

Performance can suffer from loading all of those unused bits of JavaScript.
Development can slow from steep learning curves.

A project that
- has little dynamic content to display OR
- has a back-end templating solution (PHP, JavaServer Pages, ASP.NET, etc.)
may be biting off more front-end framework than it will ever need to chew.

Chances are a front-end framework is being loaded simply to offer means to add custom functionality. This is where FrenchDipJS shines like a freshly baked baguette.

What FrenchDip

FrenchDip is a component wrapper that ties JavaScript classes defined in your project to instances of assigned DOM elements. This allows you to basically build your own framework.

How FrenchDip

Displays two different numbers

HTML
Use the "data-frenchdip" attribute to request the JavaScript Class that needs to be invoked for an element.

<p>Displays two different numbers</p>

<div class="your-class-name"
    data-frenchdip="YourClass"></div>

<div class="your-class-name"
    data-frenchdip="YourClass"></div>

JavaScript
Create a JavaScript Class and register it with FrenchDip, provide the Class itself and then its name as a string.

function YourClass() {
    // this.root - node tied to an instance
    // this.options - node's data-attr values
    this.root.innerHTML = Math.random();
}

FrenchDip.register(YourClass, 'YourClass');

FrenchDipJS collects registered DOM elements, forEach's through them, and invokes a new instance of the requested Class for each one.

If the name property is set on a registered component, the string form isn’t required as a second argument for FrenchDip.register(YourClass). If the name property is not set, FrenchDip requires the name as a string FrenchDip.register(YourClass, 'YourClass').

Install

Manual install from GitHub

Bower install: bower install french-dip --save

Setup

Be sure FrenchDip loads before your app's JavaScript, otherwise it can get read in anywhere in your document. Head, body, below the footer, it's all good.

<!-- French Dip -->
<script src="french-dip/french-dip.js"></script>

<!-- App JS -->
<script src="scripts/app.js"></script>

Usage Examples

Examples with vanilla JavaScript

Bruce Wayne

...for 3 seconds anyway

<div class="demo--js"
    data-frenchdip="DemoJS"
    data-heading="nananana Batman"
    data-new-src="batman.png"
    data-interval="3000">
    <img src="bruce-wayne.png"/>
    <p class="heading">Bruce Wayne</p>
</div>

Bruce Wayne

Changes once

<div class="demo--js"
    data-frenchdip="DemoJS"
    data-heading="Batman Beyond"
    data-new-src="batman-beyond.png">

    <img src="bruce-wayne.png"/>
    <p class="heading">Bruce Wayne</p>
</div>
/** JavaScript Class pattern */

function DemoJS() {
    var heading = this.root.querySelectorAll('h4')[0],
        img = this.root.querySelectorAll('img')[0],
        newHead = this.options.heading,
        newSrc = this.options.newSrc,
        oldHead, oldSrc;

    if (this.options.interval) {
        runInterval(this.options.interval);
    } else {
        runTimeout();
    }

    function runInterval(interval) {
        setInterval(swapAssets, interval);
    }
    function runTimeout() {
        setTimeout(swapAssets, 1000);
    }
    function swapAssets() {
        oldHead = heading.innerHTML;
        oldSrc = img.getAttribute('src');
        heading.innerHTML = newHead;
        img.setAttribute('src', newSrc);
        newHead = oldHead;
        newSrc = oldSrc;
    }
}

/** Register Class with FrenchDipJS */
FrenchDip.register(DemoJS, 'DemoJS');

Examples with ES2015

Bruce Wayne

Changes once

<div class="demo--es62015"
    data-frenchdip="DemoES2015"
    data-heading="Batman"
    data-new-src="batman.png">
    <img src="bruce-wayne.png"/>
    <p class="heading">Bruce Wayne</p>
</div>

Bruce Wayne

Changes once

<div class="demo--es62015"
    data-frenchdip="DemoES2015"
    data-heading="Batman"
    data-new-src="fireproof.png">
    <img src="bruce-wayne.png"/>
    <p class="heading">Bruce Wayne</p>
</div>
/** ES2015 Class */
class DemoES2015 {
    constructor() {
        this.heading = this.root.querySelectorAll('.heading')[0];
        this.img = this.root.querySelectorAll('img')[0];
        this.options = this.options;

        setTimeout(() => {
            this.swapAssets();
        }, 1000);
    }

    swapAssets() {
        this.heading.innerHTML = this.options.heading;
        this.img.setAttribute('src', this.options.newSrc);
    }
}

/** Register Class with FrenchDipJS */
FrenchDip.register(DemoES2015, 'DemoES2015');

Examples with jQuery

Bruce Wayne

For a dark knight, click here!

<div class="demo--jquery"
    data-frenchdip="DemoJQ"
    data-new-src="demo/images/batman.png">
    <img src="bruce-wayne.png"/>
    <p class="heading">Bruce Wayne</p>
</div>
/** JQuery */

var DemoJQ = DemoJQ;

$.extend(DemoJQ.prototype, {
    heading: 'Batman via $.onClick'
});

/** Register Class with FrenchDipJS */
FrenchDip.register(DemoJQ, 'DemoJQ'); // Register DemoJQ Class with FrenchDip

function DemoJQ() {
    this.$root = $(this.root);
    this.$heading = $(this.$root.find('.heading').get(0));
    this.$img = $(this.$root.find('img').get(0));

    this.$root.on('click', $.proxy(swapAssets, this));
}

function swapAssets() {
    this.$heading.html(this.heading);
    this.$img.attr('src', this.options.newSrc);
    this.$root.off();
}