View on GitHub

One Bang - Smart Attributes

One Bang turns html attributes starting with an exclamation point into an easy way to write code shorthand.

Download this project as a .zip file Download this project as a tar.gz file

OneBang

NPM version Build Status

OneBang (aka 1!) turns html attributes starting with ! into an easy way to write code shorthand.

Star OneBang

Table of Contents

Installation

OneBang is available on NPM for browser and webpack consumption. (Recommended)

$ npm i --save onebang

CDNs are also available. (Not Recommended)

<!-- Latest Version -->
<script src="https://unpkg.com/onebang/dist/onebang.min.js"></script>
<!-- Specific Version (e.g. 1.0.2) -->
<script src="https://unpkg.com/onebang@1.0.2/dist/onebang.min.js"></script>

Example

Before

<div !id:example>
    <div !id:test !c:testclass !s:color:red>
        <i !i:fa:code></i> Test
    </div>
    <a !#:test>Scroll</a>
</div>

After

<div id="example">
    <div id="test" class="testclass" style="color:red;">
        <i class="fa fa-code"></i> Test
    </div>
    <a href="#test">Scroll</a>
</div>

Usage

<script src="onebang.js"></script> <!--Automatically adds window.onebang-->
var settings = {};
onebang(/* optional settings */ settings); //This starts processing.

Processing happens automatically when the document’s body is updated for most browsers.

Settings Object

{
    developerMode: false, /* Enable developer mode (turn off for production) */
    debugMode: false, /* Enable debug mode */
    userBang: '!', /* Attribute prefix */
    userBangRegex: /^\!.*$/, /* Regex for identifying if an attribute should be processed */
    userConnector: ':', /* Connector for variables */
    userConnectorRegex: /\:/g, /* Regex for all connectors in a string */
    functions: {}, /* Function specific options */
    removeBangPrefixes: [] /* Remove built-in bang prefixes (only necessary if there is a compatibility issue) */
}

Built-in Bang Prefixes

For convenience, some prefix options are built into the system that can be used interchangibly with the !.

<div !style:color:red></div> <!-- Single bang mark -->
<div B_style:color:red></div> <!-- Letter B and underscore (Compliant with stricter syntax) -->
<div b_style:color:red></div>
<div __style:color:red></div> <!-- Double underscore -->
<div ::style:color:red></div> <!-- Double colon -->
<div 1style:color:red></div> <!-- Single number 1 -->
<!--All result in: <div style="color: red;"></div>-->
<!--Learn more about the syntax below-->

To remove some of these from OneBang, add an exception to the settings object.

{
    // ...
    removeBangPrefixes: ['__','::','!'] //OneBang will not interpret these prefixes
}

1! Functions

Basics

<div !class:one:two></div> <!-- !(name of function):(variable):(another variable) -->

An unlimited number of variables can be added on for functions that accept them.

Class

Names: ‘class’, ‘c’

Accepts: Unlimited classes

<div !class:one:two:three></div> <!-- <div class="one two three"></div> -->
<div !c:one:two:three></div> <!-- <div class="one two three"></div> -->

Style

Names: ‘style’, ‘s’

Accepts: One css attribute and one css value

<div !style:color:red !style:font-size:14px></div> <!-- <div style="color:red;font-size:14px;"></div> -->
<div !s:width:20%></div> <!-- <div style="width:20%;"></div> -->

Href Hash

Names: ‘hash’, ‘#’

Accepts: No or one hash value

<div !hash:test></div> <!-- <div href="#test"></div> -->
<div !#></div> <!-- <div href="#"></div> -->

ID

Names: ‘id’

Accepts: One id value

<div !id:cool></div> <!-- <div id="cool"></div> -->

Icon

Names: ‘icon’, ‘i’

Accepts: One icon library and one icon ending (for extra FontAwesome options see below)

<div !i:fa:code></div> <!-- FontAwesome <div class="fa fa-code"></div> -->
<div !icon:fa:code:3></div> <!-- FontAwesome <div class="fa fa-code fa-3x"></div> -->
<div !i:fa:refresh:5:s></div> <!-- FontAwesome <div class="fa fa-code fa-5x fa-spin"></div> -->
<div !i:ion:ios-eye></div> <!-- Ionic Icons <div class="ion icon ion-ios-eye"></div> -->
<div !i:gly:person></div> <!-- Glyphicon (Twitter Bootstrap) <div class="glyphicon glyphicon-person"></div> -->
<div !i:oi:person></div> <!-- Open Iconic <div class="oi oi-person"></div> -->

Exclaim

Names: ‘exclaim’, ‘!’

Accepts: Unlimited number of exclaim classes

