├── .gitignore ├── .vscode └── settings.json ├── DOCS.md ├── LICENSE ├── README.md ├── _redirects ├── css └── taino.css ├── favicon.ico ├── images ├── taino-cemi.svg └── taino-sun.svg ├── index.html ├── js ├── about.js ├── contact.js ├── docs.js ├── docs │ └── spa_and_server.js ├── faq.js ├── fourohfour.js ├── home.js ├── license.js └── template.js ├── robots.txt ├── sitemap.xml └── taino.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": {} 3 | } -------------------------------------------------------------------------------- /DOCS.md: -------------------------------------------------------------------------------- 1 | #System documentation [live doc, not set in stone] 2 | 3 | - config [used for config defined variables] 4 | - final [used for build variables completed for rendering on initial page load] 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | 4 | Copyright (c) 2019 https://taino.netlify.app/license 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Taino-js 2 | Building Single-Page applications and websites with vanilla js 3 | 4 | Reason for the name: 5 | Frameworks have tried to abstract away from core javascript far too much and from our point of view we just don't need that much complexity. 6 | Most projects all start with a basic few needs and from there they're all just branches from the original vanilla. 7 | We simple need to create "good relatives" to vanilla js, just the Taino. 8 | 9 | Origin of the term: 10 | Taino is a term referring to the indigenous peoples of the carribean. It's original meaning is "relatives" and "good people" and these are considered to be part of the Arawak natives of south america and the carribean. 11 | https://en.wikipedia.org/wiki/Arawak 12 | https://www.researchgate.net/publication/296694496_Origins_of_the_word_Taino 13 | 14 | # TUTORIALS: 15 | Initial Setup: 16 | - Click the green "clone or download" button top right. Make sure to select the "taino_base" branch and download it. 17 | - To run on your local machine, you will need to be running a server. 18 | For these steps we use Node JS => https://nodejs.org/ 19 | And run a SPA the simplest way on Node is to use Live Server => https://www.npmjs.com/package/live-server 20 | - Once downloaded use the terminal to navigate to the directory your copy of the code is in and run 21 | this command: live-server --port=8080 --entry-file=index.html 22 | - A copy of this website should open in your default browser, ready to go. 23 | - You can now modify this to your heart's content. 24 | - Read more at https://taino.netlify.com 25 | 26 | 27 | # CURRENT FEATURES: 28 | - It lets you build websites, fast, any website, almost. What else do ya need? ;) 29 | 30 | # TO-DO: 31 | - State handling 32 | - Expand pupper [site crawler and flat file builder for Taino] and setup its repo. 33 | 34 | # STRUCTURE: 35 | - taino.js [loads core functionality, contains all route definitions] 36 | - /css/taino.css [should be your main CSS file for the project, components can make use of their own CSS but we recommend it being in the main file so it's cached on first load] 37 | - template.js [defines header and footer and any other shared template objects you want to have, eg. popup forms, slide in cart, etc Also shared functions/methods eg. for setting active states on page load] 38 | - /js/ contains all layouts/components/pages 39 | 40 | -------------------------------------------------------------------------------- /_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /css/taino.css: -------------------------------------------------------------------------------- 1 | *{box-sizing:border-box;} 2 | html,body{width:100%;min-height:100vh; font-size:16px;margin:0;padding:0;color:#000;background:#1D2838;} 3 | html{text-rendering:optimizeLegibility !important;} 4 | 5 | /*colors 6 | Green - #00FF40 7 | DarkGreen - #00A128 8 | DarkBg - #0D1219 9 | LightBg -#1D2838 10 | */ 11 | /*FONTS*/ 12 | body{font-family: 'Oswald', sans-serif; letter-spacing:0.1rem;} 13 | 14 | /*GENERAL RULES*/ 15 | h1{margin:0; font-size:4rem; } 16 | h2{} 17 | h3{} 18 | ul{list-style-type:none;margin:0;padding:0} 19 | ul.l{text-align:left; list-style-type: disc; margin-left: 40px;} 20 | a{color:#C59952; text-decoration:none; } 21 | a:hover{ color:rgb(235, 148, 10);} 22 | .hidden{display:none;opacity:0} 23 | #tainomain{min-height:500px;} 24 | .goback{float:left; color:#C59952;padding:0.5rem 1rem; border-radius:4px; box-shadow: 0px 0px 5px rgba(13, 18, 25,0.8);background:rgb(13, 18, 25); cursor:pointer;} 25 | .goback:hover, .goback:active{color:#fff;} 26 | 27 | /*TEMPLATE*/ 28 | header{position:relative; z-index:2; width:100%; background:rgb(13, 18, 25); text-align:center; height:80px; padding-top:50px;} 29 | header nav{width:96%; max-width:1200px; margin:0 auto; height:40px; } 30 | header nav a{height:40px; line-height:40px;display:inline-block; vertical-align:top; padding:0 12px; margin:0 0.4rem; font-size:16px; color:#123; background:#ddd; text-align:center; text-transform:uppercase; font-weight:bold; box-shadow:3px 3px #00A128; transition:all 0.1s;} 31 | header nav a:hover,header nav a.active{color:#123; box-shadow:6px 6px #00FF40;} 32 | footer{width:100%; background:#333; color:#fff; text-align:center; height:100px; padding:20px;} 33 | footer a{color:#fff;} 34 | footer a:hover{color:#fff;} 35 | footer a:hover:before{content:"<"; color:#fff; text-decoration:none;} 36 | footer a:hover:after{content:">"; color:#fff; text-decoration:none;} 37 | 38 | /*PAGES*/ 39 | .pagewrap{position:relative; overflow:hidden; z-index:1; margin:0 auto; min-height:80vh; width:100%; padding:4rem; font-size:20px; text-align:center; color:#fff; } 40 | .pagewrap:before{content:' '; position:absolute; top:0; right:0; width:40vw; height:40vw; transform:rotate(-40deg); background:url(../images/taino-cemi.svg) no-repeat top right; background-size:contain; opacity:0.4; z-index:-1;} 41 | .pagewrap:after{content:' '; position:absolute; top:5vh; left:5vw; width:40vw; height:40vw; transform:rotate(-30deg); background:url(../images/taino-sun.svg) no-repeat top right; background-size:contain; opacity:0.4; z-index:-1;} 42 | .pagewrap .content{padding:2rem; width:90%; max-width:1200px; margin:0 auto 40px auto;background:rgba(13, 18, 25,0.8); box-shadow:0px 0px 5px #00A128; border-radius:4px;} 43 | .pagewrap .content a.btn{color:#fff; padding:0.5rem 1rem; border-radius:4px; box-shadow: 0px 0px 5px #C59952; background: rgba(13, 18, 25,0.8);} 44 | .pagewrap .content a.btn:hover:before{content:"<"; color:#fff; text-decoration:none;} 45 | .pagewrap .content a.btn:hover:after{content:">"; color:#fff; text-decoration:none;} 46 | .home .content{border:0; background:none; box-shadow:none;} 47 | .home h1 span{display:block; font-size:2.5rem; font-weight:normal; font-style:italic; color:#00A128; } 48 | .home .two-blocks{display:flex; justify-content:space-around; flex-wrap:wrap;} 49 | .home .two-blocks .block{width:48%; max-width:600px; box-shadow:0px 0px 5px #00A128; border-radius:4px; padding:.4rem; background:rgba(13, 18, 25,0.8); } 50 | .about .pagewrap{ } 51 | .contact .pagewrap{ } 52 | 53 | 54 | @media screen and (max-width:960px){ 55 | h1{margin:0 0.5rem 1rem 0.5rem; font-size:2.5rem; } 56 | h2{margin:0 0.5rem 1rem 0.5rem; font-size:1.5rem;} 57 | .pagewrap{padding:4rem 2rem;} 58 | .home .two-blocks .block{width:90%; margin-bottom:1rem;} 59 | } 60 | @media screen and (max-width:640px){ 61 | header{padding-top:30px;} 62 | header nav a{margin-bottom:12px;} 63 | .pagewrap{padding:4rem 0.5rem;} 64 | .pagewrap:before{display:none;} 65 | .pagewrap:after{display:none;} 66 | } -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ravavyr/taino-js/2d7adf4453bdd762284d7f7186e7d5c5b19287a5/favicon.ico -------------------------------------------------------------------------------- /images/taino-cemi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 21 | 30 | 39 | 48 | 57 | 66 | 75 | 84 | 93 | 94 | 95 | 104 | 105 | 114 | 115 | 116 | 125 | 134 | 143 | 152 | 161 | 170 | 179 | 188 | 197 | 206 | 207 | 208 | 217 | 226 | 235 | 244 | 253 | 262 | 271 | 280 | 289 | 298 | 299 | 300 | 309 | 318 | 327 | 336 | 345 | 354 | 363 | 372 | 381 | 390 | 391 | 392 | 401 | 410 | 419 | 428 | 437 | 446 | 455 | 464 | 473 | 482 | 483 | 484 | 493 | 502 | 511 | 520 | 529 | 538 | 547 | 556 | 565 | 574 | 575 | 576 | 585 | 594 | 603 | 612 | 621 | 630 | 639 | 648 | 657 | 666 | 667 | 668 | 677 | 686 | 695 | 704 | 713 | 722 | 731 | 740 | 749 | 758 | 759 | 760 | 769 | 778 | 787 | 796 | 805 | 814 | 823 | 832 | 841 | 850 | 851 | 852 | 853 | 862 | 871 | 880 | 889 | 898 | 907 | 916 | 925 | 934 | 943 | 944 | 945 | 946 | 947 | 1054 | 1071 | 1078 | 1088 | 1089 | 1090 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --- 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /js/about.js: -------------------------------------------------------------------------------- 1 | class aboutLoader { 2 | constructor(site) { 3 | this.title = "We are the Taino!"; 4 | this.meta_desc = "About the Taino JS Framework"; 5 | this.starthtml = ` 6 |
7 |

