├── week5
├── hangout
│ ├── .bowerrc
│ ├── bower.json
│ ├── js
│ │ ├── init.js
│ │ └── app.js
│ ├── css
│ │ └── style.css
│ └── index.html
├── README.md
└── 2-todo-crud
│ └── README.md
├── week6
├── README.md
├── hangout1
│ ├── .bowerrc
│ ├── data
│ │ └── rest.json
│ ├── bower.json
│ ├── package.json
│ ├── public
│ │ ├── js
│ │ │ ├── init.js
│ │ │ ├── taskModel.js
│ │ │ ├── app.js
│ │ │ └── tasksView.js
│ │ └── css
│ │ │ └── style.css
│ ├── views
│ │ └── index.jade
│ └── server.js
├── hangout2
│ ├── .bowerrc
│ ├── public
│ │ ├── img
│ │ │ ├── header-bg.jpg
│ │ │ ├── events
│ │ │ │ ├── event1.jpg
│ │ │ │ ├── event2.jpg
│ │ │ │ └── event3.jpg
│ │ │ └── artists
│ │ │ │ ├── james-brown.jpg
│ │ │ │ ├── jamiroquai.jpg
│ │ │ │ └── tom-jones.jpeg
│ │ └── css
│ │ │ ├── inc
│ │ │ ├── sections
│ │ │ │ ├── _home.scss
│ │ │ │ └── _events.scss
│ │ │ ├── helpers
│ │ │ │ ├── _vars.scss
│ │ │ │ └── _bootstrap_mod.scss
│ │ │ ├── _base.scss
│ │ │ └── _layout.scss
│ │ │ ├── style.scss
│ │ │ └── style.css
│ ├── bower.json
│ ├── package.json
│ ├── views
│ │ ├── artists.jade
│ │ ├── layout.jade
│ │ ├── index.jade
│ │ └── events.jade
│ └── server.js
├── 2-hobby-site
│ ├── .bowerrc
│ ├── views
│ │ ├── index.jade
│ │ └── layout.jade
│ ├── server.js
│ └── README.md
├── hangout1_full
│ ├── .bowerrc
│ ├── data
│ │ └── rest.json
│ ├── bower.json
│ ├── package.json
│ ├── views
│ │ └── index.jade
│ ├── public
│ │ ├── css
│ │ │ └── style.css
│ │ └── js
│ │ │ ├── init.js
│ │ │ ├── taskModel.js
│ │ │ ├── tasksView.js
│ │ │ └── app.js
│ └── server.js
├── guides
│ └── sass.md
└── 1-bootstrap-shop
│ └── README.md
├── week1
├── hangout
│ ├── .bowerrc
│ ├── .gitignore
│ ├── public
│ │ ├── img
│ │ │ ├── bg.jpg
│ │ │ ├── logo.png
│ │ │ ├── post1.png
│ │ │ ├── post2.jpg
│ │ │ └── content-bg.png
│ │ └── css
│ │ │ └── style.css
│ ├── views
│ │ ├── post.jade
│ │ ├── index.jade
│ │ └── layout.jade
│ ├── package.json
│ ├── bower.json
│ ├── posts.json
│ └── server.js
├── 2-simple-blog
│ └── README.md
├── README.md
├── 3-jade-blog
│ └── README.md
└── 1-hello-node
│ └── README.md
├── week8
├── hangout
│ ├── .gitignore
│ ├── .bowerrc
│ ├── bower.json
│ ├── public
│ │ ├── views
│ │ │ ├── users.jade
│ │ │ ├── subs.jade
│ │ │ └── mags.jade
│ │ └── js
│ │ │ ├── resource.js
│ │ │ └── init.js
│ ├── package.json
│ ├── data
│ │ └── restMap.json
│ ├── views
│ │ └── index.jade
│ └── server.js
├── rest-example
│ ├── .bowerrc
│ ├── views
│ │ └── index.jade
│ ├── bower.json
│ ├── data
│ │ └── restMap.json
│ ├── package.json
│ ├── public
│ │ └── js
│ │ │ ├── init.js
│ │ │ └── resource.js
│ └── server.js
├── 2-rest-resource
│ ├── .bowerrc
│ ├── data
│ │ └── restMap.json
│ ├── public
│ │ └── js
│ │ │ └── init.js
│ ├── server.js
│ └── README.md
└── README.md
├── .gitignore
├── week4
├── 2-DOM-Todo
│ ├── mockup.png
│ ├── example.html
│ ├── example.js
│ └── README.md
├── materials
│ ├── page.js
│ ├── page.html
│ └── dom.js
├── 1-Keeping-up-the-Score
│ ├── mockup.png
│ ├── page.html
│ ├── README.md
│ └── page.js
├── hangout
│ ├── README.md
│ ├── index.html
│ ├── interface.js
│ └── dom-wrapper.js
└── README.md
├── week2
├── hangout
│ ├── data
│ │ └── users.json
│ ├── package.json
│ └── crud.js
├── 1-bulls-n-cows
│ └── README.md
├── 2-console-crud
│ └── README.md
└── README.md
├── Application
├── README.md
├── 1-Mask-Words
│ └── README.md
├── 2-A-Simple-Logger
│ └── README.md
└── 3-Query-Language-Over-CSV
│ └── README.md
├── week3
├── 4-Queue
│ ├── queue.js
│ └── README.md
├── materials
│ ├── person.js
│ ├── call_apply.js
│ └── closure.js
├── 5-Event-Bus
│ ├── bus.js
│ └── README.md
├── 3-Prototypes
│ ├── prototypes.js
│ └── README.md
├── README.md
├── 2-Point
│ ├── points.js
│ └── README.md
├── 1-A-Panda
│ ├── panda.js
│ └── README.md
└── 6-HTML-Generator
│ └── README.md
├── week7
└── 1-students-crud
│ └── README.md
└── README.md
/week5/hangout/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "lib"
3 | }
--------------------------------------------------------------------------------
/week6/README.md:
--------------------------------------------------------------------------------
1 | # Week6 : Bootstrap & SASS
2 |
3 |
--------------------------------------------------------------------------------
/week1/hangout/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
--------------------------------------------------------------------------------
/week8/hangout/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | public/lib
3 |
4 |
--------------------------------------------------------------------------------
/week6/hangout1/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week6/hangout2/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week8/hangout/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week1/hangout/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | public/lib
3 | npm-debug.log
--------------------------------------------------------------------------------
/week6/2-hobby-site/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week6/2-hobby-site/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
--------------------------------------------------------------------------------
/week6/hangout1_full/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week8/rest-example/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/week8/2-rest-resource/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "public/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | README.html
2 | lib
3 | node_modules
4 | public/lib
5 | style.css.map
6 | npm-debug.log
7 | .sass-cache
8 |
--------------------------------------------------------------------------------
/week1/2-simple-blog/README.md:
--------------------------------------------------------------------------------
1 | # Week 1 Task 2: Simple Blog
2 | Now let's create something more complex than a hello world page.
--------------------------------------------------------------------------------
/week4/2-DOM-Todo/mockup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week4/2-DOM-Todo/mockup.png
--------------------------------------------------------------------------------
/week1/hangout/public/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week1/hangout/public/img/bg.jpg
--------------------------------------------------------------------------------
/week4/materials/page.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function(event) {
2 | console.log("Hip hip");
3 | });
4 |
--------------------------------------------------------------------------------
/week1/hangout/public/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week1/hangout/public/img/logo.png
--------------------------------------------------------------------------------
/week1/hangout/public/img/post1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week1/hangout/public/img/post1.png
--------------------------------------------------------------------------------
/week1/hangout/public/img/post2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week1/hangout/public/img/post2.jpg
--------------------------------------------------------------------------------
/week1/hangout/public/img/content-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week1/hangout/public/img/content-bg.png
--------------------------------------------------------------------------------
/week4/1-Keeping-up-the-Score/mockup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week4/1-Keeping-up-the-Score/mockup.png
--------------------------------------------------------------------------------
/week6/hangout2/public/img/header-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/header-bg.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/events/event1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/events/event1.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/events/event2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/events/event2.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/events/event3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/events/event3.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/artists/james-brown.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/artists/james-brown.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/artists/jamiroquai.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/artists/jamiroquai.jpg
--------------------------------------------------------------------------------
/week6/hangout2/public/img/artists/tom-jones.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HackBulgaria/Frontend-JavaScript-2/HEAD/week6/hangout2/public/img/artists/tom-jones.jpeg
--------------------------------------------------------------------------------
/week4/1-Keeping-up-the-Score/page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/week1/hangout/views/post.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | article
5 | a.title= post.title
6 | img(src=post.img)
7 | p.text= post.text
--------------------------------------------------------------------------------
/week6/2-hobby-site/views/layout.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Title
4 | //- styles here
5 | body
6 |
7 | //- header here
8 |
9 | block content
10 |
11 |
12 | //- scripts here
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/sections/_home.scss:
--------------------------------------------------------------------------------
1 | #home {
2 | #upcomming-events {
3 | .event {
4 | margin: 10px 0px;
5 | img {
6 | width: 100%;
7 | height: 150px;
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/week1/hangout/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | each post, id in posts
5 | hr
6 | article
7 | a.title(href="/"+id+".html")= post.title
8 | p.text= post.text
9 |
--------------------------------------------------------------------------------
/week4/2-DOM-Todo/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Add Task!
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/week4/2-DOM-Todo/example.js:
--------------------------------------------------------------------------------
1 | window.onload = function() {
2 | var button = document.getElementById("add-task-button");
3 | button.onclick = function(event) {
4 | var input = document.getElementById("task-input");
5 |
6 | console.log(input.value);
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/week2/hangout/data/users.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 123,
4 | "name": "Alex",
5 | "email": "alex@i4web.biz"
6 | },
7 | {
8 | "id": "567",
9 | "name": "Tosho",
10 | "email": "tosho@test.com"
11 | },
12 | {
13 | "id": "456",
14 | "name": "Gosho",
15 | "email": "iam@back.com"
16 | }
17 | ]
18 |
--------------------------------------------------------------------------------
/week8/rest-example/views/index.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Resource Test
4 | link(rel="stylesheet",href="lib/bootstrap/dist/css/bootstrap.css")
5 |
6 |
7 |
8 |
9 | body
10 |
11 | script(src="lib/jquery/dist/jquery.js")
12 | script(src="lib/q/q.js")
13 | script(src="js/resource.js")
14 | script(src="js/init.js")
15 |
16 |
--------------------------------------------------------------------------------
/week6/hangout2/public/css/style.scss:
--------------------------------------------------------------------------------
1 |
2 | @import url(http://fonts.googleapis.com/css?family=Audiowide);
3 |
4 |
5 | @import "inc/helpers/vars";
6 | @import "inc/helpers/bootstrap_mod";
7 |
8 | @import "inc/base";
9 | @import "inc/layout";
10 |
11 | /* sections */
12 | @import "inc/sections/home";
13 | @import "inc/sections/events";
14 |
15 |
16 |
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/helpers/_vars.scss:
--------------------------------------------------------------------------------
1 |
2 | $funkytown-color-light: #FFF;
3 | $funkytown-color-text: #dacea9;
4 | $funkytown-color-dark: #000;
5 | $funkytown-color-red: #e70000;
6 | $funkytown-color-yellow: #ffc100;
7 |
8 | $funkytown-font-text: Helvetica, Arial, sans-serif;
9 | $funkytown-font-heading: "Audiowide", Helvetica, Arial, sans-serif;
10 |
--------------------------------------------------------------------------------
/week8/README.md:
--------------------------------------------------------------------------------
1 | # Week 8 Async & Promises, MVC & App Architecture
2 |
3 | ## Check out theese resources
4 |
5 | - [What makes javascript weird and awesome](https://www.youtube.com/watch?v=JEq7Ehw-qk8&list=PLoYCgNOIyGABI011EYc-avPOsk1YsMUe_)
6 | - [Philip Roberts: What the heck is the event loop anyway](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
7 | - https://github.com/kriskowal/q
--------------------------------------------------------------------------------
/Application/README.md:
--------------------------------------------------------------------------------
1 | # Application problems for Frontend JavaScript
2 |
3 | ## Problem 1 - Mask out words
4 |
5 | [Read the description here.](1-Mask-Words)
6 |
7 | ## Problem 2 - A simple Logger
8 |
9 | [Read the description here.](2-A-Simple-Logger)
10 |
11 | ## Problem 3 - Query language over CSV
12 |
13 | [Read the description here.](3-Query-Language-Over-CSV)
14 |
15 |
--------------------------------------------------------------------------------
/week4/hangout/README.md:
--------------------------------------------------------------------------------
1 | # Hangout 3 - DOM and jQuery like implementation
2 |
3 | In that hangout we implement a simple class, that behaves like jQuery.
4 |
5 | The main idea is to provide our own DOM API, which is much better than the original. We do this by wrappingthe DOM API with methods of our own.
6 |
7 | [Here is the video from the hangout](https://www.youtube.com/watch?v=AnHwvAO2q0U)
8 |
--------------------------------------------------------------------------------
/week6/hangout1/data/rest.json:
--------------------------------------------------------------------------------
1 | {
2 | "collections" : {
3 | "tasks": {
4 | "model": "Task",
5 | "schema": {
6 | "name" : "String",
7 | "finished" : "Boolean"
8 | }
9 | }
10 | },
11 | "routes": {
12 | "api" : {
13 | "_meta": {
14 | "virtual": true,
15 | "crud": true,
16 | "contentType": "json"
17 | },
18 | "tasks": {
19 | }
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/week6/guides/sass.md:
--------------------------------------------------------------------------------
1 | ## Installation
2 | - http://www.hongkiat.com/blog/getting-started-saas/ - win & mac + basic info
3 | - http://sass-lang.com/install - linux
4 |
5 |
6 | ## Compile SASS to CSS
7 | ```sh
8 | sass css/style.scss:css/style.css --sourcemap
9 | ```
10 |
11 | ## Basic example
12 |
13 |
14 |
15 |
16 | ## Style Guide
17 | - https://css-tricks.com/sass-style-guide/
18 | - http://sass-guidelin.es/
--------------------------------------------------------------------------------
/week8/rest-example/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week8-resource",
3 | "version": "0.0.0",
4 | "authors": [
5 | "Alex Milanov "
6 | ],
7 | "license": "MIT",
8 | "ignore": [
9 | "**/.*",
10 | "node_modules",
11 | "bower_components",
12 | "public/lib",
13 | "test",
14 | "tests"
15 | ],
16 | "dependencies": {
17 | "jquery": "~2.1.4",
18 | "q": "1.x"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week6/hangout2/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "2-hobby-site",
3 | "version": "0.0.0",
4 | "authors": [
5 | "Alex Milanov "
6 | ],
7 | "license": "MIT",
8 | "ignore": [
9 | "**/.*",
10 | "node_modules",
11 | "bower_components",
12 | "public/lib",
13 | "test",
14 | "tests"
15 | ],
16 | "dependencies": {
17 | "bootstrap": "~3.3.4",
18 | "fontawesome": "~4.3.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week3/4-Queue/queue.js:
--------------------------------------------------------------------------------
1 | var queue = (function() {
2 | var data = [];
3 |
4 | function pop() {
5 | var head = data.shift();
6 | return head;
7 | }
8 |
9 | function push(item) {
10 | data.push(item);
11 | return item;
12 | }
13 |
14 | function isEmpty() {
15 | return data.length == 0;
16 | }
17 |
18 | return {
19 | "pop": pop,
20 | "push": push,
21 | "isEmpty": isEmpty
22 | }
23 | })();
24 |
25 |
--------------------------------------------------------------------------------
/week8/hangout/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week8-subsciptions",
3 | "version": "0.1.0",
4 | "authors": [
5 | "Alex Milanov "
6 | ],
7 | "license": "MIT",
8 | "ignore": [
9 | "**/.*",
10 | "node_modules",
11 | "bower_components",
12 | "test",
13 | "tests"
14 | ],
15 | "dependencies": {
16 | "jquery": "~2.1.4",
17 | "q": "1.x",
18 | "bootstrap": "~3.3.4",
19 | "jade": "~1.9.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/week8/rest-example/data/restMap.json:
--------------------------------------------------------------------------------
1 | {
2 | "collections" : {
3 | "students": {
4 | "model": "Student",
5 | "schema": {
6 | "name" : "String",
7 | "email" : "String",
8 | "gitRepo" : "String",
9 | "hobbyProject" : "String"
10 | }
11 | }
12 | },
13 | "routes": {
14 | "api" : {
15 | "_meta": {
16 | "virtual": true,
17 | "crud": true,
18 | "contentType": "json"
19 | },
20 | "students": {
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/week3/materials/person.js:
--------------------------------------------------------------------------------
1 | var person = {
2 | "name": "Ivo",
3 | "age": 24
4 | };
5 |
6 |
7 | // "closure" -> "обвивка"
8 |
9 | function createPerson(name, age) {
10 | return {
11 | "getName": function() {
12 | return name;
13 | },
14 | "getAge": function() {
15 | return age;
16 | }
17 | }
18 |
19 | }
20 |
21 | var ivo = createPerson("ivo", 22);
22 | ivo.name = ivo.getName();
23 | ivo.name = "Rado";
24 | console.log(ivo);
25 |
26 |
--------------------------------------------------------------------------------
/week8/2-rest-resource/data/restMap.json:
--------------------------------------------------------------------------------
1 | {
2 | "collections" : {
3 | "students": {
4 | "model": "Student",
5 | "schema": {
6 | "name" : "String",
7 | "email" : "String",
8 | "gitRepo" : "String",
9 | "hobbyProject" : "String"
10 | }
11 | }
12 | },
13 | "routes": {
14 | "api" : {
15 | "_meta": {
16 | "virtual": true,
17 | "crud": true,
18 | "contentType": "json"
19 | },
20 | "students": {
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/week6/hangout2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "2-hobby-site",
3 | "version": "1.0.0",
4 | "description": "## ULTRA TASK Recreate 3 site types with 2-3 screens each using bootstrap & SASS",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "express": "^4.12.3",
14 | "jade": "^1.9.2"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/week2/hangout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout2crud",
3 | "version": "0.0.0",
4 | "description": "crud operations in console",
5 | "main": "crud.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "crud",
11 | "console",
12 | "prompt"
13 | ],
14 | "author": "",
15 | "license": "ISC",
16 | "dependencies": {
17 | "prompt": "~0.2.14",
18 | "jsonfile": "~2.0.0",
19 | "chalk": "~1.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/week1/hangout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week1hangout",
3 | "version": "0.0.9",
4 | "description": "week 1 final project plus some stuff",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "keywords": [
11 | "jade",
12 | "express",
13 | "blog"
14 | ],
15 | "author": "Alex Milanov",
16 | "license": "ISC",
17 | "dependencies": {
18 | "express": "^4.12.3",
19 | "jade": "^1.9.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/week4/materials/page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello!
4 |
5 |
6 |
7 |
HEADING!
8 |
9 | First item
10 | Second item
11 | Third item
12 | Fourh item
13 |
14 |
15 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/week6/hangout2/views/artists.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | .container-fluid#artists
5 | h1 Artists
6 | #artists-list
7 | .row
8 | .col-xs-3
9 | img(src="/img/artists/james-brown.jpg",width="100%")
10 | .col-xs-9
11 | h2 James Brown
12 | .row
13 | .col-xs-3
14 | img(src="/img/artists/tom-jones.jpeg",width="100%")
15 | .col-xs-9
16 | h2 Tom Jones
17 | .row
18 | .col-xs-3
19 | img(src="/img/artists/jamiroquai.jpg",width="100%")
20 | .col-xs-9
21 | h2 Jamiroquai
--------------------------------------------------------------------------------
/week1/hangout/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week1hangout",
3 | "version": "0.0.9",
4 | "authors": [
5 | "Alex Milanov "
6 | ],
7 | "description": "week 1 final project plus some stuff",
8 | "main": "server.js",
9 | "keywords": [
10 | "jade",
11 | "blog",
12 | "express"
13 | ],
14 | "license": "MIT",
15 | "ignore": [
16 | "**/.*",
17 | "node_modules",
18 | "bower_components",
19 | "test",
20 | "tests"
21 | ],
22 | "dependencies": {
23 | "bootstrap": "~3.3.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/week1/hangout/views/layout.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Jade Blog
4 | link(rel="stylesheet",type="text/css",href="css/style.css")
5 | body
6 | .container
7 | header
8 | a(href="/")
9 | img(src="img/logo.png")
10 | section
11 | .sidebar
12 | p.widget-title Category List
13 | ul.widget-list
14 | li: a(href="/") Category1
15 | li: a(href="/") Category2
16 | .content
17 | block content
--------------------------------------------------------------------------------
/week6/hangout1_full/data/rest.json:
--------------------------------------------------------------------------------
1 | {
2 | "collections" : {
3 | "tasks": {
4 | "model": "Task",
5 | "schema": {
6 | "name" : "String",
7 | "finished" : "Boolean"
8 | }
9 | },
10 | "settings": {
11 | "model": "Setting",
12 | "schema": {
13 | "tasksOrder": ["ObjectId"]
14 | }
15 | }
16 | },
17 | "routes": {
18 | "api" : {
19 | "_meta": {
20 | "virtual": true,
21 | "crud": true,
22 | "contentType": "json"
23 | },
24 | "tasks": {
25 | },
26 | "settings": {
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/week4/hangout/index.html:
--------------------------------------------------------------------------------
1 |
2 | jQuery-like example
3 |
4 | Buy!!!
5 |
6 |
7 | Item 1
8 | Item 2
9 | Item 3
10 | Item 4
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/sections/_events.scss:
--------------------------------------------------------------------------------
1 | #events {
2 | #events-list {
3 | .thumbnail {
4 | .date {
5 | position: absolute;
6 | top: 0px;
7 | left: 0px;
8 | width: 80px;
9 | height: 30px;
10 | line-height: 30px;
11 | font-size: 16px;
12 | text-align: center;
13 | font-weight: bold;
14 | color: white;
15 | background: $funkytown-color-yellow;
16 |
17 | }
18 | &:hover {
19 | .date {
20 | background: $funkytown-color-red;
21 | }
22 | }
23 | cursor: pointer;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/week6/hangout1/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout1",
3 | "version": "0.0.0",
4 | "homepage": "https://github.com/HackBulgaria/Frontend-JavaScript-2",
5 | "authors": [
6 | "Alex Milanov "
7 | ],
8 | "license": "MIT",
9 | "ignore": [
10 | "**/.*",
11 | "node_modules",
12 | "bower_components",
13 | "public/lib",
14 | "test",
15 | "tests"
16 | ],
17 | "dependencies": {
18 | "jquery": "~2.1.3",
19 | "fontawesome": "~4.3.0",
20 | "bootstrap": "~3.3.4",
21 | "jqueryui": "~1.11.4"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/week8/hangout/public/views/users.jade:
--------------------------------------------------------------------------------
1 | h4 Users
2 |
3 | .row
4 | .col-sm-4
5 | form.well#users-form
6 | .form-group
7 | label Magazine
8 | input.form-control(name="name",type="text")
9 | .form-group
10 | label User
11 | input.form-control(name="email",type="text")
12 | button.btn.btn-primary(type="submit") Save
13 | button.btn.btn-default Reset
14 |
15 | .col-sm-8
16 | table.table
17 | thead: tr
18 | th Name
19 | th Email
20 | tbody
21 | each user in users
22 | tr
23 | td= user.name
24 | td= user.email
--------------------------------------------------------------------------------
/week6/hangout1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "body-parser": "^1.12.3",
14 | "express": "^4.12.3",
15 | "iblokz-node-restify": "git://github.com/iblokz/node-restify",
16 | "jade": "^1.9.2",
17 | "method-override": "^2.3.2",
18 | "mongoose": "^4.0.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week6/hangout1_full/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout1",
3 | "version": "0.0.0",
4 | "homepage": "https://github.com/HackBulgaria/Frontend-JavaScript-2",
5 | "authors": [
6 | "Alex Milanov "
7 | ],
8 | "license": "MIT",
9 | "ignore": [
10 | "**/.*",
11 | "node_modules",
12 | "bower_components",
13 | "public/lib",
14 | "test",
15 | "tests"
16 | ],
17 | "dependencies": {
18 | "jquery": "~2.1.3",
19 | "fontawesome": "~4.3.0",
20 | "bootstrap": "~3.3.4",
21 | "jqueryui": "~1.11.4"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/week6/hangout1_full/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "body-parser": "^1.12.3",
14 | "express": "^4.12.3",
15 | "iblokz-node-restify": "git://github.com/iblokz/node-restify",
16 | "jade": "^1.9.2",
17 | "method-override": "^2.3.2",
18 | "mongoose": "^4.0.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week8/hangout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week8-subsciptions",
3 | "version": "0.1.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "body-parser": "^1.12.3",
14 | "express": "^4.12.3",
15 | "iblokz-node-restify": "git://github.com/iblokz/node-restify",
16 | "jade": "^1.9.2",
17 | "method-override": "^2.3.2",
18 | "mongoose": "^4.0.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week8/rest-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "week8-resource",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "body-parser": "^1.12.3",
14 | "express": "^4.12.3",
15 | "iblokz-node-restify": "git://github.com/iblokz/node-restify",
16 | "jade": "^1.9.2",
17 | "method-override": "^2.3.2",
18 | "mongoose": "^4.0.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/week5/hangout/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hangout",
3 | "version": "0.0.0",
4 | "homepage": "https://github.com/HackBulgaria/Frontend-JavaScript-2",
5 | "authors": [
6 | "Alex Milanov "
7 | ],
8 | "description": "todo app",
9 | "main": "index.html",
10 | "license": "MIT",
11 | "ignore": [
12 | "**/.*",
13 | "node_modules",
14 | "bower_components",
15 | "lib",
16 | "test",
17 | "tests"
18 | ],
19 | "dependencies": {
20 | "jquery": "~2.1.3",
21 | "jqueryui": "~1.11.4",
22 | "fontawesome": "~4.3.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/week2/1-bulls-n-cows/README.md:
--------------------------------------------------------------------------------
1 | # Week 2 : Task 1 : Bulls & Cows
2 |
3 | Let's recreate the game where you have to guess a four-digit number whereby all digits are unique.
4 |
5 | ## Dependencies
6 | - npm
7 | - prompt
8 | - chalk
9 |
10 | ## Premise
11 | - generate a 4 digit number with unique digits
12 | - 4375 is ok
13 | - 5566 not ok
14 | - prompt user for input
15 | - if guess is successful end game
16 | - if not prompt until successful
17 |
18 | ## Example
19 | ```sh
20 | node bulls-n-cows.js
21 | > 4582
22 | 1 bulls 2 cows
23 | > 4735
24 | 2 bulls 2 cows
25 | > 4375
26 | you guessed it!
27 | ```
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/_base.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | body {
4 | background: $funkytown-color-dark;
5 | color: $funkytown-color-light;
6 | font-family: $funkytown-font-text;
7 | > .container-fluid {
8 | margin-top: 70px;
9 | a {
10 | color: $funkytown-color-yellow;
11 | &:hover {
12 | color: $funkytown-color-red;
13 | text-decoration: none;
14 | }
15 | }
16 | }
17 | }
18 |
19 | h1, h2, h3, .navbar-brand, .navbar-nav li {
20 | font-family: $funkytown-font-heading;
21 | }
22 |
23 | h1, h2, h3 {
24 | padding: 0 0 2px;
25 | border-bottom: 2px solid $funkytown-color-red;
26 | margin: 0 0 13px;
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/helpers/_bootstrap_mod.scss:
--------------------------------------------------------------------------------
1 | .thumbnail {
2 | background: inherit;
3 | border-radius: 0px;
4 | border: 0px;
5 | padding: 0px;
6 | position: relative;
7 | img {
8 | width: 100%;
9 | }
10 | h4 {
11 | font-family: $funkytown-font-heading;
12 | }
13 | p {
14 | color: $funkytown-color-text;
15 | }
16 | }
17 |
18 |
19 | /* small screens */
20 | @media only screen and (max-width : 768px) {
21 | .thumbnail {
22 | img {
23 | width: 30%;
24 | display: inline-block;
25 | }
26 | .caption {
27 | width: 70%;
28 | display: inline-block;
29 | vertical-align: top;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/week3/materials/call_apply.js:
--------------------------------------------------------------------------------
1 | function Person(name) {
2 | this.name = name;
3 | }
4 |
5 | Person.prototype.toString = function() {
6 | return "Hello, I am " + this.name;
7 | }
8 | // 1. Да открадна this
9 | // 2. Да открадна prototype
10 | function Student(name, fn) {
11 | Person.call(this, name);
12 | this.fn = fn;
13 | }
14 |
15 | Student.prototype = Object.create(Person.prototype);
16 | Student.prototype.toString = function() {
17 | return Person.prototype.toString.call(this) + " " + this.fn;
18 | }
19 |
20 | var p = new Person("Rado");
21 | var s = new Student("Ivo", "800000");
22 |
23 | console.log(p.toString());
24 | console.log(s.toString());
25 |
26 |
--------------------------------------------------------------------------------
/week3/materials/closure.js:
--------------------------------------------------------------------------------
1 | function makeCounter() {
2 | return (function() {
3 | var count = 0;
4 | return function() {
5 | count += 1;
6 | return count;
7 | }
8 | }());
9 | }
10 |
11 | var c1 = makeCounter();
12 | console.log(c1());
13 | console.log(c1());
14 |
15 | console.log("Swiching counters");
16 |
17 | var c2 = makeCounter();
18 | console.log(c2());
19 | console.log(c2());
20 |
21 | // private for object literals
22 | // with closure
23 | var person =
24 | (function() {
25 | var name = "Ivo";
26 |
27 | return {
28 | "getName": function() {
29 | return name;
30 | }
31 | }
32 | }());
33 |
34 | console.log(person.getName());
35 |
--------------------------------------------------------------------------------
/week4/1-Keeping-up-the-Score/README.md:
--------------------------------------------------------------------------------
1 | # Keeping up the Score
2 |
3 | We are going to introduce ourselves to the DOM by creating elements and attaching events to them.
4 |
5 | Check the [page.html](page.html) file - it is a blank HTML with one `div` container.
6 |
7 | We are going to need a `page.js` file to control our code.
8 |
9 | ## Two Buttons
10 |
11 | We are going to need two buttons:
12 |
13 | * One for `TeamA`
14 | * One for `TeamB`
15 |
16 | Also, we are going to need to paragraphs of text, which will hold the score.
17 |
18 | When we click `TeamA`'s button, we are going to increase their score. The same thing goes for `TeamB`.
19 |
20 | See this mockup:
21 |
22 | 
23 |
--------------------------------------------------------------------------------
/week8/hangout/public/views/subs.jade:
--------------------------------------------------------------------------------
1 | h4 Subscriptions
2 |
3 | .row
4 | .col-sm-4
5 | form.well#subs-form
6 | .form-group
7 | label Magazine
8 | input.form-control(name="magId",type="text")
9 | .form-group
10 | label User
11 | input.form-control(name="userId",type="text")
12 | .form-group
13 | label Months
14 | input.form-control(name="months",type="number")
15 | button.btn.btn-primary(type="submit") Save
16 | button.btn.btn-default Reset
17 |
18 | .col-sm-8
19 | table.table
20 | thead: tr
21 | th Mag
22 | th User
23 | th Months
24 | tbody
25 | each sub in subs
26 | tr
27 | td= sub.magId
28 | td= sub.userId
29 | td= sub.months
--------------------------------------------------------------------------------
/week5/hangout/js/init.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | $(document).ready(function(){
4 | // init stuff
5 | $("ul#tasks-list").sortable({
6 | start: function(event, ui) {
7 | var fromIndex = ui.item.index();
8 | ui.item.data('fromIndex', fromIndex);
9 | },
10 | update: function (event, ui) {
11 | var fromIndex = ui.item.data('fromIndex');
12 | var toIndex = ui.item.index();
13 |
14 | TodoApp.moveTask(fromIndex, toIndex);
15 | TodoApp.displayList();
16 | }
17 | });
18 |
19 | $("#new-task-form").submit(function(){
20 |
21 | var taskName = $("#task-name").val();
22 | $("#task-name").val("")
23 |
24 | TodoApp.addTask(taskName);
25 | TodoApp.displayList();
26 |
27 | event.preventDefault();
28 | })
29 | })
--------------------------------------------------------------------------------
/week3/5-Event-Bus/bus.js:
--------------------------------------------------------------------------------
1 | // IIFE - Immediately Invoked Function Expression
2 | // design pattern in JavaScript
3 | var bus = (function() {
4 | var eventTable = {};
5 |
6 | function trigger(event) {
7 | var events = eventTable[event] || [];
8 |
9 | events.forEach(function(callback) {
10 | callback();
11 | });
12 | }
13 |
14 | function remove(event) {
15 | delete eventTable[event];
16 | }
17 |
18 | function on(event, callback) {
19 | if(typeof(eventTable[event]) === "undefined") {
20 | eventTable[event] = [];
21 | }
22 |
23 | eventTable[event].push(callback);
24 | }
25 |
26 | return {
27 | "trigger": trigger,
28 | "on": on,
29 | "remove": remove
30 | }
31 | })();
32 |
33 |
--------------------------------------------------------------------------------
/week4/materials/dom.js:
--------------------------------------------------------------------------------
1 | // PART1 - QUERING
2 | // If you want to take an element by tag:
3 |
4 | // ps is an array
5 | var ps = document.getElementsByTagName("p");
6 |
7 | for(var i = 0; i < ps.length; i += 1) {
8 | var p = ps[i];
9 | // changing the style of each paragraph
10 | p.style.border = "dashed 1px green";
11 | }
12 |
13 | // EVENTS
14 |
15 | var button = document.getElementById("main-button");
16 | button.onclick = function(event) {
17 | console.log("button was clicked");
18 | };
19 |
20 | // CREATING ELEMENTS
21 | var button = document.createElement("button");
22 | var text = document.createTextNode("I am Groot!");
23 | button.appendChild(text);
24 |
25 | var div = document.getElementById("the-div");
26 | div.appendChild(button);
27 |
--------------------------------------------------------------------------------
/week8/hangout/data/restMap.json:
--------------------------------------------------------------------------------
1 | {
2 | "collections" : {
3 | "users": {
4 | "model": "User",
5 | "schema": {
6 | "name" : "String",
7 | "email" : "String"
8 | }
9 | },
10 | "mags": {
11 | "model": "Mag",
12 | "schema": {
13 | "name": "String",
14 | "vol": "Number",
15 | "price": "Number"
16 | }
17 | },
18 | "subs": {
19 | "model": "Sub",
20 | "schema": {
21 | "userId": "ObjectId",
22 | "magId": "ObjectId",
23 | "months": "Number"
24 | }
25 | }
26 | },
27 | "routes": {
28 | "api" : {
29 | "_meta": {
30 | "virtual": true,
31 | "crud": true,
32 | "contentType": "json"
33 | },
34 | "users": {
35 | },
36 | "mags": {
37 | },
38 | "subs": {
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/week6/hangout1/public/js/init.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | $(document).ready(function(){
4 | // init stuff
5 | /*
6 | $("ul#tasks-list").sortable({
7 | start: function(event, ui) {
8 | var fromIndex = ui.item.index();
9 | ui.item.data('fromIndex', fromIndex);
10 | },
11 | update: function (event, ui) {
12 | var fromIndex = ui.item.data('fromIndex');
13 | var toIndex = ui.item.index();
14 |
15 | TodoApp.moveTask(fromIndex, toIndex);
16 | TodoApp.displayList();
17 | }
18 | });
19 | */
20 |
21 | $("#new-task-form").submit(function(){
22 |
23 | var taskName = $("#task-name").val();
24 | $("#task-name").val("")
25 |
26 | TodoApp.addTask(taskName);
27 |
28 | event.preventDefault();
29 | })
30 |
31 | TodoApp.init();
32 |
33 |
34 |
35 | })
--------------------------------------------------------------------------------
/week4/README.md:
--------------------------------------------------------------------------------
1 | # The DOM API
2 |
3 | We are now going to write our JavaScript code in the browser and start manipulating the DOM.
4 |
5 | Here are some essential materials:
6 |
7 | * [Introduction to DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction)
8 | * [Events in the DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)
9 | * [More DOM examples](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples)
10 | * [Difference between window, document and screen](http://stackoverflow.com/questions/9895202/what-is-the-difference-between-window-screen-and-document-in-javascript)
11 | * [Code examples for DOM API](materials/dom.js)
12 | * [How to listen for DOM ready event](materials/page.js)
13 |
14 |
--------------------------------------------------------------------------------
/week6/hangout1/views/index.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Week6 REST TODO
4 | link(rel="stylesheet", type="text/css", href="lib/fontawesome/css/font-awesome.css")
5 | link(rel="stylesheet", type="text/css", href="css/style.css")
6 | body
7 |
8 | form#new-task-form
9 | input#task-name(type="text", placeholder="Add new task")
10 |
11 | ul#tasks-list
12 |
13 | //- 3rd party libs
14 | script(type="text/javascript",src="lib/jquery/dist/jquery.min.js")
15 | script(type="text/javascript",src="lib/jqueryui/jquery-ui.min.js")
16 |
17 | //- our app
18 | script(type="text/javascript",src="js/taskModel.js")
19 | script(type="text/javascript",src="js/tasksView.js")
20 | script(type="text/javascript",src="js/app.js")
21 | script(type="text/javascript",src="js/init.js")
--------------------------------------------------------------------------------
/week3/3-Prototypes/prototypes.js:
--------------------------------------------------------------------------------
1 | // variadic arguments
2 | String.prototype.format = function(dict) {
3 | var result = this;
4 |
5 | if(typeof(dict) === "object") {
6 | Object.keys(dict).forEach(function(key) {
7 | result = result.replace("{" + key + "}", dict[key]);
8 | });
9 | return result;
10 | }
11 |
12 | var args = [];
13 | var n = arguments.length;
14 | var i = 0;
15 |
16 | for(i; i < n; i+=1) {
17 | args.push(arguments[i]);
18 | }
19 |
20 | var result = this;
21 |
22 | args.forEach(function(arg) {
23 | result = result.replace("{}", arg);
24 | });
25 |
26 | return result;
27 | }
28 |
29 | console.log("{} {} {}".format("one", "two", "three"));
30 | console.log("Hello {name}, I am {friend}".format({
31 | "name": "Ivo",
32 | "friend": "Rado"
33 | }));
34 |
35 |
--------------------------------------------------------------------------------
/week8/hangout/public/views/mags.jade:
--------------------------------------------------------------------------------
1 | h4 Magazines
2 |
3 | .row
4 | .col-sm-4
5 | form.well#mags-form
6 | .form-group
7 | label Name
8 | input.form-control(name="name",type="text")
9 | .form-group
10 | label Volume
11 | input.form-control(name="vol",type="number")
12 | .form-group
13 | label Price
14 | input.form-control(name="price",type="number")
15 | button.btn.btn-primary(type="submit") Save
16 | button.btn.btn-default Reset
17 |
18 | .col-sm-8
19 | table.table
20 | thead: tr
21 | th Name
22 | th Vol
23 | th Price
24 | th Actions
25 | tbody
26 | each mag in mags
27 | tr
28 | td= mag.name
29 | td= mag.vol
30 | td= mag.price
31 | td
32 | a.btn.btn-primary edit
33 | |
34 | a.btn.btn-danger delete
--------------------------------------------------------------------------------
/week8/hangout/views/index.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Resource Test
4 | link(rel="stylesheet",href="lib/bootstrap/dist/css/bootstrap.css")
5 | body
6 |
7 |
8 | .container
9 |
10 | h1 Ultra Cool Publisher
11 | ul.nav.nav-tabs.nav-pills
12 | li.active: a(href="#mags", data-toggle="tab") Magazines
13 | li: a(href="#users", data-toggle="tab") Users
14 | li: a(href="#subs", data-toggle="tab") Subscriptions
15 |
16 | .tab-content
17 | .active.tab-pane#mags
18 |
19 | .tab-pane#users
20 |
21 | .tab-pane#subs
22 |
23 |
24 |
25 | script(src="lib/jquery/dist/jquery.js")
26 | script(src="lib/q/q.js")
27 | script(src="lib/bootstrap/dist/js/bootstrap.js")
28 | script(src="lib/jade/jade.js")
29 | //- app files
30 | script(src="js/resource.js")
31 | script(src="js/init.js")
32 |
33 |
--------------------------------------------------------------------------------
/week5/hangout/css/style.css:
--------------------------------------------------------------------------------
1 |
2 | input#task-name {
3 | width: 600px;
4 | height: 30px;
5 | line-height: 30px;
6 | font-size: 18px;
7 | padding: 5px;
8 | }
9 |
10 | ul#tasks-list {
11 | list-style-type: none;
12 | width: 600px;
13 | padding-left: 0px;
14 | }
15 |
16 |
17 | ul#tasks-list li {
18 | width: 100%;
19 | height: 24px;
20 | line-height: 24px;
21 | font-size: 16px;
22 | }
23 |
24 | input#task-name, ul#tasks-list li {
25 | border: 1px solid #AAA;
26 | margin-top: 5px;
27 | border-radius: 5px;
28 | }
29 |
30 | li.finished {
31 | text-decoration: line-through;
32 | }
33 |
34 | #tasks-list li i.removeTask {
35 | float: right;
36 | height: 24px;
37 | line-height: 24px;
38 | margin-right: 5px;
39 | }
40 |
41 | #tasks-list li i.finishTask {
42 | float: left;
43 | height: 24px;
44 | line-height: 24px;
45 | margin-left: 5px;
46 | }
--------------------------------------------------------------------------------
/week6/hangout1/public/css/style.css:
--------------------------------------------------------------------------------
1 |
2 | input#task-name {
3 | width: 600px;
4 | height: 30px;
5 | line-height: 30px;
6 | font-size: 18px;
7 | padding: 5px;
8 | }
9 |
10 | ul#tasks-list {
11 | list-style-type: none;
12 | width: 600px;
13 | padding-left: 0px;
14 | }
15 |
16 |
17 | ul#tasks-list li {
18 | width: 100%;
19 | height: 24px;
20 | line-height: 24px;
21 | font-size: 16px;
22 | }
23 |
24 | input#task-name, ul#tasks-list li {
25 | border: 1px solid #AAA;
26 | margin-top: 5px;
27 | border-radius: 5px;
28 | }
29 |
30 | li.finished {
31 | text-decoration: line-through;
32 | }
33 |
34 | #tasks-list li i.removeTask {
35 | float: right;
36 | height: 24px;
37 | line-height: 24px;
38 | margin-right: 5px;
39 | }
40 |
41 | #tasks-list li i.finishTask {
42 | float: left;
43 | height: 24px;
44 | line-height: 24px;
45 | margin-left: 5px;
46 | }
--------------------------------------------------------------------------------
/week6/hangout1_full/views/index.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title Week6 REST TODO
4 | link(rel="stylesheet", type="text/css", href="lib/fontawesome/css/font-awesome.css")
5 | link(rel="stylesheet", type="text/css", href="css/style.css")
6 | body
7 |
8 | form#new-task-form
9 | input#task-name(type="text", name="name", placeholder="Add new task")
10 | input#task-id(type="hidden", name="id", value="")
11 |
12 | ul#tasks-list
13 |
14 | //- 3rd party libs
15 | script(type="text/javascript",src="lib/jquery/dist/jquery.min.js")
16 | script(type="text/javascript",src="lib/jqueryui/jquery-ui.min.js")
17 |
18 | //- our app
19 | script(type="text/javascript",src="js/taskModel.js")
20 | script(type="text/javascript",src="js/tasksView.js")
21 | script(type="text/javascript",src="js/app.js")
22 | script(type="text/javascript",src="js/init.js")
--------------------------------------------------------------------------------
/week6/hangout1_full/public/css/style.css:
--------------------------------------------------------------------------------
1 |
2 | input#task-name {
3 | width: 600px;
4 | height: 30px;
5 | line-height: 30px;
6 | font-size: 18px;
7 | padding: 5px;
8 | }
9 |
10 | ul#tasks-list {
11 | list-style-type: none;
12 | width: 600px;
13 | padding-left: 0px;
14 | }
15 |
16 |
17 | ul#tasks-list li {
18 | width: 100%;
19 | height: 24px;
20 | line-height: 24px;
21 | font-size: 16px;
22 | }
23 |
24 | input#task-name, ul#tasks-list li {
25 | border: 1px solid #AAA;
26 | margin-top: 5px;
27 | border-radius: 5px;
28 | }
29 |
30 | li.finished {
31 | text-decoration: line-through;
32 | }
33 |
34 | #tasks-list li i.removeTask, #tasks-list li i.editTask{
35 | float: right;
36 | height: 24px;
37 | line-height: 24px;
38 | margin-right: 5px;
39 | }
40 |
41 | #tasks-list li i.finishTask {
42 | float: left;
43 | height: 24px;
44 | line-height: 24px;
45 | margin-left: 5px;
46 | }
--------------------------------------------------------------------------------
/week8/2-rest-resource/public/js/init.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | var student = new Resource("http://192.168.0.66:3000/api/students");
3 |
4 | var displayResult = function(res){
5 | console.log(res)
6 |
7 | return res;
8 | }
9 |
10 | var getId = function(data){
11 |
12 | var id = data._id;
13 |
14 | return id;
15 | };
16 |
17 | // query
18 |
19 | // create
20 | var data = {
21 | name: "Gospodin",
22 | email: "gospodin@gospodinoff.cc"
23 | };
24 |
25 | var newData = {
26 | name: "Peter"
27 | }
28 | student.query()
29 | .then(displayResult)
30 | .then(function(){
31 | return student.create(data);
32 | })
33 | .then(displayResult)
34 | .then(getId)
35 | .then(function(id){
36 | return student.update(id, newData);
37 | })
38 | .then(displayResult)
39 | .then(function(){
40 | return student.query();
41 | })
42 | .then(displayResult);
43 |
44 | })
--------------------------------------------------------------------------------
/week8/rest-example/public/js/init.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | var student = new Resource("http://192.168.0.66:3000/api/students");
3 |
4 | var displayResult = function(res){
5 | console.log(res)
6 |
7 | return res;
8 | }
9 |
10 | var getId = function(data){
11 |
12 | var id = data._id;
13 |
14 | return id;
15 | };
16 |
17 | // query
18 |
19 | // create
20 | var data = {
21 | name: "Gospodin",
22 | email: "gospodin@gospodinoff.cc"
23 | };
24 |
25 | var newData = {
26 | name: "Peter"
27 | }
28 | student.query()
29 | .then(displayResult)
30 | .then(function(){
31 | return student.create(data);
32 | })
33 | .then(displayResult)
34 | .then(getId)
35 | .then(function(id){
36 | return student.update(id, newData);
37 | })
38 | .then(displayResult)
39 | .then(function(){
40 | return student.query();
41 | })
42 | .then(displayResult);
43 |
44 | })
--------------------------------------------------------------------------------
/week4/hangout/interface.js:
--------------------------------------------------------------------------------
1 | // s - query
2 | // do something with elements
3 |
4 | s(document).on("DOMContentLoaded", function() {
5 | console.log("DOM Loaded");
6 |
7 | var container = s("#container"),
8 | lists = s("#lists"),
9 | hideButton = c("button"),
10 | showButton = c("button");
11 |
12 | hideButton
13 | .addClass("btn")
14 | .attr("id", "hide-button")
15 | .text("Hide")
16 | .appendTo(container);
17 |
18 | showButton
19 | .addClass("btn")
20 | .attr("id", "show-button")
21 | .text("Show!")
22 | .appendTo(container);
23 |
24 | s("button").on("click", function(event) {
25 | console.log(this);
26 | console.log(s(this).attr("id"));
27 | var id = s(this).attr("id");
28 |
29 | if(id === "show-button") {
30 | lists.show();
31 | } else if(id === "hide-button") {
32 | lists.hide();
33 | }
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/week6/hangout1_full/public/js/init.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | $(document).ready(function(){
4 | // init stuff
5 |
6 | $("ul#tasks-list").sortable({
7 | start: function(event, ui) {
8 | var fromIndex = ui.item.index();
9 | ui.item.data('fromIndex', fromIndex);
10 | },
11 | update: function (event, ui) {
12 | var fromIndex = ui.item.data('fromIndex');
13 | var toIndex = ui.item.index();
14 | TodoApp.moveTask(fromIndex, toIndex);
15 |
16 | }
17 | });
18 |
19 |
20 | $("#new-task-form").submit(function(){
21 |
22 | var taskName = $("#task-name").val();
23 | $("#task-name").val("")
24 |
25 | var task = {
26 | name: taskName
27 | };
28 |
29 | if($("#task-id").val() !== ""){
30 | task._id = $("#task-id").val();
31 | $("#task-id").val("");
32 | }
33 |
34 | TodoApp.saveTask(task);
35 |
36 | event.preventDefault();
37 | })
38 |
39 | TodoApp.init();
40 |
41 |
42 |
43 | })
--------------------------------------------------------------------------------
/week1/hangout/posts.json:
--------------------------------------------------------------------------------
1 | {
2 | "post1" : {
3 | "img": "img/post1.png",
4 | "title": "Optimizing Investing, Blood, Hormones, and Life (Podcast Double-Header: #63 and #65)",
5 | "text": "[DISCLAIMER: I’m not a doctor, nor do I play one on the Internet. Speak with a medical professional before doing anything medical-related, m’kay?]There is something here for everyone.This post details two jam-packed discussions — one with world-renowned macro investors and investment strategists (Mark Hart and Raoul Pal), and another with a top performance doc you’ve referenced hundreds of times (Peter Attia, MD).In both, we address dozens of topics."
6 | },
7 | "post2" : {
8 | "img": "img/post2.jpg",
9 | "title": "The Good, The Bad, and The Ugly of CrossFit",
10 | "text": "This post delves into the good, the bad, and the ugly of all things CrossFit. It answers many important questions"
11 | }
12 | }
--------------------------------------------------------------------------------
/week6/hangout2/views/layout.jade:
--------------------------------------------------------------------------------
1 | html
2 | head
3 | title FunkyTOWN Ibiza
4 | link(rel="stylesheet",type="text/css",href="/lib/bootstrap/dist/css/bootstrap.css")
5 | link(rel="stylesheet",type="text/css",href="/lib/fontawesome/css/font-awesome.css")
6 | link(rel="stylesheet",type="text/css",href="/css/style.css")
7 | body
8 |
9 | nav.navbar.navbar-inverse
10 | .container-fluid
11 | .navbar-header
12 | button.navbar-toggle.collapsed(data-toggle="collapse",data-target="#my-menu")
13 | i.fa.fa-bars
14 | a(href="/").navbar-brand FunkyTOWN Ibiza
15 |
16 | .collapse.navbar-collapse#my-menu
17 | ul.nav.navbar-nav.navbar-left
18 | li: a(href="/events") Events
19 | li: a(href="/artists") Artists
20 |
21 | block content
22 |
23 |
24 |
25 | //- scripts
26 | script(src="/lib/jquery/dist/jquery.min.js")
27 | script(src="/lib/bootstrap/dist/js/bootstrap.js")
28 |
29 | block scripts
30 |
--------------------------------------------------------------------------------
/week5/hangout/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hangout Week5 TODO App
4 |
5 |
6 |
7 |
8 |
9 |
12 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/week3/README.md:
--------------------------------------------------------------------------------
1 | # Basic JavaScript OOP & Working with the DOM
2 |
3 | Here are two very good guides for starting with JavaScript OOP from the Mozilla Dev Network:
4 |
5 | * [Introduction to Object Oriented JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript)
6 | * [Details of the Object Model in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model)
7 | * [What is that object prototype in JavaScript?](http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work)
8 | * [The chapter from Eloquent JavaScript](http://eloquentjavascript.net/06_object.html)
9 | * There are good slides from John Resig for "advanced JavaScript" - http://ejohn.org/apps/learn - you can check it!
10 | * [Example for creating object with JavaScript literal](materials/person.js)
11 | * [Examples for Function.prototype.call and Function.prototype.apply](materials/call_apply.js)
12 | * [Examples for closures](materials/closure.js)
13 |
--------------------------------------------------------------------------------
/week1/README.md:
--------------------------------------------------------------------------------
1 | # Week 1 Start
2 |
3 | ## Prerequisites
4 |
5 | ### Environment
6 | - Node Installed
7 | - For Linux Users - Search Google for: "Digital Ocean install node via nvm"
8 | - Git Installed
9 | - IDE - minimum Sublime
10 |
11 | ### Knowledge
12 | - HTML, CSS (required)
13 | - Basic programming knowledge (recommended)
14 | - Data types, Operations, Arrays, Dictionaries, OOP
15 |
16 | ## Before you start
17 |
18 | - Create a folder for the course, preferably in a Projects folder in your home folder
19 | ```sh
20 | # in linux
21 | $ mkdir -p ~/Projects/frontendjs/week1
22 | $ cd ~/Projects/frontendjs
23 | ```
24 |
25 | - init a git repo that you will add all your tasks each week
26 | ```sh
27 | # init the repo
28 | $ git init
29 | # create an empty file to be added to the repo
30 | $ touch README.md
31 | # add all
32 | $ git add .
33 | # your first commit
34 | $ git commit -m "initial commit"
35 | ```
36 |
37 | - create a repo in github and follow the instructions there to link them
38 |
39 | Next up - Hello Node
--------------------------------------------------------------------------------
/week3/5-Event-Bus/README.md:
--------------------------------------------------------------------------------
1 | ## An Event bus
2 |
3 | Create a single object, that behaves like an event bus! We can attach custom events with callbacks to them and also trigger those events.
4 |
5 | The object should have the following __public__ methods:
6 |
7 | * `.on(eventName, callback)` - adds the given `callback` for the given `eventName`
8 | * `.remove(eventName)` - removes all callbacks for the given `eventName`
9 | * `.trigger(eventName)` - fires the given `eventName` which calls all callbacks for that event
10 |
11 | __Everything else, regarding the implementation of the event bus should be private!__
12 |
13 | Here is an example usage:
14 |
15 | ```javascript
16 | var bus = { // implementation }
17 |
18 | bus.on("PANIC_EVENT", function() {
19 | console.log("PANIC_EVENT HAPPENED!")
20 | });
21 |
22 | bus.on("PANIC_EVENT", function() {
23 | console.log("PANIC_EVENT HAPPENED AGAIN!");
24 | });
25 | ```
26 |
27 | Now, if we call:
28 |
29 | ```javascript
30 | bus.trigger("PANIC_EVENT");
31 | ```
32 |
33 | This will log:
34 |
35 | ```
36 | "PANIC_EVENT HAPPENED!"
37 | "PANIC_EVENT HAPPENED AGAIN!"
38 | ```
39 |
--------------------------------------------------------------------------------
/week3/4-Queue/README.md:
--------------------------------------------------------------------------------
1 | # A classic queue
2 |
3 | In a file called `queue.js` implement the following:
4 |
5 | Using a literal object - `{}` - create an object, that behaves like a queue.
6 |
7 | For example, if we store our queue like this:
8 |
9 | ```javascript
10 | var queue = {
11 | // implementation
12 | }
13 | ```
14 |
15 | It should have the following methods:
16 |
17 | * `queue.push(item)` - pushes the item to the queue
18 | * `queue.pop()` - returns the item on top of the queue
19 | * `queue.isEmpty()` - returns true if the queue is empty
20 |
21 | Here is an example:
22 |
23 | ```javascript
24 | function bfs(graph, start, end) {
25 | prev = {};
26 | visited = [start];
27 | queue.push(start);
28 |
29 | while(!queue.isEmpty()) {
30 | var node = queue.pop();
31 |
32 | if(node.is(end)) {
33 | // do something
34 | return
35 | }
36 |
37 | graph.getNeighbours(node).forEach(function(n) {
38 | if(visited.indexOf(n) !== -1) {
39 | visited.push(n);
40 | prev[n] = node;
41 |
42 | queue.push(n);
43 | }
44 | });
45 |
46 | }
47 | }
48 | ```
49 |
--------------------------------------------------------------------------------
/week6/hangout2/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 |
7 | // create app
8 | var app = express()
9 |
10 |
11 | // configuration and middleware
12 | app.use(express.static('public'));
13 | app.set('view engine', 'jade');
14 |
15 |
16 | // routes
17 | app.get('/', function (req, res) {
18 | res.render('index');
19 | })
20 |
21 | // listen for files: /post -> /views/post.jade
22 | app.get("/:fileName", function(req, res, next){
23 | if(req.params && req.params.fileName){
24 | var fileName = req.params.fileName.replace(".html","");
25 |
26 | // if jade file exists
27 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
28 | res.render(fileName);
29 | // if post is in posts
30 | } else {
31 | next();
32 | }
33 |
34 | } else {
35 | next();
36 | }
37 | })
38 |
39 |
40 |
41 | // set up server
42 | var server = app.listen(3000, function () {
43 |
44 | var host = server.address().address
45 | var port = server.address().port
46 |
47 | console.log('Example app listening at http://%s:%s', host, port)
48 |
49 | })
--------------------------------------------------------------------------------
/week6/2-hobby-site/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 |
7 | // create app
8 | var app = express()
9 |
10 |
11 | // configuration and middleware
12 | app.use(express.static('public'));
13 | app.set('view engine', 'jade');
14 |
15 |
16 | // routes
17 | app.get('/', function (req, res) {
18 | res.render('index');
19 | })
20 |
21 | // listen for files: /post -> /views/post.jade
22 | app.get("/:fileName", function(req, res, next){
23 | if(req.params && req.params.fileName){
24 | var fileName = req.params.fileName.replace(".html","");
25 |
26 | // if jade file exists
27 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
28 | res.render(fileName);
29 | // if post is in posts
30 | } else {
31 | next();
32 | }
33 |
34 | } else {
35 | next();
36 | }
37 | })
38 |
39 |
40 |
41 | // set up server
42 | var server = app.listen(3000, function () {
43 |
44 | var host = server.address().address
45 | var port = server.address().port
46 |
47 | console.log('Example app listening at http://%s:%s', host, port)
48 |
49 | })
--------------------------------------------------------------------------------
/week6/hangout1/public/js/taskModel.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | var TaskModel = (function() {
4 |
5 | // private vars
6 | var tasks = [];
7 |
8 | var getTasks = function(){
9 | return tasks;
10 | }
11 |
12 | var create = function(task, cb){
13 |
14 | $.ajax({
15 | url: "/api/tasks/",
16 | data: task,
17 | success: function(){
18 | read(cb);
19 | },
20 | method: "POST"
21 | });
22 |
23 | }
24 |
25 | var read = function(cb){
26 | // empty the current list
27 | tasks = [];
28 | // add tasks from api
29 | $.get("http://localhost:3000/api/tasks", function(data){
30 | tasks = data.list;
31 | cb(tasks);
32 | })
33 | }
34 |
35 | var update = function(id, task, cb){
36 | $.ajax({
37 | url: "/api/tasks/"+id,
38 | data: task,
39 | success: function(){
40 | read(cb)
41 | },
42 | method: "PUT"
43 | });
44 | }
45 |
46 | var remove = function(id, cb){
47 | $.ajax({
48 | url: "/api/tasks/"+id,
49 | success: function(){
50 | read(cb)
51 | },
52 | method: "DELETE"
53 | });
54 | }
55 |
56 | return {
57 | getTasks: getTasks,
58 | create: create,
59 | read: read,
60 | update: update,
61 | remove: remove
62 | }
63 | })();
64 |
--------------------------------------------------------------------------------
/week6/hangout1/public/js/app.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var TodoApp = (function() {
4 |
5 | var init = function(){
6 | TaskModel.read(function(tasks){
7 | TasksView.update(tasks);
8 | })
9 | }
10 |
11 | // adds a new task to the collection
12 | var addTask = function(taskName) {
13 | TaskModel.create({
14 | name: taskName,
15 | finished: false
16 | },function(tasks){
17 | TasksView.update(tasks);
18 | })
19 | };
20 |
21 |
22 | // updates the task
23 | var finishTask = function(task) {
24 |
25 | task.finished = !task.finished;
26 |
27 | TaskModel.update(task._id, task,function(tasks){
28 | TasksView.update(tasks);
29 | })
30 | };
31 |
32 | var removeTask = function(task) {
33 | TaskModel.remove(task._id,function(tasks){
34 | TasksView.update(tasks);
35 | })
36 | }
37 | /*
38 | var moveTask = function(fromIndex, toIndex){
39 |
40 | // get the el and remove it from tasks
41 | var elToMove = tasks.splice(fromIndex, 1)[0];
42 |
43 | // push it to the new index
44 | tasks.splice(toIndex, 0, elToMove);
45 |
46 | }
47 | */
48 |
49 | return {
50 | addTask: addTask,
51 | finishTask: finishTask,
52 | removeTask: removeTask,
53 | init: init
54 | }
55 | })();
--------------------------------------------------------------------------------
/week3/2-Point/points.js:
--------------------------------------------------------------------------------
1 | function MutablePoint3d(x, y, z) {
2 | this.getX = function() {
3 | return x;
4 | }
5 |
6 | this.getY = function() {
7 | return y;
8 | }
9 |
10 | this.getZ = function() {
11 | return z;
12 | }
13 |
14 | this.move = function(dx, dy, dz) {
15 | x += dx;
16 | y += dy;
17 | z += dz;
18 | }
19 | }
20 |
21 | MutablePoint3d.prototype.toString = function() {
22 | return "(" + [this.getX(), this.getY(), this.getZ()].join(", ") + ")";
23 | }
24 |
25 |
26 | function ImmutablePoint3d(x, y, z) {
27 | this.getX = function() {
28 | return x;
29 | }
30 |
31 | this.getY = function() {
32 | return y;
33 | }
34 |
35 | this.getZ = function() {
36 | return z;
37 | }
38 | }
39 |
40 | ImmutablePoint3d.prototype.move = function(dx, dy, dz) {
41 | return new ImmutablePoint3d(this.getX() + dx, this.getY() + dy, this.getZ() + dz);
42 | }
43 |
44 | ImmutablePoint3d.prototype.toString = function() {
45 | return "(" + [this.getX(), this.getY(), this.getZ()].join(", ") + ")";
46 | }
47 |
48 | var p2 = new ImmutablePoint3d(0, 0, 0);
49 | var result = p2.move(0, 0, -1);
50 |
51 | console.log(p2.toString());
52 | console.log(result.toString());
53 |
54 |
--------------------------------------------------------------------------------
/week8/hangout/public/js/resource.js:
--------------------------------------------------------------------------------
1 | function Resource(url) {
2 | this.url = url;
3 | }
4 |
5 | // api/students -> GET, POST
6 |
7 | Resource.prototype.query = function(queryParams) {
8 |
9 | return Q($.ajax({
10 | url: this.url, // api endpoint
11 | method: "get", // method
12 | data: queryParams,
13 | dataType: "json" // data type
14 | }));
15 | }
16 |
17 | Resource.prototype.create = function(data) {
18 | return Q($.ajax({
19 | url: this.url, // api endpoint
20 | method: "post", // method
21 | data: data,
22 | dataType: "json" // data type
23 | }));
24 | }
25 |
26 | // api/students/:id -> GET, PUT, DELETE
27 |
28 | Resource.prototype.view = function(id) {
29 | return Q($.get(this.url+"/"+id));
30 | }
31 |
32 | Resource.prototype.update = function(id, data) {
33 | return Q($.ajax({
34 | url: this.url+"/"+id, // api endpoint
35 | method: "put", // method
36 | data: data,
37 | dataType: "json" // data type
38 | }));
39 | }
40 |
41 | Resource.prototype.delete = function(id) {
42 | return Q($.ajax({
43 | url: this.url+"/"+id, // api endpoint
44 | method: "delete",
45 | dataType: "json" // data type
46 | }));
47 | }
--------------------------------------------------------------------------------
/week8/rest-example/public/js/resource.js:
--------------------------------------------------------------------------------
1 | function Resource(url) {
2 | this.url = url;
3 | }
4 |
5 | // api/students -> GET, POST
6 |
7 | Resource.prototype.query = function(queryParams) {
8 |
9 | return Q($.ajax({
10 | url: this.url, // api endpoint
11 | method: "get", // method
12 | data: queryParams,
13 | dataType: "json" // data type
14 | }));
15 | }
16 |
17 | Resource.prototype.create = function(data) {
18 | return Q($.ajax({
19 | url: this.url, // api endpoint
20 | method: "post", // method
21 | data: data,
22 | dataType: "json" // data type
23 | }));
24 | }
25 |
26 | // api/students/:id -> GET, PUT, DELETE
27 |
28 | Resource.prototype.view = function(id) {
29 | return Q($.get(this.url+"/"+id));
30 | }
31 |
32 | Resource.prototype.update = function(id, data) {
33 | return Q($.ajax({
34 | url: this.url+"/"+id, // api endpoint
35 | method: "put", // method
36 | data: data,
37 | dataType: "json" // data type
38 | }));
39 | }
40 |
41 | Resource.prototype.delete = function(id) {
42 | return Q($.ajax({
43 | url: this.url+"/"+id, // api endpoint
44 | method: "delete",
45 | dataType: "json" // data type
46 | }));
47 | }
--------------------------------------------------------------------------------
/week6/hangout1_full/public/js/taskModel.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | var TaskModel = (function() {
4 |
5 | // private vars
6 | var tasks = [];
7 |
8 | var getTasks = function(){
9 | return tasks;
10 | }
11 |
12 | var setTasks = function(_tasks){
13 | tasks = _tasks;
14 | }
15 |
16 | var create = function(task, cb){
17 |
18 | $.ajax({
19 | url: "/api/tasks/",
20 | data: task,
21 | success: function(){
22 | read(cb);
23 | },
24 | method: "POST"
25 | });
26 | }
27 |
28 | var read = function(cb){
29 | // empty the current list
30 | tasks = [];
31 | // add tasks from api
32 | $.get("http://localhost:3000/api/tasks", function(data){
33 | tasks = data.list;
34 | cb(tasks);
35 | })
36 | }
37 |
38 | var update = function(id, task, cb){
39 | $.ajax({
40 | url: "/api/tasks/"+id,
41 | data: task,
42 | success: function(){
43 | read(cb)
44 | },
45 | method: "PUT"
46 | });
47 | }
48 |
49 | var remove = function(id, cb){
50 | $.ajax({
51 | url: "/api/tasks/"+id,
52 | success: function(){
53 | read(cb)
54 | },
55 | method: "DELETE"
56 | });
57 | }
58 |
59 | return {
60 | getTasks: getTasks,
61 | setTasks: setTasks,
62 | create: create,
63 | read: read,
64 | update: update,
65 | remove: remove
66 | }
67 | })();
68 |
--------------------------------------------------------------------------------
/week1/hangout/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var posts = require("./posts.json");
7 |
8 | // create app
9 | var app = express()
10 |
11 |
12 | // configuration and middleware
13 | app.use(express.static('public'));
14 | app.set('view engine', 'jade');
15 |
16 |
17 | // routes
18 | app.get('/', function (req, res) {
19 | res.render('index', {posts: posts});
20 | })
21 |
22 | // listen for files: /post -> /views/post.jade
23 | app.get("/:fileName", function(req, res, next){
24 | if(req.params && req.params.fileName){
25 | var fileName = req.params.fileName.replace(".html","");
26 |
27 | // if jade file exists
28 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
29 | res.render(fileName);
30 | // if post is in posts
31 | } else if (posts[fileName]) {
32 | res.render("post", {post: posts[fileName]});
33 | // else continue
34 | } else {
35 | next();
36 | }
37 |
38 | } else {
39 | next();
40 | }
41 | })
42 |
43 |
44 |
45 | // set up server
46 | var server = app.listen(3000, function () {
47 |
48 | var host = server.address().address
49 | var port = server.address().port
50 |
51 | console.log('Example app listening at http://%s:%s', host, port)
52 |
53 | })
--------------------------------------------------------------------------------
/week4/2-DOM-Todo/README.md:
--------------------------------------------------------------------------------
1 | # Really dead simple Todo list with DOM
2 |
3 | Every JavaScripter should implement at least one todo list in his life!
4 |
5 | We are going to honor this, right now.
6 |
7 | Again, use the pure DOM + JavaScript API, but this time, write whatever HTML and CSS you like. Think of how you can achieve that.
8 |
9 | We want to have the following feature:
10 |
11 | **A userinput, where we enter text, click the `Add` button and the task goes to a list of tasks.**
12 |
13 | That's it.
14 |
15 | Here is a mockup:
16 |
17 | 
18 |
19 | ## How to take a value from an input
20 |
21 | Consider the following HTML:
22 |
23 | ```html
24 |
25 |
26 |
27 | Add Task!
28 |
29 |
30 |
31 |
32 | ```
33 |
34 | And the following JavaScript:
35 |
36 | ```javascript
37 | window.onload = function() {
38 | var button = document.getElementById("add-task-button");
39 | button.onclick = function(event) {
40 | var input = document.getElementById("task-input");
41 |
42 | console.log(input.value);
43 | };
44 | };
45 | ```
46 |
47 | They are called `example.html` and `example.js`. Run them and check the console, by typing and clickin on the button.
48 |
--------------------------------------------------------------------------------
/week6/hangout1/public/js/tasksView.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | var TasksView = (function() {
5 |
6 | var update = function(tasks) {
7 |
8 | var tasksList = $("#tasks-list");
9 |
10 | // clear the contents
11 | tasksList.empty();
12 |
13 | // loop through the tasks
14 | tasks.forEach(function(task){
15 |
16 | var taskId = task._id;
17 | var _task = task;
18 |
19 | var liTask = $(" ");
20 |
21 | // finish task button
22 | var chkFinishTask = $(" ");
23 | chkFinishTask.addClass("finishTask fa fa-square-o");
24 | chkFinishTask.click(function(){
25 | TodoApp.finishTask(_task);
26 | })
27 |
28 | // remove task button
29 | var chkRemoveTask = $(" ");
30 | chkRemoveTask.addClass("removeTask fa fa-trash");
31 | chkRemoveTask.click(function(){
32 | TodoApp.removeTask(_task);
33 | })
34 |
35 | if(task.finished === true){
36 | chkFinishTask.toggleClass("fa-square-o fa-check-square-o");
37 | liTask.addClass("finished");
38 | }
39 |
40 | // append contents to li
41 | liTask.append(chkFinishTask);
42 | liTask.append(task.name);
43 | liTask.append(chkRemoveTask);
44 |
45 | // append each task
46 | tasksList.append(liTask);
47 | })
48 |
49 | // attach event listeners
50 |
51 | };
52 |
53 | return {
54 | update: update
55 | };
56 |
57 | })()
--------------------------------------------------------------------------------
/Application/1-Mask-Words/README.md:
--------------------------------------------------------------------------------
1 | # Problem 1 - Mask Out Words
2 |
3 | In a programming language of your choice, implement the following function/method:
4 |
5 | ```
6 | maskOutWords(words, text)
7 | ```
8 |
9 | If you read type declarations well, here it is:
10 |
11 | ```haskell
12 | maskOutWords :: [String] -> String -> String
13 | ```
14 |
15 | Where:
16 |
17 | * `words` is a list of words (strings)
18 | * `text` is a string, that may contain newlines - `\n`
19 |
20 |
21 | The function should return a new text, where each matching word from `words` is replaced by the same number of characters `*`.
22 |
23 | Consider the following things:
24 |
25 | * **All matching should be case insensitive!**
26 | * Take care of words that end with `,` or `.` - they should be matached, without the punctiation.
27 |
28 | For example, if we have the following arguments:
29 |
30 | * `words = ["PHP"]`
31 | * `text = "We love coding in PHP!\nThis makes us really productive"`
32 |
33 | The result is going to be:
34 |
35 | ```
36 | "We love coding in ***!\nThis makes us really productive"
37 | ```
38 |
39 | Another example will be:
40 |
41 | * `words = ["yesterday", "Dog", "food", "walk"]`
42 | * `text = "Yesterday, I took my dog for a walk.\n It was crazy! My dog wanted only food."`
43 |
44 | The result is going to be:
45 |
46 | ```
47 | ********, I took my *** for a ****.\n It was crazy! My *** wanted only ****."
48 | ```
49 |
--------------------------------------------------------------------------------
/week7/1-students-crud/README.md:
--------------------------------------------------------------------------------
1 | # Week 7 : Task 1 Students CRUD
2 |
3 | ## Premise
4 | Using what we've learned so far we are going to create a full-stack app.
5 | We will
6 | - create a server that provides a RESTful api following this tutorial [Build RESTful APIs with Node and Express](http://alexmilanov.com/restful-apis-node-express)
7 | - modify it to use a collection instead of the structure used in the tutorial.
8 | ```js
9 | var students = [{
10 | id: 1,
11 | name: "Pesho",
12 | email: "pesho@abv.bg"
13 | }]
14 | ```
15 | - The endpoints should be at /api/students instead of /users
16 | - test the API with the chrome extension [Advanced REST Client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo)
17 | - Finally build a front-end client using what we've learned with jQuery
18 |
19 |
20 | ## Cheat sheets
21 |
22 | ### Get index by id
23 | ```js
24 | function getIndexById(collection, id){
25 | var docIndex = -1;
26 | collection.forEach(function(item, index){
27 | if(item["id"] === id){
28 | docIndex = index;
29 | }
30 | })
31 | return docIndex;
32 | }
33 | ```
34 |
35 | ### jQuery API Calls
36 | ```js
37 | // do get request with $.get
38 | $.get("/api/students/",function(students){
39 |
40 | })
41 | // post, put & delete via
42 | $.ajax({
43 | url: "/api/students/1", // api endpoint
44 | method: "put", // method
45 | data: { // data to send
46 | name: "Pesho",
47 | },
48 | dataType: "json" // data type
49 | }).done(function(result){
50 |
51 | })
--------------------------------------------------------------------------------
/Application/2-A-Simple-Logger/README.md:
--------------------------------------------------------------------------------
1 | # Problem 2 - A simple logger
2 |
3 | In a language of your choice, implement the following things:
4 |
5 | ## The interface
6 |
7 | Make an interface, called `MyLogger` with only 1 method - `log(level, message)`
8 |
9 | The two arguments should be:
10 |
11 | * `level` - an integer, from 1 to 3.
12 | * 1 means that your are logging with `INFO` level.
13 | * 2 means that you are logging with `WARNING` level.
14 | * 3 means that you are logging with `PLSCHECKFFS` level.
15 | * `message` is a string, that you are logging.
16 |
17 | There is a rule of how to make the log message, regardless where you are saving it:
18 |
19 | ```
20 | {LOG_LEVEL_STRING}::{TIMESTAMP}::{MESSAGE}
21 | ```
22 |
23 | For example, if we log with `level = 1`, and `message = "Hello World"`, this will produce the following line:
24 |
25 | ```
26 | INFO::2015-02-02T01:43:19+00:00::Hello World
27 | ```
28 |
29 | [The timestamp should be in ISO 8901 format.](http://en.wikipedia.org/wiki/ISO_8601)
30 |
31 | Make 3 different classes, that implement the interface `MyLogger`:
32 |
33 | ## `ConsoleLogger`
34 |
35 | The `ConsoleLogger` should log the messages directly to the console.
36 |
37 | ## `FileLogger`
38 |
39 | The `FileLogger` should log the messages to a given file.
40 |
41 | ## `HTTPLogger`
42 |
43 | The `HTTPLogger` shoud log the messages via a POST request to a given HTTP url.
44 |
45 | ## Examples
46 |
47 | For each logger, make sure to include examples - scripts or tests that show how the logging works.
48 |
--------------------------------------------------------------------------------
/week6/hangout2/public/css/inc/_layout.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | /* default layout styles */
4 | nav.navbar {
5 | #my-menu .navbar-nav li a {
6 | &:hover {
7 | background: darken($funkytown-color-light, 40%);
8 | color: lighten($funkytown-color-dark, 10%);
9 | }
10 | }
11 | }
12 |
13 |
14 | /* small screens */
15 | @media only screen and (max-width : 768px) {
16 | nav.navbar {
17 | background: url(/img/header-bg.jpg) #000 no-repeat center -38px;
18 | .navbar-brand {
19 | height: 52px;
20 | line-height: 52px;
21 | padding: 0px 10px;
22 | }
23 | #my-menu {
24 | background: lighten($funkytown-color-dark, 10%);
25 | }
26 | }
27 | }
28 |
29 | /* big screens */
30 | @media only screen and (min-width : 768px) {
31 | nav.navbar {
32 | background: url(/img/header-bg.jpg) #000 no-repeat center -25px;
33 | height: 70px;
34 | .container-fluid {
35 | padding: 0px;
36 | }
37 | .navbar-header {
38 | margin-left: 10px;
39 | width: 300px;
40 | }
41 | .navbar-brand {
42 | height: 70px;
43 | line-height: 70px;
44 | font-size: 24px;
45 | margin: 0px;
46 | padding: 0px 20px;
47 | }
48 | #my-menu {
49 | padding: 0px;
50 | .navbar-nav{
51 | margin-top: -10px;
52 | padding-left: 10px;
53 | background: lighten($funkytown-color-dark, 10%);
54 | width: 100%;
55 | display: block;
56 | height: 40px;
57 | li a {
58 | height: 40px;
59 | line-height: 40px;
60 | font-size: 18px;
61 | margin: 0px;
62 | padding: 0px 10px;
63 | }
64 | }
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/week3/2-Point/README.md:
--------------------------------------------------------------------------------
1 | # Point3D
2 |
3 | We are going to model a simple 3D point, holding `x`, `y` and `z`.
4 |
5 |
6 | With a little twist, we will make one mutable and one immutable version of that object.
7 |
8 | ## Mutable point
9 |
10 | We want to have the following things:
11 |
12 | * All the three components - `x`, `y` and `z` should be private with only getters - `getX()`, `getY()`, `getZ()`.
13 | * Our point should have a method, called `move(dx, dy, dz)`, which mutates our point in the following way: `x = x + dx`, `y = y + dy`, `z = z + dz`.
14 | * We want the `toString()` method to return a string looking like `({x}, {y}, {z})`
15 |
16 | For example:
17 |
18 | ```javascript
19 | var p1 = MutablePoint3d(0, 0, 0);
20 |
21 | p1.move(0, 0, -1);
22 |
23 | p1.getX() == 0; // true
24 | p1.getY() == 0; // true
25 | p1.getZ() == -1; // true
26 |
27 | p1.toString() == "(0, 0, -1)" // true
28 | ```
29 |
30 | ## Immutable Point
31 |
32 | The twist. We want to create a `ImmutablePoint3d` object, which behaves the same as `MutablePoint3d`.
33 |
34 | The only difference is that the `move(dx, dy, dz)` method should return a new `ImmutablePoint3d`, instead of mutating the instance.
35 |
36 | For example:
37 |
38 | ```javascript
39 | var p2 = new ImmutablePoint3d(0, 0, 0);
40 |
41 | var result = p2.move(0, 0, -1);
42 |
43 | p2.getX() == 0; // true
44 | p2.getY() == 0; // true
45 | p2.getZ() == 0; // true
46 |
47 |
48 | result.getZ() == -1; // true
49 |
50 | p2.toString() == "(0, 0, 0)" // true
51 | result.toString() == "(0, 0, -1)" // true
52 | ```
53 |
--------------------------------------------------------------------------------
/week8/hangout/public/js/init.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 |
3 | function displayWithJade(container, fileName, data){
4 | return Q($.get(fileName)).then(function(jadeString){
5 | var renderedHtml = jade.render(jadeString, data);
6 | container.html(renderedHtml);
7 | })
8 | }
9 |
10 | function getDataFromForm(form){
11 |
12 | var formArray = form.serializeArray();
13 |
14 | var data = {};
15 |
16 | formArray.forEach(function(field){
17 | data[field.name] = field.value;
18 | })
19 | return data;
20 | }
21 |
22 | // resources
23 | var mag = new Resource("/api/mags");
24 | var sub = new Resource("/api/subs");
25 | var user = new Resource("/api/users");
26 |
27 | // queries
28 | mag.query().then(function(res){
29 | var container = $("#mags");
30 | var mags = res.list;
31 |
32 | return displayWithJade(container, "/views/mags.jade", {
33 | mags: mags
34 | });
35 |
36 | }).then(function(){
37 | $("#mags-form").on("submit", function(event){
38 |
39 | var data = getDataFromForm($(this));
40 |
41 | mag.create(data).then(function(){
42 | console.log("Created Successfuly!")
43 | })
44 |
45 | event.preventDefault();
46 | })
47 |
48 | })
49 |
50 |
51 | sub.query().then(function(res){
52 | var container = $("#subs");
53 | var subs = res.list;
54 |
55 | displayWithJade(container, "/views/subs.jade", {
56 | subs: subs
57 | });
58 | })
59 |
60 | user.query().then(function(res){
61 | var container = $("#users");
62 | var users = res.list;
63 |
64 | displayWithJade(container, "/views/users.jade", {
65 | users: users
66 | });
67 | })
68 |
69 |
70 | })
--------------------------------------------------------------------------------
/week6/hangout1_full/public/js/tasksView.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | var TasksView = (function() {
5 |
6 | var update = function(tasks) {
7 |
8 | var tasksList = $("#tasks-list");
9 |
10 | // clear the contents
11 | tasksList.empty();
12 |
13 | // loop through the tasks
14 | tasks.forEach(function(task){
15 |
16 | var taskId = task._id;
17 | var _task = task;
18 |
19 | var liTask = $(" ");
20 |
21 | // finish task button
22 | var chkFinishTask = $(" ");
23 | chkFinishTask.addClass("finishTask fa fa-square-o");
24 | chkFinishTask.click(function(){
25 | TodoApp.finishTask(_task);
26 | })
27 |
28 | // remove task button
29 | var chkRemoveTask = $(" ");
30 | chkRemoveTask.addClass("removeTask fa fa-trash");
31 | chkRemoveTask.click(function(){
32 | TodoApp.removeTask(_task);
33 | })
34 |
35 | // remove task button
36 | var chkEditTask = $(" ");
37 | chkEditTask.addClass("removeTask fa fa-pencil");
38 | chkEditTask.click(function(){
39 | $("#task-name").val(_task.name);
40 | $("#task-id").val(_task._id)
41 | })
42 |
43 | if(task.finished === true){
44 | chkFinishTask.toggleClass("fa-square-o fa-check-square-o");
45 | liTask.addClass("finished");
46 | }
47 |
48 | // append contents to li
49 | liTask.append(chkFinishTask);
50 | liTask.append(task.name);
51 | liTask.append(chkRemoveTask);
52 | liTask.append(chkEditTask);
53 |
54 |
55 | // append each task
56 | tasksList.append(liTask);
57 | })
58 |
59 | // attach event listeners
60 |
61 | };
62 |
63 | return {
64 | update: update
65 | };
66 |
67 | })()
--------------------------------------------------------------------------------
/week8/hangout/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var mongoose = require("mongoose");
7 | var bodyParser = require('body-parser');
8 | var methodOverride = require('method-override');
9 |
10 | // restify
11 | var restify = require("iblokz-node-restify");
12 | var restMap = require("./data/restMap.json");
13 |
14 | // create app
15 | var app = express()
16 |
17 | // connect to db
18 | var db = mongoose.connect("mongodb://localhost/week8-subscriptions");
19 |
20 | // load model
21 | restify.loadModel(restMap, db);
22 |
23 | app.use(function(req, res, next) {
24 | res.header('Access-Control-Allow-Origin', '*');
25 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
26 | res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
27 |
28 | // intercept OPTIONS method
29 | if ('OPTIONS' == req.method) {
30 | res.send(200);
31 | }
32 | else {
33 | next();
34 | }
35 | });
36 |
37 | // configuration and middleware
38 | app.use(express.static('public'));
39 | app.set('view engine', 'jade');
40 |
41 | app.use(bodyParser.urlencoded({
42 | extended: true
43 | }));
44 | app.use(bodyParser.json());
45 | app.use(methodOverride());
46 |
47 |
48 | // routes
49 | app.get('/', function (req, res) {
50 | res.render('index');
51 | })
52 |
53 | // init routes
54 | restify.initRoutes(app,restMap,{},db);
55 |
56 | // set up server
57 | var server = app.listen(3000, function () {
58 |
59 | var host = server.address().address
60 | var port = server.address().port
61 |
62 | console.log('Example app listening at http://%s:%s', host, port)
63 |
64 | })
--------------------------------------------------------------------------------
/week8/rest-example/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var mongoose = require("mongoose");
7 | var bodyParser = require('body-parser');
8 | var methodOverride = require('method-override');
9 |
10 | // restify
11 | var restify = require("iblokz-node-restify");
12 | var restMap = require("./data/restMap.json");
13 |
14 | // create app
15 | var app = express()
16 |
17 | // connect to db
18 | var db = mongoose.connect("mongodb://localhost/week8-resource");
19 |
20 | // load model
21 | restify.loadModel(restMap, db);
22 |
23 | app.use(function(req, res, next) {
24 | res.header('Access-Control-Allow-Origin', '*');
25 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
26 | res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
27 |
28 | // intercept OPTIONS method
29 | if ('OPTIONS' == req.method) {
30 | res.send(200);
31 | }
32 | else {
33 | next();
34 | }
35 | });
36 |
37 | // configuration and middleware
38 | app.use(express.static('public'));
39 | app.set('view engine', 'jade');
40 |
41 | app.use(bodyParser.urlencoded({
42 | extended: true
43 | }));
44 | app.use(bodyParser.json());
45 | app.use(methodOverride());
46 |
47 |
48 | // routes
49 | app.get('/', function (req, res) {
50 | res.render('index');
51 | })
52 |
53 | // init routes
54 | restify.initRoutes(app,restMap,{},db);
55 |
56 | // set up server
57 | var server = app.listen(3000, function () {
58 |
59 | var host = server.address().address
60 | var port = server.address().port
61 |
62 | console.log('Example app listening at http://%s:%s', host, port)
63 |
64 | })
--------------------------------------------------------------------------------
/week8/2-rest-resource/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var mongoose = require("mongoose");
7 | var bodyParser = require('body-parser');
8 | var methodOverride = require('method-override');
9 |
10 | // restify
11 | var restify = require("iblokz-node-restify");
12 | var restMap = require("./data/restMap.json");
13 |
14 | // create app
15 | var app = express()
16 |
17 | // connect to db
18 | var db = mongoose.connect("mongodb://localhost/week8-resource");
19 |
20 | // load model
21 | restify.loadModel(restMap, db);
22 |
23 | app.use(function(req, res, next) {
24 | res.header('Access-Control-Allow-Origin', '*');
25 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
26 | res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
27 |
28 | // intercept OPTIONS method
29 | if ('OPTIONS' == req.method) {
30 | res.send(200);
31 | }
32 | else {
33 | next();
34 | }
35 | });
36 |
37 | // configuration and middleware
38 | app.use(express.static('public'));
39 | app.set('view engine', 'jade');
40 |
41 | app.use(bodyParser.urlencoded({
42 | extended: true
43 | }));
44 | app.use(bodyParser.json());
45 | app.use(methodOverride());
46 |
47 |
48 | // routes
49 | app.get('/', function (req, res) {
50 | res.render('index');
51 | })
52 |
53 | // init routes
54 | restify.initRoutes(app,restMap,{},db);
55 |
56 | // set up server
57 | var server = app.listen(3000, function () {
58 |
59 | var host = server.address().address
60 | var port = server.address().port
61 |
62 | console.log('Example app listening at http://%s:%s', host, port)
63 |
64 | })
--------------------------------------------------------------------------------
/week3/1-A-Panda/panda.js:
--------------------------------------------------------------------------------
1 | function getRandomInt(min, max) {
2 | return Math.floor(Math.random() * (max - min)) + min;
3 | }
4 |
5 | function Panda(name, sex) {
6 | this.name = name;
7 |
8 | if(["male", "female"].indexOf(sex) === -1) {
9 | sex = "female";
10 | }
11 |
12 | this.sex = sex;
13 | this.weight = 20;
14 | this.isLazy = false;
15 | }
16 |
17 | Panda.prototype.isMale = function() {
18 | return this.sex === "male";
19 | }
20 |
21 | Panda.prototype.isFemale = function() {
22 | return this.sex === "female";
23 | }
24 |
25 | Panda.prototype.toString = function() {
26 | return [this.name, "is a", this.sex, "panda which weighs", this.weight, "kg"].join(" ");
27 | }
28 |
29 |
30 | Panda.prototype.eat = function(bamboo) {
31 | this.weight += bamboo / 2;
32 |
33 | if(this.weight >= 80 && !this.isLazy) {
34 | this.name = "Lazy Panda " + this.name;
35 | this.isLazy = true;
36 | }
37 | }
38 |
39 | Panda.prototype.mate = function(anotherPanda) {
40 | var fatherName = "";
41 | var motherName = "";
42 |
43 | if(this.isMale() && anotherPanda.isFemale()) {
44 | fatherName = this.name;
45 | motherName = anotherPanda.name
46 | } else if(this.isFemale() && anotherPanda.isMale()) {
47 | fatherName = anotherPanda.name;
48 | motherName = this.name;
49 | } else {
50 | throw {
51 | "name": "PandasCannotMate",
52 | "message": "They love each other but sadly cannot mate ;("
53 | };
54 | }
55 |
56 | var babySex = ["female", "male"][getRandomInt(0, 2)];
57 |
58 | var babyName = {
59 | "female": motherName + " " + fatherName,
60 | "male": fatherName + " " + motherName
61 | }[babySex];
62 |
63 | return new Panda(babyName, babySex);
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/week1/hangout/public/css/style.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | background: url("/img/bg.jpg") no-repeat scroll center top #1A1A1A;
4 | color: #333;
5 | font-family: Helvetica,Arial,sans-serif;
6 | font-size: 14px;
7 | }
8 |
9 | a {
10 | text-decoration: none;
11 | color: #144E9C
12 | }
13 |
14 | .container {
15 | margin: 20px auto;
16 | padding: 0px;
17 | width: 900px;
18 | }
19 |
20 | /* header */
21 |
22 | header {
23 | height: 70px;
24 | }
25 |
26 | header a {
27 | margin:0px;
28 | margin-left: 20px;
29 | height: 60px;
30 | line-height: 60px;
31 | display: block;
32 | padding: 5px;
33 | }
34 |
35 |
36 | /* section */
37 |
38 |
39 | /* section - content */
40 |
41 | section {
42 | background: url("/img/content-bg.png") repeat-y scroll 0px 0px #FFF;
43 | box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.35);
44 | padding: 20px;
45 | min-height: 100%;
46 | height: 100%;
47 | }
48 |
49 | section hr {
50 | color: rgba(0, 0, 0, 0.13);
51 | }
52 |
53 | section .content {
54 | float: left;
55 | width: 510px;
56 | }
57 |
58 |
59 | /* post */
60 | article a.title {
61 | color: #64AF1B;
62 | font-size: 28px;
63 | line-height: 30px;
64 | font-weight: bold;
65 | letter-spacing: -1px;
66 | }
67 |
68 |
69 | /* section - sidebar */
70 |
71 | .sidebar {
72 | float: right;
73 | width: 300px;
74 | }
75 |
76 | .sidebar .widget-title {
77 | font-weight: bold;
78 | margin: 0px 0px 0.5em;
79 | font-size: 16px;
80 | }
81 |
82 |
83 | .sidebar ul.widget-list {
84 | list-style: none;
85 | background: white;
86 | margin: 0px;
87 | padding: 5px 7px;
88 | border: 2px solid #8CBF1F;
89 | }
90 |
91 | .sidebar ul.li {
92 | font-size: 16px;
93 | }
94 |
95 |
--------------------------------------------------------------------------------
/week6/hangout1/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var mongoose = require("mongoose");
7 | var bodyParser = require('body-parser');
8 | var methodOverride = require('method-override');
9 |
10 | // restify
11 | var restify = require("iblokz-node-restify");
12 | var restMap = require("./data/rest.json");
13 |
14 | // create app
15 | var app = express()
16 |
17 | // connect to db
18 | var db = mongoose.connect("mongodb://localhost/todo-app");
19 |
20 | // load model
21 | restify.loadModel(restMap, db);
22 |
23 |
24 | // configuration and middleware
25 | app.use(express.static('public'));
26 | app.set('view engine', 'jade');
27 |
28 | app.use(bodyParser.urlencoded({
29 | extended: true
30 | }));
31 | app.use(bodyParser.json());
32 | app.use(methodOverride());
33 |
34 |
35 | // routes
36 | app.get('/', function (req, res) {
37 | res.render('index');
38 | })
39 |
40 | // init routes
41 | restify.initRoutes(app,restMap,{},db);
42 |
43 |
44 | // listen for files: /post -> /views/post.jade
45 | /*
46 | app.get("/:fileName", function(req, res, next){
47 | if(req.params && req.params.fileName){
48 | var fileName = req.params.fileName.replace(".html","");
49 |
50 | // if jade file exists
51 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
52 | res.render(fileName);
53 | // if post is in posts
54 | } else if (posts[fileName]) {
55 | res.render("post");
56 | // else continue
57 | } else {
58 | next();
59 | }
60 |
61 | } else {
62 | next();
63 | }
64 | })
65 | */
66 |
67 |
68 | // set up server
69 | var server = app.listen(3000, function () {
70 |
71 | var host = server.address().address
72 | var port = server.address().port
73 |
74 | console.log('Example app listening at http://%s:%s', host, port)
75 |
76 | })
--------------------------------------------------------------------------------
/week6/hangout1_full/server.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | // dependancies
4 | var express = require('express')
5 | var fs = require("fs");
6 | var mongoose = require("mongoose");
7 | var bodyParser = require('body-parser');
8 | var methodOverride = require('method-override');
9 |
10 | // restify
11 | var restify = require("iblokz-node-restify");
12 | var restMap = require("./data/rest.json");
13 |
14 | // create app
15 | var app = express()
16 |
17 | // connect to db
18 | var db = mongoose.connect("mongodb://localhost/todo-app");
19 |
20 | // load model
21 | restify.loadModel(restMap, db);
22 |
23 |
24 | // configuration and middleware
25 | app.use(express.static('public'));
26 | app.set('view engine', 'jade');
27 |
28 | app.use(bodyParser.urlencoded({
29 | extended: true
30 | }));
31 | app.use(bodyParser.json());
32 | app.use(methodOverride());
33 |
34 |
35 | // routes
36 | app.get('/', function (req, res) {
37 | res.render('index');
38 | })
39 |
40 | // init routes
41 | restify.initRoutes(app,restMap,{},db);
42 |
43 |
44 | // listen for files: /post -> /views/post.jade
45 | /*
46 | app.get("/:fileName", function(req, res, next){
47 | if(req.params && req.params.fileName){
48 | var fileName = req.params.fileName.replace(".html","");
49 |
50 | // if jade file exists
51 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
52 | res.render(fileName);
53 | // if post is in posts
54 | } else if (posts[fileName]) {
55 | res.render("post");
56 | // else continue
57 | } else {
58 | next();
59 | }
60 |
61 | } else {
62 | next();
63 | }
64 | })
65 | */
66 |
67 |
68 | // set up server
69 | var server = app.listen(3000, function () {
70 |
71 | var host = server.address().address
72 | var port = server.address().port
73 |
74 | console.log('Example app listening at http://%s:%s', host, port)
75 |
76 | })
--------------------------------------------------------------------------------
/week6/hangout2/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | .container-fluid#home
5 |
6 | .row
7 | .col-md-6.col-lg-8
8 | h2 Welcome to FunkyTOWN Ibiza
9 | .carousel.slide#funkytown-slider(data-ride="carousel")
10 | ol.carousel-indicators
11 | li.active(data-target="#funkytown-slider",data-slide-to="0")
12 | li.active(data-target="#funkytown-slider",data-slide-to="1")
13 | li.active(data-target="#funkytown-slider",data-slide-to="2")
14 | .carousel-inner(role="listbox")
15 | .item.active
16 | img(data-src="holder.js/1600x700/auto/#777:#555/text:First slide" alt="First slide")
17 | .item
18 | img(data-src="holder.js/1600x700/auto/#777:#555/text:Second slide" alt="Second slide")
19 | .item
20 | img(data-src="holder.js/1600x700/auto/#777:#555/text:Third slide" alt="Third slide")
21 | a.left.carousel-control(href="#funkytown-slider",data-slide="prev")
22 | span.glyphicon.glyphicon-chevron-left(aria-hidden="true")
23 | span.sr-only Previous
24 | a.right.carousel-control(href="#funkytown-slider",data-slide="next")
25 | span.glyphicon.glyphicon-chevron-right(aria-hidden="true")
26 | span.sr-only Next
27 | .col-md-6.col-lg-4#upcomming-events
28 | h2 Upcomming Events
29 | .row.event
30 | .col-xs-4
31 | img(src="/img/events/event1.jpg")
32 | .col-xs-8
33 | h4: a(href="#") JazzFM Funky Sensation
34 | p Ultra cool event
35 | .row.event
36 | .col-xs-4
37 | img(src="/img/events/event2.jpg")
38 | .col-xs-8
39 | h4: a(href="#") Funky House & R'N'B
40 | p Ultra cool event
41 | .row.event
42 | .col-xs-4
43 | img(src="/img/events/event3.jpg")
44 | .col-xs-8
45 | h4: a(href="#") Funky Smugglers
46 | p Ultra cool event
47 |
48 |
49 | block scripts
50 | script(src="http://getbootstrap.com/assets/js/docs.min.js")
51 |
52 |
--------------------------------------------------------------------------------
/week6/2-hobby-site/README.md:
--------------------------------------------------------------------------------
1 | # Hobby Site Using Bootstrap & Sass
2 |
3 | ## ULTRA TASK
4 | Recreate 3 site types with 2-3 screens each using bootstrap & SASS
5 |
6 | ## Premise
7 | - Pick a site type that is related to your hobby - f1, fitness, books, world of warcraft
8 |
9 | ## Step 1 Brainstorm
10 | - Brainstorm what type of information will be shared there, also in what form
11 | - Do some research check other sites, possible layouts, images you would use, elements you like etc...
12 |
13 | ## Step 2 Create a mockup
14 | - Create a mockup on a sheet of paper or with a software following this process:
15 | - What would be the basic layout -> header, sidebar, footer
16 | - What would be the structure for each page -> list, table, thumbnails, article ...
17 | - Specify elements -> slider, product info, tabs ...
18 |
19 | ## Step 3 Identify MVP
20 | - Identify MVP -> the minimum amount of info, elements and structure in order to present how the ux will look and feel like the final version
21 | - in a catalogue we only need 2 rows of items
22 | - product page would have picture on the left, parameters on the right and product info below them
23 |
24 | ## Step 4 Project Setup (ref previous projects)
25 | - backend (npm) - express, jade
26 | - frontend (bower) - bootstrap, fontawesome
27 | - styles will be in public/css
28 |
29 | ## Step 5 Create the first screen (index.html)
30 | - include the styles and scripts
31 | - create the layout - header, sidebar ...
32 | - create the content structure - table, grid, thumbnails ...
33 | - create it using bootstrap classes and structure
34 | - header -> .navbar
35 | - sidebar -> .nav.nav-stacked
36 | - grid & structure -> .row and .col-xs-12.col-sm-4.col-md-3
37 | - thumnails -> .thumbnail
38 | - buttons -> .btn.btn-success
39 |
40 | ## Step 6 Separate the layout from the content
41 |
42 | ## Step 7 Create the base interface for the other screens
43 |
44 | ## Step 8 Use SASS to make things look better
--------------------------------------------------------------------------------
/week2/2-console-crud/README.md:
--------------------------------------------------------------------------------
1 | # Week 2 : Task 2 : Console CRUD
2 |
3 | ## Premise
4 | Create an app that allows you to create, read, update, delete users in a collection.
5 | - displays a menu with different CRUD actions
6 | - prompts for an action
7 | - each action either displays a result (List users) or prompts for additional information (Add User)
8 | - the data is stored in a global variable users of type collection (dictionary in array)
9 | ```js
10 | var users = [{
11 | id: 1, name: "Pesho", email: "pesho@gmail.com"
12 | },{
13 | id: 2, name: "Gosho", email: "gosho@gmail.com"
14 | }];
15 | ```
16 |
17 | ## Steps
18 | 1. Create interface and prompt
19 | 2. Implement list users and add user
20 | 3. Implement get user, edit user and delete user
21 | 4. Implement search users
22 | 5. Implement save, load to json file
23 | 6. Create function that draws the users table
24 |
25 | ## Dependencies
26 | - npm
27 | - prompt
28 | - chalk
29 |
30 | ## Intitial Interface
31 | ```sh
32 | node console-crud.js
33 |
34 | Pick action:
35 | 1. List users
36 | 2. Add user
37 | > action: _
38 |
39 | # List users
40 | > action: 1
41 | Listing Users:
42 | 1 Ivan ivan@gmail.com
43 | 2 Pesho pesho@gmail.com
44 |
45 | # Add user
46 | > action: 2
47 | Enter user data:
48 | > id: 3
49 | > name: Todor
50 | > email: todor@gmail.com
51 |
52 | ```
53 |
54 | ## Final Interface
55 | ```sh
56 | node console-crud.js
57 |
58 | |=================|
59 | | Pick action |
60 | |=================|
61 | | 1. List users |
62 | | 2. Add user |
63 | | 3. Get user |
64 | | 4. Edit user |
65 | | 5. Delete user |
66 | | 6. Search users |
67 | | 7. Load users |
68 | | 8. Save users |
69 | |=================|
70 | > action: _
71 |
72 | # Search users
73 | > action: 6
74 | Search users:
75 | > keyword: sho
76 | Results: 2
77 | |===============================|
78 | | ID | Name | Email |
79 | |===============================|
80 | | 1 | Pesho | pesho@gmail |
81 | | 2 | Gosho | gosho@gmail |
82 | |===============================|
83 |
84 | #
85 | ```
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Frontend-JavaScript-2
2 |
3 | The second edition of the Frontend JavaScript course in HackBulgaria.
4 |
5 | ```
6 | _ _____ _ _
7 | | | / ____| (_) | |
8 | | | __ _ __ __ __ _ | (___ ___ _ __ _ _ __ | |_
9 | _ | | / _` |\ \ / // _` | \___ \ / __|| '__|| || '_ \ | __|
10 | | |__| || (_| | \ V /| (_| | ____) || (__ | | | || |_) || |_
11 | \____/ \__,_| \_/ \__,_||_____/ \___||_| |_|| .__/ \__|
12 | | |
13 | |_|
14 | ```
15 |
16 | ## Douglas Crockford
17 |
18 | Watch those videos:
19 |
20 | * [JavaScript - The Early Years](https://www.youtube.com/watch?v=JxAXlJEmNMg)
21 | * [And Then There Was JavaScript](https://www.youtube.com/watch?v=RO1Wnu-xKoY)
22 | * [Function the Ultimate](https://www.youtube.com/watch?v=ya4UHuXNygM)
23 | ## Materials for prepartion
24 | * [Metamorphosis of AJAX](https://www.youtube.com/watch?v=Fv9qT9joc0M)
25 | * [The End of All Things](https://www.youtube.com/watch?v=47Ceot8yqeI)
26 |
27 |
28 | We strongly recommend that you check the following materials:
29 |
30 | * Throughout the course we will use the following book - http://eloquentjavascript.net/
31 | * For the start of the course, **you can read from chapter 1 to chapter 4** - to get a good feeling of the language.
32 | * If you are into it, you can complete the JavaScript track in CodeCademy - http://www.codecademy.com/en/tracks/javascript
33 |
34 |
35 | ## Course Program
36 |
37 | **The program is subject to change and will change until it gets to its final form ;)**
38 |
39 | * JavaScript the good the bad and the weird parts - learning JavaScript as a language.
40 | * The Art and Science of Front-end development
41 | * Building an Interface with jQuery
42 | - DOM manipulation
43 | - event handling
44 | - plugins
45 |
46 | * Bootstrapping the UX
47 | * Sculpting with SASS
48 | * Thinking Async - Closures, Callbacks, Promises
49 | * CRUD Pattern with jQuery and Firebase
50 | * Data manipulation with lodash
51 | * SPAs with Angular Part 1
52 | * SPAs with Angular Part 2
53 | * HTML5 APIs - Canvas & WebSockets. Making games!
54 | * (Bonus) 3D Apps with Three.js
55 | * (Bonus) Diagrams, Charts with d3.js and Raphael.js
56 |
57 |
--------------------------------------------------------------------------------
/week3/1-A-Panda/README.md:
--------------------------------------------------------------------------------
1 | # We will model a Panda
2 |
3 | In a file called `panda.js`, create a `Panda` object, which takes two arguments:
4 |
5 | * The `name` of the panda
6 | * The `sex` of the panda - can be `"male"` or `"female"`
7 | * Each `Panda` should have a `weight` property, which always starts at `20`
8 |
9 | Our `Panda` should have the following methods, attached to the `Panda`'s prototype:
10 |
11 | * `toString()` - returns a string representation of our panda. See the examples below for how it should look like
12 | * `isMale()` and `isFemale()` - returns true/false based on the `sex` of the Panda
13 | * `eat(bamboo)` where `bamboo` is an integer - how much kilograms does tha panda eat. When a panda eats `x` kg of `bamboo`, it gains `x/2` weight. If the weight of the panda goes above 80, the name of the panda should be prepended with `"Lazy Panda"`. See examples below.
14 | * `mate(anotherPanda)` - we will have a reproduction mechanism for our pandas. More on mating below.
15 |
16 | ## Basic examples for our Panda
17 |
18 | ```javascript
19 | var ivo = new Panda("Ivo", "male");
20 |
21 | ivo.weight == 20; // true
22 | ivo.isMale() == true; // true
23 | ivo.isFemale() == false; // true
24 | ivo.toString() == "Ivo is a male panda which weights 20 kg" // true
25 |
26 | ivo.eat(80);
27 | ivo.weight == 60; // true
28 |
29 | ivo.eat(80);
30 | ivo.weight == 100; // true
31 |
32 | ivo.name == "Lazy Panda Ivo" // true
33 | ```
34 |
35 | ## Examples for Panda Mating
36 |
37 | When we call the `mate(anotherPanda)` method, we should get a new panda with the following criteria:
38 |
39 | * The sex of the new panda should be a 50% chance between male and female.
40 | * **If the panda is male**, the name of the baby panda should be: `"{Name-of-Father} {Name-of-Mother}"`
41 | * Otherwise, it should be the other way around - `"{Name-of-Mother} {Name-of-Father}"`
42 | * If we try to mate male with male or female with female panda, the method should throw an error `CannotMatePandas`. Research how you can throw an error from JavaScript code :)
43 |
44 | Example:
45 |
46 |
47 | ```javascript
48 | var ivan = new Panda("Ivan", "male");
49 | var ivanka = new Panda("Ivanka", "female");
50 |
51 | var baby = ivan.mate(ivanka);
52 |
53 | // we can have one of the two options:
54 |
55 | baby.name == "Ivan Ivanka" && baby.sex == "male"
56 | baby.name == "Ivanka Ivan" && baby.sex == "female"
57 | ```
58 |
--------------------------------------------------------------------------------
/week8/2-rest-resource/README.md:
--------------------------------------------------------------------------------
1 | # Week 8 Task 2 REST Resource
2 |
3 | ## Premise
4 | Create a helper class that encapsulates ajax calls to REST resources whereby
5 | - the constructor gets an `url` attribute.
6 | ```js
7 | function Resource(url){
8 |
9 | }
10 | ```
11 | - has the following methods
12 | - query() - calls a rest resource and returns a list of items (collection)
13 | - create(data) - sends a new entry (document) to the list
14 | - update(id, data) - updates a document by id
15 | - delete(id) - deletes by id
16 | - implements and returns a promise for each method
17 |
18 | ## Usage
19 | ### Basic
20 | ```js
21 |
22 | var student = Resource("/api/students")
23 |
24 | student.query().then(function(result){
25 | console.log(result);
26 | })
27 |
28 | ```
29 | ### Advanced
30 | ```js
31 | var student = new Resource("http://192.168.0.66:3000/api/students");
32 |
33 | var displayResult = function(res){
34 | console.log(res)
35 |
36 | return res;
37 | }
38 |
39 | var getId = function(data){
40 |
41 | var id = data._id;
42 |
43 | return id;
44 | };
45 |
46 | // query
47 |
48 | // create
49 | var data = {
50 | name: "Gospodin",
51 | email: "gospodin@gospodinoff.cc"
52 | };
53 |
54 | var newData = {
55 | name: "Peter"
56 | }
57 | student.query()
58 | .then(displayResult)
59 | .then(function(){
60 | return student.create(data);
61 | })
62 | .then(displayResult)
63 | .then(getId)
64 | .then(function(id){
65 | return student.update(id, newData);
66 | })
67 | .then(displayResult)
68 | .then(function(){
69 | return student.query();
70 | })
71 | .then(displayResult);
72 |
73 | })
74 | ```
75 |
76 | ## Dependencies
77 | - bower - for the task itself
78 | - jquery
79 | - q#1.x
80 | - npm - to be able to run a RESTful API to test
81 | - express
82 | - method-override
83 | - body-parser
84 | - iblokz/node-restify
85 | - mongoose
86 | - jade
87 |
88 | ## Hints
89 | - CRUD pattern -> Create (POST), Read (GET), Update (PUT), Delete
90 | - REST resource archtypes
91 | - document
92 | - collection
93 | - REST endpoints
94 | - collection
95 | - /api/users GET, POST
96 | - document
97 | - /api/users/:id GET, PUT, DELETE
98 |
99 | ## Next Steps
100 | - Use it in a previous task where you have to access RESTful APIs
--------------------------------------------------------------------------------
/week5/hangout/js/app.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var TodoApp = (function() {
4 |
5 | // private vars
6 | var tasks = [];
7 | var idIndex = 0;
8 |
9 | // adds a new task to the collection
10 | var addTask = function(taskName) {
11 | idIndex++;
12 |
13 | tasks.push({
14 | name: taskName,
15 | id: idIndex,
16 | finished: false
17 | })
18 | };
19 |
20 | // updates the task
21 | var finishTask = function(id) {
22 | tasks.forEach(function(task, index){
23 | if(task.id === id){
24 | task.finished = !task.finished;
25 | tasks[index] = task;
26 | }
27 | })
28 | };
29 |
30 | var removeTask = function(id) {
31 | tasks = tasks.filter(function(task, index){
32 | return task.id !== id;
33 | })
34 | }
35 |
36 | var moveTask = function(fromIndex, toIndex){
37 |
38 | // get the el and remove it from tasks
39 | var elToMove = tasks.splice(fromIndex, 1)[0];
40 |
41 | // push it to the new index
42 | tasks.splice(toIndex, 0, elToMove);
43 |
44 | }
45 |
46 | var displayList = function() {
47 |
48 | var tasksList = $("#tasks-list");
49 |
50 | // clear the contents
51 | tasksList.empty();
52 |
53 | // loop through the tasks
54 | tasks.forEach(function(task){
55 |
56 | var taskId = task.id;
57 |
58 | var liTask = $(" ");
59 |
60 | // finish task button
61 | var chkFinishTask = $(" ");
62 | chkFinishTask.addClass("finishTask fa fa-square-o");
63 | chkFinishTask.click(function(){
64 | finishTask(taskId);
65 | displayList();
66 | })
67 |
68 | // remove task button
69 | var chkRemoveTask = $(" ");
70 | chkRemoveTask.addClass("removeTask fa fa-trash");
71 | chkRemoveTask.click(function(){
72 | removeTask(taskId);
73 | displayList();
74 | })
75 |
76 | if(task.finished === true){
77 | chkFinishTask.toggleClass("fa-square-o fa-check-square-o");
78 | liTask.addClass("finished");
79 | }
80 |
81 | // append contents to li
82 | liTask.append(chkFinishTask);
83 | liTask.append(task.name);
84 | liTask.append(chkRemoveTask);
85 |
86 | // append each task
87 | tasksList.append(liTask);
88 | })
89 |
90 | // attach event listeners
91 |
92 | };
93 |
94 | // public api
95 | return {
96 | addTask: addTask,
97 | finishTask: finishTask,
98 | moveTask: moveTask,
99 | displayList: displayList
100 | };
101 | })();
--------------------------------------------------------------------------------
/Application/3-Query-Language-Over-CSV/README.md:
--------------------------------------------------------------------------------
1 | # Problem 3 - A query language over a CSV file
2 |
3 | A CSV files (comma separated values) can be represented as a table.
4 |
5 | For example this CSV file:
6 |
7 | ```csv
8 | id, name, course
9 | 1, Rado, Haskell
10 | 2, Ivo, Python
11 | ```
12 |
13 | Can be represented by this table:
14 |
15 | | id | name | course |
16 | |----|------|---------|
17 | | 1 | Rado | Haskell |
18 |
19 |
20 | We are going to use CSV files as tables and make a simple query language for fetching data.
21 |
22 | **In a language of your choice, make a program that:**
23 |
24 | * Reads a CSV file.
25 | * Gives the user an interactive input for queries.
26 | * Answers the queries with data from the CSV file.
27 |
28 | The queries, that should be supported are:
29 |
30 | * `SELECT [columns] LIMIT X` - where you can SELECT without giving the LIMIT. Then this will fetch all rows.
31 | * `SUM [column]` - returns the sum of all integers in the given column.
32 | * `SHOW` - returns a list of all column names in your data.
33 | * `FIND X` - returns all rows, that has `X` in some of their cells (Match X with at least one of the columns). **If `X` is a string, search for every string, that contains `X` as a substring.**
34 |
35 | Here are examples of all queries.
36 |
37 | Consider that we have loaded the following CSV:
38 |
39 | ```csv
40 | id,name,hometown
41 | 1,Kiara,Lunel
42 | 2,Mona,Henley-on-Thames
43 | 3,Kiayada,Villers-aux-Tours
44 | 4,Karly,Hillsboro
45 | 5,Igor,Oranienburg
46 | ```
47 |
48 | Now, lets make queries:
49 |
50 |
51 | ```
52 | query>SELECT id
53 | |id|
54 | |--|
55 | |1 |
56 | |2 |
57 | |3 |
58 | |4 |
59 | |5 |
60 | ```
61 |
62 | ```
63 | query> SELECT id, name
64 | |id| name |
65 | |--|--------|
66 | |1 |Kiara |
67 | |2 |Mona |
68 | |3 |Kiayada |
69 | |4 |Karly |
70 | |5 |Igor |
71 | ```
72 |
73 | ```
74 | query> SELECT id, name LIMIT 1
75 | |id| name |
76 | |--|--------|
77 | |1 |Kiara |
78 | ```
79 |
80 | ```
81 | query> SUM id
82 | 15
83 | ```
84 |
85 | ```
86 | query> SHOW
87 | id, name, hometown
88 | ```
89 |
90 | ```
91 | query> FIND "-"
92 | |id| name | hometown |
93 | |--|--------| ------------------|
94 | |2 |Mona | Henley-on-Thames |
95 | |3 |Kiayada | Villers-aux-Tours |
96 | ```
97 |
98 | ## Features
99 |
100 | * If the query is non-valid - say it. Don't crash the program.
101 | * As you see in the examples, the results should be displayed in visual, tabular way. This is up to you. You don't have to follow the styles of the example.
102 |
--------------------------------------------------------------------------------
/week5/README.md:
--------------------------------------------------------------------------------
1 | # Week5 : jQuery
2 |
3 | Before we start here is a cheat sheet for jQuery
4 |
5 | ## Selecting elements
6 |
7 | ```js
8 | // dom objects
9 | var domObject = document.getElementById("idHere");
10 | $( domObject )
11 |
12 | // select by tagname
13 | $( "div" )
14 |
15 | // select by class
16 | $( "span.superClass" )
17 | $( ".anotherClass")
18 |
19 | // select by id
20 | $( "p#ultraId" )
21 |
22 | // select childs
23 | $( "ul.list > li.list-element")
24 | ```
25 |
26 | ## Getting and Setting
27 |
28 | ```js
29 | // html, text
30 | $("p.article").html("Article Title ")
31 | $("textarea[name='summary']").text("Some Text Here")
32 |
33 | // input values
34 | $("input#search").val()
35 |
36 | // attributes
37 | $("img#logo").attr("src","dir.bg/logo.png")
38 | $("a#myLink").attr()
39 |
40 | // classes
41 | $("button#trigger").addClass("active")
42 | $("button#trigger").removeClass("active")
43 | $("button#trigger").toggleClass("active")
44 | ```
45 |
46 | ## DOM Manipulation
47 |
48 | ```js
49 | // removing and emptying
50 | $("div").remove()
51 | $("div").empty()
52 |
53 | // creating
54 | var input = $(document.createElement("input"));
55 | var item = $(" ");
56 |
57 | // appending
58 | $("div#container").append($(""))
59 | $(" ").appendTo("div.withSpans")
60 |
61 | // prepending
62 | $("p.article").text("Article Text").prepend("Article Title ")
63 | ```
64 |
65 | ## Event Handling
66 |
67 | ```js
68 | // on document ready
69 | $( document ).ready(function(){
70 | // init stuff here
71 | })
72 |
73 | // clicks
74 | $( "a#trigger" ).click(function(){
75 |
76 | })
77 |
78 | // multiple events
79 | $( "a#button" ).on("mouseenter mouseleave", function(){
80 |
81 | })
82 | ```
83 |
84 | ## Naming Suggestions
85 |
86 | ```js
87 | // wtf is done here
88 | $("div#container").append($("").addClass("items-list").append($("List Item ").addClass("list-item")))
89 |
90 | // better
91 | var divContainer = $("div#container");
92 | var ulItemsList = $("").addClass("items-list");
93 | var liListItem = $("List Item ").addClass("list-item")
94 |
95 | ulItemsList.append(liListItem);
96 | divContainer.append(ulItemsList);
97 |
98 | // or at least
99 | var container, itemsList, listItem;
100 | ```
101 |
102 | ## Conventions, Style Guides etc.
103 |
104 | http://contribute.jquery.org/style-guide/js/
105 |
106 | https://github.com/airbnb/javascript
107 |
108 | https://github.com/yuanyan/pragmatic-jquery
--------------------------------------------------------------------------------
/week6/hangout1_full/public/js/app.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var TodoApp = (function() {
4 |
5 | var tasksOrder = [];
6 |
7 | var updateView = function(tasks){
8 | var orderedTasks = [];
9 | if(tasksOrder.length > 0){
10 | tasksOrder.forEach(function(taskId){
11 | tasks.forEach(function(task){
12 | if(task._id === taskId){
13 | orderedTasks.push(task);
14 | }
15 | })
16 | })
17 | } else {
18 | orderedTasks = tasks;
19 | }
20 | TaskModel.setTasks(orderedTasks);
21 | TasksView.update(orderedTasks);
22 | }
23 |
24 | var updateOrder = function(cb){
25 |
26 | if(!cb){
27 | cb = function(){};
28 | }
29 |
30 | var tasks = TaskModel.getTasks();
31 | tasksOrder = [];
32 | tasks.forEach(function(task,index){
33 | tasksOrder.push(task._id);
34 | })
35 | $.ajax({
36 | url: "/api/settings/55380aad1e7726c31b03670b",
37 | data: {
38 | tasksOrder: tasksOrder
39 | },
40 | success: function(){
41 | cb();
42 | },
43 | method: "PUT"
44 | });
45 | }
46 |
47 | var init = function(){
48 | // load the order
49 | $.get("/api/settings/55380aad1e7726c31b03670b",function(settings){
50 | if(settings)
51 | tasksOrder = settings.tasksOrder || [];
52 | // load the tasks
53 | TaskModel.read(updateView)
54 | });
55 | }
56 |
57 | // adds a new task to the collection
58 | var saveTask = function(task) {
59 | if(typeof task._id === "undefined") {
60 | TaskModel.create(task, function(tasks){
61 | updateOrder(function(){
62 | updateView(tasks);
63 | })
64 | })
65 | } else {
66 | TaskModel.update(task._id, task, updateView);
67 | }
68 | };
69 |
70 | // updates the task
71 | var finishTask = function(task) {
72 |
73 | task.finished = !task.finished;
74 |
75 | TaskModel.update(task._id, task,updateView)
76 | };
77 |
78 | var removeTask = function(task) {
79 | TaskModel.remove(task._id, function(tasks){
80 | updateOrder(function(){
81 | updateView(tasks);
82 | })
83 | })
84 | }
85 |
86 | var moveTask = function(fromIndex, toIndex){
87 |
88 | var tasks = TaskModel.getTasks();
89 |
90 | // get the el and remove it from tasks
91 | var elToMove = tasks.splice(fromIndex, 1)[0];
92 |
93 | // push it to the new index
94 | tasks.splice(toIndex, 0, elToMove);
95 |
96 | TaskModel.setTasks(tasks);
97 |
98 | updateOrder();
99 |
100 | }
101 |
102 | return {
103 | saveTask: saveTask,
104 | finishTask: finishTask,
105 | removeTask: removeTask,
106 | moveTask: moveTask,
107 | init: init
108 | }
109 | })();
--------------------------------------------------------------------------------
/week5/2-todo-crud/README.md:
--------------------------------------------------------------------------------
1 | # Week 5 : Task 2 : Todo CRUD App
2 |
3 | ## Reference
4 | - http://learn.jquery.com/code-organization/concepts/
5 | - http://contribute.jquery.org/style-guide/js/
6 |
7 |
8 | ## Last time
9 | - got the code from week 4
10 | - created and inited a new project
11 | - replaced dom modifications and event handling with jQuery
12 | - added "finish task" logic
13 |
14 | ## Today
15 | - no npm & express
16 | - code refactoring
17 | - CRUD pattern
18 | - Module pattern
19 |
20 | ## New Project Steps
21 | for more info see week1 1-hello-node
22 |
23 | - initial file structure
24 | - create new files and directories
25 | - copy the files with repeating functionality
26 | - inits and dependencies (bower, npm)
27 | - initial interface
28 | - initial functionality
29 |
30 |
31 | ## Directory Structure
32 |
33 | ```
34 | .
35 | ├── .bowerrc # change public/lib to just lib here
36 | ├── bower.json # generated by bower init
37 | ├── index.html
38 | ├── js
39 | │ ├── app.js # TodoApp = (fucntion(){...})()
40 | │ └── init.js # $(document).ready(...) here
41 | └── lib
42 | └── jquery # bower install --save jquery
43 | ```
44 |
45 | ## What is a collection
46 |
47 | ```js
48 | var task = {
49 | id: 25,
50 | name: "Do the dishes"
51 | finished: false
52 | }
53 |
54 | var tasks = [
55 | {
56 | id: 15,
57 | name: "Get some groceries",
58 | finished: true
59 | },
60 | {
61 | id: 20,
62 | name: "Call grandma",
63 | finished: false
64 | },
65 | {
66 | id: 25,
67 | name: "Do the dishes"
68 | finished: false
69 | }
70 | ]
71 | ```
72 |
73 | ## app.js
74 |
75 | http://learn.jquery.com/code-organization/concepts/#the-module-pattern
76 |
77 | ```js
78 | var TodoApp = (function() {
79 | // private vars
80 | var tasks = [];
81 | var index = 0;
82 |
83 | // (optional) store the reference with the jQuery selectors here
84 | var refs = {
85 | addTask: "input#addTask",
86 | container: "#container"
87 | }
88 |
89 | // (optional) interface for setting the
90 | var setSelectorRefs = function(refs){
91 |
92 | }
93 |
94 | var addTask = function(taskName) {
95 | // add to tasks
96 | };
97 |
98 | var finishTask = function(id) {
99 | // update task
100 | };
101 |
102 | var displayList = function() {
103 | // clear the contents
104 | // loop through the tasks
105 | // append each task
106 | };
107 |
108 | // public api
109 | return {
110 | createTask: addTask,
111 | finishTask: finishTask,
112 | displayList: displayList
113 | };
114 | })();
115 |
116 | // access via
117 | TodoApp.addTask("Do the dishes")
118 |
119 | ```
120 |
121 | ## init.js
122 |
123 | ```js
124 | 'use strict'
125 |
126 | $(document).ready(function(){
127 | // init stuff
128 | })
129 | ```
--------------------------------------------------------------------------------
/week6/hangout2/views/events.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | .container-fluid#events
5 | h1 Events
6 | .row#events-list
7 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
8 | .thumbnail
9 | span.date 9 JAN
10 | img(src="img/events/event1.jpg")
11 | .caption
12 | h4: a(href="#") JazzFM Funky Sensation
13 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
14 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
15 | .thumbnail
16 | span.date 9 JAN
17 | img(src="img/events/event2.jpg")
18 | .caption
19 | h4: a(href="#") JazzFM Funky Sensation
20 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
21 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
22 | .thumbnail
23 | span.date 9 JAN
24 | img(src="img/events/event3.jpg")
25 | .caption
26 | h4: a(href="#") JazzFM Funky Sensation
27 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
28 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
29 | .thumbnail
30 | span.date 9 JAN
31 | img(src="img/events/event1.jpg")
32 | .caption
33 | h4: a(href="#") JazzFM Funky Sensation
34 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
35 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
36 | .thumbnail
37 | span.date 9 JAN
38 | img(src="img/events/event1.jpg")
39 | .caption
40 | h4: a(href="#") JazzFM Funky Sensation
41 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
42 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
43 | .thumbnail
44 | span.date 9 JAN
45 | img(src="img/events/event2.jpg")
46 | .caption
47 | h4: a(href="#") JazzFM Funky Sensation
48 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
49 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
50 | .thumbnail
51 | span.date 9 JAN
52 | img(src="img/events/event3.jpg")
53 | .caption
54 | h4: a(href="#") JazzFM Funky Sensation
55 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
56 | .col-xs-12.col-sm-4.col-md-3.col-lg-2
57 | .thumbnail
58 | span.date 9 JAN
59 | img(src="img/events/event1.jpg")
60 | .caption
61 | h4: a(href="#") JazzFM Funky Sensation
62 | p We know the release date of the brand new album of Riverside - Shrine of New Generation Slaves
63 |
64 |
65 | block scripts
66 | script.
67 | function reziseThumbs(){
68 | $(".thumbnail > img").each(function(){
69 | $(this).height($(this).width()/4*5);
70 | })
71 | }
72 |
73 | $(document).ready(function(){
74 | reziseThumbs();
75 | $(window).resize(function(){
76 | reziseThumbs();
77 | });
78 | })
--------------------------------------------------------------------------------
/week1/3-jade-blog/README.md:
--------------------------------------------------------------------------------
1 | # Week 1 Task 3: Jade Blog
2 |
3 | ## Init Stuff
4 | You know the drill, files, dependencies, server. If not check out the hello node task.
5 |
6 | You should end up with something like this:
7 | ```
8 | .
9 | ├── server.js
10 | ├── package.json
11 | ├── node_modules
12 | │ └── express
13 | ├── .bowerrc
14 | ├── bower.json
15 | └── public
16 | ├── index.html
17 | └── lib
18 | └── fontawesome
19 | ```
20 |
21 | ## Jade What
22 |
23 | There are a lot of template engines out there. Most of them are plain old html with additional patterns or masks that indicate where variables should be inserted, conditional statements, loops etc...
24 |
25 | One of the biggest things that differentiate jade is that it goes one step further and get's rid of the unneeded characters and leaves only the most important.
26 |
27 | so this:
28 | ```html
29 |
30 | ```
31 | translates to this:
32 | ```jade
33 | div.className#idName(attr="1")
34 | ```
35 |
36 | div's, since we all use them a lot in jade we can ommit them. So this also works:
37 | ```jade
38 | .className#idName(attr="1")
39 | ```
40 |
41 | You may notice that this jade statemet looks very much like a css selector.
42 |
43 | To top things off you don't need closing tags. The structure is defined, well with a structure.
44 |
45 | Here is a more complex example:
46 | ```jade
47 | .className#idName(attr="1",style="border: 1px;")
48 | span.class1.class2#id1 Some Text Here
49 | p.
50 | Text positioned bellow a tag with a "." at the end
51 | and with additional identation will be inserted as is
52 | no matter on how many lines. Of course this works great for
53 | script(type="text/javascript").
54 | var javaScript = "Code Here";
55 | function forReal(){
56 | alert("I am not kidding!");
57 | }
58 | ```
59 |
60 | Compiled will produce the following html:
61 | ```html
62 |
63 |
Some Text Here
64 |
65 | Text positioned bellow a tag with a "." at the end
66 | and with additional identation will be inserted as is
67 | no matter on how many lines. Of course this works great for
68 |
69 |
75 |
76 | ```
77 |
78 | Ok now that we know what jade code looks like and how to translate it to and back from html (if not check the jade lang site. It has a good documentation and examples)
79 |
80 | ## Install Jade
81 |
82 | Since we already inited our project and have installed and set up express we can just
83 | ```sh
84 | npm install --save jade
85 | ```
86 |
87 | To make express play nice with jade just after
88 | ```javascript
89 | // configure the app
90 | app.use(express.static('public'));
91 | ```
92 |
93 | add
94 | ```javascript
95 | app.set('view engine', 'jade');
96 | ```
--------------------------------------------------------------------------------
/week6/1-bootstrap-shop/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## Premise
3 |
4 | Create the interface of a shop app using bootstrap and jade.
5 |
6 | We will need the following screens:
7 | - index.jade - a catalogue with products
8 | - product.jade - a view product screen
9 | - cart.jade - view with shopping cart
10 |
11 |
12 |
13 | ## Snippets
14 |
15 | ### jade support for express
16 |
17 | ```js
18 | app.set('view engine', 'jade');
19 |
20 | // routes
21 | app.get('/', function (req, res) {
22 | res.render('index');
23 | })
24 |
25 | // listen for files: /post -> /views/post.jade
26 | app.get("/:fileName", function(req, res, next){
27 | if(req.params && req.params.fileName){
28 | var fileName = req.params.fileName.replace(".html","");
29 |
30 | // if jade file exists
31 | if(fs.existsSync(__dirname+"/views/"+fileName+".jade")){
32 | res.render(fileName);
33 | // if post is in posts
34 | } else {
35 | next();
36 | }
37 |
38 | } else {
39 | next();
40 | }
41 | })
42 | ```
43 |
44 | ### layout structure
45 |
46 | - index.jade
47 | ```jade
48 | extends layout
49 |
50 | block content
51 | //- put content here
52 | ```
53 |
54 | - layout.jade
55 | ```jade
56 | ...
57 | //- sidebar
58 | include nav.jade
59 | ...
60 | //- content here
61 | block content
62 | ```
63 |
64 | ### bootstrap
65 |
66 | ## hello world example
67 |
68 | ```jade
69 | .container
70 | h1.text-success
71 | i.fa.fa-child
72 | | Hello Bootstrap Shop
73 | p.text-warning Some useless text here
74 | a.btn.btn-danger Hit me!
75 |
76 | ```
77 |
78 | ## grid system basic example
79 | ```jade
80 | .container
81 | .row
82 | .col-xs-12 one huge column
83 | .row
84 | .col-xs-6 two
85 | .col-xs-6 columns
86 | .row
87 | .col-xs-4 one
88 | .col-xs-4 two
89 | .col-xs-4 three
90 | .row
91 | .col-xs-3 uno
92 | .col-xs-3 dos
93 | .col-xs-3 tres
94 | .col-xs-3 quatro
95 | .row
96 | .col-xs-2 a
97 | .col-xs-2 a
98 | .col-xs-2 a
99 | .col-xs-2 a
100 | .col-xs-2 a
101 | .col-xs-2 a
102 | ```
103 |
104 | ## grid system responsive example
105 | ```jade
106 | .container
107 | .row
108 | .col-md-3.col-sm-4.col-xs-12 item 1
109 | .col-md-3.col-sm-4.col-xs-12 item 2
110 | .col-md-3.col-sm-4.col-xs-12 item 3
111 | .col-md-3.col-sm-4.col-xs-12 item 4
112 | .col-md-3.col-sm-4.col-xs-12 item 5
113 | .col-md-3.col-sm-4.col-xs-12 item 6
114 | .col-md-3.col-sm-4.col-xs-12 item 7
115 | .col-md-3.col-sm-4.col-xs-12 item 8
116 | ```
117 |
118 | ## navbar header example
119 | ```jade
120 | nav.navbar.navbar-default
121 | .container-fluid
122 | .navbar-header
123 | button.navbar-toggle.collapsed(data-toggle="collapse",data-target="#my-menu")
124 | i.fa.fa-bars
125 | a(href="/").navbar-brand Bootstrap Shop
126 |
127 | .collapse.navbar-collapse#my-menu
128 | ul.nav.navbar-nav.navbar-left
129 | li: a(href="#")
130 | i.fa.fa-star-o
131 | | Promos
132 | ul.nav.navbar-nav.navbar-right
133 | li: a(href="/cart")
134 | i.fa.fa-shopping-cart
135 | | View Cart
136 | ```
--------------------------------------------------------------------------------
/week6/hangout2/public/css/style.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/css?family=Audiowide);
2 | .thumbnail {
3 | background: inherit;
4 | border-radius: 0px;
5 | border: 0px;
6 | padding: 0px;
7 | position: relative; }
8 | .thumbnail img {
9 | width: 100%; }
10 | .thumbnail h4 {
11 | font-family: "Audiowide", Helvetica, Arial, sans-serif; }
12 | .thumbnail p {
13 | color: #dacea9; }
14 |
15 | /* small screens */
16 | @media only screen and (max-width: 768px) {
17 | .thumbnail img {
18 | width: 30%;
19 | display: inline-block; }
20 | .thumbnail .caption {
21 | width: 70%;
22 | display: inline-block;
23 | vertical-align: top; } }
24 | body {
25 | background: #000;
26 | color: #FFF;
27 | font-family: Helvetica, Arial, sans-serif; }
28 | body > .container-fluid {
29 | margin-top: 70px; }
30 | body > .container-fluid a {
31 | color: #ffc100; }
32 | body > .container-fluid a:hover {
33 | color: #e70000;
34 | text-decoration: none; }
35 |
36 | h1, h2, h3, .navbar-brand, .navbar-nav li {
37 | font-family: "Audiowide", Helvetica, Arial, sans-serif; }
38 |
39 | h1, h2, h3 {
40 | padding: 0 0 2px;
41 | border-bottom: 2px solid #e70000;
42 | margin: 0 0 13px; }
43 |
44 | /* default layout styles */
45 | nav.navbar #my-menu .navbar-nav li a:hover {
46 | background: #999999;
47 | color: #1a1a1a; }
48 |
49 | /* small screens */
50 | @media only screen and (max-width: 768px) {
51 | nav.navbar {
52 | background: url(/img/header-bg.jpg) #000 no-repeat center -38px; }
53 | nav.navbar .navbar-brand {
54 | height: 52px;
55 | line-height: 52px;
56 | padding: 0px 10px; }
57 | nav.navbar #my-menu {
58 | background: #1a1a1a; } }
59 | /* big screens */
60 | @media only screen and (min-width: 768px) {
61 | nav.navbar {
62 | background: url(/img/header-bg.jpg) #000 no-repeat center -25px;
63 | height: 70px; }
64 | nav.navbar .container-fluid {
65 | padding: 0px; }
66 | nav.navbar .navbar-header {
67 | margin-left: 10px;
68 | width: 300px; }
69 | nav.navbar .navbar-brand {
70 | height: 70px;
71 | line-height: 70px;
72 | font-size: 24px;
73 | margin: 0px;
74 | padding: 0px 20px; }
75 | nav.navbar #my-menu {
76 | padding: 0px; }
77 | nav.navbar #my-menu .navbar-nav {
78 | margin-top: -10px;
79 | padding-left: 10px;
80 | background: #1a1a1a;
81 | width: 100%;
82 | display: block;
83 | height: 40px; }
84 | nav.navbar #my-menu .navbar-nav li a {
85 | height: 40px;
86 | line-height: 40px;
87 | font-size: 18px;
88 | margin: 0px;
89 | padding: 0px 10px; } }
90 | /* sections */
91 | #home #upcomming-events .event {
92 | margin: 10px 0px; }
93 | #home #upcomming-events .event img {
94 | width: 100%;
95 | height: 150px; }
96 |
97 | #events #events-list .thumbnail {
98 | cursor: pointer; }
99 | #events #events-list .thumbnail .date {
100 | position: absolute;
101 | top: 0px;
102 | left: 0px;
103 | width: 80px;
104 | height: 30px;
105 | line-height: 30px;
106 | font-size: 16px;
107 | text-align: center;
108 | font-weight: bold;
109 | color: white;
110 | background: #ffc100; }
111 | #events #events-list .thumbnail:hover .date {
112 | background: #e70000; }
113 |
114 | /*# sourceMappingURL=style.css.map */
115 |
--------------------------------------------------------------------------------
/week4/1-Keeping-up-the-Score/page.js:
--------------------------------------------------------------------------------
1 | function text(content) {
2 | return document.createTextNode(content);
3 | }
4 |
5 | function hasKey(dict, key) {
6 | return typeof dict[key] !== "undefined";
7 | }
8 |
9 | Element.createElement = function(tagName, content, attributes) {
10 | attributes = attributes || {};
11 |
12 | var obj = document.createElement(tagName);
13 | obj.appendChild(text(content));
14 |
15 | if(hasKey(attributes, "id")) {
16 | obj.id = attributes["id"];
17 | }
18 |
19 | return new Element(obj);
20 | };
21 |
22 | function Element(domElement) {
23 | this.domElement = domElement;
24 | }
25 |
26 | Element.prototype.appendChild = function(child) {
27 | if(child instanceof Element) {
28 | child = child.domElement;
29 | }
30 |
31 | this.domElement.appendChild(child);
32 | };
33 |
34 | Element.prototype.on = function(type, callback) {
35 | this.domElement.addEventListener(type, callback);
36 | };
37 |
38 | Element.prototype.attr = function(attributeName, attributeValue) {
39 | var aliases = {
40 | "class": "className"
41 | };
42 |
43 | if(hasKey(aliases, attributeName)) {
44 | attributeName = aliases[attributeName];
45 | }
46 |
47 | if(hasKey(this.domElement, attributeName)) {
48 | if (typeof attributeValue === "undefined") {
49 | return this.domElement[attributeName];
50 | } else {
51 | this.domElement[attributeName] = attributeValue;
52 | return attributeValue;
53 | }
54 | }
55 | };
56 |
57 |
58 | function print(obj) {
59 | console.log(obj);
60 | }
61 |
62 | document.addEventListener("DOMContentLoaded", function(event) {
63 | function buttonClickHandler(event) {
64 | var id = event.target.id;
65 | scores[id] += 1;
66 |
67 | document.getElementById(id + "Score").firstChild.data = scores[id];
68 | }
69 |
70 | var scores = {
71 | "teamA": 0,
72 | "teamB": 0
73 | },
74 | container = document.getElementById("container");
75 |
76 | var teamAButton = Element.createElement("button", "Team A", {
77 | id: "teamA"
78 | });
79 |
80 | var teamAScoreText = "Team A Score: ";
81 | var teamAHeading = Element.createElement("h1", teamAScoreText);
82 |
83 | var teamASpan = Element.createElement("span", "0", {
84 | id: "teamAScore"
85 | });
86 |
87 | teamAHeading.appendChild(teamASpan);
88 |
89 | teamAButton.on("click", function(event) {
90 | console.log("Does it work?");
91 | console.log(event);
92 | });
93 |
94 | // var teamBButton = document.createElement("button");
95 | // teamBButton.id = "teamB";
96 | // teamBButton.appendChild(text("Team B"));
97 |
98 | // var teamBScoreText = "Team B Score: ";
99 | // var teamBHeading = document.createElement("h1");
100 | // var teamBSpan = document.createElement("span");
101 | // teamBSpan.appendChild(text("0"));
102 | // teamBSpan.id = "teamBScore";
103 |
104 | // teamBHeading.appendChild(text(teamBScoreText));
105 | // teamBHeading.appendChild(teamBSpan);
106 |
107 | // teamAButton.onclick = buttonClickHandler;
108 | // teamBButton.onclick = buttonClickHandler;
109 |
110 | container.appendChild(teamAHeading.domElement);
111 | container.appendChild(teamAButton.domElement);
112 |
113 | // container.appendChild(teamBHeading);
114 | // container.appendChild(teamBButton);
115 | });
116 |
--------------------------------------------------------------------------------
/week4/hangout/dom-wrapper.js:
--------------------------------------------------------------------------------
1 | // s(element) -> element/s
2 | // element.text
3 | // element.appendTo(anotherElement)
4 | // element.on
5 | // element.attr
6 | // element.addClass()
7 | // element.removeClass()
8 | // element.show()
9 | // element.hide()
10 |
11 | // element.forEach
12 |
13 | function hasKey(dict, key) {
14 | return typeof dict[key] !== "undefined";
15 | }
16 |
17 |
18 | function isArrayLike(object) {
19 | return Array.isArray(object) ||
20 | (typeof(object.length) !== "undefined" && typeof(object.item) !== "undefined");
21 | }
22 |
23 |
24 | function s(selector) {
25 | if(selector instanceof Element) {
26 | return selector;
27 | } else if(typeof(selector) === "string") {
28 | var domObjects = document.querySelectorAll(selector);
29 |
30 | return new Element(domObjects);
31 | } else if(typeof(selector) === "object") {
32 | return new Element(selector);
33 | } else {
34 | throw {
35 | "name": "Selection Error",
36 | "message": "Cannot select: " + selector.toString()
37 | };
38 | }
39 | }
40 |
41 | function c(tag) {
42 | var domObject = document.createElement(tag);
43 | return new Element(domObject);
44 | }
45 |
46 | function Element(domObjects) {
47 | this.domRepr = function() {
48 | if(isArrayLike(domObjects) && domObjects.length === 1) {
49 | return domObjects[0];
50 | }
51 |
52 | return domObjects;
53 | };
54 | }
55 |
56 | Element.prototype.text = function(text) {
57 | var textNode = document.createTextNode(text);
58 | this.domRepr().appendChild(textNode);
59 |
60 | return this;
61 | };
62 |
63 | Element.prototype.appendTo = function(container) {
64 | container.domRepr().appendChild(this.domRepr());
65 | return this;
66 | };
67 |
68 | Element.prototype.on = function(event, callback) {
69 | this.forEach(function(domElement) {
70 | domElement.addEventListener(event, callback);
71 | });
72 |
73 | return this;
74 | };
75 |
76 | Element.prototype.addClass = function(newClass) {
77 | this.forEach(function(domElement) {
78 | if(domElement.className === "") {
79 | domElement.className = newClass;
80 | return this;
81 | }
82 |
83 | var classes = domElement.className.split(" ");
84 | classes.push(newClass);
85 | domElement.className = classes.join(" ");
86 |
87 | });
88 |
89 | return this;
90 | };
91 |
92 |
93 | Element.prototype.removeClass = function(className) {
94 | var domElement = this.domRepr();
95 | var classes = domElement.className.split(" ");
96 |
97 | classes = classes.filter(function(currentClass) {
98 | return currentClass !== className;
99 | });
100 |
101 | domElement.className = classes.join(" ");
102 |
103 | return this;
104 | };
105 |
106 | Element.prototype.hide = function() {
107 | this.domRepr().style.visibility = "hidden";
108 |
109 | return this;
110 | };
111 |
112 | Element.prototype.show = function() {
113 | this.domRepr().style.visibility = "";
114 |
115 | return this;
116 | };
117 |
118 | // s("#container").attr("id") == getter
119 | // s("#container").attr("class", "container2") == setter
120 | Element.prototype.attr = function(attributeName, attributeValue) {
121 | var aliases = {
122 | "class": "className"
123 | };
124 | var domElement = this.domRepr();
125 |
126 | if(hasKey(aliases, attributeName)) {
127 | attributeName = aliases[attributeName];
128 | }
129 |
130 | if(hasKey(domElement, attributeName)) {
131 | if (typeof attributeValue === "undefined") {
132 | return domElement[attributeName];
133 | } else {
134 | domElement[attributeName] = attributeValue;
135 | return this;
136 | }
137 | }
138 | };
139 |
140 | Element.prototype.forEach = function(f) {
141 | var domElement = this.domRepr();
142 |
143 | if(!isArrayLike(domElement)) {
144 | domElement = [domElement];
145 | }
146 |
147 | for(var i = 0; i < domElement.length; i += 1) {
148 | f(domElement[i]);
149 | }
150 |
151 | return this;
152 | };
153 |
154 |
--------------------------------------------------------------------------------
/week3/6-HTML-Generator/README.md:
--------------------------------------------------------------------------------
1 | # A set of classes that generate HTML
2 |
3 | We are going to implement a set of different classes that takes data and renders as HTML.
4 |
5 | We are going to combine that into a `Page` class, which will render the entire HTML.
6 |
7 | * Each class is going to have a common interface of the `render()` method, which returns a string, representing the rendered HTML.
8 | * Some of the classes are going to be containers, having an `addChild()` method - to add different components as their children.
9 | * **Each level of nesting should be indented with 2 spaces!**
10 |
11 | ## The Paragraph class
12 |
13 | Here is an example usage:
14 |
15 | ```javascript
16 | var p = new Paragraph("Some text here");
17 | p.render() == "Some text here
";
18 | ```
19 |
20 | ## The Div class
21 |
22 | `Div` will be a container and for the case, our only container.
23 |
24 | **The `addChild` method should return `this` in order to have chaining. Check the page example for more info.**
25 |
26 | Here is an example usage:
27 |
28 | ```javascript
29 | var div = new Div();
30 | div.addChild(new Paragraph("I am inside that div"));
31 | div.addChild(new Paragraph("I am inside that div too"));
32 |
33 | div.render() ==
34 | "
35 |
I am inside that div
36 |
I am inside that div too
37 |
"
38 | ```
39 |
40 | If we render a div with no children:
41 |
42 | ```javascript
43 | var div = new Div();
44 | div.render() == "
";
45 | ```
46 |
47 | We can also nest divs:
48 |
49 | ```javascript
50 | var div1 = new Div();
51 | var div2 = new Div();
52 |
53 | div1.addChild(div1);
54 |
55 | div1.render() ==
56 | "
57 |
60 | "
61 | ```
62 |
63 | ## The Table class
64 |
65 | Our table class can accept a dictionary, with the following format:
66 |
67 | ```javascript
68 | {
69 | "column_name1": [column values, ...],
70 | "column_name2": [colun values, ...]
71 | }
72 | ```
73 |
74 | Also, our table class can accept a list, with the following format:
75 |
76 | **Consider the first element the row with the name of the columns.**
77 |
78 | ```javascript
79 | [ ["Column1", "Column2"],
80 | ["data1, "data2"], ...
81 | ]
82 | ```
83 |
84 | Here are examples:
85 |
86 | ```javascript
87 | var tableData = {
88 | "name": ["Ivo", "Rado", "Maria"],
89 | "age": [22, 24, 22]
90 | }
91 |
92 |
93 | var table = new Table(tableData);
94 |
95 | table.render() ==
96 | "
97 |
98 |
99 |
100 | name
101 | age
102 |
103 |
104 |
105 |
106 | Ivo
107 | 22
108 |
109 |
110 | Rado
111 | 24
112 |
113 |
114 | Maria
115 | 22
116 |
117 |
118 |
119 | "
120 | ```
121 |
122 | The same goes with list data:
123 |
124 | ```javascript
125 | var tableData = [ ["name", "age"], ["Ivo", 22], ["Rado", 24], ["Maria", 22] ];
126 |
127 | var table = new Table(tableData);
128 | table.render() ==
129 | "
130 |
131 |
132 |
133 | name
134 | age
135 |
136 |
137 |
138 |
139 | Ivo
140 | 22
141 |
142 |
143 | Rado
144 | 24
145 |
146 |
147 | Maria
148 | 22
149 |
150 |
151 |
152 | "
153 | ```
154 |
155 | ## Rendering everything in a page
156 |
157 | We should have a `Page` class which takes a root element and reners everything from it.
158 |
159 | Here is an example:
160 |
161 | ```javascript
162 | var p = new Paragraph("Rolling in the deep");
163 | var div = new Div();
164 |
165 | div
166 | .addChild(new Div())
167 | .addChild(new Div())
168 | .addChild(p);
169 |
170 | var page = new Page(div);
171 |
172 | page.render() ==
173 | "
174 |
175 |
176 |
177 |
Rolling in the deep
178 |
179 | "
180 |
181 | ```
182 |
--------------------------------------------------------------------------------
/week3/3-Prototypes/README.md:
--------------------------------------------------------------------------------
1 | # Augmeting existing object's prototypes
2 |
3 | We are going to play with the prototypes of the existing `String` and `Array` prototypes.
4 |
5 | In a file called `prototypes.js`, add the following methods to:
6 |
7 | ## String
8 |
9 | Extend the `String` prototype by adding the following methods:
10 |
11 | ## capitalize()
12 |
13 | Make the first letter of the string uppercase.
14 |
15 | ```javascript
16 | "javaScript".capitalize() == "JavaScript"
17 | ```
18 |
19 | ## isBlank()
20 |
21 | Returns `true` if the string is an empty string or containing only empty strings.
22 |
23 | ```javascript
24 | " ".isBlank() == true
25 | " ".isBlank() == true
26 | " asda ".isBlank() == false
27 | ```
28 |
29 | ## words()
30 |
31 | Splits a string into array of words.
32 |
33 | ```javascript
34 | var words = "This is a very clever sentence!".words()
35 | console.log(words)
36 | // ["This", "is", "a", "very", "clever", "sentence!"]
37 | ```
38 |
39 | ## format()
40 |
41 | The missing format function in JavaScript. Formats a string with the specified arguments.
42 |
43 | The placeholders should be `"{}"` or named `"{name}"` curly braces.
44 |
45 | Here are some examples:
46 |
47 | ```javascript
48 | var name = "What?";
49 | var result = "Hi, my name is {}. Nice to meet you {}".format(name, "Good sir!");
50 | console.log(result);
51 | // "Hi, my name is What?. Nice to meet you Good sir!"
52 |
53 | ```
54 |
55 | Here is an example with named curly braces:
56 |
57 | ```javascript
58 | var replaces = { "name": "Ivan", "language": "Bulgarian" };
59 | var result = "Hello there {name}! Do you speak {language}?".format(replaces);
60 | console.log(result);
61 | // "Hello there Ivan! Do you speak Bulgarian?"
62 | ```
63 |
64 | ## Array
65 |
66 | ### head, tail and last
67 |
68 | * `head` returns the first element of the array.
69 | * `tail` returns the array without the first element.
70 | * `last` returns the last element of the array.
71 |
72 | ```javascript
73 | var a = [1, 2, 3];
74 |
75 | a.head() == 1;
76 | a.tail() == [2, 3]
77 | a.last() == [3]
78 |
79 | # We do not change the array
80 | a == [1, 2, 3];
81 | ```
82 |
83 | ## range
84 |
85 | Range is a method of two arguments - `start` and `end` and returns a new array of all integers between `[start, end]`
86 |
87 | ```javascript
88 | var result = [].range(1, 10);
89 | result == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
90 | ```
91 | ## sum
92 |
93 | Self explanatory. Returns the sum of all numbers in the array.
94 |
95 | ```javascript
96 | [1, 2, 3].sum() == 6;
97 | ```
98 |
99 | ## product
100 |
101 | Like sum, but returns the product of all numbers in the array
102 |
103 | ```javascript
104 | [1, 2, 3].product() == 6;
105 | ```
106 | ## compact
107 |
108 | Returns a new version of the array where all **falsy** values have been removed.
109 |
110 | Here is a list of faulty values in JavaScript:
111 |
112 | * `false`
113 | * `0` (zero)
114 | * `""` (empty string)
115 | * `null`
116 | * `undefined`
117 | * `NaN` (a special Number value meaning Not-a-Number!)
118 |
119 | Example:
120 |
121 | ```javascript
122 | [false, true, 0, "", null, 5, undefined, NaN, "JavaScript"].compact() == [true, 5, "JavaScript"]
123 | ```
124 |
125 | ## take and drop
126 |
127 | * `take` takes one argument - an integer value `n`, and returns the first `n` elements from the array
128 | * `drop` takes one argument - an integer value `n` and returns a new array, where the first `n` elements are removed
129 |
130 | If something overflows, either return the entire array or an empty one.
131 |
132 | Examples:
133 |
134 | ```javascript
135 | var a = [].range(1, 10);
136 | a.take(3) == [1, 2, 3];
137 | a.drop(5) == [6, 7, 8, 9, 10];
138 | a.take(100) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
139 | a.drop(100) == [];
140 | ```
141 |
142 | ## dedup
143 |
144 | Returns a new array where all duplicate elements are removed, leaving only one copy of each.
145 |
146 | **Compare elements with `===`**
147 |
148 | ```javascript
149 | [1, 1, 1, 1, 1].dedup() == [1];
150 | ```
151 |
152 | ## sample
153 |
154 | Returns a random sample from the array.
155 |
156 | Example:
157 |
158 | ```javascript
159 | [1, 2, 3].sample() // can be 1
160 | [1, 2, 3].sample() // can be 3
161 | [1, 2, 3].sample() // can be 2
162 | ```
163 |
164 |
--------------------------------------------------------------------------------
/week1/1-hello-node/README.md:
--------------------------------------------------------------------------------
1 | # Week 1 Task 1: Hello Node
2 | To start off let's create our directory structure and set up a new hello world project.
3 |
4 | ## Starting File Structure
5 | ```sh
6 | # in unix you can create it in 1 line:
7 | $ mkdir -p ~/Projects/frontendjs/week1/hello-node
8 |
9 | # enter the project folder
10 | $ cd ~/Projects/frontendjs/week1/hello-node
11 |
12 | # also creating a file is easy
13 | $ touch server.js
14 | ```
15 |
16 | The file structure should look something like this:
17 | ```
18 | .
19 | └── Projects
20 | └── frontendjs
21 | └── week1
22 | └── hello-node
23 | └── server.js
24 | ```
25 |
26 | ## Inits and Dependencies
27 |
28 | Let's init our configuration file and fetch the modules we need.
29 |
30 | We will use [npm](https://www.npmjs.com/) (Node Package Manager) for that:
31 |
32 | ```sh
33 | # init the project. When prompted leave the defaults
34 | $ npm init
35 | ```
36 | This will produce *package.json* which holds info about the project and it's dependencies.
37 |
38 | Speaking of which our dependency for this project would be [express](http://www.expressjs.com).
39 |
40 | ```
41 | # installs the express module to the ./node_modules folder
42 | # --save adds it to the dependencies in package.json
43 | $ npm install --save express
44 | ```
45 |
46 | ## Hello Express
47 |
48 | Open server.js and add the following code:
49 |
50 | ```javascript
51 | "use strict"
52 |
53 | // require the dependencies
54 | var express = require('express');
55 |
56 | // declare the app
57 | var app = express();
58 |
59 | // TODO: configure the app
60 |
61 | // add the routes
62 | app.get('/', function (req, res) {
63 | res.send('Hello World!');
64 | })
65 |
66 | // launch the server
67 | var server = app.listen(3000, function () {
68 |
69 | var host = server.address().address;
70 | var port = server.address().port;
71 |
72 | console.log('Example app listening at http://%s:%s', host, port);
73 |
74 | })
75 |
76 | ```
77 |
78 | Next run the example with *node* and check the result at http://localhost:3000/
79 |
80 | ```sh
81 | $ node server.js
82 | ```
83 |
84 | Nice we have running our first node server. Oh wait wasn't this a front-end course.
85 |
86 | ## Go Public
87 |
88 | With our example above we set up a server that prints out "Hello World" everytime someone opens the base url. In order to be able to serve different *static* files such as htmls, styles, images we eighter need to add another route for each or we can just use the middleware express graciously provided.
89 |
90 | Just add the following code in the "configure the app section":
91 | ```javascript
92 | // configure the app
93 | app.use(express.static('public'));
94 | ```
95 |
96 | Next let's create the public folder, in it an index.html file.
97 | ```sh
98 | # Look ma, all in 1 line
99 | $ mkdir public; touch public/index.html
100 | ```
101 |
102 | Also add the hello world message there:
103 | ```html
104 |
105 | Hello World!
106 | ```
107 |
108 | And remove or comment the old route in *server.js* so that it doesn't conflict with *index.html*
109 | ```javascript
110 | // add the routes
111 | /*app.get('/', function (req, res) {
112 | res.send('Hello World!');
113 | })*/
114 | ```
115 |
116 | Save, restart and check the browser again.
117 |
118 | Well basically the same message. Shall we spice things up a bit.
119 |
120 | ## Bower up
121 |
122 | If you remember we used [npm](www.npmjs.com) to manage our dependencies for the server.
123 |
124 | Now that we have created a public folder for our front-end needs we need a front-end package manager.
125 |
126 | [Bower](bower.io) is our app. Pretty much works the same way as npm.
127 |
128 | Speaking of npm we will need it to install bower globally so that we can use it in all our projects.
129 | ```sh
130 | # -g stands for gangsta
131 | npm install -g bower
132 | ```
133 |
134 | Next we need to configure a directory for our front-end libs. Create(touch) the file .bowerrc and add the following content to it:
135 | ```json
136 | {
137 | "directory": "public/lib"
138 | }
139 | ```
140 |
141 | Next we be initing
142 | ```sh
143 | # same as npm, produces bower.json
144 | $ bower init
145 | ```
146 |
147 | Alright let's add an awesome lib to mark our first steps in bower.
148 | ```sh
149 | # adds the lib to public/lib and saves the dependency to bower.json
150 | $ bower install --save fontawesome
151 | ```
152 |
153 | Our directory structure should look something like this:
154 | ```
155 | .
156 | ├── server.js
157 | ├── package.json
158 | └── node_modules
159 | │ └── express
160 | ├── .bowerrc
161 | ├── bower.json
162 | └── public
163 | ├── index.html
164 | └── lib
165 | └── fontawesome
166 | ```
167 |
168 | Awesome, [Font Awesome](http://fontawesome.io/)
169 |
170 | Add to top things off add a nice icon to compliment our message:
171 |
172 | ```html
173 |
174 |
175 | Hello World!
176 | ```
177 |
--------------------------------------------------------------------------------
/week2/README.md:
--------------------------------------------------------------------------------
1 | # Week 2 Data Types & Operations
2 |
3 | ## Basic Syntax
4 |
5 | ### Variables
6 |
7 | As you know, variables are defined with the `var` keyword.
8 |
9 | ```javascript
10 | var a = 5;
11 | var b = 6;
12 |
13 | console.log(a + b);
14 | ```
15 |
16 | Variables have types but the types are hidden from us since JavaScript is a dynamic language.
17 |
18 | We can have functions, numbers, strings, lists, objects and so on.
19 |
20 | ```javascript
21 | // numbers
22 | var n = 5;
23 |
24 | // strings
25 | var str = "JavaScript is Awesome!";
26 |
27 | // arrays / lists
28 | var list = [1,2,3];
29 |
30 | // functions
31 | var f = function(x) {
32 | return x * x;
33 | };
34 |
35 | // objects - they serve as dictionaries
36 | var courses = {
37 | "FrontendJavaScript" : "https://github.com/HackBulgaria/Frontend-JavaScript-1/",
38 | "Core Java" : "https://github.com/HackBulgaria/Core-Java-1"
39 | };
40 | ```
41 |
42 | ### Function Scope for variables
43 |
44 | In languages like C / C++, Java, C#, etc. - we have block scope visibility for variables.
45 |
46 | That means, if we create a new variable inside a for-loop, it won't be visible outside it:
47 |
48 | ```c
49 | for(int i = 0; i < 10; i++) {
50 | // something with i
51 | }
52 |
53 | // i is not visible here
54 | printf("%d", i);
55 | ```
56 |
57 | __In JavaScript, a variable is visible to the enclosing function!__
58 |
59 | For example:
60 |
61 | ```javascript
62 | var arr = [1,2,3];
63 | for(var i = 0; i < arr.length; i++) {
64 | console.log(arr[i]);
65 | }
66 |
67 | // i is visible
68 | // this will print 3
69 | console.log(i);
70 | ```
71 |
72 | We have something called __variable hoisting__. All `var` statements are moved to the top of the enclosing function, but the value is assigned later, in the original place of the `var` statement
73 |
74 | The code above is translated to:
75 |
76 | ```javascript
77 | var arr = [1,2,3];
78 | var i; // undefined
79 |
80 | for(i = 0; i < arr.length; i++) {
81 | console.log(arr[i]);
82 | }
83 |
84 | // i is visible
85 | // this will print 3
86 | console.log(i);
87 | ```
88 |
89 | ### Iterating arrays
90 |
91 | In JavaScript, we have a standard for-loop:
92 |
93 | ```javascript
94 | var
95 | arr = [1,2,3],
96 | i = 0,
97 | n = arr.length;
98 |
99 | for(i; i < n; i++) {
100 | // do something with arr[i]
101 | }
102 | ```
103 |
104 | But also, we have something far more powerful - a [`forEach` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) of the array object:
105 |
106 | ```javascript
107 | var arr = [1,2,3];
108 |
109 | arr.forEach(function(value, index, arr) {
110 | // do something with value
111 | console.log(value);
112 | });
113 | ```
114 |
115 | `forEach` takes a function (__we call this callback__) and calls the given function for every item in the array.
116 |
117 | The function is called with 3 arguments:
118 |
119 | * `value` - which is the current item in the array
120 | * `index` - which is the index of the current value in the array
121 | * `array` - the array itself.
122 |
123 | `forEach` is a method. Since everything in JavaScript is a function, we have methods for most of our types.
124 |
125 | ### Iterating objects
126 |
127 | Objects in JavaScript can serve as dictionaries (hash tables) where the key can be string.
128 | __In JavaScript, objects cannot have keys with different types than a string.__
129 |
130 | A fully functioning hash table is coming in the next version of JavaScript.
131 |
132 | To iterate an object, we can use a `for .. in` loop:
133 |
134 | ```javascript
135 | var courses = {
136 | "FrontendJavaScript" : "https://github.com/HackBulgaria/Frontend-JavaScript-1/",
137 | "Core Java" : "https://github.com/HackBulgaria/Core-Java-1"
138 | };
139 |
140 | for(var course in courses) {
141 | console.log("A link for " + course + " can be found here - " + courses[course]);
142 | };
143 | ```
144 |
145 | Later, we will find out that `for .. in` loop goes one step further and returns object properties that we do not want.
146 |
147 | Another way to iterate is to use the `Object.keys()` method, which returns all keys from a given object.
148 |
149 | For example:
150 |
151 | ```javascript
152 | var courses = {
153 | "FrontendJavaScript" : "https://github.com/HackBulgaria/Frontend-JavaScript-1/",
154 | "Core Java" : "https://github.com/HackBulgaria/Core-Java-1"
155 | };
156 |
157 | console.log(Object.keys(courses)); // [ 'FrontendJavaScript', 'Core Java' ]
158 | ```
159 |
160 | Knowing that arrays have `forEach` method, we can do the following:
161 |
162 | ```javascript
163 | var courses = {
164 | "FrontendJavaScript" : "https://github.com/HackBulgaria/Frontend-JavaScript-1/",
165 | "Core Java" : "https://github.com/HackBulgaria/Core-Java-1"
166 | };
167 |
168 | // we can skip the index and array arguments
169 | Object.keys(courses).forEach(function(value) {
170 | console.log("A link for " + value + " can be found here - " + courses[value])
171 | });
172 | ```
173 |
174 | ## Sorting Arrays
175 |
176 | It is a good idea to read the documentation about sort - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
177 |
178 |
179 | The default sort sorts the items lexicographically.
180 |
181 |
182 | Check this out:
183 |
184 | ```javascript
185 | var scores = [1, 2, 10, 21];
186 | scores.sort(); // [1, 10, 2, 21]
187 | ```
188 |
189 | If you want to sort numbers, you have to give a comparator function:
190 |
191 | ```javascript
192 | var numbers = [4, 2, 5, 1, 3];
193 | numbers.sort(function(a, b) {
194 | return a - b;
195 | });
196 | console.log(numbers);
197 | ```
198 |
199 | ### TODO String Operations, String/Array Conversions
--------------------------------------------------------------------------------
/week2/hangout/crud.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | // dependencies
3 | var prompt = require('prompt');
4 | var jsonfile = require('jsonfile');
5 | var chalk = require('chalk');
6 |
7 | // file to store users
8 | var usersFile = 'data/users.json';
9 |
10 | // searchable fields
11 | var searchableFields = ["name", "email"];
12 |
13 | // value colors
14 | var valueColors = {
15 | "number" : "blue",
16 | "string" : "yellow"
17 | }
18 |
19 | // collection with users
20 | var users = [
21 | {
22 | id: 123,
23 | name: "Alex",
24 | email: "alex@i4web.biz"
25 | },
26 | {
27 | id: 456,
28 | name: "Gosho",
29 | email: "gosho@test.com"
30 | }
31 | ];
32 |
33 | // collection with commands
34 | var commands = [
35 | {"menu": "list"},
36 | {"menu": "add"},
37 | {"menu": "get"},
38 | {"menu": "update"},
39 | {"menu": "remove"},
40 | {"menu": "load"},
41 | {"menu": "save"},
42 | {"menu": "quit"}
43 | ];
44 |
45 | // util functions
46 | // reset screen
47 | function resetScreen() {
48 | return process.stdout.write('\x1Bc');
49 | }
50 |
51 | function createMold(length){
52 | var mold = "|";
53 | for(var i=1; i<=length; i++){
54 | mold += " ";
55 | }
56 | mold += "|";
57 | return mold;
58 | }
59 |
60 | function buildSeparator(lengths){
61 | var output = "";
62 | lengths.forEach(function(length){
63 | for(var i=1; i<=length+2; i++){
64 | output += "-";
65 | }
66 | })
67 | console.log(output);
68 | }
69 |
70 | function buildColumn(value, length, color){
71 | var mold = createMold(length);
72 | var fmtValue = (color) ? chalk[color](value) : value;
73 | return mold.substr(0,2) + fmtValue + mold.substr(value.length+2);
74 | }
75 |
76 | function buildHeader(item, lengths){
77 | var output = "";
78 | Object.keys(item).forEach(function(key, index){
79 | output += buildColumn(key, lengths[index], "red")
80 | });
81 | console.log(output);
82 | }
83 |
84 | function buildRow(item, lengths){
85 | var output = "";
86 | Object.keys(item).forEach(function(key, index){
87 |
88 | var value = String(item[key]);
89 | var color = valueColors[typeof(item[key])] || false;
90 |
91 | output += buildColumn(value, lengths[index], color)
92 | });
93 | console.log(output);
94 | }
95 |
96 |
97 | function calculateLengths(items){
98 | var maxLengths = [];
99 | items.forEach(function(item, index) {
100 | Object.keys(item).forEach(function(key, keyIndex){
101 | var value = String(item[key]);
102 | if(!maxLengths[keyIndex] || value.length+2 > maxLengths[keyIndex]){
103 | maxLengths[keyIndex] = value.length+2;
104 | }
105 | })
106 | })
107 | return maxLengths;
108 | }
109 |
110 | // build table
111 | function buildTable(items){
112 | var lengths = calculateLengths(items);
113 | buildSeparator(lengths)
114 | buildHeader(items[0], lengths);
115 | buildSeparator(lengths)
116 | items.forEach(function(item, index) {
117 | buildRow(item, lengths);
118 | })
119 | buildSeparator(lengths)
120 | }
121 |
122 | // get functions
123 | // show list
124 | function showList(){
125 | buildTable(users);
126 | }
127 |
128 | function selectIndexById(arr, id){
129 | // var to store matched index
130 | var matchIndex = false;
131 |
132 | // select element by id
133 | arr.forEach(function(item, index) {
134 | if(item.id == id){
135 | matchIndex = index;
136 | }
137 | });
138 |
139 | return matchIndex;
140 | }
141 |
142 | // get by id
143 | function promptGetById(){
144 | prompt.get(['id'], function (err, result) {
145 |
146 | var id = result.id;
147 |
148 | // var to store matched index
149 | var matchIndex = selectIndexById(users, id);
150 |
151 | // display it
152 | if(matchIndex !== false){
153 | buildTable([users[matchIndex]]);
154 | } else {
155 | console.log("Could not find user");
156 | }
157 |
158 | // prompt for next command
159 | promptMenuCommand();
160 |
161 | });
162 | }
163 |
164 | // search
165 | function promptSearch(){
166 | prompt.get(['keyword'], function(err, result){
167 |
168 | var keyword = result.keyword;
169 |
170 | var matchedItems = [];
171 |
172 | users.forEach(function(item, index) {
173 | var hasMatch = false;
174 | searchableFields.forEach(function(field){
175 | if(item[field].match(keyword)){
176 | hasMatch = true;
177 | }
178 | })
179 | if(hasMatch){
180 | matchedItems.push(item);
181 | }
182 | });
183 |
184 | if(matchedItems.length > 0)
185 | buildTable(matchedItems);
186 | else
187 | console.log("Could not find matches!");
188 |
189 | promptMenuCommand();
190 |
191 | })
192 | }
193 |
194 | // update by id
195 | function promptUpdateById(){
196 | prompt.get(['id','field','value'], function (err, result) {
197 |
198 | if(!result.id || !result.field || result.value === undefined){
199 | console.log("id, field, value are required");
200 | promptUpdateById();
201 | return false;
202 | }
203 |
204 | var id = result.id;
205 | var field = result.field;
206 | var value = result.value;
207 |
208 | // var to store matched index
209 | var matchIndex = selectIndexById(users, id);
210 |
211 | // update entry
212 | if(matchIndex !== false){
213 | var oldValue = users[matchIndex][field];
214 |
215 | users[matchIndex][field] = value;
216 |
217 | console.log("Successfully changed the value of "+field
218 | +" from "+oldValue+" to "+value+" for id "+id);
219 |
220 | console.log(users[matchIndex]);
221 |
222 | } else {
223 | console.log("Could not find user");
224 | }
225 |
226 | // prompt for next command
227 | promptMenuCommand();
228 |
229 | });
230 | }
231 |
232 | // remove
233 | function promptRemoveById(){
234 | prompt.get(['id'], function (err, result) {
235 |
236 | var id = result.id;
237 |
238 | // var to store matched index
239 | var matchIndex = selectIndexById(users, id);
240 |
241 | // remove it
242 | if(matchIndex !== false){
243 | users.splice(matchIndex, 1);
244 | console.log("Successfully removed user for id "+id);
245 |
246 | // show updated list
247 | showList();
248 |
249 | } else {
250 | console.log("Could not find user");
251 | }
252 |
253 | // prompt for next command
254 | promptMenuCommand();
255 |
256 | });
257 | }
258 |
259 | // add item
260 | function promptAddItem(){
261 |
262 | //
263 | console.log("Enter item to add:");
264 |
265 | prompt.get(['id','name','email'], function (err, result) {
266 |
267 | users.push(result);
268 | console.log("Successfully added user!");
269 |
270 | // show updated list
271 | showList();
272 |
273 | // prompt for next command
274 | promptMenuCommand();
275 |
276 | });
277 | }
278 |
279 | function loadFromFile(){
280 | users = jsonfile.readFileSync(usersFile);
281 |
282 | }
283 |
284 | function saveToFile(){
285 | jsonfile.writeFileSync(usersFile, users);
286 | }
287 |
288 |
289 | // quit
290 | function quit(){
291 | console.log("See you soon!");
292 | }
293 |
294 | // show menu
295 | function showMenu(){
296 | buildTable(commands);
297 | }
298 |
299 | // prompt menu command
300 | function promptMenuCommand(){
301 |
302 | console.log("")
303 | showMenu();
304 |
305 | prompt.get(['command'], function (err, result) {
306 |
307 | resetScreen();
308 |
309 | if(result === undefined){
310 | return quit();
311 | }
312 |
313 | var command = result.command;
314 |
315 | switch(command){
316 | case "list":
317 | showList();
318 | promptMenuCommand();
319 | break;
320 | case "add":
321 | promptAddItem();
322 | break;
323 | case "get":
324 | promptGetById();
325 | break;
326 | case "search":
327 | promptSearch();
328 | break;
329 | case "update":
330 | promptUpdateById();
331 | break;
332 | case "remove":
333 | promptRemoveById();
334 | break;
335 | case "load":
336 | loadFromFile();
337 | promptMenuCommand();
338 | break;
339 | case "save":
340 | saveToFile();
341 | promptMenuCommand();
342 | break;
343 | case "quit":
344 | quit();
345 | break;
346 | default:
347 | console.log("Unrecognized command!");
348 | promptMenuCommand();
349 | break;
350 | }
351 |
352 | });
353 |
354 | }
355 |
356 |
357 | // code
358 | prompt.start();
359 |
360 | promptMenuCommand();
361 |
--------------------------------------------------------------------------------