add example
This commit is contained in:
parent
461a237880
commit
685e412a11
3 changed files with 314 additions and 0 deletions
3
examples/widget_design_patterns/css/example.css
Normal file
3
examples/widget_design_patterns/css/example.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
OxMyBox.focused {
|
||||
box-shadow: inset 0 0 1px black;
|
||||
}
|
13
examples/widget_design_patterns/index.html
Normal file
13
examples/widget_design_patterns/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Widget Design Patterns</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<link rel="shortcut icon" type="image/png" href="../../source/Ox.UI/themes/classic/png/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" href="css/example.css"/>
|
||||
<script type="text/javascript" src="../../dev/Ox.js"></script>
|
||||
<script type="text/javascript" src="js/example.js"></script>
|
||||
<script>window.addEventListener('message', function(e) { eval(e.data); });</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
298
examples/widget_design_patterns/js/example.js
Normal file
298
examples/widget_design_patterns/js/example.js
Normal file
|
@ -0,0 +1,298 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
Load the UI module.
|
||||
*/
|
||||
Ox.load('UI', function() {
|
||||
|
||||
/*
|
||||
Create our own namespace.
|
||||
*/
|
||||
Ox.My = {};
|
||||
|
||||
/*
|
||||
First, lets build the most basic Box widget. A widget is a "constructor"
|
||||
function that takes two (optional) arguments, `options` and `self`, and
|
||||
returns a widget object. It's not a constructor in JavaScript terms though:
|
||||
It doesn't have to be called with `new`, and doesn't return an instance of
|
||||
anything. It just enhances another widget object and returns it.
|
||||
*/
|
||||
Ox.My.Box = function(options, self) {
|
||||
|
||||
/*
|
||||
This is how every widget "constructor" begins. `self` is the widget's
|
||||
shared private object. It is private since it can only be accessed
|
||||
inside the widget, but shared because it can be passed to a widget upon
|
||||
its creation.
|
||||
*/
|
||||
self = self || {};
|
||||
/*
|
||||
`that` is the widget itself, its public object, or, in JavaScript terms,
|
||||
its `this`. Every widget "inherits" from another widget, by simple
|
||||
assignment. All public properties of the "super" widget, i.e. all
|
||||
properties of its `that`, will be present on our own `that`. In this
|
||||
case, we use Ox.Element, the "root" widget at the end of the inheritance
|
||||
chain, and pass an empty options object. But we always pass our own
|
||||
`self`, which means that any property that Ox.Element (or any other
|
||||
widget in the inheritance chain) adds to self will be present on our own
|
||||
`self`. Then we call the public `defaults` and `options` methods.
|
||||
`defaults` assigns the defaults object to `self.defaults` and copies it
|
||||
to `self.options`, then `options` extends `self.options` with the
|
||||
options object.
|
||||
*/
|
||||
var that = Ox.Element({}, self)
|
||||
.defaults({
|
||||
color: [128, 128, 128],
|
||||
size: 128
|
||||
})
|
||||
.options(options || {});
|
||||
|
||||
/*
|
||||
Ox.Element, and every widget that inherits from it, has a private
|
||||
`self.setOption` method that is invoked whenever, by way of calling the
|
||||
public `that.options` method, a property of `self.options` is modified
|
||||
or added. If we don't want to react to such changes, we can leave
|
||||
`self.setOption` untouched. In this case though, we want to update color
|
||||
and size, so we just overwrite `self.setOption`.
|
||||
*/
|
||||
self.setOption = function(key, value) {
|
||||
if (key == 'color') {
|
||||
setColor();
|
||||
} else if (key == 'size') {
|
||||
setSize();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
The following part of the "constructor" function can be thought of as
|
||||
the "initializer", and contains everything needed to set up the
|
||||
"instance". In this case, we just define a minimum and maximum size and
|
||||
then set the widget's color and size. We could have used `var minSize`
|
||||
and `var maxSize` here, but by using `self` for private variables that
|
||||
we want to be accessible across all the widget's methods, we can be sure
|
||||
that inside such methods, any local `var` is actually local to the
|
||||
method. We could have set color and size directly, too, but as we also
|
||||
need to set them in `self.setOption`, we create methods for both cases.
|
||||
*/
|
||||
self.minSize = 128;
|
||||
self.maxSize = 384;
|
||||
|
||||
setColor();
|
||||
setSize();
|
||||
|
||||
/*
|
||||
Now we declare the widget's private methods. These are simple function
|
||||
declarations, hoisted to the top of the "constructor".
|
||||
*/
|
||||
function setColor() {
|
||||
/*
|
||||
To interact with the DOM, Ox.Element (and any widget derived from
|
||||
it) wraps jQuery. If you type `Ox.Element()` in the console, you
|
||||
will get something like `[<div class="OxElement"></div>]`, and the
|
||||
widget's prototype has all the methods of a `$('<div>')`, with
|
||||
proper chaining. If you have `var $d = $('<div>'), $e =
|
||||
Ox.Element();`, then `$d.appendTo($e)` returns `$d`, and
|
||||
`$e.append($d)` returns `$e`.
|
||||
*/
|
||||
that.css({
|
||||
backgroundColor: 'rgb(' + self.options.color.join(', ') + ')',
|
||||
});
|
||||
}
|
||||
|
||||
function setSize() {
|
||||
/*
|
||||
Before setting the size, we make sure the value is between minSize
|
||||
and maxSize.
|
||||
*/
|
||||
self.options.size = Ox.limit(
|
||||
self.options.size, self.minSize, self.maxSize
|
||||
);
|
||||
that.css({
|
||||
height: self.options.size + 'px',
|
||||
width: self.options.size + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Next, we define the widgets public methods, as properties of `that`.
|
||||
(Note that unlike private methods, they are not hoisted.)
|
||||
*/
|
||||
that.showOptions = function() {
|
||||
/*
|
||||
As there isn't much to do yet, this method just displays the
|
||||
widget's options.
|
||||
*/
|
||||
that.html(JSON.stringify(self.options).replace(/([,:])/g, '$1 '));
|
||||
/*
|
||||
Public methods should return `that`, for chaining.
|
||||
*/
|
||||
return that;
|
||||
};
|
||||
|
||||
/*
|
||||
At the very end of the "constructor", we always return `that`. And
|
||||
that's it.
|
||||
*/
|
||||
return that;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
`Ox.My.Box({size: 256}).appendTo(Ox.$body).showOptions()`
|
||||
*/
|
||||
|
||||
window.myBox = Ox.My.Box().appendTo(Ox.$body);
|
||||
return;
|
||||
|
||||
Ox.My.Box = function(options, self) {
|
||||
|
||||
self = self || {};
|
||||
var that = Ox.Element('<div>', self)
|
||||
.defaults({
|
||||
color: [128, 128, 128],
|
||||
size: 128
|
||||
})
|
||||
.options(options || {})
|
||||
.addClass('OxMyBox OxMonospace')
|
||||
.css({
|
||||
color: 'white',
|
||||
padding: '16px',
|
||||
textShadow: '1px 1px 1px black'
|
||||
})
|
||||
.bindEvent({
|
||||
anyclick: focus,
|
||||
key_0: reset,
|
||||
key_equal: function() {
|
||||
Ox.print('+', self.options.size)
|
||||
setSize(self.options.size + 16, true);
|
||||
},
|
||||
key_minus: function() {
|
||||
setSize(self.options.size - 16, true);
|
||||
}
|
||||
});
|
||||
|
||||
self.initialSize = self.options.size;
|
||||
self.minSize = 128;
|
||||
self.maxSize = 384;
|
||||
|
||||
setColor();
|
||||
setSize(self.options.size);
|
||||
showOptions();
|
||||
|
||||
function focus(e) {
|
||||
Ox.print(e.target);
|
||||
if (e.target == that.$element[0]) {
|
||||
that.gainFocus();
|
||||
}
|
||||
}
|
||||
|
||||
function setColor() {
|
||||
that.css({
|
||||
backgroundColor: 'rgb(' + self.options.color.join(', ') + ')',
|
||||
});
|
||||
}
|
||||
|
||||
function setSize(size, animate) {
|
||||
var css;
|
||||
self.options.size = Ox.limit(size, self.minSize, self.maxSize);
|
||||
css = {
|
||||
height: self.options.size + 'px',
|
||||
width: self.options.size + 'px',
|
||||
};
|
||||
Ox.print('SET SIZE', size, animate, self.minSize, self.maxSize, css)
|
||||
if (animate) {
|
||||
that.stop().animate(css, 100, showOptions);
|
||||
} else {
|
||||
that.css(css);
|
||||
}
|
||||
}
|
||||
|
||||
function showOptions() {
|
||||
try {
|
||||
that.html(JSON.stringify(self.options).replace(/([,:])/g, '$1 '));
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
self.options = self.initialOptions;
|
||||
showOptions();
|
||||
}
|
||||
|
||||
self.setOption = function(key, value) {
|
||||
if (key == 'color') {
|
||||
setColor();
|
||||
} else if (key == 'size') {
|
||||
setSize(value);
|
||||
}
|
||||
showOptions();
|
||||
};
|
||||
|
||||
return that;
|
||||
|
||||
};
|
||||
|
||||
Ox.My.RoundedBox = function(options, self) {
|
||||
|
||||
self = self || {};
|
||||
var that = Ox.My.Box({}, self);
|
||||
that.defaults(Ox.extend(that.defaults(), {
|
||||
radius: 16
|
||||
}))
|
||||
.options(options || {});
|
||||
|
||||
setRadius();
|
||||
|
||||
function setRadius() {
|
||||
that.css({
|
||||
MozBorderRadius: self.options.radius + 'px',
|
||||
OBorderRadius: self.options.radius + 'px',
|
||||
WebkitBorderRadius: self.options.radius + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
self.setSuperOption = self.setOption;
|
||||
|
||||
self.setOption = function(key, value) {
|
||||
if (key == 'radius') {
|
||||
setRadius();
|
||||
} else {
|
||||
self.setSuperOption(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return that;
|
||||
|
||||
};
|
||||
|
||||
Ox.My.MetaBox = function(options, self) {
|
||||
|
||||
self = self || {};
|
||||
Ox.print('MB', options)
|
||||
var that = Ox.My.Box({}, self);
|
||||
that.defaults(Ox.extend(that.defaults(), {
|
||||
boxes: []
|
||||
}))
|
||||
.options(options || {});
|
||||
|
||||
self.options.boxes.forEach(function(box) {
|
||||
that.append(box);
|
||||
});
|
||||
|
||||
return that;
|
||||
|
||||
};
|
||||
|
||||
Ox.My.MetaBox({
|
||||
boxes: [
|
||||
Ox.My.Box({
|
||||
color: [64, 128, 255]
|
||||
}),
|
||||
Ox.My.RoundedBox({
|
||||
color: [255, 128, 64]
|
||||
})
|
||||
],
|
||||
size: 384
|
||||
})
|
||||
.appendTo(Ox.$body);
|
||||
|
||||
});
|
Loading…
Reference in a new issue