Why do not you upload the images in Phaser? - javascript

I'm trying to upload images to Phaser in order to create an application.
I created a server with node.js
but they do not load the images, it loads a black background with a square in the center.
I edit the question:
I have added the html code where it is called Phaser.
Phaser install it with npm and function perfectly as you sample the console.
I show the image of the console on the network, as they suggested.
I hope this helps the companions to be able to help me, if I have to add more, they should just tell me.
console image
The Chrome inspector does not give me any errors, it shows that Phaser normally charges.
I have changed the configuration of my server several times without success, finally use one that I saw in another site.
This is my server.js file and the code that should be loaded.
const http = require('http')
const fs = require('fs')
const path = require('path')
http.createServer(function (request, response) {
console.log('request ', request.url)
var filePath = '.' + request.url
if (filePath == './') {
filePath = './index.html'
}
var extname = String(path.extname(filePath)).toLowerCase()
var mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
'.wav': 'audio/wav',
'.mp4': 'video/mp4',
'.woff': 'application/font-woff',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'application/font-otf',
'.svg': 'application/image/svg+xml'
}
var contentType = mimeTypes[extname] || 'application/octet-stream'
fs.readFile(filePath, function(error, content) {
if (error) {
if(error.code == 'ENOENT') {
fs.readFile('./404.html', function(error, content) {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8')
})
}
else {
response.writeHead(500);
response.end('Lo sentimos, consulte con el administrador del sitio para el error: '+error.code+' ..\n')
response.end()
}
}
else {
response.writeHead(200, { 'Content-Type': contentType })
response.end(content, 'utf-8')
}
})
}).listen(3000);
console.log('server corriendo en el puerto 3000')
All the files are in the same folder, because I had the images and html files in different folders, but it did not work either.
I found several questions on the site similar to mine, but none is the same, and I found no solution in them.
Can you give me any idea why the image is not loaded?
Thanks, I hope to show enough and clearly explain my goals.
Edit:
I show you the folder structure of my project:
In the main folder of the project are files package.json, server.js
and a folder with the images and the index.html file
Phaser-tuto1 {
package.json
server.js
public(folder) [
   -index.html
      -sky.png
      -platform-png
      -start.png
      -bomb.png
      -dude.png
   ]
}
I hope to clarify with this how my project is distributed.
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Making your first Phaser 3 Game - Part 1</title>
<script src="//cdn.jsdelivr.net/npm/phaser#3.11.0/dist/phaser.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
function preload() {
this.load.image('sky', 'sky.png')
}
function create() {
this.add.image(400, 300, 'sky')
}
function update() {
}
</script>
</body>
</html>

I use express for something like this, so I'm 100% sure this is the answer, but no harm trying.
this.load.image('sky', 'sky.png') tries to go to __dirname/sky.png which you haven't established yet. In server.js, add the line
if (filePath == './sky') {
filePath = './sky.png'
}
In phaser, you would then write:
this.load.image('sky', 'sky')
I hope this helps.

in phaser 3 you add image to scene dynamically from HTML Dom input
create a scene like this and do remeber to add dom container in game config
var Menu = new Phaser.Class({
Extends: Phaser.Scene,
key:'Menu',
initialize:
function Menu ()
{
Phaser.Scene.call(this, { key: 'Menu', active: false });
},
preload:function() {
this.load.html('browse', 'assets/forms/browse-btn.html');
},
create:function(){
var element = this.add.dom(220, 180).createFromCache('browse');
element.setScale(2.3,2);
element.setPerspective(800);
element.addListener('change');
element.on('change', function (event) {
_this.loadImage(event.target.files[0]);
});
},
loadImage:function(file){
var objectURL = URL.createObjectURL(file);
var name = file.name;
const card = this.add.image(WIDTH/2, HEIGHT/2, name);
let loader = new Phaser.Loader.LoaderPlugin(this);
loader.image(name, objectURL);
loader.once(Phaser.Loader.Events.COMPLETE, () => {
// texture loaded so use instead of the placeholder
console.log("loaded successfully");
card.setTexture(name)
});
loader.start();
},
});

Related

electron js - cannot get button to perform simple actions from click

