• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

xenForo variables in Javascript

cclaerhout

Well-known member
#1
Is there an easy solution to get a xenForo variable in Javascript (jquery)? Let's take a simple example:
In php to get a xenForo phrase, I do:
Code:
new XenForo_Phrase('toggleMe_Expand');
If I want to get a xenForo variable I use:
Code:
$call->getParam('variable')
Is there something in Javascript? Or do I have to use my php file to send those data to my Javascript ? If it's the case, do someone has a simple example to show me how to do it? I've read a lot of tutorials on Internet based on AJAX and almost each of them use a different way to do it.
 

cclaerhout

Well-known member
#3
I think the only way is using ajax to get the data of a PHP file. If you want a example, I can get one to you.
Actually there is this tutorial: http://xenforo.com/community/threads/xenforo-ajax-tutorial.8091/
I've watched these videos this morning. The first was ok, the second harder, but still ok. The thirst lost me... and the fourth... well looks impressive but I need more practice ^^

When I watched these videos, I didn't find what I was looking for. I know that if I use Javascript in xen templates, then I can access all xen variables, but from a independent js file, I was curious to know how to get those variables. If you've got time to show me an example, it would be nice of you, but take your time, there's no hurry. Thanks for your answer :)
 

HeadHodge

Active member
#4
I've watched these videos this morning. The first was ok, the second harder, but still ok. The thirst lost me... and the fourth... well looks impressive but I need more practice ^^

When I watched these videos, I didn't find what I was looking for. I know that if I use Javascript in xen templates, then I can access all xen variables, but from a independent js file, I was curious to know how to get those variables. If you've got time to show me an example, it would be nice of you, but take your time, there's no hurry. Thanks for your answer :)
Did you ever figure this out. I'm trying to do the same thing (i.e. access php variables from my template javascript)
 

cclaerhout

Well-known member
#5
Did you ever figure this out. I'm trying to do the same thing (i.e. access php variables from my template javascript)
Yes, I figured out that my question was stupid ^^

From a way or another you need to inject any data you need in the template (which means in the DOM) so you can get back the data in JavaScript.
There are several way of doing it:
  • Extend the template "page_container_js_body" ; any new js element will be available then from the XenForo JavaScript objet
  • Inject some JS data using some json helper (which is done for the editor configuration) ; might be too complex to start
  • The easiest: add a "data" element do a html tag and get it back its value in JS
    HTML:
    <div id="myId" class="myClass" data-test="abc"></div>
    Code:
    $('#myId').data('test');

This is the very basics, you will probably need to read a lot of codes and examples to get used to.
 

HeadHodge

Active member
#6
Yes, I figured out that my question was stupid ^^

From a way or another you need to inject any data you need in the template (which means in the DOM) so you can get back the data in JavaScript.
There are several way of doing it:
  • Extend the template "page_container_js_body" ; any new js element will be available then from the XenForo JavaScript objet
  • Inject some JS data using some json helper (which is done for the editor configuration) ; might be too complex to start
  • The easiest: add a "data" element do a html tag and get it back its value in JS
    HTML:
    <div id="myId" class="myClass" data-test="abc"></div>
    Code:
    $('#myId').data('test');

This is the very basics, you will probably need to read a lot of codes and examples to get used to.
Thanks for your reply.

You might be interested in this. I just now tried it and it works!!!

In my template:
<xen:callback class="HeadHodge_Callback" method="getHtml" params="{$name}"></xen:callback>
And then in my callback class:
<?php
class HeadHodge_Callback {
public static function getHtml($content, $params) {
$output = '<script id="HeadHodge">';
$output .= 'var myname = "' . $params . '";';
$output .= 'alert(myname);';
$output .= '</script>';
return $output;
}
}
?>
 

HeadHodge

Active member
#7
I don't know if anyone is interested but I just did this successfully:

In my template:
<xen:callback class="HeadHodge_Callback" method="getHtml" params="{$visitor}"></xen:callback>
In my class:
<?php
class HeadHodge_Callback {
public static function getHtml($content, $params) {
$json = XenForo_ViewRenderer_Json::jsonEncodeForOutput($params, false);
$output = 'Hello World <br />';
$output .= '<script id="HeadHodge">';
$output .= 'var json = ' . $json . ';';
$output .= '</script>';
return $output;
}
}
?>
This successfully converted the php array $visitor to a javascript object. I was able to use regular javascript to iterate through the whole object (some 50+ variables) and output it to my browsers console!!!

Javascript in template to dump variable:
<script>
for (varname in json) {
console.debug(varname);
}
</script>
Here's a snippet of my browsers console afterwards:

index.php?review-filter:934 user_id
index.php?review-filter:934 username
index.php?review-filter:934 email
index.php?review-filter:934 gender
index.php?review-filter:934 custom_title
index.php?review-filter:934 language_id
 
