Initial shit i think.

This commit is contained in:
Linus Miller 2015-09-02 11:04:34 +02:00
commit e7e0ea4f2a
44 changed files with 1406 additions and 0 deletions

36
.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
# Bower dependency directory
bower_components
/dump
/public
/server/uploads

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "gulp"]
path = gulp
url = https://github.com/thecodebureau/gulp.git

1
gulp Submodule

@ -0,0 +1 @@
Subproject commit 57adc62ecbec966afa0f717e967287c820c09095

12
gulpconfig.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
browserify: {
entries: [
'app.js',
'admin/app.js'
],
outputs: [
'app.js',
'admin.js'
]
}
};

1
gulpfile.js Symbolic link
View File

@ -0,0 +1 @@
gulp/gulpfile.js

11
nodemon.json Normal file
View File

@ -0,0 +1,11 @@
{
"ext": "js,dust",
"ignore": [
"bower_components",
"gulp",
"node_modules",
"public",
"samples",
"src"
]
}

16
package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "change-this-fool",
"version": "0.0.0",
"description": "",
"main": "./server/server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "The Code Bureau <info@thecodebureau.com> (https://thecodebureau.com)",
"dependencies": {
"hats": "^0.2.0",
"epiphany": "0.6.1",
"ridge": "0.5.3",
"dustjs-linkedin": "^2.7.2"
}
}

5
server/config/details.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
title: 'Epiphany',
name: 'epiphany'
};

47
server/config/dir.js Normal file
View File

@ -0,0 +1,47 @@
// MODULES
// modules : NATIVE
var path = require('path');
var PWD = process.env.PWD;
// Server folders. All folder related to the Node server handling most things.
module.exports = {
// Any code that needs to a "middle landing spot" while built, place it anywhere here
build: {
root: path.join(PWD, 'build')
},
// public directories. Where all static/built/live content goes.
public: {
css: path.join(PWD, 'public', 'css'),
fonts: path.join(PWD, 'public', 'fonts'),
img: path.join(PWD, 'public', 'img'),
root: path.join(PWD, 'public'),
scripts: path.join(PWD, 'public', 'js')
},
root: PWD,
server: {
middleware: path.join(PWD, 'server', 'middleware'),
models: path.join(PWD, 'server', 'models'),
routes: path.join(PWD, 'server', 'routes'),
root: path.join(PWD, 'server'),
schemas: path.join(PWD, 'server', 'schema.org'),
templates: path.join(PWD, 'server', 'templates'),
uploads: path.join(PWD, 'server', 'uploads')
},
// Source directories. This is where you put all content that needs to be built before use.
src: {
fonts: path.join(PWD, 'src', 'fonts'),
raster: path.join(PWD, 'src', 'raster'),
root: path.join(PWD, 'src'),
sass: path.join(PWD, 'src', 'sass'),
static: path.join(PWD, 'src', 'static'),
scripts: path.join(PWD, 'src', 'js'),
svg: path.join(PWD, 'src', 'svg'),
}
};

12
server/config/domain.js Normal file
View File

@ -0,0 +1,12 @@
var _ = require('lodash');
module.exports = function(config) {
if(!config.port || !_.isNumber(config.port)) throw new Error('Port undefined or not a number');
return {
development: 'localhost:' + config.port,
testing: 'changeThisFool.testing.thecodebureau.com',
staging: 'changeThisFool.thecodebureau.com',
production: 'www.changeThisFool.se'
}[ENV];
};

View File

@ -0,0 +1,23 @@
module.exports = {
defaults: {
mystify: {
properties: [ 'message', 'name', 'status', 'statusText' ]
},
log: {
// if database = true there has to be a mongoose model name ErrorModel
ignore: [],
}
},
development: {
log: {
database: false,
console: true,
}
},
production: {
log: {
database: true,
console: false,
}
},
};

10
server/config/globals.js Normal file
View File

@ -0,0 +1,10 @@
var path = require('path');
module.exports = function(bind) {
bind = bind || global;
bind.ENV = process.env.NODE_ENV || 'development';
bind.PWD = process.env.PWD;
//bind.LOGIN_USER = 'username';
//bind.LOGIN_USER = 'email@domain.com';
};

10
server/config/mongo.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
defaults: {
uri: 'mongodb://localhost/changeThisFool'
//uri: 'mongodb://user:password@tcb01.thecodebureau.com/changeThisFool'
},
development: {
//uri: 'mongodb://user:password@tcb01.thecodebureau.com/changeThisFoolDev'
uri: 'mongodb://localhost/changeThisFoolDev'
}
};

8
server/config/port.js Normal file
View File

