Custom HTML element attribute not showing - Web-Components - javascript

I'm exploring web-components custom HTML elements, and I am running into a problem adding custom attributes to my custom elements: any value I set in the markup is never honored.
For a simple element like this, which should show the text supplied in the "flagtext" attribute, it does always show the default value.
<test-flag flagtext="my text"></test-flag>
Full JSBin sample is here.
The JSBin uses the Polymer library (as this is the only thing I can pull in there). I am using webcomponents.js generally, same result. Both in Chrome 49 and in Firefox 45 gives same result. There is no error showing in the console or debugger.
Every sample I find on the web has similar code but I tried various versions and it always refuses to update. I even copied a few samples into JSBin and they do not work either.
What could be wrong? I understand it is experimental technology but the consistency with which this isn't working is still surprising. Has this standard been abandoned? (I see that the latest April 2016 W3C draft of custom elements has entirely changed its approach.)
When I define "attributeChangedCallback" function, it does not fire.
I can easily modify the property via Javascript, this is not a problem.
But why can I not specify the property in markup, as I am supposed to?
Edit - full code
Note that you'll need to put these into separate files for the HTML import, and that you need the "webcomponents-lite.js" library.
Main HTML file
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
test-flag
{
border: 1px solid blue;
}
</style>
</head>
<body>
<script src="lib/webcomponents-lite.min.js"></script>
<link rel="import" href="test-flag.html">
Here is the custom test-flag component:
<p>
<test-flag flagtext="my text"></test-flag>
</body>
</html>
File: test-flag.html
<template>
<style>
</style>
Content:
<div id="testflagID">
</div>
</template>
<script>
(function() {
var _currentScript = (document._currentScript || document.currentScript);
var importDoc = _currentScript.ownerDocument;
var customPrototype = Object.create(HTMLElement.prototype);
Object.defineProperty(customPrototype, 'flagtext', {value: '(default)', writable: true});
document.registerElement('test-flag', {prototype: customPrototype});
customPrototype.createdCallback = function()
{
var template = importDoc.querySelector('template');
var clone = document.importNode(template.content, true);
var idx = clone.querySelector("#testflagID");
idx.textContent = this.flagtext;
var root = this;
var createdElement = root.appendChild(clone);
};
})();
</script>

There are 2 concepts that are not automatically linked together.
In the HTML code:
<test-flag flagtext="my text"></test-flag>
...term flagtext is an HTML attribute (not a property).
In the JavaScript code:
Object.defineProperty(customPrototype, 'flagtext', {value: '(default)', writable: true})
...term flagtext is a JavaScript property (not an attribute).
For standard elements, the browser automatically binds the property value to the attribute value (and vice versa). For Custom Elements, too (with standard attributes). But if you want to add a custom attribute, you'll have to bind it manually.
For example, in the createdCallback() method, add:
this.flagtext = this.getAttribute( 'flagtext' ) || '(default)'
Live sample:
document.registerElement( 'test-flag' , {
prototype: Object.create( HTMLElement.prototype, {
flagtext: {
value: '(default)',
writable: true
},
createdCallback: {
value: function()
{
this.flagtext = this.getAttribute( 'flagtext' ) || this.flagtext
this.innerHTML = 'flagtext=' + this.flagtext
}
},
} )
} )
<test-flag flagtext='new content'>Hello</test-flag>
NB: the attributeChangedCallback() method is fired only when an attribute is changed after element creation (which is not the case here).

Related

What is the best way to store multiple items in local storage?

