Introduction to

Core Coding

in MWF 1.3

Overview

  1. CSS & JS Handlers
  2. Device Telemetry Stack
  3. PHP Decorators
  4. Trigger/Target Engine
  5. Collaborative Development

Why CSS & JS Handlers?

Control behavior based on device classifications

  • Media queries
  • Server-side assembly

Without media queries:

  1. Detect device capabilities with Javascript
  2. Pass this information to the server
  3. Assemble the proper behavioral definitions

How do we determine capabilities?

Device telemetry stack to pass information to server

PHP objects in the core to access this information:

  • Classification
  • Screen

Classification used by handlers

Screen to determine mobile or desktop

Classifications

Basic

  • XHTML MP 1.0
  • WCSS

Standard

  • HTML 4.01
  • CSS 2.1
  • Javascript 1.5
  • Cookies
  • DOM Writes
  • DOM Events

Full

  • HTML 5
  • CSS 3
  • AJAX
  • CSS 3 Border Radius
  • CSS 3 Box Shadow
  • CSS 3 Gradient

Assembling CSS

A file per classification:

  • basic.css
  • standard.css
  • full.css

.src.css versions are sources for minification

Source files must be minified for each build

Custom CSS files

Core CSS is loaded from /root/css/default

Custom CSS goes other subdirectories within /root/css

Loaded in FIFO order from /config/css.ini

Good for institutional-specific overrides

Assembling Javascript

Assembled based on classifications like CSS handler

Complicated by URL parameters

  • basic_libs, standard_libs, full_libs
  • basic, standard, full

Handling Libraries & Includes

Libraries in /root/js/core are always loaded

Other libraries included on request from /root/js

  • Organized by classification
  • Defined by a key that references a file
  • Dependencies handled through a map in JS object

Includes are fetched through curl and minified

What is DTS?

Need a way to determine device capabilities

Media queries aren't sufficient

Why not use metadata?

  • Keeping up with new devices
  • Non-default browser settings
  • Openness of metadata APIs

Instead, use Javascript to detect capabilities

Some Problems

How does browser-side code get to server?

  • Writing cookies
  • First-load problem
  • Cross-domain

What about devices without Javascript?

  • Server-side intelligence

DTS Mechanics

Capability detection

  • Use mwf.capability to determine capabilities
  • Classify device through mwf.classification

Deliver data to server

  • Does server already know?
  • Update cookies if not
  • Refresh page to reload handlers

Caveats

Performance hit on first-load

  • HTTP request cost on 3 files

Federation requires pass-through, not refresh

  • HTTP request cost on 5 files

Infinite loop issues

  • Some cases diagnosed explicitly
  • Expensive catch-all protection

What's in the Stack?

  • mwf.capability abstracts Modernizr and others
  • mwf.browser for browser size
  • mwf.userAgent for UA information
  • mwf.screen for device size
  • mwf.classification for classifying devices
  • mwf.override for override handling

Telemetry within PHP

Subset of data exposed in PHP

PHP objects abstract the cookies set

  • Classification
  • Screen
  • User_Agent *
  • Browser *

User_Agent and Browser not advisable

Overrides

Classification can be overridden by URI of any page

  • Set by ?override=[CLASSIFICATION]
  • Unset by ?override=no

Mobile redirection script

  • assets/redirect/js.php?m=[URL]
  • Prevent by ?override_redirect=1
  • Unset by ?override_redirect=0

PHP Decorators

Programmatic representation of MWF elements

$decorator = Site_Decorator::menu();
$decorator->set_title('Menu Title');
$decorator->add_item('Item 1', '#1');
$decorator->add_item('Item 2', '#2');
echo $decorator->render();
<div class="menu">
    <h1>Menu Title</h1>
    <ul>
        <li><a href="#1">Item 1</a></li>
        <li><a href="#1">Item 2</a></li>
    </ul>
</div>

Site Decorators

  • Site_Decorator::menu()
  • Site_Decorator::content()
  • Site_Decorator::button()
  • Site_Decorator::header()
  • Site_Decorator::footer()
  • Site_Decorator::form()
  • Site_Decorator::input()

Site Decorator Factory

Site_Decorator is actually a factory