//settings
{
    ...
    functions: {
        exclaim: {
            default: 'defaultclass', // 'default' is the default class
            o: 'otherclass'
        }
    }
}
<div !!></div> <!-- <div class="defaultclass"></div> -->
<div !!:o></div> <!-- <div class="otherclass"></div> -->
<div !!::o></div> <!-- <div class="defaultclass otherclass"></div> -->
<div !!:o:></div> <!-- <div class="defaultclass otherclass"></div> -->

Hide

Names: ‘hide’

Accepts: None

<div !hide></div> <!-- <div style="display:none;"></div> -->

Additional OneBangs

These are the basic, most important OneBangs, but there are more included. Review the additional OneBang documentation for extras.

Plugins

Plugins allow developers to adapt OneBang to their own needs.

What is a plugin?

A plugin is a function that is executed when a specified OneBang namespace is used. Here is a 1! for the sake of example:

!class:example:onebang

The namespace class comes after the bang and before the connector. This would run the function for class which comes with OneBang.

function associatedfunction (/*variables*/) {
    //classes are added here
}

How do OneBang functions work?

All important variables are passed to the plugin’s function when it is run.

function plugin (input /*Array*/, options /*Object*/, version /*String*/, error /*Function*/, log /*Function*/ ) {
    this /*Object*/;
    //...
}
  1. input is an array of all bang variables (e.g. !class:one:two => [“one”,”two”])
  2. options is the options object of the function (see Settings Object, for an example see 1! Exclaim)
  3. version is the OneBang version, for compatibility
  4. error is a function for logging errors that takes a string description
  5. log is a function for logging information that takes a string description
    • this is DOM node of the element with the 1!

Adding Plugins

onebang.addplugin

This is a function that adds one plugin.

var pluginfunction = function (input, opts, v, err, log) {
    log('Running plugin');
    if (typeof input[0] ==='string'&&input[0]) {
        this.setAttribute('onclick','alert("'+input[0]+'");');
    } else {
        err('There are no variables');
    }
};
onebang.addplugin('example', pluginfunction);
<div !example:Hello!></div> <!-- <div onclick="alert(\"Hello!\")"></div> -->

onebang.addplugins

This is a function that adds many plugins at once.

var plugins = {
    red: function () {
        this.style.color = 'red';
    },
    large: function () {
        this.style['font-size'] = '30px';
    }
};
onebang.addplugins(plugins);
<div !red !large></div> <!-- <div style="color: red; font-size: 30px;"></div> -->

Aliasing

Adding aliases is simple. Just use onebang.addplugin or onebang.addplugins and replace the function with a string value of the real function.

// ex is an alias of example
onebang.addplugin('ex','example');

In the function options in the settings object, use the original option name and not the alias.

{
    // ...
    functions: {
        // This is will work for both ex and example
        example: {
            test: 'works'
        },
        // Since ex is an alias, this will not work
        ex: {
            test: 'fails'
        }
    }
}

Angular

Integration with Angular.js is simple and automatic.

<script src="angular.js"></script>
<script src="onebang.js"></script>
<script src="mycode.js"></script>
//mycode.js

var app = angular.module('test',['oneBang']);
app.run(['$oneBang', function ($oneBang) {
    $oneBang({/* options */})); //has all of the same variables as window.onebang
}]);
//... bootstrap app

To ensure that older browsers can use OneBang with automatic DOM updates, a singular “!” attribute can be added to the parent element(s) of the areas that should be searched for 1!s. This is only necessary if you are using templates (HTML that is not in the body on page load), and it can be use in place of intervals.

<!--Example-->
<script id="template.html" type="text/ng-template">
    <div ! !s:color:red><div !s:color:blue></div></div>
    <!--<div style="color: red;"><div style="color: blue;"></div></div>-->
</script>

Webpack

Webpack can be used to easily include code from NPM and other sources.

An example of how to use webpack is available under the test/webpack directory.

var init = require('onebang');
init(/* settings */);
//window.onebang must be used for everything else

Intervals

OneBang makes use of MutationObserver which is supported by the modern version of all modern browsers with the sole exception of Opera Mini (which doesn’t support many other Javascript features).

Can I Use mutationobserver?

However, intervals are available for use to ensure that websites using templates can support older browsers.

onebang.interval

onebang.interval(500); //starts an interval executing every 500 milliseconds
onebang.interval(false); //stops the interval

Manual Interpretation

DOM nodes can be manually interpreted by passing them through the onebang.interpret function. If you plan on using OneBang manually or with direct DOM manipulation, it is recommended that you use the ‘B_’ prefix rather than ‘!’, which is not valid XML.

onebang.interpret

This function runs OneBang manually on any DOM node.

var example = document.createElement('div');
example.setAttribute('b_style:color:red','');
onebang.interpret(example);
// example -> <div style="color: red;"></div>

Testing

OneBang undergoes a lot of testing to ensure functionality.

To view all tests go here and open the browser’s console.

Build Status

Syntax checks are also available here.

License

MIT © Russell Steadman