From f195758c8f29d39a4f2bed35269fedfad11afa1b Mon Sep 17 00:00:00 2001 From: derFaizio Date: Wed, 12 Apr 2017 11:39:13 +0200 Subject: [PATCH 01/25] Updated multiple-window-electron-desktop-app to work with electron v1.6.2 --- multi-window-electron-desktop-app/app.js | 51 ++++++++++---------- multi-window-electron-desktop-app/main.js | 38 ++++++++------- multi-window-electron-desktop-app/prefs.html | 36 +++++++------- 3 files changed, 63 insertions(+), 62 deletions(-) diff --git a/multi-window-electron-desktop-app/app.js b/multi-window-electron-desktop-app/app.js index 7f2c2ff..31202f9 100644 --- a/multi-window-electron-desktop-app/app.js +++ b/multi-window-electron-desktop-app/app.js @@ -1,26 +1,25 @@ -var app = require('app') -var BrowserWindow = require('browser-window') -var ipc = require('ipc') - -app.on('ready', function () { - var mainWindow = new BrowserWindow({ - width: 800, - height: 600 - }) - mainWindow.loadUrl('file://' + __dirname + '/main.html') - mainWindow.openDevTools() - - var prefsWindow = new BrowserWindow({ - width: 400, - height: 400, - show: false - }) - prefsWindow.loadUrl('file://' + __dirname + '/prefs.html') - - ipc.on('toggle-prefs', function () { - if (prefsWindow.isVisible()) - prefsWindow.hide() - else - prefsWindow.show() - }) -}) +const {app, BrowserWindow, ipcMain} = require('electron') + +app.on('ready', function () { + var mainWindow = new BrowserWindow({ + width: 800, + height: 600 + }) + mainWindow.loadURL('file://' + __dirname + '/main.html') + mainWindow.openDevTools() + + var prefsWindow = new BrowserWindow({ + width: 400, + height: 400, + show: false + }) + prefsWindow.loadURL('file://' + __dirname + '/prefs.html') + + ipcMain.on('toggle-prefs', function () { + if (prefsWindow.isVisible()) + prefsWindow.hide() + else + prefsWindow.show() + }) + +}) \ No newline at end of file diff --git a/multi-window-electron-desktop-app/main.js b/multi-window-electron-desktop-app/main.js index 5f2724d..2f4a239 100644 --- a/multi-window-electron-desktop-app/main.js +++ b/multi-window-electron-desktop-app/main.js @@ -1,18 +1,20 @@ -var remote = require('remote') -var ipc = require('ipc') -var Menu = remote.require('menu') - -var menu = Menu.buildFromTemplate([ - { - label: 'Electron', - submenu: [ - { - label: 'Prefs', - click: function () { - ipc.send('toggle-prefs') - } - } - ] - } -]) -Menu.setApplicationMenu(menu) +const {remote, ipcRenderer} = require('electron') +const {Menu, MenuItem} = remote + +const menu = new Menu() + +menu.append(new MenuItem( + { + label: 'Electron', + submenu: [ + { + label: 'Prefs', + click: function () { + ipcRenderer.send('toggle-prefs') + } + } + ] + }) +) + +Menu.setApplicationMenu(menu) \ No newline at end of file diff --git a/multi-window-electron-desktop-app/prefs.html b/multi-window-electron-desktop-app/prefs.html index 52ee719..5abaa90 100644 --- a/multi-window-electron-desktop-app/prefs.html +++ b/multi-window-electron-desktop-app/prefs.html @@ -1,18 +1,18 @@ - - - - - - Prefs - - - + + + + + + Prefs + + + \ No newline at end of file From e5f91a822bf0541d4d9df60305aa447e7ba05da0 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 21 Mar 2018 08:25:28 -0700 Subject: [PATCH 02/25] dom event listeners example --- .gitignore | 1 + dom-event-listeners/index.js | 31 +++++++++++++++++++++++++++++++ dom-event-listeners/package.json | 15 +++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 dom-event-listeners/index.js create mode 100644 dom-event-listeners/package.json diff --git a/.gitignore b/.gitignore index 66fd66c..d763b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules npm-debug.log* +package-lock.json \ No newline at end of file diff --git a/dom-event-listeners/index.js b/dom-event-listeners/index.js new file mode 100644 index 0000000..9155c39 --- /dev/null +++ b/dom-event-listeners/index.js @@ -0,0 +1,31 @@ +const bear = document.createElement('button') +bear.textContent = 'growl' + +// bear.addEventListener('click', function onclick (e) { +// console.log(e.target) +// }, false) + + +const forest = document.createElement('div') +for (var i = 0; i < 100; i++) { + const bear = document.createElement('button') + bear.textContent = 'click ' + i + forest.appendChild(bear) +} +document.body.appendChild(forest) + +forest.addEventListener('click', function (e) { + console.log(e.currentTarget) +}, false) + +document.addEventListener('click', function (e) { + console.log(e.target) +}, false) + +const cat = document.createElement('button') +cat.textContent = 'meow' +forest.appendChild(cat) +cat.addEventListener('click', function (e) { + e.stopPropagation() + console.log('mew') +}, false) \ No newline at end of file diff --git a/dom-event-listeners/package.json b/dom-event-listeners/package.json new file mode 100644 index 0000000..33a8962 --- /dev/null +++ b/dom-event-listeners/package.json @@ -0,0 +1,15 @@ +{ + "name": "dom-event-listeners", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js --live", + "test": "node test.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0" + } +} From 05fb4a87a57f0c5c880f833720634d0dcf89ec9f Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 21 Mar 2018 08:28:14 -0700 Subject: [PATCH 03/25] Add readme for dom event listeners --- dom-event-listeners/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 dom-event-listeners/README.md diff --git a/dom-event-listeners/README.md b/dom-event-listeners/README.md new file mode 100644 index 0000000..789b957 --- /dev/null +++ b/dom-event-listeners/README.md @@ -0,0 +1,10 @@ +# DOM Event Listeners + +> [https://youtu.be/ocXVINp-5oU](https://youtu.be/ocXVINp-5oU) + +Install [Node.js](https://nodejs.org/en/). + +Within this folder run the terminal command `npm install` to install the +`dependencies`. + +Then run `npm start` to start up a development server on `http://localhost:9966` From 4f6a266d95d7bcf3f832183ab5d3e17e5b1f0eba Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 21 Mar 2018 08:28:30 -0700 Subject: [PATCH 04/25] Fix crlf --- multi-window-electron-desktop-app/app.js | 48 ++++++++++---------- multi-window-electron-desktop-app/main.js | 38 ++++++++-------- multi-window-electron-desktop-app/prefs.html | 34 +++++++------- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/multi-window-electron-desktop-app/app.js b/multi-window-electron-desktop-app/app.js index 31202f9..475bd53 100644 --- a/multi-window-electron-desktop-app/app.js +++ b/multi-window-electron-desktop-app/app.js @@ -1,25 +1,25 @@ -const {app, BrowserWindow, ipcMain} = require('electron') - -app.on('ready', function () { - var mainWindow = new BrowserWindow({ - width: 800, - height: 600 - }) - mainWindow.loadURL('file://' + __dirname + '/main.html') - mainWindow.openDevTools() - - var prefsWindow = new BrowserWindow({ - width: 400, - height: 400, - show: false - }) - prefsWindow.loadURL('file://' + __dirname + '/prefs.html') - - ipcMain.on('toggle-prefs', function () { - if (prefsWindow.isVisible()) - prefsWindow.hide() - else - prefsWindow.show() - }) - +const {app, BrowserWindow, ipcMain} = require('electron') + +app.on('ready', function () { + var mainWindow = new BrowserWindow({ + width: 800, + height: 600 + }) + mainWindow.loadURL('file://' + __dirname + '/main.html') + mainWindow.openDevTools() + + var prefsWindow = new BrowserWindow({ + width: 400, + height: 400, + show: false + }) + prefsWindow.loadURL('file://' + __dirname + '/prefs.html') + + ipcMain.on('toggle-prefs', function () { + if (prefsWindow.isVisible()) + prefsWindow.hide() + else + prefsWindow.show() + }) + }) \ No newline at end of file diff --git a/multi-window-electron-desktop-app/main.js b/multi-window-electron-desktop-app/main.js index 2f4a239..a6bf75e 100644 --- a/multi-window-electron-desktop-app/main.js +++ b/multi-window-electron-desktop-app/main.js @@ -1,20 +1,20 @@ -const {remote, ipcRenderer} = require('electron') -const {Menu, MenuItem} = remote - -const menu = new Menu() - -menu.append(new MenuItem( - { - label: 'Electron', - submenu: [ - { - label: 'Prefs', - click: function () { - ipcRenderer.send('toggle-prefs') - } - } - ] - }) -) - +const {remote, ipcRenderer} = require('electron') +const {Menu, MenuItem} = remote + +const menu = new Menu() + +menu.append(new MenuItem( + { + label: 'Electron', + submenu: [ + { + label: 'Prefs', + click: function () { + ipcRenderer.send('toggle-prefs') + } + } + ] + }) +) + Menu.setApplicationMenu(menu) \ No newline at end of file diff --git a/multi-window-electron-desktop-app/prefs.html b/multi-window-electron-desktop-app/prefs.html index 5abaa90..ab4028e 100644 --- a/multi-window-electron-desktop-app/prefs.html +++ b/multi-window-electron-desktop-app/prefs.html @@ -1,18 +1,18 @@ - - - - - - Prefs - - + + + + + + Prefs + + \ No newline at end of file From f9d084f480e2ed83e8330f4e57f05b3cd4ca45f2 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Sat, 24 Mar 2018 21:37:35 -0700 Subject: [PATCH 05/25] Updating budo for security warnings --- ajax-requests/package.json | 2 +- debugging-javascript/package.json | 2 +- intro-to-leveldb/package.json | 2 +- javascript-modules/package.json | 2 +- js-arrays/package.json | 2 +- js-timers/package.json | 2 +- learn-to-yo-yo/package.json | 2 +- mastering-callbacks/package.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ajax-requests/package.json b/ajax-requests/package.json index 13656ce..ed9637e 100644 --- a/ajax-requests/package.json +++ b/ajax-requests/package.json @@ -12,6 +12,6 @@ "nets": "^3.1.0" }, "devDependencies": { - "budo": "^4.1.0" + "budo": "^11.2.0" } } diff --git a/debugging-javascript/package.json b/debugging-javascript/package.json index f6a635b..bfed94b 100644 --- a/debugging-javascript/package.json +++ b/debugging-javascript/package.json @@ -12,6 +12,6 @@ "nets": "^3.2.0" }, "devDependencies": { - "budo": "^5.1.5" + "budo": "^11.2.0" } } diff --git a/intro-to-leveldb/package.json b/intro-to-leveldb/package.json index e447f3c..6fb6107 100644 --- a/intro-to-leveldb/package.json +++ b/intro-to-leveldb/package.json @@ -13,7 +13,7 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "budo": "^4.2.1" + "budo": "^11.2.0" }, "dependencies": { "level": "^1.3.0", diff --git a/javascript-modules/package.json b/javascript-modules/package.json index d2b3523..6ebbe01 100644 --- a/javascript-modules/package.json +++ b/javascript-modules/package.json @@ -24,6 +24,6 @@ "devDependencies": { "babel-preset-es2015": "^6.3.13", "babelify": "^7.2.0", - "budo": "^7.1.0" + "budo": "^11.2.0" } } diff --git a/js-arrays/package.json b/js-arrays/package.json index 7ace0d8..c258380 100644 --- a/js-arrays/package.json +++ b/js-arrays/package.json @@ -10,6 +10,6 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "budo": "^4.1.0" + "budo": "^11.2.0" } } diff --git a/js-timers/package.json b/js-timers/package.json index 03b07da..99f25bb 100644 --- a/js-timers/package.json +++ b/js-timers/package.json @@ -9,6 +9,6 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "budo": "^4.2.1" + "budo": "^11.2.0" } } diff --git a/learn-to-yo-yo/package.json b/learn-to-yo-yo/package.json index 66cee81..aea44e3 100644 --- a/learn-to-yo-yo/package.json +++ b/learn-to-yo-yo/package.json @@ -10,6 +10,6 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "budo": "^8.3.0" + "budo": "^11.2.0" } } diff --git a/mastering-callbacks/package.json b/mastering-callbacks/package.json index 794b373..8ce1efe 100644 --- a/mastering-callbacks/package.json +++ b/mastering-callbacks/package.json @@ -9,6 +9,6 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "budo": "^4.0.0" + "budo": "^11.2.0" } } From f3dcb849798a92ce42d2da2af9712cd6fe302d02 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Sat, 24 Mar 2018 21:47:33 -0700 Subject: [PATCH 06/25] Updating deps and config --- getting-started-with-browserify/package.json | 4 ++-- getting-started-with-webpack/package.json | 17 +++++++---------- getting-started-with-webpack/webpack.config.js | 11 +++++++++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/getting-started-with-browserify/package.json b/getting-started-with-browserify/package.json index cf9744f..4437839 100644 --- a/getting-started-with-browserify/package.json +++ b/getting-started-with-browserify/package.json @@ -10,10 +10,10 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "browserify": "^9.0.8", + "browserify": "^16.1.1", "watchify": "^3.1.1" }, "dependencies": { - "jquery": "^2.1.3" + "jquery": "^3.3.1" } } diff --git a/getting-started-with-webpack/package.json b/getting-started-with-webpack/package.json index 84eb5e8..4322a9f 100644 --- a/getting-started-with-webpack/package.json +++ b/getting-started-with-webpack/package.json @@ -8,18 +8,15 @@ "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", "devDependencies": { - "css-loader": "^0.15.1", - "style-loader": "^0.12.3", - "webpack": "^1.10.1", - "webpack-dev-server": "^1.10.1" + "css-loader": "^0.28.11", + "style-loader": "^0.20.3", + "webpack": "^4.2.0", + "webpack-cli": "^2.0.13", + "webpack-dev-server": "^3.1.1" }, "dependencies": { - "css-loader": "~0.15.1", - "jquery": "^2.1.4", - "node-libs-browser": "~0.5.2", - "style-loader": "~0.12.3", - "webpack": "~1.10.1", - "webpack-dev-server": "~1.10.1" + "jquery": "^3.3.1", + "node-libs-browser": "^2.1.0" }, "description": "" } diff --git a/getting-started-with-webpack/webpack.config.js b/getting-started-with-webpack/webpack.config.js index 6b1ee5c..e0ce9c5 100644 --- a/getting-started-with-webpack/webpack.config.js +++ b/getting-started-with-webpack/webpack.config.js @@ -4,9 +4,16 @@ module.exports = { path: __dirname, filename: 'bundle.js' }, + mode: 'development', module: { - loaders: [ - { test: /\.css$/, loader: 'style!css!' } + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + } ] } } From dd6013289ee9c46604e4866c590558ba0a8e1bcc Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Sun, 25 Mar 2018 11:02:43 -0700 Subject: [PATCH 07/25] Guide on the dev setup I use --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/README.md b/README.md index db7a5dc..6959969 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,70 @@ All the code examples for the youtube series ## Ideas? If you have any screencast you'd like to see or suggestions, please [open an issue here](https://github.com/shama/letswritecode/issues). Thanks! + +## Dev Setup +Throughout these videos I typically use the same development environment. This +is a guide through that development setup. + +### Dependencies +Rather than copying / pasting script tags into my HTML for 3rd party code, I use +[npm](https://www.npmjs.com/). The `npm` command comes with Node.js. When I run +`npm install jquery`, it downloads the 3rd party files into the `node_modules/jquery/` +folder. + +The `package.json` file can hold those dependencies and versions, so the next +time you want to install those files, run `npm install` in the same folder. + +### Build Tool +[Browserify](http://browserify.org/) is a tool that reads your JavaScript source +files and files you've installed with `npm`. Then outputs those files loaded in +the correct order to a single bundled file. + +You can install the `browserify` command on your machine with: `npm install browserify -g`. + +To create a bundled file, run `browserify index.js -o bundle.js`, where `index.js` +is the entry point to all your scripts. + +In your `index.js` file, you can include other files with `require('./other.js')` +or a 3rd party file installed with `npm` by doing `require('jquery')`. + +Once you have generated this `bundle.js` file, you can add a single script tag in +your HTML: `` and host those assets like any +other HTML, JavaScript and CSS files. + +### Dev Server +While rapidly developing, running the `browserify` command every time you make +a change in the code can get tedious. Also having to FTP, git push or some other +method to deploy the code to a server can slow your development down. + +I use a tool called [budo](https://www.npmjs.com/package/budo) which runs a server +locally on your machine (`http://localhost:9966`) and automatically bundles your +code with Browserify as you refresh the page or live as you make changes if you +have the `--live` option on. + +Install the `budo` command with: `npm install budo` and run the server with: +`budo index.js`. Now you can rapidly develop the code by viewing `localhost:9966`. + +For convenience, I add the `budo` command to the `scripts` section of my +`package.json`: + +```json +{ + "scripts": { + "start": "budo index.js" + } +} +``` + +Now I only need to run `npm start` to start developing code. + +### Deployment +After you're done developing the code, run `browserify index.js -o bundle.js` to +create your JavaScript bundle. Add the script tag to your HTML: +`` to load that JavaScript file. + +Then upload those files to your remote server. Either via FTP/SFTP, +[`git` deploying](https://www.youtube.com/watch?v=9qIK8ZC9BnU), +[heroku](https://devcenter.heroku.com/categories/deployment), +[firebase](https://firebase.google.com/docs/hosting/deploying) or whatever method +you normally use to deploy your website. From a4398aec5d83681e179e186b25c06920d469f59f Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Tue, 27 Mar 2018 09:27:02 -0700 Subject: [PATCH 08/25] Getting started with Vue.js --- getting-started-with-vuejs/App.vue | 33 +++++++++++++++++++++++++ getting-started-with-vuejs/BearList.vue | 19 ++++++++++++++ getting-started-with-vuejs/README.md | 10 ++++++++ getting-started-with-vuejs/index.html | 11 +++++++++ getting-started-with-vuejs/index.js | 8 ++++++ getting-started-with-vuejs/package.json | 22 +++++++++++++++++ 6 files changed, 103 insertions(+) create mode 100644 getting-started-with-vuejs/App.vue create mode 100644 getting-started-with-vuejs/BearList.vue create mode 100644 getting-started-with-vuejs/README.md create mode 100644 getting-started-with-vuejs/index.html create mode 100644 getting-started-with-vuejs/index.js create mode 100644 getting-started-with-vuejs/package.json diff --git a/getting-started-with-vuejs/App.vue b/getting-started-with-vuejs/App.vue new file mode 100644 index 0000000..6054544 --- /dev/null +++ b/getting-started-with-vuejs/App.vue @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/getting-started-with-vuejs/BearList.vue b/getting-started-with-vuejs/BearList.vue new file mode 100644 index 0000000..55bf739 --- /dev/null +++ b/getting-started-with-vuejs/BearList.vue @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/getting-started-with-vuejs/README.md b/getting-started-with-vuejs/README.md new file mode 100644 index 0000000..6bf2a66 --- /dev/null +++ b/getting-started-with-vuejs/README.md @@ -0,0 +1,10 @@ +# Getting Started with Vue.js + +> [https://www.youtube.com/watch?v=iFqWU1dxm8U](https://www.youtube.com/watch?v=iFqWU1dxm8U) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/getting-started-with-vuejs/index.html b/getting-started-with-vuejs/index.html new file mode 100644 index 0000000..e16f160 --- /dev/null +++ b/getting-started-with-vuejs/index.html @@ -0,0 +1,11 @@ + + + + + Document + + +
+ + + \ No newline at end of file diff --git a/getting-started-with-vuejs/index.js b/getting-started-with-vuejs/index.js new file mode 100644 index 0000000..8e76601 --- /dev/null +++ b/getting-started-with-vuejs/index.js @@ -0,0 +1,8 @@ +const Vue = require('vue') +const App = require('./App.vue') +new Vue({ + el: '#app', + render: function (h) { + return h(App) + } +}) \ No newline at end of file diff --git a/getting-started-with-vuejs/package.json b/getting-started-with-vuejs/package.json new file mode 100644 index 0000000..ad018b6 --- /dev/null +++ b/getting-started-with-vuejs/package.json @@ -0,0 +1,22 @@ +{ + "name": "getting-started-with-vuejs", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js:bundle.js -- -t vueify", + "test": "node test.js" + }, + "browser": { + "vue": "vue/dist/vue.common.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0", + "vueify": "^9.4.1" + }, + "dependencies": { + "vue.js": "^0.3.2" + } +} From 33f3d0355e62c4f7e272407ef079536a86467d62 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Tue, 3 Apr 2018 23:12:18 -0700 Subject: [PATCH 09/25] Simple P2P with WebRTC --- simple-p2p-with-webrtc/README.md | 10 +++++++ simple-p2p-with-webrtc/index.js | 43 +++++++++++++++++++++++++++++ simple-p2p-with-webrtc/package.json | 18 ++++++++++++ simple-p2p-with-webrtc/player.js | 32 +++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 simple-p2p-with-webrtc/README.md create mode 100644 simple-p2p-with-webrtc/index.js create mode 100644 simple-p2p-with-webrtc/package.json create mode 100644 simple-p2p-with-webrtc/player.js diff --git a/simple-p2p-with-webrtc/README.md b/simple-p2p-with-webrtc/README.md new file mode 100644 index 0000000..e73c406 --- /dev/null +++ b/simple-p2p-with-webrtc/README.md @@ -0,0 +1,10 @@ +# Simple P2P with WebRTC + +> [https://youtu.be/jY9k4rfXwEI](https://youtu.be/jY9k4rfXwEI) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/simple-p2p-with-webrtc/index.js b/simple-p2p-with-webrtc/index.js new file mode 100644 index 0000000..0c3d16e --- /dev/null +++ b/simple-p2p-with-webrtc/index.js @@ -0,0 +1,43 @@ +const signalhub = require('signalhub') +const hub = signalhub('my-game', [ + 'http://localhost:8080' +]) + +const Player = require('./player.js') +const you = new Player() + +const players = {} +hub.subscribe('update').on('data', function (data) { + if (data.color === you.color) return + if (!players[data.color]) { + players[data.color] = new Player(data) + } + players[data.color].update(data) + //console.log(data) +}) + +setInterval(function () { + //hub.broadcast('update', window.location.hash) + you.update() + hub.broadcast('update', you) +}, 100) + +document.addEventListener('keypress', function (e) { + const speed = 16 + switch (e.key) { + case 'a': + you.x -= speed + break + case 'd': + you.x += speed + break + case 'w': + you.y -= speed + break + case 's': + you.y += speed + break + } +}, false) + + diff --git a/simple-p2p-with-webrtc/package.json b/simple-p2p-with-webrtc/package.json new file mode 100644 index 0000000..702c864 --- /dev/null +++ b/simple-p2p-with-webrtc/package.json @@ -0,0 +1,18 @@ +{ + "name": "simple-p2p-with-webrtc", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js", + "signalhub": "signalhub listen -p 8080" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0" + }, + "dependencies": { + "signalhub": "^4.9.0" + } +} diff --git a/simple-p2p-with-webrtc/player.js b/simple-p2p-with-webrtc/player.js new file mode 100644 index 0000000..d7e883f --- /dev/null +++ b/simple-p2p-with-webrtc/player.js @@ -0,0 +1,32 @@ +module.exports = Player + +function Player (data) { + data = data || {} + this.color = data.color || randomColor() + this.x = 0 + this.y = 0 + this.element = document.createElement('div') + Object.assign(this.element.style, { + width: '16px', + height: '16px', + position: 'absolute', + top: '0px', + left: '0px', + backgroundColor: this.color + }) + document.body.appendChild(this.element) +} + +Player.prototype.update = function (data) { + data = data || {} + this.x = data.x || this.x + this.y = data.y || this.y + Object.assign(this.element.style, { + top: this.y + 'px', + left: this.x + 'px' + }) +} + +function randomColor () { + return '#' + ((1 << 24) * Math.random() | 0).toString() +} \ No newline at end of file From 467b192f7ef59a48cd7252e18c2e5eecfacfe489 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Tue, 10 Apr 2018 22:36:40 -0700 Subject: [PATCH 10/25] Add chrome extension example --- how-to-make-chrome-extensions/README.md | 8 +++++++ .../bear/background.js | 8 +++++++ how-to-make-chrome-extensions/bear/content.js | 13 +++++++++++ .../bear/manifest.json | 18 +++++++++++++++ how-to-make-chrome-extensions/bear/popup.html | 11 +++++++++ how-to-make-chrome-extensions/bear/popup.js | 23 +++++++++++++++++++ 6 files changed, 81 insertions(+) create mode 100644 how-to-make-chrome-extensions/README.md create mode 100644 how-to-make-chrome-extensions/bear/background.js create mode 100644 how-to-make-chrome-extensions/bear/content.js create mode 100644 how-to-make-chrome-extensions/bear/manifest.json create mode 100644 how-to-make-chrome-extensions/bear/popup.html create mode 100644 how-to-make-chrome-extensions/bear/popup.js diff --git a/how-to-make-chrome-extensions/README.md b/how-to-make-chrome-extensions/README.md new file mode 100644 index 0000000..fc9afa3 --- /dev/null +++ b/how-to-make-chrome-extensions/README.md @@ -0,0 +1,8 @@ +# How To Make Chrome Extensions + +> [https://youtu.be/Ipa58NVGs_c](https://youtu.be/Ipa58NVGs_c) + +* Go to `chrome://extensions/` +* Enable Developer mode +* Load unpacked and select the `bear` folder from this project. + diff --git a/how-to-make-chrome-extensions/bear/background.js b/how-to-make-chrome-extensions/bear/background.js new file mode 100644 index 0000000..9373dd3 --- /dev/null +++ b/how-to-make-chrome-extensions/bear/background.js @@ -0,0 +1,8 @@ +window.bears = {} +chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { + window.bears[request.url] = request.count +}) + +chrome.browserAction.onClicked.addListener(function (tab) { + chrome.tabs.create({url: 'popup.html'}) +}) \ No newline at end of file diff --git a/how-to-make-chrome-extensions/bear/content.js b/how-to-make-chrome-extensions/bear/content.js new file mode 100644 index 0000000..e11d1c4 --- /dev/null +++ b/how-to-make-chrome-extensions/bear/content.js @@ -0,0 +1,13 @@ +//alert('Grrr.') +// chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { +// const re = new RegExp('bear', 'gi') +// const matches = document.documentElement.innerHTML.match(re) +// sendResponse({count: matches.length}) +// }) + +const re = new RegExp('bear', 'gi') +const matches = document.documentElement.innerHTML.match(re) +chrome.runtime.sendMessage({ + url: window.location.href, + count: matches.length +}) \ No newline at end of file diff --git a/how-to-make-chrome-extensions/bear/manifest.json b/how-to-make-chrome-extensions/bear/manifest.json new file mode 100644 index 0000000..0896d7f --- /dev/null +++ b/how-to-make-chrome-extensions/bear/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "bear", + "version": "1.0", + "manifest_version": 2, + "content_scripts": [ + { + "matches": [""], + "js": ["content.js"] + } + ], + "browser_action": { + "default_title": "Bear" + }, + "background": { + "scripts": ["background.js"] + }, + "permissions": ["tabs"] +} \ No newline at end of file diff --git a/how-to-make-chrome-extensions/bear/popup.html b/how-to-make-chrome-extensions/bear/popup.html new file mode 100644 index 0000000..78b4998 --- /dev/null +++ b/how-to-make-chrome-extensions/bear/popup.html @@ -0,0 +1,11 @@ + + + + + Document + + + + + + \ No newline at end of file diff --git a/how-to-make-chrome-extensions/bear/popup.js b/how-to-make-chrome-extensions/bear/popup.js new file mode 100644 index 0000000..8918f30 --- /dev/null +++ b/how-to-make-chrome-extensions/bear/popup.js @@ -0,0 +1,23 @@ +document.addEventListener('DOMContentLoaded', function () { + + const bg = chrome.extension.getBackgroundPage() + Object.keys(bg.bears).forEach(function (url) { + const div = document.createElement('div') + div.textContent = `${url}: ${bg.bears[url]}` + document.body.appendChild(div) + }) + + // document.querySelector('button').addEventListener('click', onclick, false) + // + // function onclick () { + // chrome.tabs.query({currentWindow: true, active: true}, function (tabs) { + // chrome.tabs.sendMessage(tabs[0].id, 'hi', setCount) + // }) + // } + // + // function setCount (res) { + // const div = document.createElement('div') + // div.textContent = `${res.count} bears` + // document.body.appendChild(div) + // } +}, false) \ No newline at end of file From 8f80244d2f1273ebb5f802701f50be7d49097972 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 18 Apr 2018 07:22:00 -0700 Subject: [PATCH 11/25] drawing animating with svgs --- drawing-animating-svgs/README.md | 10 ++++++ drawing-animating-svgs/index.html | 53 +++++++++++++++++++++++++++++ drawing-animating-svgs/index.js | 0 drawing-animating-svgs/package.json | 15 ++++++++ 4 files changed, 78 insertions(+) create mode 100644 drawing-animating-svgs/README.md create mode 100644 drawing-animating-svgs/index.html create mode 100644 drawing-animating-svgs/index.js create mode 100644 drawing-animating-svgs/package.json diff --git a/drawing-animating-svgs/README.md b/drawing-animating-svgs/README.md new file mode 100644 index 0000000..577e553 --- /dev/null +++ b/drawing-animating-svgs/README.md @@ -0,0 +1,10 @@ +# Drawing & Animating SVGs + +> [https://www.youtube.com/watch?v=Nnnx9ytFqK4](https://www.youtube.com/watch?v=Nnnx9ytFqK4) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/drawing-animating-svgs/index.html b/drawing-animating-svgs/index.html new file mode 100644 index 0000000..12cd9d8 --- /dev/null +++ b/drawing-animating-svgs/index.html @@ -0,0 +1,53 @@ + + + + + Obligatory Bear Inclusion + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drawing-animating-svgs/index.js b/drawing-animating-svgs/index.js new file mode 100644 index 0000000..e69de29 diff --git a/drawing-animating-svgs/package.json b/drawing-animating-svgs/package.json new file mode 100644 index 0000000..105a321 --- /dev/null +++ b/drawing-animating-svgs/package.json @@ -0,0 +1,15 @@ +{ + "name": "drawing-animating-svgs", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js --live", + "test": "node test.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0" + } +} From f6186b5e3e01fe3d4c526d7b5780040dbc24276d Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Thu, 26 Apr 2018 08:25:46 -0700 Subject: [PATCH 12/25] JS proxy --- javascript-proxy/README.md | 10 ++++++ javascript-proxy/array.js | 59 +++++++++++++++++++++++++++++++++++ javascript-proxy/index.js | 53 +++++++++++++++++++++++++++++++ javascript-proxy/package.json | 16 ++++++++++ javascript-proxy/person.js | 20 ++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 javascript-proxy/README.md create mode 100644 javascript-proxy/array.js create mode 100644 javascript-proxy/index.js create mode 100644 javascript-proxy/package.json create mode 100644 javascript-proxy/person.js diff --git a/javascript-proxy/README.md b/javascript-proxy/README.md new file mode 100644 index 0000000..6596ec9 --- /dev/null +++ b/javascript-proxy/README.md @@ -0,0 +1,10 @@ +# JavaScript Proxy + +> [https://youtu.be/gZ4MCb2nlfQ](https://youtu.be/gZ4MCb2nlfQ) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/javascript-proxy/array.js b/javascript-proxy/array.js new file mode 100644 index 0000000..5125216 --- /dev/null +++ b/javascript-proxy/array.js @@ -0,0 +1,59 @@ + +const IndexedArray = new Proxy(Array, { + construct: function (target, [originalArray]) { + const index = {} + originalArray.forEach(function (item) { + index[item.id] = item + }) + + const newArray = new target(...originalArray) + + return new Proxy(newArray, { + get: function (target, name) { + if (name === 'push') { + return function (item) { + index[item.id] = item + return target[name].call(target, item) + } + } else if (name === 'findById') { + return function (searchId) { + return index[searchId] + } + } + return target[name] + } + }) + } +}) + +const bears = new IndexedArray([ + { + id: 2, + name: 'grizzly', + }, + { + id: 4, + name: 'black', + }, + { + id: 3, + name: 'polar', + }, +]) + +bears.push({ + id: 55, + name: 'brown' +}) + +const brown = bears.findById(55) +console.log(brown) +console.log(bears.findById(3)) + +// const index = {} +// bears.forEach(function (bear) { +// index[bear.id] = bear +// }) +// +// const polar = index[3] +// const black = index[4] diff --git a/javascript-proxy/index.js b/javascript-proxy/index.js new file mode 100644 index 0000000..88d7492 --- /dev/null +++ b/javascript-proxy/index.js @@ -0,0 +1,53 @@ +let bears = { grizzly: true } + +let grizzlyCount = 0 + +const proxyBears = new Proxy(bears, { + get: function (target, prop) { + if (prop === 'grizzly') grizzlyCount++ + return target[prop] + }, + set: function (target, prop, value) { + if (['grizzly', 'brown', 'polar'].indexOf(prop) === -1) { + throw new Error('THAT IS TOTALLY NOT A BEAR!') + } + target[prop] = value + }, + deleteProperty: function (target, prop) { + console.log(`You have deleted ${prop}`) + delete target[prop] + } +}) + +//proxyBears.aardvark = true +proxyBears.polar = true +//delete proxyBears.polar +//console.log(proxyBears.polar) + +// proxyBears.grizzly +// proxyBears.grizzly +// proxyBears.grizzly +// proxyBears.grizzly +// console.log(grizzlyCount) + +function growl() { + return 'grrr' +} +const loudGrowl = new Proxy(growl, { + apply: function (target, thisArg, args) { + return target().toUpperCase() + '!!!' + } +}) + +console.log(loudGrowl()) + + + + + + + + + + + diff --git a/javascript-proxy/package.json b/javascript-proxy/package.json new file mode 100644 index 0000000..8c75330 --- /dev/null +++ b/javascript-proxy/package.json @@ -0,0 +1,16 @@ +{ + "name": "javascript-proxy", + "version": "0.1.0", + "description": "", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "budo": "^9.1.0" + }, + "scripts": { + "start": "budo array.js --live", + "test": "node test.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT" +} diff --git a/javascript-proxy/person.js b/javascript-proxy/person.js new file mode 100644 index 0000000..0d05ecd --- /dev/null +++ b/javascript-proxy/person.js @@ -0,0 +1,20 @@ +const person = { + first: 'Bear', + last: 'McBearison' +} + +const cleverPerson = new Proxy(person, { + get: function (target, prop) { + if (!(prop in target)) { + return prop.split('_').map(function (part) { + return target[part] + }).join(' ') + } + return target[prop] + } +}) + +console.log(cleverPerson.last_first_first_first_first_first) + +cleverPerson.last = 'Beary' +console.log(cleverPerson.first_last) \ No newline at end of file From 6db81241a5f6ef7b2f390a57194d25e6b2db13b1 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 2 May 2018 10:11:50 -0700 Subject: [PATCH 13/25] easier webgl and shaders --- easier-webgl-shaders-stackgl/README.md | 10 +++++ easier-webgl-shaders-stackgl/index.js | 48 +++++++++++++++++++++++ easier-webgl-shaders-stackgl/package.json | 20 ++++++++++ 3 files changed, 78 insertions(+) create mode 100644 easier-webgl-shaders-stackgl/README.md create mode 100644 easier-webgl-shaders-stackgl/index.js create mode 100644 easier-webgl-shaders-stackgl/package.json diff --git a/easier-webgl-shaders-stackgl/README.md b/easier-webgl-shaders-stackgl/README.md new file mode 100644 index 0000000..33caf49 --- /dev/null +++ b/easier-webgl-shaders-stackgl/README.md @@ -0,0 +1,10 @@ +# Easier WebGL and Shaders with stack.gl + +> [https://www.youtube.com/watch?v=Qsku8RfB-pM](https://www.youtube.com/watch?v=Qsku8RfB-pM) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/easier-webgl-shaders-stackgl/index.js b/easier-webgl-shaders-stackgl/index.js new file mode 100644 index 0000000..656949b --- /dev/null +++ b/easier-webgl-shaders-stackgl/index.js @@ -0,0 +1,48 @@ +const shell = require('gl-now')() +const createShader = require('gl-shader') +const createBuffer = require('gl-buffer') +const mat4 = require('gl-mat4') + +let shader, buffer +shell.on('gl-init', function () { + const gl = shell.gl + shader = createShader(gl, ` + uniform mat4 model; + uniform mat4 camera; + attribute vec3 position; + void main() { + gl_Position = camera * model * vec4(position, 1.0); + } + `, ` + void main() { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + `) + buffer = createBuffer(gl, [ + 0.0, 0.5, 0.0, + -0.5, -0.5, 0.0, + 0.5, -0.5, 0.0, + ]) +}) + +shell.on('gl-render', function () { + const gl = shell.gl + shader.bind() + buffer.bind() + + const camera = mat4.create() + mat4.perspective(camera, 45 * Math.PI / 180, shell.width / shell.height, 0.1, 1000.0) + mat4.translate(camera, camera, [0, 0, -2]) + shader.uniforms.camera = camera + + const model = mat4.create() + mat4.translate(model, model, [-.3, 0, 0]) + //mat4.rotate(model, model, 45, [0, 0, 1]) + mat4.scale(model, model, [.5, .5, 1]) + shader.uniforms.model = model + shader.attributes.position.pointer() + gl.drawArrays(gl.TRIANGLES, 0, 3) +}) + + + diff --git a/easier-webgl-shaders-stackgl/package.json b/easier-webgl-shaders-stackgl/package.json new file mode 100644 index 0000000..3bb131a --- /dev/null +++ b/easier-webgl-shaders-stackgl/package.json @@ -0,0 +1,20 @@ +{ + "name": "easier-webgl-shaders-stackgl", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js --live" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0" + }, + "dependencies": { + "gl-buffer": "^2.1.2", + "gl-mat4": "^1.2.0", + "gl-now": "^1.4.0", + "gl-shader": "^4.2.1" + } +} From 57c0b1aba7b55f408cf978d5b93b999608ecae67 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Fri, 4 May 2018 17:48:16 -0700 Subject: [PATCH 14/25] Whoops! --- simple-p2p-with-webrtc/README.md | 5 +- simple-p2p-with-webrtc/index.js | 110 ++++++++++++++++++---------- simple-p2p-with-webrtc/package.json | 3 +- simple-p2p-with-webrtc/player.js | 13 +++- 4 files changed, 85 insertions(+), 46 deletions(-) diff --git a/simple-p2p-with-webrtc/README.md b/simple-p2p-with-webrtc/README.md index e73c406..b2ea7dd 100644 --- a/simple-p2p-with-webrtc/README.md +++ b/simple-p2p-with-webrtc/README.md @@ -1,7 +1,10 @@ -# Simple P2P with WebRTC +# P2P Signaling for WebRTC +# I MADE A WEBRTC MISTAKE > [https://youtu.be/jY9k4rfXwEI](https://youtu.be/jY9k4rfXwEI) +> UPDATED with WebRTC: [https://youtu.be/gDnS1tnp1ZQ](https://youtu.be/gDnS1tnp1ZQ) + Install [Node.js](https://nodejs.org/). Within this folder run the terminal command `npm install` to install the diff --git a/simple-p2p-with-webrtc/index.js b/simple-p2p-with-webrtc/index.js index 0c3d16e..b30d4d9 100644 --- a/simple-p2p-with-webrtc/index.js +++ b/simple-p2p-with-webrtc/index.js @@ -1,43 +1,73 @@ -const signalhub = require('signalhub') -const hub = signalhub('my-game', [ - 'http://localhost:8080' -]) - -const Player = require('./player.js') -const you = new Player() - -const players = {} -hub.subscribe('update').on('data', function (data) { - if (data.color === you.color) return - if (!players[data.color]) { - players[data.color] = new Player(data) - } - players[data.color].update(data) - //console.log(data) -}) +navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function (stream) { + + const signalhub = require('signalhub') + const createSwarm = require('webrtc-swarm') + const hub = signalhub('my-game', [ + 'http://localhost:8080' + ]) + const swarm = createSwarm(hub, { + stream: stream + }) + + const Player = require('./player.js') + const you = new Player() + you.addStream(stream) + + const players = {} + swarm.on('connect', function (peer, id) { + if (!players[players]) { + players[id] = new Player() + peer.on('data', function (data) { + data = JSON.parse(data.toString()) + players[id].update(data) + }) + players[id].addStream(peer.stream) + } + }) -setInterval(function () { - //hub.broadcast('update', window.location.hash) - you.update() - hub.broadcast('update', you) -}, 100) - -document.addEventListener('keypress', function (e) { - const speed = 16 - switch (e.key) { - case 'a': - you.x -= speed - break - case 'd': - you.x += speed - break - case 'w': - you.y -= speed - break - case 's': - you.y += speed - break - } -}, false) + swarm.on('disconnect', function (peer, id) { + if (players[id]) { + players[id].element.parentNode.removeChild(players[id].element) + delete players[id] + } + }) + // hub.subscribe('update').on('data', function (data) { + // if (data.color === you.color) return + // if (!players[data.color]) { + // players[data.color] = new Player(data) + // } + // players[data.color].update(data) + // //console.log(data) + // }) + + setInterval(function () { + //hub.broadcast('update', window.location.hash) + you.update() + //hub.broadcast('update', you) + const youString = JSON.stringify(you) + swarm.peers.forEach(function (peer) { + peer.send(youString) + }) + }, 100) + + document.addEventListener('keypress', function (e) { + const speed = 16 + switch (e.key) { + case 'a': + you.x -= speed + break + case 'd': + you.x += speed + break + case 'w': + you.y -= speed + break + case 's': + you.y += speed + break + } + }, false) + +}) diff --git a/simple-p2p-with-webrtc/package.json b/simple-p2p-with-webrtc/package.json index 702c864..a735c9e 100644 --- a/simple-p2p-with-webrtc/package.json +++ b/simple-p2p-with-webrtc/package.json @@ -13,6 +13,7 @@ "budo": "^11.2.0" }, "dependencies": { - "signalhub": "^4.9.0" + "signalhub": "^4.9.0", + "webrtc-swarm": "^2.9.0" } } diff --git a/simple-p2p-with-webrtc/player.js b/simple-p2p-with-webrtc/player.js index d7e883f..a188163 100644 --- a/simple-p2p-with-webrtc/player.js +++ b/simple-p2p-with-webrtc/player.js @@ -5,10 +5,10 @@ function Player (data) { this.color = data.color || randomColor() this.x = 0 this.y = 0 - this.element = document.createElement('div') + this.element = document.createElement('video') Object.assign(this.element.style, { - width: '16px', - height: '16px', + width: '64px', + height: '64px', position: 'absolute', top: '0px', left: '0px', @@ -17,6 +17,11 @@ function Player (data) { document.body.appendChild(this.element) } +Player.prototype.addStream = function (stream) { + this.element.srcObject = stream + this.element.play() +} + Player.prototype.update = function (data) { data = data || {} this.x = data.x || this.x @@ -28,5 +33,5 @@ Player.prototype.update = function (data) { } function randomColor () { - return '#' + ((1 << 24) * Math.random() | 0).toString() + return '#' + Math.random().toString(16).substr(-6) } \ No newline at end of file From 53666c3dfcdfba2c0f018008cff5b08dfa57b93a Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 9 May 2018 12:02:54 -0700 Subject: [PATCH 15/25] Fix typo --- simple-p2p-with-webrtc/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simple-p2p-with-webrtc/index.js b/simple-p2p-with-webrtc/index.js index b30d4d9..379d143 100644 --- a/simple-p2p-with-webrtc/index.js +++ b/simple-p2p-with-webrtc/index.js @@ -15,7 +15,7 @@ navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function const players = {} swarm.on('connect', function (peer, id) { - if (!players[players]) { + if (!players[id]) { players[id] = new Player() peer.on('data', function (data) { data = JSON.parse(data.toString()) From e06c981ac07fe51a930ee7c3e29951c391cf74d5 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 9 May 2018 12:04:06 -0700 Subject: [PATCH 16/25] Fix link to video --- simple-p2p-with-webrtc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simple-p2p-with-webrtc/README.md b/simple-p2p-with-webrtc/README.md index b2ea7dd..142d040 100644 --- a/simple-p2p-with-webrtc/README.md +++ b/simple-p2p-with-webrtc/README.md @@ -3,7 +3,7 @@ > [https://youtu.be/jY9k4rfXwEI](https://youtu.be/jY9k4rfXwEI) -> UPDATED with WebRTC: [https://youtu.be/gDnS1tnp1ZQ](https://youtu.be/gDnS1tnp1ZQ) +> UPDATED with WebRTC: [https://www.youtube.com/watch?v=IqPJb6o_S1Q](https://www.youtube.com/watch?v=IqPJb6o_S1Q) Install [Node.js](https://nodejs.org/). From 1b6e42fc4d6390d87f90ce7e7a88872d399820eb Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Mon, 14 May 2018 15:03:18 -0700 Subject: [PATCH 17/25] mutation observer --- javascript-mutation-observer/README.md | 10 ++++++ javascript-mutation-observer/bears.js | 13 ++++++++ javascript-mutation-observer/index.html | 13 ++++++++ javascript-mutation-observer/index.js | 40 +++++++++++++++++++++++ javascript-mutation-observer/package.json | 14 ++++++++ javascript-mutation-observer/sizer.js | 13 ++++++++ 6 files changed, 103 insertions(+) create mode 100644 javascript-mutation-observer/README.md create mode 100644 javascript-mutation-observer/bears.js create mode 100644 javascript-mutation-observer/index.html create mode 100644 javascript-mutation-observer/index.js create mode 100644 javascript-mutation-observer/package.json create mode 100644 javascript-mutation-observer/sizer.js diff --git a/javascript-mutation-observer/README.md b/javascript-mutation-observer/README.md new file mode 100644 index 0000000..bef233b --- /dev/null +++ b/javascript-mutation-observer/README.md @@ -0,0 +1,10 @@ +# JavaScript Mutation Observer + +> [https://youtu.be/Hn2zzi_lquA](https://youtu.be/Hn2zzi_lquA) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/javascript-mutation-observer/bears.js b/javascript-mutation-observer/bears.js new file mode 100644 index 0000000..d00f052 --- /dev/null +++ b/javascript-mutation-observer/bears.js @@ -0,0 +1,13 @@ +const theOnlyBearsIKnow = ['Polar', 'Brown', 'Grizzly'] + +setTimeout(function addBear () { + const bears = document.querySelector('ul.bears') + const bear = document.createElement('li') + bear.textContent = theOnlyBearsIKnow[parseInt(Math.random() * theOnlyBearsIKnow.length, 10)] + bears.appendChild(bear) +}, Math.random() * 2000) + +setTimeout(function removeBear () { + const bears = document.querySelector('ul.bears') + bears.removeChild(bears.querySelector('li')) +}, Math.random() * 2000 + 2000) \ No newline at end of file diff --git a/javascript-mutation-observer/index.html b/javascript-mutation-observer/index.html new file mode 100644 index 0000000..538748f --- /dev/null +++ b/javascript-mutation-observer/index.html @@ -0,0 +1,13 @@ + + + + + MutationObserver + + +
    +