There is no problem with one element. I need to make at least 10 buttons, and so that they do not depend on each other. That is, some buttons were with hidden text, and others with open text.
What is the best way to do this so that the code does not look like a freak?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<style>
#myid { display: none; }
</style>
<button onclick="onclickmyid()">Open</button><br><br><span id="myid">Hidden text</span>
<script>
var myid = document.getElementById('myid');
function onclickmyid() {
myid.style.display = (myid.style.display == 'block') ? '' : 'block';
localStorage.setItem('conceal', myid.style.display);
}
if(localStorage.getItem('conceal') == 'block') {
document.getElementById('myid').style.display = 'block';
}
</script>
</body>
</html>
Put all the persistent data you need into an array or an object, then serialize that (single) array or object into a single Local Storage key. Something along the lines of
const config = localStorage.config
? JSON.parse(localStorage.config)
: defaultConfig; // define defaultConfig earlier
cons saveConfig = () => localStorage.config = JSON.stringify(config);
// then, to save to the config when a change is made:
function onclickmyid() {
const newShow = myid.style.display === '';
config.myid = newShow;
updateUI();
saveConfig();
}
// and retrieve values on pageload:
const updateUI = () => {
myid.style.display = config.myid ? 'block' : '';
// etc for other elements
};
updateUI();
I'd also highly, highly recommend avoiding inline handlers, they're pretty universally considered to be quite terrible practice nowadays - attach listeners properly using JavaScript's addEventListener instead whenever possible.
For additional buttons, just add more properties to the config object, and toggle and access them in the click handlers.

Uncaught TypeError: translate is not a function

Keep getting an uncaught type error when I click the button that is supposed to trigger the translate function. Unsure what is causing this. I've tried changing the element from a button element to an input element with type button. Whatever I do I still get this error. Anyone able to help?
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Language" content="en-us">
<title>Example Web Editor</title>
<link rel="stylesheet" type="text/css" href="xtext/2.24.0/xtext-ace.css"/>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="webjars/requirejs/2.3.6/require.min.js"></script>
<script type="text/javascript">
var baseUrl = window.location.pathname;
var fileIndex = baseUrl.indexOf("index.html");
if (fileIndex > 0)
baseUrl = baseUrl.slice(0, fileIndex);
require.config({
baseUrl: baseUrl,
paths: {
"jquery": "webjars/jquery/3.5.1/jquery.min",
"ace/ext/language_tools": "webjars/ace/1.3.3/src/ext-language_tools",
"xtext/xtext-ace": "xtext/2.24.0/xtext-ace"
}
});
require(["webjars/ace/1.3.3/src/ace"], function() {
require(["xtext/xtext-ace"], function(xtext) {
xtext.createEditor({
baseUrl: baseUrl,
syntaxDefinition: "xtext-resources/generated/mode-logic"
});
});
});
</script>
<script>
function translate() {
console.log("function being triggered.");
let req = new XMLHttpRequest();
console.log("request created");
req.open( "POST", "localhost:8003/translate", false);
req.send(ace.edit('xtext-editor').getSession().getValue());
return req.responseText;
}
</script>
</head>
<div class="container">
<div class="header">
<h1>Example LogicLang Web Editor</h1>
</div>
<div class="content">
<div id="xtext-editor" data-editor-xtext-lang="logic"></div>
</div>
</div>
<form onsubmit = "return false">
<input type="button" onclick="translate()"> Compile </input>
<button class="save-button" onclick="console.log(ace.edit('xtext-editor').getSession().getValue());"> Test </button>
</form>
</body>
</html>
You need to use a different name for that function.
translate() is already an existing method used for 2D Canvas drawings.
The translate() is a method of a 2D drawing context. The translate(x,y) method moves the canvas and its origin x units horizontally and y units vertically. source.
Solution
Avoid this by defining a JS event handler property with:
document.querySelector("input[type=button]").addEventListener("click", translate)
// or
jQuery('input[type="button"]').on("click", translate)
which will create a handler with a more predictable (probably global) scope. For best practice, also use event delegation.
Explanation
The lexical scope of a handler function defined as an html element attribute already has a translate property.
JS functions are bundled together with references to their surrounding state (the lexical environment). When you set an HTML attribute as a string of js code, you are implicitly defining a function within the scope of the HTML element.
Your <input> element will inherit properties from these interfaces: HTMLElement -> HTMLInputElement -> Node -> Event Target. We can check to see if any of them have a translate property:
console.log(Object.getOwnPropertyNames(EventTarget.prototype).includes("translate"))
// > false
console.log(Object.getOwnPropertyNames(Node.prototype).includes("translate"))
// > false
console.log(Object.getOwnPropertyNames(HTMLInputElement.prototype).includes("translate"))
// > false
console.log(Object.getOwnPropertyNames(HTMLElement.prototype).includes("translate"))
// > true
The HTMLElement interface includes a "translate" property, which is a Boolean value. The translate reference in your handler therefore gets resolved to that value, and you will get a TypeError telling you "translate is not a function" because you are trying to call a Boolean
More Explanation
If I run this in the Chrome DevTools console:
const div = document.createElement("div");
function translate() {
console.log(".")
};
div.setAttribute("onclick", "translate()");
getEventListeners(div).click[0]
I can inspect the listeners, and see the scope chain:
listener: ƒ onclick(event)
arguments: null
caller: null
length: 1
name: "onclick"
prototype: { constructor: ƒ }
__proto__: ƒ()
[[FunctionLocation]]:
[[Scopes]]: Scopes[4]
0: With Block { align: "", title: "", lang: "", translate: true, dir: "", ... }
1: With Block { location: Location, jQuery321081306834416800691: {…}, implementation: DOMImplementation, URL: "https://....com/", … }
2: Script { div: div }
3: Global { window: Window, self: Window, document: document, name: "", location: Location, … }
once: false
passive: false
type: "click"
useCapture: false
The first object in that scope chain list is the <div> that triggers the handler. Generally, the scope chains of functions defined in html element attributes way will be something like: (1) the call object -> (2) the HTML element -> (3) . . . stuff in between . . . -> (4) Document -> (5) Global.
When a variable is being resolved or looked up, js will go up the scope chain until it finds the definition. If you declare an un-nested function in your script the usual way, it will be a property of the global object. If anything between the global scope and the HTML element where the handler is defined has a property with the same name as your function, references to your function will be resolved to that property instead of your function.
Screenshot of DevTools comparing scopes of handlers defined as HTML attributes vs. with addEventListener()

