Surf JS - An Insanely Small JavaScript UI Library With Reactive Element Templates and JQuery Alternative
Tags: react, javascript, webdev, tutorial
Published: 2022-07-15 17:44:29

 
    
[<img alt="Surf JS"  src="https://surf.monster/imgs/logo.png" />](https://surf.monster/imgs/logo.png)



## What is it?

### It's an insanely small ~13kb minified (that's ~2.6kb smaller than cash @ https://github.com/fabiospampinato/cash ), plugin extendable JavaScript library for building user interfaces (UI).  

**Surf JS** is a few different things all wrapped up in one small package.

But it's also a super small JQuery clone/replacement library that has **reactive element templates** (read on to learn what these are).


**Don't let the JQuery clone part fool you!** -  **Surf JS** lets you build your component based UI using a familiar syntax and NO JSX! Using **Surf JS** as you would JQuery (in a non component based way) is entirely **optional**!

 **Surf JS** doesn't implement all JQuery methods but the basics are pretty similar and you can always configure **Surf JS** to do anything you want via plugins.


A good way to think about **Surf JS** is that it's like JQuery if JQuery had a way to use components **AND** if JQuery had reactive element templates...with a much smaller footprint than JQuery. 

If you would rather not think about it, you could just use **Surf JS**  as a replacement for JQuery!


### Where To Get It?
**Get it from Github:** https://github.com/bretgeek/surf/   

**Visit:** https://surf.monster for more documentation, updates and working examples.

### Features

* 
**Super Small!** - currently at around  ~13KB minified (smaller if gzipped).


* **Reactive Element Templates** - Reactive element templates are strings in your HTML that look like **{% raw %} {{msg}} {% endraw %}** and once initialized can become ANYTHING you desire when you desire. When your data changes you can set the template to your new data, new HTML or even new components!


* **Lightweight JQuery Clone** - Can be used as a general purpose JQuery like library.

* **Easy Familiar Syntax** - familiar chainable syntax with built-in DOM manipulation methods.

* **Build with Components** - Optional component based syntax allowing you to build your UI with re-usable components without using JSX as well as solving CSS bleed issues from web components. 


* **Extendable** - Highly configurable (you can change anything you want about the base functionality with a run time config) and it's extendable with plugins.


* **Versatile** - It's intended to give you power and not lock you down into any one way of doing things. You can probably find ways to use it that the author has not even thought of yet. Use it in ways that you and your team define!



### Getting Started
Basic usage for manually adding and using **Surf JS** to a web page.


### Add **Surf JS** to your page before your closing body tag:

```html


<script src='https://yoururl.com/surf.min.js'></script>



```

### First make sure it works
So we can do more interesting things later but first let's use **Surf JS** similar to how we would use JQuery to make sure our setup is working.

### In an html file:



```js

// Somewhere in your HTML

<div id='app'> I am an App </div>


```


### In a script tag after surf.min.js:

```js

// Create kickoff function that will run once the document is ready.

function kickoff(){

// There are many options to "grab" but this minimal use returns the first element of #app by default

$('#app').css('color: red;');

}


// Run your function when the document is ready...

$(document).ready(kickoff);


```

**You should now see "I am an App" in red.**



### Reactive Element Templates
**Surf JS** has a really powerful feature called **"Reactive Element Templates"** that allows you to manipulate your HTML with changing data defined by {% raw %} {{templates}} {% endraw %}. Since Reactive Templates resolve to functions (once they are activated) there is no DOM querying...changes are live! 
The main takeaway here is that...when your data changes, templates can be used to display your data as text, HTML or even components! 

### Lets start with a basic example to see how Reactive Templates work
In your html file add: 

```js

// Somewhere in your HTML

<div id='msgapp'> This is a {{msg}} </div>


```


In your script file somewhere in your kickoff function add: 

```js

// Somewhere in your kickoff function of your JS script

// Use set to change msg and CSS to color #msgapp green so we can see it;

$('#msgapp').set({msg: ' my narly note!'}); // We can send in HTML, text or components here;
$('#msgapp').css('color: green;');


```


If you are lucky enough to catch a glimpse you should see the msg in the template change when the browser is done loading.
Keep in mind this is setting the templates via HTML in a textual based JQuery like way, but templates give you even more power when setting them to or from components!




### Components
Creating a re-usable component is as easy as writing a function (a named function or an arrow function and a name parameter) that returns an element then registering it by calling a special function **$().register(componentName)** to register it. Once registered it can be used over and over by it's name.

Let's give it a try:

First we will need a place to put our component in.
### In your HTML file:

```js

// Somewhere in your HTML

<div id='comp1'> COMPONENT  </div>



```



 Now lets make the component - a button that increments a counter when clicked.

Somewhere in your kickoff script file (or where it will be called by ready) define a function for your component:

```js


// A button component that counts when clicked

function buttonCounter(props={}){ // You can also pass in a props object 
let color = props.color || 'green';

   // The component with create a node each time it's used

   const node = $().createNode('button');


   // This node's CSS, attributes, reactive template and html

   $(node).html('Count is: {{cnt}} ').attr('data-count', 0).css('cursor: pointer;').css(`color: ${color};`); // color from props


   // initialize cnt template to 0

   $(node).set({cnt: '0'});

// Add a click event to the node
$(node).on('click', function(){
let cnt = parseFloat($(this).attr('data-count'))+1;
$(this).attr('data-count', cnt);
$(this).set({cnt: cnt});
});


 // A component must return an element
return node;
}



// Register the component
$().register(buttonCounter); 


```



To make sure our component works we will use **Surf JS's** "append" method to add it to the DOM... but keep in mind you can add components to other components with a special syntax which we will get to later.
```js


// create a reference to a component

const abutton = $().buttonCounter(); // pass in option props too


// Create a reference to the place we want to put our component

const comp1 = $('#comp1').first();


// Finally append the component to the element in DOM

$(comp1).append(abutton);  // OR without a reference: $(comp1).append($().buttonCounter());


```

**You should now see a clickable button with a counter that increments as you click.**


### Syntax to render components to other components
 The most useful thing about components is their re-use. In this section we will go over how to add a component to another component.
Here we will make a **containerBox** component and add our **buttonCounter** we made earlier to it. We will add buttonCounter twice to show different ways to do it.


Make a place to in the DOM to hold our containerbox component.
### In your HTML file add:

```js

// Somewhere in your HTML

<div id='comp2'> some random place holder text not required  </div>


```


 In your kickoff script file add the code below for the containerBox component:

```js

// A component for a container box

function containerBox(){

  // The kind of element this component will be...

  const node = $().createNode('div');
  
  // Some HTML with a reactive template for demonstration purposes.

  $(node).html('{{ button }} ')


  // Some CSS to add a border so we can see it.

  $(node).css('border: 2px solid blue; padding: 9px; width: 120px;'); 


  // There are two ways to add a component - use the Set method on templates or DOM insertion.
  // If using both ways in the same component the Set method on templates must come first.


  // First way: Set a template to another component

  $(node).set({ button: $().buttonCounter() });


  // Second way: Use DOM manipulation methods to add a component to this component

  $(node).prepend( $().buttonCounter() );

  return node; // compontents must return an element
}

// Don't forget to register it somewhere in your script file
$().register(containerBox);



```


###  Test it to see if adding components to another works.
Somewhere else in your kickoff script add:

```js


const abox = $().containerBox(); // create a new instance  

$('#comp2').append(abox); // add to somewhere in the DOM OR with variable instance do $('#comp2').append($().containerBox());



```




**You should now see three components - 1 containerBox component containing 2 buttonCounter components!**


We covered a lot of ground introducing the basics of **Surf JS** but the possibilities are endless!

I hope you have enjoyed this short tutorial on getting started with **Surf JS** and would love to read your comments and see what you will build.


**If you found this interesting please favorite here and star Surf JS project on Github** https://github.com/bretgeek/surf/