PDA

View Full Version : js not modifying tags in external files



tonybabb
11-30-2013, 11:29 AM
Hi John,

Several months ago you kindly helped me create a js script that would play a sound file and change the background color in a smartphone app and it has worked fine. As a reminder a smartphone app typically has a single physical index.html file that contains multiple pages and in this environment the js script correctly plays a sound and changes the background color.

The app has grown quite large (over 1,100 lines with probably another 1,000+ to be added) and is having, I think, memory management problems causing it to sometimes not play sound files and occasionally to freeze. I have been advised that I should split the index.html file into multiple smaller html files to try and fix this problem. So I did this and now find that the original js script is not displaying the Spanish phrases correctly and is not playing the associated sound file.

I created a short demo app to show the problem. The menu page contains two entries, "Arrest" points to a page that is part of index.html and correctly displays the phrases and plays sounds, the "Age weight & height" points to a separate external html file and does not display the phrase correctly or play the sound. The web version of the app can be seen at http://www.lawenforcementspanish.com/mledemo2 (http://www.lawenforcementspanish.com/mledemo2).

I took a look at the Chrome element inspector for the Spanish phrases and it appears that the js additions shown below are not added to the tags in the separate file:

<img id="jp_poster_0" style="width: 0px; height: 0px; display: none;"><audio id="jp_audio_0" preload="metadata" src="http://www.lawenforcementspanish.com/mledemo2/test.mp3"></audio> to the tags is not being done in the separate file.

Below is the source code for a phrase in the "arrest" page which works correctly

<div class="wrapper">
<a class="formal spanish ui-link" data-trigger="arr1f" href="test.mp3" id="jp_jplayer_0" style="width: 0px; height: 0px;"><img id="jp_poster_0" style="width: 0px; height: 0px; display: none;"><audio id="jp_audio_0" preload="metadata" src="http://www.lawenforcementspanish.com/mledemo2/test.mp3"></audio></a>
<a class="formal trigger ui-link" id="arr1f" href="#" data-playing="false" style="background-color: rgb(255, 255, 255);">F: Está bajo arresto</a>
<div class="spacer"></div>
<a class="informal spanish ui-link" data-trigger="arr1i" href="ringding.mp3" id="jp_jplayer_1" style="width: 0px; height: 0px;"><img id="jp_poster_1" style="width: 0px; height: 0px; display: none;"><audio id="jp_audio_1" preload="metadata" src="http://www.lawenforcementspanish.com/mledemo2/ringding.mp3"></audio></a>
<a class="informal trigger ui-link" id="arr1i" href="#">I: Informal Spanish phrase</a>
</div>
Below is the source code for a phrase in the "Age weight and height" page which doesn't display correctly or play sounds:

<div class="wrapper">
<a class="formal spanish ui-link" data-trigger="howoldf" href="test.mp3">F: Cuántos años tiene?</a>
<a class="formal trigger ui-link" id="howoldf" href="#">F: Cuántos años tiene?</a>
<div class="spacer"></div>
<a class="informal spanish ui-link" data-trigger="howoldi" href="ringding.mp3">I: Cuántos años tienes?</a>
<a class="informal trigger ui-link" id="howoldi" href="#">I: Cuántos años tienes?</a>
</div>

When I just look at the source code, not using the inspector I don't see the additional tags in either page so I'm assuming it's being done by js. I don't know what is creating the additional [img] and [Audio] tags but that is the only difference I can see between the two pages.

Also, if js is adding [Audio] tags does this mean it supports playing the [Audio] tag?

Thanks for any insight or direction you can provide.

Tony Babb

jscheuer1
12-02-2013, 12:41 PM
I can't see/figure out the mechanism whereby you are changing content, what is it? Is it some sort of AJAX?

tonybabb
12-02-2013, 12:57 PM
Hi John,
I don't know what's changing the html, could be Ajax but I really don't know. From the ID names it looks like it's related to jPlayer. It's odd that when I do a View Page Source the two lines of code don't show, but it does show in the element inspector. Is there something I can do to help track what is making the change?

Thanks,

Tony

jscheuer1
12-02-2013, 02:11 PM
That's not what I was asking. Yes, jPlayer is initializing the audio and thereby adding the audio tags for those browsers that support them (It adds Flash code for those that do not).