About TainoJS

8 |
9 |

10 | It's a simple codebase built on vanilla javascript. 11 |

12 |

TainoJS is the brainchild of Ravavyr.

13 |

14 | I've been coding websites and web applications since 2005 and in that time I've noticed how everything has shifted towards making things easier for non-developers to do, and for new developers to use. 15 | This is a great concept, but at the same time web development has been over-abstracted and over-engineered to this end goal that is frankly unachievable. 16 |

17 | You have all seen the bulky and bloated sites out there, full of popups and tracking scripts that the owners don't understand. 18 | Libraries on top of frameworks that contain 100k lines of code, where maybe 5k are being used to actually render the site. 19 | All because the team that built it didn't understand the tools they were using. 20 |

21 | The average person does not need to, nor wants to make websites. They want a website that does the things they want and does it well. 22 | Giving them these modern tools is like saying "Here's a scalpel, go be a surgeon". 23 | Imagine if we started selling "Surgery kits for amateurs" that come with big gloves and dulled scalpels that let you pretend to be a surgeon. 24 | You'd end up with the equivalent of the web today. A massacred pile of things you want to call successful surgeries. 25 |

26 | I propose we simplify the codebase we need to implement websites, but require developers to still learn the basic languages behind web development. 27 | For frontend this is specifically HTML/CSS/Vanilla JS. 28 | In the end, this is what every single website and web application renders. 29 | We can use simple tools while producing beautiful and performant websites we can feel proud of. 30 |

