Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Thursday, 15 December 2016

How to: Input text box in Animate CC canvas, version 2

This method will allow you to put input text boxes within a particular location on your canvas, using co-ordinates etc that make sense, that will change if the page is resized.

By the end of it, you should be able to create an input textbox form within your canvas, just by calling a function like this:

createTextBox(250, 76.05, 315.1, 16);//width, xpos, ypos, fontsize

1) Put the canvas in a div, so that you can easily add input boxes just after the canvas.

 <div id='canvasHolder'>
<canvas id="canvas" width="800" height="450" style="display: block; background-color:rgba(0, 0, 0, 1.00)"></canvas>
</div>

2) My canvas is set to resize with the window, under Publish Settings, I chose: Center stage, Both; Make responsive, Both; Scale to fill visible area, Fit in view. So this code works for those settings, but seeing this might help if you are using something different.

So the canvas html contains a function that automatically resizes the canvas, and you will need some of those variables to figure out how big your textbox needs to be. So you need to give them a global scope. In the javascript,

var pRatio, xRatio, yRatio, sRatio;

Also, create an array that will hold all your text boxes so that you can resize them later.

var txtBoxes = new Array();

You also need to go into the resizing function and remove the 'var' so that they are global variables. In the resizeCanvas function, change:

var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;

to

pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;

3) Now here is the function that will create the input text box:

function createTextBox(wid, xpos, ypos, fsize) {
var node = document.createElement("INPUT");
node.type = 'text';
node.style = "position: fixed; font-family:'Gill Sans MT'; border:none; border-bottom-style:solid; border-bottom-width:1px";
txtBoxes.push({'ele':node,'wid':wid,'xpos':xpos,'ypos':ypos,'fsize':fsize});
sizeBox(txtBoxes[txtBoxes.length-1]);
document.getElementById('canvasHolder').appendChild(node);
}

The first line of this function creates an input 'node', the second specifies it as a text input, although this is the default, so not strictly necessary.

Setting the css position to fixed works for me, but some others might work too, this isn't my strong point. Setting the font and border was a personal choice.

It adds an object containing the node and all its sizing properties to the txtBoxes array, so that this info can be used when resizing later.

It calls the sizeBox function with the object - this will position the object appropriately.

Then it adds the node to the canvasHolder element (where the canvas is).

4) Here is the sizeBox function:

function sizeBox(obj) {
var node = obj['ele'];
node.style.width =  Math.round((canvas.width/pRatio)*(obj['wid']/lib.properties.width)) + "px";
node.style.fontSize = Math.round(sRatio*obj['fsize'])+"px";
if(xRatio < yRatio) {
node.style.left = Math.round((canvas.width/pRatio)*(obj['xpos']/lib.properties.width))+"px";
node.style.top = Math.round((0.5*(window.innerHeight-(canvas.height/pRatio)))+((canvas.height/pRatio)*(obj['ypos']/lib.properties.height)))+"px";
}else{
node.style.left = Math.round((0.5*(window.innerWidth - (canvas.width/pRatio))) + ((canvas.width/pRatio) * (obj['xpos']/lib.properties.width))) + "px";
node.style.top = Math.round((canvas.height/pRatio)*(obj['ypos']/lib.properties.height)) + "px";
}
}

The size properties of the canvas is complex and I don't fully understand how it works, but I just kept fiddling around with things until it sort of made sense. Basically, you can set the width relative to the canvas' actual size, same for the font.

Its similar for the x and y position, but one will need to be offset because the ratio of the width and the height may not be equal.

5) Finally, alter the resizeCanvas function so that the textboxes are automatically altered.

After this line:

lastW = iw; lastH = ih; lastS = sRatio;

Add this:

for(i=0; i sizeBox(txtBoxes[i]);
}

It goes through each of the txtBoxes and resizes them, as the window is being resized.


6) Now you can create them from your canvas, like so:

createTextBox(250, 76.05, 315.1, 16);//width, xpos, ypos, fontsize


Just a few notes about this method, the alignment is 100% flawless, I think because everything has to be rounded off to pixels, but it is pretty good.
Also, how to access the value inside? You can't assign them an id, and use document.getElementById, because the node is dynamically added. But you can access the txtBoxes array and get the value of the node.

Wednesday, 14 December 2016

How to: Input text box in Animate CC Canvas, version 1

Am getting more used to animate CC canvas, and was quite happy until I found that you couldn't do input text boxes, at least not directly. But I suppose the nice thing about these difficulties is the smug feeling of self-satisfaction you get when you overcome it (entirely undeserved, with all the online help I got), anyway!