@ -0,0 +1,8 @@
var basePort = 10000;
module.exports = {
development: basePort,
testing: basePort + 1,
staging: basePort + 2,
production: basePort + 3
}[ENV];

14
server/config/session.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
defaults: {
secret: 'changeThisFool',
resave: true,
saveUninitialized: true
},
production: {
redis: {
port: 6379,
host: 'localhost'
}
}
};

13
server/modules.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = [
// hats > hats
//'hats/base',
//'hats/admin',
//'hats/errors',
//'hats/organization',
//'hats/news',
//'hats/gallery',
//'hats/employees',
// hats > project
//'./hats/events',
];

30
server/pages.js Normal file
View File

@ -0,0 +1,30 @@
module.exports = function(mw) {
return {
public: [
{
title: 'Start',
template: 'pages/index',
path: '/'
}, {
title: 'Spytext'
}, {
title: 'Playground'
}, {
title: 'CSS',
name: 'css'
}
],
//redirects: [
// [ '/coupon','/kupongen' ],
//],
//admin: [
// {
// title: 'Dashboard',
// path: '/',
// template: 'admin/pages/index'
// }
//]
};
};

9
server/server.js Normal file
View File

@ -0,0 +1,9 @@
var Epiphany = require('epiphany');
var server = new Epiphany({
modules: require('./modules'),
pages: require('./pages'),
start: false
});
server.start();

View File

@ -0,0 +1,9 @@
<div class="error page row">
<div class="col">
<h1>Oops!</h1>
<p>Ett problem har tyvärr uppstått.<p>
<h2>{error.status} : {error.statusText}</h2>
<p>{error.message}<p>
<pre>{error.stack}</pre>
</div>
</div>

View File

@ -0,0 +1,62 @@
<!doctype html>
<html>
<head>
<title>TCB IT &amp; Development AB</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.png" />
<link type="text/css" rel="stylesheet" href="/css/main.css" />
</head>
<body>
<header>
<div class="row">
<div class="col">
<div class="company">
<h1 class="logo"><span>TCB IT &amp; Development</span></h1>
</div>
{>"partials/navigation":navigation page=page /}
</div>
</div>
</header>
<main>
{?error}
{>"error"/}
{:else}
{?template}
{>"{template}"/}
{/template}
{/error}
</main>
<footer class="bottom">
<div class="row">
<div class="col m-6">Copyright TCB IT &amp; Development AB</div>
<div class="col m-6 text-right">Website by <a href="https://thecodebureau.com">TCB</a>.</div>
</div>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.13.1/jquery.validate.min.js"></script>
<!-- IE Fixes -->
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/selectivizr/1.0.2/selectivizr-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<!--[if lt IE 10]>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-placeholder/2.0.8/jquery.placeholder.min.js"></script>
<![endif]-->
<script src="/js/common.js"></script>
<script src="/js/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,23 @@
<div class="css page row">
<div class="col">
<h1>CSS playground</h1>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
</div>
</div>

View File