31 |

Why Taino

32 |

33 | In looking for a name for what I was building I wanted it to relate to my origins as a native of the carribean. 34 | When I came across the term Taino and its meaning “relatives”, it just felt like the right name as this project is meant to give developers multiple ways to approach building sites and applications by starting with a codebase setup relative to their end goals. 35 |

36 | Taino is a term referring to the indigenous people of the carribean. 37 | It's original meaning is "relatives" and "good people" and these were considered to be part of the Arawak natives of south america and the carribean. 38 | For more information: See Wikipedia and also The origins of the word Taino 39 |

40 |
41 |
42 | `; 43 | this.loaddata(); 44 | } 45 | 46 | async loaddata(){ 47 | templateLoader.updatemainnav('about'); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /js/contact.js: -------------------------------------------------------------------------------- 1 | class contactLoader { 2 | constructor(site) { 3 | this.title = "Contact us about TainoJS"; 4 | this.meta_desc = "Contact us about TainoJS"; 5 | this.starthtml = ` 6 |
7 |

Contact us about TainoJS

8 |
9 | As this project is just starting out, please contact Ravavyr with any questions or comments.

10 | Twitter: @Ravavyr

11 | Email: Ravavyr{at}gmail.com 12 |
13 |
14 | `; 15 | this.loaddata(); 16 | } 17 | 18 | async loaddata(){ 19 | templateLoader.updatemainnav('contact'); 20 | } 21 | } -------------------------------------------------------------------------------- /js/docs.js: -------------------------------------------------------------------------------- 1 | class docsLoader { 2 | constructor(site) { 3 | this.title = "How to use Taino JS"; 4 | this.meta_desc = "Examples for uses of the Taino JS Framework"; 5 | this.starthtml = ` 6 |
7 |

