Flash player control from javascript outside? - javascript

I am making flash player that suppose to be controlled from outside, from javascript.
I need those methods:
Play/Pause and Volume level
I am stuck with volume level... I tried to add this code:
flashMovie.volume = 10;
Where flashMovie is flash instance... And it's show NO ERROR but it's NOT WORKING
I try to make inner AddCall(); and then when it's called to call() from javascript to return sound level.
AS 3:
function setthisvolume()
{
var vlm = ExternalInterface.call('giveMeVolume()');
this.soundTransform.volume = vlm;
}
ExternalInterface.addCallback("setthisvolume", setthisvolume);
JS:
var soundlevel = 10;
function soundlevelset()
{
var flashMovie=getFlashMovieObject("objswf");
flashMovie.setthisvolume();
}
function giveMeVolume()
{
return parseInt(soundlevel);
}
But I am getting this error:
Error calling method on NPObject!
I even tried with setInterval():
AS 3:
function setthisvolume()
{
var vlm = ExternalInterface.call('giveMeVolume()');
this.soundTransform.volume = vlm;
}
setInterval(setthisvolume, 1000);
JS:
var soundlevel = 10;
function giveMeVolume()
{
return parseInt(soundlevel);
}
And it doesn't show any error, but it doesn't work neither...
Did someone work with stuffs like this?
Can someone help me what I am doing wrong here...
Thank you!

Thank you, #someone!
This second option worked okay!
Here is working code:
AS3:
function setthisvolume(vlm)
{
this.soundTransform = new SoundTransform(vlm);
}
ExternalInterface.addCallback("setthisvolume", setthisvolume);
JS:
function getFlashMovieObject(movieName)
{
if (window.document[movieName])
{
return window.document[movieName];
}
if (navigator.appName.indexOf("Microsoft Internet")==-1)
{
if (document.embeds && document.embeds[movieName])
return document.embeds[movieName];
}
else
{
return document.getElementById(movieName);
}
}
var soundlevel = 0.5; // it's 0-1 volume, not 0-100
function soundlevelset()
{
var flashMovie=getFlashMovieObject("objswf");
flashMovie.setthisvolume(parseFloat(soundlevel));
}
When you are using slider each time slider change you need to change soundlevel variable and call soundlevelset();
Hope I helped next one who is starting with this... :)
Thank you!

Try removing the parentheses when calling giveMeVolume, by changing this:
var vlm = ExternalInterface.call('giveMeVolume()');
to this:
var vlm = ExternalInterface.call('giveMeVolume');
If that doesn't work, try passing the volume directly as an argument/parameter, like this (this is probably a better way to do it):
AS3:
function setthisvolume(vlm)
{
this.soundTransform.volume = vlm;
}
ExternalInterface.addCallback("setthisvolume", setthisvolume);
JS:
var soundlevel = 10;
function soundlevelset()
{
var flashMovie=getFlashMovieObject("objswf");
flashMovie.setthisvolume(soundlevel);
}

Code looks reasonable.
Check if you allow Flash to communicate with script There is property when you create Flash object - AllowsScriptAccess - http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7c9b.html .
Check if Falsh is coming from the same domain as HTML page.
For addCallback check if you are getting correct Flash object by Id (the way to create Flash is different in IE/FF, so you may be getting the wrong one).
Check if you have correct SWF file - browser may cache older version... I.e. add element on the Flash control that simply shows static number and make sure it matches to latest one.

Related

Trouble referencing object from within function - adobe animate canvas

I am having trouble getting a function to reference a movie clip on the stage (thatsRight). I can reference it outside of a function to initially set it visible = false and inside the this.Correct function to visible = true, but calling another function this.removeAndCheck can not reference the same movie clip on the stage. I get the error
"TypeError: undefined is not an object (evaluating
'this.thatsRight.visible = false')"
on the line in the this.removeAndCheck function. This doesn't make sense to me. One function can reference the movie clip but another can not. This code is on frame.
this.thatsRight.visible = false;
this.Correct = function() {
this.thatsRight.visible = true;
setTimeout(this.removeAndCheck, 3000)
}
this.removeAndCheck = function() {
this.thatsRight.visible = false;
this.CheckAllCorrect();
}
I am also have issue with this.CheckAllCorrect() being called. this.CheckAllCorrect() is also on from one but on another action layer.
This is part of a conversion of different as3 flash assets to html5 canvas assets using adobe animate CC. Any help with this would be greatly appreciated.
#Sammeer is correct, this is a scoping issue. Typically I get around this with a Function.bind
setTimeout(this.removeAndCheck.bind(this), 3000);
You might also see local variable binding like this:
var that = this;
setTimeout(function() { that.removeAndCheck(); }, 3000);
Here is some further reading.
This is a scoping issue with the value of the this variable, which is a common mistake in javascript. To avoid these issues completely, just use arrow functions instead:
this.thatsRight.visible = false;
this.removeAndCheck = () => {
this.thatsRight.visible = false;
this.CheckAllCorrect();
}
this.Correct = () => {
this.thatsRight.visible = true;
setTimeout(this.removeAndCheck, 3000)
}