@ -0,0 +1,26 @@
<div class="css page row">
<div class="col">
<h1>D3 Testing Area</h1>
<div class="D3">
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,95 @@
<div class="page row">
<section data-title="Welcome" class="welcome">
<header class="col">
<h1>Welcome / Välkommen!</h1>
<h2><span>The Code Bureau:</span> Advanced Web Development &amp; Design</h2>
</header>
<div class="col m-6">
<p>The Code Bureau is a web development & design firm based in Lund,
Sweden. Unlike most other web designers/developers, all our employees
have a background in mathematics or computer science.</p>
<p class="emph">We make it our business to stay up to date on the latest
trends and technologies. The applications we create are always
state-of-the-art and built for the future. When you employ us, you wont need to update your
products for years.</p>
</div>
<div class="col m-6">
<p>We cater a range of different services to our customers;
always focusing on the development of code for the web. Our love for code
and the new possibilities of the web enable us to do almost anything. Just ask.</p>
<p class="emph">The Code Bureau is a fairly new venture, and as such we
are still building a portfolio of show cases. During this time we
are offering our services at greatly reduced prices.</p>
</div>
</section>
<section data-title="What We Do" class="what-we-do">
<header class="col">
<h1>What We Do</h1>
</header>
<div class="item col m-4">
<h2><span>Web Pages</span></h2>
<p>Obviously we create websites. Essentially everything we create are
web sites of varying complexity. However, we refer to web sites as our
entry level products that mainly focus on presentation of information without excessive functionality.</p>
</div>
<div class="item col m-4">
<h2><span>Web Apps</span></h2>
<p>Web apps are advanced web sites that emulate functionality usually
found in native apps or programs.</p>
<p>Web apps have, unlike native apps, the benefit of running on all
computers and devices. The users only need a browser to access its
functionality.</p>
</div>
<div class="item col m-4">
<h2><span>Web Games</span></h2>
<p>As the name suggests, web games are games made to run in a browser on any device.</p>
</div>
</section>
<section data-title="Why Choose Us" class="why-choose-us">
<header class="col">
<h1>Why Choose Us?</h1>
</header>
<div class="col">
<ol>
<li>
<h2>We know code</h2>
<p>Most web designers or developers are artistically creative individuals. However,
to create stable, reliable web sites and apps you need to know more than design. We
are a collection of individuals that both truly love and know code, computers and the web.</p>
</li>
<li>
<h2>SEO</h2>
<p>Search Engine Optimization is probably the most important
factor for a web sites success. It is also constantly changing, and your web sites
need to be updated constantly to stay ahead of the competition.</p>
<p>One of the most important factors for good SEO today is the speed
of your website. Using a framework like WordPress will doom you to a
slow web site with poor search engine performance. Our web sites
are many, many times faster than those built with WordPress or similar.</p>
</li>
<li>
<h2>Future Proof</h2>
<p>The internet and web browsers have become infinately more advanced the last few years. Web sites are quickly becoming
more like apps and the user experience can be greatly improved. Our love for code means we understand the trends, and can
make decisions that ensure our products will be up to date for years to come. No WordPress or PHP here.</p>
</li>
</ol>
</div>
</section>
<section data-title="Contact" class="contact">
<header class="col">
<h1>Contact</h1>
</header>
<div typeof="Organization" class="col">
<p property="telephone" class="phone">+46 (0) 708 922 122</p>
<p property="email" class="email"><a href="mailto:info@thecodebureau.com">info@thecodebureau.com</a></p>
<p class="address"><span property="legalName">TCB IT & Development AB</span><br />
Ideon Agora<br />
<span typeof="PostalAddress" property="address">
<span property="streetAddress">Scheelevägen 15</span><br />
<span property="postalCode">22363</span> <span property="addressLocality">Lund</span><br />
<span property="addressCountry">Sweden</span></p>
</span>
</div>
</div>

View File

@ -0,0 +1,20 @@
<div class="mod page row">
<div class="col">
<h1>MOD</h1>
<div class="mod">
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,9 @@
<div class="page row">
<div class="col" data-view="TreeWalker">
<h1>Playground</h1>
<div id="tree-walker" contentEditable=true><p>aaa<u><b>bbb</b><i>ccc</i>ddd<b>eee</b><strike>fff<strong>ggg</strong></strike></u>hhh<b id="start">456</b></p><p><br/></p><p><br/></p><p><br/></p><p>aaa</p></div>
<div id="walker" contentEditable=true><script>var a = 4</script><style>body { background: white !important; }</style><p>aaa<u><b>bbb</b><i>ccc</i>ddd<b>eee</b><strike>fff<strong>ggg</strong></strike></u>hhh<b id="start">456</b></p><p><br/></p><p><br/></p><p><br/></p><p>aaa</p></div>
</div>
</div>

View File

