Skip to content
/ frontal Public

Control your javascript interactions from the server

Notifications You must be signed in to change notification settings

stol/frontal

Repository files navigation

frontal.js

Control your javascript interactions from the server.

Your frontend application logic is handled server side.

Frontal VS Traditionnal way comparison

Traditional way : ajax controller is frontend (example with jquery)

<!--
  -- REPEAT CODE BELOW FOR EVERY AJAX ACTION OF THE SITE… SIGH !
  -->
<a href="#" class="some-link">Display a list bellow</a>
<script>
$(".link").on("click", function(e){
    var $link = $(this);
    
    // No default action
    e.preventDefault(); 
    
    // Is the link already loading ?
    if( $(this).is(".loading") ){
		alert("Ajax request is already launched !")
		return;
	}
	// Add loading state
	$link.addClass("loading").text("Loading…");
    $.ajax({
        url: "/some-url.php",
    }).done(function(response) {
    	// Response error ? Revert to initial state
    	if (response.error){
    		alert("An error occured while loading list");
			$link.removeClass("loading").text("Display a list below");
    		return;
    	}
    	// Else, build HTML with data retrieved
    	var ul = '<ul>';    
    	for(var i=0; i<response.length; i++){
    		ul+= '<li>List item :'+response[i]+'</li>';
    	}
    	ul+= '</ul>';
    	
    	// Insert it after the link
    	$link.after("<ul>");
    
    	// remove the loading link
        $link.replaceWith("<span>List loaded below :</span>");
    });
});
</script>

Frontal way (with jQuery PHP adapter)

<a href="/some-url.php" class="some-link" data-f-ajaxify="1">Display a list bellow</a>

And pseudo code, server side

function someControllerAction()
{
    // Main content of the page
    $renderedHtml = render('/some-view.tpl');

    // If ajax, add content after the link, and remove the link 
    if ($request->isAjax(){
        // Call to a php wrapper, generating json instructions
        Frontal::getInstance()
            ->query(".some-link")
            ->after($renderedHtml)
            ->remove()
        ->send(); // => Does exit
    }
    
    // Otherwise, render the page normally
    $layout->set('content', $renderedHtml);
    $layout->render();
}

Voilà !

The server, when receiving a call, checks either it's an ajax call or a normal call.

If it's an ajax call, the server sends a json string, containing the instructions for frontal.

So the logic stays on the server. No need to edit any JS file. All the templating is done server side.

Installation

via bower :

$ bower install frontal

via git :

$ git clone https://github.com/Stol/frontal

Inspiration

frontal.js was inspired by facebook "primer", detailed in a frontend talk in 2010.

Recently, 37signals made a blog post of Server-generated JavaScript Responses similar to frontal.js

I used frontal.js for several years in various projects. It did remove many javascript code, unified templates, and is declarative, as it's commonly approved thoses days.

How it works

Setup

jQuery
<script src="frontal.jquery.js"></script>
<script>frontal.listen();</script>
NATIVE
import { frontal } from 'frontal';

# OR

const frontal = require('frontal');

frontal.listen();

Callbacks

After success XHR, you will receive response looking like this :

{
  "success": true,
  "actions": [
    {
      "selector": ".selector",
      "method": "html",
      "args": [
        "<h1>Awesome title</h1>"
      ]
    },
    {
      "selector": null,
      "method": "doSomething",
      "args": []
    }
  ]
}

Each method property in actions item will be call as function:

jQuery

In this mode, each custom jQuery function are handled, like html, after, prepend, etc ... You can also declare custom callbacks, like this :

$.fn.doSomething = function() {
    alert('Best function ever !');
}:
NATIVE

You must declare a global object FrontalCallbacks, who contains yours callbacks:

const FrontalCallbacks = {

    html : function(str) {
        this && (this.innerHTML = str);
    },

    doSomething: function() {
        alert('Best function ever !');
    }

};

Click

When clicking on any element, frontal is triggered IF data-f-ajaxify is present.

If the element clicked is a link, it sends an ajax request to the url specified in href attribute, or to the url specified in the data-f-href attribute (if present).

If the element clicked is a [type=submit] button/input inside a form with data-f-ajaxify, the button is cloned as an hidden field, the click event canceled so the submit event can happen.

Submit

When submiting a form, if it has the class data-f-ajaxify, the form is sent via an ajax request

Hover

When clicking en element, if it's a submit input/button,

Attributes API (namespaced with "data-f-xxx)

AttributeValueDescription
data-f-ajaxify1|0Triggers frontal for the tag
data-f-hrefurlForces the url for the ajax request
data-f-hover1|0Triggers the ajax call on hover
data-f-loadingspinner|selectorspinner: adds a spinner to the page
selector: adds class js-loading to the element(s) matching the css selector
data-f-uniq1|0Frontal will only run once
data-f-confirmstringDisplay a confirm alertbox before sending the request
data-f-stop1|0Stops Triggers frontal for the tag
data-f-toggle1|0Can't remember :p
data-f-methodpost|getForces the request method
data-f-register[url][url] will be ajaxified once frontal.listen() is called

Examples

Sending a form :

  • ajax via frontal, if enter is pressed, or "Send ajax" is clicked
  • non-ajax if "Send normal" is clicked
<form action="/action.php" method="post" data-f-ajaxify="1">
    <input type="text" name="name" placeholder="Type your name"/>
    <!-- Will trigger frontal -->
    <button type="submit">Send ajax</button>
    <!--Will send normally, because of data-f-stop="1" -->
    <button type="submit" data-f-stop="1">Send normal</button>
</form>

Sending a form with an alert

<form action="/action.php" method="post" data-f-ajaxify="1" data-f-confirm="Are you sure ?">
    <button type="submit">Delete</button>
</form>

Hovering, only once, with force url

<a href="/user/42" data-f-ajaxify="1" data-f-hover="1" data-f-uniq="1" data-f-href="/user/42/card">User 42 (hover for more info)</a>

Full examples

Clone this repository, then navigate to /frontal/web/

ROADMAP

  • Create a native frontend core
  • Create a jQuery adapter (front & back)
  • Improve doc
  • Make tests

Changelog

  • 1.0.2: handleEvent() > js-injected > fix node used to build fake input
  • 1.0.1: XHR response > fix data returned.
  • 1.0.0: add native version
  • 0.6.4: contentchange event now send element triggered
  • 0.6.3: ajaxify() > return deferred
  • 0.6 : added data-f-register

frontal.js is licensed under the MIT license.

About

Control your javascript interactions from the server

Resources

Stars

Watchers

Forks

Packages

No packages published