Taino 101

8 |
9 |

10 | The Source Code lives here and is open source:
11 | https://github.com/Ravavyr/taino-js
12 | The branches mentioned below can be downloaded there. 13 |

14 |

15 |

Initial Requirements

16 | 21 |

22 |
23 |
24 |

25 |

Installing any Branch

26 | 34 |

35 |
36 |
37 |

38 |

Current Branches

39 | 44 |

Coming Soon:

45 | 50 |

51 |
52 |
53 | `; 54 | this.loaddata(); 55 | } 56 | 57 | async loaddata(){ 58 | templateLoader.updatemainnav('docs'); 59 | } 60 | } -------------------------------------------------------------------------------- /js/docs/spa_and_server.js: -------------------------------------------------------------------------------- 1 | class docs_spa_and_serverLoader { 2 | constructor(site) { 3 | this.title = "SPA and Servers"; 4 | this.meta_desc = "Explanation of Single Page Applications and servers"; 5 | this.starthtml = ` 6 |
7 |

SPA and Servers

8 |
9 |

10 |

11 | Here are two great articles explaining what a SPA is, how it talks to a server and how it all ties together to run singe page applications.
12 | https://blog.pshrmn.com/how-single-page-applications-work/
13 | https://blog.pshrmn.com/single-page-applications-and-the-server/ 14 | 15 |

16 |
17 |
18 | `; 19 | this.loaddata(); 20 | } 21 | 22 | async loaddata(){ 23 | templateLoader.updatemainnav('docs'); 24 | } 25 | } -------------------------------------------------------------------------------- /js/faq.js: -------------------------------------------------------------------------------- 1 | class faqLoader { 2 | constructor(site) { 3 | this.title = "Questions about TainoJS"; 4 | this.meta_desc = "Questions and answers about the TainoJS"; 5 | this.starthtml = ` 6 |
7 |

Frequently Asked Questions about TainoJS

8 |
9 |

Why did you make TainoJS?

10 |

11 | Existing frameworks have tried to abstract away from core vanilla javascript far too much and from our point of view it is not necessary. 12 | We simply need to create "good relatives" to vanilla js, just the Taino. 13 |

14 |

What does Taino mean?

15 |

16 | Taino is a term referring to the indigenous peoples of the carribean. 17 | It's original meaning is "relatives" and "good people" and these were considered to be part of the Arawak natives of south america and the carribean. 18 | For more information: See Wikipedia and also The origins of the word Taino 19 |

20 |

Why should I use TainoJS?

21 |

22 | You will be able to build any website or web app without a massive learning curve. You only need to know HTML/CSS/Javascript. 23 | Taino itself is made to be as simple as possible when compared to other frameworks.

24 | Save yourself time and often money. 25 |

26 |
27 |
28 | `; 29 | this.loaddata(); 30 | } 31 | 32 | async loaddata(){ 33 | templateLoader.updatemainnav('faq'); 34 | } 35 | } -------------------------------------------------------------------------------- /js/fourohfour.js: -------------------------------------------------------------------------------- 1 | class fourohfourLoader { 2 | constructor(site) { 3 | this.title = "Page Not Found"; 4 | this.meta_desc = "Page Not Found"; 5 | this.starthtml = ` 6 |

Page not Found, Shoo!

7 |

8 | Ok, so not Shoo, but seriously the url you found doesn't exist. 9 |

10 |

Use the menu to find content :)

11 |
12 | `; 13 | this.loaddata(); 14 | } 15 | 16 | loaddata(){ 17 | site.addmeta('robots','noindex'); 18 | } 19 | } -------------------------------------------------------------------------------- /js/home.js: -------------------------------------------------------------------------------- 1 | class homeLoader { 2 | constructor(site) { 3 | this.title = "Welcome to the Taino!"; 4 | this.meta_desc = "Taino is a vanilla javascript codebase written to build fast Single-Page applications and websites."; 5 | this.starthtml = ` 6 |
7 |

Taino JS A simple code base for making websites

8 |
9 | Get Started With Taino! 10 |
11 | 12 |
13 |
14 |

Our Purpose

15 |

