Dynamically load jQuery templates - javascript

For jQuery template:
http://api.jquery.com/category/plugins/templates/
I want to be able to dynamically load the templates from a server, rather than predefining it on the page.
The demos I saw on the projects are using predefined templates. After some research I found out that it is possible.
I try doing this and it doesn't work:
<script src="child.html" type="text/x-jquery-tmpl"></script>
I tried doing this and it doesn't work:
$(function () {
$.get("child.html", function (data) {
//Add template
$.template("tmplChild", data);
});
//template binds before async call is done
$.tmpl("tmplChild").appendTo("body");
});
And finally, I have get it down to the following hack:
so.html (This is the main page):
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script>
<script type="text/javascript" src="so.js"></script>
<script type="text/javascript">
$(function () {
initTemplates(templateReady);
});
function templateReady() {
$.tmpl("tmplChild").appendTo("body");
}
</script>
</body>
</html>
child.html (This is the child template)
<h1>Child Loaded</h1>
so.js (This is my hack for ajaxly loading the js templates)
function initTemplates(callback) {
var templateUrl = "child.html";
var templateName = "tmplChild";
initTemplate(templateUrl, templateName, callback);
}
function initTemplate(url, name, callback) {
var opts =
{
type: "GET",
url: url,
dataType: ($.browser.msie) ? "text" : "xml",
success: function (data) {
xmlCallback(data, name, callback);
},
error: function (x) {
xmlCallback(x.responseText, name, callback);
}
}
$.ajax(opts);
}
function xmlCallback(data, name, callback) {
if (typeof data != "string") {
if (window.ActiveXObject) {
var str = data.xml;
data = str;
}
// code for Mozilla, Firefox, Opera, etc.
else {
var str = (new XMLSerializer()).serializeToString(data);
data = str;
}
}
//only takes strings!
$.template(name, data);
callback();
}
And here's what I don't like about it.
This doesn't work on Chrome
It seems like a lot of code just to load some template
I lost the ability to use $(document).ready(). I must now put all my code in this templateReady() method to be "template safe".
Is there a way around this?
Thanks,
Chi

Just load the template body as simple text and forget about putting it in a dummy <script> block. You can use $.tmpl(body, params) to populate the template and turn it into a string for appending to the DOM.
The whole thing with "not really script" <script> blocks is just a convenience useful in some situations.
edit — example:
$.get("/some/url/for/a/template", function(templateBody) {
var expandedTemplate = $.tmpl(templateBody, { param1: 0, param2: "Hello World" });
});

If the goal is to fetch a unique template each time you get data via ajax, then you might try fetching the template at the same time and include it in your data, that is if you have the luxury of modifying the returned object (anonymous object in .Net). Then you can store the template anywhere you want and you only need 1 ajax call for both the data and the template.

Refer here:
https://www.npmjs.com/package/jlate
use CDN:
<script src="https://cdn.jsdelivr.net/combine/npm/lodash,npm/jlate#0.0.2/jlate/JLate.min.js"></script>
HTML Code:
<body>
<div>
<jlate id="my_temp" src="template/jlate_title.html" type="template">
Loading...
</jlate>
</div>
</body>
Javascript:
$$("#my_temp").jlate({ title: "sample title"});

Related

script in HTML string is not executed when passed via JSON

