-1

My question is almost similar in nature to one posted here. I am loading HTML content from my database that contains a third party script. As i have found out Durandal does not load that script or rather the view will not compose that element. My html content(from 3rd party) looks:

<p id="oilChart"><script src="http://www.oil-price.net/TABLE2/gen.php?lang=en" type="text/javascript">
</script>
<noscript> &amp;amp;amp;amp;lt;a href="http://www.oil-  price.net/dashboard.php?lang=en#TABLE2" mce_href="http://www.oil-price.net/dashboard.php?lang=en#TABLE2"&amp;amp;amp;amp;gt;To get the oil price, please enable Javascript.&amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;gt;&amp;amp;amp;amp;lt;br     /&amp;amp;amp;amp;gt; </noscript>
</p>

All my other scripts are referenced in the main.js. I have tried to reference it that way and then use durandal's compositionComplete to link with the id I have specified in the content. It did not work. Is there another way of looking at it and doing it. Thanks for you help in advance.

Community
  • 1
  • 1
mboko
  • 359
  • 6
  • 16

4 Answers4

2

Durandal, as you pointed out, will ignore the script tag in views. They are loaded only from the index.html (or its equivalent).

Are you able to reference the script (and noscript) ahead of time, putting them instead in the index.html file? In other words, do they have to be loaded dynamically?

