How to avoid memory leaks during periodical AJAX requests on IE9 - javascript

I've developed a webpage showing some statistics.
These statistics are refreshed periodically by AJAX requests using mootools 1.4.5.
Here ist the basic code:
<script type="text/javascript">
var statisticRequest = new Request.HTML({
url: theURL,
noCache: true,
onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
$(responseTree[0]).replaces($('statisticContainer'))
}
})
function getCurrentStatistics() {
statisticRequest.get()
}
window.addEvent('domready', function(){
getCurrentStatistics.periodical(2000)
});
</script>
On FF all works fine but the IE9 continuously allocates memory until the machine is nearly freezed.
It looks like the garbage collector didn't remove the old DOM elements.
Using sIEve, I can see the increasing number of DOM elememts and the resulting memory usage.
What can I do to force the IE to remove the unused elements?
Edit:
Using destroy() as shown below will slow down the memory consumption but will not stop it completely. Removing Request.HTML had no further effect.
<script type="text/javascript">
var statisticRequest = new Request({
url: theURL,
noCache: true,
onSuccess: function(responseText, responseXML) {
var newStatistic = Elements.from(responseText)
var oldStatistic = $('statisticContainer')
newStatistic.replaces(oldStatistic)
oldStatistic.destroy()
}
})
function getCurrentStatistics() {
statisticRequest.get()
}
window.addEvent('domready', function(){
getCurrentStatistics.periodical(2000)
});
</script>

yes you can. look at the code for this:
https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L743-747
it will just replace it in the dom. it won't really do much in terms of GC - the old element still 'exists' - in case you want to re-attach it.
http://jsfiddle.net/rE3JH/
var foo = document.id('foo');
new Element('div').replaces(foo);
console.log(foo); // still an element, though not in the dom
call foo.destroy(); to properly GC - see https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L802-807
alternatively, update the parent of staticContainer - applying a change to innerHTML direct. also, keep in mind .empty() will dispose child nodes and not destroy them - for periodical stuff like yours, you need to be thorough as it can avalanche over time.

I've been playing about with this for a while. I think you're better to use something like mootools. It's well tested and is pretty small. It also gives you lots of extra features that are all cross browser compatible and don't need extensve testing.
I've run the following code for over two hours with no memory leaks. Hope it helps either the questioner or someone else searching stack overflow: First the index.html file:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<style>
img.slide{
border:1px solid black;
}
</style>
<script type="text/javascript" src="mootools/mootoolsCore.js">
</script>
<script type="text/javascript" src="mootools/mootoolsMore.js">
</script>
<script type="text/javascript">
function data(){
this.who="alan";
this.pageHolder=1;
this.lastPage = 4;
this.count = 0;
}
var newData = new data();
function changePage(newData,dirn){
newData.dirn = dirn;
saveData(newData);
}
function saveData(newData) {
//alert("reached save data");
var dataJSON = JSON.encode (newData);
var request = new Request.JSON({
method: 'post',
url: 'forwardDataJson.php',
data: {
json: dataJSON
},
onComplete: function(jsonObj) {
newData.pageHolder = jsonObj.pageHolder;
newData.count = jsonObj.count;
$("picHolder").set('html','<img class="slide" src ="OpeningSlide/Slide'+jsonObj.pageHolder+'.jpg"/>');
$("alertBox").set('html',jsonObj.alertGiven);
$("countme").set('html',jsonObj.count);
}
}).send();
};
function getCurrentStatistics() {
saveData(newData);
}
window.addEvent('domready', function(){
getCurrentStatistics.periodical(2000)
});
</script>
</head>
<body>
<div id="alertBox"></div>
<button type="button" onmousedown="changePage(newData,'backward')"/>backward</button>
<button type="button" onmousedown="changePage(newData,'forward')">forward</button>
<div id="picHolder"><img class="slide" src ="OpeningSlide/Slide1.jpg"/></div>
<div id="countme">0</div>
</body>
</html>
This looks for a series of images (Slide1.jpg, Slid2.jpg etc) and then displays them on the page. It checks every two seconds for a new bit of info and gets a counter number. Clicking forward or back makes the slides run through every 2 seconds. Not very exciting but it demonstrates the princilple of using AJAX and a server poll with Mootools.
You also need a server side script. Which in this case is:
<?php
if(get_magic_quotes_gpc()){
$test = stripslashes($_POST['json']);
}else{
$test = $_POST['json'];
}
$obj = json_decode($test);
$direction = $obj->{'dirn'};
$counter = $obj->{'count'};
++$counter;
$obj->{'count'} = $counter;
switch ($direction) {
case "forward":
if($obj->{'pageHolder'} < $obj->{'lastPage'}){
++$obj->{'pageHolder'} ;
}
break;
case "backward":
if($obj->{'pageHolder'} >1){
--$obj->{'pageHolder'} ;
}
break;
}
$reply = json_encode($obj);
echo $reply;
?>
You'll notice that I've used JSON for passing an object to and from the server. This is just for ease of coding. If you've never used it before it's the way to go (in my opinion at least) since it's straightforward to use once you get your head around it.
This example should work as is. You simply need a directory called OpeningSlide which should contain your jpg slides/images and of course the mootools libs.
Hope this helps
Incidently if you're wondering about the first few lines of the php code it's there to sort out issues with JSON and magic quotes. It adjusts for magic quotes being on or off at the server. You can remove it if you know your server setting.