This is a follow-up question of this one.
Goal is to use some user input that is converted to a HTML document that should be displayed in a new tab (that's answered in the link above).
Problem is, however, that - if the HTML document contains <script> tags - those are not executed when this HTML string is passed as JSON. Below I use a simple string:
'<!DOCTYPE html><title>External html</title><div>Externally created</div><script>alert("WORKING");</script>'
This is a minimal example to illustrate the problem (you will see this in your browser when you load the HTML from below):
When I click on the button, the new tab is opened but the script is not executed i.e. there is no alert shown. By clicking on the alert link, the html string is loaded directly and the alert is shown correctly.
My question is, how to postprocess the HTML string that is returned from .getJSON to execute the script correctly. Currently I do it like this (entire code can be found below):
$.get('/_process_data', {
some_data: JSON.stringify('some data'),
}).success(function(data) {
var win = window.open("", "_blank");
win.document.body.innerHTML = data;
})
This is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-muted">Get new tab!</h3>
</div>
<button type="button" id="process_input">no alert</button>
<a href="/html_in_tab" class="button" target='_blank'>alert</a>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#process_input').bind('click', function() {
$.get('/_process_data', {
some_data: JSON.stringify('some data'),
}).success(function(data) {
var win = window.open("", "_blank");
win.document.body.innerHTML = data;
})
return false;
});
});
</script>
</body>
</html>
and the flask file:
from flask import Flask, render_template, request, jsonify
import json
# Initialize the Flask application
app = Flask(__name__)
#app.route('/html_in_tab')
def get_html():
# provided by an external tool
# takes the user input as argument (below mimicked by a simple string concatenation)
return '<!DOCTYPE html><title>External html</title><div>Externally created</div><script>alert("WORKING");</script>'
#app.route('/_process_data')
def data_collection_and_processing():
# here we collect some data and then create the html that should be displayed in the new tab
some_data = json.loads(request.args.get('some_data'))
# just to see whether data is retrieved
print(some_data)
# oversimplified version of what actually happens; get_html comes from an external tool
my_new_html = get_html() + '<br>' + some_data
print(my_new_html)
# this html should now be displyed in a new tab
return my_new_html
#app.route('/')
def index():
return render_template('index_new_tab.html')
if __name__ == '__main__':
app.run(debug=True)
I think you need something like this:
var win = window.open("", "_blank",);
win.document.write('<!DOCTYPE html><title>External html</title><div>Externally created</div><script>(function(){alert(1);})();</script>');
when you open the popup, this executes JavaScript. You could add data and do whatever you want inside <script>(function(){alert(data);})();</script>
After the HTML has been added to the page, you could execute a function to run it. This would require wrapping your scripts with functions like this:
function onStart() {
// Your code here
}
Then after the HTML is added to the page, run the function:
$.get('/_process_data', {
some_data: JSON.stringify('some data'),
}).success(function(data) {
var win = window.open("", "_blank");
win.document.body.innerHTML = data;
onStart();
})
Instead of...
var win = window.open("", "_blank");
win.document.body.innerHTML = data;
Use jquery to load the html and wait for loading to complete:
$.get('/_process_data', {
some_data: JSON.stringify('some data'),
}).success(function(data) {
var w = window.open("", "_blank");
$(w.document.body).load(data, function () {
//execute javascript here
});
})

YouTube API -- extracting title and videoId attributes to build hyperlink

The following is a JavaScript file that searches through YouTube video data using its API. Down at the bottom you'll see the onSearchResponse() function, which calls showResponse(), which in turn displays the search results.
As this code from Codecademy stands, a HUGE amount of information gets printed relating to my search term.
Instead of all that, can I simply display a hyperlink using the title and videoId attributes? How would I go about altering responseString in showResponse() to build that link? Thank you!
// Your use of the YouTube API must comply with the Terms of Service:
// https://developers.google.com/youtube/terms
// Helper function to display JavaScript value on HTML page.
function showResponse(response) {
var responseString = JSON.stringify(response, '', 2);
document.getElementById('response').innerHTML += responseString;
}
// Called automatically when JavaScript client library is loaded.
function onClientLoad() {
gapi.client.load('youtube', 'v3', onYouTubeApiLoad);
}
// Called automatically when YouTube API interface is loaded (see line 9).
function onYouTubeApiLoad() {
// This API key is intended for use only in this lesson.
// See link to get a key for your own applications.
gapi.client.setApiKey('AIzaSyCR5In4DZaTP6IEZQ0r1JceuvluJRzQNLE');
search();
}
function search() {
// Use the JavaScript client library to create a search.list() API call.
var request = gapi.client.youtube.search.list({
part: 'snippet',
q: 'clapton'
});
// Send the request to the API server,
// and invoke onSearchRepsonse() with the response.
request.execute(onSearchResponse);
}
// Called automatically with the response of the YouTube API request.
function onSearchResponse(response) {
showResponse(response);
console.log(response);
}
Here is the corresponding HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="stylesheets/styles.css">
<meta charset="UTF-8">
<title>My YouTube API Demo</title>
</head>
<body>
<section>
<div id="response"></div>
</section>
<script src="javascripts/search-2.js"></script>
<script src="https://apis.google.com/js/client.js?onload=onClientLoad" type="text/javascript"></script>
</body>
</html>
Your advice is much appreciated!
I think it might be what you are exactly trying to do.
function showResponse(response) {
var html = response.items.map(itemToHtml);
document.getElementById('response').innerHTML += html;
}
function itemToHtml(item) {
var title = item.snippet.title;
var vid = item.id.videoId;
return generateHyperlink(title, vid);
}
function generateHyperlink(title, vid) {
return '' + title + '<br/>';
}
This code show up links named title having YouTube video link using videoId.

