How to merge server-side templating and AJAX to maximize reusability - javascript

Consider the following general issue before I go to the specific problem: You use server-side templating (e.g. Smarty) to generate a page in a particular way depending on a particular state. However, you can also change the state and update that page dynamically using Javascript. How do you construct such a system that does not involve replicating one's work in both Javascript and PHP?
Now, for the specific question that relates to the above. I have a navigation bar for an educational website. Depending on the URL provided by the user, you can be at various levels of navigation: field, subject, course, section, lesson. For example, if the user accesses the following index.php?field=Social_Sciences, the following XML will be returned and parsed by PHP and sent to Smarty such that the appropriate subjects are listed:
<subjects>
<subject>
<id>81</id>
<name>Sociology</name>
<description>Sociology</description>
<path>/data/material/Social_Sciences/Sociology/</path>
</subject>
<subject>
<id>82</id>
<name>Economics</name>
<description>Economics</description>
<path>/data/material/Social_Sciences/Economics/</path>
</subject>
</subject>
Similarly, if a user goes to index.php?field=Social_Sciences&subject=Economics, PHP would parse the following and send it to Smarty:
<courses>
<course>
<id>65</id>
<name>Introduction to Microeconomics</name>
<description>Introduction to Microeconomics</description>
<path>
/data/material/Social_Sciences/EconomicsIntroduction_to_Microeconomics/
</path>
</course>
<course>
<id>66</id>
<name>Introduction to Macroeconomics</name>
<description>Introduction to Macroeconomics</description>
<path>
/data/material/Social_Sciences/EconomicsIntroduction_to_Macroeconomics/
</path>
</course>
</courses>
Now, the problem is the user can also dynamically navigate using AJAX--that is, they can click through the navigation without reloading the page. That means the navigation XML then has to be parsed by jQuery, which means I have to write the same code to parse the XML twice--once in PHP and once in Javascript. After this system proved unwieldy, I started only using AJAX even on the initial load but this is sub-optimal in terms of speed and number of requests. (If you think this is trivial, there are other examples of such issues in my code.) How can one continue to use PHP templating and dynamic AJAX updating without re-writing the same parsing code twice in both languages?

JSON
If you're php actions were returning JSON objects, then I would recommend jQuery's beta product .template()
In a perfect world, you're in html 5 and can send the jQuery.template() parser equivalents of your smarty work from the server outright, as found on pandora.com's html 5 enabled player if you look at the bottom of the page source. it will kind of look like this:
<!DOCTYPE html>
<html>
<head>
<!--- pilfered from jQuery.com's demo linked above --->
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#aControl").click(function(event){
$.get("/your/url").success(function(text, response, jQxhr){
$("#iWillPrintACourseTemplate").tmpl(response).appendTo("#tbodyDestination");
}).error(function(text, response, jQxhr){
});
});
});
</script>
</head>
<body>
<script id="iWillPrintACourseTemplate" type="text/x-jquery-tmpl">
<tr class="detail"><td><p>stuff : ${id} - ${}</p><p>${description}</p><p>${path}</p></td></tr>
</script>
<div><a id="aControl" href='#'>click me</a></div>
<table>
<thead/>
<tfoot/>
<tbody id="tbodyDestination">
</tbody>
</table>
</body>
</html>
not html 5
then you have to move the jQuery html 5 <script type='text/x-jquery-tmpl'/> declaration into your javascript via a $.template("name", html with templating ${} in it); i would get the html with templating ${} stuff via an ajax call. Why? I would try to keep your html templates server side. to allow easy translation between a SMARTY template and a jQuery.Template() should their syntax ever diverge.

Related

ForEach thymeleaf javascript

I'm trying to use thymeleaf inside javascript.
my code work fine when i use th:each with html
<table>
<tr th:each="theme : ${les_themes_1}">
<td th:text="${theme.id}">id</td>
</tr>
</table>
but when i use forEach inside a script,it return me null
<script th:inline="javascript" >
/*<![CDATA[*/
/*[# th:each="theme : ${les_themes_1}"]*/
document.write(/*[[${theme}]]*/); //return null
document.write(/*[[${theme.id}]]*/); //not working
/*[/]*/
/*]]>*/
</script>
help plz ! thank you!
This kind of question has a pretty long history, going all the way back to the early days of the JSP spec. One key thing to remember about JavaScript is that it executes within your browser based on the output generated from your server-side Java components. This is true for JSP and Javascript, Velocity and Javascript, JSTL and other custom tags and Javascript, as well as Thymeleaf and Javascript. In this scenario, the Thymeleaf template is executed well before the Javascript.
Knowing this, one critical troubleshooting strategy is to simply view and inspect the HTML & Javascript source code you generate at runtime.