Where to store temporary live <style> styling

I'm trying to create a website builder (drag and drop page builder) and was wondering where to store the styles when someone changes the styles of an element. For example, in WordPress you can type in your own custom CSS in Customizer (image example: https://i.imgur.com/qaUiVl6.png)
In other page builders like Wix or Google Chrome Inspect Element, you can click button to enable or disable styles.
While making current/live CSS edits to the page, where and how are these styles saved? (I'm not talking about a database as the code has not been saved yet. I'm talking about while making changes onsite changes, where do these "temporary/live" CSS styles get saved?)
You can use the CSSStyleSheet APIs to generate a stylesheet in memory then use insert and delete methods to add or remove rules from the stylesheet at will. When the user is done modifying you could then pass the generated stylesheet back server side to save perm.
Ref docs can be found here:
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet#Methods
Compatability is IE9+ and all other modern browsers so it has good coverage.
Quick and dirty example below.
var style = (function() {
// Create the <style> tag
var style = document.createElement("style");
// Add the <style> element to the page
document.head.appendChild(style);
return style;
})();
function AddRule(){
//append rule from textbox to ss here
style.sheet.insertRule(document.getElementById("cssIn").value, 0);
document.getElementById("appliedRules").innerHTML = '';
var rules = style.sheet.cssRules;
for (var r in rules) {
if(rules[r].cssText){
document.getElementById("appliedRules").innerHTML += '<br>' + rules[r].cssText;
}
}
}
//enable this to see your special prize in the console
//console.log(style.sheet);
<div class="test"> here we go</div>
Add Rule: <input type="text" id="cssIn" value=".test {color:blue}">
<button type="button" onClick="AddRule();">Add</button>
<div id="appliedRules"></div>
Here is a simple proof-of-concept that demonstrates how this can be done using pure javascript. Just click the save button to see the CSS in the textarea get applied to the page. The CSS is just stored as the input value of the textarea element. You can also make it more complex by using localStorage and an iframe or shadow dom so you only affect a "preview" pane. But this is just a demonstration.
function saveStyles() {
document.querySelector('#style-container').innerHTML = document.querySelector('#style-input').value;
}
#style-input {
width: 100%;
box-sizing: border-box;
display: block;
margin-bottom: 8px;
}
<style id="style-container"></style>
<textarea id="style-input" rows="5">body{background:red;}</textarea>
<button onclick="saveStyles()">Save</button>
Here's an alternative that puts the stylesheet into memory and loads it via a blob URL.
This behaves a bit more like a real stylesheet than inline styles do in some edge cases, which may be desirable in some cases. It can also work on a webpage that blocks inline styles via a Content Security Policy (provided blob URL's are allowed).
(function() {
var styles = document.getElementById('styles');
var save = document.getElementById('save');
var link = null;
function getLink() {
if (!link) {
link = document.createElement('link');
link.rel = 'stylesheet';
document.head.appendChild(link);
}
return link;
}
save.addEventListener('click', function() {
var link = getLink();
if (link.href) {
URL.revokeObjectURL(link.href);
}
link.href = URL.createObjectURL(new Blob([styles.value], {type: 'text/css'}));
});
})();
#styles {
display: block;
width: 95%;
}
<textarea id="styles" rows="5">body {
background: green;
}
</textarea>
<button id="save">Save</button>
The answers here focus on the methods for building a stylesheet and adding css rules using common methods browsers provide as part of the DOM api. These are the underlying function calls that any UI framework on the web will use.
But when you ask, "Where is this stored?". In a sense, you are asking how is the "state" managed. If you look at original post jQuery/web app building frameworks, like Backbone.js -- its motto was, "Get your model out of the DOM". So generally the "elements" of the ui-building tools will themselves be represented as component/models.
If you look at view-centric frameworks, like React or Vue, more complex web apps will use a framework like Redux to handle "state", which is stored in single object store. This represents the current options of all the components on the page.
So ultimately, a non-toy WYSIWYG web editor will likely treat each "element" as a component that renders its styles based on an inputted state. 
This coupled with a controlled and predictable way to change state, allows for the managing of complex UI. For instance, the click method would trigger an action that acts like the name of an event handler, triggering the functions (in redux world, reducers), which ultimately changes the state, in our example, color of the element.
The low-level calls to the DOM that facilitate this in a complex web-app/web-editor would be abstracted away.
Based on the discussion, I can suggest to use separate styles for each element id. Here is a sketch.
<script>
function setStyle(id, style_text)
{
var style_id = "style_" + id;
var style_forId = "#" + id + " " + style_text;
var styleDom = document.getElementById(style_id);
if(!styleDom)
{
styleDom = document.createElement('style');
styleDom.type = 'text/css';
styleDom.id = style_id;
styleDom.innerHTML = style_forId;
document.getElementsByTagName("head")[0].appendChild(styleDom);
}
else
{
styleDom.innerHTML = style_forId;
}
}
</script>
<button id="myButton1" type="button" >My Button 1</button>
<button id="myButton2" type="button" >My Button 2</button>
<br>
<button onclick="setStyle('myButton1', '{color:red}'); "> Set Red color for myButton1 </button>
<br>
<button onclick="setStyle('myButton2', '{color:red}'); "> Set Red color for myButton2 </button>
<br>
<button onclick="setStyle('myButton1', '{color:green}'); "> Set Green color for myButton1 </button>
<br>
<button onclick="setStyle('myButton2', '{color:green}'); "> Set Green color for myButton2 </button>
<br>
Great Answers already just putting a different viewpoint out there.
Simple Version
Using CSSStyleSheet
const style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(`
header {
background: 'black'
}
`, 0);
Real World
I would take this simple idea and control it through a data structure like this.
// A JS Object to control and modify CSS styles on.
const css = {
header: {
background: 'black',
border: '2px green solid',
'font-size': '12px'
}
}
// Converts JS Object to CSS Text (This is not battle tested)
function objToCss(style) {
return Object.entries(style).reduce((styleString, [propName, propValue]) => {
propName = propName.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
if (typeof propValue === 'object') {
return `${styleString}${propName}{${objToCss(propValue)}}`;
} else {
return `${styleString}${propName}:${propValue};`;
}
}, '')
}
// Setup
const style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(objToCss(css), 0);
// Updates
css.header.border = '1px blue solid';
style.sheet.replace(objToCss(css), 0);