But that's not content, that's code. The content is what you see on the screen. When you click on Arrest, you see its content from that page, when you click on Age, Weight, Height, you see some other content from another page. How is this content changing? I don't see and haven't been able yet to figure out the mechanism by which this happens. If I actually go to subAge.html, it works just fine. But when I click on it from the main page it doesn't. So it seems as though subAge.html is being loaded into the main page, but I don't see how that's happening. Do you know?

jscheuer1
12-02-2013, 03:32 PM
OK, I've researched this a bit more and jQuery Mobile automatically uses AJAX for same domain page transitions. If you want to override that, use the rel="external" attribute on the link. For example:


<li><a href="subAge.html" rel="external">Age, Weight & Height</a></li>

The problem you've been having is that since the audio is initialized on page load, once AJAX brings in new audio content, it's too late. If there were a callback, we could use that. But there doesn't appear to be one mentioned in the docs. I know there is one (there always is in jQuery AJAX), but accessing it without overriding what jQuery Mobile is using it for (the docs imply that jQuery Mobile is using it for certain things, like page transitions (slide) and URL mapping), may be tricky. If we could use it we could initialize the new content once it arrives. But as long as it's OK to actually switch to the subAge.html page, using the rel="external" as mentioned above will allow that page to fully load on its own and thereby initialize as desired.

jscheuer1
12-02-2013, 05:48 PM
We might be able to keep the jQuery Mobile way of automatically loading same domain pages via AJAX. I've looked into this further and discovered there is a callback built in. For example we can do (on the 'top' page):


$( document ).delegate("#age", "pageinit", function() {
//initialize the audio and/or font size changes, etc. here
});

And that code (represented above as a comment, to do anything we will have to put real code there) will fire after the external page with the id 'age' is loaded.

In order to take advantage of that we would need to change the code that already initializes the sound a little so that it could be more easily reused. And it would probably have to add a flag (like a class) to each audio link it has already initialized so as not to initialize the same one(s) more than once.

Hopefully one such call could be used to initialize the content on multiple pages via comma separated ids where there is currently the single one, that would make it relatively easy to delegate the pageinit for as many pages as needed, provided they all require the same treatment. But if not, code could be written to do it for multiple pages.

I'm also thinking that the font change code might be best kept off of the external page and used exclusively from the 'top' page to keep it active at all times without duplicating it. A cookie or variable may have to be set so that when an external page is imported it can know whether or not the font was already changed and respond accordingly.

tonybabb
12-02-2013, 10:45 PM
Hi John,

Thank you so much for your time on this. I tried the rel="external" on the link and that worked, the transition from menu to the Age page worked, the phrases were formatted correctly and the sound played. So do I need to concern myself with the callback functions you mentioned?
The only other change I made was at the bottom of the page where there's a "Back" button to take the user to the main menu, on the external page I changed the call from

<a href="#" data-rel="back" data-icon="back">Back</a>
to be

<a href="index.html" rel="external">Back to Main Menu</a>
and that seems to work correctly.