Javascript fails because of double inverted comma in a test

I have some text saved in my database in HTML format, This text was saved into datatbase from a email.
Sometimes emails have single or double opening inverted commas but no closing inverted commans.
Becuase of this other scripts on the page stop to work.
How can i prevent this html code which i am reading from database to not affect my page style or scripts.
You can consider my application to be simple email reading application.
Any email that i read from database even if it has improper/buggy html, i don't want it to break my code.
Please let me know how i can fix this issues
I am working on following
- Laravel
- Bootstrap
Always escape the data that you receive from the client or you will become a victim of XSS (Cross Site Scripting).
That said if you really want to do it then there are two ways so that the content of the email doesn't affect your code.
IFrame
Shadow DOM
Both of these have a separate context than the parent page so they will not interfere with your code unless the code inside them manually tries to access parent.
Following is the sample for both. Same on JSFiddle
<html>
<head>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="iframeParent">
</div>
<div id="shadowParent">
</div>
<script>
var emailContent = "<h1>helloworld</h1>";
var iframeContainer = $("#iframeParent");
$('<iframe/>').appendTo(iframeContainer).on("load", function () {
$(this).contents().find("body").html(emailContent);//firefox
}).contents().find("body").html(emailContent);//chrome
var shadowContainer = $("#shadowParent");
alert(shadowDom);
var shadowDom = shadowContainer.get(0).createShadowRoot();
shadowDom.innerHTML = emailContent;
</script>
</body>
</html>
Note: Shadom DOM is probably not the best solution as it's not enabled by default on the firefox. See this link

Is there any point in a JS file that has no functions?