Angular 2.0 and Mathjax not working well

I pieced together a semi working edition of mathjax with angular 2.0, but it is breaking in a manner I can not quite grasp. I have added a plunkr below to clearly demonstrate the situation.
In my code (not the plunkr) this is my relevant html:
<textarea
#editorArea
ngDefaultControl
spellcheck="false"
class="editor"
[(ngModel)]='assignment.content.text'
(keyup)="updateResult()"
[ngStyle]="{'height' : formatDimension(editorDimensions.height), 'padding' : formatDimension(editorDimensions.padding)}
"></textarea>
<div class="result" #result>{{ editorArea.value }}</div>
and this is the relevant update function triggered from the HTML:
#ViewChild('result') result : ElementRef;
updateResult() {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, this.result.nativeElement]);
}
Finally this is my mathJax configuration:
<script type="text/x-mathjax-config">
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>
http://plnkr.co/edit/lEJZZaxKUYxFGdLtWW7Z?p=preview
It seems like the main question here is how to repeatedly render the contents of the <textarea> into a separate area of the page using MathJax. This is covered in a simple case in the Modifying Math on the Page documentation.
Basically you have two options:
Option 1
Keep ahold of the rendered math element and then use the Text function to re-render with a new math string (Note: this requires that the whole textarea is one big math string, not normal text with math strings interspersed) Plunker:
HTML :
<div id="result">$ $ <!-- empty mathstring as placeholder -->
hello-mathjax.ts (portion):
ngOnInit() {
var self = this;
// callback function saves the rendered element, so it can
// be re-rendered on update with the "Text" function.
MathJax.Hub.Queue(
["Typeset",MathJax.Hub,"result"],
function () {self.resultElement = MathJax.Hub.getAllJax("result")[0];
self.updateResult();
}
);
}
updateResult () {
// re-render the same element with the value from the textarea
MathJax.Hub.Queue(["Text",this.resultElement,this.inputValue]);
}
updateResult () {
MathJax.Hub.Queue(["Text",this.resultElement,this.inputValue]);
}
Option 2
Wipe out the renderd div every time and completely re-render the contents of the textarea. (This is the way to go if the textarea will contain a mix of mathstrings and regular text) Plunker:
HTML:
<div id="result"></div> <!-- No placeholder math string needed -->
hello-mathjax.ts (portion):
ngOnInit() {
var self = this;
MathJax.Hub.Queue(
["Typeset",MathJax.Hub,"result"],
function () {
self.updateResult();
}
);
}
updateResult () {
var resultDiv = document.getElementById("result");
// Replace the rendered content entirely
// with the bare text from the textarea.
resultDiv.innerHTML = this.inputValue;
// Rerender the entire resultDiv
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"result"]);
}
This plunker demonstrates rendering a <textarea> that contains a mix of non-math and math statements (e.g. test test $\frac 12$)
This Plunker demonstrates rendering a <textarea> that should be interpreted entirely as math statements (e.g. \frac {11}2)

