Control behavior based on device classifications
Without media queries:
Device telemetry stack to pass information to server
PHP objects in the core to access this information:
ClassificationScreenClassification used by handlers
Screen to determine mobile or desktop
|
Basic |
|
|
|
Standard |
|
|
|
Full |
|
|
A file per classification:
.src.css versions are sources for minification
Source files must be minified for each build
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
Assembled based on classifications like CSS handler
Complicated by URL parameters
basic_libs, standard_libs, full_libsbasic, standard, fullLibraries in /root/js/core are always loaded
Other libraries included on request from /root/js
JS objectIncludes are fetched through curl and minified
Need a way to determine device capabilities
Media queries aren't sufficient
Why not use metadata?
Instead, use Javascript to detect capabilities
How does browser-side code get to server?
What about devices without Javascript?
Capability detection
mwf.capability to determine capabilitiesmwf.classificationDeliver data to server
Performance hit on first-load
Federation requires pass-through, not refresh
Infinite loop issues
mwf.capability abstracts Modernizr and othersmwf.browser for browser sizemwf.userAgent for UA informationmwf.screen for device sizemwf.classification for classifying devicesmwf.override for override handlingSubset of data exposed in PHP
PHP objects abstract the cookies set
ClassificationScreenUser_Agent *Browser *User_Agent and Browser not advisable
Classification can be overridden by URI of any page
?override=[CLASSIFICATION]?override=noMobile redirection script
assets/redirect/js.php?m=[URL]?override_redirect=1?override_redirect=0Programmatic 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_Decorator::menu()Site_Decorator::content()Site_Decorator::button()Site_Decorator::header()Site_Decorator::footer()Site_Decorator::form()Site_Decorator::input()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 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');
}
Programmatic definition of HTML
Pattern of reuse
Extend as needed
Everyone wants rich interactivity, but...
How about a CSS-based solution?
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>
<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>
triggert-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
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');
}
}
}
mwf.standard.interactivity.expandable = {
'handler': {
// ...
}
};
mwf.standard.interactivity.registerHandler(
'expandable', // effect class name
'click', // trigger event
mwf.standard.interactivity.expandable.handler // effect handler
);
mwf.standard.interactivity.yourPlugin = {
'handler': {
'init':function(){ /* ... */ },
'exec':function(){ /* ... */ },
'initContainerBefore':function(){ /* ... */ },
'execContainerBefore':function(){ /* ... */ },
'initContainerAfter':function(){ /* ... */ },
'execContainerAfter':function(){ /* ... */ }
}
}
MWF is community source
GitHub is the starting point for MWF collaboration
For a campus,
Core developers fork from MWF or campus repository
Construct specifications for review on the GitHub wiki
File merge requests or issues for code review
Core Dev meetings on an as-needed basis