ExternalInterface - javascript

Hey, so I'm having a bunch of trouble getting ExternalInterface to work, which is odd, because I use it somewhat often.
I'm hoping it's something I just missed because I've been looking at it too long.
The flash_ready function is correctly returning the objectID, and as far as I can tell, everything else is in order.
Unfortunately, when I run it, I get an error (varying by browser) telling me that basically document.getElementById(<movename>).test() is not a valid method.
Here's the code:
javascript:
function flash_ready(i){
document.getElementById(i).test('success!');
}
Embed Html (Generated):
<script type="text/javascript">
swfobject.embedSWF("/chainmaille/includes/media/flash/upload_image.swf", "/chainmaille/includes/media/flash/upload_image", "500", "50", "9.0.0","expressInstall.swf", {}, {allowScriptAccess:'always', wmode:'transparent'},{id:'uploader_flash',name:'uploader_flash'});
</script>
<object type="application/x-shockwave-flash" id="uploader_flash" name="uploader_flash" data="/chainmaille/includes/media/flash/upload_image.swf" width="500" height="50"><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>
AS3 :
package com.jesseditson.uploader {
import flash.display.MovieClip;
import flash.external.ExternalInterface;
import flash.system.Security;
public class UI extends MovieClip {
// Initialization:
public function UI() {
Security.allowDomain('*');
ExternalInterface.addCallback("test", test);
var jscommand:String = "flash_ready('"+ExternalInterface.objectID+"');";
var url:URLRequest = new URLRequest("javascript:" + jscommand + " void(0);");
navigateToURL(url, "_self");
}
public function test(t){
trace(t);
}
}
}
Swfobject is being included via google code, and the flash embeds just fine, so that's not the problem.
I've got a very similar setup working on another server, but can't seem to get it working on this one. It's a Hostgator shared server. Could it be the server's fault? Anybody see any obvious syntax problems?
Thanks in advance!

The Flash isn't actually finished constructing yet. You're calling your flash_ready callback from the constructor, and so the JS is trying to call in before the object is on the stage. Move your flash_ready call to, say, an Event.ADDED_TO_STAGE listener and it should start working.

Ok, so after further investigation, it appears that there was a problem with multiple instances of the flash object, because I was cloning it to a lightbox. I have gotten it working now.

Just spent 5 hours fighting with this. It was all really frustrating. In my case the solution was very very simple and I would have never guessed it.
So first of for all of you who have never seen the flash player debugger running on files inside your browser finding this link that walks you through the setup has resulted in a somewhat magical experience :)
Now to my ExternalInterface discovery: There was a sandbox violation inside the same domain. This meant that flash cannot access www.yourdomain.com from yourdomain.com. The weird thing of course is that you are not explicitly calling the domain with ExternalInterface.
Anyhow, the solution was very simple: add this to my .htaccess file and that was it!
# Redirect non-www to www
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) http://www.youtdomain.com/$1 [R=301,L]
Hope this helps someone

Is flash_ready receiving the objectID that you are expecting?
Also, why use:
var jscommand:String = "flash_ready('"+ExternalInterface.objectID+"');";
var url:URLRequest = new URLRequest("javascript:" + jscommand + " void(0);");
navigateToURL(url, "_self");
When this is designed to do that:
ExternalInterface.call("flash_ready", ExternalInterface.objectID);

Post your source (pre-generatred). When your browser says [Flash].Method is not a function, 99% of the time it means that you tried calling a function in Flash before the .swf was ready for it. I see that you tried to do that, but clearly its not working so something must be off. So post your pre-rendered source and I am sure we can find the problem.

Related

add Office.onReady() function to javascript