@ -0,0 +1,128 @@
<div class="spytext page row">
<div class="col">
<h1>Spytext</h1>
</div>
<div class="row">
<div class="col m-6">
<div data-view="SpytextField">
<p>AAA<b><u>BBB</u></b>CCC</p>
<p>DDD<br><br></p>
<p>EEE<b><u>FFF</u></b>GGG</p>
<p>HHH<b>III<u>KKK</u>LLL</b>MMM</p>
<ul>
<li>NNN</li>
<li><br></li>
<li>OOO</li>
</ul>
<p>PPP</p>
<ul>
<li>RRR</li>
<li>SSS</li>
<li>TTT</li>
</ul>
</div>
</div>
<div class="col m-6">
<div data-view="SpytextField">
<p>One lorem ipsum dolor sit amet, <b><u>consectetur adipiscing elit. Maecenas semper</u></b> turpis eros, sed rhoncus purus sodales sit amet.</p>
<p>Two quisque lacus est, B TWO this is some bold molestie et diam id, varius sagittis nisi. Donec placerat mi egestas, congue ligula non, lacinia tortor.<br><br></p>
<p>Three aecenas <b><u>B U THREE laskjdf</u></b> id sodales dui. Nulla ipsum justo, elementum in fermentum at, feugiat nec neque.</p>
<p>Four vestibulum <b>B tempor <u>U dolor vitae</u> risus</b> faucibus elementum. Aliquam leo odio, convallis non luctus eu, faucibus vel lorem.</p>
<ul>
<li>Top Menu Item 1</li>
<li>Top Menu Item 2</li>
<li>Top Menu Item 3</li>
<li>Top Menu Item 4</li>
<li>Top Menu Item 5</li>
</ul>
<p>Paragraph 1<br><br></p>
<p>Para<br>graph 2</p>
<p>Paragraph 3<br><div></div></p>
<p>Paragraph 4</p>
<p>Paragraph 5</p>
<p>Paragraph 6</p>
<ul>
<li>Middle Menu Item 1</li>
<li>Middle Menu Item 2</li>
<li>Middle Menu Item 3</li>
<li>Middle Menu Item 4</li>
<li>Middle Menu Item 5</li>
</ul>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<p>Paragraph 4</p>
<p>Paragraph 5</p>
<p>Paragraph 6</p>
<ul>
<li>Bottom Menu Item 1</li>
<li>Bottom Menu Item 2</li>
<li>Bottom Menu Item 3</li>
<li>Bottom Menu Item 4</li>
<li>Bottom Menu Item 5</li>
</ul>
</div>
</div>
<div class="col m-6">
<div data-view="SpytextField">
<p>One lorem ipsum dolor sit amet, <b><u>consectetur adipiscing elit. Maecenas semper</u></b> turpis eros, sed rhoncus purus sodales sit amet.</p>
<p>Two quisque lacus est, B TWO this is some bold molestie et diam id, varius sagittis nisi. Donec placerat mi egestas, congue ligula non, lacinia tortor.<br><br></p>
<p>Three aecenas <b><u>B U THREE laskjdf</u></b> id sodales dui. Nulla ipsum justo, elementum in fermentum at, feugiat nec neque.</p>
<p>Four vestibulum <b>B tempor <u>U dolor vitae</u> risus</b> faucibus elementum. Aliquam leo odio, convallis non luctus eu, faucibus vel lorem.</p>
<ul>
<li>test</li>
<li><br></li>
<li>test</li>
</ul>
<p>Test</p>
<ul>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>
</div>
</div>
<div class="col m-6">
<div data-view="SpytextField">
<h1>Hello</h1>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>Sublist
<ul>
<li>Sublist Item 1</li>
<li>Sublist Item 2</li>
<li>Sublist Item 3</li>
<li>Sublist
<ul>
<li>Sublist Item 1</li>
<li>Sublist Item 2</li>
<li>Sublist Item 3</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Test 1</p>
<p>Test 2</p>
<p>Test 3</p>
<p>Test 4</p>
<p>Test 5</p>
<p>Test 6</p>
<p>Test 7</p>
<ul>
<li>test</li>
<li><br></li>
<li>test</li>
</ul>
<p>Test</p>
<ul>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,332 @@
module.exports = function() {
events: {
'click button': 'command'
},
template: 'spytext-toolbar',
command: function() {
var command = $(e.currentTarget).attr('data-command');
}
};
var SpytextButton = function(config, spytext) {
this.spytext = spytext;
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
this.element = $('<button class="spytext-button" st-button-type="' + config.preset + '" tabindex="' + -1 + '">')[0];
for(var property in this.events)
$(this.element).on(property, this.events[property].bind(this));
this.disable();
};
SpytextButton.prototype = {
setActive: function() {
$(this.element).addClass('active');
},
unsetActive: function() {
$(this.element).removeClass('active');
},
enable: function() {
this.element.disabled = false;
},
disable: function() {
this.element.disabled = true;
this.unsetActive();
},
events: {
click: function(e) {
e.preventDefault();
this.spytext.execute(this.config.action, this.config.options);
}
},
presets: {
alignLeft: { title: 'Align Left', action: 'align', options: { alignment: 'left' }},
alignRight: { title: 'Align Right', action: 'align', options: { alignment: 'right' }},
alignCenter: { title: 'Align Center', action: 'align', options: { alignment: 'center' }},
alignJustify: { title: 'Align Justify', action: 'align', options: { alignment: 'justify' }},
bold: { title: 'Bold', action: 'format', options: { tag: 'B' }},
strikeThrough: { title: 'Strike Through', action: 'format', options: { tag: 'STRIKE' }},
underline: { title: 'Underline', action: 'format', options: { tag: 'U' }},
italic: { title: 'Italic', action: 'format', options: { tag: 'I' }},
removeFormat: { action: 'removeFormat' },
typeHeading1: { title: 'Heading 1', action: 'block', options: { tag: 'H1' }},
typeHeading2: { title: 'Heading 2', action: 'block', options: { tag: 'H2' }},
typeHeading3: { title: 'Heading 3', action: 'block', options: { tag: 'H3' }},
typeHeading4: { title: 'Heading 4', action: 'block', options: { tag: 'H4' }},
typeHeading5: { title: 'Heading 5', action: 'block', options: { tag: 'H5' }},
typeHeading6: { title: 'Heading 6', action: 'block', options: { tag: 'H6' }},
typeParagraph: { title: 'Paragraph', action: 'block', options: { tag: 'P' }},
orderedList: { title: 'Ordered List', action: 'list', options: { tag: 'OL' }},
unorderedList: { title: 'Unordered List', action: 'list', options: { tag: 'UL' }},
indent: { title: 'Indent', action: 'indent', options: { outdent: false }},
outdent: { title: 'Outdent', action: 'indent', options: { outdent: true }}
}
};
var SpytextDropdown = function(config, spytext) {
this.spytext = spytext;
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
this.items = [];
this.element = $('<ul class="spytext-dropdown">')[0];
var property;
this.config.items.forEach(function(item) {
var $el = $('<li><span>' + item.title + '</span></li>');
$(this.element).append($el);
for(property in this.events.item)
$el.on(property, this.events.item[property].bind(this));
this.items.push(item);
}.bind(this));
for(property in this.events.dropdown)
$(this.element).on(property, this.events.dropdown[property].bind(this));
this.index = 0;
this.length = $(this.element).children().length;
this.disable();
};
SpytextDropdown.prototype = {
setIndex: function(index) {
this.index = index;
var liHeight = this.element.children[0].offsetHeight;
var children = this.element.children;
for(var i = 0; i < children.length; i++) {
$(children[i]).css('top', '-' + (index * liHeight) + 'px');
if(i === index) $(children[i]).addClass('active');
else $(children[i]).removeClass('active');
}
},
setNoActive: function() {
this.index = 0;
var children = this.element.children;
for(var i = 0; i < children.length; i++) {
$(children[i]).css('top', '0');
$(children[i]).removeClass('active');
}
},
setActive: function(options) {
for(var i = 0; i < this.items.length; i++)
for(var prop in options)
if(options[prop] === this.items[i].options[prop])
return this.setIndex(i);
},
enable: function() {
$(this.element).removeClass('disabled');
},
disable: function() {
$(this.element).addClass('disabled').removeClass('expanded');
this.setNoActive();
},
events: {
dropdown: {
click: function(e) {
if(this.spytext.currentField) {
$(this.element).toggleClass('expanded');
}
}
},
item: {
click: function(e) {
if($(this.element).hasClass('expanded')) {
var index = $(this.element).children().index(e.currentTarget);
this.spytext.execute(this.config.action, this.items[index].options);
}
}
}
},
presets: {
type: {
action: 'block',
items: [
{ title: 'Heading 1', options: { tag: 'H1' }},
{ title: 'Heading 2', options: { tag: 'H2' }},
{ title: 'Heading 3', options: { tag: 'H3' }},
{ title: 'Heading 4', options: { tag: 'H4' }},
{ title: 'Heading 5', options: { tag: 'H5' }},
{ title: 'Heading 6', options: { tag: 'H6' }},
{ title: 'Paragraph', options: { tag: 'P' }}
]
}
}
};
var SpytextToolbar = function(config, spytext) {
this.dropdowns = [];
this.buttons = [];
this.spytext = spytext;
this.config = typeof config.preset === 'string' ? merge(this.presets[config.preset], config) : config;
this.element = $('<div class="spytext-toolbar">')[0];
for(var property in this.config.dropdowns)
this.addDropdown.call(this, this.config.dropdowns[property], property);
for(property in this.config.buttonGroups)
this.addButtonGroup.call(this, this.config.buttonGroups[property], property);
for(property in this.events)
$(this.element).on(property, this.events[property].bind(this));
};
SpytextToolbar.prototype = {
addButtonGroup: function(group) {
var $ul = $('<UL>').addClass('spytext-button-group ' + group.name);
group.buttons.forEach(function(buttonType) {
var $li = $('<LI>');
var button = this.addButton({ preset: buttonType }, this.spytext);
$ul.append($li);
$li.append(button.element);
}.bind(this));
$(this.element).append($ul);
},
addButton: function(config) {
var button = new SpytextButton(config, this.spytext);
this.buttons[config.preset] = button;
return button;
},
addDropdown: function(config) {
config = typeof config === 'string' ? { preset: config } : config;
var dropdown = new SpytextDropdown(config, this.spytext);
this.dropdowns[config.preset] = dropdown;
$(this.element).append(dropdown.element);
return dropdown;
},
enable: function() {
for(var i in this.buttons) {
var button = this.buttons[i];
//button.element.setAttribute('disabled');
button.enable();
}
for(var j in this.dropdowns) {
this.dropdowns[j].enable();
//button.element.setAttribute('disabled');
}
$(this.element).addClass('active');
},
disable: function() {
for(var i in this.buttons) {
this.buttons[i].disable();
}
for(var j in this.dropdowns) {
this.dropdowns[j].disable();
}
$(this.element).removeClass('active');
},
setActiveStyles: function() {
function setBlock(tag) {
switch(tag) {
case 'P':
case 'H1':
case 'H2':
case 'H3':
case 'H4':
case 'H5':
case 'H6':
if(that.dropdowns.type) {
that.dropdowns.type.setActive({ tag: tag });
}
break;
case 'UL':
that.buttons.unorderedList.setActive();
that.dropdowns.type.setNoActive();
break;
case 'OL':
that.buttons.orderedList.setActive();
that.dropdowns.type.setNoActive();
break;
}
}
var that = this;
var tags = [];
var blocks = [];
var rng;
var s = 0;
while(!rng) {
rng = this.spytext.currentField.selectron.range();
if(s++ > 10000) return;
}
if(!rng) return;
if(rng.collapsed) {
tags = ancestors(rng.startContainer, null, this.spytext.currentField.element);
// The last element should always be the block element, such as P or UL.
} else {
var el = rng.commonAncestorContainer;
tags = ancestors(el, null, this.spytext.element);
}
if(tags.length > 0) blocks.push(tags.pop());
for(var i in this.buttons) {
var button = this.buttons[i];
if(button.config.options && $(tags).is(button.config.options.tag).length > 0) {
button.setActive();
} else button.unsetActive();
}
var blockTag;
for(var j = 0; j < blocks.length; j++) {
if(blockTag && blockTag !== blocks[j].tagName) {
blockTag = null;
break;
} else {
blockTag = blocks[j].tagName || null;
}
}
if(blockTag) setBlock(blockTag);
},
presets: {
standard: {
dropdowns: [ 'type' ],
buttonGroups: [
//{ name: 'block', buttons: ['typeHeading1', 'typeHeading2', 'typeHeading3', 'typeHeading4', 'typeHeading5', 'typeHeading6', 'typeParagraph']},
{ name: 'format', buttons: ['bold', 'italic', 'underline', 'strikeThrough', 'removeFormat']},
{ name: 'align', buttons: ['alignLeft', 'alignCenter', 'alignRight', 'alignJustify']},
{ name: 'list', buttons: ['unorderedList', 'orderedList']},
{ name: 'indent', buttons: ['indent', 'outdent']}
]
},
format: {
buttonGroups: [
{ name: 'format', buttons: ['bold', 'underline', 'strikeThrough', 'removeFormat']},
]
}
},
events: {
mousedown: function(e) {
// this is needed to prevent toolbar from stealing focus
e.preventDefault();
}
}
};