Basic var misunderstanding

I have created this:
var where = function(){
sym.getSymbol("Man").getPosition()
}
console.log(where);
if (where()<=0){
var playMan = sym.getSymbol("Man").play();
} else {
var playMan = sym.getSymbol("Man").playReverse();
}
This is for Edge Animate hence all the syms. I am trying to access the timeline of symbol Man, then if it is at 0 play it. But it isnt working and the reason, I think, is that I have an incomplete understanding of how a var works. In my mind I am giving the variable 'where' the value of the timeline position of symbol 'Man'. In reality the console is just telling me I have a function there, not the value of the answer. I have run into this before and feel if I can crack it I will be a much better human being.
So if anyone can explain in baby-language what I am misunderstanding I would be grateful.
Thanks
S
var where = function () { ... };
and
function where() { ... }
are essentially synonymous here. So, where is a function. You are calling that function here:
if (where()<=0)
However, the function does not return anything. You need to return the value from it, not just call sym.getSymbol("Man").getPosition() inside it.
That, or don't make it a function:
var where = sym.getSymbol("Man").getPosition();
if (where <= 0) ...
The value will only be checked and assigned once in this case, instead of updated every time you call where().
Try
var where = function()
{
return sym.getSymbol("Man").getPosition();
};
Your code wasn't returning anything.
var where = function() {
return sym.getSymbol("Man").getPosition()
}
console.log(where);
if(where()<=0) {
var playMan = sym.getSymbol("Man").play();
} else {
var playMan = sym.getSymbol("Man").playReverse();
}

How to form callback when using context.executeQueryAsync delegates in javascript

Sorry for yet another question about callbacks. In trying to solve this problem, I've run across about a million of them. However, I'm having trouble wrapping my head around this particular scenario.
I have the code below, which obviously doesn't work as delegates apparently don't return values (I'm learning as I go, here). So, I know I need a callback at this point, but I'm not sure how to change this code to do that. Can anyone help?
function MyFunction() {
var ThisLoggedInUser = checkCurrentUser();
//do some stuff with the current user
}
function checkCurrentUser() {
var context = SP.ClientContext.get_current();
var siteColl = context.get_site();
var web = siteColl.get_rootWeb();
this._currentUser = web.get_currentUser();
context.load(this._currentUser);
context.executeQueryAsync(Function.createDelegate(this, this.CheckUserSucceeded),
Function.createDelegate(this, this.CheckUserfailed));
}
function CheckUserSucceeded() {
var ThisUser = this._currentUser.get_title();
return ThisUser;
}
function CheckUserfailed() {
alert('failed');
}
Based on your comment, you have to rething the way you want your code because you cannot use ThisUser in MyFunction().
For example you could do that:
function CheckUser() { ... }
// then call the function to find the current user
CheckUser();
// then in CheckUserSucceeded you call MyFunction()
function CheckUserSucceeded() {
MyFunction(this._currentUser.getTitle())
}
// and now you can use ThisUser in MyFunction()
function MyFunction(ThisUser) {
// do something with ThisUser
}
Your CheckUserSucceed won't return anything because it's asynchronous....
So you have to do something like that:
var ThisUser;
function CheckUserSucceeded() {
ThisUser = this._currentUser.getTitle()
// here you can call an other action and do something with ThisUser
}
You may also want to check the $SP().whoami() function from http://aymkdn.github.io/SharepointPlus/ and see the documentation.

Whats the best way to load Object Oriented JS properties dependent on page?

I have and external JS scripts file with all my objects in that runs once the document is ready something like this...
jQuery(function($) {
var Main = {
run: function () {
myFunction.setup();
}
}
var myFunction = {
setup: function() {
//Do some stuff here
}
}
Main.run();
});
I want to be able to run myFunction.setup() only if im on a certain page though otherwise I get errors if that method is looking for elements on the page that don't exist e.g a slideshow, menus etc.
At the moment I have got round this by checking if the element exists with .length and if it does then running the rest of the method but I was wondering if there was a nicer way? Maybe like if it was possible to send variables to the scripts file when it loads based on the page im on so it knows what to methods run?
Any help would be really appreciated.
Thanks
Giles
Paul Irish has a great way of doing exactly this, using ID and classes from the body tag to execute certain blocks of code:
http://paulirish.com/2009/markup-based-unobtrusive-comprehensive-dom-ready-execution/
This kind of thing might help:
Page specific
var page_config = {
setup_allowed: true
// ... more config
};
Generic
var Main,
myFunction;
(function ($, _config) {
myFunction = (function () {
var _public = {};
if (_config.setup_allowed === true) {
_public.setup = function () {
};
}
return _public;
})();
Main = (function () {
var _public = {};
if (typeof myFunction.setup !== "undefined") {
_public.run = function () {
myFunction.setup();
};
// Run it as we had Main.run() before
_public.run();
}
return _public;
})();
})(jQuery, page_config);
This way Main.run() and myFunction.setup() are only available if specified in page_config.
Here's a working example you can have a play with. This may be a bit verbose for your particular requirement but hopefully it'll help in some way :-)