I've got Olapic's API in front of me, and it looks something like this:
<script src="https://olapic_source.net"
data-olapic="olapic_specific_widget"
data-instance="213598612346580671235"
data-apikey="081274081760283650812734612"
data-tags="product_ID"
async="async">
</script>
I'm all for keeping JS out of HTML files wherever possible. I'm just wondering if there is any reason to put this in its own file, versus putting it right on the page.
The only requirement is that the script is located inside of a div class called "olapic_specific_widget"
So essentially
<div class="olapic_specific_widget">
<script src="path/to/external/file.js" type="text/javascript">
</script>
</div>
Which is tidier than
<div class="olapic_specific_widget">
<script src="https://olapic_source.net"
data-olapic="olapic_specific_widget"
data-instance="213598612346580671235"
data-apikey="081274081760283650812734612"
data-tags="product_ID"
async="async">
</script>
</div>
And so again, is there a point to this, or should I just leave all that stuff in there? If there is a point to it, I know you're supposed to take the script tag out of the external file. So, does my external file then look like this?
src="https://olapic_source.net"
data-olapic="olapic_specific_widget"
data-instance="213598612346580671235"
data-apikey="081274081760283650812734612"
data-tags="product_ID"
async="async"
Thanks for your time!
The script loaded from the src URL probably examines the page and looks for a <script> tag inside of a <div class="olapic_specific_widget">.
You cannot move any of the data- attributes out of the <script> tag, because the script loaded from src expects the <script> DOM element to contain those data- attributes. These settings are HTML attributes, not JavaScript.
In short, this <script> tag acts in two different roles at one:
a mechanism to import a remote script (because it has a src attribute)
a collection of widget settings, specified by data- attributes.
The remote script (that is imported by the <script> in role #1) reads the data that is set in the <script>'s attributes (in role #2).
You may consider this way to use the <script> element as a kind of remote function call. The several data attributes are the parameters of the call, and the script itself, as specified with the src URL, can perform a variety of actions depending on these parameters. This adds more flexibility in the design of JavaScript libraries for use in web pages.

How to preserve c++ template code in html? [duplicate]

This question already has answers here:
How to display raw HTML code on an HTML page
(30 answers)
Closed 8 years ago.
I'm writing a C++ Style Guide for my company in html/css/javascript. I'm quite irritated with html as it treats anything between < and > as html tag and thus processes them as well. As a result of which my code (which I put in the style guide) doesn't look as such. Here is an example:
<pre>
std::vector<std::string> get_project_names();
template<typename Printable>
void print(Printable const & item);
template<typename FwdIterable, typename Predicate>
FwdIterable find_if(FwdIterable begin, FwdIterable end, Predicate pred);
</pre>
and I want the browser to render it exactly like that, but it doesn't render so, e.g Chrome doesn't show <std::string> part, and IE 8.0 capitalize <std::string> as <STD::STRING> (and all such template codes).
I don't want any kind of interference by html engine. Is there any simple way to achieve what I want? Any polite way to tell the browser to not modify my code?
Note that replacing < with < and > with > would work, but it is cumbersome to write it everytime I write a template code. It also makes my code difficult to read in the source code of the html. So I'm looking for a simple solution.
The notion of a "polite way to to tell the browser to not modify (parse) my code" is precisely what XML's CDATA does. Nothing more, nothing less.
CDATA does not exist in HTML, so there is no way in HTML to treat <std:vector> as anything other than on opening tag for the (non-existent) std:vector element.
The normal way to do this is a server-side transformation. Now if you aren't generating your HTML server-side, and are instead writing it by hand, you can make your life just a dash easier with a client-side transformation like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Page Title</title>
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
</head>
<body>
<pre><script type="text/coffeescript" >document.write "
std::vector<std::string> get_project_names();
".replace('<','<')
</script></pre>
</body>
</html>
Here I used CoffeeScript because of its multiline string capability which is coming in ES6 for regular JavaScript. It makes it easy to just drop in your code between the boilerplate lines.
Now I know full well even this solution is lacking! If your inserted code contains a " you're out of luck. And it doesn't escape ampersands.
Bottom line is that there is no CDATA, so no "simple" solution exists. A transformation, client-side or server-side, is required.
Have you tried markdown?
I've been dealing with this particular problem for years, and it's always been frustrating. I've always appreciated the simplicity and elegance of Markdown, so I did a little research to see if there was any way to use Markdown to build an HTML document.
Thing is, code samples sometimes involve HTML, yet HTML is the language we're using to write style guides and API documentation, so my thought was that if we wrote the API documentation and style guides in Markdown, we'd eliminate all of the conflicts between HTML and the syntax of other languages.
I found Strapdown.js, which is a library that allows you to create a Web page with pure Markdown. The library then compiles it to HTML and renders it on the page client side. We put together the API documentation for one of our products using this library, and we published it as a GitHub page.
Here's a small, concise example:
<!DOCTYPE html>
<html>
<title>JavaScript API</title>
<xmp theme="united" style="display:none;">
## Print the name
Print the user's name:
```javascript
function printName(name) {
alert(name);
}
```
</xmp>
<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script>
</html>
Everything inside the <xmp> tags gets compiled to HTML.
Note: The XMP tag has been deprecated for some time as per the Mozilla HTML documentation on XMP. Thus, you may want to either hack the code to make it use PRE or CODE, or you may want to consider using the lower-level Marked library that was used to build Strapdown.js. I filed an issue with the Strapdown.js team.
For that you can use this
<pre>
std::vector<std::string> get_project_names();
template<typename Printable>
void print(Printable const & item);
template<typename FwdIterable, typename Predicate>
FwdIterable find_if(FwdIterable begin, FwdIterable end, Predicate pred);
</pre>
This would be encoded and you'll get the result that you want.
Here is the fiddle for that: http://jsfiddle.net/afzaal_ahmad_zeeshan/7B9xB/
JavaScript code
The JavaScript method of doing this would be simple, you can convert the whole code to a String variable.
As this
var string = "content here";
Then apply this,
string.replace('<','<').replace('>','>');
Convert all the characters and then have then rendered by the Browser.
http://jsfiddle.net/afzaal_ahmad_zeeshan/7B9xB/1/
For my book I used http://markup.su/highlighter/ syntax highlighter. Paste the code into it, generate highlighted code, and paste the latter into the HTML document. Worked pretty well. Here's a fiddle with your code: http://jsfiddle.net/6GTs2/.
Here's your code highlighted for HTML:
<pre style="background:#000;color:#f8f8f8">std::vector<std::string> <span style="color:#89bdff">get_project_names</span>();
<span style="color:#99cf50">template</span><<span style="color:#99cf50">typename</span> Printable>
<span style="color:#99cf50">void</span> <span style="color:#89bdff">print</span>(Printable const & item);
<span style="color:#99cf50">template</span><<span style="color:#99cf50">typename</span> FwdIterable, <span style="color:#99cf50">typename</span> Predicate>
FwdIterable <span style="color:#89bdff">find_if</span>(FwdIterable begin, FwdIterable end, Predicate pred);
</pre>

Extract all classes from body element of AJAX-ed page and replace current page's body classes

I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});

Categories