View File

@ -0,0 +1,72 @@
<div class="spytext-toolbar">
<ul class="spytext-dropdown">
<li style="top: 0px;">
<button data-command="block" data-option="h1">Heading 1</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="h2">Heading 2</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="h3">Heading 3</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="h4">Heading 4</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="h5">Heading 5</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="h6">Heading 6</button>
</li>
<li style="top: 0px;">
<button data-command="block" data-option="p">Paragraph</button>
</li>
</ul>
<ul class="spytext-button-group format">
<li>
<button class="spytext-button bold" data-command="format" data-option="strong" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button italic" data-command="format" data-option="em" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button underline" data-command="format" data-option="u" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button strike-through" data-command="format" data-option="strike" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button remove-format" data-command="format" tabindex="-1"></button>
</li>
</ul>
<ul class="spytext-button-group align">
<li>
<button class="spytext-button align-left" data-command="align" data-option="left" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button align-center" data-command="align" data-option="center" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button align-right" data-command="align" data-option="right" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button align-justify" data-command="align" data-option="justify" tabindex="-1"></button>
</li>
</ul>
<ul class="spytext-button-group list">
<li>
<button class="spytext-button unordered-list" data-command="list" data-option="ul" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button ordered-list" data-command="list" data-option="ol" tabindex="-1"></button>
</li>
</ul>
<ul class="spytext-button-group indent">
<li>
<button class="spytext-button indent" data-command="indent" tabindex="-1"></button>
</li>
<li>
<button class="spytext-button outdent" data-command="outdent" tabindex="-1"></button>
</li>
</ul>
</div>