Long story short I am working on a single page application that sends commands over a local network. Testing out Electron JS and I can't even seem to get a simple button to work. I feel like I am not linking the logic between main.js and index.js somehow but for the life of me I cannot figure out the correct way to do it. I have even put breakpoints in index.js and through main.js & index.html but none of the breakpoints are hit aside from the ones in main.js. I put a simple function in a preload.js file and that function is correctly called but the one I am trying to attach to a button located in index.html and index.js is never even being hit. A lot of the commented out code is things I want to remember or things I have noticed a different method of creating and just wanted to try and see if that worked. If anyone has any answers or guidance it would be greatly appreciated! :D
Below is my main.js
//#region ---for dev only | hot reload
try {
require('electron-reloader')(module)
} catch (_) {}
//#endregion
const electron = require('electron');
const {app, BrowserWindow, Menu} = require('electron');
const path = require('path');
const ipcMain = electron.ipcMain;
//#region globals
const SRC_DIR = '/src/'
const IMG_DIR = '/assets/images'
//#endregion
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
//frame: false,
webPreferences: {
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
//Used to auto open dev tools for debugging
//win.openDevTools();
win.loadFile('src/index.html');
// win.loadURL(url.format({
// pathname: path.join(__dirname, 'index.html'),
// protocol: 'file',
// slashes: true
// }));
}
app.whenReady().then(() => {
//nativeTheme.shouldUseDarkColors = true;
createWindow();
})
//closes app processes when window is closed
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit();
})
var menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [
{label: 'Edit'},
{type: 'separator'},
{
label: 'Exit',
click() {
app.quit();
}
}
]
}
])
Menu.setApplicationMenu(menu);
Here is index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Ecas Software</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<p id="myText">Let's get started :)</p>
<button id="myBtn">Change Text</button>
<script type="text/javascript" src="./index.js" ></script>
</body>
</html>
Lastly here is my index.js (aka my first and only renderer?)
const electron = require('electron');
const chgBtn = document.getElementById('myBtn');
function replaceText(selector, text){
const element = document.getElementById(selector);
if (element) element.innerText = text;
}
chgBtn.onclick = function() {
replaceText('myText', 'no boom...');
}
// chgBtn.addEventListener('click', function(){
// // if (document.getElementById('myText').innerText == 'boom'){
// // replaceText('myText','no boom...');
// // } else {
// // replaceText('myText','boom');
// // }
// document.alert("working function");
// });
//chgBtn.addEventListener('click', replaceText('myText','no boom...'));
Why you have this error
The problem here is that you didn't use your scripts files the way Electron was intended.
If you use the Devtools Console (by uncommenting win.openDevTools()), you should see this error in your console :
Uncaught ReferenceError: require is not defined (from index.js file)
This is because your index.js file is loaded as a "normal javascript file". If you want to use the Node syntaxe (aka the "require" syntaxe), you need to do it in your preload script. Only the preload script can use the require syntaxe, since it is the only script allowed by Electron to use Node.
You can also use other javascripts files, by import it in your HTML as you did for the index.js file, but you should remove the require call. As the "require" call (on the first line) will throw and error, all the following code will not run. This is why your button did not react on click.
The correct way to do it
If you need to use some methods from the Electron Renderer API (such as the ipcRenderer), you need to put it in your preload script.
If you want to use your own script, in a separate file, you can also do it, you will not be able to directly call Electron API. There is a solution if you want to call the Electron API in your own script, it is called the Context Bridge. This allows you to create an object in your preload script, that can use the Electron API. You can give this object a name, and then call it from your others script by using the window global object.
For example, if you want to use ipcRenderer.send(channel, payload) :
// Preload script
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('theNameYouWant',
{
send: (channel, payload) => ipcRenderer.send(channel, payload)
}
)
// index.js file, imported in your HTML file
window.theNameYouWant.send("channel-name", { someData: "Hello" })
In your example
// Add this in your main.js file to see when a user click on the button from main process
ipcMain.on("button-clicked", (event, data) => console.log(data))
// Preload script
const { contextBridge, ipcRenderer } = require("electron")
contextBridge.exposeInMainWorld("electron", {
send: (channel, payload) => ipcRenderer.send(channel, payload),
})
// index.js
const chgBtn = document.getElementById("myBtn")
function replaceText(selector, text) {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
chgBtn.onclick = function () {
replaceText("myText", "no boom...")
window.electron.send("button-clicked", { someData: "Hello" })
}

Electron: Cannot find DOM elements from child window

I am trying to send a parameter and its property from the main process to the renderer process, then append that property value as a string onto a div in my html/ child window. However, the renderer process cannot find the Id I have specified and returns the error:
Cannot read property 'append' of null at EventEmitter.<anonymous>
I thought I could get around this error by sourcing the renderer file to my html but that makes the html look for other elements that are also sourced to that renderer process as I have multiple html files connected to it and it doesn't work either way.
So after this, I created another javascript file specifically for that html window but that window cannot recieve events from the main process.
Here is my current code:
HTML
<div id="brst_files">
</div>
<script type="text/javascript" src="./renderer.js">
</script>
<script>
//Open the dialog for burst button
let brstfile = document.getElementById('brst_add_files')
brstfile.addEventListener('click', function(event){
console.log('recieved')
ipcRenderer.send('brst_add_files')
console.log('add file')
})
ipcRenderer.on('brstfiles', function(event){
console.log('html recieved')
document.getElementById('brst_files').append('data.filePath')
console.log('file path recieved')
})
</script>
Main
//Open burst window dialog menu
ipcMain.on('brst_add_files', function(event){
console.log('adding files')
dialog.showOpenDialog({properties:['openFile','dontAddToRecent','multiSelections'],
filters: [
{ name: 'All Files', extensions: ['*'] }
//Recieve and send the file path data
]}).then((data) => {
console.log(data.filePaths);
mainWindow.webContents.send('brstfiles', data.filePaths)
console.log('file path sent')
});
})
}
Renderer
//Burst create window
let brstwindow = new BrowserWindow({
width:400,
height:415,
frame: false,
useContentSize: true,
backgroundColor: '#00000000',
alwaysOnTop: false,
transparent: true,
resizable: true,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
useContentSize:true
}
});
brstwindow.loadURL(url.format({
pathname: path.join(__dirname, 'Burstcreate.html'),
protocol: 'file',
slashes:true
}));
brstwindow.webContents.openDevTools()
brstwindow.hide()
//Open the burst button window
let brstopen = document.getElementById('burstbtn')
brstopen.addEventListener('click', function(event){
brstwindow.show()
})
//Recieve file path from main and append to div
ipcRenderer.on('brstfiles', function(event){
console.log('html recieved')
document.getElementById('brst_files').append('data.filePath')//I know this just appends a string
console.log('file path recieved')
})
Other renderer
const { ipcRenderer, webContents} = require('electron');
const app = require('electron').remote.app;
const electron = require('electron');
const { get } = require('http');
const BrowserWindow = electron.remote.BrowserWindow;
const path = require('path');
const { on } = require('process');
const {dialog} = require('electron')
const url = require('url');
//Recieved the file path back from main and appending it to div
ipcRenderer.on('brstfiles', function(event){
console.log('html recieved')
document.getElementById('brst_files').append('data.filePath')
console.log('file path recieved')
})
So my main question is: How can I find DOM elements in a child window from renderer? Should I do everything from the main process?
Extra question: How do I recieve parameters from main process in the renderer process?