The strategy is basically to make an invisible text box that holds on to text when you type and passes it to the text box on your canvas.

In terms of making the text box invisible, you can't use display: none, as textboxes can't get the focus if they are not displayed, or hidden.

If you use opacity:0, then you won't be able to see the textbox, but it will still take up space, and someone could click on it by accident, possibly leading to upredictable results.

So I'm opting to use opacity, set its width to 0, and setting it to be off of the screen as well!

1)
Here is the html for the textbox:

<input type='text' id='testInput' oninput="sendInput();" style="position:absolute; z-index:-1; opacity:0; width:0; top:-30px">

If this is the very first element in the body tag, then it should be above the visible window, ie offstage. If you have other elements around your canvas you may need to fiddle with this, but I doubt it as the textbox doesn't need to be in any particular div to work.


2)
In the script tag in the head, you need to create variables for your input textbox, and whatever the receiving textbox might be, something like:
<script>
var txtTarget, txtInput;

And in the init function called by the loading body tag:
<body onLoad="init()">

You need to assign the input textbox to the txtInput variable:

function init() {
     txtInput = document.getElementById('testInput');
}


3)
As for the sendInput function, that goes in the script section:

function sendInput() {
 txtTarget.text = txtInput.value;
}

This sends the content of the input text box to the text box in the canvas element.

4)
In the animate CC flash file, you need to create a dynamic text box (call it textReceiver), and a button behind it (called txtbtn), you could save time by making it look like an input textbox.

The code for this is:

this.tstbtn.on('click', focusText.bind(this));
function focusText(e) {
 //txtInput.value = this.testReceive.text = '';
 txtInput.focus();
 txtTarget = this.testReceive;
}

This function means that when someone clicks on the button, it is as though they have clicked on the input textbox. It also sets the html page to recognise the canvas's text box as the text receiver.


In theory, you could create multiple textboxes (though not on the same frame in animate CC), and put a button behind each one, so that when it is clicked, it registers its textbox as txtTarget. In that case, you need to use the line that is commented out, so that the text from one textbox doesn't get copied over to another.

The downsides to this method, which occurred to me as I was writing the post, are that the user doesn't get a cursor, they can't highlight the text, and they can't easily edit the content, since they can't click part way through the text.

So I may go back to the drawing board on this, to get the full input text box functionality.

Monday, 18 August 2014

How to randomly generate -1 or +1, in one line.

A hobby of mine is avoiding if statements, with mathematical formula that return the right number based on other conditions.

It is easy to generate a 0 or a 1 randomly, simply use Math.round(Math.random());

That will work in a number of languages, or something similar.

For a random -1 or +1, try this:

var randNum = -1 + (2*Math.round(Math.random));

If the random number generated by Math.random() is 0.5 or above, then the answer will be 1. If the random number generated is less than 0.5, the answer will be 1.

Enjoy!

Sunday, 8 April 2012

Javascript: Rewrite element content

How to change the content of an element...?

In the head tag:

<script type="text/javascript">
function giveWidth(e) {
 document.getElementById('wid').innerHTML = window.innerWidth;
}
</script>

In the body tag:

<p>Window width <a href="" onclick="giveWidth(event);return false">is</a> <span id="wid">500</span> pixels.<p>

The return false makes sure that the browser doesn't try to open a new window when you click on the link.

Friday, 6 August 2010

Line breaks

OK, so...

I am entering text in a flash text field, which gets sent to a mysql database. This later gets retrieved by php, and folded into a javascript function, so that another swf can use that data.

The problem is, if there are any line breaks in the initial text, then that ends up in the javascript function, and is seen as an error.

So to solve it, I will attempt to get the php file that takes the text out of the database, to convert that line break into something that the javascript function can stand, and that the swf can interpret.

Continuation -

Yeah, that worked. First I tried nl2br, which is supposed to put html linebreak tags where the line breaks are, although I din't see this effect. But this would have required me to make changes to my flash file.

So I used:

$lineBreaks = Array("\n","\r");
$iQuestion = ...get text from MySQL database
$oQuestion = str_replace($lineBreaks,'\u000d',$iQuestion);

$lineBreaks is an array of possible ways in which the line breaks may come down, I wasn't sure if this would differ depending on the user's operating system etc.

Wednesday, 23 June 2010

JavaScript CAN Call PHP Functions

So this is where I got to:

