npm package: @overneath42/framewerk
Description: A framework for managing scripting on top of server-rendered pages.
Author: Justin Toon
Latest version: 1.0.0-alpha.8

# Framewerk

**A framework for managing scripting on top of server-rendered pages. (a.k.a. yet another JavaScript framework 😉)**

## What is Framewerk?

Many existing JavaScript frameworks are targeted toward JS-rendered single-page apps. However, there are many, _many_ developers working on apps which are primarily server-rendered, yet have large amounts of scripting to enhance the user experience within those apps. Conventional wisdom is to isolate JavaScript to its own files to maintain separation of concerns — yet how do you then effectively integrate that scripting into your views? Or do you just give up and shove it into _ad hoc_ `<script>` tags within your view files?

Framewerk is an attempt to create a consistent interface for cleanly attaching complex scripting to view files.  It was initially inspired by [AngularJS](https://angularjs.org/). (Yes, the old, bad version.) It borrows a couple of ideas from AngularJS but has happily diverged in a different direction. It does not directly rely on [jQuery](https://jquery.com/), but can certainly coexist with it.

## But what does it DO?

The core functionality of Framewerk operates in two sections.

### Controllers

A `Controller` contains selector string references, logic-heavy methods and view-based DOM operations. The `Controller` is then activated by attaching a `data-controller` attribute to the container element upon which the `Controller` should operate.

### Plugins

The `Plugin` is a way to wrap a third-party plugin within a consistent, repeatable structure, allowing for safe, dynamic activation of plugins on an as-needed basis. This is designed to sidestep the following all-too-typical scenarios:

- manually calling a plugin initialization within a view-level `<script>` tag
- activating the plugin on every page regardless of whether or not it's actually needed

## Usage

### Controllers

An individual `Controller` is created by passing three values to a new instance:

- `name`: A unique slug name, which is also the value used for `data-controller`
- `targets`: An object of unique keywords, with each storing a `NodeList` of elements. This object is generated by the `getTargets` class method of `Controller`. Provide an object should be given an object with the keywords desired in the final object, and a selector string for each value.Ï
- `events`: An object where the keys are internal reference names for events, and the values are functions which will attach event listeners to the DOM. If a `Controller` is initialized on a particular page, each function in this object will be called once after loading has completed.

The preferred way to do this is by creating a new function to set values for each of the above, and then return the new `Controller` when the function is called. This allows you to use the values stored within `targets` to target your event listeners.

```javascript
import { Controller } from 'framewerk';

export default function myController() {
  // this string will be used to match a `data-controller` attribute
  const name = 'my-controller';

  // this creates a list of DOM lookups and caches it for later use
  const targets = Controller.getTargets({
    main: '[data-target-main]',
    secondary: '[data-target-secondary]'
  });

  // each function in this object will be called once
  const events = {
    mainTargetClick: () => {
      targets.main.addEventListener('click', () => {
        // do something when any element within `targets.main` is clicked.
      });
    }
  }

  // at the bottom, return a new Controller with the three values above
  return new Controller({ name, targets, events });
}

```

All controllers should live in a separate folder (typically called `/controllers`, but this doesn't really matter), and then imported as a single object in your main entry, along with the core `fw` function.

```javascript
import { fw } from 'framewerk';

// this should be shaped like an object of modules
import controllers from './controllers';

// pass `controllers` into the `fw` function, then call `initialize` to start it.
fw(controllers).initialize();
```

## Important Note

This projects was created for my own personal use; therefore the API is tailored to my personal needs and highly opinionated as a result.