├── .DS_Store ├── README.md └── examples ├── .DS_Store ├── AudioPlayer ├── High Energy beats.mp3 ├── High Energy beats.wav ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── main.js │ └── style.css └── vite.config.js ├── Canvas1 ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-plugin-timemark.js ├── src │ ├── filtering.js │ ├── fonts │ │ ├── OFL.txt │ │ └── Tapestry-Regular.ttf │ ├── images │ │ └── background.jpg │ ├── main.js │ └── styles │ │ ├── common.scss │ │ ├── fonts.scss │ │ └── main.scss └── vite.config.js ├── ChromeExtension ├── 1 │ ├── README.md │ ├── html │ │ ├── hello.html │ │ ├── popup.html │ │ └── settings.html │ ├── icons │ │ ├── alert.png │ │ ├── icon-128.png │ │ ├── icon-16.png │ │ ├── icon-32.png │ │ └── icon-48.png │ ├── js │ │ ├── background.js │ │ ├── content.js │ │ ├── hello.js │ │ └── popup.js │ └── manifest.json └── 2 │ ├── README.md │ ├── css │ └── toastify.css │ ├── html │ └── settings.html │ ├── icons │ ├── alert.png │ ├── icon-128.png │ ├── icon-16.png │ ├── icon-32.png │ └── icon-48.png │ ├── js │ ├── background.js │ ├── content.js │ └── toastify.js │ └── manifest.json ├── IntersectionObserver ├── .gitignore ├── README.md ├── css │ └── style.css ├── index.html ├── package-lock.json ├── package.json ├── public │ └── spinner.svg ├── src │ ├── api.js │ ├── components │ │ ├── comment.js │ │ ├── post.js │ │ └── user.js │ ├── examples │ │ ├── example1.js │ │ ├── example2.js │ │ ├── example3.js │ │ ├── example4.js │ │ ├── example5.js │ │ ├── index.js │ │ ├── start.js │ │ └── start2.js │ ├── main.js │ └── tools.js └── vite.config.js ├── MutationObserver ├── .gitignore ├── README.md ├── css │ └── style.css ├── index.html ├── package-lock.json ├── package.json ├── public │ └── spinner.svg ├── src │ ├── examples │ │ ├── example1.js │ │ ├── example2.js │ │ ├── example3.js │ │ └── index.js │ ├── main.js │ └── tools.js └── vite.config.js ├── ProxyAndReflect ├── .gitignore ├── README.md ├── index.html ├── javascript.svg ├── main.js ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── code1.js │ ├── code2.js │ └── code3.js ├── style.css └── vite.config.js ├── ServiceWorker ├── README.md ├── assets │ ├── image-1.png │ ├── image-2.png │ ├── image-3.png │ ├── image-4.png │ └── image-5.png ├── css │ └── style.css ├── index.html ├── index.js ├── package.json ├── page1.html ├── page2.html ├── page3.html ├── public │ └── sw.js └── vite.config.js ├── SortChallenge ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-plugin-timemark.js ├── src │ ├── algorithms │ │ ├── binaryTreeSort.js │ │ ├── bubbleSort.js │ │ ├── coctailSort.js │ │ ├── combSort.js │ │ ├── gnomeSort.js │ │ ├── heapSort.js │ │ ├── insertionSort.js │ │ ├── introSort.js │ │ ├── mergeSort.js │ │ ├── quickJsSort.js │ │ ├── quickSort.js │ │ ├── selectionSort.js │ │ ├── shellSort.js │ │ ├── smoothSort.js │ │ ├── stoogeSort.js │ │ └── timSort.js │ ├── chartEngine.js │ ├── fonts │ │ ├── OFL.txt │ │ └── Tapestry-Regular.ttf │ ├── images │ │ └── background.jpg │ ├── main.js │ └── styles │ │ ├── common.scss │ │ ├── fonts.scss │ │ └── main.scss └── vite.config.js ├── Symbols ├── README.md ├── index.html ├── package.json ├── src │ ├── examples │ │ ├── example1.js │ │ ├── example10.js │ │ ├── example11.js │ │ ├── example12.js │ │ ├── example2.js │ │ ├── example3.js │ │ ├── example4.js │ │ ├── example5.js │ │ ├── example6.js │ │ ├── example7.js │ │ ├── example8.js │ │ ├── example9.js │ │ └── index.js │ └── index.js └── vite.config.js ├── TagLiteral ├── README.md └── index.html ├── WasmRust ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── index.js │ └── tools.js ├── vite.config.js ├── wasm-src │ └── lib.rs └── wasm_image_editor │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── lib.rs ├── WebRTS ├── .vscode │ └── launch.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── simple.html ├── src │ ├── client │ │ └── stream.js │ ├── server │ │ ├── server.js │ │ └── streams.js │ ├── streamer.js │ ├── utils.js │ └── viewer.js ├── streamer.html ├── viewer.html └── vite.config.js ├── WebSocket ├── .vscode │ └── launch.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── client │ │ ├── main.js │ │ ├── messages.js │ │ ├── style.css │ │ ├── usersList.js │ │ └── websocket.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ └── server │ │ ├── server.js │ │ ├── streams.js │ │ └── utils.js └── vite.config.js ├── WebWorker ├── example1.js ├── example2.js ├── index.html ├── index.js ├── index2.html ├── index2.js ├── package-lock.json ├── package.json ├── vite.config.js └── webworker.js ├── WebWorker2 ├── index.html ├── package.json ├── scheme.pdf ├── src │ ├── appConstants.js │ └── index.js └── vite.config.js ├── arrow-functions ├── .gitignore ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── example1.js │ ├── example2.js │ ├── example3.js │ ├── example4.js │ ├── example5.js │ ├── favicon.ico │ ├── index.js │ └── tools.js └── vite.config.js ├── drag-n-drop ├── .gitignore ├── README.md ├── package.json ├── public │ └── index.html ├── src │ ├── components │ │ ├── cell.js │ │ ├── data.json │ │ ├── row.js │ │ └── table.js │ └── main.js └── webpack.config.js ├── generator ├── index.html ├── index1.html ├── index2.html ├── index3.html ├── index4.html ├── index5.html └── src │ ├── generator1.js │ ├── generator3.js │ ├── generator4.js │ ├── generator5.js │ ├── index1.js │ ├── index2.js │ ├── index3.js │ ├── index4.js │ └── index5.js ├── macro-micro ├── example1.js ├── example2.js ├── example3.js ├── index.html ├── index.js ├── package-lock.json ├── package.json └── vite.config.js ├── pagination ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-plugin-timemark.js ├── server.mjs ├── src │ ├── fonts │ │ ├── OFL.txt │ │ └── Tapestry-Regular.ttf │ ├── images │ │ └── background.jpg │ ├── js │ │ ├── api.js │ │ ├── constants.js │ │ ├── example1.js │ │ ├── example2.js │ │ ├── example3.js │ │ ├── example4.js │ │ ├── main.js │ │ ├── main2.js │ │ └── todo.js │ └── styles │ │ ├── common.scss │ │ ├── fonts.scss │ │ └── main.scss └── vite.config.js ├── redux1 ├── .gitignore ├── README.md ├── package.json ├── public │ └── index.html ├── src │ ├── components │ │ ├── cell.js │ │ ├── row.js │ │ └── table.js │ ├── data │ │ └── data.json │ ├── main.js │ └── redux │ │ ├── actions.js │ │ ├── reducer.js │ │ └── store.js └── webpack.config.js ├── snowfall_css ├── README.md ├── img │ ├── background1.png │ ├── background2.png │ └── background3.png └── index.html └── spa ├── bonus1 ├── REST_server │ ├── README.md │ ├── db.json │ ├── mongo-config.conf │ ├── mongodb │ │ └── fake.txt │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ └── generateDB.js │ ├── server-config.json │ ├── server.js │ └── src │ │ ├── common │ │ ├── constants.js │ │ └── utils.js │ │ ├── decorators.js │ │ ├── handlers │ │ ├── auth │ │ │ ├── auth.js │ │ │ └── index.js │ │ ├── comments │ │ │ ├── comments.js │ │ │ └── index.js │ │ ├── posts │ │ │ ├── index.js │ │ │ └── posts.js │ │ └── users │ │ │ ├── index.js │ │ │ └── users.js │ │ ├── plugins │ │ ├── awt-plugin.js │ │ └── swagger-plugin.js │ │ └── routes │ │ ├── auth-routes.js │ │ ├── comments-routes.js │ │ ├── index.js │ │ ├── posts-routes.js │ │ ├── schemas │ │ ├── allSchemas.js │ │ ├── comment.js │ │ ├── pagination.js │ │ ├── post.js │ │ ├── querystrings.js │ │ └── user.js │ │ └── users-routes.js └── generateDB │ ├── README.md │ ├── db.json │ ├── index.js │ └── package.json ├── bonus2 ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── authApi.js │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── app-component.js │ │ ├── comment-component.js │ │ ├── date-formatted.js │ │ ├── fake-form.js │ │ ├── index.js │ │ ├── link-component.js │ │ ├── list-component.js │ │ ├── modal-dialog.js │ │ ├── nav-component.js │ │ ├── pagination-component.js │ │ ├── post-component.js │ │ ├── post-detail.js │ │ ├── user-avatar.js │ │ └── user-component.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── main │ │ │ ├── bottom.template │ │ │ ├── left.template │ │ │ ├── right.template │ │ │ └── top.template │ │ ├── post.template │ │ ├── posts.template │ │ ├── user.template │ │ ├── userComments.template │ │ ├── userPosts.template │ │ └── users.template │ ├── router │ │ └── index.js │ ├── service │ │ ├── comments.js │ │ ├── posts.js │ │ └── users.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part1 ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part2 ├── README.md ├── index.html ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── index.js │ │ ├── link-component.js │ │ └── nav-component.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part3 ├── README.md ├── db.json ├── index.html ├── package-lock.json ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── index.js │ │ ├── link-component.js │ │ └── nav-component.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part4 ├── README.md ├── db.json ├── index.html ├── package-lock.json ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── index.js │ │ ├── link-component.js │ │ ├── nav-component.js │ │ ├── pagination-component.js │ │ ├── post-component.js │ │ ├── posts-component.js │ │ └── user-avatar.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ ├── service │ │ └── posts.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part5 ├── README.md ├── db.json ├── index.html ├── package-lock.json ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── index.js │ │ ├── link-component.js │ │ ├── nav-component.js │ │ ├── pagination-component.js │ │ ├── post-component.js │ │ ├── posts-component.js │ │ └── user-avatar.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ ├── service │ │ └── posts.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part6 ├── README.md ├── db.json ├── index.html ├── package-lock.json ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── index.js │ │ ├── link-component.js │ │ ├── list-component.js │ │ ├── nav-component.js │ │ ├── pagination-component.js │ │ ├── post-component.js │ │ ├── posts-component.js │ │ ├── user-avatar.js │ │ └── user-component.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── posts.template │ │ └── users.template │ ├── router │ │ └── index.js │ ├── service │ │ ├── posts.js │ │ └── users.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js ├── part7 ├── README.md ├── db.json ├── index.html ├── package.json ├── plugins │ └── vite-template-plugin.js ├── src │ ├── api │ │ ├── baseApi.js │ │ ├── commentsApi.js │ │ ├── index.js │ │ ├── postsApi.js │ │ └── usersApi.js │ ├── common │ │ ├── constants.js │ │ └── utils.js │ ├── components │ │ ├── comment-component.js │ │ ├── date-formatted.js │ │ ├── index.js │ │ ├── link-component.js │ │ ├── list-component.js │ │ ├── nav-component.js │ │ ├── pagination-component.js │ │ ├── post-component.js │ │ ├── post-detail.js │ │ ├── user-avatar.js │ │ └── user-component.js │ ├── index.js │ ├── pages │ │ ├── main.template │ │ ├── post.template │ │ ├── posts.template │ │ ├── user.template │ │ ├── userComments.template │ │ ├── userPosts.template │ │ └── users.template │ ├── router │ │ └── index.js │ ├── service │ │ ├── comments.js │ │ ├── posts.js │ │ └── users.js │ └── styles │ │ ├── common.scss │ │ └── main.scss └── vite.config.js └── part8 ├── README.md ├── db.json ├── index.html ├── package.json ├── plugins └── vite-template-plugin.js ├── src ├── api │ ├── baseApi.js │ ├── commentsApi.js │ ├── index.js │ ├── postsApi.js │ └── usersApi.js ├── common │ ├── constants.js │ └── utils.js ├── components │ ├── app-component.js │ ├── comment-component.js │ ├── date-formatted.js │ ├── fake-form.js │ ├── index.js │ ├── link-component.js │ ├── list-component.js │ ├── modal-dialog.js │ ├── nav-component.js │ ├── pagination-component.js │ ├── post-component.js │ ├── post-detail.js │ ├── user-avatar.js │ └── user-component.js ├── index.js ├── pages │ ├── main.template │ ├── main │ │ ├── bottom.template │ │ ├── left.template │ │ ├── right.template │ │ └── top.template │ ├── post.template │ ├── posts.template │ ├── user.template │ ├── userComments.template │ ├── userPosts.template │ └── users.template ├── router │ └── index.js ├── service │ ├── comments.js │ ├── posts.js │ └── users.js └── styles │ ├── common.scss │ └── main.scss └── vite.config.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/.DS_Store -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/.DS_Store -------------------------------------------------------------------------------- /examples/AudioPlayer/High Energy beats.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/AudioPlayer/High Energy beats.mp3 -------------------------------------------------------------------------------- /examples/AudioPlayer/High Energy beats.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/AudioPlayer/High Energy beats.wav -------------------------------------------------------------------------------- /examples/AudioPlayer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audioanalize", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^6.2.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/AudioPlayer/src/style.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | gap: 10px; 4 | align-items: center; 5 | margin: 10px 0; 6 | } 7 | 8 | .input-holder { 9 | display: flex; 10 | gap: 10px; 11 | align-items: center; 12 | } 13 | 14 | .audio-holder { 15 | display: grid; 16 | grid-template-columns: auto 100px 300px; 17 | } 18 | 19 | #audio{ 20 | width: 100%; 21 | } -------------------------------------------------------------------------------- /examples/AudioPlayer/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | host: '0.0.0.0', 6 | port: 3000, 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/Canvas1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Image editor 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/Canvas1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-it-vitejs-setup", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "serve": "vite preview --port 3000", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "browserslist": [ 14 | "cover 99.5%" 15 | ], 16 | "author": "", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "@vitejs/plugin-legacy": "^5.2.0", 20 | "sass": "^1.69.6", 21 | "vite": "^5.0.10" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/Canvas1/src/fonts/Tapestry-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/Canvas1/src/fonts/Tapestry-Regular.ttf -------------------------------------------------------------------------------- /examples/Canvas1/src/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/Canvas1/src/images/background.jpg -------------------------------------------------------------------------------- /examples/Canvas1/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | @import 'fonts.scss'; 2 | 3 | body { 4 | margin: 0; 5 | padding: 0; 6 | background-image: url(../images/background.jpg); 7 | } 8 | 9 | .page-header{ 10 | text-align: center; 11 | font-family: 'Square Peg', cursive; 12 | font-size: 50px; 13 | } 14 | 15 | .image-block{ 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | } -------------------------------------------------------------------------------- /examples/Canvas1/src/styles/fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Tapestry'; 3 | src: local('Tapestry'), url(../fonts/Tapestry-Regular.ttf) format('truetype'); 4 | } 5 | 6 | @import url('https://fonts.googleapis.com/css2?family=Square+Peg&display=swap'); -------------------------------------------------------------------------------- /examples/Canvas1/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import legacy from "@vitejs/plugin-legacy"; 3 | import timeMarkPlugin from "./plugins/vite-plugin-timemark"; 4 | 5 | export default defineConfig({ 6 | build: { 7 | target: "es2017", 8 | outDir: "build", 9 | rollupOptions: { 10 | output: { 11 | assetFileNames: ({ name }) => { 12 | if (/\.(gif|jpe?g|png|svg)$/.test(name ?? "")) { 13 | return "assets/images/[name]-[hash][extname]"; 14 | } 15 | 16 | if (/\.(ttf|otf|fnt|woff)$/.test(name ?? "")) { 17 | return "assets/fonts/[name]-[hash][extname]"; 18 | } 19 | 20 | if (/\.css$/.test(name ?? "")) { 21 | return "assets/css/[name]-[hash][extname]"; 22 | } 23 | 24 | return "assets/[name]-[hash][extname]"; 25 | }, 26 | }, 27 | }, 28 | }, 29 | server: { 30 | port: 3000, 31 | host: "0.0.0.0", 32 | hmr: true, 33 | }, 34 | plugins: [ 35 | legacy({ 36 | targets: ["defaults", "not IE 11"], 37 | }), 38 | timeMarkPlugin(), 39 | ], 40 | }); 41 | -------------------------------------------------------------------------------- /examples/ChromeExtension/1/html/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

EasyIt Extension - settings

4 |
5 | A lot of settings could be here ;) 6 |
7 | 8 | -------------------------------------------------------------------------------- /examples/ChromeExtension/1/icons/alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/1/icons/alert.png -------------------------------------------------------------------------------- /examples/ChromeExtension/1/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/1/icons/icon-128.png -------------------------------------------------------------------------------- /examples/ChromeExtension/1/icons/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/1/icons/icon-16.png -------------------------------------------------------------------------------- /examples/ChromeExtension/1/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/1/icons/icon-32.png -------------------------------------------------------------------------------- /examples/ChromeExtension/1/icons/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/1/icons/icon-48.png -------------------------------------------------------------------------------- /examples/ChromeExtension/1/js/hello.js: -------------------------------------------------------------------------------- 1 | const onClick = async(e) => { 2 | let queryOptions = { active: true, lastFocusedWindow: true }; 3 | const [tab] = await chrome.tabs.query(queryOptions) 4 | chrome.tabs.remove(tab.id) 5 | } 6 | 7 | const btn = document.querySelector('.ok-button') 8 | if(btn){ 9 | btn.addEventListener('click', onClick) 10 | } 11 | -------------------------------------------------------------------------------- /examples/ChromeExtension/2/html/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

EasyIt Extension - settings

4 |
5 | A lot of settings could be here ;) 6 |
7 | 8 | -------------------------------------------------------------------------------- /examples/ChromeExtension/2/icons/alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/2/icons/alert.png -------------------------------------------------------------------------------- /examples/ChromeExtension/2/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/2/icons/icon-128.png -------------------------------------------------------------------------------- /examples/ChromeExtension/2/icons/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/2/icons/icon-16.png -------------------------------------------------------------------------------- /examples/ChromeExtension/2/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/2/icons/icon-32.png -------------------------------------------------------------------------------- /examples/ChromeExtension/2/icons/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ChromeExtension/2/icons/icon-48.png -------------------------------------------------------------------------------- /examples/ChromeExtension/2/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "EasyIt Extension", 4 | "description": "EasyIt Extension - clipboard", 5 | "version": "1.0", 6 | "author": "EasyIT development", 7 | "action": { 8 | "default_title": "Enable Clipboard handling", 9 | "default_icon": "icons/icon-32.png" 10 | }, 11 | "icons": { 12 | "16": "icons/icon-16.png", 13 | "32": "icons/icon-32.png", 14 | "48": "icons/icon-48.png", 15 | "128": "icons/icon-128.png" 16 | }, 17 | "content_scripts": [ 18 | { 19 | "js": [ 20 | "js/content.js", 21 | "js/toastify.js" 22 | ], 23 | "css": [ 24 | "css/toastify.css" 25 | ], 26 | "matches": [ 27 | "" 28 | ] 29 | } 30 | ], 31 | "permissions": [ 32 | "tabs", 33 | "activeTab", 34 | "storage", 35 | "contextMenus" 36 | ], 37 | "host_permissions": [ 38 | "" 39 | ], 40 | "background": { 41 | "service_worker": "js/background.js" 42 | } 43 | } -------------------------------------------------------------------------------- /examples/IntersectionObserver/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/IntersectionObserver/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Intersection Observer examples 8 | 9 | 10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/IntersectionObserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intersectionobserver", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^5.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/IntersectionObserver/src/components/comment.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/IntersectionObserver/src/components/comment.js -------------------------------------------------------------------------------- /examples/IntersectionObserver/src/components/post.js: -------------------------------------------------------------------------------- 1 | export const createPost = (postData) => { 2 | 3 | const post = document.createElement('div') 4 | post.dataset.postId = postData.id; 5 | post.dataset.userId = postData.userId; 6 | post.className = 'post' 7 | post.innerHTML = ` 8 |

${postData.title}