How to access jquery from the render process inside the preload script on Electron

I configured the Node integration to false in my window because, as described in the documentation, disabling is a good practice.
I want to access the jQuery of my render process in my preload script, but I don't know How I can do this.
Is it possible to activate a modal (for example) after some event occurs in the preload script?
Link to my example code in Github: https://github.com/JhonatanRSantos/Sample
As Janith said, you don't need to use a preload script. Here is a working sample based on your Github repo :
Index.html - in HEADER part, modify like this :
<script>window.$ = window.jQuery = require('jquery');</script>
<script src="./node_modules/popper.js/dist/umd/popper.min.js"></script>
<script src="./node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
Note that you have to use the path ./node_modules/popper.js/dist/umd/popper.min.js or you will get an error in the console (see popper.js in bootstrap 4 gives SyntaxError Unexpected token export)
Index.html - FOOTER, add :
<script src="./index.js"></script>
Rename preload.js to index.js
index.js can be :
console.log('Preload.js');
setTimeout(() => {
console.log('Open Boostrap Modal');
$('#myModal').modal('show');
}, 5000);
and finally, main.js can be :
const { app, BrowserWindow } = require('electron');
const path = require('path')
const url = require('url')
let createWindow = () => {
let win = new BrowserWindow({
width: 800,
height: 500,
center: true,
resizable: false,
show: false
});
win.setMenu(null);
const mainUrl = url.format({ // https://electronjs.org/docs/api/browser-window#winloadurlurl-options
protocol: 'file',
slashes: true,
pathname: path.join(__dirname, 'index.html')
})
win.loadURL(mainUrl);
win.once('ready-to-show', () => {
win.show();
win.webContents.openDevTools();
});
win.on('closed', () => {
win = null;
});
};
app.on('ready', createWindow);
I made a pull request to your repo to get changes.

