• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

HTML5 Canvas, List Component Qustion

Contributor ,
Apr 09, 2020 Apr 09, 2020

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.

Views

762

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Apr 10, 2020 Apr 10, 2020

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2020 Apr 11, 2020

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Apr 11, 2020 Apr 11, 2020

Copy link to clipboard

Copied

Hi JC,

This is awesome, and thank you!  I modified the code, and I have another question:

  • I converted your example for a <SELECT> list, which is what I'm trying to achieve.
  • This requires a MC on the stage, named testButton .
  • testButton does a console.log showing the clicked result.
  1. Could you please help me with onchange event?  I'm trying to follow w3schools example.  I have worked for hours, and I cannot get anything to trigger when an item in the <SELECT> list is changed.  See my commented line at the end.  Can you indicate what I'm doing wrong on that line?
  2. Can you please explain this line? I don't understand the syntax or what it's doing: var parentNode = props && props.parentNode ? props.parentNode : canvas.parentNode;
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 );
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2020 Apr 11, 2020

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Apr 11, 2020 Apr 11, 2020

Copy link to clipboard

Copied

LATEST

Hi JC,

Thanks -- again, that answers my question.

  • For 1: I wanted to get the values immediately from the <SELECT> element by using the <SELECT> DOM element -- in other words, when the <SELECT> element is changed, it should "trigger" an event.  Basically, I want to show another <SELECT> list based upon clicking this first <SELECT> list.  Apparently, the document.getElementById("test-list").addEventListener("change", root.listClickHandler); line within the root.dataLoaded function is where it needed to be (I was getting that wrong, previously).
  • For 2: Ahhhh... I just learned something new!  I had never seen that.

Thank you!!!  - Steve

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines