I am trying to insert some analytics code into my ExpressionEngine template's footer files, but it treats the {}'s as a function call or something. Is there any way to make it so it understands that EE shouldn't execute what's inside the braces?
I've already tried inserting backslashes and it doesn't seem to work.
Any help would be much appreciated.
ExpressionEngine's Template Class parses curly braces {} as template variables.
Because many programming languages use curly braces, this can cause problems by ExpressionEngine replacing JavaScript curly braces as Template Variables.
For example, the following JavaScript with curly braces all on one line:
<script>var addthis_config = { 'ui_click': true };</script>
Will be parsed by ExpressionEngine as a template variable and rendered as:
<script>var addthis_config = ;</script>
You'll notice everything starting at the opening { and ending with the closing } curly brace gets parsed and replaced! As a workaround, you can place the braces on separate lines and avoid this problem:
<script>
var addthis_config = {
'ui_click': true,
'data_track_clickback': true
};
</script>
If you've written a JavaScript function that expects values from ExpressionEngine, just place your braces on separate lines — which is a good coding convention and is optimal for readability.
What is your Debug preference in EE? It should be set to "1" (recommended). If it's currently at "0" try changing the setting value to "1". In some cases there are possible issues with non-EE {} characters used while debug is set to "0".
You can change the Debug Preference from
CP => Admin => System Administration => Output and Debugging => Debug Preference.
Putting the {} braces on separate lines would also work, but that Debug setting ("1") is highly recommended, and maybe even why this "bug" isn't fixed.
Separate your analytics code into a separate template.
It's probably because you have the analytics code INSIDE another EE loop and so it's trying to parse it as a template variable.
So isolate the code if you need it within the loop and create an embedded template to include.
Thus, create an include called .analytics.
In the .analytics template, do the following (I'm using Google Analytics as an example):
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-xxxxxx-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
NOTE: Using this method, keep the template as a normal template, do NOT change it to a javascript template because you are using the <script type="text/javascript"> tags inside the template.
Then, in your main template, do a simple:
{embed="template_group/.analytics"}
And you will be good to go.
Try the Protect Javascript config variable. I've used it to mix/match EE vars and JS several times.
EE 1.x
$conf['protect_javascript'] = 'y';
Reference
EE 2
$config['protect_javascript'] = 'y';
Reference
You should be using the hidden config varable protect javascript
$config['protect_javascript'] = 'y';
Have you tried commenting out the whole block of Analtics code using EE template comment tags? i.e.
{!--
Your comments will go in here.
You can even span it across multiple lines.
--}
From here http://expressionengine.com/user_guide/templates/commenting.html
I recommend you to avoid inserting (or trying to insert) raw JS into HTML templates. You can create a different template, with type JavaScript instead of HTML, then you can either add it at the head with a script tag, or {embed="js/piece-of-raw-javascript"}
Related
I am altering a database with approximately 500 html pages using phpmyadmin.
Several pages contain a Facebook Pixel or Google Tag that I would like to remove.
The easiest way I thought would be to search via regex the entire tag that contains some expression or term related to Facebook or Google, and replace it with blank.
An example would be
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXX');
</script>
or
<script>
(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '9999999999999999');
fbq('track', 'salespage_xxxxxx');
</script>
Although all are unique, some have the same code or another element that makes it possible to identify each one of them.
Before running in myphpadmin, I'm trying to formulate the expression using SublimeText3
It's the first contact I have with the regex and I found it fascinating, but even following some references I can't match the search.
The expression I came up with after some research was
<(.*)>[\s\S]face[\s\S]<\/(.*)>
Where I thought the expression would select the entire tag containing the word "face", but it doesn't find anything.
I would like some help.
If it works, it would be able to make several other necessary changes.
This regex expression will match the <script> tag that contains the face keyword
<(script)>(?:(?!<\/\1>|face)[\s\S])+face(?:(?!<\/\1>)[\s\S])+<\/\1>
See example: https://regex101.com/r/LfRlBV/1
I have a partial and I need to swap out a link depending on the context, and I also need to use helpers on my expressions within that link. I tried adding this to my partial and including it in the partial template, but it is adding the line as a string, instead of html.
{{> partial link='<a href="/matchup/{{formatForWeb this.name }}/{{formatForWeb
matchup.name }}" class="matchup-card__link">code</a>'}}
I then added it as {{link}} to my partial template:
<div>
{{link}}
</div>
Here it is in dev tools being added as a string to my page:
How can I make this work? Thanks for your time!
You won't be able to use a helper inside a partial.
The solution is to pass the data and HTML elements in different variables to the partial and do the manipulation within the partial definition.
Example
{{> newPartial
link = 'code'
var1 = this.name
var2 = matchup.name
}}
Note that as per the syntax, the data(var1 and var2) should not be wrapped inside curly braces{{}} or quotes"".
Now the partial can be registered as below
Handlebars.registerPartial('newPartial', function(val) {
console.log(val);
return val;
});
Here, in the variable val, you will receive all the 3 variables link, var1 and var2 as array objects, with which you may handle the manipulation and return the end result.
Hope this helps.
Do Chameleon templates escape/strip XSS and HTML tags for variables? Would the following be safe?
<script type="text/javascript">
var initialComments = ${comments};
for (var i = 0; i < initialComments.length; i++) {
initialComments[i].userId = initialComments[i].user_id;
}
var post = ${post}
// ...
</script>
This is actually harder than it seems, and depends upon circumstances. If the output format is HTML, then the script contents are a special CDATA section, wherein the XML/SGML escapes are not interpreted. If the output format is XML, with XML content type, then the escapes work as expected. Even though it could be possible to patch Chameleon so that it understood the <script></script> element as special, currently it does not.
When embedded in <script> tag, depending on a browser version, a sole </ or </script will end the script tag, making it vulnerable to XSS. Furthermore, a < can start a HTML comment as in <!--, and legacy considerations require that <script></script> can be written balanced WITHIN the script tag, thus the safest is to escape the < altogether in all strings.
Another problem is that JSON is not a strict subset of JavaScript, allowing character strings like U+2028 and U+2029 break the script, if you use ensure_ascii=False:
Thus the proper way to do this on python/chameleon, to embed within a <script> tag in HTML is to use:
post_json = (json.dumps(foo, ensure_ascii=False)
.replace('\u2028', r'\u2028')
.replace('\u2029', r'\u2029')
.replace('<', r'\u003c'))
This is true for only content embedded in <script> tags.
or if you just want to get unreadable escapes for pretty much all characters you can be content with:
post_json = json.dumps(foo, ensure_ascii=True)\
.replace('<', r'\u003c')
and then embed with
${structure: post_json}
I posted a feature request in the Python bug tracker to have a keyword argument to do this automatically, but it was rejected.
The safer way to embed stuff is to store it in data-* attributes.
UPDATE escaping </ alone is not enough.
From the Chameleon introduction page:
By default, the string is escaped before insertion. To avoid this, use the structure: prefix
However, that won't escape JavaScript values. Use JSON for that; in your view, use:
post_json = (json.dumps(post)
.replace(u'<', u'\\u003c')
.replace(u'>', u'\\u003e')
.replace(u'&', u'\\u0026')
.replace(u"'", u'\\u0027'))
to produce a HTML-safe JSON string; JSON (as produced by json.dumps() at least 1) is a Javascript subset, here with any HTML-dangerous characters escaped (with thanks to the Flask json.htmlsafe_dumps() function).
Interpolate that into your template using structure:
<script type="text/javascript">
var initialComments = ${comments};
for (var i = 0; i < initialComments.length; i++) {
initialComments[i].userId = initialComments[i].user_id;
}
var post = ${structure:post_json};
// ...
</script>
1JSON allows for U+2028 and U+2029 characters but the json.dumps() function escapes all non-ASCII codepoints by default.
I am trying to use a single smarty template in both PHP and JavaScript. This works great but I'm trying to figure out how I can use an {include file=""} tag in the template when the JavaScript side expects an element ID and the PHP side expects a file path?
Do the element IDs have to match the path I will use when on the PHP side?
OK I worked out how to do this, I overwrote the js prototype method for jsmart that requests a template by id:
jSmart.prototype.getTemplate = function () {}; // Add your method here
That way I can control what to do with the id including mapping it to a template element with a different ID from the passed path.
I know this question looks old, but would like to answer your question since I came across this question via Google and may happen with many others.
xyz.tpl - Template to be included.
Hello {$name}
pqr.tpl - parent template.
There you see the message
{include file='./xyz.tpl'}
Now in Javascript section of a web page define
jSmart.prototype.getTemplate = function (name) {
// Load template content here of template 'name' via ajax or DOM. Say here in the e.g. it would be './xyz.tpl'.
};
Now just call the parent template
<script>
var tplData = <content of pqr.tpl>; // You can load data in this via ajax or from DOM.
var tplObj = new jSmart(tplData);
var output = tplObj.fetch({'name': 'World'});
alert(output);
</script>
Source:-
https://github.com/umakantp/jsmart/wiki/Include-Templates
I want to add a call to a onclick event in any href that includes a mailto: tag.
For instance, I want to take any instance of:
<a href="mailto:user#domain.com">
And change it into:
<a href="mailto:user#domain.com" onclick="return function();">
The problem that I'm having is that the value of the mailto string is not consistent.
I need to say something like replace all instances of the '>' character with 'onclick="return function();">' in strings that match '<a href="mailto:*">' .
I am doing this in ColdFusion using the REreplacenocase() function but general RegEx suggestions are welcome.
The following will add your onclick to all mailto links contained withing a string str:
REReplaceNoCase(
str,
"(<a[^>]*href=""mailto:[^""]*""[^>]*)>",
"\1 onclick=""return function();"">",
"all"
)
What this regular expression will do is find any <a ...> tag that looks like it's an email link (ie. has an href attribute using the mailto protocol), and add the onclick attribute to it. Everything up to the end of the tag will be stored into the first backreferrence (referred to by \1 in the replacement string) so that any other attributes in the <a> will be preserved.
If the only purpose of this is to add a JavaScript event handler, I don't think Regex is the best choice. If you use JavaScript to wire up your JavaScript events, you'll get more graceful degradation if JS is not available (e.g. nothing will happen, instead of having onclick cruft scattered throughout your markup).
Plus, using the DOM eliminates the possibility of missing matches or false positives that can occur from a Regex that doesn't perfectly anticipate every possible markup formation:
function myClickHandler() {
//do stuff
return false;
}
var links = document.getElementsByTagName('a');
for(var link in links) {
if(link.href.indexOf('mailto:') == 0) {
link.onclick = myClickHandler;
}
}
Why wouldn't you do this on the frontend with a library like jQuery?
$(function(){
$("a[href^=mailto]").click(function(){
// place the code you want to execute here
})
});