9 |
${postData.body}
10 | ` 11 | return post 12 | } -------------------------------------------------------------------------------- /examples/IntersectionObserver/src/examples/index.js: -------------------------------------------------------------------------------- 1 | export { default as start } from "./start"; 2 | export { default as start2 } from "./start2"; 3 | export { default as example1 } from "./example1"; 4 | export { default as example2 } from "./example2"; 5 | export { default as example3 } from "./example3"; 6 | export { default as example4 } from "./example4"; 7 | export { default as example5 } from "./example5"; 8 | -------------------------------------------------------------------------------- /examples/IntersectionObserver/src/tools.js: -------------------------------------------------------------------------------- 1 | export const getUserAvatarUrl = (userName) => { 2 | return `https://api.dicebear.com/9.x/personas/svg?seed=${userName}`; 3 | }; 4 | -------------------------------------------------------------------------------- /examples/IntersectionObserver/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | port: 3000, 6 | host: '0.0.0.0' 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/MutationObserver/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/MutationObserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intersectionobserver", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^5.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/MutationObserver/src/examples/example1.js: -------------------------------------------------------------------------------- 1 | import { changeCanvas } from "../tools"; 2 | 3 | let div = null; 4 | let canvas = null; 5 | let context = null; 6 | let interval = null; 7 | 8 | 9 | const cleanUp = () => { 10 | if (interval) { 11 | clearInterval(interval); 12 | interval = null; 13 | } 14 | }; 15 | 16 | const run = () => { 17 | div = document.querySelector("#container"); 18 | canvas = document.querySelector("#canvas"); 19 | context = canvas.getContext("2d"); 20 | if (context) { 21 | // Проверяем размеры div каждую секунду 22 | interval = setInterval(()=>{changeCanvas({div, canvas, context})}, 1000); 23 | changeCanvas({div, canvas, context}); 24 | } 25 | return div; 26 | }; 27 | 28 | export default { 29 | run, 30 | cleanUp, 31 | }; 32 | -------------------------------------------------------------------------------- /examples/MutationObserver/src/examples/example2.js: -------------------------------------------------------------------------------- 1 | import { changeCanvas } from "../tools"; 2 | 3 | let div = null; 4 | let canvas = null; 5 | let context = null; 6 | let observer = null; 7 | 8 | const cleanUp = () => { 9 | if (observer) { 10 | observer.disconnect(); 11 | observer = null; 12 | } 13 | }; 14 | 15 | const run = () => { 16 | div = document.querySelector("#container"); 17 | canvas = document.querySelector("#canvas"); 18 | context = canvas.getContext("2d"); 19 | if (context && div) { 20 | // Создаем observer для отслеживания изменений стилей и атрибутов 21 | observer = new MutationObserver((mutations) => { 22 | mutations.forEach((mutation) => { 23 | if (mutation.type === "attributes") { 24 | changeCanvas({div, canvas, context}); 25 | } 26 | }); 27 | }); 28 | observer.observe(div, { attributes: true }); 29 | // Первоначальная настройка 30 | changeCanvas({div, canvas, context}); 31 | } 32 | return div; 33 | }; 34 | 35 | export default { 36 | run, 37 | cleanUp, 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /examples/MutationObserver/src/examples/index.js: -------------------------------------------------------------------------------- 1 | export { default as example1 } from "./example1"; 2 | export { default as example2 } from "./example2"; 3 | export { default as example3 } from "./example3"; 4 | -------------------------------------------------------------------------------- /examples/MutationObserver/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | port: 3000, 6 | host: '0.0.0.0' 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/ProxyAndReflect/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/ProxyAndReflect/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ProxyAndReflect/javascript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/ProxyAndReflect/main.js: -------------------------------------------------------------------------------- 1 | import code1 from './src/code1' 2 | import code2 from './src/code2' 3 | import code3 from './src/code3' 4 | 5 | 6 | // code1(); 7 | //code2(); 8 | code3(); 9 | -------------------------------------------------------------------------------- /examples/ProxyAndReflect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proxyandreflect", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^5.4.8" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/ProxyAndReflect/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | export default defineConfig({ 4 | server: { 5 | host: '0.0.0.0', 6 | port: 3000, 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/ServiceWorker/README.md: -------------------------------------------------------------------------------- 1 | # Web service example 2 | 3 | ## **Добавляем возможность офф-лайновой работы для любого сайта или веб приложения** 4 | 5 | 6 | ## Как пользоваться 7 | 8 | ``` 9 | npm install 10 | npm run build 11 | ``` 12 | или 13 | 14 | ``` 15 | npm install 16 | npm run start 17 | ``` 18 | 19 | или 20 | 21 | ``` 22 | npm run build 23 | cd build 24 | npx http-server-spa ./ ./index.html 5001 25 | ``` 26 | ## Видео с объяснением как это все работает здесь: 27 | https://youtu.be/bgp1NR0OXOA 28 | 29 | ## Еще по vitejs 30 | 31 | https://youtu.be/wIEauCguZGI 32 | https://youtu.be/t98Q9hliZZo 33 | https://youtu.be/aMzCDR_MHF0 34 | https://youtu.be/TZN6dC7ZOs0 35 | 36 | 37 | ## Полезные видео по настройке webpack: 38 | 39 | 40 | Минимальная конфигурация: 41 | 42 | https://youtu.be/unEl3Hezwpw 43 | 44 | Настройка горячей перезагрузки: 45 | 46 | https://youtu.be/oOpzkF2nU0s 47 | 48 | Настройка сборки проекта с подгрузкой файлов css/scss/изображений: 49 | 50 | https://youtu.be/3B-NGZmMe-Y 51 | 52 | Модульный принцип конфигурации проекта: 53 | 54 | https://youtu.be/fnUqyWyG5kk 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/ServiceWorker/assets/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ServiceWorker/assets/image-1.png -------------------------------------------------------------------------------- /examples/ServiceWorker/assets/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ServiceWorker/assets/image-2.png -------------------------------------------------------------------------------- /examples/ServiceWorker/assets/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ServiceWorker/assets/image-3.png -------------------------------------------------------------------------------- /examples/ServiceWorker/assets/image-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ServiceWorker/assets/image-4.png -------------------------------------------------------------------------------- /examples/ServiceWorker/assets/image-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/ServiceWorker/assets/image-5.png -------------------------------------------------------------------------------- /examples/ServiceWorker/css/style.css: -------------------------------------------------------------------------------- 1 | .links{ 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-around; 5 | } 6 | 7 | .links .link{ 8 | background-color: #aaa; 9 | padding: 5px 20px; 10 | color: #fff; 11 | } 12 | 13 | .links .link.selected{ 14 | background-color: #00a; 15 | } 16 | 17 | .links .link a{ 18 | text-decoration: none; 19 | color: #fff; 20 | } 21 | 22 | .links .link:hover a{ 23 | color: #eee; 24 | } 25 | 26 | .container { 27 | display: flex; 28 | flex-wrap: wrap; 29 | align-items: center; 30 | justify-content: center; 31 | } 32 | 33 | .container .card { 34 | display: flex; 35 | flex-direction: column; 36 | justify-content: center; 37 | align-items: center; 38 | padding: 10px; 39 | margin: 10px; 40 | border: 1px solid #ccc; 41 | border-radius: 8px; 42 | } 43 | 44 | .container .card .img{ 45 | 46 | } 47 | 48 | .container .card .text{ 49 | font-size: 20pt; 50 | color: rgba(0,0,0, 0.3); 51 | padding: 10px; 52 | } 53 | 54 | .container.page1{ 55 | flex-direction: row-reverse; 56 | } 57 | 58 | .container.page2{ 59 | flex-direction: column; 60 | } 61 | 62 | .container.page3{ 63 | flex-direction: column-reverse; 64 | } -------------------------------------------------------------------------------- /examples/ServiceWorker/index.js: -------------------------------------------------------------------------------- 1 | const onWorkerReady = () => { 2 | console.log('SW is ready'); 3 | } 4 | 5 | 6 | navigator.serviceWorker.register('sw.js'); 7 | 8 | navigator.serviceWorker.ready.then(onWorkerReady); 9 | -------------------------------------------------------------------------------- /examples/ServiceWorker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serviceworker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "vite": "^3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/ServiceWorker/vite.config.js: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | server: { 6 | host: "0.0.0.0", 7 | port: 5000, 8 | }, 9 | build: { 10 | target: "es2017", 11 | outDir: "build", 12 | rollupOptions: { 13 | input: { 14 | main: resolve(__dirname, "./index.html"), 15 | page1: resolve(__dirname, "./page1.html"), 16 | page2: resolve(__dirname, "./page2.html"), 17 | page3: resolve(__dirname, "./page3.html"), 18 | }, 19 | output: { 20 | assetFileNames: ({ name }) => { 21 | if (/\.(gif|jpe?g|png|svg)$/.test(name ?? "")) { 22 | return "assets/images/[name]-[hash][extname]"; 23 | } 24 | 25 | if (/\.(ttf|otf|fnt|woff)$/.test(name ?? "")) { 26 | return "assets/fonts/[name]-[hash][extname]"; 27 | } 28 | 29 | if (/\.css$/.test(name ?? "")) { 30 | return "assets/css/[name]-[hash][extname]"; 31 | } 32 | 33 | return "assets/[name]-[hash][extname]"; 34 | }, 35 | }, 36 | }, 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /examples/SortChallenge/README.md: -------------------------------------------------------------------------------- 1 | # Проверяем скорость работы различных алгоритмов сортировки 2 | 3 | 4 | ## Как пользоваться 5 | 6 | ``` 7 | npm install 8 | npm run start 9 | 10 | ``` 11 | 12 | ## Работающий пример (с некоторыми изменениями): 13 | https://easy-linux.github.io/sort/ 14 | 15 | ## Видео с объяснением как это все работает здесь: 16 | https://youtu.be/CmEoY7IcZbc 17 | 18 | ## Сайт где можно найти нужные шрифты: 19 | 20 | https://fonts.google.com/ 21 | 22 | ## Еще по vitejs 23 | 24 | https://youtu.be/wIEauCguZGI 25 | https://youtu.be/t98Q9hliZZo 26 | https://youtu.be/aMzCDR_MHF0 27 | https://youtu.be/TZN6dC7ZOs0 28 | 29 | 30 | ## Полезные видео по настройке webpack: 31 | 32 | 33 | Минимальная конфигурация: 34 | 35 | https://youtu.be/unEl3Hezwpw 36 | 37 | Настройка горячей перезагрузки: 38 | 39 | https://youtu.be/oOpzkF2nU0s 40 | 41 | Настройка сборки проекта с подгрузкой файлов css/scss/изображений: 42 | 43 | https://youtu.be/3B-NGZmMe-Y 44 | 45 | Модульный принцип конфигурации проекта: 46 | 47 | https://youtu.be/fnUqyWyG5kk 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /examples/SortChallenge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-it-vitejs-setup", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "serve": "vite preview --port 3000", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "browserslist": [ 14 | "cover 99.5%" 15 | ], 16 | "author": "", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "@vitejs/plugin-legacy": "^4.0.1", 20 | "sass": "^1.58.3", 21 | "vite": "^4.1.4" 22 | }, 23 | "dependencies": { 24 | "chart.js": "^4.2.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/bubbleSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Пузырьковая сортировка 3 | */ 4 | 5 | const bubbleSort = (arr) => { 6 | let len = arr.length; 7 | for (let i = 0; i < len; i++) { 8 | for (let j = 0; j < len - 1; j++) { 9 | if (arr[j] > arr[j + 1]) { 10 | let temp = arr[j]; 11 | arr[j] = arr[j + 1]; 12 | arr[j + 1] = temp; 13 | } 14 | } 15 | } 16 | return arr; 17 | } 18 | 19 | export default bubbleSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/coctailSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Сортировка перемешиванием 3 | */ 4 | 5 | const cocktailSort = (arr) => { 6 | let start = 0; 7 | let end = arr.length - 1; 8 | let swapped = true; 9 | 10 | while (swapped) { 11 | // Проход с начала к концу 12 | swapped = false; 13 | for (let i = start; i < end; i++) { 14 | if (arr[i] > arr[i + 1]) { 15 | let temp = arr[i]; 16 | arr[i] = arr[i + 1]; 17 | arr[i + 1] = temp; 18 | swapped = true; 19 | } 20 | } 21 | end--; 22 | 23 | // Проход с конца к началу 24 | for (let j = end; j > start; j--) { 25 | if (arr[j] < arr[j - 1]) { 26 | let temp = arr[j]; 27 | arr[j] = arr[j - 1]; 28 | arr[j - 1] = temp; 29 | swapped = true; 30 | } 31 | } 32 | start++; 33 | } 34 | 35 | return arr; 36 | } 37 | 38 | // Пример использования 39 | //let arr = [64, 34, 25, 12, 22, 11, 90]; 40 | //var sortedArr = cocktailSort(arr); 41 | //console.log(sortedArr); // [11, 12, 22, 25, 34, 64, 90] 42 | 43 | export default cocktailSort 44 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/combSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Сортировка расческой 3 | */ 4 | 5 | const combSort = (arr) => { 6 | const shrinkFactor = 1.3; 7 | let gap = arr.length; 8 | let swapped = true; 9 | while (gap > 1 || swapped) { 10 | gap = Math.floor(gap / shrinkFactor); 11 | if (gap < 1) { 12 | gap = 1; 13 | } 14 | swapped = false; 15 | let i = 0; 16 | while (i + gap < arr.length) { 17 | if (arr[i] > arr[i + gap]) { 18 | [arr[i], arr[i + gap]] = [arr[i + gap], arr[i]]; 19 | swapped = true; 20 | } 21 | i++; 22 | } 23 | } 24 | return arr; 25 | } 26 | 27 | export default combSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/gnomeSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Гномья сортировка 3 | */ 4 | 5 | const gnomeSort = (arr) => { 6 | let len = arr.length; 7 | let pos = 0; 8 | 9 | while (pos < len) { 10 | if (pos === 0 || arr[pos] >= arr[pos - 1]) { 11 | pos++; 12 | } else { 13 | let temp = arr[pos]; 14 | arr[pos] = arr[pos - 1]; 15 | arr[pos - 1] = temp; 16 | pos--; 17 | } 18 | } 19 | 20 | return arr; 21 | } 22 | 23 | export default gnomeSort 24 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/heapSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Пирамидальная сортировка 3 | */ 4 | 5 | const heapify = (arr, n, i) => { 6 | let largest = i; 7 | const left = 2 * i + 1; 8 | const right = 2 * i + 2; 9 | if (left < n && arr[left] > arr[largest]) { 10 | largest = left; 11 | } 12 | if (right < n && arr[right] > arr[largest]) { 13 | largest = right; 14 | } 15 | if (largest !== i) { 16 | [arr[i], arr[largest]] = [arr[largest], arr[i]]; 17 | heapify(arr, n, largest); 18 | } 19 | } 20 | 21 | const heapSort = (arr) => { 22 | const n = arr.length; 23 | for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { 24 | heapify(arr, n, i); 25 | } 26 | for (let i = n - 1; i > 0; i--) { 27 | [arr[0], arr[i]] = [arr[i], arr[0]]; 28 | heapify(arr, i, 0); 29 | } 30 | return arr; 31 | } 32 | 33 | export default heapSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/insertionSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Сортировка вставками 3 | */ 4 | 5 | const insertionSort = (arr) => { 6 | let len = arr.length; 7 | for (let i = 1; i < len; i++) { 8 | let key = arr[i]; 9 | let j = i - 1; 10 | while (j >= 0 && arr[j] > key) { 11 | arr[j + 1] = arr[j]; 12 | j--; 13 | } 14 | arr[j + 1] = key; 15 | } 16 | return arr; 17 | } 18 | 19 | export default insertionSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/mergeSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Сортировка слиянием 3 | */ 4 | 5 | function merge(left, right) { 6 | let result = []; 7 | while (left.length && right.length) { 8 | if (left[0] <= right[0]) { 9 | result.push(left.shift()); 10 | } else { 11 | result.push(right.shift()); 12 | } 13 | } 14 | while (left.length) { 15 | result.push(left.shift()); 16 | } 17 | while (right.length) { 18 | result.push(right.shift()); 19 | } 20 | return result; 21 | } 22 | 23 | const mergeSort = (arr) => { 24 | if (arr.length < 2) { 25 | return arr; 26 | } 27 | 28 | let middle = Math.floor(arr.length / 2); 29 | let left = arr.slice(0, middle); 30 | let right = arr.slice(middle); 31 | 32 | return merge(mergeSort(left), mergeSort(right)); 33 | } 34 | 35 | export default mergeSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/quickJsSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Быстрая JS сортировка 3 | */ 4 | 5 | const quickJsSort = (arr) => { 6 | return arr.sort((a, b) => { 7 | if (a > b) return 1; 8 | if (a < b) return -1; 9 | return 0; 10 | }); 11 | }; 12 | 13 | export default quickJsSort; 14 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/quickSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Быстрая сортировка 3 | */ 4 | 5 | const quickSort = (arr) => { 6 | if (arr.length <= 1) { 7 | return arr; 8 | } 9 | const pivot = arr[0]; 10 | const left = []; 11 | const right = []; 12 | for (let i = 1; i < arr.length; i++) { 13 | if (arr[i] < pivot) { 14 | left.push(arr[i]); 15 | } else { 16 | right.push(arr[i]); 17 | } 18 | } 19 | return [...quickSort(left), pivot, ...quickSort(right)]; 20 | } 21 | 22 | export default quickSort 23 | 24 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/selectionSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Сортировка выбором 3 | */ 4 | 5 | const selectionSort = (arr) => { 6 | for (let i = 0; i < arr.length; i++) { 7 | let minIndex = i; 8 | for (let j = i + 1; j < arr.length; j++) { 9 | if (arr[j] < arr[minIndex]) { 10 | minIndex = j; 11 | } 12 | } 13 | if (minIndex !== i) { 14 | [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; 15 | } 16 | } 17 | return arr; 18 | } 19 | 20 | export default selectionSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/shellSort.js: -------------------------------------------------------------------------------- 1 | /** 2 | Сортирвока Шелла 3 | */ 4 | 5 | const shellSort = (arr) => { 6 | let gap = Math.floor(arr.length / 2); 7 | while (gap > 0) { 8 | for (let i = gap; i < arr.length; i++) { 9 | let j = i; 10 | const temp = arr[i]; 11 | while (j >= gap && arr[j - gap] > temp) { 12 | arr[j] = arr[j - gap]; 13 | j -= gap; 14 | } 15 | arr[j] = temp; 16 | } 17 | gap = Math.floor(gap / 2); 18 | } 19 | return arr; 20 | } 21 | 22 | export default shellSort 23 | -------------------------------------------------------------------------------- /examples/SortChallenge/src/algorithms/stoogeSort.js: -------------------------------------------------------------------------------- 1 | /* 2 | Придурковатая сортировка 3 | */ 4 | 5 | const stoogeSort = (arr, l = 0, h = arr.length - 1) => { 6 | if (l >= h) { 7 | return arr; 8 | } 9 | 10 | // Если первый элемент меньше последнего, то меняем их местами 11 | if (arr[l] > arr[h]) { 12 | [arr[l], arr[h]] = [arr[h], arr[l]]; 13 | } 14 | 15 | // Если в массиве больше двух элементов 16 | if (h - l + 1 > 2) { 17 | const t = Math.floor((h - l + 1) / 3); 18 | 19 | // Рекурсивно сортируем первые 2/3 элементов 20 | arr = stoogeSort(arr, l, h - t); 21 | 22 | // Рекурсивно сортируем последние 2/3 элементов 23 | arr = stoogeSort(arr, l + t, h); 24 | 25 | // Рекурсивно сортируем первые 2/3 элементов снова 26 | arr = stoogeSort(arr, l, h - t); 27 | } 28 | 29 | return arr; 30 | } 31 | 32 | export default stoogeSort -------------------------------------------------------------------------------- /examples/SortChallenge/src/fonts/Tapestry-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/SortChallenge/src/fonts/Tapestry-Regular.ttf -------------------------------------------------------------------------------- /examples/SortChallenge/src/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/SortChallenge/src/images/background.jpg -------------------------------------------------------------------------------- /examples/SortChallenge/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | @import 'fonts.scss'; 2 | 3 | body { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | .page-header{ 9 | text-align: center; 10 | font-family: 'Square Peg', cursive; 11 | font-size: 50px; 12 | } 13 | 14 | .image-block{ 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | } -------------------------------------------------------------------------------- /examples/SortChallenge/src/styles/fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Tapestry'; 3 | src: local('Tapestry'), url(../fonts/Tapestry-Regular.ttf) format('truetype'); 4 | } 5 | 6 | @import url('https://fonts.googleapis.com/css2?family=Square+Peg&display=swap'); -------------------------------------------------------------------------------- /examples/SortChallenge/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | .all-links { 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | padding: 20px; 8 | user-select: none; 9 | 10 | a { 11 | padding: 20px; 12 | margin: 20px; 13 | background-color: #ddd; 14 | border-color: #00f; 15 | border-radius: 10px; 16 | min-width: 200px; 17 | text-align: center; 18 | text-decoration: none; 19 | color: black; 20 | font-weight: bold; 21 | font-size: 30px; 22 | font-family: Arial, Helvetica, sans-serif; 23 | 24 | &:hover{ 25 | font-style: italic; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /examples/SortChallenge/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import legacy from "@vitejs/plugin-legacy"; 3 | import timeMarkPlugin from "./plugins/vite-plugin-timemark"; 4 | 5 | export default defineConfig({ 6 | base: '', 7 | build: { 8 | target: "es2017", 9 | outDir: "build", 10 | rollupOptions: { 11 | output: { 12 | assetFileNames: ({ name }) => { 13 | if (/\.(gif|jpe?g|png|svg)$/.test(name ?? "")) { 14 | return "assets/images/[name]-[hash][extname]"; 15 | } 16 | 17 | if (/\.(ttf|otf|fnt|woff)$/.test(name ?? "")) { 18 | return "assets/fonts/[name]-[hash][extname]"; 19 | } 20 | 21 | if (/\.css$/.test(name ?? "")) { 22 | return "assets/css/[name]-[hash][extname]"; 23 | } 24 | 25 | return "assets/[name]-[hash][extname]"; 26 | }, 27 | }, 28 | }, 29 | }, 30 | server: { 31 | port: 3000, 32 | host: "0.0.0.0", 33 | hmr: true, 34 | }, 35 | plugins: [ 36 | legacy({ 37 | targets: ["defaults", "not IE 11"], 38 | }), 39 | timeMarkPlugin(), 40 | ], 41 | }); 42 | -------------------------------------------------------------------------------- /examples/Symbols/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Symbols examples 7 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/Symbols/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symbols", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "vite" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "vite": "^5.4.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example1.js: -------------------------------------------------------------------------------- 1 | const name = 'example1' 2 | 3 | const run = () => { 4 | const sym1 = Symbol(); 5 | const sym2 = Symbol('description'); 6 | 7 | console.clear() 8 | console.log(name) 9 | 10 | console.log(sym1); 11 | console.log(sym2); 12 | } 13 | 14 | export default { 15 | name, 16 | run, 17 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example10.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.toPrimitive' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | const obj1 = { 8 | value: 10, 9 | name: 'obj1', 10 | } 11 | const obj2 = { 12 | value: 20, 13 | name: 'obj2', 14 | } 15 | 16 | console.log('obj1 * obj2', obj1 * obj2) 17 | 18 | const toPrimitive = function(hint){ 19 | switch (hint) { 20 | case 'string': 21 | return this.name; 22 | case 'number': 23 | return this.value; 24 | default: 25 | return this.value; 26 | } 27 | }; 28 | 29 | obj1[Symbol.toPrimitive] = toPrimitive 30 | obj2[Symbol.toPrimitive] = toPrimitive 31 | 32 | console.log('obj1 * obj2 with Symbol.toPrimitive', obj1 * obj2) 33 | console.log('obj1 * obj2 with Symbol.toPrimitive', `name=${obj1} name=${obj2}`) 34 | } 35 | 36 | export default { 37 | name, 38 | run, 39 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example11.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.toStringTag' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | class CustomCollection { 8 | constructor(items) { 9 | this.items = items; 10 | } 11 | 12 | get [Symbol.toStringTag]() { 13 | return 'CustomCollection'; 14 | } 15 | } 16 | 17 | const myCollection = new CustomCollection([1, 2, 3]); 18 | 19 | console.log('myCollection', `${myCollection}`) 20 | 21 | const obj = { 22 | [Symbol.toStringTag]: 'MySpecialObject' 23 | }; 24 | 25 | console.log('MySpecialObject', `${obj}`) 26 | 27 | 28 | } 29 | 30 | export default { 31 | name, 32 | run, 33 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example12.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.species' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | class MyArray extends Array { 8 | // static get [Symbol.species]() { 9 | // return Array; 10 | // } 11 | } 12 | 13 | const myArray = new MyArray(1, 2, 3, 4); 14 | const slicedArray = myArray.slice(1, 3); 15 | 16 | console.log('slicedArray instanceof MyArray', slicedArray instanceof MyArray); 17 | console.log('slicedArray instanceof Array', slicedArray instanceof Array); 18 | } 19 | 20 | export default { 21 | name, 22 | run, 23 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example2.js: -------------------------------------------------------------------------------- 1 | const name = 'example2' 2 | 3 | const run = () => { 4 | const sym1a = Symbol(); 5 | const sym1b = Symbol(); 6 | const sym2a = Symbol('description'); 7 | const sym2b = Symbol('description'); 8 | 9 | console.clear() 10 | console.log(name) 11 | 12 | console.log('sym1', sym1a === sym1b); 13 | console.log('sym2', sym2a === sym2b); 14 | } 15 | 16 | export default { 17 | name, 18 | run, 19 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example3.js: -------------------------------------------------------------------------------- 1 | const name = 'example3' 2 | 3 | const run = () => { 4 | const propName = Symbol('propName') 5 | 6 | const myObject = { 7 | [propName]: 'initial', 8 | setValue(data){ 9 | this[propName] = data; 10 | }, 11 | getValue(){ 12 | return this[propName]; 13 | }, 14 | }; 15 | 16 | 17 | console.clear(); 18 | console.log(name); 19 | 20 | myObject.setValue(12345); 21 | console.log('myObject.getValue', myObject.getValue()); 22 | 23 | console.log('myObject', myObject); 24 | 25 | console.log('JSON.stringify', JSON.stringify(myObject, null, 4)); 26 | const keys = Object.keys(myObject) 27 | console.log('Object.keys', keys, keys.map((k) => myObject[k])); 28 | 29 | console.log("myObject[Symbol('propName')]", myObject[Symbol('propName')]); 30 | console.log("myObject['Symbol(propName)']", myObject['Symbol(propName)']); 31 | 32 | } 33 | 34 | export default { 35 | name, 36 | run, 37 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example4.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.iterator' 2 | 3 | const run = () => { 4 | const rangeFabric = (start, end, step) => ({ 5 | start, 6 | end, 7 | [Symbol.iterator]() { 8 | return { 9 | current: this.start, 10 | last: this.end, 11 | next() { 12 | if (this.current <= this.last) { 13 | const value = this.current 14 | this.current += step 15 | return { done: false, value }; 16 | } else { 17 | return { done: true }; 18 | } 19 | } 20 | }; 21 | } 22 | }) 23 | const range = rangeFabric(1, 100, 1) 24 | 25 | 26 | console.clear() 27 | console.log(name) 28 | console.log(...range) 29 | } 30 | 31 | export default { 32 | name, 33 | run, 34 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example5.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.asyncIterator' 2 | 3 | const run = async () => { 4 | const asyncRangeFabric = (start, end, step) => ({ 5 | start, 6 | end, 7 | [Symbol.asyncIterator]() { 8 | return { 9 | current: this.start, 10 | last: this.end, 11 | next: async function () { 12 | if (this.current <= this.last) { 13 | const value = this.current 14 | this.current += step 15 | await new Promise(resolve => setTimeout(resolve, 1000)); 16 | return { done: false, value }; 17 | } else { 18 | return { done: true }; 19 | } 20 | } 21 | }; 22 | } 23 | }) 24 | const asyncRange = asyncRangeFabric(1, 100, 1) 25 | 26 | 27 | console.clear() 28 | console.log(name) 29 | 30 | for await (let value of asyncRange) { 31 | console.log(value); 32 | } 33 | } 34 | 35 | export default { 36 | name, 37 | run, 38 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example6.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.hasInstance' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | class MyClass { 8 | static [Symbol.hasInstance](instance) { 9 | return 'customProperty' in instance; 10 | } 11 | } 12 | 13 | const obj1 = { customProperty: 123 }; 14 | const obj2 = { anotherProperty: 456 }; 15 | console.log('obj1', obj1); 16 | console.log('obj1 instanceof MyClass', obj1 instanceof MyClass); 17 | console.log('obj2', obj2); 18 | console.log('obj2 instanceof MyClass', obj2 instanceof MyClass); 19 | } 20 | 21 | export default { 22 | name, 23 | run, 24 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example7.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.isConcatSpreadable' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | const arr1 = [1, 2, 3]; 8 | const arr2 = [4, 5]; 9 | 10 | console.log('arr1.concat(arr2)', arr1.concat(arr2)); 11 | 12 | const obj = { 0: 'a', 1: 'b', length: 2 }; 13 | 14 | console.log('arr1.concat(obj)', arr1.concat(obj)); 15 | 16 | 17 | arr2[Symbol.isConcatSpreadable] = false; 18 | console.log('arr1.concat(arr2) Symbol.isConcatSpreadable === false', arr1.concat(arr2)); 19 | obj[Symbol.isConcatSpreadable] = true; 20 | console.log('arr1.concat(obj) Symbol.isConcatSpreadable === true', arr1.concat(obj)); 21 | } 22 | 23 | export default { 24 | name, 25 | run, 26 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/example8.js: -------------------------------------------------------------------------------- 1 | const name = 'Symbol.match' 2 | 3 | const run = () => { 4 | console.clear() 5 | console.log(name) 6 | 7 | class CustomMatcher { 8 | constructor(value) { 9 | this.value = value; 10 | } 11 | 12 | [Symbol.match](string) { 13 | const index = string.indexOf(this.value); 14 | return index === -1 ? { found: false} : {position: index, found: true, value: this.value}; 15 | } 16 | } 17 | 18 | const matcher = new CustomMatcher('hello'); 19 | 20 | const result1 = 'hello world'.match(matcher); 21 | console.log("'hello world'.match(matcher)", result1); 22 | 23 | const result2 = 'goodbye world'.match(matcher); 24 | console.log("'goodbye world'.match(matcher)", result2); 25 | } 26 | 27 | export default { 28 | name, 29 | run, 30 | } -------------------------------------------------------------------------------- /examples/Symbols/src/examples/index.js: -------------------------------------------------------------------------------- 1 | import example1 from './example1' 2 | import example2 from './example2' 3 | import example3 from './example3' 4 | import example4 from './example4' 5 | import example5 from './example5' 6 | import example6 from './example6' 7 | import example7 from './example7' 8 | import example8 from './example8' 9 | import example9 from './example9' 10 | import example10 from './example10' 11 | import example11 from './example11' 12 | import example12 from './example12' 13 | 14 | export const examples = [ 15 | example1, 16 | example2, 17 | example3, 18 | example4, 19 | example5, 20 | example6, 21 | example7, 22 | example8, 23 | example9, 24 | example10, 25 | example11, 26 | example12, 27 | ] 28 | -------------------------------------------------------------------------------- /examples/Symbols/src/index.js: -------------------------------------------------------------------------------- 1 | import { examples } from './examples'; 2 | const buttons = document.getElementById('buttons'); 3 | 4 | if(Array.isArray(examples)){ 5 | examples.forEach((example) => { 6 | const btn = document.createElement('button'); 7 | btn.type = 'button'; 8 | btn.textContent = example.name 9 | btn.addEventListener('click', example.run); 10 | buttons.appendChild(btn); 11 | }) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/Symbols/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | export default defineConfig({ 4 | server: { 5 | port: 3000, 6 | host: '0.0.0.0' 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/WasmRust/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wasmrust", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "vite", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "vite": "6.0.6", 16 | "wasm_image_editor": "file:wasm_image_editor/pkg" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/WasmRust/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | port: 3000, 6 | host: '0.0.0.0' 7 | } 8 | }) -------------------------------------------------------------------------------- /examples/WasmRust/wasm_image_editor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm_image_editor" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | wasm-bindgen = "0.2.99" 8 | 9 | [lib] 10 | crate-type = ["cdylib"] 11 | 12 | [profile.release] 13 | lto = true 14 | 15 | -------------------------------------------------------------------------------- /examples/WebRTS/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Launch Program", 8 | "skipFiles": [ 9 | "/**" 10 | ], 11 | "runtimeExecutable": "/Users/easy/.nvm/versions/node/v22.15.0/bin/node", 12 | "program": "${workspaceFolder}/src/server/server.js" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /examples/WebRTS/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 17 | 18 | 19 |
20 |
Simple
A simple way (no server needed)
21 |
I'm a streamer
To stream something
22 |
I'm a viewer
To subscribe to a stream
23 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/WebRTS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webrts", 3 | "version": "1.0.0", 4 | "main": "server.js", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "server": "npm run build && node ./src/server/server.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "description": "", 16 | "dependencies": { 17 | "@fastify/cors": "^11.0.1", 18 | "@fastify/static": "^8.1.1", 19 | "@fastify/websocket": "^11.0.2", 20 | "express": "^5.1.0", 21 | "fastify": "^5.3.2", 22 | "ws": "^8.18.1" 23 | }, 24 | "devDependencies": { 25 | "vite": "^6.3.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/WebRTS/src/client/stream.js: -------------------------------------------------------------------------------- 1 | const peers = []; 2 | 3 | const createPeer = (streamId, role, signalHandler) => { 4 | const peer = new SimplePeer({ 5 | initiator: role === 'streamer', 6 | trickle: false, 7 | }); 8 | 9 | peer.on('signal', (data) => { 10 | signalHandler(data); 11 | }); 12 | 13 | peer.on('stream', (stream) => { 14 | if (role === 'viewer') { 15 | const video = document.getElementById('video'); 16 | video.srcObject = stream; 17 | } 18 | }); 19 | 20 | peer.on('error', (err) => { 21 | console.error('Peer Error:', err); 22 | }); 23 | peers.push(peer); 24 | return peer; 25 | }; 26 | 27 | export { createPeer }; -------------------------------------------------------------------------------- /examples/WebRTS/src/utils.js: -------------------------------------------------------------------------------- 1 | export const getWebSocketAddress = () => { 2 | const wsProtocol = location.protocol === "https:" ? "wss://" : "ws://"; 3 | const wsHost = location.host; 4 | const wsUrl = `${wsProtocol}${wsHost}/ws`; 5 | return wsUrl; 6 | }; 7 | -------------------------------------------------------------------------------- /examples/WebRTS/streamer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Стример 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/WebRTS/viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Вьювер 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/WebRTS/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | host: '0.0.0.0', 6 | port: 3000, 7 | }, 8 | build: { 9 | rollupOptions: { 10 | input: { 11 | index: './index.html', 12 | streamer: './streamer.html', 13 | viewer: './viewer.html', 14 | simple: './simple.html', 15 | } 16 | } 17 | } 18 | }) -------------------------------------------------------------------------------- /examples/WebSocket/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "runtimeExecutable": "/Users/easy/.nvm/versions/node/v22.15.0/bin/node", 15 | "program": "${workspaceFolder}/src/server/server.js" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /examples/WebSocket/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
    11 |
    12 |
    13 |
    Display name:
    14 |
    15 |
    16 | 17 |
    18 |
    Message:
    19 |
    20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 |
    27 |
    28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/WebSocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "websocket", 3 | "private": true, 4 | "version": "0.0.1", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "server": "node src/server.js" 11 | }, 12 | "devDependencies": { 13 | "vite": "^6.3.1" 14 | }, 15 | "dependencies": { 16 | "@fastify/websocket": "^11.0.2", 17 | "fastify": "^5.3.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/WebSocket/src/client/websocket.js: -------------------------------------------------------------------------------- 1 | import { appConstants } from "../common/constants"; 2 | import { sendToSocket } from "../common/utils"; 3 | 4 | let ws; 5 | 6 | export const init = (id, {onOpen, onMessage, onError, onClose}) => { 7 | ws = new WebSocket(`ws://${appConstants.wsAddress}/ws?id=${id}`); 8 | 9 | ws.addEventListener('open', onOpen); 10 | ws.addEventListener('message', onMessage); 11 | ws.addEventListener('close', onClose); 12 | ws.addEventListener('error', onError); 13 | } 14 | 15 | export const sendMessage = (message) => { 16 | sendToSocket(ws, message); 17 | } -------------------------------------------------------------------------------- /examples/WebSocket/src/common/constants.js: -------------------------------------------------------------------------------- 1 | export const appConstants = { 2 | message: { 3 | type: { 4 | setName: "setName", 5 | getUsers: "getUsers", 6 | sendMessage: "sendMessage", 7 | messageDelivered: "messageDelivered", 8 | usersList: "usersList", 9 | publicMessage: "publicMessage", 10 | }, 11 | }, 12 | wsAddress: 'localhost:3001', 13 | button: { 14 | type: { 15 | sendMessage: 'sendMessage' 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /examples/WebSocket/src/server/server.js: -------------------------------------------------------------------------------- 1 | import Fastify from "fastify"; 2 | import fastifyWebsocket from "@fastify/websocket"; 3 | import { addStream } from "./streams.js"; 4 | 5 | const fastify = Fastify({ logger: true}); 6 | await fastify.register(fastifyWebsocket); 7 | 8 | fastify.register(async (fastify) => { 9 | fastify.get('/ws', {websocket: true}, (socket, req) => { 10 | let clientStreamId = req.query.id; 11 | addStream(clientStreamId, socket); 12 | }) 13 | }); 14 | 15 | fastify.listen({port: 3001, host: '0.0.0.0'}, (err) => { 16 | if(err){ 17 | fastify.log.error(err) 18 | process.exit(1); 19 | } 20 | }) -------------------------------------------------------------------------------- /examples/WebSocket/src/server/utils.js: -------------------------------------------------------------------------------- 1 | export const parseServerMessage = (message) => { 2 | if (Buffer.isBuffer(message)) { 3 | const str = message.toString("utf-8"); 4 | return JSON.parse(str); 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /examples/WebSocket/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | server: { 5 | host: '0.0.0.0', 6 | port: 3000 7 | }, 8 | }) -------------------------------------------------------------------------------- /examples/WebWorker/example2.js: -------------------------------------------------------------------------------- 1 | let worker; 2 | 3 | const onMessage = (e) => { 4 | if (e?.data) { 5 | document.querySelector("#result").textContent = JSON.stringify(e.data, null, 2); 6 | } 7 | }; 8 | 9 | const reCreate = () => { 10 | if (worker) { 11 | worker.terminate(); 12 | } 13 | const scriptText = document.querySelector("#textblock").value; 14 | const blob = new Blob([scriptText], { type: "text/javascript" }); 15 | worker = new Worker(window.URL.createObjectURL(blob)); 16 | 17 | worker.onmessage = onMessage; 18 | }; 19 | 20 | const onClickTodo = () => { 21 | worker.postMessage({ type: "todo", id: 1 }); 22 | }; 23 | const onClickUser = () => { 24 | worker.postMessage({ type: "user", id: 2 }); 25 | }; 26 | const onClickRecreate = () => { 27 | reCreate() 28 | }; 29 | 30 | document.querySelector("#btn1").addEventListener("click", onClickTodo); 31 | document.querySelector("#btn2").addEventListener("click", onClickUser); 32 | document.querySelector("#btn3").addEventListener("click", onClickRecreate); 33 | 34 | reCreate() 35 | -------------------------------------------------------------------------------- /examples/WebWorker/index.js: -------------------------------------------------------------------------------- 1 | import './example1' 2 | 3 | -------------------------------------------------------------------------------- /examples/WebWorker/index2.js: -------------------------------------------------------------------------------- 1 | import './example2' 2 | 3 | -------------------------------------------------------------------------------- /examples/WebWorker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micromacro", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "vite", 7 | "build": "vite build", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "vite": "^3.1.4" 15 | }, 16 | "dependencies": { 17 | "esbuild-darwin-64": "^0.15.10", 18 | "esbuild": "^0.15.10", 19 | "function-bind": "^1.1.1", 20 | "has": "^1.0.3", 21 | "fsevents": "^2.3.2", 22 | "is-core-module": "^2.10.0", 23 | "picocolors": "^1.0.0", 24 | "nanoid": "^3.3.4", 25 | "path-parse": "^1.0.7", 26 | "source-map-js": "^1.0.2", 27 | "postcss": "^8.4.17", 28 | "resolve": "^1.22.1", 29 | "rollup": "^2.78.1", 30 | "supports-preserve-symlinks-flag": "^1.0.0" 31 | }, 32 | "description": "" 33 | } 34 | -------------------------------------------------------------------------------- /examples/WebWorker/vite.config.js: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | server: { 6 | host: "0.0.0.0", 7 | port: 3000, 8 | }, 9 | build: { 10 | target: "es2017", 11 | outDir: "build", 12 | rollupOptions: { 13 | input: { 14 | main: resolve(__dirname, "./index.html"), 15 | main2: resolve(__dirname, "./index2.html"), 16 | }, 17 | }, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /examples/WebWorker/webworker.js: -------------------------------------------------------------------------------- 1 | function answer(data) { 2 | postMessage(data); 3 | } 4 | 5 | const calculate = (data) => { 6 | if (data?.text) { 7 | const textArray = [...data.text]; 8 | let result = ""; 9 | while (textArray.length > 0) { 10 | const idx = Math.floor(Math.random() * textArray.length); 11 | result = result + textArray.splice(idx, 1)[0]; 12 | } 13 | answer({ type: "result", result }); 14 | return 15 | } 16 | answer({ type: "defailt", result: data }); 17 | }; 18 | 19 | onmessage = (event) => { 20 | if (event?.data) { 21 | calculate(event.data); 22 | } else { 23 | answer({ type: "defailt", result: event }); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /examples/WebWorker2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atomicapi", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "vite.config.js", 6 | "scripts": { 7 | "start" : "vite", 8 | "build": "vite build", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "vite": "^5.0.5" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/WebWorker2/scheme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/WebWorker2/scheme.pdf -------------------------------------------------------------------------------- /examples/WebWorker2/src/appConstants.js: -------------------------------------------------------------------------------- 1 | export const appConstants = { 2 | workers: { 3 | worker1: { 4 | name: 'worker1', 5 | expInput: 'exp1', 6 | inputIndex: 0, 7 | output: 'result1', 8 | }, 9 | worker2: { 10 | name: 'worker2', 11 | expInput: 'exp2', 12 | inputIndex: 1, 13 | output: 'result2', 14 | }, 15 | worker3: { 16 | name: 'worker3', 17 | expInput: 'exp3', 18 | inputIndex: 2, 19 | output: 'result3', 20 | }, 21 | } 22 | } -------------------------------------------------------------------------------- /examples/WebWorker2/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | export default defineConfig({ 4 | server: { 5 | host: '0.0.0.0', 6 | port: 3000, 7 | headers: { 8 | 'Cross-Origin-Opener-Policy': 'same-origin', 9 | 'Cross-Origin-Embedder-Policy': 'require-corp', 10 | } 11 | }, 12 | }) -------------------------------------------------------------------------------- /examples/arrow-functions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ 4 | reports/ 5 | raml/examples_local/ 6 | .vscode/ 7 | .idea/ 8 | coverage/ 9 | /yarn.lock 10 | 11 | .npmrc 12 | -------------------------------------------------------------------------------- /examples/arrow-functions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 |

    Arrow functions specifics

    12 | 13 |
    14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /examples/arrow-functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/arrow-functions/src/example1.js: -------------------------------------------------------------------------------- 1 | import { printToDiv } from './tools' 2 | 3 | class Example { 4 | constructor (data){ 5 | this.data = data 6 | } 7 | } 8 | 9 | const example1 = new Example('example1') 10 | const example2 = new Example('example2') 11 | 12 | const getData = function(){ 13 | printToDiv(`getData ===> ${this.constructor.name} ${this.data}`) 14 | return this.data 15 | } 16 | 17 | example1.getData = getData 18 | 19 | example1.getData() 20 | 21 | example1.getData.call(example2) 22 | 23 | document.getElementById('button').addEventListener('click', example1.getData.bind(example1)) 24 | 25 | setTimeout(example1.getData.bind(example1), 1000) 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/arrow-functions/src/example2.js: -------------------------------------------------------------------------------- 1 | import { printToDiv } from './tools' 2 | 3 | class Example { 4 | constructor (data){ 5 | this.data = data 6 | } 7 | getData(){ 8 | printToDiv(`getData ===> ${this.constructor.name} ${this.data}`) 9 | return this.data 10 | } 11 | } 12 | 13 | const example1 = new Example('example1') 14 | const example2 = new Example('example2') 15 | 16 | 17 | example1.getData() 18 | 19 | example1.getData.call(example2) 20 | 21 | //document.getElementById('button').addEventListener('click', example1.getData) 22 | //document.getElementById('button').addEventListener('click', example1.getData.bind(example1)) 23 | document.getElementById('button').addEventListener('click', example1.getData.bind(example2)) 24 | 25 | setTimeout(example1.getData, 1000) 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/arrow-functions/src/example3.js: -------------------------------------------------------------------------------- 1 | import { printToDiv } from './tools' 2 | 3 | class Example { 4 | constructor (data){ 5 | this.data = data 6 | } 7 | getData = () => { 8 | printToDiv(`getData ===> ${this.constructor.name} ${this.data}`) 9 | return this.data 10 | } 11 | } 12 | 13 | const example1 = new Example('example1') 14 | const example2 = new Example('example2') 15 | 16 | 17 | example1.getData() 18 | 19 | example1.getData.call(example2) 20 | 21 | //document.getElementById('button').addEventListener('click', example1.getData) 22 | //document.getElementById('button').addEventListener('click', example1.getData.bind(example1)) 23 | document.getElementById('button').addEventListener('click', example1.getData.bind(example2)) 24 | 25 | setTimeout(example1.getData, 1000) 26 | 27 | class newExample extends Example{ 28 | constructor(data){ 29 | super(data) 30 | } 31 | 32 | getData = () => { 33 | const data = this.data 34 | printToDiv(`new Example getData ===> ${this.constructor.name} ${this.data}`) 35 | return data 36 | } 37 | } 38 | 39 | const example3 = new newExample('example2') 40 | 41 | 42 | example3.getData() -------------------------------------------------------------------------------- /examples/arrow-functions/src/example5.js: -------------------------------------------------------------------------------- 1 | import { printToDiv } from './tools' 2 | 3 | const Example = { 4 | data: 'Example5', 5 | init(){ 6 | this.getData = () => { 7 | if(this){ 8 | printToDiv(`getData ===> ${this.constructor.name} ${this.data}`) 9 | return this.data 10 | } else { 11 | printToDiv(`getData ===> I don't see any "this" here!`) 12 | } 13 | } 14 | }, 15 | } 16 | 17 | Example.init() 18 | Example.getData() 19 | Example.getData.call({data: 'bla-bla-bla'}) 20 | 21 | document.getElementById('button').addEventListener('click', Example.getData.bind({data: 'bla-bla-bla'})) 22 | 23 | setTimeout(Example.getData, 1000) 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/arrow-functions/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/arrow-functions/src/favicon.ico -------------------------------------------------------------------------------- /examples/arrow-functions/src/index.js: -------------------------------------------------------------------------------- 1 | //import './example1' 2 | //import './example2' 3 | import './example3' 4 | //import './example4' 5 | //import './example5' 6 | -------------------------------------------------------------------------------- /examples/arrow-functions/src/tools.js: -------------------------------------------------------------------------------- 1 | export const printToDiv = (data) => { 2 | const rootDiv = document.getElementById('content') 3 | const div = document.createElement('div') 4 | div.textContent = `${data}` 5 | if(rootDiv){ 6 | rootDiv.appendChild(div) 7 | } 8 | } 9 | 10 | export default { 11 | printToDiv 12 | } -------------------------------------------------------------------------------- /examples/arrow-functions/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | 5 | export default defineConfig({ 6 | build: { 7 | target: 'es2017', 8 | outDir: 'build', 9 | }, 10 | server: { 11 | port: 3000, 12 | host: '0.0.0.0', 13 | hmr: true, 14 | }, 15 | plugins: [ 16 | ViteAliases(), 17 | legacy({ 18 | targets: ['defaults', 'not IE 11'], 19 | }) 20 | ], 21 | }) -------------------------------------------------------------------------------- /examples/drag-n-drop/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ -------------------------------------------------------------------------------- /examples/drag-n-drop/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebPackHotReload", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack serve --hot --open", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "webpack": "^5.64.3", 15 | "webpack-cli": "^4.9.1", 16 | "webpack-dev-server": "^4.5.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/drag-n-drop/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hot reload 5 | 6 | 7 |

    Hi here!

    8 |
    9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/drag-n-drop/src/components/cell.js: -------------------------------------------------------------------------------- 1 | const Cell = (data) => { 2 | const cell = document.createElement('div') 3 | cell.style.padding = '10px' 4 | cell.textContent = data 5 | cell.style.border = "1px solid #CCC" 6 | cell.style.width = '25%' 7 | return cell 8 | } 9 | 10 | export default Cell -------------------------------------------------------------------------------- /examples/drag-n-drop/src/components/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "user1", "salary": 1000, "position": "dev", "department": "dep1"}, 3 | { "name": "user2", "salary": 1000, "position": "acc", "department": "dep1"}, 4 | { "name": "user3", "salary": 2000, "position": "dev", "department": "dep1"}, 5 | { "name": "user4", "salary": 1000, "position": "man", "department": "dep2"}, 6 | { "name": "user5", "salary": 3000, "position": "dev", "department": "dep2"}, 7 | { "name": "user6", "salary": 3000, "position": "dev", "department": "dep3"}, 8 | { "name": "user7", "salary": 1000, "position": "acc", "department": "dep4"}, 9 | { "name": "user8", "salary": 1500, "position": "qa", "department": "dep4"}, 10 | { "name": "user9", "salary": 1000, "position": "qa", "department": "dep4"}, 11 | { "name": "user10", "salary": 4500, "position": "dev", "department": "dep10"}, 12 | { "name": "user11", "salary": 1500, "position": "dev", "department": "dep10"}, 13 | { "name": "user12", "salary": 1060, "position": "dev", "department": "dep10"} 14 | 15 | ] 16 | 17 | -------------------------------------------------------------------------------- /examples/drag-n-drop/src/components/row.js: -------------------------------------------------------------------------------- 1 | import Cell from './cell' 2 | 3 | let DraggingElement = null 4 | 5 | function onDragStart(e){ 6 | console.log('onDragStart') 7 | DraggingElement = this 8 | } 9 | 10 | function onDrop(e){ 11 | console.log('onDrop') 12 | const target = this 13 | const source = DraggingElement 14 | target.parentElement.insertBefore(source, target.nextSibling) 15 | } 16 | 17 | function onDragOver(e){ 18 | e.preventDefault() 19 | return false; 20 | } 21 | 22 | 23 | 24 | const Row = (rowData) => { 25 | const row = document.createElement('div') 26 | row.style.display = 'flex' 27 | row.style.justifyContent = 'space-between' 28 | row.draggable = true; 29 | 30 | Object.keys(rowData).forEach(key => { 31 | const d = rowData[key] 32 | row.appendChild(Cell(d)) 33 | }); 34 | row.addEventListener('dragstart', onDragStart) 35 | row.addEventListener('drop', onDrop) 36 | row.addEventListener('dragover', onDragOver) 37 | return row 38 | } 39 | 40 | export default Row -------------------------------------------------------------------------------- /examples/drag-n-drop/src/components/table.js: -------------------------------------------------------------------------------- 1 | import Row from './row' 2 | 3 | 4 | const Table = (tableData) => { 5 | const table = document.createElement('div') 6 | table.style.padding = '10px' 7 | table.style.border = "1px solid #CCC" 8 | 9 | tableData.forEach(row => { 10 | table.appendChild(Row(row)) 11 | }); 12 | 13 | return table 14 | } 15 | 16 | export default Table -------------------------------------------------------------------------------- /examples/drag-n-drop/src/main.js: -------------------------------------------------------------------------------- 1 | import data from './components/data.json' 2 | import Table from './components/table' 3 | 4 | 5 | function init(){ 6 | const table = Table(data); 7 | 8 | document.querySelector('body').appendChild(table) 9 | 10 | const div = document.getElementById('content') 11 | div.textContent = 'Bla bla bla!!!'; 12 | } 13 | 14 | init() -------------------------------------------------------------------------------- /examples/drag-n-drop/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | 3 | module.exports = { 4 | mode: 'development', 5 | entry: './src/main.js', 6 | output: { 7 | path: __dirname + '/public', 8 | filename: 'bandle.js' 9 | }, 10 | devServer: { 11 | port: 5000, 12 | static: './public', 13 | hot: true 14 | } 15 | } -------------------------------------------------------------------------------- /examples/generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 13 | 14 | 15 |
      16 |
    1. example 1
    2. 17 |
    3. example 2
    4. 18 |
    5. example 3
    6. 19 |
    7. example 4
    8. 20 |
    9. example 5
    10. 21 |
    22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/generator/index1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 8 | 9 |
    10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/generator/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 16 | 17 | 18 |
    19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/generator/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 16 | 17 | 18 |
    19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/generator/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 16 | 17 | 18 |
    19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/generator/index5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generator 7 | 16 | 17 | 18 |
    19 | 20 | 21 | 22 | 23 | 24 | 25 |
    26 |
    27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/generator/src/generator1.js: -------------------------------------------------------------------------------- 1 | export function* GetGenerator(text){ 2 | for (let i=0; i < 10; i++){ 3 | yield `${text} ${i+1}` 4 | } 5 | } -------------------------------------------------------------------------------- /examples/generator/src/generator3.js: -------------------------------------------------------------------------------- 1 | export function* GetGenerator(){ 2 | for (let i=0; i < 10; i++){ 3 | yield `${this.name} ${i+1}` 4 | } 5 | } -------------------------------------------------------------------------------- /examples/generator/src/generator4.js: -------------------------------------------------------------------------------- 1 | import {GetGenerator} from './generator1.js' 2 | 3 | export function* ManyGenerators(){ 4 | yield* GetGenerator('AAAAA 1') 5 | yield* GetGenerator('BBBBB 2') 6 | yield* GetGenerator('CCCCC 3') 7 | } -------------------------------------------------------------------------------- /examples/generator/src/generator5.js: -------------------------------------------------------------------------------- 1 | async function* GetGenerator() { 2 | let query; 3 | while (true) { 4 | if (query) { 5 | query = yield await fetch(`https://jsonplaceholder.typicode.com/${query}`).then((res) => res.json()); 6 | } else { 7 | query = yield null; 8 | } 9 | } 10 | } 11 | 12 | const init = () => { 13 | const gen = GetGenerator() 14 | gen.next() 15 | 16 | return { 17 | getData: async (query) => { 18 | const data = await gen.next(query) 19 | if(!data.done){ 20 | return data.value 21 | } 22 | }, 23 | stop: (data) => { 24 | gen.return(data) 25 | }, 26 | error: () => { 27 | gen.throw(new Error('it is an error')) 28 | } 29 | } 30 | } 31 | 32 | export default init 33 | -------------------------------------------------------------------------------- /examples/generator/src/index1.js: -------------------------------------------------------------------------------- 1 | import {GetGenerator} from './generator1.js' 2 | 3 | const output = document.querySelector('.output') 4 | if(output){ 5 | const gen = GetGenerator('Iteration') 6 | let data = gen.next() 7 | while(!data.done){ 8 | const div = document.createElement('div') 9 | div.textContent = data.value 10 | output.appendChild(div) 11 | data = gen.next() 12 | } 13 | } -------------------------------------------------------------------------------- /examples/generator/src/index2.js: -------------------------------------------------------------------------------- 1 | import { GetGenerator } from "./generator1.js"; 2 | 3 | const output = document.querySelector(".output"); 4 | if (output) { 5 | const gen = GetGenerator('Like Array') 6 | const data = [...gen] 7 | data.forEach((value) => { 8 | const div = document.createElement("div"); 9 | div.textContent = value; 10 | output.appendChild(div); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /examples/generator/src/index3.js: -------------------------------------------------------------------------------- 1 | import { GetGenerator } from "./generator3.js"; 2 | 3 | const output = document.querySelector(".output"); 4 | if (output) { 5 | 6 | const IterableObject = { 7 | name: 'IterableObject', 8 | [Symbol.iterator]: GetGenerator 9 | } 10 | 11 | const data = [...IterableObject] 12 | data.forEach((value) => { 13 | const div = document.createElement("div"); 14 | div.textContent = value; 15 | output.appendChild(div); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /examples/generator/src/index4.js: -------------------------------------------------------------------------------- 1 | import { ManyGenerators } from "./generator4.js"; 2 | 3 | const output = document.querySelector(".output"); 4 | if (output) { 5 | const data = [...ManyGenerators()] 6 | data.forEach((value) => { 7 | const div = document.createElement("div"); 8 | div.textContent = value; 9 | output.appendChild(div); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /examples/generator/src/index5.js: -------------------------------------------------------------------------------- 1 | import init from "./generator5.js"; 2 | 3 | const dataHub = init(); 4 | 5 | const output = document.querySelector(".output"); 6 | 7 | const getData = async (query) => { 8 | const data = await dataHub.getData(query); 9 | if (data) { 10 | data.forEach((row) => { 11 | const div = document.createElement("div"); 12 | div.className = "row"; 13 | 14 | div.innerHTML = Object.entries(row) 15 | .map(([key, value]) => { 16 | if(typeof(value) !== 'object'){ 17 | return `
    ${value}
    `; 18 | } 19 | return '' 20 | }) 21 | .join(""); 22 | 23 | output.appendChild(div); 24 | }); 25 | } 26 | }; 27 | 28 | document.querySelector(".buttons").addEventListener("click", (e) => { 29 | if(e.target.hasAttribute('data')){ 30 | output.innerHTML = ''; 31 | const data = e.target.getAttribute('data') 32 | if(data === 'stop'){ 33 | dataHub.stop() 34 | } else if(data === 'error'){ 35 | dataHub.error() 36 | } else{ 37 | getData(data) 38 | } 39 | } 40 | e.stopPropagation() 41 | }); 42 | -------------------------------------------------------------------------------- /examples/macro-micro/example1.js: -------------------------------------------------------------------------------- 1 | 2 | const doIt = (text) => () => console.log(text); 3 | 4 | const startMacro = (func) => { 5 | setTimeout(func); 6 | }; 7 | 8 | const startMicro = (func) => { 9 | queueMicrotask(func); 10 | }; 11 | 12 | const onClick = () => { 13 | for (let i = 0; i < 10; i++) { 14 | doIt("macro 1 " + i)(); 15 | startMacro(doIt("macro 2 - " + i)); 16 | 17 | startMicro(doIt("> MICRO - " + i)); 18 | 19 | Promise.resolve().then(doIt("promise 4 - " + i)); 20 | 21 | fetch('https://jsonplaceholder.typicode.com/todos/1').then(doIt("promise fetch - " + i)) 22 | 23 | // startMicro(()=>fetch('https://jsonplaceholder.typicode.com/todos/1') 24 | // .then(doIt("promise fetch micro - " + i))) 25 | 26 | const p = new Promise((resolve) => { 27 | setTimeout(()=>resolve('ok'), 5000) 28 | }) 29 | p.then(doIt("promise with 5sec delay - " + i)) 30 | } 31 | 32 | }; 33 | 34 | document.querySelector("#btn").addEventListener("click", onClick); -------------------------------------------------------------------------------- /examples/macro-micro/example2.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const onClick = () => { 4 | const text = document.querySelector("#textblock").value; 5 | const textArray = [...text]; 6 | 7 | document.querySelector("#textblock").value = '' 8 | while (textArray.length > 0) { 9 | const idx = Math.floor(Math.random() * textArray.length); 10 | document.querySelector("#textblock").value = document.querySelector("#textblock").value + textArray.splice(idx, 1)[0] 11 | } 12 | 13 | }; 14 | 15 | document.querySelector("#btn").addEventListener("click", onClick); -------------------------------------------------------------------------------- /examples/macro-micro/example3.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const doStep = (textArray) => { 4 | let counter = 0 5 | while (textArray.length > 0 && counter < 10) { 6 | const idx = Math.floor(Math.random() * textArray.length); 7 | document.querySelector("#textblock").value = document.querySelector("#textblock").value + textArray.splice(idx, 1)[0] 8 | counter++ 9 | } 10 | if(textArray.length){ 11 | setTimeout(()=>doStep(textArray)) 12 | } else { 13 | console.log('done!') 14 | } 15 | console.log(textArray.length) 16 | } 17 | 18 | const onClick = () => { 19 | const text = document.querySelector("#textblock").value; 20 | const textArray = [...text]; 21 | 22 | document.querySelector("#textblock").value = '' 23 | setTimeout(()=>doStep(textArray)) 24 | }; 25 | 26 | document.querySelector("#btn").addEventListener("click", onClick); -------------------------------------------------------------------------------- /examples/macro-micro/index.js: -------------------------------------------------------------------------------- 1 | import './example1' 2 | 3 | -------------------------------------------------------------------------------- /examples/macro-micro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micromacro", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "vite": "^3.1.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/macro-micro/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | 4 | export default defineConfig({ 5 | server: { 6 | host: '0.0.0.0', 7 | port: 3000, 8 | } 9 | }) -------------------------------------------------------------------------------- /examples/pagination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Pagination examples 8 | 9 | 10 |

    Pagination examples

    11 |
    12 |
    13 |
    14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/pagination/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-it-vitejs-setup", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "serve": "vite preview --port 3000", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "browserslist": [ 14 | "cover 99.5%" 15 | ], 16 | "author": "", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "@vitejs/plugin-legacy": "^4.0.1", 20 | "sass": "^1.58.3", 21 | "vite": "^4.1.4" 22 | }, 23 | "dependencies": { 24 | "@fastify/express": "^2.3.0", 25 | "cors": "^2.8.5", 26 | "fastify": "^4.22.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/pagination/server.mjs: -------------------------------------------------------------------------------- 1 | import fastify from "fastify"; 2 | import cors from "cors"; 3 | import express from "@fastify/express"; 4 | 5 | const app = fastify(); 6 | app.register(express).then(() => { 7 | app.use(cors()); 8 | const address = "0.0.0.0"; 9 | const port = 4000; 10 | try { 11 | app.get("/todos", (req, res) => { 12 | const { _start, _limit } = req.query; 13 | fetch(`https://jsonplaceholder.typicode.com/todos?_start=${_start}&_limit=${_limit}`) 14 | .then((response) => response.json()) 15 | .then((todos) => { 16 | setTimeout(() => { 17 | res.send(todos); 18 | }, 2000); 19 | }) 20 | .catch((e) => console.log(e)); 21 | }); 22 | 23 | app.listen({ address, port }, function (err, address) { 24 | if (err) { 25 | console.log(err); 26 | process.exit(1); 27 | } 28 | console.log(`server listening on ${address}`); 29 | }); 30 | } catch (err) { 31 | console.log(err); 32 | process.exit(1); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /examples/pagination/src/fonts/Tapestry-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/pagination/src/fonts/Tapestry-Regular.ttf -------------------------------------------------------------------------------- /examples/pagination/src/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/pagination/src/images/background.jpg -------------------------------------------------------------------------------- /examples/pagination/src/js/api.js: -------------------------------------------------------------------------------- 1 | import appConstants from "./constants"; 2 | 3 | export const fetchTodos = ({start}, options = {}) => { 4 | return new Promise((resolve, reject) => { 5 | fetch(`http://localhost:4000/todos?_start=${start}&_limit=${appConstants.pageLimit}`, options) 6 | .then((response) => response.json()) 7 | .then(resolve) 8 | .catch(reject); 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/pagination/src/js/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | buttons: { 3 | example1: "example1", 4 | example2: "example2", 5 | example3: "example3", 6 | example4: "example4", 7 | }, 8 | pageLimit: 15, 9 | }; 10 | 11 | export default appConstants; 12 | -------------------------------------------------------------------------------- /examples/pagination/src/js/example1.js: -------------------------------------------------------------------------------- 1 | import { fetchTodos } from "./api"; 2 | import { createToDo } from "./todo"; 3 | 4 | const example = (targetEl, start = 0) => { 5 | fetchTodos({start}) 6 | .then((todos) => { 7 | todos.forEach((todo) => { 8 | targetEl.appendChild(createToDo(todo)); 9 | }); 10 | }) 11 | .catch((e) => console.log(e)); 12 | }; 13 | 14 | export default example; 15 | -------------------------------------------------------------------------------- /examples/pagination/src/js/example2.js: -------------------------------------------------------------------------------- 1 | import { fetchTodos } from "./api"; 2 | import { createToDo } from "./todo"; 3 | 4 | let timeout = null; 5 | 6 | const example = (targetEl, start = 0) => { 7 | if (timeout) { 8 | clearTimeout(timeout); 9 | timeout = null; 10 | } 11 | timeout = setTimeout(() => { 12 | fetchTodos({start}) 13 | .then((todos) => { 14 | todos.forEach((todo) => { 15 | targetEl.appendChild(createToDo(todo)); 16 | }); 17 | timeout = null; 18 | }) 19 | .catch((e) => console.log(e)); 20 | }, 1000); 21 | }; 22 | 23 | export default example; 24 | -------------------------------------------------------------------------------- /examples/pagination/src/js/example3.js: -------------------------------------------------------------------------------- 1 | import { fetchTodos } from "./api"; 2 | import { createToDo } from "./todo"; 3 | 4 | let timeout = null; 5 | 6 | const example = (targetEl, start = 0) => { 7 | if (timeout) { 8 | return; 9 | } 10 | timeout = setTimeout(() => { 11 | timeout = null; 12 | }, 1000); 13 | 14 | fetchTodos({ start }) 15 | .then((todos) => { 16 | todos.forEach((todo) => { 17 | targetEl.appendChild(createToDo(todo)); 18 | }); 19 | }) 20 | .catch((e) => console.log(e)); 21 | }; 22 | 23 | export default example; 24 | -------------------------------------------------------------------------------- /examples/pagination/src/js/example4.js: -------------------------------------------------------------------------------- 1 | import { fetchTodos } from "./api"; 2 | import { createToDo } from "./todo"; 3 | 4 | let controller; 5 | 6 | const example = (targetEl, start = 0) => { 7 | if (controller && !controller.signal.aborted) { 8 | controller.abort(); 9 | } 10 | 11 | controller = new AbortController(); 12 | fetchTodos({ start }, { signal: controller.signal }) 13 | .then((todos) => { 14 | todos.forEach((todo) => { 15 | targetEl.appendChild(createToDo(todo)); 16 | }); 17 | controller = null; 18 | }) 19 | .catch((e) => console.log(e)); 20 | }; 21 | 22 | export default example; 23 | -------------------------------------------------------------------------------- /examples/pagination/src/js/todo.js: -------------------------------------------------------------------------------- 1 | export const createToDo = (data) => { 2 | const todo = document.createElement('article') 3 | todo.className = 'todo' 4 | const textId = document.createElement('p') 5 | textId.className = 'todo-id' 6 | textId.textContent = data.id 7 | todo.appendChild(textId) 8 | 9 | const text = document.createElement('p') 10 | text.className = 'todo-text' 11 | text.textContent = data.title 12 | todo.appendChild(text) 13 | return todo 14 | } 15 | -------------------------------------------------------------------------------- /examples/pagination/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | @import 'fonts.scss'; 2 | 3 | body, * { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | .page-header{ 9 | text-align: center; 10 | font-family: 'Square Peg', cursive; 11 | font-size: 50px; 12 | } 13 | 14 | .image-block{ 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | } -------------------------------------------------------------------------------- /examples/pagination/src/styles/fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Tapestry'; 3 | src: local('Tapestry'), url(../fonts/Tapestry-Regular.ttf) format('truetype'); 4 | } 5 | 6 | @import url('https://fonts.googleapis.com/css2?family=Square+Peg&display=swap'); -------------------------------------------------------------------------------- /examples/pagination/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import legacy from "@vitejs/plugin-legacy"; 3 | import timeMarkPlugin from "./plugins/vite-plugin-timemark"; 4 | 5 | export default defineConfig({ 6 | build: { 7 | target: "es2017", 8 | outDir: "build", 9 | rollupOptions: { 10 | output: { 11 | assetFileNames: ({ name }) => { 12 | if (/\.(gif|jpe?g|png|svg)$/.test(name ?? "")) { 13 | return "assets/images/[name]-[hash][extname]"; 14 | } 15 | 16 | if (/\.(ttf|otf|fnt|woff)$/.test(name ?? "")) { 17 | return "assets/fonts/[name]-[hash][extname]"; 18 | } 19 | 20 | if (/\.css$/.test(name ?? "")) { 21 | return "assets/css/[name]-[hash][extname]"; 22 | } 23 | 24 | return "assets/[name]-[hash][extname]"; 25 | }, 26 | }, 27 | }, 28 | }, 29 | server: { 30 | port: 3000, 31 | host: "0.0.0.0", 32 | hmr: true, 33 | }, 34 | plugins: [ 35 | legacy({ 36 | targets: ["defaults", "not IE 11"], 37 | }), 38 | timeMarkPlugin(), 39 | ], 40 | }); 41 | -------------------------------------------------------------------------------- /examples/redux1/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ -------------------------------------------------------------------------------- /examples/redux1/README.md: -------------------------------------------------------------------------------- 1 | # Пример как можно работать с Redux на чистом JavaScript 2 | 3 | ## Как пользоваться: 4 | 5 | npm install 6 | 7 | npm run start 8 | 9 | 10 | 11 | ## Полезные ссылки 12 | 13 | Самый правильный способ установки node и npm, настоятельно рекомендую устанавливать только так, это спасет Вас от лишних проблем в будущем. 14 | 15 | https://youtu.be/gP4OPx2vBoc 16 | 17 | Как настроить сборку проекта с помощью webpack 18 | 19 | https://youtu.be/unEl3Hezwpw 20 | 21 | Как настроить горячую перезагрузку (hot reloading) с помощью webpack 22 | 23 | https://youtu.be/oOpzkF2nU0s 24 | 25 | -------------------------------------------------------------------------------- /examples/redux1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebPackHotReload", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack serve --hot --open", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "webpack": "^5.64.3", 15 | "webpack-cli": "^4.9.1", 16 | "webpack-dev-server": "^4.5.0" 17 | }, 18 | "dependencies": { 19 | "redux": "^4.1.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/redux1/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Redux 5 | 6 | 7 |

    Simple redux example

    8 | 9 |
    10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/redux1/src/data/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "id": "100", "name": "user1", "salary": 1000, "position": "dev", "department": "dep1"}, 3 | { "id": "200", "name": "user2", "salary": 1000, "position": "acc", "department": "dep1"}, 4 | { "id": "300", "name": "user3", "salary": 2000, "position": "dev", "department": "dep1"}, 5 | { "id": "400", "name": "user4", "salary": 1000, "position": "man", "department": "dep2"}, 6 | { "id": "500", "name": "user5", "salary": 3000, "position": "dev", "department": "dep2"}, 7 | { "id": "600", "name": "user6", "salary": 3000, "position": "dev", "department": "dep3"}, 8 | { "id": "700", "name": "user7", "salary": 1000, "position": "acc", "department": "dep4"}, 9 | { "id": "800", "name": "user8", "salary": 1500, "position": "qa", "department": "dep4"}, 10 | { "id": "900", "name": "user9", "salary": 1000, "position": "qa", "department": "dep4"}, 11 | { "id": "101", "name": "user10", "salary": 4500, "position": "dev", "department": "dep10"}, 12 | { "id": "102", "name": "user11", "salary": 1500, "position": "dev", "department": "dep10"}, 13 | { "id": "103", "name": "user12", "salary": 1060, "position": "dev", "department": "dep10"} 14 | 15 | ] 16 | 17 | -------------------------------------------------------------------------------- /examples/redux1/src/main.js: -------------------------------------------------------------------------------- 1 | import data from './data/data.json' 2 | import Table from './components/table' 3 | import store from './redux/store' 4 | import {INIT_STATE} from './redux/actions' 5 | 6 | function init(){ 7 | const table = new Table(data, true); 8 | const table2 = new Table(data, false); 9 | document.querySelector('#content').appendChild(table.element) 10 | document.querySelector('#content').appendChild(table2.element) 11 | store.dispatch({ type: INIT_STATE, payload: data }) 12 | } 13 | 14 | init() -------------------------------------------------------------------------------- /examples/redux1/src/redux/actions.js: -------------------------------------------------------------------------------- 1 | export const INIT_STATE = 'INIT_STATE' 2 | export const CHANGE_CELL = 'CHANGE_CELL' 3 | export const CHANGE_ORDER = 'CHANGE_ORDER' -------------------------------------------------------------------------------- /examples/redux1/src/redux/reducer.js: -------------------------------------------------------------------------------- 1 | import * as ACTIONS from './actions' 2 | 3 | const Reducer = (state = [], action) => { 4 | switch(action.type){ 5 | case ACTIONS.INIT_STATE: { 6 | return [ 7 | ...action.payload 8 | ] 9 | } 10 | case ACTIONS.CHANGE_CELL: { 11 | const { id, key, data } = action.payload 12 | const newState = state.map(user => { 13 | if(user.id === id){ 14 | user[key] = data 15 | } 16 | return { 17 | ...user 18 | } 19 | }) 20 | return newState 21 | } 22 | 23 | case ACTIONS.CHANGE_ORDER: { 24 | const { idSource, idTarget } = action.payload 25 | return [ ...state ] 26 | } 27 | default: { 28 | return state 29 | } 30 | } 31 | } 32 | 33 | export default Reducer -------------------------------------------------------------------------------- /examples/redux1/src/redux/store.js: -------------------------------------------------------------------------------- 1 | import { createStore } from "redux" 2 | import Reducer from './reducer' 3 | 4 | const store = createStore(Reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) 5 | 6 | export default store -------------------------------------------------------------------------------- /examples/redux1/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | 3 | module.exports = { 4 | mode: 'development', 5 | entry: './src/main.js', 6 | output: { 7 | path: __dirname + '/public', 8 | filename: 'bandle.js' 9 | }, 10 | devServer: { 11 | port: 5000, 12 | static: './public', 13 | hot: true 14 | } 15 | } -------------------------------------------------------------------------------- /examples/snowfall_css/img/background1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/snowfall_css/img/background1.png -------------------------------------------------------------------------------- /examples/snowfall_css/img/background2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/snowfall_css/img/background2.png -------------------------------------------------------------------------------- /examples/snowfall_css/img/background3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/snowfall_css/img/background3.png -------------------------------------------------------------------------------- /examples/snowfall_css/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Snow Fall 5 | 6 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/mongo-config.conf: -------------------------------------------------------------------------------- 1 | systemLog: 2 | destination: file 3 | path: /usr/local/var/log/mongodb/mongo.log 4 | logAppend: true 5 | storage: 6 | dbPath: /usr/local/var/mongodb 7 | net: 8 | bindIp: 127.0.0.1, ::1 9 | ipv6: true 10 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/mongodb/fake.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easy-linux/VanillaJS/669a17e27d0c46968f93ab14dade4762110e006d/examples/spa/bonus1/REST_server/mongodb/fake.txt -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RESTapi", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "mongo-start": "mongod --config ./mongo-config.conf --dbpath ./mongodb --logpath ./mongo.log", 9 | "generate": "node ./scripts/generateDb.js", 10 | "server": "concurrently \"npm run mongo-start\" \"npm run generate\" \"node ./server.js\"" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "@fastify/express": "^1.1.0", 17 | "@fastify/jwt": "^5.0.1", 18 | "@fastify/mongodb": "^5.0.0", 19 | "@fastify/static": "^5.0.2", 20 | "@fastify/swagger": "^6.0.1", 21 | "cors": "^2.8.5", 22 | "dns-prefetch-control": "^0.3.0", 23 | "fastify": "^3.29.0", 24 | "fastify-jwt": "^4.2.0", 25 | "fastify-mysql": "^2.2.0", 26 | "fastify-swagger": "^5.2.0", 27 | "frameguard": "^4.0.0", 28 | "hide-powered-by": "^1.1.0", 29 | "hsts": "^2.2.0", 30 | "ienoopen": "^1.1.0", 31 | "joi-to-json": "^2.2.4", 32 | "x-xss-protection": "^2.0.0" 33 | }, 34 | "devDependencies": { 35 | "concurrently": "^7.2.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/server-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "0.0.0.0", 3 | "port": 3333 4 | } -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/common/constants.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/common/utils.js: -------------------------------------------------------------------------------- 1 | const getToken = (request) => { 2 | 3 | }; 4 | 5 | module.exports = { 6 | 7 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/decorators.js: -------------------------------------------------------------------------------- 1 | module.exports = function(fastify){ 2 | fastify.decorate('BadRequest', (request, reply, message) => { 3 | reply.code(400).type('application/json').send(message) 4 | }); 5 | fastify.decorate('LoginError', (request, reply) => { 6 | reply.code(401).type('application/json').send({message: 'Unauthorized Error'}) 7 | }); 8 | fastify.decorate('OnlyAdmin', (request, reply) => { 9 | reply.code(403).type('application/json').send('You have no permission to do it') 10 | }); 11 | fastify.decorate('notFound', (request, reply) => { 12 | reply.code(404).type('application/json').send('Not Found') 13 | }); 14 | 15 | fastify.decorate("getTokenDecoded", function(request, reply) { 16 | try { 17 | const Auth = request.headers["authorization"]; 18 | if (Auth) { 19 | const parsed = Auth.split(" "); 20 | const decodedToken = fastify.jwt.decode(parsed[1]); 21 | return decodedToken; 22 | } 23 | } catch (err) { 24 | return null; 25 | } 26 | return null; 27 | }) 28 | 29 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/handlers/auth/auth.js: -------------------------------------------------------------------------------- 1 | const login = function(fastify) { 2 | return (request, reply) => { 3 | const { login, password } = request.body; 4 | 5 | const token = fastify.jwt.sign({ 6 | user_id: '123', 7 | user_login: login, 8 | user_name: 'user name', 9 | randomData: Math.random() 10 | }); 11 | 12 | reply.send({ token }); 13 | }; 14 | }; 15 | 16 | module.exports = { 17 | login, 18 | }; 19 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/handlers/auth/index.js: -------------------------------------------------------------------------------- 1 | 2 | const auth = require('./auth'); 3 | 4 | module.exports = { 5 | ...auth 6 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/handlers/comments/index.js: -------------------------------------------------------------------------------- 1 | const comments = require('./comments'); 2 | 3 | module.exports = { 4 | ...comments 5 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/handlers/posts/index.js: -------------------------------------------------------------------------------- 1 | const posts = require('./posts'); 2 | 3 | module.exports = { 4 | ...posts 5 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/handlers/users/index.js: -------------------------------------------------------------------------------- 1 | const users = require('./users'); 2 | 3 | module.exports = { 4 | ...users 5 | }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/plugins/awt-plugin.js: -------------------------------------------------------------------------------- 1 | const fp = require("fastify-plugin") 2 | 3 | module.exports = fp(async function(fastify, opts) { 4 | fastify.register(require("@fastify/jwt"), { 5 | secret: "supersecret" 6 | }); 7 | 8 | fastify.decorate("authenticate", async function(request, reply, done) { 9 | try { 10 | await request.jwtVerify(); 11 | done(); 12 | } catch (err) { 13 | reply.send(err); 14 | } 15 | }); 16 | 17 | fastify.decorate("isAdmin", async function(request, reply, done) { 18 | try { 19 | const decodedToken = await request.jwtVerify(); 20 | if(decodedToken['user_admin']){ 21 | done(); 22 | } else { 23 | fastify.OnlyAdmin(request, reply); 24 | } 25 | } catch (err) { 26 | reply.send(err); 27 | } 28 | }); 29 | }) 30 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/auth-routes.js: -------------------------------------------------------------------------------- 1 | const authHandlers = require("../handlers/auth"); 2 | 3 | const addRoutes = fastify => { 4 | 5 | fastify.post( 6 | "/login", 7 | { 8 | schema: { 9 | description: "Log in into the system", 10 | tags: ['auth'], 11 | summary: "Log in into the system", 12 | params: {}, 13 | body: { 14 | type: "object", 15 | properties: { 16 | login: { 17 | type: "string", 18 | description: `user's email` 19 | }, 20 | password: { 21 | type: "string", 22 | description: "user password" 23 | } 24 | } 25 | }, 26 | response: { 27 | 200: { 28 | description: "Successful loggin", 29 | type: "object", 30 | properties: { 31 | token: { type: "string" } 32 | } 33 | } 34 | }, 35 | security: [] 36 | } 37 | }, 38 | authHandlers.login(fastify) 39 | ); 40 | 41 | 42 | }; 43 | 44 | module.exports = addRoutes; 45 | -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/index.js: -------------------------------------------------------------------------------- 1 | 2 | const usersRoutes = require('./users-routes'); 3 | const postsRoutes = require('./posts-routes'); 4 | const commentsRoutes = require('./comments-routes'); 5 | const authRoutes = require('./auth-routes'); 6 | 7 | const addAllRoutes = (fastify) => { 8 | fastify.get('/', async (request, reply) => { 9 | return { result: 'ok' } 10 | }); 11 | fastify.post('/', async (request, reply) => { 12 | return { result: 'ok' } 13 | }); 14 | 15 | usersRoutes(fastify); 16 | postsRoutes(fastify); 17 | commentsRoutes(fastify); 18 | authRoutes(fastify); 19 | }; 20 | 21 | module.exports = addAllRoutes; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/allSchemas.js: -------------------------------------------------------------------------------- 1 | const user = require('./user') 2 | const { postShort, postFull } = require('./post') 3 | const { commentShort, commentFull, commentWithOutPost } = require('./comment') 4 | const { queryPagination } = require('./querystrings') 5 | const pagination = require('./pagination') 6 | 7 | module.exports = (fastify) => { 8 | fastify.addSchema(user) 9 | fastify.addSchema(postShort) 10 | fastify.addSchema(postFull) 11 | fastify.addSchema(commentShort) 12 | fastify.addSchema(commentFull) 13 | fastify.addSchema(commentWithOutPost) 14 | fastify.addSchema(queryPagination) 15 | fastify.addSchema(pagination) 16 | 17 | } -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/comment.js: -------------------------------------------------------------------------------- 1 | 2 | const commentShort = { 3 | $id: "commentShort", 4 | "type": "object", 5 | "properties": { 6 | "id": { 7 | "type": "string", 8 | "format": "uuid", 9 | "description": "post public ID" 10 | }, 11 | "text": { 12 | "type": "string", 13 | "description": "post text" 14 | }, 15 | "createdAt": { 16 | "type": "string", 17 | "description": "creating date" 18 | }, 19 | } 20 | } 21 | 22 | const commentFull = { 23 | $id: "commentFull", 24 | type: "object", 25 | properties: { 26 | ...commentShort.properties, 27 | user: {$ref: 'user#'}, 28 | post: {$ref: 'postShort#'}, 29 | 30 | } 31 | } 32 | 33 | const commentWithOutPost = { 34 | $id: "commentWithOutPost", 35 | type: "object", 36 | properties: { 37 | ...commentShort.properties, 38 | user: {$ref: 'user#'}, 39 | } 40 | } 41 | 42 | module.exports = {commentShort, commentFull, commentWithOutPost}; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/pagination.js: -------------------------------------------------------------------------------- 1 | const schema = { 2 | $id: 'pagination', 3 | "type": "object", 4 | "properties": { 5 | "totalCount": { 6 | "type": "number", 7 | "description": "total count" 8 | }, 9 | "limit": { 10 | "type": "number", 11 | "description": "current limit" 12 | }, 13 | "page": { 14 | "type": "number", 15 | "description": "current page number" 16 | } 17 | } 18 | } 19 | 20 | module.exports = schema; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/post.js: -------------------------------------------------------------------------------- 1 | const postShort = { 2 | $id: 'postShort', 3 | "type": "object", 4 | "properties": { 5 | "id": { 6 | "type": "string", 7 | "format": "uuid", 8 | "description": "post public ID" 9 | }, 10 | "title": { 11 | "type": "string", 12 | "description": "post title" 13 | }, 14 | "text": { 15 | "type": "string", 16 | "description": "post text" 17 | }, 18 | "createdAt": { 19 | "type": "string", 20 | "description": "creating date" 21 | }, 22 | } 23 | } 24 | 25 | const postFull = { 26 | $id: 'postFull', 27 | "type": "object", 28 | properties: { 29 | ...postShort.properties, 30 | user: {$ref: 'user#'} 31 | } 32 | } 33 | 34 | module.exports = {postShort, postFull}; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/querystrings.js: -------------------------------------------------------------------------------- 1 | const queryPagination = { 2 | $id: 'queryPagination', 3 | type: "object", 4 | properties: { 5 | limit: { 6 | in: 'query', 7 | type: 'number', 8 | description: "max records to return", 9 | }, 10 | _page: { 11 | in: 'query', 12 | type: 'number', 13 | description: "page number to return", 14 | }, 15 | userId: { 16 | in: 'query', 17 | type: 'string', 18 | format: "uuid", 19 | description: "search by userId", 20 | }, 21 | search: { 22 | in: 'query', 23 | type: 'string', 24 | description: "search by sub-string", 25 | } 26 | 27 | }, 28 | required: ['limit', '_page'] 29 | } 30 | 31 | 32 | module.exports = { queryPagination }; -------------------------------------------------------------------------------- /examples/spa/bonus1/REST_server/src/routes/schemas/user.js: -------------------------------------------------------------------------------- 1 | const user = { 2 | $id: 'user', 3 | "type": "object", 4 | "properties": { 5 | "id": { 6 | "type": "string", 7 | "format": "uuid", 8 | "description": "user's public ID" 9 | }, 10 | "user_name": { 11 | "type": "string", 12 | "description": "users's name" 13 | }, 14 | "user_fullname": { 15 | "type": "string", 16 | "description": "user's full name" 17 | } 18 | } 19 | } 20 | 21 | 22 | module.exports = user; -------------------------------------------------------------------------------- /examples/spa/bonus1/generateDB/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MongoDB", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "mongodb": "^4.5.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/spa/bonus2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SPA on VanillaJs (based on Web Components) 8 | 9 | 10 | 11 |

    SPA on VanillaJs (based on Web Components)

    12 |
    13 | 14 | 15 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/spa/bonus2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@vitejs/plugin-legacy": "^1.7.0", 18 | "cross-env": "^7.0.3", 19 | "sass": "^1.46.0", 20 | "vite": "^2.8.0", 21 | "vite-aliases": "^0.8.7" 22 | }, 23 | "dependencies": { 24 | "route-parser": "0.0.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/spa/bonus2/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/api/authApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const login = (user, password) => { 4 | return baseApi.post(`/login`, {login: user, password}) 5 | } 6 | 7 | 8 | export default { 9 | login, 10 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPost = (postId, page) => { 4 | return baseApi.get(`/post/${postId}/comments?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&limit=10`) 9 | } 10 | 11 | export const getCommentsSearch = (search, page) => { 12 | return baseApi.get(`/comments?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getCommentsByPost, 17 | getCommentsByUser, 18 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' 4 | export {default as authApi } from './authApi' -------------------------------------------------------------------------------- /examples/spa/bonus2/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10`) 9 | } 10 | 11 | export const getPostById = (postId) => { 12 | return baseApi.get(`/post/${postId}`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?search=${search}&_page=${page}&limit=10`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUserById = (userId) => { 8 | return baseApi.get(`/user/${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?search=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUserById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | postsSearch: '/posts/query/:query', 6 | usersSearch: '/users/query/:query', 7 | users: '/users', 8 | post: '/post/:post', 9 | user: '/user/:user', 10 | userPosts: '/user/:user/posts', 11 | userComments: '/user/:user/comments', 12 | }, 13 | search: { 14 | types: { 15 | post: 'post', 16 | user: 'user', 17 | } 18 | }, 19 | lists: { 20 | types: { 21 | post: 'post', 22 | user: 'user', 23 | comment: 'comment', 24 | } 25 | }, 26 | storage: { 27 | keys: { 28 | token: 'token' 29 | } 30 | }, 31 | } 32 | 33 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/bonus2/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './user-component' 6 | import './list-component' 7 | import './pagination-component' 8 | import './post-detail' 9 | import './comment-component' 10 | import './date-formatted' 11 | import './app-component' 12 | import './fake-form' 13 | import './modal-dialog' 14 | 15 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 |
    ${props.topBlock || ''}
    10 |
    ${props.leftBlock || ''}
    11 |
    ${props.rightBlock || ''}
    12 |
    ${props.bottomBlock || ''}
    13 |
    -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/main/bottom.template: -------------------------------------------------------------------------------- 1 | 25 |
    26 | ${ [...Array(20).keys()].map((block)=>{ 27 | return `
    Bottom block ${block+1}
    ` 28 | }).join('\n')} 29 |
    -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/main/right.template: -------------------------------------------------------------------------------- 1 | 30 | 31 |
    32 | ${ [...Array(12).keys()].map((block)=>{ 33 | return `
    34 | 35 |
    ` 36 | }).join('\n')} 37 |
    38 | 39 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/main/top.template: -------------------------------------------------------------------------------- 1 | 23 |
    24 | ${ [...Array(10).keys()].map((block)=>{ 25 | return `
    Top block ${block+1}
    ` 26 | }).join('\n')} 27 |
    -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/post.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/user.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/userComments.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/userPosts.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/service/comments.js: -------------------------------------------------------------------------------- 1 | const comments = new Map() 2 | 3 | export const getComment = (commentId) => { 4 | return comments.get(commentId) 5 | } 6 | 7 | export const setComment = (comment) => { 8 | return comments.set(comment.id, comment) 9 | } 10 | 11 | export default { 12 | getComment, 13 | setComment, 14 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/service/users.js: -------------------------------------------------------------------------------- 1 | const users = new Map() 2 | 3 | export const getUser = (userId) => { 4 | return users.get(userId) 5 | } 6 | 7 | export const setUser = (user) => { 8 | users.set(user.id, user) 9 | } 10 | 11 | export default { 12 | getUser, 13 | setUser 14 | } -------------------------------------------------------------------------------- /examples/spa/bonus2/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/bonus2/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/bonus2/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part1/README.md: -------------------------------------------------------------------------------- 1 | # SPA приложение на основе web компонентов (часть 1). 2 | 3 | ## Как пользоваться 4 | 5 | npm install 6 | 7 | #### Запуск приложения 8 | 9 | npm run start 10 | 11 | 12 | ## Команды для сборки дев и прод версий 13 | 14 | npm run build 15 | npm run ibuild-prod 16 | 17 | ## Видео с объяснением как это все работает здесь: 18 | 19 | https://youtu.be/eqAefmCqA6M 20 | 21 | 22 | ## Другие видео по Vanilla js: 23 | 24 | - Эффект падающего снега для сайта https://youtu.be/3xk4ldXe4YI 25 | - Введиние в Cordova, часть 1 https://youtu.be/O5mQRVTmUf4 26 | - Введиние в Cordova, часть 2 https://youtu.be/-R3fA4cVWFM 27 | - Введиние в Cordova, часть 3 https://youtu.be/hMtQKROmHZs 28 | - Введиние в Cordova, часть 4 https://youtu.be/SUUmj8YgbQY 29 | 30 | 31 | ## Полезные видео по настройке webpack: 32 | 33 | - Настройка горячей перезагрузки - https://youtu.be/oOpzkF2nU0s 34 | 35 | - Настройка сборки проекта с подгрузкой файлов css/scss/изображений - https://youtu.be/3B-NGZmMe-Y 36 | 37 | - Модульный принцип конфигурации проекта - https://youtu.be/fnUqyWyG5kk 38 | 39 | -------------------------------------------------------------------------------- /examples/spa/part1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@vitejs/plugin-legacy": "^1.7.0", 18 | "cross-env": "^7.0.3", 19 | "sass": "^1.46.0", 20 | "vite": "^2.8.0", 21 | "vite-aliases": "^0.8.7" 22 | }, 23 | "dependencies": { 24 | "route-parser": "0.0.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/spa/part1/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part1/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | users: '/users', 6 | }, 7 | search: { 8 | types: { 9 | post: 'post', 10 | user: 'user' 11 | } 12 | } 13 | } 14 | 15 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part1/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | 4 | initRouter() 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/spa/part1/src/pages/main.template: -------------------------------------------------------------------------------- 1 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part1/src/pages/posts.template: -------------------------------------------------------------------------------- 1 |
    Posts template
    -------------------------------------------------------------------------------- /examples/spa/part1/src/pages/users.template: -------------------------------------------------------------------------------- 1 |
    Users template
    -------------------------------------------------------------------------------- /examples/spa/part1/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part1/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part1/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part2/README.md: -------------------------------------------------------------------------------- 1 | # SPA приложение на основе web компонентов (часть 2). 2 | 3 | ## Как пользоваться 4 | 5 | npm install 6 | 7 | #### Запуск приложения 8 | 9 | npm run start 10 | 11 | 12 | ## Команды для сборки дев и прод версий 13 | 14 | npm run build 15 | npm run build-prod 16 | 17 | ## Видео с объяснением как это все работает здесь: 18 | 19 | https://youtu.be/HKFEUBXuAxc 20 | 21 | ## Видео первой части здесь: 22 | 23 | https://youtu.be/eqAefmCqA6M 24 | 25 | 26 | ## Другие видео по Vanilla js: 27 | 28 | - Эффект падающего снега для сайта https://youtu.be/3xk4ldXe4YI 29 | - Введиние в Cordova, часть 1 https://youtu.be/O5mQRVTmUf4 30 | - Введиние в Cordova, часть 2 https://youtu.be/-R3fA4cVWFM 31 | - Введиние в Cordova, часть 3 https://youtu.be/hMtQKROmHZs 32 | - Введиние в Cordova, часть 4 https://youtu.be/SUUmj8YgbQY 33 | 34 | 35 | ## Полезные видео по настройке webpack: 36 | 37 | - Настройка горячей перезагрузки - https://youtu.be/oOpzkF2nU0s 38 | 39 | - Настройка сборки проекта с подгрузкой файлов css/scss/изображений - https://youtu.be/3B-NGZmMe-Y 40 | 41 | - Модульный принцип конфигурации проекта - https://youtu.be/fnUqyWyG5kk 42 | 43 | -------------------------------------------------------------------------------- /examples/spa/part2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@vitejs/plugin-legacy": "^1.7.0", 18 | "cross-env": "^7.0.3", 19 | "sass": "^1.46.0", 20 | "vite": "^2.8.0", 21 | "vite-aliases": "^0.8.7" 22 | }, 23 | "dependencies": { 24 | "route-parser": "0.0.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/spa/part2/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part2/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | users: '/users', 6 | }, 7 | search: { 8 | types: { 9 | post: 'post', 10 | user: 'user' 11 | } 12 | } 13 | } 14 | 15 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part2/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | -------------------------------------------------------------------------------- /examples/spa/part2/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part2/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part2/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 |
    Posts template
    -------------------------------------------------------------------------------- /examples/spa/part2/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 |
    Users template
    -------------------------------------------------------------------------------- /examples/spa/part2/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part2/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part2/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part3/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part3/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPosts = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&_expand=user&_expand=post`) 9 | } 10 | 11 | export default { 12 | getCommentsByPosts, 13 | getCommentsByUser, 14 | } -------------------------------------------------------------------------------- /examples/spa/part3/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part3/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostsById = (postId) => { 12 | return baseApi.get(`/posts/postId=${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostsById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part3/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUsersById = (userId) => { 8 | return baseApi.get(`/users/userId=${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUsersById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part3/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | users: '/users', 6 | }, 7 | search: { 8 | types: { 9 | post: 'post', 10 | user: 'user' 11 | } 12 | } 13 | } 14 | 15 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part3/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | -------------------------------------------------------------------------------- /examples/spa/part3/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part3/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part3/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 |
    Posts template
    -------------------------------------------------------------------------------- /examples/spa/part3/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 |
    Users template
    -------------------------------------------------------------------------------- /examples/spa/part3/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part3/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part3/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part4/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part4/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPosts = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&_expand=user&_expand=post`) 9 | } 10 | 11 | export default { 12 | getCommentsByPosts, 13 | getCommentsByUser, 14 | } -------------------------------------------------------------------------------- /examples/spa/part4/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part4/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostsById = (postId) => { 12 | return baseApi.get(`/posts/postId=${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostsById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part4/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUsersById = (userId) => { 8 | return baseApi.get(`/users/userId=${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUsersById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part4/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | users: '/users', 6 | }, 7 | search: { 8 | types: { 9 | post: 'post', 10 | user: 'user' 11 | } 12 | } 13 | } 14 | 15 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part4/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './posts-component' 6 | import './pagination-component' 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part4/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part4/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part4/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | Posts template -------------------------------------------------------------------------------- /examples/spa/part4/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 |
    Users template
    -------------------------------------------------------------------------------- /examples/spa/part4/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/part4/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part4/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part4/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part5/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part5/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPosts = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&_expand=user&_expand=post`) 9 | } 10 | 11 | export default { 12 | getCommentsByPosts, 13 | getCommentsByUser, 14 | } -------------------------------------------------------------------------------- /examples/spa/part5/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part5/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostsById = (postId) => { 12 | return baseApi.get(`/posts/postId=${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostsById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part5/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUsersById = (userId) => { 8 | return baseApi.get(`/users/userId=${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUsersById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part5/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | postsSearch: '/posts/query/:query', 6 | users: '/users', 7 | }, 8 | search: { 9 | types: { 10 | post: 'post', 11 | user: 'user' 12 | } 13 | } 14 | } 15 | 16 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part5/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './posts-component' 6 | import './pagination-component' 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part5/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part5/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part5/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | Posts template -------------------------------------------------------------------------------- /examples/spa/part5/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 |
    Users template
    -------------------------------------------------------------------------------- /examples/spa/part5/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/part5/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part5/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part5/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part6/README.md: -------------------------------------------------------------------------------- 1 | # SPA прилоежние на основе web компонентов. 2 | 3 | ## Как пользоваться 4 | 5 | npm install 6 | npm install -g json-server 7 | npm install -g http-server-spa 8 | 9 | #### Запуск локального REST API сервера 10 | 11 | npm run server 12 | 13 | #### Запуск приложения 14 | 15 | npm run start 16 | 17 | 18 | ## Команды для сборки дев и прод версий 19 | 20 | npm run build 21 | npm run ibuild-prod 22 | 23 | ## Build and run spa server 24 | 25 | npm run build // или npm run build-prod 26 | cd build 27 | http-server-spa . ./index.html 3000 28 | 29 | ## Видео с объяснением как это все работает здесь: 30 | 31 | https://youtu.be/6rA2Wmt9trI 32 | 33 | 34 | ## Другие видео по Vanilla js: 35 | 36 | - Введиние в Cordova, превращаем существующее приложение в мобильное https://youtu.be/O5mQRVTmUf4 37 | 38 | ## Полезные видео по настройке webpack: 39 | 40 | - Настройка горячей перезагрузки - https://youtu.be/oOpzkF2nU0s 41 | 42 | - Настройка сборки проекта с подгрузкой файлов css/scss/изображений - https://youtu.be/3B-NGZmMe-Y 43 | 44 | - Модульный принцип конфигурации проекта - https://youtu.be/fnUqyWyG5kk 45 | 46 | -------------------------------------------------------------------------------- /examples/spa/part6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part6/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPosts = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&_expand=user&_expand=post`) 9 | } 10 | 11 | export default { 12 | getCommentsByPosts, 13 | getCommentsByUser, 14 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part6/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostsById = (postId) => { 12 | return baseApi.get(`/posts/postId=${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostsById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUsersById = (userId) => { 8 | return baseApi.get(`/users/userId=${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUsersById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | postsSearch: '/posts/query/:query', 6 | usersSearch: '/users/query/:query', 7 | users: '/users', 8 | }, 9 | search: { 10 | types: { 11 | post: 'post', 12 | user: 'user', 13 | } 14 | }, 15 | lists: { 16 | types: { 17 | post: 'post', 18 | user: 'user', 19 | } 20 | } 21 | } 22 | 23 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part6/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './user-component' 6 | import './list-component' 7 | import './pagination-component' 8 | 9 | -------------------------------------------------------------------------------- /examples/spa/part6/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part6/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part6/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | Posts template -------------------------------------------------------------------------------- /examples/spa/part6/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 | Posts template -------------------------------------------------------------------------------- /examples/spa/part6/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/service/users.js: -------------------------------------------------------------------------------- 1 | const users = new Map() 2 | 3 | export const getUser = (userId) => { 4 | return users.get(userId) 5 | } 6 | 7 | export const setUser = (user) => { 8 | users.set(user.id, user) 9 | } 10 | 11 | export default { 12 | getUser, 13 | setUser 14 | } -------------------------------------------------------------------------------- /examples/spa/part6/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part6/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part6/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part7/README.md: -------------------------------------------------------------------------------- 1 | # SPA прилоежние на основе web компонентов. 2 | 3 | ## Как пользоваться 4 | 5 | npm install 6 | npm install -g json-server 7 | npm install -g http-server-spa 8 | 9 | #### Запуск локального REST API сервера 10 | 11 | npm run server 12 | 13 | #### Запуск приложения 14 | 15 | npm run start 16 | 17 | 18 | ## Команды для сборки дев и прод версий 19 | 20 | npm run build 21 | npm run ibuild-prod 22 | 23 | ## Build and run spa server 24 | 25 | npm run build // или npm run build-prod 26 | cd build 27 | http-server-spa . ./index.html 3000 28 | 29 | ## Видео с объяснением как это все работает здесь: 30 | 31 | https://youtu.be/eTaNwVqSmXk 32 | 33 | 34 | ## Другие видео по Vanilla js: 35 | 36 | - Введиние в Cordova, превращаем существующее приложение в мобильное https://youtu.be/O5mQRVTmUf4 37 | 38 | ## Полезные видео по настройке webpack: 39 | 40 | - Настройка горячей перезагрузки - https://youtu.be/oOpzkF2nU0s 41 | 42 | - Настройка сборки проекта с подгрузкой файлов css/scss/изображений - https://youtu.be/3B-NGZmMe-Y 43 | 44 | - Модульный принцип конфигурации проекта - https://youtu.be/fnUqyWyG5kk 45 | 46 | -------------------------------------------------------------------------------- /examples/spa/part7/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SPA on VanillaJs (based on Web Components) 7 | 8 | 9 |

    SPA on VanillaJs (based on Web Components)

    10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/spa/part7/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part7/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPost = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&limit=10&_expand=user&_expand=post`) 9 | } 10 | 11 | export const getCommentsSearch = (search, page) => { 12 | return baseApi.get(`/comments?q=${search}&_page=${page}&limit=10&_expand=user&_expand=post`) 13 | } 14 | 15 | export default { 16 | getCommentsByPost, 17 | getCommentsByUser, 18 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part7/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostById = (postId) => { 12 | return baseApi.get(`/posts/${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUserById = (userId) => { 8 | return baseApi.get(`/users/${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUserById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | postsSearch: '/posts/query/:query', 6 | usersSearch: '/users/query/:query', 7 | users: '/users', 8 | post: '/post/:post', 9 | user: '/user/:user', 10 | userPosts: '/user/:user/posts', 11 | userComments: '/user/:user/comments', 12 | }, 13 | search: { 14 | types: { 15 | post: 'post', 16 | user: 'user', 17 | } 18 | }, 19 | lists: { 20 | types: { 21 | post: 'post', 22 | user: 'user', 23 | comment: 'comment', 24 | } 25 | } 26 | } 27 | 28 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part7/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './user-component' 6 | import './list-component' 7 | import './pagination-component' 8 | import './post-detail' 9 | import './comment-component' 10 | import './date-formatted' 11 | 12 | -------------------------------------------------------------------------------- /examples/spa/part7/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 2 |
    Main template (new content)
    -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/post.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/user.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/userComments.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/userPosts.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part7/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part7/src/service/comments.js: -------------------------------------------------------------------------------- 1 | const comments = new Map() 2 | 3 | export const getComment = (commentId) => { 4 | return comments.get(commentId) 5 | } 6 | 7 | export const setComment = (comment) => { 8 | return comments.set(comment.id, comment) 9 | } 10 | 11 | export default { 12 | getComment, 13 | setComment, 14 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/service/users.js: -------------------------------------------------------------------------------- 1 | const users = new Map() 2 | 3 | export const getUser = (userId) => { 4 | return users.get(userId) 5 | } 6 | 7 | export const setUser = (user) => { 8 | users.set(user.id, user) 9 | } 10 | 11 | export default { 12 | getUser, 13 | setUser 14 | } -------------------------------------------------------------------------------- /examples/spa/part7/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part7/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part7/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) -------------------------------------------------------------------------------- /examples/spa/part8/README.md: -------------------------------------------------------------------------------- 1 | # SPA приложение на основе web компонентов. 2 | 3 | ## Как пользоваться 4 | 5 | npm install 6 | npm install -g json-server 7 | npm install -g http-server-spa 8 | 9 | #### Запуск локального REST API сервера 10 | 11 | npm run server 12 | 13 | #### Запуск приложения 14 | 15 | npm run start 16 | 17 | 18 | ## Команды для сборки дев и прод версий 19 | 20 | npm run build 21 | npm run ibuild-prod 22 | 23 | ## Build and run spa server 24 | 25 | npm run build // или npm run build-prod 26 | cd build 27 | http-server-spa . ./index.html 3000 28 | 29 | ## Видео с объяснением как это все работает здесь: 30 | 31 | https://youtu.be/HIdYceoPhlg 32 | 33 | 34 | ## Другие видео по Vanilla js: 35 | 36 | - Введиние в Cordova, превращаем существующее приложение в мобильное https://youtu.be/O5mQRVTmUf4 37 | 38 | ## Полезные видео по настройке webpack: 39 | 40 | - Настройка горячей перезагрузки - https://youtu.be/oOpzkF2nU0s 41 | 42 | - Настройка сборки проекта с подгрузкой файлов css/scss/изображений - https://youtu.be/3B-NGZmMe-Y 43 | 44 | - Модульный принцип конфигурации проекта - https://youtu.be/fnUqyWyG5kk 45 | 46 | -------------------------------------------------------------------------------- /examples/spa/part8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spa_example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "cross-env BUILD_TYPE=dev vite build", 9 | "serve": "vite preview --port 3000", 10 | "build-prod": "cross-env BUILD_TYPE=prod vite build", 11 | "server": "json-server --port 1111 ./db.json", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@vitejs/plugin-legacy": "^1.7.0", 19 | "cross-env": "^7.0.3", 20 | "sass": "^1.46.0", 21 | "vite": "^2.8.0", 22 | "vite-aliases": "^0.8.7" 23 | }, 24 | "dependencies": { 25 | "route-parser": "0.0.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/spa/part8/plugins/vite-template-plugin.js: -------------------------------------------------------------------------------- 1 | const fileRegex = /\.(template)$/ 2 | 3 | export default function templatePlugin(){ 4 | return { 5 | name: 'template-loader-plugin', 6 | 7 | transform(src, id) { 8 | if(fileRegex.test(id)) { 9 | return { 10 | code: `export default function template(props = {}){return \`${src}\`}`, 11 | map: null, 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/api/commentsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getCommentsByPost = (postId, page) => { 4 | return baseApi.get(`/posts/${postId}/comments?_page=${page}&limit=10&_expand=user&_sort=createAt`) 5 | } 6 | 7 | export const getCommentsByUser = (userId, page) => { 8 | return baseApi.get(`/comments?userId=${userId}&_page=${page}&limit=10&_expand=user&_expand=post`) 9 | } 10 | 11 | export const getCommentsSearch = (search, page) => { 12 | return baseApi.get(`/comments?q=${search}&_page=${page}&limit=10&_expand=user&_expand=post`) 13 | } 14 | 15 | export default { 16 | getCommentsByPost, 17 | getCommentsByUser, 18 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/api/index.js: -------------------------------------------------------------------------------- 1 | export {default as postsApi } from './postsApi' 2 | export {default as usersApi } from './usersApi' 3 | export {default as commentsApi } from './commentsApi' -------------------------------------------------------------------------------- /examples/spa/part8/src/api/postsApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getPosts = (page) => { 4 | return baseApi.get(`/posts?_page=${page}&limit=10&_expand=user`) 5 | } 6 | 7 | export const getPostsByUser = (userId, page) => { 8 | return baseApi.get(`/posts?userId=${userId}&_page=${page}&limit=10&_expand=user`) 9 | } 10 | 11 | export const getPostById = (postId) => { 12 | return baseApi.get(`/posts/${postId}?_expand=user`) 13 | } 14 | 15 | export const getPostsSearch = (search, page) => { 16 | return baseApi.get(`/posts?q=${search}&_page=${page}&limit=10&_expand=user`) 17 | } 18 | 19 | export default { 20 | getPosts, 21 | getPostsByUser, 22 | getPostById, 23 | getPostsSearch, 24 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/api/usersApi.js: -------------------------------------------------------------------------------- 1 | import baseApi from './baseApi' 2 | 3 | export const getUsers = (page) => { 4 | return baseApi.get(`/users?_page=${page}&limit=10`) 5 | } 6 | 7 | export const getUserById = (userId) => { 8 | return baseApi.get(`/users/${userId}`) 9 | } 10 | 11 | export const getUsersSearch = (search, page) => { 12 | return baseApi.get(`/users?q=${search}&_page=${page}&limit=10`) 13 | } 14 | 15 | export default { 16 | getUsers, 17 | getUserById, 18 | getUsersSearch, 19 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/common/constants.js: -------------------------------------------------------------------------------- 1 | const appConstants = { 2 | routes: { 3 | index: '/', 4 | posts: '/posts', 5 | postsSearch: '/posts/query/:query', 6 | usersSearch: '/users/query/:query', 7 | users: '/users', 8 | post: '/post/:post', 9 | user: '/user/:user', 10 | userPosts: '/user/:user/posts', 11 | userComments: '/user/:user/comments', 12 | }, 13 | search: { 14 | types: { 15 | post: 'post', 16 | user: 'user', 17 | } 18 | }, 19 | lists: { 20 | types: { 21 | post: 'post', 22 | user: 'user', 23 | comment: 'comment', 24 | } 25 | } 26 | } 27 | 28 | export default appConstants -------------------------------------------------------------------------------- /examples/spa/part8/src/components/index.js: -------------------------------------------------------------------------------- 1 | import './link-component' 2 | import './nav-component' 3 | import './user-avatar' 4 | import './post-component' 5 | import './user-component' 6 | import './list-component' 7 | import './pagination-component' 8 | import './post-detail' 9 | import './comment-component' 10 | import './date-formatted' 11 | import './app-component' 12 | import './fake-form' 13 | import './modal-dialog' 14 | 15 | -------------------------------------------------------------------------------- /examples/spa/part8/src/index.js: -------------------------------------------------------------------------------- 1 | import './styles/main.scss' 2 | import initRouter from './router' 3 | import './components' 4 | 5 | initRouter() 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/main.template: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 |
    ${props.topBlock || ''}
    10 |
    ${props.leftBlock || ''}
    11 |
    ${props.rightBlock || ''}
    12 |
    ${props.bottomBlock || ''}
    13 |
    -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/main/bottom.template: -------------------------------------------------------------------------------- 1 | 25 |
    26 | ${ [...Array(20).keys()].map((block)=>{ 27 | return `
    Bottom block ${block+1}
    ` 28 | }).join('\n')} 29 |
    -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/main/right.template: -------------------------------------------------------------------------------- 1 | 30 | 31 |
    32 | ${ [...Array(12).keys()].map((block)=>{ 33 | return `
    34 | 35 |
    ` 36 | }).join('\n')} 37 |
    38 | 39 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/main/top.template: -------------------------------------------------------------------------------- 1 | 23 |
    24 | ${ [...Array(10).keys()].map((block)=>{ 25 | return `
    Top block ${block+1}
    ` 26 | }).join('\n')} 27 |
    -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/post.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/posts.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/user.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/userComments.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/userPosts.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/spa/part8/src/pages/users.template: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/spa/part8/src/service/comments.js: -------------------------------------------------------------------------------- 1 | const comments = new Map() 2 | 3 | export const getComment = (commentId) => { 4 | return comments.get(commentId) 5 | } 6 | 7 | export const setComment = (comment) => { 8 | return comments.set(comment.id, comment) 9 | } 10 | 11 | export default { 12 | getComment, 13 | setComment, 14 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/service/posts.js: -------------------------------------------------------------------------------- 1 | const posts = new Map() 2 | 3 | export const getPost = (postId) => { 4 | return posts.get(postId) 5 | } 6 | 7 | export const setPost = (post) => { 8 | posts.set(post.id, post) 9 | } 10 | 11 | export default { 12 | getPost, 13 | setPost 14 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/service/users.js: -------------------------------------------------------------------------------- 1 | const users = new Map() 2 | 3 | export const getUser = (userId) => { 4 | return users.get(userId) 5 | } 6 | 7 | export const setUser = (user) => { 8 | users.set(user.id, user) 9 | } 10 | 11 | export default { 12 | getUser, 13 | setUser 14 | } -------------------------------------------------------------------------------- /examples/spa/part8/src/styles/common.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | background-color: #fff; 4 | color: #000; 5 | } 6 | -------------------------------------------------------------------------------- /examples/spa/part8/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import 'common.scss'; 2 | 3 | body{ 4 | background-color: #fff; 5 | color: #000; 6 | } 7 | -------------------------------------------------------------------------------- /examples/spa/part8/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { ViteAliases } from "vite-aliases"; 3 | import legacy from "@vitejs/plugin-legacy" 4 | import TemplateLoader from './plugins/vite-template-plugin' 5 | 6 | export default defineConfig({ 7 | build: { 8 | target: 'es2017', 9 | outDir: 'build', 10 | }, 11 | server: { 12 | port: 3000, 13 | host: '0.0.0.0', 14 | hmr: true, 15 | }, 16 | plugins: [ 17 | ViteAliases(), 18 | TemplateLoader(), 19 | legacy({ 20 | targets: ['defaults', 'not IE 11'], 21 | }) 22 | ], 23 | }) --------------------------------------------------------------------------------