32
src/js/admin/app.js Normal file
View File

@ -0,0 +1,32 @@
var Ridge = require('ridge');
var app = new Ridge({
router: {
root: '/admin'
},
templateRoot: 'admin/',
models: require('../models'),
collections: require('../collections'),
views: require('./views'),
modules: [
// hats > native
//require('hats/admin'),
//require('hats/organization/admin'),
//require('hats/errors/admin'),
//require('hats/news/admin'),
//require('hats/gallery/admin'),
//require('hats/employees/admin'),
// hats > project
//require('../../../hats/events/admin'),
//require('../../../hats/sponsors/admin')
]
});
window.broadcast = _.extend({}, Backbone.Events);
$(function() {
app.navigation = new app.views.Navigation({ el: app.$('nav') });
Backbone.history.start({ silent: true, pushState: true });
});

View File

@ -0,0 +1,6 @@
module.exports = {
Page: require('ridge/views/page'),
Model: require('ridge/views/model'),
Collection: require('ridge/views/collection'),
Navigation: require('./navigation')
};

View File

@ -0,0 +1,22 @@
module.exports = {
initialize: function() {
this.listenTo(this.app.router, 'route', this.onRouteChange);
},
onRouteChange: function(route, params) {
this.$('li.current').removeClass('current');
var path = (params[0] || 'dashboard').split('/');
var $ref = this.$el.children('ul');
while($ref.length > 0 && path.length > 0) {
var $el = $ref.children('.' + path.shift());
$el.addClass('current');
$ref = $el.children('ul');
}
},
};

