Is anyone doing this? I have a script which works in the console, but has serious problems when I embed it in the page. The main issue is that the location of that information (a comment after the </body> tag but before the </html> tag) is very difficult to identify cleanly and access in the document object.
What does your javascript you are executing in the console look like?
-Sam
Something like this:
function SessionDetails() { commentStart = "Content Deployed: " mosStart = "Session MOS: " mosEnd = "/" promoStart = "Promo:" promoEnd = ")" dtext = document.documentElement.outerHTML comment = dtext.substring(dtext.indexOf(commentStart) + commentStart.length, dtext.length) this.mos = this.comment.substring(this.comment.indexOf(mosStart) + mosStart.length, this.comment.length) this.mos = Number(this.mos.substring(0, this.mos.indexOf(mosEnd)).trim()) this.promo = this.comment.substring(this.comment.indexOf(promoStart) + promoStart.length, this.comment.length) this.promo = Number(this.promo.substring(0, this.promo.indexOf(promoEnd)).trim().substring(1, this.promo.length)) }
Hi Gawain, how about something like this (assuming you don't mind using a little jquery):
$(function() {
$("body").contents().filter(function(){
return this.nodeType == 8;
}).each(function(i, e){
if (e.nodeValue.indexOf("Content Deployed") > -1) { console.log(e.nodeValue) };
});
}); And then you can iterate over that to find what you're looking for.
The problem you are probably having is that your code runs before the html is loaded on the page. It works correctly in your console, because you manually run it after the DOM is loaded. To solve this problem you can use jQuery to wait for the page to finish loading.
tnew.$(document).ready(function() {
// code here will run after the dom has completed loading.
Ah, of course.
I'll give that a shot: couldn't figure out a way to actually grab it as a node through regular JS. Is that only looking at the <body> though? This comment is outside of the body.
This really piqued my interest and I went digging a little deeper into the StackOverflow question that I think Josh came from :-).
I'm not sure _why_ the body selector works, but you can see that it does with a console.log($("body")); However, the SO question indicates that this isn't completely reliable, and you should use $("*") instead. Then the question becomes how do you filter down to the correct comment. We could use .last() on the body selector, but this doesn't work with the wildcard, so I think Josh made the best guess with indexOf("Content Deployed"). If that could conceivably be in one of your other html comments, then the org tag or template URL might be better -- who knows.
Anyway, I hacked at this until it didn't break and was concise enough for my liking--we don't really need an each():
var commentString = $("*").contents().filter(function(){ return this.nodeType == 8 ? this.nodeValue.indexOf("Content Deployed") > -1: false; })[0].nodeValue;
(The ternary operator's necessary because we can't call indexOf on everything being filtered.) This example assigns the TNEW comment to a variable so you can then do string processing on it to get the value of Session MOS or whatever else you need. As Sam mentions, you'd need to put this in a $(document).ready(function(){}); so it only runs once the page is fully loaded.
But anyway how kickass would it be if all of this information was just provided in a JSON object we could access? Sam? :eyebrows:
Hi Nick,
That's a great question! With each release of TNEW, we expand the capabilities of JavaScript. In version 5 we created a module called tnew. You can see this on any page. It contains our version of jQuery as well as some basic data about the session. We will continue to expand this module to contain more pieces of data.
Overall, TNEW is evolving to allow for more ways of customizing. In version 7, we are making a large effort to standardize and document how TNEW is styled and built upon with tools like JavaScript. Providing feedback like "MOS is something important, and why" is very helpful to us to understand how you want to customize TNEW. So, please post things like this.
Sam
Unknown said:Providing feedback like "MOS is something important, and why" is very helpful to us to understand how you want to customize TNEW. So, please post things like this.
My usage case is that I want to be able to show specific messaging on pages depending on customer rank (i.e. MOS) or promotion (either MOS or source number).
Hey, look at that! I remember seeing the tnew object as a way to namespace your jquery, but I must have missed the tnew.session information.
To be honest, I'd strongly recommend adding all of that session information to the tnew.session variable by default. Maybe no one's thought of a business reason why template URL is important for anyone now, but providing that information as structured data should be trivial for the devs, and doing so will enable us to be creative with it.
For example, I've wanted for a while to write something that would give me a push notification whenever the website version number changes (yes, I know there's a chrome plugin) -- but I've been putting it off because I didn't feel like doing string processing on an HTML comment. If the version number was in that session variable, I probably would have done it already! Maybe the ORG value would be useful to a web shop that manages a bunch of different TNEW sites. You really never know what someone will come up with.
Interesting: that fails for me because I guess it's trying to traverse a part of our page that is pulled from a different domain.
Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "https://secure.calperformances.org" from accessing a cross-origin frame.
at Error (native)
at f.each.contents (https://secure.calperformances.org/_QA_/_script/jquery.min.js:3:29605)
at Function.e.extend.map (https://secure.calperformances.org/_QA_/_script/jquery.min.js:2:12686)
at f.fn.(anonymous function) [as contents] (https://secure.calperformances.org/_QA_/_script/jquery.min.js:3:29720)
at <anonymous>:2:28
at Object.InjectedScript._evaluateOn (<anonymous>:875:140)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:808:34)
at Object.InjectedScript.evaluate (<anonymous>:664:21)f.each.contents @ jquery.min.js:3e.extend.map @ jquery.min.js:2f.fn.(anonymous function) @ jquery.min.js:3(anonymous function) @ VM154:2InjectedScript._evaluateOn @ VM140:875InjectedScript._evaluateAndWrap @ VM140:808InjectedScript.evaluate @ VM140:664
I appreciate this thread, it was a timely find for me!
We had a need to get the session ID out of the comment, so I could pass it to a server-side script. (It's to allow patrons using TNEW at our location, in a sort of kiosk context, to print physical tickets immediately via a PrintTickets API call from the confirmation page.) This approach works great – I split the comment by line return and iterate over it to find the previous line.
var tnewCommentLines = $("*").contents().filter(function(){
return this.nodeType == 8 ? this.nodeValue.indexOf("Content Deployed") > -1: false;
})[0].nodeValue.split("\n");
//As the session ID doesn't have a key, let's find it relative to its preceding neighbor
for(var i=0; i<tnewCommentLines.length; i++) if(tnewCommentLines[i].indexOf('Content Deployed')!=-1) { sessionID = tnewCommentLines[i+1]; break; }
Hi Luke,
A better/supported approach would be to be pass the contents of the TNEW cookie to your API. Your API could then decrypt the cookie which contains the session key. I believe you guys already have code to decrypt the cookie. If you don't we have documentation and sample code.
Nick,
Thanks for the feedback! Things like "Template URL" would never to occur to me as being useful. Even having folks parse the comment section of the page is a new idea to me. This means if we change the format of that comment, we break a lot of customization's. We will keep this in mind moving forward.
Hi Sam,
Ah, of course. You're right, we do, I just haven't worked with that code yet. Thank you!
Gawain,
I've never done anything with iframes before, but of course the cross-origin policy is a thing. Do I correctly understand that you have an iframe embedded in your TNEW page, and so the "*" selector is trying to filter its elements as a result? Changing back to the body selector would probably exclude it... not sure if there are better options.
Good question about the IFRAME, I'll have to dig in to what is going on, but I assumed it was just complaining about our locally-hosted template.
So far as I can tell, though, the body selector doesn't contain that final comment, which makes sense, it's outside of the <body> tags.
Oh, that's weird. We use a locally-hosted template as well, but when I get $("body").contents() it contains the comment even though its outside the body. But if you're not getting it, that means its implementation-specific and not suitable for use (I was testing on Safari and Chrome).
I just asked an SO question about this -- feel free to throw it an upvote: http://stackoverflow.com/q/34109501/152891 (or answer it if you're better at DOM traversal than I am).
Hey Gawain,
Try the last code example on this accepted answer: http://stackoverflow.com/a/34109699/152891
I just tried it in the console on your calperformances site and it seems to work!
Hey, that seems to work great! I've given you votes, although I'm too disreputable on SO to actually have my votes appear...