NodeJS won't Properly load other Files [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I'm having trouble getting my NodeJS server to properly return the auxiliary files an HTML files needs. Instead of returning them to their appropriate places within the files, it does something really screwy.
Here's the code in question:
index.js:
var http = require('http');
var url = require('url');
var fs = require('fs');
var path = require('path');
var findFile = (function(basename) {
var results = {
contentType: '',
data: ''
};
var dataCSS = {
dir: '../CSS/',
contentType: 'text/css'
};
var dataHTML = {
dir: '../HTML/',
contentType: 'text/html'
};
var dataJS = {
dir: '../JS/',
contentType: 'text/javascript'
};
return function(basename) {
switch (path.extname(basename)) {
case '.css':
fs.readFile(dataCSS.dir + basename, function(err, data) {
results = {
contentType: dataCSS.contentType,
data: data
};
});
break;
case '.html':
fs.readFile(dataHTML.dir + basename, function(err, data) {
results = {
contentType: dataHTML.contentType,
data: data
};
});
break;
case '.js':
fs.readFile(dataJS.dir + basename, function(err, data) {
results = {
contentType: dataJS.contentType,
data: data
};
});
break;
default:
fs.readFile(dataHTML.dir + 'Home.html', function(err, data) {
results = {
contentType: dataHTML.contentType,
data: data
};
});
break;
}
return results;
};
})();
http.createServer(function(req, res) {
var myUrl = url.parse(req.url);
var basename = path.basename(myUrl.path);
console.log('request url: ' + req.url);
if (req.url !== '/') {
console.log('File requested: ' + basename);
} else {
basename = "Home.html";
}
console.log("Basename: " + basename);
var data = findFile(basename);
console.log(data);
res.writeHead(200, { 'ContentType': data.contentType });
res.write(data.data);
res.end();
}).listen(8080);
Home.html:
<!DOCTYPE html>
<html lang="en-US">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<link rel="stylesheet" type="text/css" href="../CSS/myApp.css">
<script src="../JS/myApp.js"></script>
<script src="../JS/myCtrl.js"></script>
</head>
<body>
<h2>myApp Test</h2>
<div class="myApp" ng-app="myApp" ng-controller="myCtrl" ng-init="quantity = 10; cost = 5" my-Directive>
<p>Color: <input type="text" style="background-color:{{myColor}}" ng-model="myColor" value="{{myColor}}"></p>
<p>Total in dollar (raw exp): {{quantity * cost}}</p>
<p>Total in dollar (span): <span ng-bind="quantity * cost"></span></p>
<p> First Name: <input type="text" ng-model="firstName"></p>
<p> Last Name: <input type="text" ng-model="lastName"></p>
<h1>Hello, {{firstName + " " + lastName}}</h1>
</div>
Are you even changing?!
</body>
</html>
A current run of my code does this:
I use "node index.js" in the console to start the server.
I navigate to "localhost:8080" in my browser for the first time, it shows nothing; there's an error in the dev window that says that I did not format the headers properly. This isn't true since I set it in the findFile method on each hit to the server. A console readout first looks like this:
The dev window in Firefox looks like this:
The next refresh loads the HTML page, but without any influence from the auxiliary files, even though the logging shows everything has been requested:
console log at this point:
Subsequent refreshes turns the page into a roulette with each of the separate files representing a number on the wheel. Instead of the HTML page, one of the others might display instead, with the looks of a text file. I'll spare the pictures; I feel like I've done too many as it is.
What am I doing wrong here? Is there a different way I should be doing this? Should I even have to do this at all? Please send help.
Thank you.
fs.readFile is asynchronous, meaning the callback you give to it doesn't happen immediately, it happens sometime later. Particularly, it happens after the findFile function returns the value. See this related question for more details.
In order for findFile to work correctly, it needs to receive a callback to call whenever any of the fs.readFile operations are finished. Also look into promises and async/await as a cleaner alternative to using callbacks.
function findFile(basename, done) {
switch (path.extname(basename)) {
case ".css":
fs.readFile(dataCSS.dir + basename, function(err, data) {
var results = {
contentType: dataCSS.contentType,
data: data,
}
// this function is the `function(results)` we call with down there
done(results)
})
break
case ".html":
// same as above
case ".js":
// same as above
default:
// same as above
}
}
function requestHandler(req, res) {
// same as before
findFile(basename, function(results) {
console.log(results)
res.writeHead(200, { ContentType: results.contentType })
res.write(results.data)
res.end()
})
}
http.createServer(requestHandler).listen(8080)