I am new to Javascript and am trying to make an outlook web-addin take the Office.onReady() function properly.
https://learn.microsoft.com/en-us/office/dev/add-ins/develop/initialize-add-in
I tried using
Office.onReady()
.then
to make my function work with the office js API but it then I got an error that my function couldn't be found.
Code:
$("#brief-summary").click(briefsummary);
$("#email-setup").click(emailsetup);
Office.onReady()
.then(function briefsummary() {
var msgFrom = Office.context.mailbox.item.from;
var msgfirstname = String(msgFrom.displayName).split(" ");
Office.context.mailbox.item.displayReplyAllFormAsync(
"Hello " +
msgfirstname[0] +
", <br> \
<br> Here is a brief summary on everything worked on: \
<br> \
<br>Thank you for your time, \
<br>"
);
});
Result:
Uncaught ReferenceError: briefsummary is not defined
So I am pretty sure I am doing it wrong.
I also tried using Office.onReady(); at the begining of the script. It suppressed the Uncaught Error: Office.js has not fully loaded. Your app must call "Office.onReady()" error but office javascript doesn't do anything. (Its suppose to bring up a new reply window with text inside)
Link to where the app is hosted: https://alloyautomateaddinbeta3.azurewebsites.net/index.html (Although the office.js only loads when you are in the outlook app. But you can go to sources from inspector in chrome and look at the js script in full)
Any ideas would be awesome.
I have seems to figure out what to do but I was pretty janky. If anyone knowas a better way to clean this up let me know.
I essentially my code inbetween this and it worked:
Office.onReady((info) => {
if (info.host === Office.HostType.Outlook) {
#Insert code here
}
});
It was pretty janky as it gives me a warning saying Function variables should not be placed in blocks. Use a function expression or move the statement to the top of the outer function
I will be working on the code periodically so I will update my answer to a better one as time goes on unless someone else has an answer as well.
Thanks

Failed to execute 'postMessage' on 'DOMWindow': https://www.youtube.com !== http://localhost:9000

