Copy link to clipboard
Copied
Hello,
I'm converting my Flash application to HTML5 Canvas in Adobe Animate. The old Flash version had a List Component. This had a scrollbar, selectable items, data provider, etc. In that, I read an XML file and populated the List with the data.
The new HTML5 Canvas List Component is only a numbered or bulleted list -- it is nothing like the "listbox"-style Component from Flash. There is no scrollbar, and you can't select any items.
Can anyone please answer:
1) Should I be doing something different in Adobe Animate/HTML5 Canvas to achive the same style of scrollable/selectable List Component?
2) If not, can you please point me in the right direction of how I can bring in that type of object?
Thank you for any help.
Copy link to clipboard
Copied
Sorry to be a pain, but if anyone has any guidance on this question, I'd greatly appreciate it. Thank you, as always.
Copy link to clipboard
Copied
Hi.
That List component seems to only wraps a regular ul and li elements.
If you want more features, you're gonna need to create a DOM element and populate it with your data.
Here is a suggestion using JSON because I'm not really a big fan of XML.
var root = this;
var dataURL = "https://jsonplaceholder.typicode.com/posts";
var listHTML = "";
var list, posts;
root.start = function()
{
root.stop();
root.request(dataURL, root.dataLoaded);
};
root.dataLoaded = function(xhttp)
{
var i, total;
posts = JSON.parse(xhttp.responseText);
listHTML += "<ul>";
for (i = 0, total = posts.length; i < total; i++)
listHTML += "<li> Title: " + posts[i].title + " <br>Body: " + posts[i].body + "</li>";
listHTML += "</ul>";
list = root.createElement(
"div",
{ id: "test-list" },
{ position: "absolute", left: 0, top: 0, height: "400px", overflow: "auto" },
{ innerHTML: listHTML }
);
};
root.createElement = function(type, attributes, style, props)
{
var element = document.createElement(type);
var parentNode = props && props.parentNode ? props.parentNode : canvas.parentNode;
var key;
parentNode.appendChild(element);
if (attributes)
{
for (key in attributes)
element[key] = attributes[key];
}
if (style)
{
for (key in style)
element.style[key] = style[key];
}
if (props && props.innerHTML)
element.innerHTML = props.innerHTML;
return element;
};
root.request = function(url, callBack)
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
callBack(xhttp);
};
xhttp.open("GET", url, true);
xhttp.send();
};
root.start();
But if you really need to work with XML, what I like to do is to use a third party library to convert from XML to JSON or you can just search for learning materials on websites like W3 Schools.
Regards,
JC
Copy link to clipboard
Copied
Hi JC,
This is awesome, and thank you! I modified the code, and I have another question:
var root = this;
var dataURL = "https://jsonplaceholder.typicode.com/posts";
var listHTML = "";
var list, posts;
root.start = function() {
root.stop();
root.request(dataURL, root.dataLoaded);
}
root.dataLoaded = function(xhttp) {
var i, total;
posts = JSON.parse(xhttp.responseText);
listHTML += "<select id='test-list' size='10'>";
for (i = 0, total = posts.length; i < total; i++)
listHTML += "<option value='" + posts[i].title.substring(0, 20) + "'>" + posts[i].body.substring(0, 20) + "</option>";
listHTML += "</select>";
list = root.createElement(
"div",
{ id: "parent-div-1" },
{ position: "absolute", left: "50px", top: "80px", height: "400px", width: "400px", overflow: "auto" },
{ innerHTML: listHTML }
)
}
root.createElement = function(type, attributes, style, props) {
var element = document.createElement(type);
var parentNode = props && props.parentNode ? props.parentNode : canvas.parentNode;
var key;
parentNode.appendChild(element);
if (attributes) {
for (key in attributes)
element[key] = attributes[key];
}
if (style) {
for (key in style)
element.style[key] = style[key];
}
if (props && props.innerHTML)
element.innerHTML = props.innerHTML;
return element;
};
root.request = function(url, callBack) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
callBack(xhttp);
}
xhttp.open("GET", url, true);
xhttp.send();
}
root.start();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// THE LINE BELOW DOESN'T WORK: RESULTS IN ERROR: "Uncaught TypeError: Cannot set property 'onchange' of null"
//document.getElementById("test-list").onchange = function() { testButtonFunction() };
this.testButton.addEventListener("click", testButtonFunction.bind(this));
function testButtonFunction() {
console.log ( "value = " + document.getElementById("test-list").value );
console.log ( "selectedIndex = " + document.getElementById("test-list").selectedIndex );
}
Copy link to clipboard
Copied
Hi again.
1 - I'm really not sure about the actual event you want to handle. Do you want to get the values from the select element by using a Canvas/CreateJS/Animate Button or by using the select DOM element? An object created in Animate CC cannot be mixed with DOM elements because Animate CC objects created with the IDE design/drawing tools live inside of a canvas element while a select is just another DOM element like the canvas.
But if what you want is just to get the values from the select element alone:
var root = this;
var dataURL = "https://jsonplaceholder.typicode.com/posts";
var listHTML = "";
var list, posts;
root.start = function ()
{
root.stop();
root.request(dataURL, root.dataLoaded);
};
root.dataLoaded = function (xhttp)
{
var i, total;
posts = JSON.parse(xhttp.responseText);
listHTML += "<select id='test-list' size='10'>";
for (i = 0, total = posts.length; i < total; i++)
listHTML += "<option value='" + posts[i].title.substring(0, 5) + "' style='border-bottom: 1px solid black; width: 200px;'>" + posts[i].body.substring(0, 5) + "</option>";
listHTML += "</select>";
list = root.createElement(
"div",
{
id: "parent-div-1"
},
{
position: "absolute",
left: "50px",
top: "80px",
height: "400px",
overflow: "auto"
},
{
innerHTML: listHTML
}
);
document.getElementById("test-list").addEventListener("change", root.listClickHandler);
};
root.listClickHandler = function(e)
{
console.log("selectedIndex = " + e.currentTarget.selectedIndex);
console.log("value = " + e.target.value);
console.log("text = " + e.currentTarget.options[e.currentTarget.selectedIndex].text);
console.log("");
}
root.createElement = function (type, attributes, style, props)
{
var element = document.createElement(type);
var parentNode = props && props.parentNode ? props.parentNode : canvas.parentNode;
var key;
parentNode.appendChild(element);
if (attributes)
{
for (key in attributes)
element[key] = attributes[key];
}
if (style)
{
for (key in style)
element.style[key] = style[key];
}
if (props && props.innerHTML)
element.innerHTML = props.innerHTML;
return element;
};
root.request = function (url, callBack)
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function ()
{
if (this.readyState == 4 && this.status == 200)
callBack(xhttp);
}
xhttp.open("GET", url, true);
xhttp.send();
};
root.start();
2 - This is called a conditional (ternary) operator. There are three operands:
condition ? if true : if false
To give you a simpler example:
var nextScreenName = player.lives > 0 ? "continue" : "gameOver".
This is the same as:
if (player.lives > 0)
{
nextScreen = "continue";
}
else
{
nextScreen = "gameOver";
}
It's just a way of writing a simple conditional with less lines of code.
Copy link to clipboard
Copied
Hi JC,
Thanks -- again, that answers my question.
Thank you!!! - Steve