oxjs/index.js

650 lines
26 KiB
JavaScript
Raw Normal View History

2012-05-29 22:28:29 +00:00
'use strict';
2012-04-06 23:42:54 +00:00
Ox.load(function() {
var app = {
$ui: {},
animate: function() {
var home = app.url.get().page == '';
2012-04-08 12:48:07 +00:00
app.state.animating = true;
2012-04-06 23:42:54 +00:00
if (home) {
app.$ui.logo.attr({
src: app.getSRC('logo')
});
app.$ui.screen.show();
app.$ui.label.show();
app.$ui.menu.options({value: ''}).show();
} else {
app.$ui.menu.options({value: app.user.page});
2012-04-06 23:42:54 +00:00
}
2012-04-08 12:48:07 +00:00
app.$ui.panel.find('.OxButtonGroup').css({opacity: 0});
2012-04-06 23:42:54 +00:00
[
'screen', 'logo', 'label', 'menu', 'switch'
].forEach(function(element) {
app.$ui[element].stop().animate(
app.getCSS(element),
1000,
element == 'screen' ? function() {
if (!home) {
app.$ui.logo.attr({
src: app.getSRC('logo')
});
app.$ui.panel.find('.OxButtonGroup').css({opacity: 1});
app.$ui.screen.hide();
2012-04-07 14:42:57 +00:00
app.$ui.label.hide();
2012-04-06 23:42:54 +00:00
app.$ui.menu.hide().options({value: ''});
}
2012-04-08 12:48:07 +00:00
app.state.animating = false;
2012-04-06 23:42:54 +00:00
} : void 0
);
});
},
2012-04-07 14:42:57 +00:00
data: {
2012-04-08 18:18:25 +00:00
html: {},
2012-04-08 12:48:07 +00:00
pages: [
2012-04-07 14:42:57 +00:00
{id: 'about', title: 'About'},
{id: 'readme', title: 'Readme'},
{id: 'examples', title: 'Examples'},
{id: 'doc', title: 'Documentation'},
{id: 'downloads', title: 'Downloads'},
{id: 'development', title: 'Development'}
],
user: {
item: {doc: '', examples: '', readme: ''},
page: '',
previousPage: 'about'
}
2012-04-07 14:42:57 +00:00
},
db: Ox.localStorage('OxJS'),
2012-04-06 23:42:54 +00:00
getCSS: function(element) {
var css = {},
home = app.url.get().page == '',
2012-04-06 23:42:54 +00:00
center = Math.floor(window.innerWidth / 2),
middle = Math.floor(window.innerHeight / 2);
if (element == 'label') {
css = home ? {
top: middle + 16 + 'px',
left: center - 128 + 'px',
2012-04-08 18:18:25 +00:00
width: '242px',
height: '16px',
fontSize: '12px',
2012-04-19 17:35:27 +00:00
opacity: 1,
overflow: 'visible'
2012-04-06 23:42:54 +00:00
} : {
2012-04-08 18:18:25 +00:00
top: '35px',
2012-04-06 23:42:54 +00:00
left: '4px',
2012-04-08 18:18:25 +00:00
width: '40px',
2012-04-08 12:48:07 +00:00
height: '4px',
2012-04-06 23:42:54 +00:00
fontSize: '1px',
opacity: 0
}
} else if (element == 'loading') {
2012-04-08 18:18:25 +00:00
css.top = middle + 52 + 'px'
2012-04-06 23:42:54 +00:00
} else if (element == 'logo') {
2012-04-08 12:48:07 +00:00
css = home || !app.state.loaded ? {
2012-04-06 23:42:54 +00:00
left: center - 128 + 'px',
top: middle - 128 + 'px',
width: '256px',
2012-04-09 08:36:25 +00:00
height: '128px',
borderRadius: '32px'
2012-04-06 23:42:54 +00:00
} : {
2012-04-09 08:36:25 +00:00
top: '6px',
left: '6px',
2012-04-08 18:18:25 +00:00
width: '48px',
2012-04-09 08:36:25 +00:00
height: '24px',
borderRadius: '6px'
2012-04-06 23:42:54 +00:00
};
} else if (element == 'menu') {
css = home ? {
2012-04-08 18:18:25 +00:00
top: middle + 56 + 'px',
2012-04-06 23:42:54 +00:00
left: Math.ceil(center - app.$ui.menu.width() / 2) + 'px'
} : {
2012-04-09 08:36:25 +00:00
top: '6px',
2012-04-06 23:42:54 +00:00
left: Math.ceil(center - app.$ui.menu.width() / 2) + 'px'
};
} else if (element == 'screen') {
css.opacity = home ? 1 : 0;
} else if (element == 'switch') {
css = home ? {
2012-04-08 18:18:25 +00:00
top: middle + 96 + 'px',
2012-04-06 23:42:54 +00:00
right: Math.floor(center - app.$ui.switch.width() / 2) + 'px'
} : {
2012-04-09 08:36:25 +00:00
top: '6px',
right: '6px'
2012-04-06 23:42:54 +00:00
};
} else if (element == 'warning') {
css = {
left: center - 128 + 'px',
top: middle + 16 + 'px',
};
2012-04-06 23:42:54 +00:00
}
return css;
},
getSRC: function(element) {
var src,
home = app.url.get().page == '',
theme = app.user.theme || 'classic';
2012-04-06 23:42:54 +00:00
if (element == 'icon') {
src = 'source/Ox.UI/themes/' + theme
+ '/png/icon16.png';
} else if (element == 'loading') {
src = 'source/Ox.UI/themes/' + theme
+ '/svg/symbolLoading.svg'
2012-04-06 23:42:54 +00:00
} else if (element == 'logo') {
2012-04-09 08:36:25 +00:00
src = 'source/Ox.UI/themes/' + theme
+ '/png/logo128.png'
2012-04-06 23:42:54 +00:00
}
return src;
},
2012-04-08 18:18:25 +00:00
html: {},
2012-04-06 23:42:54 +00:00
init: function() {
app.loadScreen(function() {
app.loadData(function() {
Ox.load({UI: {theme: app.theme}}, app.load);
});
});
},
load: function(browserSupported) {
2012-04-06 23:42:54 +00:00
var url = app.url.get();
app.user = Ox.extend(app.data.user, app.db())
app.user.page = url.page;
if (url.item && url.page in app.user.item) {
app.user.item[url.page] = url.item;
2012-04-06 23:42:54 +00:00
}
app.db(app.user);
2012-04-06 23:42:54 +00:00
app.$ui.panel = app.ui.panel()
.select(app.user.page)
2012-04-06 23:42:54 +00:00
.appendTo(Ox.$body);
2012-04-07 14:42:57 +00:00
// jqueryfy so that we can animate
2012-04-06 23:42:54 +00:00
['screen', 'logo', 'loading'].forEach(function(element) {
app.$ui[element] = $('.' + element);
});
app.$ui.loading.animate({opacity: 0}, 500, function() {
app.$ui.loading.remove();
});
if (!browserSupported) {
app.$ui.warning = app.ui.warning()
.css(app.getCSS('warning'))
.appendTo(Ox.$body);
app.$ui.logo
.css({cursor: 'pointer'})
.one({
click: function() {
app.$ui.warning.remove();
app.load(true);
}
});
} else if (!url.page) {
2012-04-06 23:42:54 +00:00
app.$ui.logo
.css({cursor: 'pointer'})
2012-05-28 14:06:22 +00:00
.on({
2012-04-08 12:48:07 +00:00
click: app.toggle
2012-04-06 23:42:54 +00:00
});
['label', 'menu', 'switch'].forEach(function(element) {
app.$ui[element] = app.ui[element]()
.css({opacity: 0})
.appendTo(Ox.$body);
app.$ui[element]
.css(app.getCSS(element))
.animate({opacity: 1}, 500);
});
} else {
['label', 'menu', 'switch'].forEach(function(element) {
app.$ui[element] = app.ui[element]().appendTo(Ox.$body);
2012-04-08 12:48:07 +00:00
app.$ui[element].css(app.getCSS(element)).hide();
2012-04-06 23:42:54 +00:00
});
app.$ui.screen.animate({opacity: 0}, 500, function() {
app.$ui.screen.hide();
});
app.$ui.logo.animate({opacity: 0}, 500, function() {
app.$ui.logo
.attr({src: app.getSRC('logo')})
.css(app.getCSS('logo'))
.animate({opacity: 1}, 500, function() {
app.$ui.logo
.css({cursor: 'pointer'})
2012-05-28 14:06:22 +00:00
.on({
2012-04-08 12:48:07 +00:00
click: app.toggle
2012-04-06 23:42:54 +00:00
});
});
2012-04-08 12:48:07 +00:00
app.$ui.switch.css({opacity: 0}).show().animate({
opacity: 1
}, 500);
2012-04-06 23:42:54 +00:00
});
}
2012-05-28 14:06:22 +00:00
Ox.$window.on({
2012-04-06 23:42:54 +00:00
hashchange: app.urlchange
});
2012-04-08 12:48:07 +00:00
app.state.loaded = true;
2012-04-06 23:42:54 +00:00
},
loadData: function(callback) {
2012-04-18 12:35:16 +00:00
Ox.getJSON('index.json?'+Ox.random(1000), function(data) {
2012-04-07 14:42:57 +00:00
app.data = Ox.extend(app.data, data);
2012-04-08 18:18:25 +00:00
app.data.pages.forEach(function(page) {
var id = page.id == 'doc' ? 'documentation' : page.id;
Ox.get('readme/html/_' + (id) + '.html', function(html) {
app.html[id] = html;
Ox.len(app.html) == app.data.pages.length && callback();
});
})
2012-04-06 23:42:54 +00:00
});
},
loadScreen: function(callback) {
app.setTheme(app.user.theme || 'classic');
2012-04-06 23:42:54 +00:00
app.$ui.screen = app.ui.screen();
app.$ui.loading = app.ui.loading();
app.$ui.logo = app.ui.logo()
.one({
2012-04-06 23:42:54 +00:00
load: function() {
Ox.$('body')
.append(app.$ui.screen)
.append(app.$ui.logo)
.append(app.$ui.loading);
2012-05-29 22:28:29 +00:00
app.rotate();
2012-04-06 23:42:54 +00:00
callback();
}
});
2012-05-28 14:06:22 +00:00
Ox.$(window).on({
2012-04-06 23:42:54 +00:00
resize: app.resize
});
},
2012-04-08 18:18:25 +00:00
patchButtonGroup: function($buttonGroup) {
$buttonGroup.find('.OxButton').css({
height: '22px',
2012-04-09 08:36:25 +00:00
paddingLeft: '8px',
paddingRight: '8px',
fontSize: '13px'
2012-04-08 18:18:25 +00:00
});
$buttonGroup.find('.OxButton:first-child').css({
//paddingLeft: '9px',
borderTopLeftRadius: '6px',
borderBottomLeftRadius: '6px'
});
$buttonGroup.find('.OxButton:last-child').css({
//paddingRight: '9px',
borderTopRightRadius: '6px',
borderBottomRightRadius: '6px'
});
},
2012-04-06 23:42:54 +00:00
re: {
code: [
new RegExp(
'<span class="OxIdentifier">Ox</span>'
2012-04-09 08:36:25 +00:00
+ '(<span class="OxOperator">\\.</span>'
2012-04-06 23:42:54 +00:00
+ '<span class="OxIdentifier">UI</span>)?'
2012-04-09 08:36:25 +00:00
+ '<span class="OxOperator">\\.</span>'
2012-06-12 12:32:49 +00:00
+ '<span class="Ox\\w+">([\\w\\$]+)<\\/span>',
2012-04-06 23:42:54 +00:00
'g'
),
function (str) {
return '<a href="#doc/' + Ox.stripTags(str)
+ '" class="doclink">' + str + '</a>';
}
],
comment: [
2012-06-12 12:32:49 +00:00
/\b(Ox\.[\w\$]+)/g,
2012-04-06 23:42:54 +00:00
'<a href="#doc/$1" class="OxMonospace doclink">$1</a>'
2012-04-07 14:42:57 +00:00
],
version: [
'{version}',
function() {
return (
/:\/\/oxjs.org\//.test(window.location.href)
? 'The latest version is'
: 'You\'re currently running version'
) + ' <code>' + Ox.VERSION + '.</code>'
2012-04-07 14:42:57 +00:00
}
2012-04-06 23:42:54 +00:00
]
},
resize: function() {
[
'logo', 'loading', 'label', 'menu', 'switch'
].forEach(function(element) {
app.$ui[element] && app.$ui[element].css(app.getCSS(element));
});
},
2012-05-29 22:28:29 +00:00
rotate: function() {
var css, deg = 0,
previousTime = +new Date(),
interval = setInterval(function() {
var currentTime = +new Date(),
delta = (currentTime - previousTime) / 1000,
loadingIcon = document.getElementById('loadingIcon');
if (loadingIcon) {
previousTime = currentTime;
deg = Math.round((deg + delta * 360) % 360 / 30) * 30;
css = 'rotate(' + deg + 'deg)';
loadingIcon.style.MozTransform = css;
loadingIcon.style.MSTransform = css;
loadingIcon.style.OTransform = css;
loadingIcon.style.WebkitTransform = css;
} else {
clearInterval(interval);
}
}, 83);
},
2012-04-06 23:42:54 +00:00
setTheme: function(theme) {
app.user.theme = theme;
app.db(app.user);
2012-04-06 23:42:54 +00:00
(Ox.$('#icon') || Ox.$('<link>').attr({
id: 'icon',
rel: 'shortcut icon',
type: 'image/png'
}).appendTo(Ox.$('head'))).attr({
href: app.getSRC('icon')
});
2012-04-07 14:42:57 +00:00
app.$ui.logo && app.$ui.logo
.attr({src: app.getSRC('logo')})
.css(app.getCSS('logo'));
2012-04-06 23:42:54 +00:00
Ox.Theme
? Ox.Theme(theme)
: Ox.$('body').addClass('OxTheme' + Ox.toTitleCase(theme)
);
},
2012-04-08 12:48:07 +00:00
state: {
animating: false,
loaded: false
},
toggle: function() {
!app.state.animating && app.url.set(
app.url.get().page ? {
page: '',
item: ''
} : {
page: app.user.previousPage,
item: app.user.previousPage in app.user.item
? app.user.item[app.user.previousPage] : ''
}
2012-04-08 12:48:07 +00:00
);
},
2012-04-06 23:42:54 +00:00
ui: {
doc: function() {
return Ox.DocPanel({
2012-04-09 08:36:25 +00:00
element: $('<div>')
2012-06-12 12:32:49 +00:00
.addClass('page')
2012-04-09 08:36:25 +00:00
.css({
margin: '32px',
width: window.innerWidth - 640 + 'px'
})
.html(app.html.documentation),
2012-06-12 12:32:49 +00:00
examples: app.data.examples,
examplesPath: 'examples/',
2012-04-09 08:36:25 +00:00
files: app.data.docItems ? void 0 : app.data.documentation,
2012-04-08 18:18:25 +00:00
getModule: function(item) {
var file = item.file.replace(/^dev\//, '');
return file.split('/')[0];
},
getSection: function(item) {
var file = item.file.replace(/^dev\//, '');
return item.section || file.split('/')[2].split('.')[0];
},
2012-04-09 08:36:25 +00:00
items: app.data.docItems || void 0,
2012-04-08 18:18:25 +00:00
path: 'dev/',
2012-06-12 12:32:49 +00:00
references: /\b(Ox\.[\w\$]+)\b/g,
replace: [app.re.code],
2012-06-12 11:18:42 +00:00
selected: app.user.item.doc,
showTests: true
2012-04-08 18:18:25 +00:00
})
.bindEvent({
select: function(data) {
app.user.item.doc = data.id;
app.db(app.user);
app.url.set();
2012-04-08 18:18:25 +00:00
}
2012-04-09 08:36:25 +00:00
})
.bindEventOnce({
load: function(data) {
app.data.docItems = data.items;
}
2012-04-08 18:18:25 +00:00
});
2012-04-06 23:42:54 +00:00
},
examples: function() {
return Ox.ExamplePanel({
2012-04-09 08:36:25 +00:00
element: $('<div>')
2012-06-12 12:32:49 +00:00
.addClass('page')
2012-04-09 08:36:25 +00:00
.css({
margin: '32px',
width: window.innerWidth - 640 + 'px'
})
.html(app.html.examples),
2012-04-06 23:42:54 +00:00
examples: app.data.examples,
path: 'examples/',
2012-06-12 12:32:49 +00:00
references: /\b(Ox\.[\w\$]+)\b/g,
2012-04-06 23:42:54 +00:00
replaceCode: [app.re.code],
replaceComment: [app.re.comment],
selected: app.user.item.examples
2012-04-06 23:42:54 +00:00
})
.bindEvent({
select: function(data) {
app.user.item.examples = data.id;
app.db(app.user);
app.url.set();
2012-04-06 23:42:54 +00:00
}
});
},
label: function() {
return Ox.Label({
textAlign: 'center',
title: 'A JavaScript Library for Web Applications',
width: 256
})
.addClass('label animate')
2012-04-08 18:18:25 +00:00
.css({
paddingTop: '4px',
paddingBottom: '4px',
borderRadius: '6px'
})
2012-05-28 14:06:22 +00:00
.on({
2012-04-08 12:48:07 +00:00
click: app.toggle
2012-04-06 23:42:54 +00:00
});
},
loading: function() {
return Ox.$('<img>')
.addClass('loading')
.attr({id: 'loadingIcon', src: app.getSRC('loading')})
2012-04-06 23:42:54 +00:00
.css(app.getCSS('loading'));
},
logo: function() {
return Ox.$('<img>')
.addClass('logo animate')
.attr({src: app.getSRC('logo')})
.css(app.getCSS('logo'));
},
menu: function() {
2012-04-08 18:18:25 +00:00
var $menu = Ox.ButtonGroup({
2012-04-08 12:48:07 +00:00
buttons: app.data.pages,
2012-04-06 23:42:54 +00:00
min: 0,
selectable: true,
})
.addClass('menu animate')
.bindEvent({
change: function(data) {
if (data.value) {
app.url.set({page: data.value});
}
2012-04-06 23:42:54 +00:00
}
})
2012-04-08 18:18:25 +00:00
app.patchButtonGroup($menu);
return $menu;
2012-04-06 23:42:54 +00:00
},
2012-04-07 14:42:57 +00:00
page: function(page, replace) {
2012-04-06 23:42:54 +00:00
var $element = Ox.Container();
2012-04-08 18:18:25 +00:00
$('<div>')
2012-06-12 12:32:49 +00:00
.addClass('OxSelectable page')
2012-04-08 18:18:25 +00:00
.html(app.html[page].replace(app.re.version[0], app.re.version[1]))
.appendTo($element);
2012-04-06 23:42:54 +00:00
return $element;
},
panel: function() {
2012-04-08 18:18:25 +00:00
var $panel = Ox.TabPanel({
content: function(id) {
return app.$ui[id] = app.ui[id]
? app.ui[id]() : app.ui.page(id);
2012-04-08 18:18:25 +00:00
},
2012-04-09 08:36:25 +00:00
size: 36,
2012-04-08 18:18:25 +00:00
tabs: app.data.pages
})
.bindEvent({
change: function(data) {
if (app.state.loaded) {
app.user.page = data.selected;
app.db(app.user);
app.url.set();
}
2012-04-08 18:18:25 +00:00
}
}),
$buttonGroup = $panel.find('.OxButtonGroup').css({
2012-04-09 08:36:25 +00:00
top: '6px'
2012-04-08 18:18:25 +00:00
});
app.patchButtonGroup($buttonGroup);
return $panel;
2012-04-06 23:42:54 +00:00
},
readme: function() {
2012-04-07 14:42:57 +00:00
var $list = Ox.Container().css({overflowY: 'scroll'}),
$text = Ox.Container().addClass('OxSerif OxSelectable text'),
2012-04-08 12:48:07 +00:00
self = {},
that = Ox.SplitPanel({
2012-04-07 14:42:57 +00:00
elements: [
{element: $list, size: 256},
{element: $text}
],
orientation: 'horizontal'
2012-04-08 12:48:07 +00:00
}, self)
2012-04-07 14:42:57 +00:00
.addClass('readme');
2012-04-19 18:39:28 +00:00
Ox.sortBy(app.data.readme, '-date').forEach(function(item, i) {
2012-04-07 14:42:57 +00:00
var $item = $('<div>')
2012-04-08 18:18:25 +00:00
.addClass('item')
.attr({id: 'readme_' + item.id})
.css({
width: 224 - Ox.UI.SCROLLBAR_SIZE + 'px'
})
2012-05-28 14:06:22 +00:00
.on({
2012-04-08 18:18:25 +00:00
click: function(e) {
if (!$(this).is('.selected')) {
selectItem(item.id);
} else if (e.metaKey) {
selectItem();
}
2012-04-07 14:42:57 +00:00
}
2012-04-08 18:18:25 +00:00
})
.appendTo($list);
2012-04-07 14:42:57 +00:00
$('<div>')
.addClass('OxSerif title')
.html(item.title)
.appendTo($item);
$('<div>')
.addClass('OxSerif OxLight date')
.html(Ox.formatDate(item.date, '%B %e, %Y', true))
.appendTo($item);
});
selectItem(app.user.item.readme);
2012-04-08 12:48:07 +00:00
function selectItem(id) {
2012-04-07 14:42:57 +00:00
$('.readme .item.selected').removeClass('selected');
2012-04-08 12:48:07 +00:00
id && $('#readme_' + id).addClass('selected');
Ox.get('readme/html/' + (id || '_readme') + '.html', function(html) {
2012-04-09 08:36:25 +00:00
$text.empty()
.append(
id ? html
: $('<div>')
2012-06-12 12:32:49 +00:00
.addClass('page')
2012-04-09 08:36:25 +00:00
.css({
margin: '16px',
width: window.innerWidth - 640 + 'px'
})
.html(html)
)
.find('.code').each(function() {
var $this = $(this);
$this.replaceWith(
Ox.SyntaxHighlighter({
source: $this.text()
})
.attr({id: $this.attr('id')})
);
});
2012-04-08 12:48:07 +00:00
});
app.user.item.readme = id;
app.db(app.user);
app.url.set();
2012-04-08 12:48:07 +00:00
}
self.setOption = function(key, value) {
if (key == 'selected') {
selectItem(value);
2012-04-07 14:42:57 +00:00
}
}
2012-04-08 12:48:07 +00:00
return that;
2012-04-06 23:42:54 +00:00
},
screen: function() {
return Ox.$('<div>').addClass('screen animate');
},
switch: function() {
2012-04-08 18:18:25 +00:00
var $switch = Ox.ButtonGroup({
2012-04-06 23:42:54 +00:00
buttons: [
{id: 'classic', title: 'Light'},
{id: 'modern', title: 'Dark'}
],
selectable: true,
value: app.user.theme
2012-04-06 23:42:54 +00:00
})
.addClass('switch animate')
.bindEvent({
change: function(data) {
app.setTheme(data.value);
}
});
2012-04-08 18:18:25 +00:00
app.patchButtonGroup($switch);
return $switch;
},
warning: function() {
return $('<div>')
.addClass('warning')
.html(
'Aw, snap! This website requires an up-to-date, HTML5-compliant web browser. '
2012-05-25 22:30:25 +00:00
+ 'It should work fine in current versions of '
+ '<a href="http://google.com/chrome/">Chrome</a>,'
+ '<a href"http://mozilla.org/firefox/">Firefox</a> '
+ 'and <a href="http://apple.com/safari/">Safari</a>, '
+ 'or Internet Explorer with <a href="http://google.com/chromeframe/">Chrome Frame</a> installed. '
+ 'To proceed at your own risk, click on the logo above.'
);
2012-04-06 23:42:54 +00:00
}
},
url: {
get: function() {
2012-05-30 16:28:39 +00:00
var split = window.location.hash.slice(1).split('/');
2012-04-08 12:48:07 +00:00
return {page: split[0], item: split[1] || ''};
2012-04-06 23:42:54 +00:00
},
set: function(data) {
data = data || app.user;
window.location.hash = data.page + (
data.item && data.item[data.page] ? '/' + data.item[data.page] : ''
);
2012-04-06 23:42:54 +00:00
return app;
}
},
urlchange: function() {
var url = app.url.get();
app.user.previousPage = app.user.page;
app.user.page = url.page;
if (url.item && url.page in app.user.item) {
app.user.item[url.page] = url.item;
2012-04-08 12:48:07 +00:00
}
app.db(app.user);
if (app.user.page != app.user.previousPage) {
app.$ui.panel.select(app.user.page);
2012-04-09 08:36:25 +00:00
}
if (url.item) {
app.$ui[url.page].options({selected: url.item});
}
if (!app.user.page || !app.user.previousPage) {
app.animate();
2012-04-06 23:42:54 +00:00
}
},
user: {}
2012-04-06 23:42:54 +00:00
};
app.init();
window.oxjs = app;
});