16
src/js/app.js Normal file
View File

@ -0,0 +1,16 @@
var Ridge = require('ridge');
var app = new Ridge({
collections: require('./collections'),
models: require('./models'),
views: require('./views')
});
app.module(require('spytext'));
$(function() {
app.navigation = new app.views.Navigation({ el: app.$('nav') });
Backbone.history.start({ silent: true, pushState: true });
});

View File

@ -0,0 +1,2 @@
module.exports = {
};

2
src/js/models/index.js Normal file
View File

@ -0,0 +1,2 @@
module.exports = {
};

6
src/js/views/index.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
Page: require('ridge/views/page'),
Message: require('ridge/views/message'),
Navigation: require('./navigation'),
TreeWalker: require('./tree-walker')
};

View File

@ -0,0 +1,53 @@
module.exports = {
events: {
'mouseover ul': 'dud',
'mouseout ul': 'dud',
'click i, div.cover, ul': 'toggleMobile',
},
toggleMobile: function(e) {
if(document.body.clientWidth < 640) {
this.$('ul').toggleClass('show').on('touchmove', function(e) {
e.preventDefault();
});
$(document.body).toggleClass('push');
// breaks iOS:
this.$('div.cover').toggleClass('active');
}
},
dud: function() {
var $element = this.$('li:hover'),
left, width;
if($element.length === 0)
$element = this.$('li.current');
this.$el.children('.dud').toggleClass('active', $element.length !== 0).css({
left: $element.length === 0 ? '' : $element[0].offsetLeft + 'px',
width: $element.length === 0 ? 0 : $element.width() + 'px'
});
},
initialize: function(options) {
this.listenTo(this.app.router, 'route', this.onRouteChange);
},
attach: function() {
// wait for fonts to load
setTimeout(this.dud.bind(this), 300);
},
onRouteChange: function(route, params) {
$(document.body).removeClass('push');
var path = params[0];
path = path ? path.split('/')[0] : 'index';
this.$('li.current').removeClass('current');
this.$('li.' + path).addClass('current');
this.dud();
}
};

18
src/js/views/spytext.js Normal file
View File

@ -0,0 +1,18 @@
var Spytext = require('spytext');
module.exports = {
events: {
},
attach: function() {
var _view = this;
_view.$('[data-spytext]').each(function(i, el) {
// TODO clear previous spytext fields
if(!_view.spytext) _view.spytext = new Spytext();
_view.spytext.addField(el);
});
}
};

View File

@ -0,0 +1,53 @@
var s = window.getSelection;
var selectron = require('spytext/selectron');
function offsetold(node, value, root) {
value = value || 0;
root = root || document.body;
var tw = document.createTreeWalker(root);
var last = tw.currentNode = node;
while(tw.previousNode() !== tw.root) {
//!getComputedStyle(node).display.match(/inline/);
var nodeType = tw.currentNode.nodeType;
if(nodeType === 1 && (
last.nodeType === 1 && last === tw.currentNode.nextSibling ||
last.nodeType === 3 && last === tw.currentNode.firstChild
) ||
nodeType === 3 && last !== tw.currentNode.nextSibling)
value++;
if(tw.currentNode.nodeType === 3) {
value += tw.currentNode.textContent.length;
}
//console.log(tw.currentNode);
//console.log('value: ' + value);
last = tw.currentNode;
}
return value;
}
module.exports = {
attach: function() {
console.log('attach');
var $root = this.$('#tree-walker');
$root.on('keydown', function(e) {
if (e.ctrlKey && e.keyCode === 65) {
e.preventDefault();
console.log(selectron.getOffset($root[0]));
//console.log(selectron.restore($root[0], selectron.getOffset($root[0]) + 1));
var positions = selectron.get($root[0]);
s().removeAllRanges();
setTimeout(function() {
selectron.set(positions);
}, 1000);
}
});
}
};