Re the font change code I can move it to the main menu page with a link from there. In fact I have been thinking I need to change that anyway so that the selected size is stored in local storage on the smartphone and then will display the selected font size when the user next launches the app. (I haven't reached that part of my javascript book and online course yet but I know it can be done !!)

So, if you agree I don't need to add the callback code than next step for me is to add back, as external files, the content I previously removed and see if moving content to external pages fixes the original instability issues when index.html became larger than about 1,100 lines.

Thanks so much for your time and expertise, it is truly appreciated.

Tony

jscheuer1
12-03-2013, 01:44 AM
That's what I was wondering. Does it need to be an AJAX call, or can it be an entirely separate page? And implied in that is - Can either of these choices work?

From what you said, putting everything on a single page was causing a problem. And earlier you said that everything had to be on one page*, or that it was better if it was.

Whatever the case, the bottom line is if it works or not when turned into an app. Having the other pages truly external or imported via AJAX might make a difference there, or it might be that neither works. Or it might be that either works.

So basically, if it works, it's OK.


*Or was that in one folder? If simply being all in one folder is the requirement, then theoretically, either solution should be workable and it would only be a matter of which is more efficient and/or has the best look and feel. It might happen that one is more efficient while the other has a better look and feel, at which point you would need to choose which you are going for, efficiency or look and feel. It's hard to know for sure, but I would guess that having it actually load the page (rel="external") would be more efficient, loading faster with less frills, while using AJAX would have a better look and feel, but take a little longer to transition (load each page).

But the breakdown could be different than I anticipate.

To answer your question though, if it works with rel="external", yes you can use that and ignore the other approach. And the way you are handling the back link (rel="external") is fine, and in fact how it should be done if you use rel="external" to get to the Age page.

tonybabb
12-08-2013, 01:18 PM
Hi John,
I've continued testing the Spanish phrasebook app by breaking up the large index.html page into multiple separate pages, one for each subject and everything seemed to be working but I think I'm hitting the same or a similar memory problem I had before(this is just a guess that it's a memory problem). I should add I also moved the js you gave me to play sounds to an external js file.

I am finding that the app runs correctly on my PC but on my droid phone it fails after I have made 30 taps on different phrases(each tap plays a sound file and changes the background color). By "fail" I mean it does not play the sound file, but the background color changes. The fail occurs after tapping on 30 different phrases.

I have tried tapping on the phrases in one page sequentially and it failed on the 30th. I started a little lower in the list and it again failed after 30 different phrases were tapped. I also tried tapping several phrases on one page and then continued onto another page and again it failed on the 30th phrase. I also repeatedly tapped more than 30 times on 5 different phrases and it worked consistently but when I then continued on to different phrases it failed on the 30th different phrase. So, it looks like something is happening when I tap a new phrase and it accumulates until it runs out of a resource on the 30th phrase.

I know you don't do smartphones but was wondering if there's anything in the sound playing js you gave me that could possibly be using resources and then not releasing them? This is a bit of a long shot I know. Could I add an alert displaying anything helpful? I am able to run the app on the smartphone and test it remotely from my PC and can see the log and elements displayed.

Thank you for any suggestions you may have.

Tony

jscheuer1
12-08-2013, 03:25 PM
Once this is converted to an app, the memory management is handled by the app. In ordinary javascript, resources are released once the page unloads, often sooner.

Anyways, you obviously have tested this various ways. What do you have to do in between tests to clear the memory? Do you have to turn off the android?

tonybabb
12-08-2013, 11:02 PM
Hi John,

Please see my next post

Tony

tonybabb
12-09-2013, 11:11 AM
Hi John,

In smartphones when you exit an app the app actually stays in memory until the memory is needed by some other app, this has the effect of speeding up load time when I relaunch the app as it may still be in memory. With my Samsung Galaxy S4, and probably other droids, I hold down a button for several seconds and it shows me all apps that are in memory and I can remove them by swiping them to the left to clear memory. This is how I removed the app when it stopped responding and I have consistently started my tests with my app being the only one in memory.

It seemed odd to me that the background color changed (initially to yellow then back to white) as if the sound had played but the sound didn't actually play.

**UPDATE** I just downloaded an app that shows memory usage. It shows my app had a peak usage of 117MB and I have 700+MB available so maybe it's not running out of memory but something else.....sigh

** UPDATE 2** I thought I'd reduce all the categories of phrases to minimize complexity and see where it fails so I created www.lawenforcementspanish.com/mledemo3 (http://www.lawenforcementspanish.com/mledemo3)which contains two categories, one (Scenario 1) is included in the index.html file and the other (Topic 1) is in an external file. I created 30 Spanish phrases in Scenario 1 and 4 Spanish phrases in Topic 1. The sounds play correctly on my PC. I then uploaded/ downloaded to my droid. This time the Scenario 1 failed to play any sounds, the background color changed briefly to yellow and then back to white. I used two sound files "Ay Caramba" for the odd numbered Spanish phrases and "Ring Ding" for the even numbered Spanish phrases. "Ring Ding" plays on the PC for about 10 seconds but on my phone I noticed that the background color changes to yellow for maybe a second and then back to white. I don't really understand your js code but does this mean jplayer is perhaps reporting it has played the sound when it didn't even start or having some other sort of problem? Would it be worth trying something other than jplayer to play the sounds?

Thanks again,

Tony