This is the error message that I get:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided
('https://www.youtube.com') does not match the recipient window's origin
('http://localhost:9000').
I've seen other similar problems where the target origin is http://www.youtube.com and the recipient origin is https://www.youtube.com, but none like mine where the target is https://www.youtube.com and the origin is http://localhost:9000.
I don't get the problem. What is the problem?
How can I fix it?
I believe this is an issue with the target origin being https. I suspect it is because your iFrame url is using http instead of https. Try changing the url of the file you are trying to embed to be https.
For instance:
'//www.youtube.com/embed/' + id + '?showinfo=0&enablejsapi=1&origin=http://localhost:9000';
to be:
'https://www.youtube.com/embed/' + id + '?showinfo=0&enablejsapi=1&origin=http://localhost:9000';
Just add the parameter "origin" with the URL of your site in the paramVars attribute of the player, like this:
this.player = new window['YT'].Player('player', {
videoId: this.mediaid,
width: '100%',
playerVars: {
'autoplay': 1,
'controls': 0,
'autohide': 1,
'wmode': 'opaque',
'origin': 'http://localhost:8100'
},
}
Setting this seems to fix it:
this$1.player = new YouTube.Player(this$1.elementId, {
videoId: videoId,
host: 'https://www.youtube.com',
You can save the JavaScript into local files:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfluxKqfs/www-widgetapi.js
Into the first file, player_api put this code:
if(!window.YT)var YT={loading:0,loaded:0};if(!window.YTConfig)var YTConfig={host:"https://www.youtube.com"};YT.loading||(YT.loading=1,function(){var o=[];YT.ready=function(n){YT.loaded?n():o.push(n)},window.onYTReady=function(){YT.loaded=1;for(var n=0;n<o.length;n++)try{o[n]()}catch(i){}},YT.setConfig=function(o){for(var n in o)o.hasOwnProperty(n)&&(YTConfig[n]=o[n])}}());
Into the second file, find the code: this.a.contentWindow.postMessage(a,b[c]);
and replace it with:
if(this._skiped){
this.a.contentWindow.postMessage(a,b[c]);
}
this._skiped = true;
Of course, you can concatenate into one file - will be more efficient.
This is not a perfect solution, but it's works!
My Source : yt_api-concat
Make sure you are loading from a URL such as:
https://www.youtube.com/embed/HIbAz29L-FA?modestbranding=1&playsinline=0&showinfo=0&enablejsapi=1&origin=https%3A%2F%2Fintercoin.org&widgetid=1
Note the "origin" component, as well as "enablejsapi=1". The origin must match what your domain is, and then it will be whitelisted and work.
In my case this had to do with lazy loading the iframe. Removing the iframe HTML attribute loading="lazy" solved the problem for me.
I got the same error. My mistake was that the enablejsapi=1 parameter was not present in the iframe src.
You also get this message when you do not specify a targetOrigin in calls to window.postMessage().
In this example we post a message to the first iFrame and use * as target, which should allow communication to any targetOrigin.
window.frames[0].postMessage({
message : "Hi there",
command :"hi-there-command",
data : "Some Data"
}, '*')
Try using window.location.href for the url to match the window's origin.
Remove DNS Prefetch will solve this issue.
If you're using WordPress, add this line in your theme's functions.php
remove_action( 'wp_head', 'wp_resource_hints', 2 );
There could be any of the following, but all of them lead into DOM not loaded before its accessed by the javascript.
So here is what you have to ensure before actually calling JS code:
* Make sure the container has loaded before any javascript is called
* Make sure the target URL is loaded in whatever container it has to
I came across the similar issue but on my local when I am trying to have my Javascript run well before onLoad of the main page which causes the error message. I have fixed it by simply waiting for whole page to load and then call the required function.
You could simply do this by adding a timeout function when page has loaded and call your onload event like:
window.onload = new function() {
setTimeout(function() {
// some onload event
}, 10);
}
that will ensure what you are trying will execute well after onLoad is trigger.
In my instance at least this seems to be a harmless "not ready" condition that the API retries until it succeeds.
I get anywhere from two to nine of these (on my worst-case-tester, a 2009 FossilBook with 20 tabs open via cellular hotspot).... but then the video functions properly. Once it's running my postMessage-based calls to seekTo definitely work, haven't tested others.
It looks it's only a Chrome security system to block repeated requests, using CORB.
https://www.chromestatus.com/feature/5629709824032768
In my case, YouTube was blocking Access after the first load of the same webpage which has many video API data request, high payload.
For pages with low payload, the issue does not occur.
In Safari and other non Chronuim based browsers, the issue does not occur.
If I load the webpage in a new browser, the issue does not occur, when I reload the same page, the issue appears.
In some cases (as one commenter mentioned) this might be caused if you are moving the player within DOM, like append or etc..
This helped me (with Vue.js)
Found here vue-youtube
mounted() {
window.YTConfig = {
host: 'https://www.youtube.com/iframe_api'
}
const host = this.nocookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com'
this.player = player(this.$el, {
host,
width: this.width,
height: this.height,
videoId: this.videoId,
playerVars: this.playerVars
})
...
}
UPDATE:
Working like a charm like this:
...
youtube(
video-id="your_video_code_here"
nocookie
)
...
data() {
return {
playerVars: {
origin: window.location.href,
},
};
},
I think the description of the error is misleading and has originally to do with wrong usage of the player object.
I had the same issue when switching to new Videos in a Slider.
When simply using the player.destroy() function described here the problem is gone.
I had this same problem and it turns out it was because I had the Chrome extension "HTTPS Everywhere" running. Disabling the extension solved my problem.
This exact error was related to a content block by Youtube when "playbacked on certain sites or applications". More specifically by WMG (Warner Music Group).
The error message did however suggest that a https iframe import to a http site was the issue, which it wasn't in this case.
You could change your iframe to be like this and add origin to be your current website. It resolves error on my browser.
<iframe class="test-testimonials-youtube-group" type="text/html" width="100%" height="100%"
src="http://www.youtube.com/embed/HiIsKeXN7qg?enablejsapi=1&origin=http://localhost:8000"
frameborder="0">
</div>
ref: https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
Just wishing to avoid the console error, I solved this using a similar approach to Artur's earlier answer, following these steps:
Downloaded the YouTube Iframe API (from https://www.youtube.com/iframe_api) to a local yt-api.js file.
Removed the code which inserted the www-widgetapi.js script.
Downloaded the www-widgetapi.js script (from https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl7VfO1r/www-widgetapi.js) to a local www-widgetapi.js file.
Replaced the targetOrigin argument in the postMessage call which was causing the error in the console, with a "*" (indicating no preference - see https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).
Appended the modified www-widgetapi.js script to the end of the yt-api.js script.
This is not the greatest solution (patched local script to maintain, losing control of where messages are sent) but it solved my issue.
Please see the security warning about removing the targetOrigin URI stated here before using this solution - https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Patched yt-api.js example
Adding origin=${window.location.host} or "*" is not enough.
Add https:// before it and it will work.
Also, make sure that you are using an URL that can be embedded: take the video ID out and concatenate a string that has the YouTube video prefix and the video ID + embed definition.
I think we could customize the sendMessage of the YT.Player
playerOptions.playerVars.origin = window.location.origin or your domain.
this.youtubePlayer = new YT.Player(element,playerOptions);
this.youtubePlayer.sendMessage = function (a) {
a.id = this.id, a.channel = "widget", a = JSON.stringify(a);
var url = new URL(this.h.src), origin = url.searchParams.get("origin");
if (origin && this.h.contentWindow) {
this.h.contentWindow.postMessage(a, origin)
}
}
I used this function to resolve in my project.
Extending #Hokascha's answer above it was also lazy loading for me being automatically added by WordPress. This code will remove all lazy loading on the site's iframes (add to functions.php):
function disable_post_content_iframe_lazy_loading( $default, $tag_name, $context ) {
if ( 'iframe' === $tag_name ) {
return false;
}
return $default;
}
add_filter('wp_lazy_loading_enabled', 'disable_post_content_iframe_lazy_loading', 10, 3);
I got a similar error message in my attempt to embed a Stripe pricing table when:
Adding the embed code via PHP through a custom WordPress short code
Or by appending the code to the page dynamically with JavaScript (Even a using a setTimeout() delay to ensure the DOM was loaded didn't work).
I was able to solve this on my WordPress site by adding the code to the WordPress page itself using plain html code in the block editor.
mine was:
<youtube-player
[videoId]="'paxSz8UblDs'"
[playerVars]="playerVars"
[width]="291"
[height]="194">
</youtube-player>
I just removed the line with playerVars, and it worked without errors on console.
You can try :
document.getElementById('your_id_iframe').contentWindow.postMessage('your_message', 'your_domain_iframe')
I was also facing the same issue then I visit official Youtube Iframe Api where i found this:
The user's browser must support the HTML5 postMessage feature. Most modern browsers support postMessage
and wander to see that official page was also facing this issue. Just Visit official Youtube Iframe Api and see console logs. My Chrome version is 79.0.3945.88.

Crossroadsjs routing: how to use it?

I am facing the same problem as this one as I am trying to figure out how to use crossroads for a few hours now and nothing seems to work. its webiste is just another poor documented site... I think I am probably daft! I wonder if anyone has made it?
html head,
<title>Crossroads</title>
<script src="js/libs/signals.js"></script>
<script src="js/libs/crossroads.min.js"></script>
<script src="js/app.js"></script>
</head>
app.js, just as simple as this,
crossroads.addRoute('/news/{id}', function(id){
alert(id);
});
so I try it out on my localhost browser,
http://localhost/crossroadjs/#/news/123
nothing happens. I thought it would be 123??
Crossroads doesn't handle history/state change events from the browser. From their site:
A routes system shouldn't do anything else besides routing.
Instead, the site recommends Hasher for this purpose and gives a rather complete looking example:
//setup crossroads
crossroads.addRoute('foo');
crossroads.addRoute('lorem/ipsum');
crossroads.routed.add(console.log, console); //log all routes
//setup hasher
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash); //parse initial hash
hasher.changed.add(parseHash); //parse hash changes
hasher.init(); //start listening for history change
//update URL fragment generating new history record
hasher.setHash('lorem/ipsum');
Alternatively you could use a different history plugin, or write something yourself. But crossroads leaves that part up to you.
Crossroads.js gives crossroads.addRoute(pattern, [handler], [priority]); API to add route patterns. However, when the first time you load the page Crossroads does not automatically initiate the parser to check against the url of the page. You need to add crossroads.parse(document.location.pathname); on you document load to trigger the route. Check out Crossroads.js Tutorial.

Joomla2.5 framework seems to be interfering with javascript syntax

The below code works perfectly outside of Joomla2.5. as well as in earlier versions of Joomla , but fails when it's within a Joomla2.5 article, or rendered by a Joomla2.5 plugin.
The line in question is this one.
s1.addVariable('playlistfile', 'http://www.myserver.com/playlist.php?s=123&u=789
It returns an XML playlist which the player normally loads and plays as expected, but is the cuplprit because using a hardcoded file name with an XML extention works properly. I've tried all the usual encoding routines, but with no luck. Is there an approach, or syntax, that will work from within Joomla2.5?
Full Context:
<script type='text/javascript'>
var s1 = new SWFObject('http://www.myserver.com/v5.7/player.swf', 'player', '420', '315', '9.0.124', '#FFFFFF');
s1.addParam('allowfullscreen', 'true');
s1.addParam('allowscriptaccess', 'always');
s1.addVariable('streamer', 'rtmp://streaming.myserver.com/');
s1.addVariable('playlistfile', 'http://www.myserver.com/playlist.php?s=123&u=789');
s1.write('mediaspace1');
</script>
Also, I'm aware that there are newer, and other ways of loading the JW Player, but this is an interim step of converting many, many sites, and some legacy code must be retained.
Among the "usual encoding", have you tried "encodeURIComponent()" while adding the playlistfile variable? Not sure if PHP encoding would accomplish it, but Flash will not handle it correctly otherwise.

How do I load an external file and make sure that it runs first in JSFiddle?

I have a JsFiddle here, and added Microsoft AJAX to be loaded through external JS/resource section. How can I tell whether or not my JS code is run after the AJAX file has finished loading?
Seems that the AJAX does not load either. :(
Here is the code in the JSFiddle:
Type.registerNamespace("Tutorial.Chapter1");
Tutorial.Chapter1.Person = function(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
};
Tutorial.Chapter1.Person.prototype = {
set_firstName: function(value) {
this._firstName = value;
},
get_firstName: function() {
return this._firstName;
},
set_lastName: function(value) {
this._lastName = value;
},
get_lastName: function() {
return this._lastName;
},
_firstName: "",
_lastName: "",
displayName: function() {
alert("Hi! " + this._firstName + " " + this._lastName);
}
};
Tutorial.Chapter1.Person.registerClass("Tutorial.Chapter1.Person", null);
The External Resources tab of jsFiddle is currently somewhat tricky and unstable to use.
The resources defined here are often not correctly included into the code. There seems to be an issue with the automatic recognition of JS and CSS resources. If this happens, the external resource is simply not added to the head section of the resulting code. You can check that by reviewing the source code of the Result frame of your jsFiddle. You will find that your MS AJAX resource is simply NOT mentioned in the resulting HTML code.
The correct recognition can actually be forced by adding a dummy value to the resource's URL like this (see –>jsFiddle docs for more info):
...&dummy=.js
Here is an example that shows how to add the external Google Maps API resource to a jsFiddle (mind the dummy parameter at the very end!):
https://maps.googleapis.com/maps/api/js?sensor=false&dummy=.js
Unfortunately this won't work for you as the MS AJAX URL will fail when additional parameters are appended.
A solution (and currently the safest way to load external resources) is to avoid the External Resources tab altogether and load external code manually in the first line(s) of jsFiddle's HTML window like this:
<script type='text/javascript' src="http://ajax.aspnetcdn.com/ajax/3.5/MicrosoftAjax.js"></script>
Here is your jsFiddle modified to use that method: http://jsfiddle.net/rEzW5/12/
It actually does not do a lot (I did not check what is wrong with the rest of your code), but at least it does not throw JavaScript errors anymore.
Open "Add Resources" section and add the url of your external script...
#Jpsy's approach no longer seems to work (see my comment under his answer).
For me, adding the resource under External Resources also didn't work. (According to the Firefox Debugger, it couldn't find the resource).
The only way I was able to get an external bit of JavaScript code (in my case jquery.backstretch.js) to work, was to use Google to find a Fiddle which used this resource (and worked), then Fork this Fiddle and copy/paste all my code into the HTML, CSS and JavaScript panels. Ugh!
#clayRay, You absolutely went thru a code surgery. Just resolved that by mentioning external source in plain html which in my case is
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
Using External Resources tab didn't help a bit...

Categories

Resources