+ + + + \ No newline at end of file diff --git a/javascript-mutation-observer/index.js b/javascript-mutation-observer/index.js new file mode 100644 index 0000000..ea09770 --- /dev/null +++ b/javascript-mutation-observer/index.js @@ -0,0 +1,40 @@ +require('./bears.js') +require('./sizer.js') + +const observer = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + if (mutation.attributeName === 'style') { + centerModal() + } + if (mutation.addedNodes.length) { + console.log('Added', mutation.addedNodes[0]) + } + if (mutation.removedNodes.length) { + console.log('Removed', mutation.removedNodes[0]) + } + }) +}) +const bears = document.querySelector('ul.bears') +observer.observe(bears, { + childList: false, + attributes: true +}) + +function centerModal () { + const width = parseInt(bears.offsetWidth, 10) + const height = parseInt(bears.offsetHeight, 10) + Object.assign(bears.style, { + top: '50%', + left: '50%', + marginTop: -(height / 2) + 'px', + marginLeft: -(width / 2) + 'px', + }) +} + +// const poller = setInterval(function () { +// const bear = document.querySelector('ul.bears li') +// if (bear) { +// console.log(bear) +// clearInterval(poller) +// } +// }, 1000) \ No newline at end of file diff --git a/javascript-mutation-observer/package.json b/javascript-mutation-observer/package.json new file mode 100644 index 0000000..62c095c --- /dev/null +++ b/javascript-mutation-observer/package.json @@ -0,0 +1,14 @@ +{ + "name": "javascript-mutation-observer", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js:bundle.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0" + } +} diff --git a/javascript-mutation-observer/sizer.js b/javascript-mutation-observer/sizer.js new file mode 100644 index 0000000..1623c2b --- /dev/null +++ b/javascript-mutation-observer/sizer.js @@ -0,0 +1,13 @@ +setInterval(function sizer () { + const bears = document.querySelector('ul.bears') + Object.assign(bears.style, { + position: 'absolute', + border: '1px solid #ddd', + width: (Math.random() * 200) + 'px', + height: (Math.random() * 200) + 'px', + boxShadow: '0px 0px 5px 0px rgba(0,0,0,.3)', + overflow: 'hidden', + padding: '20px', + listStyle: 'none' + }) +}, 1000) \ No newline at end of file From 181bf763119cb7d546908284712f795a31a9474b Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Tue, 22 May 2018 22:57:03 -0700 Subject: [PATCH 18/25] filereader --- javascript-filereader/README.md | 10 ++++++ javascript-filereader/bear.jpg | Bin 0 -> 59569 bytes javascript-filereader/bears.csv | 3 ++ javascript-filereader/index.html | 13 +++++++ javascript-filereader/index.js | 56 +++++++++++++++++++++++++++++ javascript-filereader/package.json | 14 ++++++++ 6 files changed, 96 insertions(+) create mode 100644 javascript-filereader/README.md create mode 100644 javascript-filereader/bear.jpg create mode 100644 javascript-filereader/bears.csv create mode 100644 javascript-filereader/index.html create mode 100644 javascript-filereader/index.js create mode 100644 javascript-filereader/package.json diff --git a/javascript-filereader/README.md b/javascript-filereader/README.md new file mode 100644 index 0000000..f2e3785 --- /dev/null +++ b/javascript-filereader/README.md @@ -0,0 +1,10 @@ +# JavaScript FileReader + +> [https://www.youtube.com/watch?v=-AR-6X_98rM](https://www.youtube.com/watch?v=-AR-6X_98rM) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/javascript-filereader/bear.jpg b/javascript-filereader/bear.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b4a4aefc8cafbca7b7a546669e4dd90300a0f26 GIT binary patch literal 59569 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 literal 0 HcmV?d00001 diff --git a/javascript-filereader/bears.csv b/javascript-filereader/bears.csv new file mode 100644 index 0000000..771bfa2 --- /dev/null +++ b/javascript-filereader/bears.csv @@ -0,0 +1,3 @@ +name,type +tim,grizzly +randy,brown \ No newline at end of file diff --git a/javascript-filereader/index.html b/javascript-filereader/index.html new file mode 100644 index 0000000..1a19517 --- /dev/null +++ b/javascript-filereader/index.html @@ -0,0 +1,13 @@ + + + + + JS FileReader + + + + + + + + \ No newline at end of file diff --git a/javascript-filereader/index.js b/javascript-filereader/index.js new file mode 100644 index 0000000..2b3ef6f --- /dev/null +++ b/javascript-filereader/index.js @@ -0,0 +1,56 @@ +const input = document.querySelector('input[type="file"]') +function handleFiles (files) { + console.log(files) + const reader = new FileReader() + reader.onload = function () { + // const lines = reader.result.split('\n').map(function (line) { + // return line.split(',') + // }) + // console.log(lines) + const img = new Image() + img.onload = function () { + const canvas = document.createElement('canvas') + const context = canvas.getContext('2d') + context.drawImage(img, 0, 0) + + const imageData = context.getImageData(0, 0, canvas.width, canvas.height) + const data = imageData.data + for (var i = 0; i <= data.length; i += 4) { + const avg = (data[i] + data[i + 1] + data[i + 2]) / 3 + data[i] = avg + data[i + 1] = avg + data[i + 2] = avg + } + context.putImageData(imageData, 0, 0) + + document.body.appendChild(canvas) + //canvas.toDataURL() + //const csvfile = new Blob(['one,two,three'], { type: 'text/csv' }) + canvas.toBlob(function (blob) { + const form = new FormData() + form.append('image', blob, 'moody.jpg') + const xhr = new XMLHttpRequest() + xhr.open('POST', '/imageupload', true) + xhr.send(form) + }) + } + img.src = reader.result + //document.body.appendChild(img) + } + //reader.readAsText(files[0]) + reader.readAsDataURL(files[0]) +} + +input.addEventListener('change', function (e) { + handleFiles(input.files) +}, false) + +document.addEventListener('dragover', function (e) { + e.preventDefault() + e.stopPropagation() +}, false) +document.addEventListener('drop', function (e) { + e.preventDefault() + e.stopPropagation() + handleFiles(e.dataTransfer.files) +}, false) \ No newline at end of file diff --git a/javascript-filereader/package.json b/javascript-filereader/package.json new file mode 100644 index 0000000..270a1f7 --- /dev/null +++ b/javascript-filereader/package.json @@ -0,0 +1,14 @@ +{ + "name": "javascript-filereader", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js:bundle.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.2" + } +} From 228c24157d00cd6b55257671720c81d5ad283a2e Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Sun, 27 May 2018 10:37:04 -0700 Subject: [PATCH 19/25] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6959969..bee0d8d 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ For convenience, I add the `budo` command to the `scripts` section of my ```json { "scripts": { - "start": "budo index.js" + "start": "budo index.js:bundle.js" } } ``` From 84ecffe0b9e54fdee756b26b588adfe27d096edc Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Fri, 1 Jun 2018 08:30:39 -0700 Subject: [PATCH 20/25] Add electron, webpack, vue example --- electron-webpack-vuejs/.gitignore | 1 + electron-webpack-vuejs/README.md | 10 ++++++++ electron-webpack-vuejs/package.json | 24 ++++++++++++++++++++ electron-webpack-vuejs/src/index.html | 18 +++++++++++++++ electron-webpack-vuejs/src/main/index.js | 20 ++++++++++++++++ electron-webpack-vuejs/src/renderer/App.vue | 13 +++++++++++ electron-webpack-vuejs/src/renderer/index.js | 8 +++++++ electron-webpack-vuejs/webpack.config.js | 14 ++++++++++++ 8 files changed, 108 insertions(+) create mode 100644 electron-webpack-vuejs/.gitignore create mode 100644 electron-webpack-vuejs/README.md create mode 100644 electron-webpack-vuejs/package.json create mode 100644 electron-webpack-vuejs/src/index.html create mode 100644 electron-webpack-vuejs/src/main/index.js create mode 100644 electron-webpack-vuejs/src/renderer/App.vue create mode 100644 electron-webpack-vuejs/src/renderer/index.js create mode 100644 electron-webpack-vuejs/webpack.config.js diff --git a/electron-webpack-vuejs/.gitignore b/electron-webpack-vuejs/.gitignore new file mode 100644 index 0000000..53c37a1 --- /dev/null +++ b/electron-webpack-vuejs/.gitignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/electron-webpack-vuejs/README.md b/electron-webpack-vuejs/README.md new file mode 100644 index 0000000..e5b86ce --- /dev/null +++ b/electron-webpack-vuejs/README.md @@ -0,0 +1,10 @@ +# Electron with webpack and Vue.js + +> [https://youtu.be/oL7vIDkDOsg](https://youtu.be/oL7vIDkDOsg) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app. diff --git a/electron-webpack-vuejs/package.json b/electron-webpack-vuejs/package.json new file mode 100644 index 0000000..33d539f --- /dev/null +++ b/electron-webpack-vuejs/package.json @@ -0,0 +1,24 @@ +{ + "name": "electron-webpack-vuejs", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "electron-webpack dev", + "build": "electron-webpack && electron-builder" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "electron": "^2.0.2", + "electron-builder": "^20.15.1", + "electron-webpack": "^2.1.2", + "vue": "^2.5.16", + "vue-loader": "^15.2.2", + "vue-template-compiler": "^2.5.16", + "webpack": "^4.9.1" + }, + "dependencies": { + "source-map-support": "^0.5.6" + } +} diff --git a/electron-webpack-vuejs/src/index.html b/electron-webpack-vuejs/src/index.html new file mode 100644 index 0000000..b438956 --- /dev/null +++ b/electron-webpack-vuejs/src/index.html @@ -0,0 +1,18 @@ + + + + <%= process.env.npm_package_productName %> + + + + +
+ + diff --git a/electron-webpack-vuejs/src/main/index.js b/electron-webpack-vuejs/src/main/index.js new file mode 100644 index 0000000..8e4e7f9 --- /dev/null +++ b/electron-webpack-vuejs/src/main/index.js @@ -0,0 +1,20 @@ +import { app, BrowserWindow } from 'electron' +import path from 'path' +import { format as formatUrl } from 'url' + +const isDevelopment = process.env.NODE_ENV !== 'production' + +app.on('ready', () => { + let window = new BrowserWindow({ + width: 1024 + }) + if (isDevelopment) { + window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`) + } else { + window.loadURL(formatUrl({ + pathname: path.join(__dirname, 'index.html'), + protocol: 'file', + slashes: true + })) + } +}) \ No newline at end of file diff --git a/electron-webpack-vuejs/src/renderer/App.vue b/electron-webpack-vuejs/src/renderer/App.vue new file mode 100644 index 0000000..49f4ae4 --- /dev/null +++ b/electron-webpack-vuejs/src/renderer/App.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/electron-webpack-vuejs/src/renderer/index.js b/electron-webpack-vuejs/src/renderer/index.js new file mode 100644 index 0000000..734a3c1 --- /dev/null +++ b/electron-webpack-vuejs/src/renderer/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue' +import App from './App.vue' +new Vue({ + el: '#app', + render(h) { + return h(App) + } +}) \ No newline at end of file diff --git a/electron-webpack-vuejs/webpack.config.js b/electron-webpack-vuejs/webpack.config.js new file mode 100644 index 0000000..f9d3d0e --- /dev/null +++ b/electron-webpack-vuejs/webpack.config.js @@ -0,0 +1,14 @@ +const VueLoaderPlugin = require('vue-loader/lib/plugin') +module.exports = { + module: { + rules: [ + { + test: /\.vue$/, + use: 'vue-loader' + } + ] + }, + plugins: [ + new VueLoaderPlugin() + ] +} \ No newline at end of file From 4cdd81a41dee9e20e5f5e5e4917d6475d5f7f220 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Tue, 5 Jun 2018 22:54:51 -0700 Subject: [PATCH 21/25] vuejs computed properties --- vuejs-computed-properties/App.vue | 69 ++++++++++++++++++++++++++ vuejs-computed-properties/README.md | 10 ++++ vuejs-computed-properties/index.html | 11 ++++ vuejs-computed-properties/index.js | 28 +++++++++++ vuejs-computed-properties/package.json | 22 ++++++++ 5 files changed, 140 insertions(+) create mode 100644 vuejs-computed-properties/App.vue create mode 100644 vuejs-computed-properties/README.md create mode 100644 vuejs-computed-properties/index.html create mode 100644 vuejs-computed-properties/index.js create mode 100644 vuejs-computed-properties/package.json diff --git a/vuejs-computed-properties/App.vue b/vuejs-computed-properties/App.vue new file mode 100644 index 0000000..3bc8f6a --- /dev/null +++ b/vuejs-computed-properties/App.vue @@ -0,0 +1,69 @@ + + + \ No newline at end of file diff --git a/vuejs-computed-properties/README.md b/vuejs-computed-properties/README.md new file mode 100644 index 0000000..7a5eefd --- /dev/null +++ b/vuejs-computed-properties/README.md @@ -0,0 +1,10 @@ +# Vue.js Computed Properties + +> [https://www.youtube.com/watch?v=8antoF7LyIo](https://www.youtube.com/watch?v=8antoF7LyIo) + +Install [Node.js](https://nodejs.org/). + +Within this folder run the terminal command `npm install` to install the +`dependencies` and `devDependencies`. + +Then run `npm start` to run the app viewable on `http://localhost:9966`. diff --git a/vuejs-computed-properties/index.html b/vuejs-computed-properties/index.html new file mode 100644 index 0000000..e16f160 --- /dev/null +++ b/vuejs-computed-properties/index.html @@ -0,0 +1,11 @@ + + + + + Document + + +
+ + + \ No newline at end of file diff --git a/vuejs-computed-properties/index.js b/vuejs-computed-properties/index.js new file mode 100644 index 0000000..49fe2a2 --- /dev/null +++ b/vuejs-computed-properties/index.js @@ -0,0 +1,28 @@ +const Vue = require('vue') +const App = require('./App.vue') + +const beardb = { + 'bear1': { + name: 'Oliver', + type: 'grizzly' + }, + 'bear3': { + name: 'Sheryl', + type: 'brown' + }, + 'bear55': { + name: 'Frank', + type: 'polar' + }, +} + +new Vue({ + el: '#app', + render: function (h) { + return h(App, { + props: { + beardb: beardb + } + }) + } +}) \ No newline at end of file diff --git a/vuejs-computed-properties/package.json b/vuejs-computed-properties/package.json new file mode 100644 index 0000000..8f6f8b5 --- /dev/null +++ b/vuejs-computed-properties/package.json @@ -0,0 +1,22 @@ +{ + "name": "vuejs-computed-properties", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "budo index.js:bundle.js -- -t vueify", + "test": "node test.js" + }, + "browser": { + "vue": "vue/dist/vue.common.js" + }, + "author": "Kyle Robinson Young (http://dontkry.com)", + "license": "MIT", + "devDependencies": { + "budo": "^11.2.0", + "vueify": "^9.4.1" + }, + "dependencies": { + "vue.js": "^0.3.2" + } +} From df82325714b656caf8a490480c1e6256c06a8357 Mon Sep 17 00:00:00 2001 From: Willy Weise Date: Wed, 1 Aug 2018 14:35:45 +0200 Subject: [PATCH 22/25] Added app.quit() at main/index.js when closing the window so that process of the app quits running in the background --- electron-webpack-vuejs/src/main/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/electron-webpack-vuejs/src/main/index.js b/electron-webpack-vuejs/src/main/index.js index 8e4e7f9..c868d9d 100644 --- a/electron-webpack-vuejs/src/main/index.js +++ b/electron-webpack-vuejs/src/main/index.js @@ -17,4 +17,8 @@ app.on('ready', () => { slashes: true })) } + window.on('closed', function(){ + window = null + app.quit() + }) }) \ No newline at end of file From e035f48e4238c939d953bdfc1bba9bc75bb2b943 Mon Sep 17 00:00:00 2001 From: Willy Weise Date: Tue, 7 Aug 2018 17:09:29 +0200 Subject: [PATCH 23/25] app.quit will now be called when all windows are closed instead by closing only the main window. On macOS the app is not supposed to quit --- electron-webpack-vuejs/src/main/index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/electron-webpack-vuejs/src/main/index.js b/electron-webpack-vuejs/src/main/index.js index c868d9d..374e69a 100644 --- a/electron-webpack-vuejs/src/main/index.js +++ b/electron-webpack-vuejs/src/main/index.js @@ -17,8 +17,13 @@ app.on('ready', () => { slashes: true })) } - window.on('closed', function(){ - window = null - app.quit() + window.on("closed", () => { + window = null; }) +}) + +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } }) \ No newline at end of file From 3eb01f336501ae20d1106430d657a732297337e8 Mon Sep 17 00:00:00 2001 From: Kunal Mandalia Date: Sat, 22 Jun 2019 18:13:22 +0100 Subject: [PATCH 24/25] fix: chrome extension error --- how-to-make-chrome-extensions/bear/content.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/how-to-make-chrome-extensions/bear/content.js b/how-to-make-chrome-extensions/bear/content.js index e11d1c4..b249bae 100644 --- a/how-to-make-chrome-extensions/bear/content.js +++ b/how-to-make-chrome-extensions/bear/content.js @@ -6,7 +6,8 @@ // }) const re = new RegExp('bear', 'gi') -const matches = document.documentElement.innerHTML.match(re) +const matches = document.documentElement.innerHTML.match(re) || [] + chrome.runtime.sendMessage({ url: window.location.href, count: matches.length From b47b31e3553cfe15dd9c9d53afd64fc77dd2b493 Mon Sep 17 00:00:00 2001 From: Chuck Benedict Date: Wed, 6 Nov 2019 08:56:15 -0800 Subject: [PATCH 25/25] Ignored signing on Mac. Enabled nodeIntegration (now disabled by default). --- electron-webpack-vuejs/.gitignore | 4 +++- electron-webpack-vuejs/package.json | 2 +- electron-webpack-vuejs/src/main/index.js | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/electron-webpack-vuejs/.gitignore b/electron-webpack-vuejs/.gitignore index 53c37a1..0841ed3 100644 --- a/electron-webpack-vuejs/.gitignore +++ b/electron-webpack-vuejs/.gitignore @@ -1 +1,3 @@ -dist \ No newline at end of file +dist +node_modules +package-lock.json \ No newline at end of file diff --git a/electron-webpack-vuejs/package.json b/electron-webpack-vuejs/package.json index 33d539f..cd652ea 100644 --- a/electron-webpack-vuejs/package.json +++ b/electron-webpack-vuejs/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "electron-webpack dev", - "build": "electron-webpack && electron-builder" + "build": "electron-webpack && electron-builder -c.mac.identity=null" }, "author": "Kyle Robinson Young (http://dontkry.com)", "license": "MIT", diff --git a/electron-webpack-vuejs/src/main/index.js b/electron-webpack-vuejs/src/main/index.js index 374e69a..acd13a1 100644 --- a/electron-webpack-vuejs/src/main/index.js +++ b/electron-webpack-vuejs/src/main/index.js @@ -6,7 +6,10 @@ const isDevelopment = process.env.NODE_ENV !== 'production' app.on('ready', () => { let window = new BrowserWindow({ - width: 1024 + width: 1024, + webPreferences: { + nodeIntegration: true + } }) if (isDevelopment) { window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`)