Last edited:

cclaerhout

Well-known member
#8
@HeadHodge
You shouldn't expose the full visitor objet in your template, It might be not a great thing for security and it's cleary not good for performance: The visitor objet can contain a lot of parameters that you don't need . By the way there's a template helper to encode with json (look at the editor template) ; you probably don't need a callback for this.
 

HeadHodge

Active member
#9
@HeadHodge
You shouldn't expose the full visitor objet in your template, It might be not a great thing for security and it's cleary not good for performance: The visitor objet can contain a lot of parameters that you don't need . By the way there's a template helper to encode with json (look at the editor template) ; you probably don't need a callback for this.
Thanks for your reply.
Had no intent of doing anything with $visitor, was just using that for testing because my little test add-on doesn't pass any params in $viewParams.

Thanks for pointing me to the helper, I'll definitely give that a try. (y)
 

HeadHodge

Active member
#10
@HeadHodge
...you probably don't need a callback for this.
Even though the way I did it with a xen:callback worked fine, using html <div> tags to hold json strings turned out to be simpler for me.

1. Convert server object to json with static function: XenForo_ViewRenderer_Json::jsonEncodeForOutput($results, false);

2. Pass string to template via params in Controller Response.

3. In template use <div id='myData'>{$jsonData}</div> to place string in clients browser DOM

4. In javascript parse json string: var jsObject = JSON.parse($('myData').html());
 
#12
I would like to insert in js username, email and register date of the visitor to use them with intercom.io (see here: XF 1.4 - Integrating Xenforo with Intercom.io)
I am guessing you know how to add the code to the PAGE_CONTAINER template...

you can do something like:
Code:
<script>
  window.intercomSettings = {
    name: "{xen:jsescape $visitor.username}",
    email: "{xen:jsescape $visitor.email}",
    created_at: {$visitor.register_date},
    app_id: “XXX”
  };
</script>
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/XXX';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
And maybe add a condition for only registered visitors:
Code:
<xen:if is="{$visitor.user_id}">
<script>
  window.intercomSettings = {
    name: "{xen:jsescape $visitor.username}",
    email: "{xen:jsescape $visitor.email}",
    created_at: {$visitor.register_date},
    app_id: “XXX”
  };
</script>
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/XXX';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
</xen:if>
 

HeadHodge

Active member
#15
Thank you Goodies, I already done it but thant you anyway, I thought that was more difficult!

I simply used:
{$visitor.username}
{$visitor.email}
{$visitor.register_date}

...and it worked :D

as you suggested I'm going to add xen:jsescape

I'm posting the code here: XF 1.4 - Integrating Xenforo with Intercom.io
When I posted my objective was to create a javascript object with the data I wanted (to be used in javascript)

So basically my approach to do that would be:

Create a Callback file i.e. :

Code:
<?php

class CustomPages_InsertHtml
{
/******************************
** Callback to Render HTML  **
******************************/
public static function insertVisitorInfo()
{
$visitor = XenForo_Visitor::getInstance();

$array = array(userName => $visitor->username, eMail => $visitor->email, registerDate => $visitor.register_date);

$json = XenForo_ViewRenderer_Json::jsonEncodeForOutput($array, false); //convert array to json string

echo  '<div id="userInfo">' . $json . '</div>';
echo '<script>';
echo var visitorInfo = JSON.parse($('#userInfo).html);
echo alert(visitorInfo.username + ', ' + visitorInfo.eMail + ', ' + visitorInfo.registerDate);
echo  '</script>';
}
And put the following in your template where you want it to be inserted:

Code:
<xen:callback class="CustomPages_InsertHtml" method="insertVisitorInfo"></xen:callback>
Note: did this from memory and didn't test it for proper syntax. :)
 
Last edited:

HeadHodge

Active member
#16
Or you could skip using the <div> and insert the json object directly into javascript.
Example:

Code:
<?php

class CustomPages_InsertHtml
{
/******************************
** Callback to Render HTML  **
******************************/
public static function insertVisitorInfo()
{
$visitor = XenForo_Visitor::getInstance();

$array = array(userName => $visitor->username, eMail => $visitor->email, registerDate => $visitor.register_date);

$json = XenForo_ViewRenderer_Json::jsonEncodeForOutput($array, false); //convert array to json string

echo '<script>';
echo 'var visitorInfo = ' . XenForo_ViewRenderer_Json::jsonEncodeForOutput($array, false)) . ';';
echo 'alert(visitorInfo.username + ', ' + visitorInfo.eMail + ', ' + visitorInfo.registerDate);';
echo  '</script>';
}
This example is probably overkill for your needs. But the reason I like this technique is that you can inject html anywhere into your template with only the use of a single <xen .... > command. It lets me focus more on what needs to be done using PHP , no matter how complicated, instead of trying to jump through a bunch of hoops with <xen> commands.