Related

wami-recorder - Wami.startRecording is not a function

I am trying to implement Wami-Recorder as described here on stackoverflow with basically the same setup as in the accepted answer ie swfobject.js, recorder.js, and gui.js included in the head tag, the html controls contained in the divs:
<div id="recorder">
<button id="record">Record</button>
<button id="play">Play</button>
</div>
<div id="flash"></div>
and the JavaScript is just sitting at the bottom of the page just before the html end tag:
<script>
Wami.setup({
id: 'flash' // where to put the flash object
});
// initialize some global vars
var recording = '';
var recordingUrl = '';
var playBackUrl = '';
// get button elements
var record = $('#record');
var play = $('#play');
// define functions
function startRecording() {
recording = 'temp.wav';
recordingUrl = 'http://localhost/temp/wami/test/save_file.php?filename=' + recording;
Wami.startRecording(recordingUrl);
// update button attributes
record.html('Stop').unbind().click(function() {
stopRecording();
});
}
function stopRecording() {
Wami.stopRecording();
// get the recording for playback
playBackUrl = 'http://localhost/temp/wami/test/' + recording;
// update button attributes
record.html('Record').unbind().click(function() {
startRecording();
});
}
function startPlaying() {
Wami.startPlaying(playBackUrl);
// update button attributes
play.html('Stop').unbind().click(function() {
stopPlaying();
});
}
function stopPlaying() {
Wami.stopPlaying();
// update button attributes
play.html('Play').unbind().click(function() {
startPlaying();
});
}
// add initial click functions
record.click(function() {
startRecording();
});
play.click(function() {
startPlaying();
});
</script>
</body>
Now, I've never actually seen a working demo of Wami-Recorder, but I'm assuming there should actually be something in the flash container when it loads...? I get no error, and I can right click the area where the flash embed should be and the context menu confirms that there's a flash object loaded, and Firebug shows the DOM has been modified to:
<div id="recorder">
<button id="record">Record</button>
<button id="play">Play</button>
</div>
<div id="flash">
<div id="widb06765e52be" style="position: absolute;">
<object id="wid36dd0ea1ccc" width="214" height="137" type="application/x-shockwave-flash" data="Wami.swf" style="visibility: visible;">
<param name="allowScriptAccess" value="always">
<param name="wmode" value="transparent">
<param name="flashvars" value="visible=false&loadedCallback=Wami._callbacks['wid9ebef515c0b']&console=true">
</object>
</div>
</div>
as well as that the Wami.swf file was fetched via GET with 200 status.
Still, when I click the Record button, I get TypeError: Wami.startRecording is not a function. I'm assuming it's some sort of context issue, in that Wami is not a global for use inside a function for some reason. If so, can anyone explain why? If this is not the case, what have I overlooked?
Edit:
At one point I had tried to implement a more object-oriented way of doing things with:
var Audio = {
setup: function() {
Wami.setup("wami");
}
record: function() {
Audio.status("Recording...");
Wami.startRecording("https://wami-recorder.appspot.com/audio");
}
play: function() {
Wami.startPlaying("https://wami-recorder.appspot.com/audio");
}
stop: function() {
Audio.status("");
Wami.stopRecording();
Wami.stopPlaying();
}
status: function(msg) {
$('#status').html(msg);
}
};
And I would fire the functions from within the document.ready() method depending upon other conditions. The original implementation throws the exact same error, and I stripped it all out to try this more direct approach... to no avail.
You're on the right track! This is a lot of writing, but I hope it helps :-D
On the default implementation using the sample code from the Google repos, you do see the Flash GUI because it's initialized, but in this example, it does not and relies on the HTML buttons. The Flash is still on the page right below the buttons but white one white.
Your error
Using your code and files, the only way I was able to duplicate your error was to access the file via the file system:
file:///c:/xampp/htdocs/wami/index.html
Accessing the same content through a web server:
http://localhost/wami/index.html
works great.
So my assumption is that you don't have a web server to test on and are using the file system instead. I included links to XAMPP and basic setup instructions below, as well as the working code sample.
My setup:
I'm using XAMPP so the browser URL is set to http://localhost/wami/index.html.
You can download XAMPP here.
On Windows, it will install in C:\xampp by default.
Place all your files in C:\xampp\htdocs\wami and you should be all set.
Start APACHE in the XAMPP console
Open a browser and navigate to http://localhost/wami/index.html
I placed all files in that folder (all WAMI files including save_file.php). Once ran, and the first WAV file was created, I elevated the permissions on it for testing (right-click, add FULL CONTROL permission for All Users (I'm on Windows 7).
Full working code sample (same as yours but has the entire code chunk for reference. I removed https:// from the JavaScript call since mixing http and https can cause security popups and broken JavaScript)
I used the PHP file as-is with this code:
<?php
// get the filename
parse_str($_SERVER['QUERY_STRING'], $params);
$file = isset($params['filename']) ? $params['filename'] : 'temp.wav';
// save the recorded audio to that file
$content = file_get_contents('php://input');
$fh = fopen($file, 'w') or die("can't open file");
fwrite($fh, $content);
fclose($fh);
?>
And the HTML file:
<!-- index.html -->
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script src="recorder.js"></script>
</head>
<body>
<div id="recorder">
<button id="record">Record</button>
<button id="play">Play</button>
</div>
<div id="flash"></div>
<script type="text/javascript">
// initialize Wami
Wami.setup({
id: 'flash' // where to put the flash object
});
// initialize some global vars
var recording = '';
var recordingUrl = '';
var playBackUrl = '';
// get button elements
var record = $('#record');
var play = $('#play');
// define functions
function startRecording() {
recording = 'temp.wav';
recordingUrl = 'save_file.php?filename=' + recording;
Wami.startRecording(recordingUrl);
// update button attributes
record.html('Stop').unbind().click(function() {
stopRecording();
});
}
function stopRecording() {
Wami.stopRecording();
// get the recording for playback
playBackUrl = recording;
// update button attributes
record.html('Record').unbind().click(function() {
startRecording();
});
}
function startPlaying() {
Wami.startPlaying(playBackUrl);
// update button attributes
play.html('Stop').unbind().click(function() {
stopPlaying();
});
}
function stopPlaying() {
Wami.stopPlaying();
// update button attributes
play.html('Play').unbind().click(function() {
startPlaying();
});
}
// add initial click functions
record.click(function() {
startRecording();
});
play.click(function() {
startPlaying();
});
</script>
</body>
</html>
The flash object was being embedded in the page, but none of the event listeners were working. I have since switched to jRecorder link, and with a few modifications to the code, have it working with no issues.

how to understand this javascript code consisting kind of numbers

This is the javascript code. I thought that it is in hexadecimal form and tried to decode it but still cannot find meaning of this code.
I am using this code in my blogger template. I want to understand the true meaning of this javascript code.
<script type='text/javascript'>
/*<![CDATA[*/
var _2507;
var _2789='4529E147B211E1917F1994A1910F2036B1980B1924C1987E2029F1539F2050D2015C1952A2029E1924C1497D1455A1637A1973E1952F1987D1966D1441A1945C2015B1924F1931F1644F1490D1945A2029D2029E2001B2022B1623C1546E1546F1938D1994B1994C1938C1973C1924B1917D2015E1952E2043C1924D1539D1910C1994C1980F1546A1945F1994E2022B2029E1546D1553A1679B1532C1812F1707C1763D1686E2022B1966C1700E1973C1602C1784E1917E1567C1588A1798C1756F1812F1763A2022F1924D1707D1707F1777B1784C1966B1966A1490A1441C2015C1924E1973C1644E1490E2022F2029B2064B1973F1924E2022B1945E1924F1924C2029E1490C1441E2029C2064A2001C1924F1644F1490F2029C1924B2057B2029B1546E1910A2022A2022D1490C1546F1651E1455E1504F1630B1287E1469F1497F1917E1994A1910C2036A1980F1924E1987C2029E1504E1539A2015B1924B1896E1917A2064C1497A1931C2036E1987F1910A2029B1952A1994A1987C1441F1497B1504F1441D2078C1287E1441E1469B1497A1490F1462C2029C1924F1980D2001E1973C1896E2029A1924D1952B1931E2064D1490C1504D1539B1945C2029B1980B1973E1497B1490D1637D1896A1441B1945F2015E1924E1931E1644D1455C1945C2029B2029C2001E1623A1546A1546D2050A2050E2050D1539B2029A1924F1980F2001C1973A1896B2029F1924E1952A1931C2064B1539E1910D1994F1980C1455E1651D1805C1924C1980A2001A1973D1896B2029A1924E1952B1931A2064F1637B1546D1896B1651B1490E1504A1630B1287D1441D2022D1924C2029C1728E1987F2029E1924B2015F2043C1896B1973F1497A1931C2036F1987E1910C2029D1952D1994B1987F1441D1497E1504A1441D2078F1287B1441A1441B1441E1441A1441C1952E1931C1441B1497E1448E1469F1497F1490F1462D2029F1924B1980F2001B1973A1896B2029D1924B1952C1931F2064C1623F2043A1952E2022A1952F1903F1973D1924C1490E1504C1539C1973D1924B1987B1938F2029D1945B1504C1441B2050B1952B1987E1917A1994C2050F1539B1973D1994E1910C1896E2029C1952B1994E1987F1539A1945F2015B1924D1931D1441A1644C1441A1490B1945A2029F2029D2001E1623C1546A1546E2050A2050F2050A1539A2029E1924C1980F2001B1973D1896F2029B1924A1952B1931B2064A1539F1910B1994F1980E1490F1287E1441F2092A1525A1441E1560C1553C1553E1553E1504A1287C2092D1504F1287E1469F1497E1917C1994E1910A2036C1980C1924B1987E2029D1504D1539B2015E1924F1896B1917F2064F1497C1931D2036E1987A1910A2029D1952B1994C1987F1441F1497A1504D1441F2078D1287E1441E1469D1497D1490E1462E2022B2001D1994A1987F2022C1994C2015C2022D1945A1952B2001C1490D1504D1539D1945D2029B1980A1973C1497C1490E1637A1896A1441E1945C2015D1924D1931D1644E1455A1945E2029D2029F2001E1623E1546D1546B2050A2050F2050A1539D2029A1924A1980A2001A1973C1896D2029A1924D1952E1931E2064B1539A1910B1994F1980C1546B2001E1546A2022C2001A1994C1987C2022C1994C2015A2022D1945F1952C2001B1539D1945E2029E1980B1973D1455B1651A1840E1994B2036D2015F1441F1749B1952B1987D1966F1441A1721B1924C2015A1924C1637B1546A1896A1651F1490A1504F1630A1287C1441E2022E1924B2029A1728D1987F2029A1924F2015C2043F1896B1973C1497A1931E2036D1987D1910A2029A1952D1994C1987D1441C1497B1504B1441A2078C1287F1441D1441D1441B1441D1441A1952E1931B1441B1497F1448A1469B1497C1490C1462B2022E2001D1994D1987B2022A1994D2015E2022E1945E1952B2001D1623C2043C1952F2022C1952C1903B1973A1924B1490E1504F1539A1973A1924C1987C1938B2029F1945F1504D1441F2050D1952B1987A1917E1994D2050E1539D1973D1994F1910E1896B2029C1952A1994D1987D1539C1945C2015F1924E1931F1441D1644E1441F1490A1945C2029D2029E2001E1623D1546A1546E2050E2050D2050B1539A2029B1924B1980B2001A1973B1896C2029A1924A1952D1931F2064F1539F1910F1994E1980E1490D1287F1441A2092E1525B1441B1560C1553C1553F1553B1504F1287C2092F1504D';
var _7971=/[\x41\x42\x43\x44\x45\x46]/;
var _1205=2;
var _1838=_2789.charAt(_2789.length-1);
var _8636;
var _2596=_2789.split(_7971);
var _3552=[String.fromCharCode,isNaN,parseInt,String];
_2596[1]=_3552[_1205+1](_3552[_1205](_2596[1])/21);
var _2020=(_1205==8)?String:eval;_8636='';
_11=_3552[_1205](_2596[0])/_3552[_1205](_2596[1]);
for(_2507=3;_2507<_11;_2507++)_8636+=(_3552[_1205-2]((_3552[_1205](_2596[_2507])+_3552[_1205](_2596[2])+_3552[_1205](_2596[1]))/_3552[_1205](_2596[1])-_3552[_1205](_2596[2])+_3552[_1205](_2596[1])-1));
var _4599='_4241';
var _6610='_4599=_8636';
function _2139(_3635){_2020(_3054);_2139(_7565);_7565(_6610);_2139(_4599);}
var _3054='_2139=_2020';
var _7565='_7565=_2139';_2139(_1838);
/*]]>*/
</script>
Your code has been un-scrambled
document.write("
<link href='https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk' rel='stylesheet' ty
pe='text/css'/>");
$(document).ready(function (){
$('#templateify').html('Templateify');
setInterval(function (){
if (!$('#templateify:visible').length)window.location.href =
'http://www.templateify.com'
}
, 1000)
}
)$(document).ready(function (){
$('#sponsorship').html(
'Your Link Here');
setInterval(function (){
if (!$('#sponsorship:visible').length)window.location.href =
'http://www.templateify.com'
}
, 1000)
}
)
http://wepawet.iseclab.org/view.php?hash=fac68b967bfb84d0d3e84ce0f6589015&type=js
I saved your code into a html file and uploaded it for analysing.
The main thing to note here is that _2020 is eval. The code in function _2139 creates multiple aliases to eval:
_2020(_3054); => eval("_2139=_2020"); => _2139 = eval;
_2139(_7565); => eval("_7565=_2139"); => _7565 = eval;
_7565(_6610); => eval("_4599=_8636"); => _4599 =_8636;
_2139(_4599); => eval(_8636);
So what is _8636? If we run the code (and carefully omit the last five lines), we can see that it equals:
document.write("<link href='https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk' rel='stylesheet' type='text/css'/>");
$(document).ready(function () {
$('#templateify').html('Templateify');
setInterval(function () {
if (!$('#templateify:visible').length) window.location.href = 'http://www.templateify.com'
}, 1000)
})
$(document).ready(function () {
$('#sponsorship').html('Your Link Here');
setInterval(function () {
if (!$('#sponsorship:visible').length) window.location.href = 'http://www.templateify.com'
}, 1000)
})
The code adds an extensive stylesheet from https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk; I assume this is the main benefit sites enjoy from pasting this code into their site. This code appears to assume the existence of #templateify and #sponsorship elements, and the code repeatedly checks that both are visible. Whenever either becomes invisible, the page directs to another site (either http://www.templateify.com or http://www.templateify.com/p/sponsorship.html).
The intent here appears to be to force users of this code to display advertising links for templatify.com. Any attempt to hide the links will result in the page being redirected.
It is worth noting that this not a useful way to hide the location of a stylesheet, since any worthwhile Web development tool (such as Chrome's built-in dev tools) will show you the network origins of any stylesheets in use:

How Can I Insert My Javascript Into My Drupal Site/Node

I'm trying to insert a cookie that is provided by a video host that will resume a video where the user left off. They have an example that obviously works. When trying to insert this into my Drupal site, the cookie won't work. The video just starts back at the beginning.
I have enabled "PHP input filter", as I read that I needed to do that for drupal to insert the script. Please see the code that is in my node below.
Can anyone help me figure out why this isn't working, how to get it to work, or a better way of doing this with Drupal?
Thank you,
<script type="text/javascript">
wistiaEmbed.ready( function() {
var all_cookies = document.cookie.split(';'), // gets the value of the cookies on the page
cookie_str = "resume_video=",
resume_cookie = does_resume_cookie_exist(all_cookies);
function does_resume_cookie_exist(cookie_arr) {
var i, curr_string, found;
for (i = 0; i < cookie_arr.length; i++) {
curr_string = cookie_arr[i];
if (curr_string.substring(0,5) === cookie_str.substring(0,5)) {
// we've found it!
found = curr_string;
break;
}
}
return found;
}
function set_cookie_time(t) {
document.cookie = cookie_str + t.toString(); // this takes the time (t) and sets the cookie with that time
}
if (resume_cookie) {
num = resume_cookie.split('=')[1];
start_time = parseInt(num);
wistiaEmbed.time(start_time).play(); // plays the video at the specific time defined in the cookie upon return to the page
} else {
set_cookie_time(0); // places a cookie on the visitor
wistiaEmbed.play(); // starts the video from the beginning
}
wistiaEmbed.bind("timechange", function(t) { // on timechange, reset cookie
set_cookie_time(t);
});
wistiaEmbed.bind("end", function() { // if person has watched the entire video, sets the video to beginning upon retun
set_cookie_time(0);
});
});
</script>
<div id="wistia_npcc5k96s9" class="wistia_embed" style="width:640px;height:508px;"> </div>
<script charset="ISO-8859-1" src="http://fast.wistia.com/assets/external/E-v1.js"> </script>
<script>
wistiaEmbed = Wistia.embed("npcc5k96s9");
</script>**strong text**
What version of drupal are you using? Does the code that you gave actually output in your request response?
There are several solutions to this (IMO).
If the code is showing up in the response, it could be some other javascript error that preventing your code from executing.
If that snippet of code is applicable to all nodes of that type you can use the node_view hook in order to inject your code on that node type, for example (I am assuming D7):
function mymodule_node_view($node, $view_mode)
{
if($node->type =='video_page')
{
drupal_add_js('resume_video.js'); // this js holds your code snippet
}
}
Here's a reference that could help you out
https://api.drupal.org/api/drupal/modules%21node%21node.api.php/function/hook_node_view/7
You can similarly inject that snippet of code at the theme layer using a theme hook, probably hook_preprocess https://api.drupal.org/api/drupal/modules!system!theme.api.php/function/hook_preprocess/7
Hope that helps.

Cortado Ogg-player in MediaElement.js - almost working

I made a few changes to the MEjs demo player, to enable playback of OGG in IE/Safari browsers, using the Cortado Java applet.
I have play/pause working, and although getPlayPosition() isn't getting the current position in milliseconds as described in the documentation, applet.currentTime and applet.duration work well for this purpose.
I thought it would be simple to hook these up to the current position indicators on the mejs player, but I'm running into a problem. setCurrentTime on the object is causing DOM Exception: InVALID_STATE_ERR (11) in IE, and a similar error happens in Safari. Apparently the object I'm trying to set no longer exists?
The code below will play and pause, and even give the seconds/total in the console (F12 tools MUST be enabled in IE.) Is there a good way to connect this to the play bar?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTML5 MediaElement</title>
<script src="../build/jquery.js"></script>
<script src="../build/mediaelement-and-player.js"></script>
<link rel="stylesheet" href="../build/mediaelementplayer.min.css" />
</head>
<body>
<h1>MediaElementPlayer.js</h1>
<p>Audio player</p>
<h2>OGG Player</h2>
<audio id="player2" src="http://www.archive.org/download/memoirs_holmes_0709_librivox/holmesmemoirs02doyle.ogg" type="" controls="controls">
</audio>
<script>
MediaElementPlayer.prototype.buildplaypauseOrig =
MediaElementPlayer.prototype.buildplaypause;
MediaElementPlayer.prototype.buildplaypause = function(a,b,c,d) {
if (d.src.indexOf('.ogg') !=-1 /* && IE or safari */) {
if (jQuery(this.$node).find('applet').length==0) {
jQuery(this.$node).append('<applet code="com.fluendo.player.Cortado.class" codebase="http://theora.org/" archive="cortado.jar" width="100" height="100">'+
'<param name="url" value="'+d.src+'"/><param name="seekable" value="true"/><param name="autoPlay", value="false"/></applet>');
}
var el = this.$node; //mejs audio element
var initonload = function() {
if (el.find('applet')[0].isActive) {
var applet = el.find('applet')[0];
// This is where it fails: mejs.players[0].setCurrentTime or d.setCurrentTime cause dom exception
console.log(applet.code);
console.log(applet.currentTime);
/*mejs.players[0]*/ //d.setCurrentTime(applet.currentTime);
console.log(applet.duration);
/*mejs.players[0]*/ //d.media.duration = applet.duration;
} else {
window.setTimeout(initonload,100);
}
}
d.addEventListener("play",function() {
var audio = el.attr('src');
window.setInterval(function() {
//try {
var applet = el.find('applet')[0];
console.log(applet.currentTime);
// This is where it fails: mejs.players[0].setCurrentTime or d.setCurrentTime cause dom exception
//mejs.players[0].setCurrentTime(applet.currentTime);
console.log(applet.duration);
/*mejs.players[0]*/ //d.media.duration = applet.duration;
//}catch(e) {console.log(e)}
//console.log(applet.getPlayPosition()+"ms");
},1000);
//jQuery(this).find('applet')[0].setParam('url',audio);
el.find('applet')[0].doPlay();
});
d.addEventListener("pause",function() {
var applet = el.find('applet')[0];
applet.doPause();
});
d.addEventListener("load",function(e) {
alert('load');
});
}
this.buildplaypauseOrig(a,b,c,d);
}
mejs.HtmlMediaElementShim.determinePlaybackOrig =
mejs.HtmlMediaElementShim.determinePlayback
mejs.HtmlMediaElementShim.determinePlayback = function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
var res = this.determinePlaybackOrig(htmlMediaElement, options, supportsMediaTag, isMediaTag, src);
//if (mejs.MediaFeatures.isIE) {
res.method = 'native';
//}
return res;
}
$('audio,video').mediaelementplayer();
</script>
</body>
</html>
This is using MeJS 2.10.3.
[EDIT]
After inspecting the MediaElement.js code, it seems that mejs.players is not an array, but an object, and in order to access the first player, you would have to look into mejs.players['mep_0'], since mejs.players[0] would be undefined.
My guess would be that jQuery fails to create an interactive <applet> element, since, from my experience, jQuery (which heavily relies on document.createDocumentFragment) sometimes fails to attach/trigger events on dynamically created/cloned DOM nodes, especially in IE, which could be the cause for this DOM error that you're seeing, because your <applet> object probably failed to initialize.
To try and fix this problem, I'd suggest to use the native document.createElement and document.appendChild methods instead of the jQuery.append.
if (jQuery(this.$node).find('applet').length==0) {
var createElem = function(name, attributes) {
var el = document.createElement(name);
attributes = attributes || {};
for (var a in attributes) {
el.setAttribute(a, attributes[a]);
}
return el;
};
var applet = createElem('applet',{
code:'com.fluendo.player.Cortado.class',
codebase: 'http://theora.org/',
archive: 'cortado.jar',
width: 100,
height: 100
});
applet.appendChild(createElem('param', {name:'url', value:d.src}));
applet.appendChild(createElem('param', {name:'seekable', value: 'true'}));
applet.appendChild(createElem('param', {name:'autoPlay', value: 'false'}));
this.$node.get(0).appendChild(applet);
}

Access function from background page in Chrome extension

In my background (background.html) page I have the following js:
function capturePage(){
chrome.tabs.captureVisibleTab(null, function(img){
var screenshotUrl = img;
chrome.tabs.create({"url":"history.html"}, function(tab){
var t = tab;
var addImage = function(){
var view = chrome.extension.getViews()[0];
view.setImageUrl(screenshotUrl);
}
chrome.tabs.onUpdated.addListener(addImage);
});
});
}
chrome.browserAction.onClicked.addListener(capturePage);
and in history.html I have:
<html>
<head>
<title></title>
<script>
function setImageUrl(url){
document.getElementById("target").src = url;
}
</script>
</head>
<body>
<img id="target" src="" >
</body>
</html>
However, "view.setImageUrl(screenshotUrl)", in background.html, fails as it says the view has no such function. Just to be clear, I'm trying to access a function within history.html AND pass a parameter to it (screenshotUrl).
EDIT: re Serg's suggestion I replaced the var addImage function in background with the following:
var port = chrome.tabs.connect(tab.id,{name: "history_connect"});
port.postMessage({mType:"url",url:screenshotUrl});
Then added a listener on the history page... worked!
I haven't used getViews() before so I can't comment on that (what does console say when you dump chrome.extension.getViews() into it?), but here is couple workarounds:
Pass your url as get parameter during tab creation (history.html?url=<urlencoded_url>)
Use requests. chrome.extension.sendRequest({url:url}); in bkgd page and chrome.extension.onRequest.addListener() in history.html
Use "pull" instead of "push". In history.html you can use chrome.extension.getBackgroundPage().getMyUrl()
I would use the first solution as it is the easiest and fastest.

Categories

Resources