function gQ() {
var request = new XMLHttpRequest();
request.open("GET","getQus.php?val=What",false);
request.send();
val = request.responseText;
return val;
}

The thing is, this just gives me a query string, I can get that from PHP directly if I want one, and with less fuss.

Oh well... at least I know it can be done.

Can Javascript call PHP functions?

I am beginning to wonder...

Here's the thing, I want to get some info from a MySQL database into Flash, and if I do it straight via PHP, I am going to get these really long query strings, that just might be a bit unreliable, for example if they have any ampersands in them where they shouldn't be.

But Javascript outputs arrays and objects, and these are so much tidier. If I can get the PHP to send the info to Flash as Javascript, that will be much cooler.

'include' won't work, because the output needs to depend on the parameters that Flash sends it, 'include' would simply output something as the html file is loading or whatever, and would then remain that way forever.

'Notion commotion' on Dev Shed had a solution that I can't quite get to do what I want, but here is where I am so far:

function gQ() {

var script = document.createElement('script');
script.src = 'getQus.php?val=What';
document.getElementsByTagName('head')[0].appendChild(script);
return vall;

}

and in the getQus.php file:

header("Cache-Control:no-cache");
header('Content-Type:text/javascript');
$val=$_GET['val'].' the...';
echo "vall = '$val';";


The Flash file makes an External Interface call (when a button is pressed) to the Javascript function, and puts the returned value into a text box.

What actually happens is that I have to press the button twice to get anything back.

Why, why?

Wednesday, 26 May 2010

Calling alerts with ExternalInterface

My ominous prediction came true - Internet Explorer is refusing to cooperate.

On the plus side, I found out that you can do Javascript alerts without defining any functions on your html page.

I attached this code to a button:

ExternalInterface.call('alert','Work darnit!');

and it actually worked (on both IE and Firefox). Which was nice.

Which means that the External Interface call does work on IE, but I don't know why the whole thing is not working.

Resizing the Stage

This code was pretty hard to get hold of on the internet, actually I couldn't find it. Anyone who came close to answering kind of seemed to assume that you knew what a 'DIV' tag was for and how to use it. Well, I didn't, and I didn't, but now I kind of do!

The problem is this, I will be making a swf whose length will change, depending on what the user writes, and it will certainly be longer than the screen. I don't want to make a really long swf, that people can scroll down even though there is nothing there, on the off chance that someone might enter enough text for it to need to be that long, and what if they write even more!

Also, most of the things that were addressing this, were trying to resize the stage, so it could fit in the browser window, and again, not my problem. Anyway, the code that they gave out was really complex, and I don't like to use code unless I understand what it actually means...

So, first things first, the 'DIV' tag.
Apparently, you can put this tag around things, give it an id attribute, and then refer to it with JavaScript. But, you can do this with ordinary tags anyway, so why bother (unless you have more than one swf on the page).

It works like this:
<embed id="embedtag" src=...


and then in your javascript function:
var swfTag = document.getElementById('embedtag');

Then you can alter its attributes:
swfTag.setAttribute('height','600');


The stage of the swf will automatically update, it doesn't refresh the movie or anything.

Then I had a bit of a problem with how the swf would be displayed on the new stage. It wouldn't be aligned to the side. Now I checked, and the movie clip that was on 0, still thought it was on 0, so it wasn't moving. I fixed this by adding an attribute to the embed tag -salign="lt"-aligning it's side to the left. I wasn't using the code output by the CS3 flash publisher, because it spits out so much javascript, I can't make sense of it, or how to alter it.

I put a button in my flash movie that increased the size of one of the movie clips on screen, and then used ExternalInterface to nake sure that the stage size on the html side of things was big enough, and with the salign="lt" bit, it worked.

I haven't tried it with the ie tag yet, what are the chances that I will come across some unexpected problems...quite high, I'd say.

Flash + JavaScript: How to Use External Interface

First a short reminder on External Interface:

I use it to get info or do things that JavaScript has access to, and that I don't, for example, doing alerts. You can pass it parameters and get data from it.

There may be issues with testing it locally though.

Example:

var val:Number = ExternalInterface.call('funcName','parameter1','parameter2');

The first parameter is the name of the javascript function on the html page, the others are parameters to be passed to the function.

On your html page, you would have something like:

<script type="text/javascript">
function funcName(text1,text2){ 
return text2;
}
</script>


Of course, that would be completely useless, but I don't deal with JavaScript much, and that is what I could come up with off the top of my head. Pathetic, huh?

Anyway...