How to add ajax execution time in boomrang page load time?

I am using boomerang plugin to check web performance.
Following the code that used to get page load time.
<script type="text/javascript" src="http://yui.yahooapis.com/combo?3.1.1/build/yui/yui-base-min.js&3.1.1/build/oop/oop-min.js&3.1.1/build/yui/yui-later-min.js&3.1.1/build/event-custom/event-custom-base-min.js&3.1.1/build/querystring/querystring-stringify-simple-min.js&3.1.1/build/io/io-base-min.js"></script>
<script src="/js/boomerang.js" type="text/javascript"></script>
<script src="/js/plugins/rt.js" type="text/javascript"></script>
<script src="/js/plugins/bw.js" type="text/javascript"></script>
<script src="/js/plugins/navtiming.js" type="text/javascript"></script>
<script type="text/javascript">
BOOMR.init({
BW: {
enabled: false,
cookie: 'HOWTO-BA'
},
RT: {
cookie: 'HOWTO-RT'
}
});
YUI().use("io-base", function(Y) {
var uri = "dynamic-content.txt?" + new Date().getTime();
var timer;
function complete(id, o) {
var html = "<p>\n" + o.responseText.replace(/^$/mg, '</p>\n<p>') + "\n</p>";
document.getElementById("dynamic-content").innerHTML = html;
if(timer) timer.loaded();
};
Y.on('io:complete', complete);
timer = BOOMR.requestStart("my-timer");
var request = Y.io(uri);
});
BOOMR.plugins.RT.setTimer("t_js", new Date().getTime() - t_pagestart).
startTimer("t_head");
</script>
script src="/pgr/js/howtos.js" type="text/javascript"></script>
<script type="text/javascript">
BOOMR.plugins.RT.endTimer("t_howtojs").endTimer("t_body");
</script>
Here YUI that make separate ajax call and adds execrutiont ime in page load time. In my website there are many ajax calls on page load, those execution time I want to add in page load time.
But stuck how to use YIU with existing code.
My ajax call
jQuery(document).ready(function($) {
$.ajax({
type : 'POST',
url : '/getdata/',
data : { sid:retSid},
dataType: 'JSON',
beforeSend: function(){
$('.blocker').show();
},
success : function(result) {
if(result.data)
{
....
}
});
});
You should use one of the SPA plugins to measure single page apps / AJAX apps. It would be better to ask your question on the boomerang support forum. We prefer keeping all discussion and issues in one place so that if a code change is required, we can reference the discussion via a git reference.
You can ask the question here: https://github.com/soasta/boomerang/issues

Unable to push data to handlebars?

I used to use mustache.js for my templates on a quickbase app, but recently decided to switch over to trying handlebars so that I could use the if/then of it for a more appealing template.
However I can not seem to get them to work like mustache did, the Get for my module.js shows in the console, but after that the page doesn't load like it's supposed to (it usually loads the template.html)
module.js
var dbidApplication = "dbidHere";
var dbidTable = "dbidtHere";
var apptoken = "apptokenhere";
$.ajaxSetup({
data: {
apptoken: apptoken
}
});
var promise1 = $.get(dbidApplication, {
a: "dbpage",
pagename: "template.html"
});
var promise2 = $.get(dbidTable, {
act: "API_GenResultsTable",
query: "{3.EX." + kRid + "}",
jsa: 1,
options: "num-1",
});
$.when(promise1, promise2).then(function(html, data) {
//do some stuff with all the data
var template = Handlebars.compile(html[0]);
console.log(html[0]);
console.log(data[0]);
console.log(qdb_data);
$(template(qdb_data)).appendTo("#external");
});
My template has the source for handlebars and the div with id external
template.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.3/handlebars.runtime.min.js" type="text/javascript"></script>
<title></title>
</head>
<body>
<div id="external"></div>
</body>
</html>
I think you forgot to set qdb_data:
$.when(promise1, promise2).then(function(html, data) {
//do some stuff with all the data
var template = Handlebars.compile(html[0]);
var qdb_data = data[0];
console.log(html[0]);
console.log(data[0]);
console.log(qdb_data);
$(template(qdb_data)).appendTo("#external");
});

Make a get request with restful api in angularjs

It's my first question here, sorry in advance if there's a discussion of what i'm going to ask, already. I'm new to angularjs and I'm pretty sure this is not a big problem, but I don't understand what I have to do. I'm working with API teech.io and I would like to get some experience to learn how to use them. My problem is this: make a GET request via http (each user has an app key and an app Id), for example to materials. The documentation of materials says this:
A GET to /materials/:id fetches the material object.
GET /materials/:id HTTP/1.1 Host: api.teech.io Teech-Application-Id:
[app ID] Teech-REST-API-Key: [API key]
<!DOCTYPE html>
<html>
<head>
<!-- INCLUDE REQUIRED THIRD PARTY LIBRARY JAVASCRIPT AND CSS -->
<script type="text/javascript" src="js/angular.min.js"></script>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="teechpadController2.js"></script>
</head>
<body>
the app.js is this one
var app = angular.module('TeechTest',[]);
The teechpadController is this
teechpad.factory('$api', function($http) {
var defaults = {
method: null,
url: null,
headers: {
'Teech-REST-API-Key': api.teech.io.apikey,
'Teech-Application-Id': api.teech.io.appid.
}
};
var req = function(method, url, config) {
defaults.method = method;
defaults.url = 'http://api.teech.io' + url;
var h = angular.extend({}, defaults, config);
console.log(heart);
return $http(heart);
};
return {
get: function(url, config) {
return req('GET', url, config);
},
put: function(url, data, config) {
defaults['Content-Type'] = 'application/json';
defaults['data'] = data;
return req('PUT', url, config);
},
post: function(url, data, config) {
defaults['Content-Type'] = 'application/json';
defaults['data'] = data;
return req('POST', url, config);
},
delete: function(url, config) {
return req('DELETE', url, config);
}
}
});
What I understood till now is that teechpadcontroller re-define the PUT-POST-DELETE-GET methods. Now, How can I use, for example, get method in my controller? Or Should I create an other controller and then use $app there? Sorry again for everything, I'm very new here and in angularjs. Last but not least, I work with JSON object(I think it was clear already)
In your Controller (where you inject this factory) you could use this factory called $api.
The exposed functions to this $api is the four functions returned in the returncaluse:
return {
get: function(url, config) {
...
},
put: function(url, data, config) {
...
},
post: function(url, data, config) {
...
},
delete: function(url, config) {
...
}
}
so in your own controller you could use it something like this:
JavaScript
angular.module('myModule',['TechTest']).controller('myCtrl',function($api){
var customUrl = "/PATH/TO/ENDPOINT",
customConfig = {}; // might not be needed.
$api.get(customUrl, customConfig).success(function(data){
$scope.apiResult = data;
});
})
HTML (which needs to know about your controller per usual)
<!-- include scripts -->
<body ng-app="myModule">
<div ng-controller="myCtrl">
<div>{{apiResult}}</div>
</div>
</body>
I hope I did not missunderstood your quetion.
Now, How can I use, for example, get method in my controller?
You can use your '$api' inside any controller you define by adding it to the injectables of that controller through
var app = angular.module('TeechTest',[]).factory('$api', function($http){ ... });
var controller = app.controller('ctrl', ['$api', function($api){ ... }]);
and then call your 'get' method by going: $api.get( ... ); inside your controller.
Watch out, you've defined 'h' and 'heart' on two different lines, this might just be a typo but it might trip you up!
Your function call to $api.get( ... ); will return asynchronously and you will get the result inside either:
$api.get( ... ).success(function(response){ console.log(response); }); //success
$api.get( ... ).error(function(response){ console.log(response); }); //failure
This is a deferred callback - look into the promise API for more in depth details. You may also want to look into resetting the defaults object every time so you guarantee you're working with a clean object each function call.
Any incorrectness then say and I'll update my answer :)

Categories

Resources