16 | The goal was to create a script/framework/library that would allow anyone to quickly build websites using minimal html/css/javascript 17 |

We miss when the web was simple to code for, so we're bringing it back. 18 |

19 |
20 |
21 |

Why should I use it?

22 |

23 | You will be able to build any website or web app without a massive learning curve. You only need to know HTML/CSS/Javascript. 24 | Taino itself is made to be as simple as possible when compared to other frameworks.

25 | Save yourself time and often money. 26 |

27 |
28 |
29 |
30 | Get Started! 31 |
32 | 33 |
34 | `; 35 | this.loaddata(); 36 | } 37 | 38 | async loaddata(){ 39 | templateLoader.updatemainnav('home'); 40 | } 41 | } -------------------------------------------------------------------------------- /js/license.js: -------------------------------------------------------------------------------- 1 | class licenseLoader { 2 | constructor(site) { 3 | this.title = "Taino Has a License"; 4 | this.meta_desc = "Taino has a license!"; 5 | this.starthtml = ` 6 |
7 |

TainoJS Usage License

8 |
9 |

10 |

The MIT License

11 |

12 | Copyright (c) 2019 https://taino.netlify.app/license 13 |

14 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 15 |

16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 17 |

18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 |

20 |
21 |
22 | `; 23 | } 24 | } -------------------------------------------------------------------------------- /js/template.js: -------------------------------------------------------------------------------- 1 | class templateLoader { 2 | constructor(site) { 3 | this.header = ` 4 |
5 | 12 |
13 | `; 14 | this.footer = ` 15 | 19 | `; 20 | } 21 | 22 | static updatemainnav(linkname){ 23 | let curlink = taino.el('header nav a[data-active="'+linkname+'"]')[0]; 24 | if(curlink){ 25 | if(taino.el('header nav a.active').length>0){ taino.el('header nav a.active')[0].classList.remove("active"); } 26 | curlink.classList.add("active"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://taino.netlify.com/sitemap.xml -------------------------------------------------------------------------------- /sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://taino.netlify.com/ 5 | weekly 6 | 2019-12-19T00:00:10+00:00 7 | 8 | 9 | https://taino.netlify.com/about 10 | weekly 11 | 2019-12-19T00:00:10+00:00 12 | 13 | 14 | https://taino.netlify.com/docs 15 | weekly 16 | 2019-12-19T00:00:10+00:00 17 | 18 | 19 | https://taino.netlify.com/frequently-asked-questions 20 | weekly 21 | 2019-12-19T00:00:10+00:00 22 | 23 | 24 | https://taino.netlify.com/contact 25 | weekly 26 | 2019-12-19T00:00:10+00:00 27 | 28 | -------------------------------------------------------------------------------- /taino.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /*Run this baby: live-server --port=8080 --entry-file=index.html*/ 3 | 4 | class taino{ 5 | constructor(routes) { 6 | /*define taino global vars, mostly endpoints and public creds*/ 7 | this.jspath = '/js'; 8 | this.csspath = '/css'; 9 | this.header = ''; /*sitewide header defined in template.js or wherever*/ 10 | this.footer = ''; /*sitewide footer defined in template.js or wherever*/ 11 | this.templatefile = '/template'; 12 | 13 | /*define state variable and initial states*/ 14 | this.state = {}; 15 | 16 | /*define current location object*/ 17 | this.cur = {}; 18 | 19 | this.routes = Object.keys(routes) 20 | .sort(function(a,b){ return b.length - a.length; }) 21 | .map(function(path) { 22 | return { 23 | path: new RegExp("^" + path.replace(/:[^\s/]+/g, '([\\w%+-]+)') + "$"), 24 | module: routes[path] 25 | }; 26 | }); 27 | this.routevars=[]; 28 | 29 | this.components = new Map(); 30 | 31 | /*on browser load, identify current location object*/ 32 | this.currentpage = this.getcurrent(window.location.pathname); 33 | this.main = window.document.body; /*defaults to body if no id is set*/ 34 | if(document.getElementById('tainomain')!=null){ 35 | this.main.content = document.getElementById('tainomain'); 36 | }else{ 37 | let maindiv = document.createElement('div'); 38 | maindiv.setAttribute('id','tainomain'); 39 | this.main.appendChild(maindiv); 40 | this.main.content = document.getElementById('tainomain'); 41 | } 42 | //beforebegin, afterbegin, afterend 43 | window.addEventListener('popstate', (event) => { 44 | this.update(); 45 | }); 46 | 47 | const mutationObserver = new MutationObserver(() => { 48 | this.defaultlisteners(); 49 | }); 50 | 51 | mutationObserver.observe(document, { 52 | childList: true, 53 | }); 54 | 55 | var resizeTimer; 56 | window.addEventListener("resize", (event) => { 57 | var t =this; 58 | if(typeof(resizeTimer)!='undefined'){ clearTimeout(resizeTimer); } 59 | resizeTimer = setTimeout(function() { 60 | if(taino.ismobile() ===false){ 61 | t.loadtemplate(); 62 | t.update(); 63 | } 64 | },250); 65 | }); 66 | } 67 | 68 | 69 | createLoader(loader){ 70 | if(typeof window[loader] !== "function") { 71 | return Function("site", `return new ${loader}(site)`)(this); /*filename+'Loader' has to be the main class.*/ 72 | } 73 | throw new Error(`${loader} constructor does not exist!`); 74 | } 75 | 76 | /*additional scripts are loaded via callbacks*/ 77 | loadScript(url){ 78 | /* 79 | This script returns a promise that resolves when the requested script loads 80 | or rejects if the requested script doesn't load (think 404 error) 81 | having a rejection on error allows us to potentially redirect gracefully to a 404 page or what have you. 82 | */ 83 | if(taino.el('script[data-pageid="'+url+'"]')){ 84 | // script already exists. return a resolved promise. 85 | return Promise.resolve() 86 | }else{ 87 | let resolve = null 88 | let reject = null 89 | let scriptPromise = new Promise((res,rej)=>{ 90 | resolve = res; 91 | reject = rej; 92 | }); 93 | let body = document.body; 94 | let script = document.createElement('script'); 95 | script.async = false; 96 | script.type = 'text/javascript'; 97 | script.src = url; 98 | script.dataset.pageid = url; 99 | script.onreadystatechange = resolve; 100 | script.onload = resolve; 101 | script.onerror = reject; 102 | body.appendChild(script); 103 | return scriptPromise; 104 | } 105 | } 106 | 107 | getcurrent(path){ 108 | let curr = '/fourohfour'; /*Need to make this have a 404 header*/ 109 | for (var i = 0, l = this.routes.length; i < l; i++) { 110 | var found = path.replace(".html","").match(this.routes[i].path); 111 | if(found){ 112 | this.removemeta("robots"); 113 | curr ="/"+this.routes[i].module; // module to load 114 | this.routevars = found.slice(1); // arguments for module 115 | break; 116 | } 117 | } 118 | return curr; 119 | } 120 | 121 | loadtemplate(){ 122 | if(taino.el("body > header").length>0){ taino.el("body > header")[0].remove(); } 123 | if(taino.el("body > footer").length>0){ taino.el("body > footer")[0].remove(); } 124 | const callback = () =>{ 125 | var loader = this.templatefile.replace("/","") + 'Loader'; 126 | this.templateobject = this.createLoader(loader) /*filename+'Loader' has to be the main class.*/ 127 | this.main.header = this.templateobject.header; 128 | this.main.footer = this.templateobject.footer; 129 | this.main.content.insertAdjacentHTML('beforebegin',this.main.header); 130 | this.main.content.insertAdjacentHTML('afterend',this.main.footer); 131 | } 132 | return this.loadScript(this.jspath+this.templatefile+'.js').then(callback); 133 | } 134 | 135 | loadcontent(){ 136 | this.main.setAttribute("class",this.currentpage.replace(/\//gi,'')); 137 | var loader = this.currentpage.substr(1).replace(/\//gi,'_') + 'Loader'; 138 | var hashforanchor = window.location.hash.substr(1); 139 | if(this.cur.constructor.name && this.cur.constructor.name===loader){ 140 | this.cur = this.createLoader(loader) /*filename+'Loader' has to be the main class.*/ 141 | this.main.content.innerHTML = this.cur.starthtml; 142 | document.title = this.cur.title; 143 | taino.el('meta[name=description]').setAttribute("content",this.cur.meta_desc); 144 | this.defaultlisteners(); 145 | this.loadstyling(loader); 146 | if(taino.elid(hashforanchor)){ 147 | window.scrollBy(0, taino.elid(hashforanchor).offsetTop); 148 | } 149 | }else{ 150 | this.loadScript(this.jspath+this.currentpage+'.js').then(() => { 151 | this.cur = this.createLoader(loader) /*filename+'Loader' has to be the main class.*/ 152 | this.main.content.innerHTML = this.cur.starthtml; 153 | document.title = this.cur.title; 154 | taino.el('meta[name=description]').setAttribute("content",this.cur.meta_desc); 155 | this.defaultlisteners(); 156 | this.loadstyling(loader); 157 | if(taino.elid(hashforanchor)){ 158 | window.scrollBy(0, taino.elid(hashforanchor).offsetTop); 159 | } 160 | }); 161 | } 162 | } 163 | 164 | update(){ 165 | var path =window.location.pathname; 166 | this.currentpage = this.getcurrent(path); 167 | this.loadScript(this.jspath+this.currentpage+'.js').then(()=>{ 168 | this.loadcontent(); 169 | window.scrollTo(0,0); 170 | }); 171 | } 172 | 173 | route(path){ 174 | for (var i = 0, l = this.routes.length; i < l; i++) { 175 | var found = path.match(this.routes[i].path); 176 | if(found){ 177 | window.history.pushState({"html": this.main.innerHTML, "pageTitle": this.cur.title}, "", path); 178 | this.update(); 179 | break; 180 | } 181 | } 182 | } 183 | 184 | static el(x, getall){ 185 | var s = x.trim(); 186 | if(s.indexOf(",") > -1 || s.indexOf(" ") > -1 || getall===true){ 187 | return document.querySelectorAll(s); 188 | }else{ 189 | return document.querySelector(s); 190 | } 191 | } 192 | 193 | static elid(x){ 194 | return document.getElementById(x); 195 | } 196 | 197 | defaultlisteners(){ 198 | let as = taino.el("a:not(.cap)",true); /*recapture A tags when content reloads*/ 199 | for(let i=0; i { 204 | if ( 205 | e.ctrlKey || 206 | e.shiftKey || 207 | e.metaKey || // apple 208 | (e.button && e.button == 1) // middle click, >IE9 + everyone else 209 | ){ 210 | return; 211 | } 212 | e.preventDefault(); 213 | let href = as[i].href; 214 | let pathName = new URL(href); 215 | if(pathName.hostname === linkhost){ 216 | window.history.pushState({}, pathName, href); 217 | this.update(); 218 | }else{ 219 | window.location.href = pathName; 220 | } 221 | return false; 222 | }); 223 | } 224 | } 225 | 226 | loadstyling(loader){ /*loads in styling from a component*/ 227 | if(!this.cur.styling){return ;} 228 | else{ 229 | if(!taino.el('style.tainocss_'+loader)){ 230 | let body = document.body; 231 | let style = document.createElement('style'); 232 | style.type = 'text/css'; 233 | style.classList.add('tainocss_'+loader); 234 | style.innerHTML=this.cur.styling; 235 | body.appendChild(style); 236 | } 237 | } 238 | } 239 | 240 | static sanitize(str) { 241 | let temp = document.createElement('div'); 242 | temp.textContent = str; 243 | return temp.innerHTML; 244 | } 245 | 246 | addmeta(name, content){ 247 | var newmeta = document.createElement("meta"); 248 | newmeta.name=name; 249 | newmeta.content=content; 250 | document.head.appendChild(newmeta); 251 | } 252 | 253 | removemeta(name){ 254 | var oldmeta = taino.el("meta[name="+name+"]"); 255 | if(oldmeta){ 256 | oldmeta.remove(); 257 | } 258 | } 259 | 260 | static ismobile() { 261 | var useragent = navigator.userAgent; 262 | if(useragent.match(/Android|iPhone|iPad/i)){ 263 | return true; 264 | } else { 265 | return false; 266 | } 267 | } 268 | }; 269 | 270 | /*define routes*/ 271 | let routes = { 272 | '/':'home', 273 | '/about':'about', 274 | '/docs':'docs', 275 | '/docs/spa_and_server':'docs/spa_and_server', 276 | '/frequently-asked-questions':'faq', 277 | '/contact':'contact', 278 | '/mit-license':'license' 279 | } 280 | 281 | const site = new taino(routes); 282 | site.loadtemplate(); 283 | site.loadcontent(); 284 | --------------------------------------------------------------------------------