Highlighted

HTML5 Canvas, List Component Qustion

Participant ,
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

369

Likes

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

HTML5 Canvas, List Component Qustion

Participant ,
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

370

Likes

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
Apr 09, 2020 0
Participant ,
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.

Likes

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
Reply
Loading...
Apr 10, 2020 0
Adobe Community Professional ,
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

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

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
Reply
Loading...
Apr 11, 2020 0
Participant ,
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 );
}

 

Likes

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
Reply
Loading...
Apr 11, 2020 0
Adobe Community Professional ,
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.

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

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
Reply
Loading...
Apr 11, 2020 0
Participant ,
Apr 11, 2020

Copy link to clipboard

Copied

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

Likes

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
Reply
Loading...
Apr 11, 2020 0