I have a array fields which contain a list of strings:
var fields = ['foo', 'bar', 'zed'];
I pass it to pug from express like this:
app.get('/some_route', function(req, res) {
res.render('some_view', { fields: fields });
});
Now I want to use that array inside jquery script,
I already try:
<script>
$( document ).ready(function() {
var fields = #{fields};
// return: var fields = foo,bar,zed;
});
</script>
and:
<script>
$( document ).ready(function() {
var fields = JSON.parse(#{fields});
// return: var fields = JSON.parse(foo,bar,zed);
});
</script>
thanks
JSON-encode it an put it in an attribute somewhere, like on the <script> itself:
script(id='field-source', data-fields=JSON.stringify(fields)).
$(document).ready(function () {
var fields = JSON.parse($('#field-source').data('fields'));
});
It’s possible to put it directly into the script with some careful escaping¹ (JSON-encoding is not enough!), but not worth the effort when attributes already work so reliably.
¹ You start by JSON-encoding, then make it safe for the JavaScript context by replacing U+2028 and U+2029 with \u202[89], then make it safe for the HTML context by replacing < with \x3c. Replacing only </ is not enough, as <!-- can also mess with parsing in certain contrivable ways.
Related
I am trying to hash data using JavaScript. When I run the first code it will hash using document.write. Now I try the second code to hash by content id it didn't work. Can anyone explain why?
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js"></script>
<script>
var hash = CryptoJS.SHA256("hello");
document.write(hash.toString(CryptoJS.enc.Hex));
</script>
using this first method will work very fine
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
<script>
var hash = CryptoJS.SHA256;
var it = (hash.toString(CryptoJS.enc.Hex));
document.getElementById('hashit').innerHTML = 'it';
</script>
<p id="hashit">Hello</p>
If you want to hash something in-place in an element then you need to read out the value/text, hash it and write the text back:
var element = document.getElementById('hashit');
var hash = CryptoJS.SHA256(element.innerHTML);
element.innerHTML = hash.toString();
Here is a runnable snippet which changes the value after 2 seconds.
setTimeout(function(){
var element = document.getElementById('hashit');
var hash = CryptoJS.SHA256(element.innerHTML);
element.innerHTML = hash.toString();
}, 2000);
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/sha256.js"></script>
<p id="hashit">Hello</p>
Keep in mind that JavaScript is not like PHP. You can't simply use variables in strings like this element.innerHTML = 'it';. You have to useelement.innerHTML = it;.
I'm working with mathdox, to insert equations in my web page. I have implemented all the symbols and mathematical expressions that I need, to insert them as openmath and convert them in to MathML, except subscript. I know that it's suppose to work like this:
<OMOBJ xmlns='http://www.openmath.org/OpenMath' version='2.0' cdbase='http://www.openmath.org/cd'>
<OMA style='sub'>
<OMV name='x'/>
<OMI>2</OMI>
</OMA>
</OMOBJ>
should convert to
<math xmlns="http://www.w3.org/1998/Math/MathML">
<msub>
<mi>X</mi>
<mn>2</mn>
</msub>
</math>
but I cannot find a way to implement it in javascript or find it's existing implementation in mathdox.
For me, this only works in Firefox. The main tools for the job are createElementNS and getElementsByTagNameNS. Additionally, I'm not sure where you get your openmath document, but I'm going to be retrieving it via AJAX.
So, assuming your file structure is:
/root
+-/js
| +-convert.js
|
+-/xml
| +-openmath.xml
|
+-index.html
And your files are as follows:
index.html
The only thing to note about index.html is that we set an id on the <math> element that we want to put the converted tags under. We also include the convert.js JavaScript file.
<html>
<head>
<title>Convert</title>
<script src="js/convert.js"></script>
</head>
<body>
<main>
<math xmlns="http://www.w3.org/1998/Math/MathML" id="target"></math>
</main>
</body>
</html>
openmath.xml
This file is just the XML that you posted in your question that we will be converting to the math namespace.
<OMOBJ xmlns='http://www.openmath.org/OpenMath' version='2.0' cdbase='http://www.openmath.org/cd'>
<OMA style='sub'>
<OMV name='x' />
<OMI>2</OMI>
</OMA>
</OMOBJ>
convert.js
The way that convert.js works is that it loads up the openmath document over xhr, then creates a new XML document with the document text using DOMParser() and parseFromString(). Then we feed that document to mathSubscriptConverter() which pulls all the OMA tags, gets the relevant data from them, and then converts them to msub tags. Once we have the msub tags, we add them as children under the <math> tag that exists in our index.html.
(function () {
"use strict";
var mathNS = "http://www.w3.org/1998/Math/MathML",
openMathNS = "http://www.openmath.org/OpenMath",
xhr = new XMLHttpRequest();
function mathSubscriptConverter(openmathDoc) {
var target = document.getElementById("target"),
omas = openmathDoc.getElementsByTagNameNS(openMathNS, "OMA");
// Make sure we have a math element to put this under
if (target) {
// Iterate each OMA tag
Array.prototype.forEach.call(omas, function (oma) {
var omv, omi, msub, mi, mn;
// Get the first OMV
omv = oma.getElementsByTagNameNS(openMathNS, "OMV")[0];
// Get the first OMV
omi = oma.getElementsByTagNameNS(openMathNS, "OMI")[0];
// Create a subscript tag in the math namespace
msub = document.createElementNS(mathNS, "msub");
// Create an mi tag in the math namespace
mi = document.createElementNS(mathNS, "mi");
// Create an mn tag in the math namespace
mn = document.createElementNS(mathNS, "mn");
// Set our math attributes
mi.innerHTML = omv.getAttribute("name");
mn.innerHTML = omi.innerHTML;
// Add our new elements to the target
msub.appendChild(mi);
msub.appendChild(mn);
target.appendChild(msub);
});
}
}
// Wait for document load
document.addEventListener("DOMContentLoaded", function () {
// Load our openmath document
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var parser = new DOMParser(),
mdoc = parser.parseFromString(xhr.responseText, "application/xml");
mathSubscriptConverter(mdoc);
}
};
xhr.open("GET", "xml/openmath.xml", true);
xhr.send();
});
}());
I have MVC controller that returns a list containing a search string.
public ActionResult GetList(string searchString)
{
ViewData["searchString"] = searchString;
if (String.IsNullOrEmpty(searchString))
{
var persons = db.Persons.ToList();
return View(persons);
}
else{
var persons = db.Persons.Where(p=> p.Title.Contains(searchString)).ToList();
return View(persons);
}
}
In the view the list is displayed in a table. I want to highlight the searchString (or at most the td that contains the searchString). The following is my jquery where I attempted to achieve this. I have tried putting this bit of code in a separate .js script or in the view itself and I have also tried to change the code in several ways but it wouldn't work. It appears like the searchString remains null even if the content of my ViewData has changed.
$(document).ready(function () {
var textToHighligt = #ViewData["searchString"];
$("#simpleSearchButton").click(function () {
$("td:contains(textToHighligt)").css("background-color", "yellow");
});
});
I think this:
var textToHighligt = #ViewData["searchString"];
$("td:contains(textToHighligt)").css("background-color", "yellow");
should be concatenated:
var textToHighligt = '#ViewData["searchString"]'; //<---put in quotes
$("td:contains("+textToHighligt+")").css("background-color", "yellow");
I think you can do otherwise if it is not happening in the javascript file , create a hidden field and populate the value from the ViewBag
#Html.Hidden("hiddensearchString", (string)ViewBag.searchString)
For the ViewData
#Html.Hidden("FirstName", ViewData["searchString"])
and then the javascript read the value like this
var searchString = $("#hiddensearchString").val();
In you code you can also try this using of the single quote.
var textToHighligt = '#ViewData["searchString"]';
I wanted an if statement to show an image or html code depending on the webpage. I got this far and the html table doesn't appear at all (appears blank):
<script type="text/javascript">
<!--
var url = document.location.pathname;
if( document.location.pathname == '/tagged/photos' ){
document.innerHTML('<table><tr> hello </tr> </table>');
}
if( document.location.pathname == '/tagged/news' ){
document.write("<b>This is my news page</b>");
}
//-->
</script>
I'd do it slightly differently
Add both markup to the page, and show/hide as approproate:
<table id="table"><tr> hello </tr></table>
<span id="title"><b>This is my news page</b></span>
<script type="text/javascript">
$(function(){
var url = document.location.pathname;
if( url == '/tagged/photos' ){
$('#title').hide();
$('#table').show();
}
if( url == '/tagged/news' )
{
$('#title').show();
$('#table').hide();
}
})
</script>
I have assumed you have JQuery since it is tagged
You're using document.innerHTML, which doesn't exist. At the very least, you need to get a proper element:
document.documentElement.innerHTML = 'some HTML';
Setting aside everything else that's wrong with this approach, I'm not sure, why would you use document.write() in one branch and someElement.innerHTML in the other.
I'd suggest the following approach:
function pagePopulate() {
// you're looking at the pathname, use a sensible (meaningful) variable-name:
var pagePath = document.location.pathname,
// this is a map, of the relationship between page and content:
pathToContent = {
// pagename : html
'photos': '<table><tbody><tr><td>photos page</td></tr></tbody></table>',
'news': '<b>This is the news page</b>'
},
// getting a reference to the <body> element:
body = document.querySelector('body');
// setting the innerHTML of the <body>,
// if pagePath = 'tagged/photos', splitting with '/' would return:
// ['tagged','photos'], calling 'pop()' returns the last element of the array
// 'photos', which returns that string to the square brackets, resulting in:
// pathToContent['photos'], which would yield the '<table>...</table>' HTML.
// if that call resulted in an undefined, or falsey, value, then the default
// (the string *after* the '||' would be used instead:
body.innerHTML = pathToContent[pagePath.split('/').pop()] || '<h2>Something went wrong</h2><img src="http://blog.stackoverflow.com/wp-content/uploads/error-lolcat-problemz.jpg" />';
}
// calling the function:
pagePopulate();
References:
|| (logical 'or' operator).
Array.prototype.pop().
document.querySelector().
String.prototype.split().
I have an html page using jquery 1.7.2. Within the page I have a scrip tag like so.
<script id="navigation-template" type="text/x-handlebars-template"></script>
Further down the page I'm using javascript to load my handlebars template into the script tag using the following function:
loadTemplate: function( templateId, elementId ) {
if ( !elementId ) {
elementId = templateId;
}
$('#'+elementId).load('/my/path/templates.html #'+templateId);
}
This is working fine in chrome, the eclipse browser, and even IE 9 but seems to go south in Firefox.
I have debugged and the load call successfully completes and the content is returned, but a call to $('#navigation-template').html() gives an empty String.
I also had content in the script tag and called the load and saw that it was replaced by the empty string after the .load call.
Finally, if I manually perform $('#navigation-template').html( "hello" ); I see that the .html() for the script tag is changed.
If I go to a simple ajax get then I will have to parse it and get the given element rather than relying on load to get the element for me.
How do I get around this issue in firefox?
Here is the function I use for such purposes:
Util.loadTemplates = function(ExternalTemplates) {
$.each(ExternalTemplates, function(index, value){
var scriptUrl = value;
$.ajax({
url: scriptUrl,
dataType: 'text',
success: function(res){
var templateName = value.slice(value.lastIndexOf('/') + 1, value.lastIndexOf('.'));
TEMPLATES[templateName] = Handlebars.compile(res);
}
});
});
}
var ExternalTemplates = [
'templates/application.hbs',
'templates/people.hbs'
];
But it is better to look into doing the compiling, which turns the template into a function, before the page is sent to the client.
You are using the type as this
<script id="navigation-template" type="text/x-handlebars-template"></script>
Try changing the type to
<script id="navigation-template" type="text/javascript"></script>
One thing I liked about load() was that I could store all my templates in a single file and use load to select the div for the template I was interested in. I wrote a method that will load the template file and store the templates into a map of template name to template source and compiled template. I compile the template on the first access so that I don't needlessly compile all the templates every time, but only compile the ones I need when needed. It looks something like this:
var myTemplateHelperThingy = {
loadTemplates: function() {
$.get( '/my/path/templates.html' )
.done(function(data) {
var elements = $(data);
$( 'div.template-marker-class', elements).each( function( index, element ) {
// need to use element instead of 'this' because IE is st00pid.
var content = $(element)[0].outerHTML; // trick from StackOverflow
myAppObject.pageTemplates[this.id] = {
source: content,
template: null
};
});
});
},
getTemplate: function( name ) {
// get a compiled template, compiling it if necessary.
var result = myAppObject.pageTemplates[name].template;
if (!result) {
myAppObject.pageTemplates[name].template = Handlebars.compile(myAppObject.pageTemplates[name].source);
}
return myAppObject.pageTemplates[name].template;
},
evalTemplate: function( data, templateName ) {
var template = myAppObject.getTemplate(templateName);
if (template) {
return template(data);
}
else {
// message to user here that something went wrong.
}
},
showTemplate: function( targetElement, data, templateName ) {
$(targetElement).html(bi.evalTemplate( data, templateName ));
}
}
And templates.html looks like:
<html>
<body>
<div id="templates-wrapper-do-not-remove-or-jquery-will-not-find-the-templates">
<div id="my-first-template" class="template-marker-class other-class">
<!-- a bunch of content -->
</div>
<div id="my-second-template" class="template-marker-class another-class">
<!-- more content -->
</div>
</div>
</body>
</html>