gruntjs - how to list filenames and data attributes of those filenames in an HTML file?

I am creating a lot of HTML files that will be used as the design guideline for a development project. An HTML file will include the following HTML tags:
<title> Design pattern 001 </title>
<meta data-details="This design should show the basic homepage" />
<meta data-status="Approved" />
All of these files sit in a directory:
/designs/design-pattern-001.html
...
/designs/design-pattern-100.html
I want to run a grunt task that will create a separate index.html with the following syntax:
<table>
<tr>
<td> Aprooved</td>
<td> Design pattern 001 </td>
<td> This design should show the basic homepage </td>
</tr>
....
</table>
My development team will then use index.html
I tried the solution here: How do I generate a list of files in html, using a grunt task? but this only gets me the filename, not any of the data attributes within each respective HTML.
Is the only other solution to use jQuery (or JavaScript) to get this for each respective file like the solution here: Get HTML code of a local HTML file in Javascript ?
This can be done via a grunt custom task. I've gone ahead and built an example project on github using your outlined requirements above.
I was able to do it using the following node modules:
xmldom and xpath to parse the html files
pug to create the generated html from a template
Please check out the github project but here is most of the important code:
Grunt file ( in root of project ):
Defines custom tasks options
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
parseAndIndexHtmlFiles : {
options : {
output: "index.html",
directoryToParse: "design",
jadeTemplate: "index.jade",
parseHtmlTags: ["title"],
parseAttributes: ["data-details", "data-status"]
}
}
});
grunt.loadTasks('tasks');
grunt.registerTask('default', [ "parseAndIndexHtmlFiles" ]);
};
Custom task file ( in tasks folder of project ) /tasks/parseDesignHtml.js:
var DOMParser = require('xmldom').DOMParser;
var xpath = require('xpath');
var Promise = require("bluebird");
var pug = require('pug');
var tidy = require('htmltidy').tidy;
var fs = Promise.promisifyAll(require("fs"));
var options, done, globalGrunt = null;
var fileIndex = [];
module.exports = function(grunt) {
globalGrunt = grunt;
grunt.registerTask('parseAndIndexHtmlFiles', function () {
done = this.async();
options = this.options({
output : "",
directoryToParse : "",
jadeTemplate : "",
parseHtmlTags : [ ],
parseAttributes : [ ]
});
parseHtmlFiles(options.directoryToParse);
});
};
function parseHtmlFiles(directory) {
fs.readdirAsync(directory).map(function (filename) {
if (filename.match(/.html$/)) {
return readFile(directory + "/" + filename);
}
}).then(function (results) {
var contents = [];
for(var i = 0; i < results.length; i++){
if(results[i]){
contents.push(results[i]);
}
}
var html = pug.renderFile(options.jadeTemplate , {
files : contents
});
tidy(html, {
indent: true
}, function (err, result) {
if (err) {
globalGrunt.fail.fatal(err);
}
fs.writeFile(options.output, result, function (err) {
if (err) {
globalGrunt.fail.fatal(err);
}
done();
});
});
});
}
function readFile(filename) {
var promise = Promise.pending();
fs.readFile(filename, function (err, data) {
if (err) {
promise.reject(err);
} else if (data) {
var doc = new DOMParser().parseFromString(data.toString(), "text/html");
var params = parseDocument(doc);
promise.resolve(new IndexedFile(filename, params));
} else {
promise.reject("No Data");
}
});
return promise.promise;
}
function parseDocument(doc) {
var params = {
tags : {},
attributes : {}
};
options.parseHtmlTags.forEach(function (tag) {
var tags = doc.getElementsByTagName(tag);
if (tags.length > 0) {
params.tags[tag] = tags[0].firstChild.data;
}
});
options.parseAttributes.forEach(function (attrName) {
var attr = xpath.select("//#" + attrName, doc);
if (attr.length > 0) {
params.attributes[attrName] = attr[0].nodeValue;
}
});
return params;
}
function IndexedFile(path, parameters) {
this.path = path;
this.parameters = parameters;
}
Template file ( in root of project ) /index.jade:
doctype html
html(lang="en")
head
title="Stackoverflow Question 40011711"
body
table
- files.forEach(function (item) {
tr
td
a(href=item.path)=item.parameters.tags["title"]
td=item.parameters.attributes["data-status"]
td=item.parameters.attributes["data-details"]
- })

Categories

Resources