How to use RPG.JS

I'm trying to work with this library (RPG.js) because it looks very powerfull, I looked at the official tutorial but i don't understand a lot of things, State 4 : "Initialize the canvas in your JS file :", whitch one ?
Is any one already used this library or know an other powerfull ?
Thanks for all.
Well, actually it was not so simple; I struggled I bit until I got a minimal functional game. What I did was not the "optimal" approach, but at least worked for me (I was using Mozilla Firefox in a Windows 7 OS). If someone knows how to improve what I did, I would be happy to know (since I'm a newbie in this library too), but since I was not able to find a good a simple starter tutorial in the net, I want to share what I did, in the hope I can help someone.
Before anything, create a HTML file, and call the libs inside the <head> tag:
<script src="canvasengine-X.Y.Z.all.min.js"></script>
<script src="rpgjs-X.Y.Z.min.js"></script>
And the canvas inside the <body> tag:
<canvas id="canvas_id" width="640" height="480"></canvas>
There's a 'sample' folder inside the github project (see https://github.com/RSamaium/RPG-JS), and inside this folder there is a functional game, and you can open it in the browser by the file quick.html. The idea is that if the sample game can work, then you can make your game work too, so I started trying to use the same graphics, data etc. of the sample.
First, you need to create in the root of your project the following folders and subfolders:
core
core\scene
Data
Data\Maps
Graphics
To have a minimal functional game, you need 1) a map to walk with your character, and 2) a character to control. So, you need to have graphics for some tiles to build your map and the walking model for your character. Create the subfolders below:
Graphics\Characters
Graphics\Tilesets
Graphics\Windowskins
And then copy the following files from the corresponding sample subfolder to these folders you created:
Graphics\Characters\event1.png
Graphics\Tilesets\tileset.png
Graphics\Windowskins\window.png #this file will be necessary for some of the js files below, even if not used; to remove this necessity, you'll need to edit these files - not what we want to do in the start.
In the 'core/scene' folder, you'll have some js files to load scenes (like the scene of your walking in the map, the gameover scene). I needed to copy all the js files inside the corresponding folder in the 'sample' project to the 'core/scene' folder of your game. This folder is not inside the 'sample' folder, but in the root of the github project. I only got my game working when I added all the 7 js files (without some work inside the codes you can remove the scenes you don't want, but since what we want is just to be able to run a simple game, let's copy them for now):
Scene_Gameover.js
Scene_Generated.js
Scene_Load.js
Scene_Map.js
Scene_Menu.js
Scene_Title.js
Scene_Window.js
Now, I added the following code inside a <script> tag on the html. This is more or less the same that was in the documentation. These codes will create an "actor" (a character), a "map", and the tiles you'll use in the map
For more details on maps or tiles, you should read the documentation (the same you linked in your question).
RPGJS.Materials = {
"characters": {
"1": "event1.png"
},
"tilesets": {
"1": "tileset.png"
}
};
RPGJS.Database = {
"actors": {
"1": {
"graphic": "1"
}
},
"tilesets": {
"1": {
"graphic": "1"
}
},
"map_infos": {
"1": {
"tileset_id": "1"
}
}
};
RPGJS.defines({
canvas: "canvas_id",
autoload: false
}).ready(function() {
RPGJS.Player.init({
actor: 1,
start: {x: 10, y: 10, id: 1} // Here, map id doesn't exist
});
RPGJS.Scene.map();
Lastly, create the json file setting every tile of your map. I just copied the MAP-1.json file from the 'sample' folder to inside the Data\Maps folder.
Then you'll be able to walk with your character in an empty map! Open the html file in your browser and try it!
Printscreen from the game running in a browser
Of course to have a real game you'll need to change a lot of this (as creating a database.json file and a materials.json file where you'll put most of the code you put in the <script> tag), but with the basics I hope you can work from that!
The tutorial is very clear
3. Add this code in your page :
<!DOCTYPE html>
<script src="canvasengine-X.Y.Z.all.min.js"></script>
<script src="rpgjs-X.Y.Z.min.js"></script>
<canvas id="canvas_id" width="640" height="480"></canvas>
That's "the canvas" ^
Brian Hellekin post a great tutorial. If you want see all the power of this library you must modify your html file in this way:
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src="http://canvasengine.net/cdn/dev/canvasengine-latest.all.min.js"></script>
<script src="http://rpgjs.com/cdn/rpgjs-2.0.0.min.js"></script>
<script src="plugins/gamepad.js"></script>
<script src="plugins/virtualjoystick.js"></script>
<script src="plugins/soundmanager2-jsmin.js"></script>
<script>
var Data = null;
if (Data) {
Data.database._scenes = Data.menus;
Data.database.system = Data.settings;
}
RPGJS.defines({
canvas: "canvas",
plugins: ["/rpgjs/plugins/Hub", "/rpgjs/plugins/Arpg", "/rpgjs/plugins/MenuGenerated"],
scene_path: "/rpgjs/",
soundmanager: {
url: "/rpgjs/swf/",
},
autoload: Data == null,
ignoreLoadError: true
}).ready(function(rpg) {
var material_json = {};
var m, type;
if (Data) {
for (var i in Data.materials) {
m = Data.materials[i];
type = m['type'] + "s";
if (!material_json[type]) {
material_json[type] = {};
}
material_json[type][m['material_id']] = RPGJS_Canvas.Materials.getFilename(m['path'], true);
}
var m, e;
var map_info = Data.maps, info;
for (var id in Data.data_maps) {
m = Data.data_maps[id];
this.setMap(id, m.map.map);
info = map_info[id];
info.tileset_id = info.tileset;
info.autotiles_id = info.autotiles;
info.events = [];
info.dynamic_event = [];
for (var i=0 ; i < m.events.length ; i++) {
e = m.events[i];
if (e.data_event.type == "event" ) {
var format =
[
{
"id" : e.event_id,
"x" : e.position_x,
"y" : e.position_y,
"name" : 'EV-' + e.event_id
},
e.data_event.data.pages
];
this.setEvent(id, 'EV-' + e.event_id, format);
info.events.push('EV-' + e.event_id);
}
else {
var name, _id;
for(var key in e.data_event.data) {
_id = e.data_event.data[key];
name = key;
break;
}
info.dynamic_event.push({
"x" : e.position_x,
"y" : e.position_y,
"name" : name,
"id" : _id
});
}
}
}
Data.database.map_infos = map_info;
global.materials = material_json;
global.data = Data.database;
global.game_player.init();
}
var scene = this.scene.call("Scene_Title", {
overlay: true
});
scene.zIndex(0);
});
</script>
<style>
body {
padding: 0;
margin: 0;
overflow: hidden;
background: black;
}
canvas {
-webkit-user-select : none;
-moz-user-select : none;
overflow : hidden;
}
#font-face{
font-family : "RPG";
src : url("Graphics/Fonts/Philosopher-Regular.ttf");
}
#font-face{
font-family : "Megadeth";
src : url("Graphics/Fonts/Elementary_Gothic_Bookhand.ttf");
}
</style>
<div id="game">
<canvas id="canvas" width="640" height="480"></canvas>
</div>
Note:
/rpgjs/ is the folder where i put my project in my local server. For play the game i go to http://localhost/rpgjs/
For work you need to modify the JS file in /plugins/ directory.
/Hub/Sprite_Hub.js
use this path:
array.push(RPGJS.Path.getFile("pictures", "../Pictures/hub.png", "hub"));
array.push(RPGJS.Path.getFile("pictures", "../Pictures/hp_meter.png", "hp_meter"));
array.push(RPGJS.Path.getFile("pictures", "../Pictures/hp_number.png", "hp_number"));
array.push(RPGJS.Path.getFile("pictures", "../Pictures/Hero_Face.png", "hero_face"));
array.push(RPGJS.Path.getFile("pictures", "../Pictures/button_A.png", "button_a"));
array.push(RPGJS.Path.getFile("pictures", "../Pictures/button_B.png", "button_b"));
is very useful debug in the first time with developer tool of google chrome. When you see 404 error on a img resourse just go to your project and search the file name. Find what js script load it and fix path.
And not...the tutorial inside library project is not clear and isn't complete...they just want sell his rpgeditor and js library is put only for promotion purpose i think.
you can see here: http://rpgworld.altervista.org/rpgjs/ my final working project. Is just a try... but you can see the power of this library.
this demo load:
1- a welcome page with new and load came
2- a custom map with one event
3- a working event: a chest that if you open you will find 30 gold
4- a player manu: just click ESC button on keyboard
i don't know how use arpg plugin for a realtime combat event but i working on for understand of to use it.

Categories