On a side note: What do you mean by "All my other scripts are referenced in the main.js"? Do you mean that they are path configurations for RequireJS? Or did you mean to say that they are referenced in the index.html file (or its equivalent)?

  • 1
    To add to Erics answer here you can use your main.js config to let require know you want this script available later and load it there using the async plugin so it isn't loaded before needed. Then just add it to dependencies in your view model. – PW Kad Feb 16 '15 at 17:43
  • Hi Eric. When I reference the script ahead of time it displays. My challenge now is to display it when I load the appropriate view. My app has only one view besides the shell where I am composing all the data from the DB. it's a CMS like. To clarify on the side note: Yes I mean't they are path configurations for RequireJS. – mboko Feb 17 '15 at 07:01
  • @PWKad That sounds interesting. I am not familiar with the async. Will look into it now. Is it available via Nuget?. I think if I can use it as you explain it will work. Side Note: I have a recaptcha(https://www.google.com/recaptcha/api/js/recaptcha_ajax) path reference in my main.js that works fine without the async plugin - i do it server side. – mboko Feb 17 '15 at 07:17
  • 1
    @mboko Hmmm. I was just studying the website from which you obtained your dashboard, and it seems to me that this will need to be rendered server-side, and then pushed down to the client. I'm just wondering if it would be possible for you to access a web service for crude oil, and build your own dashboard (this site offers a free web service for oil: http://www.freewebservicesx.com/CrudeOilPrice.aspx) client-side? You would have more control: It will always be easier to swap out the data source than to swap out a proprietary dashboard. –  Feb 17 '15 at 07:43
  • 1
    @EricTaylor Thanks for that pointer. I also found an answer here: http://stackoverflow.com/questions/28052824/durandal-js-and-google-plus-sign-in-javascript-api you provided, which echos what PW said above with regards to async. I am trying that now: define('oilprice', ['async!http://www.oil-price.net/TABLE2/gen.php?lang=en'], function() { return; }); – mboko Feb 17 '15 at 08:25
  • @mboko Yes you don't have to use the Async plugin but if you do not it will eager load it up front. – PW Kad Feb 17 '15 at 16:00
  • @mboko I just posted a new answer. It is significantly different from my first answer, which is why I chose to post a new answer instead. –  Feb 18 '15 at 06:36
1

I have further investigated an answer to the question posed by the OP.

I took the following steps:

  • Followed Erikas Pliauksta's advice and created a custom KO binding.
  • Modified the binding slightly to take a boolean flag: false disables the binding, and true enables the binding. This allows me to time the rendering of the HTML with compositionComplete.

Here's a screenshot of what I get back in console:

enter image description here

Now, a search on SO yielded up this post. Bascially, if this script is utilizing document.write, or its equivalent, it won't work.

I would go back to my original recommendation of hitting a web service in order to surface the crude oil data instead of trying to incorporate third-party JavaScript, as they call it.

Community
  • 1
  • 1
  • 1
    Thanks for confirming this Eric. Yes I get the same console screenshot as above using the custom KO binding. At the moment it seems the way to do it would be as you recommended earlier - web service. Side not: OOI I will also try the custom KO binding for another 3rd party script which doesn't use document.write. Thanks for the input – mboko Feb 18 '15 at 07:47
0

You can use knockout custom bindings:

ko.bindingHandlers.oilPrice = {
  update: function( element, valueAccessor, allBindingsAccessor, viewModel, bindingContext){
  $(element).html('<script src="http://www.oil-price.net/TABLE2/gen.php?lang=en" type="text/javascript"></script><noscript> &amp;amp;amp;amp;lt;a href="http://www.oil-  price.net/dashboard.php?lang=en#TABLE2" mce_href="http://www.oil-price.net/dashboard.php?lang=en#TABLE2"&amp;amp;amp;amp;gt;To get the oil price, please enable Javascript.&amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;gt;&amp;amp;amp;amp;lt;br     /&amp;amp;amp;amp;gt; </noscript>');
  }
};

Use it in your html:

<p><span data-bind="oilPrice"></span>

UPDATE if you are using knockout 2.2 custom bindings have to contain value:

<p><span data-bind="oilPrice:'value'"></span>

for knockout version 3.2:

<p><span data-bind="oilPrice"></span>

your script rendered:

enter image description here

Erikas Pliauksta
  • 1,402
  • 1
  • 14
  • 22
  • 1
    Have you actually tried this? You're still rendering the script tag into the view, where the logic of Durandal will ignore it. Rendering the script tag into the view isn't the OP's problem. For that, he could just manually type it in and skip the custom Knockout binding. The issue is whether a script tag in a view can be utilized. –  Feb 17 '15 at 06:29
  • Yes, I've tried this: http://stackoverflow.com/questions/20559674/durundal-google-translate/20590626#20590626 The script tag gets ignored during DOM initialization. Once DOM is initialized ko.custom bindings can amend it this way. – Erikas Pliauksta Feb 17 '15 at 07:56
  • I'm curious about this myself. Am I to understand that the custom Knockout binding is a solution to this problem? If so, I will vote your answer up! –  Feb 17 '15 at 07:59
  • the use of custom bindings - I have seen it somewhere to that effect I have tried the above code it didn't work for me. Are you missing something in the data-bind tag? – mboko Feb 17 '15 at 08:09
  • can you check the resulting html for that script tag. if it's not there, can you check for any errors. firefox reports durandal errors better than chrome. – Erikas Pliauksta Feb 17 '15 at 09:29
  • @Erikas Pliauksta hhmm did u run this and it worked for u as is?does that html code u provided work as is?

    – mboko Feb 17 '15 at 11:12
  • yes, this is correct ko custom binding: http://jsfiddle.net/18888y1n/ it's difficult to see what is not working in your case. try rendering some simple html in custom binding first and see that works. then try adding script tags gradually. – Erikas Pliauksta Feb 17 '15 at 12:15
  • @ErikasPliauksta I'm not sure how the jsFiddle you reference in your comments relates to the OP's question. It is well established that the HTML binding can inject HTML. But under Durandal, treatment of the script tag is a special case. If it were simply a matter of injecting the script tag via a custom binding, that should work out of a jsFiddle as well. –  Feb 18 '15 at 05:47
  • @EricTaylor the question in the previous comment was wherever I provided the valid HTML for ko binding. I provided jsFiddle to prove was correct. – Erikas Pliauksta Feb 18 '15 at 06:59
  • @ErikasPliauksta I down-voted your answer, but upon reconsideration, I wish to reverse my position. The fact that I got back the errors that I did in the console means that your approach is sound. The problem here is that the *server-side script* is ill-behaved. If you modify your post to reflect a caveat that, while your advice is sound, it will not overcome an ill-behaved script, I will vote your answer back up. I would encourage the other down-voter to do the same. My apologies to you, and thanks for the great answer! –  Feb 18 '15 at 08:03
  • @EricTaylor I am not particularly bothered by the fact that my answer was down-graded. I did my best to help mboko and I know I have provided correct assistance to the author of this question. Your solution may have assisted as well and I am very happy for that. I am not sure if it is ethical to judge negatively the alternative solutions to questions you've been answering as well. But I can live with that. Good luck to everyone here. – Erikas Pliauksta Feb 18 '15 at 22:42
  • @ErikasPliauksta For the record, I wasn't judging your answer negatively *because* it was an alternative solution. I was questioning, as was others, whether it was a valid solution at all. Your example involved HTML that did not include a `script` tag, and I saw no *direct* answer that revolved specifically around the `script` tag. I still feel that you should modify your answer as I suggested, lest others confuse an ill-behaved server-side script with your perfectly valid answer. –  Feb 18 '15 at 23:16
  • @ErikasPliauksta I have added document.write(unescape(''%3Cscript src..)) in my handler. the HTML is as you stated. The dashboard is displayed but nothing else displays. Like everything is broken. I think I am close to fixing it. Can you think of anything that I can change to make it work?Thanks – mboko Feb 19 '15 at 12:20
0

After much research I found my answer finally. All I had to do was to use an iframe which loads my script. I replaced this:

<p id="oilChart"><script src="http://www.oil-price.net/TABLE2/gen.php?lang=en" type="text/javascript"></script></p>

with:

<iframe style ="border: none;height: 235px" srcdoc="<html lang='en'><body><script src='http://www.oil-price.net/TABLE2/gen.php?lang=en'></script></body></html>"><iframe>

Thanks for all the ideas. Learnt a lot- from possibilities of using async plugin to custom Ko handlers.

mboko
  • 359
  • 6
  • 16
  • good solution, that works in this case. I actually tried to complete it with custom Ko bindings, but could find enough time yesterday. – Erikas Pliauksta Feb 20 '15 at 21:58