20
src/sass/_content.scss Normal file
View File

@ -0,0 +1,20 @@
/* --------- MOD ------------------ */
div.mod {
.container {
width: 100%;
min-height: 300px;
> div {
float: left;
width: 25%;
min-height: 200px;
border: 1px solid black;
}
}
}
form.spytext {
.spytext-field {
min-height: 300px;
}
}

41
src/sass/_layout.scss Normal file
View File

@ -0,0 +1,41 @@
nav {
> ul {
@include wipe-list;
> li {
padding: 0 10px;
float: left;
&:first-child { padding-left: 0; }
}
}
}
body {
overflow-x: hidden;
overflow-y: scroll;
> main {
overflow-x: hidden;
width: 100%;
max-width: $row-max-width;
margin: 0 auto;
> .page {
width: 100%;
&.animate {
transition: opacity 0.2s ease-out;
float: left;
position: relative;
}
&.leave {
margin-right: -100%;
}
&.leave.active {
opacity: 0;
}
&.enter {
opacity: 0;
}
&.enter.active, &.leave {
opacity: 1;
}
}
}
}

View File

@ -0,0 +1,78 @@
// required for rem() and em() to work in this file
@import "spysass/functions";
//
// Base
//
//$include-reset: true;
//$include-normalize: false;
//$make-image-inline-block: false;
//$default-float: left;
//$opposite-direction: right;
//$text-direction: left;
//$global-radius: 0;
//$make-image-inline-block: false;
//$color-main-1: #0066c6;
//$color-message: #333;
//$color-error: #c90000;
//$color-success: #628b1c;
// This needs to be a px value since rem and em-calc use it. It is translated
// to a percante unit for html and body font-sizing like so: strip-unit($base-font-size) / 16 * 100%;
//$base-font-size: 16px;
//$base-line-height: 1.6;
//$base-line-height-computed: $base-line-height * 1rem;
//$body-font-color: #222;
//$body-font-family: "Times New Roman", sans-serif;
//$body-font-weight: normal;
//$body-font-style: normal;
//$body-bg: #fff;
//$font-smoothing: subpixel-antialiased;
// Need to be in pixels for IE8
//$small-range: 0px, 639px;
//$medium-range: 640px, 1023px;
//$large-range: 1024px, 1439px;
//$xlarge-range: 1440px, 1920px;
//$xxlarge-range: 1921px, 999999px;
//
// Grid
//
//$column-gutter: rem(30);
//$row-width: rem(1000);
//$total-columns: 12;
//
// Type
//
//$heading-font-family: $body-font-family;
//$heading-font-weight: bold;
//$heading-font-style: normal;
//$heading-font-color: $body-font-color;
//$heading-text-rendering: optimizeLegibility;
//$heading-top-margin: $base-line-height-computed;
//$heading-bottom-margin: $base-line-height-computed / 2;
//$heading-line-height: 1.2;
//$h1-font-size: 2.5rem;//40px when base-font-size is 16px
//$h2-font-size: 2.0rem;//32px when base-font-size is 16px
//$h3-font-size: 1.7rem;//27.2px when base-font-size is 16px
//$h4-font-size: 1.4rem;//22.4px when base-font-size is 16px
//$h5-font-size: 1.2rem;//19.2px when base-font-size is 16px
//$h6-font-size: 1.0rem;
//$paragraph-font-family: $body-font-family;
//$paragraph-font-weight: normal;
//$paragraph-font-size: 1.0rem;
//$paragraph-line-height: $base-line-height;
//$paragraph-margin: 0 0 ($base-line-height-computed / 2);
//$paragraph-text-rendering: optimizeLegibility;

2
src/sass/admin/main.scss Normal file
View File

@ -0,0 +1,2 @@
@import 'spysass';
@import 'themes/admin/one';

15
src/sass/main.scss Normal file
View File

@ -0,0 +1,15 @@
@import "spysass";
@import "components/type";
@import "components/grid";
@import "themes/spytext/niknus";
@import "themes/form/foundation";
@import "layout";
@import "content";
#tree-walker {
padding: 15px;
border: 1px solid black;
}

3
src/static/robots.txt Normal file
View File

@ -0,0 +1,3 @@
User-agent: *
Disallow: /admin/
Disallow: /api/