class Site_Decorator extends Decorator {
    public static function button(){
        $args = func_get_args();
        return self::factory(__FUNCTION__, $args);
    }

    // ...

    public static function factory($name, $args = array())
    {
        $name = strtolower($name);
        require_once(dirname(__FILE__).'/site/'.$name.'.class.php');
        $class = $name.'_Site_Decorator';
        $refl = new ReflectionClass($class);
        return $refl->hasMethod('__construct') 
                    ? $refl->newInstanceArgs($args) : new $class();
    }
}

Site Decorator Implementations

Site decorators extend underlying HTML decorators

class Content_Site_Decorator extends Tag_HTML_Decorator
{
    public function __construct($inner = '', $params = array())
    {
        parent::__construct('div', $inner, $params);
        $this->add_class('content');
    }
    // ...

They include additional entity-specific methods

    public function &set_padded($val = true)
    {
        return $val ? $this->remove_class('not-padded') 
                    : $this->add_class('not-padded');
    }

Why Decorators?

Programmatic definition of HTML

Pattern of reuse

Extend as needed

Trigger/Target Engine

Everyone wants rich interactivity, but...

  • Javascript isn't friendly to content editors
  • Hard to program for compatibility

How about a CSS-based solution?

Controlling Effects through CSS

Define a target element

<div class="expandable example">
    <h2>Expandable Target</h2>
    <p>This div will expand when Trigger is pressed</p>
</div>

Define a trigger element

<a href="#" class="trigger t-example">Trigger</a>

Include libary in JS handler

<script src="js.php?standard_libs=interactivity/expandable"></script>

How Does This Work?

<div class="expandable example">
    <h2>Expandable Target</h2>
    <p>This div will expand when Trigger is pressed</p>
</div>
<a href="#" class="trigger t-example">Trigger</a>
  1. Find elements with class trigger
  2. Extract target reference(s) from prefix t-
  3. Initialize the trigger for target(s)
  4. Effect on target controlled by other classes

Plugin Architecture

The class expandable defines transition from interactivity/expandable

Can represent any trigger/target interaction

Defined by a handler with event hooks

Handler is registered with mwf.standard.interactivity

Example

Expandable/Collapsible

mwf.standard.interactivity.expandable = {
    'handler': {
        'init':function(){
            if(!$(this).hasClass('expanded'))
                $(this).addClass('collapsed');
        },
        'exec':function(){
            if($(this).hasClass('collapsed'))
                $(this).removeClass('collapsed').addClass('expanded');
            else
                $(this).removeClass('expanded').addClass('collapsed');
        }
    }
}

Example

Registering a Handler

mwf.standard.interactivity.expandable = { 
    'handler': { 
        // ...
    }
};

mwf.standard.interactivity.registerHandler(
    'expandable',                                  // effect class name
    'click',                                       // trigger event
    mwf.standard.interactivity.expandable.handler  // effect handler
);

Example

Handler Hooks

mwf.standard.interactivity.yourPlugin = {
    'handler': {
        'init':function(){ /* ... */ },
        'exec':function(){ /* ... */ },
        'initContainerBefore':function(){ /* ... */ },
        'execContainerBefore':function(){ /* ... */ },
        'initContainerAfter':function(){ /* ... */ },
        'execContainerAfter':function(){ /* ... */ }
    }
}

NOTE: Development topic not yet available in production

Collaborative Development

MWF is community source

  • Six campuses have directly contributed code
  • Many have been involved in discussions and issues

GitHub is the starting point for MWF collaboration

Git Workflow

For a campus,

  • Fork from the MWF repository
  • Override styles and other simple things
  • Pull from MWF repository to upgrade

Core developers fork from MWF or campus repository

Git Workflow

Contribution Process

  1. Developer submits a specification to Core Dev Group
  2. Core Dev & Mobile Collab Group review and approve
  3. Developer creates a feature branch from release tag
  4. Developer creates a merge request (optional)
  5. Core Dev Group performs code review and testing
  6. MWF Core Team merges code when complete

Contribution Process

Getting Involved

Construct specifications for review on the GitHub wiki

File merge requests or issues for code review

Core Dev meetings on an as-needed basis

THANK YOU

Any Questions?