Javascript function objects

I edited the question so it would make more sense.
I have a function that needs a couple arguments - let's call it fc(). I am passing that function as an argument through other functions (lets call them fa() and fb()). Each of the functions that fc() passes through add an argument to fc(). How do I pass fc() to each function without having to pass fc()'s arguments separately? Below is how I want it to work.
function fa(fc){
fc.myvar=something
fb(fc)
}
function fb(fc){
fc.myothervar=something
fc()
}
function fc(){
doessomething with myvar and myothervar
}
Below is how I do it now. As I add arguments, it's getting confusing because I have to add them to preceding function(s) as well. fb() and fc() get used elsewhere and I am loosing some flexibility.
function fa(fc){
myvar=something
fb(fc,myvar)
}
function fb(fc,myvar){
myothervar=something
fc(myvar,myothervar)
}
function fc(myvar,myothervar){
doessomething with myvar and myothervar
}
Thanks for your help
Edit 3 - The code
I updated my code using JimmyP's solution. I'd be interested in Jason Bunting's non-hack solution. Remember that each of these functions are also called from other functions and events.
From the HTML page
<input type="text" class="right" dynamicSelect="../selectLists/otherchargetype.aspx,null,calcSalesTax"/>
Set event handlers when section is loaded
function setDynamicSelectElements(oSet) {
/**************************************************************************************
* Sets the event handlers for inputs with dynamic selects
**************************************************************************************/
if (oSet.dynamicSelect) {
var ySelectArgs = oSet.dynamicSelect.split(',');
with (oSet) {
onkeyup = function() { findListItem(this); };
onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }
}
}
}
onclick event builds list
function selectList(sListName, sQuery, fnFollowing) {
/**************************************************************************************
* Build a dynamic select list and set each of the events for the table elements
**************************************************************************************/
if (fnFollowing) {
fnFollowing = eval(fnFollowing)//sent text function name, eval to a function
configureSelectList.clickEvent = fnFollowing
}
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList); //create the div in the right place
var oSelected = event.srcElement;
if (oSelected.value) findListItem(oSelected)//highlight the selected item
}
Create the list
function setDiv(sPageName, sQuery, sClassName, fnBeforeAppend) {
/**************************************************************************************
* Creates a div and places a page in it.
**************************************************************************************/
var oSelected = event.srcElement;
var sCursor = oSelected.style.cursor; //remember this for later
var coords = getElementCoords(oSelected);
var iBorder = makeNumeric(getStyle(oSelected, 'border-width'))
var oParent = oSelected.parentNode
if (!oParent.id) oParent.id = sAutoGenIdPrefix + randomNumber()//create an ID
var oDiv = document.getElementById(oParent.id + sWindowIdSuffix)//see if the div already exists
if (!oDiv) {//if not create it and set an id we can use to find it later
oDiv = document.createElement('DIV')
oDiv.id = oParent.id + sWindowIdSuffix//give the child an id so we can reference it later
oSelected.style.cursor = 'wait'//until the thing is loaded
oDiv.className = sClassName
oDiv.style.pixelLeft = coords.x + (iBorder * 2)
oDiv.style.pixelTop = (coords.y + coords.h + (iBorder * 2))
XmlHttpPage(sPageName, oDiv, sQuery)
if (fnBeforeAppend) {
fnBeforeAppend(oDiv)
}
oParent.appendChild(oDiv)
oSelected.style.cursor = ''//until the thing is loaded//once it's loaded, set the cursor back
oDiv.style.cursor = ''
}
return oDiv;
}
Position and size the list
function configureSelectList(oDiv, fnOnClick) {
/**************************************************************************************
* Build a dynamic select list and set each of the events for the table elements
* Created in one place and moved to another so that sizing based on the cell width can
* occur without being affected by stylesheet cascades
**************************************************************************************/
if(!fnOnClick) fnOnClick=configureSelectList.clickEvent
if (!oDiv) oDiv = configureSelectList.Container;
var oTable = getDecendant('TABLE', oDiv)
document.getElementsByTagName('TABLE')[0].rows[0].cells[0].appendChild(oDiv)//append to the doc so we are style free, then move it later
if (oTable) {
for (iRow = 0; iRow < oTable.rows.length; iRow++) {
var oRow = oTable.rows[iRow]
oRow.onmouseover = function() { highlightSelection(this) };
oRow.onmouseout = function() { highlightSelection(this) };
oRow.style.cursor = 'hand';
oRow.onclick = function() { closeSelectList(0); fnOnClick ? fnOnClick() : null };
oRow.cells[0].style.whiteSpace = 'nowrap'
}
} else {
//show some kind of error
}
oDiv.style.width = (oTable.offsetWidth + 20) + "px"; //no horiz scroll bars please
oTable.mouseout = function() { closeSelectList(500) };
if (oDiv.firstChild.offsetHeight < oDiv.offsetHeight) oDiv.style.height = oDiv.firstChild.offsetHeight//make sure the list is not too big for a few of items
}
Okay, so - where to start? :) Here is the partial function to begin with, you will need this (now and in the future, if you spend a lot of time hacking JavaScript):
function partial(func /*, 0..n args */) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var allArguments = args.concat(Array.prototype.slice.call(arguments));
return func.apply(this, allArguments);
};
}
I see a lot of things about your code that make me cringe, but since I don't have time to really critique it, and you didn't ask for it, I will suggest the following if you want to rid yourself of the hack you are currently using, and a few other things:
The setDynamicSelectElements() function
In this function, you can change this line:
onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }
To this:
onclick = function() { selectList.apply(null, ySelectArgs); }
The selectList() function
In this function, you can get rid of this code where you are using eval - don't ever use eval unless you have a good reason to do so, it is very risky (go read up on it):
if (fnFollowing) {
fnFollowing = eval(fnFollowing)
configureSelectList.clickEvent = fnFollowing
}
And use this instead:
if(fnFollowing) {
fnFollowing = window[fnFollowing]; //this will find the function in the global scope
}
Then, change this line:
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList);
To this:
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', partial(configureSelectListAlternate, fnFollowing));
Now, in that code I provided, I have "configureSelectListAlternate" - that is a function that is the same as "configureSelectList" but has the parameters in the reverse order - if you can reverse the order of the parameters to "configureSelectList" instead, do that, otherwise here is my version:
function configureSelectListAlternate(fnOnClick, oDiv) {
configureSelectList(oDiv, fnOnClick);
}
The configureSelectList() function
In this function, you can eliminate this line:
if(!fnOnClick) fnOnClick=configureSelectList.clickEvent
That isn't needed any longer. Now, I see something I don't understand:
if (!oDiv) oDiv = configureSelectList.Container;
I didn't see you hook that Container property on in any of the other code. Unless you need this line, you should be able to get rid of it.
The setDiv() function can stay the same.
Not too exciting, but you get the idea - your code really could use some cleanup - are you avoiding the use of a library like jQuery or MochiKit for a good reason? It would make your life a lot easier...
A function's properties are not available as variables in the local scope. You must access them as properties. So, within 'fc' you could access 'myvar' in one of two ways:
// #1
arguments.callee.myvar;
// #2
fc.myvar;
Either's fine...
Try inheritance - by passing your whatever object as an argument, you gain access to whatever variables inside, like:
function Obj (iString) { // Base object
this.string = iString;
}
var myObj = new Obj ("text");
function InheritedObj (objInstance) { // Object with Obj vars
this.subObj = objInstance;
}
var myInheritedObj = new InheritedObj (myObj);
var myVar = myInheritedObj.subObj.string;
document.write (myVar);
subObj will take the form of myObj, so you can access the variables inside.
Maybe you are looking for Partial Function Application, or possibly currying?
Here is a quote from a blog post on the difference:
Where partial application takes a function and from it builds a function which takes fewer arguments, currying builds functions which take multiple arguments by composition of functions which each take a single argument.
If possible, it would help us help you if you could simplify your example and/or provide actual JS code instead of pseudocode.

Categories