Suggest any Good mustache document - javascript

Suggest me any good mustache doc. Also i want to know in a mushtach loop how do i get the count or the loop no. I mean how can i do a for loop in mustache.
In the below code i wish to change the id in every loop
<script src="http://github.com/janl/mustache.js/raw/master/mustache.js"></script>
<script>
var data, template, html;
data = {
name : "Some Tuts+ Sites",
big: ["Nettuts+", "Psdtuts+", "Mobiletuts+"],
url : function () {
return function (text, render) {
text = render(text);
var url = text.trim().toLowerCase().split('tuts+')[0] + '.tutsplus.com';
return '' + text + '';
}
}
};
template = '<h1> {{name}} </h1><ul> {{#big}}<li id="no"> {{#url}} {{.}} {{/url}} </li> {{/big}} </ul>';
html = Mustache.to_html(template, data);
document.write(html)
</script>
<body></body>

You can't get at the array index in Mustache, Mustache is deliberately simple and wants you to do all the work when you set up your data.
However, you can tweak your data to include the indices:
data = {
//...
big: [
{ i: 0, v: "Nettuts+" },
{ i: 1, v: "Psdtuts+" },
{ i: 2, v: "Mobiletuts+" }
],
//...
};
and then adjust your template to use {{i}} in the id attributes and {{v}} instead of {{.}} for the text:
template = '<h1> {{name}} </h1><ul> {{#big}}<li id="no-{{i}}"> {{#url}} {{v}} {{/url}} </li> {{/big}} </ul>';
And as an aside, you probably want to include a scheme in your url:
url : function () {
return function (text, render) {
text = render(text);
var url = text.trim().toLowerCase().split('tuts+')[0] + '.tutsplus.com';
return '' + text + '';
//---------------^^^^^^^
}
}
Demo: http://jsfiddle.net/ambiguous/SFXGG/

Expanding on #mu's answer, you could also keep an index in the data object and have the template refer to it and the function increment it. So you wouldn't need to add i to each item.
see demo : http://jsfiddle.net/5vsZ2/

Related

How to loop through HTML elements and populate a Json-object?

I'm looping through all the html tags in an html-file, checking if those tags match conditions, and trying to compose a JSON-object of a following schema:
[
{ title: 'abc', date: '10.10.10', body: ' P tags here', href: '' },
{ title: 'abc', date: '10.10.10', body: ' P tags here', href: '' },
{ title: 'abc', date: '10.10.10', body: ' P tags here', href: '' }
]
But I'd like to create the new entry only for elements, classed "header", all the other elements have to be added to earlier created entry. How do I achieve that?
Current code:
$('*').each((index, element) => {
if ( $(element).hasClass( "header" ) ) {
jsonObject.push({
title: $(element).text()
});
};
if( $(element).hasClass( "date" )) {
jsonObject.push({
date: $(element).text()
});
}
//links.push($(element))
});
console.log(jsonObject)
Result is:
{
title: 'TestA'
},
{ date: '10.10.10' },
{
title: 'TestB'
},
{ date: '10.10.11' }
I'd like it to be at this stage something like:
{
title: 'TestA'
,
date: '10.10.10' },
{
title: 'TestB'
,
date: '10.10.11' }
UPD:
Here's the example of HTML file:
<h1 class="header">H1_Header</h1>
<h2 class="date">Date</h2>
<p>A.</p>
<p>B.</p>
<p>С.</p>
<p>D.</p>
<a class="source">http://</a>
<h1 class="header">H1_Header2</h1>
<h2 class="date">Date2</h2>
<p>A2.</p>
<p>B2.</p>
<p>С2.</p>
<p>D2.</p>
<a class="source">http://2</a>
Thank you for your time!
Based on your example Html, it appears everything you are trying to collect is in a linear order, so you get a title, date, body and link then a new header with the associated items you want to collect, since this appears to not have the complication of having things being ordered in a non-linear fasion, you could do something like the following:
let jsonObject = null;
let newObject = false;
let appendParagraph = false;
let jObjects = [];
$('*').each((index, element) => {
if ($(element).hasClass("header")) {
//If newObject is true, push object into array
if(newObject)
jObjects.push(jsonObject);
//Reset the json object variable to an empty object
jsonObject = {};
//Reset the paragraph append boolean
appendParagraph = false;
//Set the header property
jsonObject.header = $(element).text();
//Set the boolean so on the next encounter of header tag the jsobObject is pushed into the array
newObject = true;
};
if( $(element).hasClass( "date" )) {
jsonObject.date = $(element).text();
}
if( $(element).prop("tagName") === "P") {
//If you are storing paragraph as one string value
//Otherwise switch the body var to an array and push instead of append
if(!appendParagraph){ //Use boolean to know if this is the first p element of object
jsonObject.body = $(element).text();
appendParagraph = true; //Set boolean to true to append on next p and subsequent p elements
} else {
jsonObject.body += (", " + $(element).text()); //append to the body
}
}
//Add the href property
if( $(element).hasClass("source")) {
//edit to do what you wanted here, based on your comment:
jsonObject.link = $(element).next().html();
//jsonObject.href= $(element).attr('href');
}
});
//Push final object into array
jObjects.push(jsonObject);
console.log(jObjects);
Here is a jsfiddle for this: https://jsfiddle.net/Lyojx85e/
I can't get the text of the anchor tags on the fiddle (I believe because nested anchor tags are not valid and will be parsed as seperate anchor tags by the browser), but the code provided should work in a real world example. If .text() doesn't work you can switch it to .html() on the link, I was confused on what you are trying to get on this one, so I updated the answer to get the href attribute of the link as it appears that is what you want. The thing is that the anchor with the class doesn't have an href attribute, so I'll leave it to you to fix that part for yourself, but this answer should give you what you need.
$('*').each((index, element) => {
var obj = {};
if ( $(element).hasClass( "header" ) ) {
obj.title = $(element).text();
};
if( $(element).hasClass( "date" )) {
obj.date = $(element).text()
}
jsonObject.push(obj);
});
I don't know about jQuery, but with JavaScript you can do with something like this.
const arr = [];
document.querySelectorAll("li").forEach((elem) => {
const obj = {};
const title = elem.querySelector("h2");
const date = elem.querySelector("date");
if (title) obj["title"] = title.textContent;
if (date) obj["date"] = date.textContent;
arr.push(obj);
});
console.log(arr);
<ul>
<li>
<h2>A</h2>
<date>1</date>
</li>
<li>
<h2>B</h2>
</li>
<li>
<date>3</date>
</li>
</ul>
Always use map for things like this. This should look something like:
let objects = $('.header').get().map(el => {
return {
date: $(el).attr('date'),
title: $(el).attr('title'),
}
})

how to get class name of all tags of json using jquery

I have a JSON data and i want to list all attributes of class name inside divs and inner divs and tags.
Sample JSON DATA :
[
{
"Field1": "<header class=\"main-header dark-bg\">\n\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xl-3\">\n<a class=\"icons-darkbg-slogan main-header__slogan\" data-event_engagement=\"\" data-event_linktype=\"internal page link\" data-event_source=\"DAM|active|de|de|/\" data-event_target=\"/\" data-event_title=\"Header Home::Slogan\" href=\"/\" target=\"_self\" title=\"DWS Homepage\"><img src=\"/globalassets/images/logos/dws_logo_global.svg\" class=\"icon-svg hide-for-print\" alt=\"dws_logo_global\"></a>\n\t\t</div>\n\n\t\t<div class=\"space-9 hide-md\"></div>\n\t</header>"
}
]
I have used children() but it is not taking inner class name, output i got is
main-header dark-bg row space-9 hide-md using the below code by taking json data in a variable
if($(t).children().length > 0){
console.log($(t).children().length);
//OUTPUT SHOWING 2
}
To achieve this you can use some relatively straightforward recursion to traverse down the DOM tree within the HTML string, something like this:
var data = [{
"Field1": "<header class=\"main-header dark-bg\">\n\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xl-3\">\n<a class=\"icons-darkbg-slogan main-header__slogan\" data-event_engagement=\"\" data-event_linktype=\"internal page link\" data-event_source=\"DAM|active|de|de|/\" data-event_target=\"/\" data-event_title=\"Header Home::Slogan\" href=\"/\" target=\"_self\" title=\"DWS Homepage\"><img src=\"/globalassets/images/logos/dws_logo_global.svg\" class=\"icon-svg hide-for-print\" alt=\"dws_logo_global\"></a>\n\t\t</div>\n\n\t\t<div class=\"space-9 hide-md\"></div>\n\t</header>"
}]
function buildClassArray($el, arr) {
arr = arr || [];
$el.each(function() {
arr.push($(this).prop('class'));
$(this).children().each(function() {
buildClassArray($(this), arr);
})
});
return arr;
}
var classes = buildClassArray($(data[0].Field1));
console.log(classes);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note that if you want multiple classes on a single element to appear within their own entity in the array, simply split() the class string before you push it to the array:
var data = [{
"Field1": "<header class=\"main-header dark-bg\">\n\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xl-3\">\n<a class=\"icons-darkbg-slogan main-header__slogan\" data-event_engagement=\"\" data-event_linktype=\"internal page link\" data-event_source=\"DAM|active|de|de|/\" data-event_target=\"/\" data-event_title=\"Header Home::Slogan\" href=\"/\" target=\"_self\" title=\"DWS Homepage\"><img src=\"/globalassets/images/logos/dws_logo_global.svg\" class=\"icon-svg hide-for-print\" alt=\"dws_logo_global\"></a>\n\t\t</div>\n\n\t\t<div class=\"space-9 hide-md\"></div>\n\t</header>"
}]
function buildClassArray($el, arr) {
arr = arr || [];
$el.each(function() {
arr.push(...$(this).prop('class').split(' '));
$(this).children().each(function() {
buildClassArray($(this), arr);
})
});
return arr;
}
var $el = $(data[0].Field1);
var classes = buildClassArray($el);
console.log(classes);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Blaze.getData(el) returns null unless data property is accessed

I am trying to make a list of re-orderable items in Meteor. My items have a info.order property which I change on click events. Why does the example below work until I comment out if the line below // ! ...?
If I comment out that line I get the error Cannot read property '_id' of null when data._id is referenced in the event handler.
This is minimal Meteor javascript:
Widget = new Mongo.Collection('widget');
if (Meteor.isClient) {
function moveUp (mongo_id) {
var clicked = Widget.findOne({_id: mongo_id});
var above = Widget.findOne({'info.order': clicked.info.order - 1});
if (above) {
Widget.update({_id: clicked._id}, {$inc: {"info.order": -1}});
Widget.update({_id: above._id}, {$inc: {"info.order": 1}});
}
}
Template.widget.helpers({
// Get list of widget to display and sort by latest first.
widget: function(data){
return Widget.find({}, {sort: {'info.order': 1}});
},
display: function(mongo_id, info) {
var html = '<div>';
html += '<div>' + info.label + '</div>';
html += '<div>Up</div>';
// ! IF NEXT LINE IS COMMENTED-OUT data == null IN EVENT HANDLER
html += '<div>' + info.order + '</div>';
html += '</div>';
return html;
}
});
Template.widget.events({
'click .js-moveup': function(e, tpl){
e.preventDefault();
var data = Blaze.getData(e.currentTarget);
moveUp(data._id);
}
});
} // end is MeteorClient
With this template:
<head></head>
<body>
{{> widget}}
</body>
<template name="widget">
<div class="container">
<h1>Widgets</h1>
{{#each widget}}
{{{display _id info}}}
{{/each}}
</div>
</template>
And this seed data:
Meteor.startup(function () {
if (Widget.find().count() === 0) {
[{info :{label: "first", order: 1}},
{info: {label: "second", order: 2}},
{info: {label: "third", order: 3}}
].forEach(function(w){
Widget.insert(w);
});
}
});
I've got an idea what's going on...
Meteor must compare the output of display() to it's previous value and only evaluate update the DOM if it has changed (or something similar). If I don't print out info.order the HTML of each widget is unchanged.
I tested this by replacing info.order with new Date() to add varying content that didn't reference the model and, sure enough, the widgets more as expected.
So, my take home message is that if you return raw HTML from display Meteor will try to do the write thing but won't always get it right.

Simple jquery plugin for converting json to html

I need to append this json data to an html element.
[
{
"website":"google",
"link":"http://google.com"
},
{
"website":"facebook",
"link":"http://fb.com"
}
]
How to convert this easily using any plugin.Presently,I couldn't find any simple plugins in jquery,So please help me friends.
Thanks in advance..........
Hi you can use jPut jQuery Plugin (http://plugins.jquery.com/jput/)
Create a HTML jPut Template
<div jput="template">
{{website}}
</div>
<div id="main">
</div>
<script>
$(document).ready(function(){
var json=[{"website":"google","link":"http://google.com"},
{"website":"facebook","link":"http://fb.com"}];
$('#main').jPut({
jsonData:json, //your json data
name:'template' //jPut template name
});
});
</script>
jPut is easy to use comparing to normal parsing.
if there is lots of data to be appended it is very difficult to append using $.each loop.
in jPut just need to create template & to print the data just put the object name in {{}}.
With jQuery, you could do something like this:
data = $.parseJson(json);
$.each(data, function(key, obj) {
htmlElement = $(''+website+'');
$('body').append(htmlElement);
})
Why use a plugin for this? No need to write a plugin to go around this. Just simply loop it through & do what you wan't with the data. Here is an example:
var data = [
{
"website":"google",
"link":"http://google.com"
},
{
"website":"facebook",
"link":"http://fb.com"
}
];
var html = '';
$.each(data, function (index, item) {
html += '' + item.website + '';
});
$('body').append(html);
If you're expecting it to be an anchor tag then -
Html -
<div id="siteContainer"></div>
JS-
var sites = [
{
"website":"google",
"link":"http://google.com"
},
{
"website":"facebook",
"link":"http://fb.com"
}
]
var $container = $('siteContainer');
$(sites).each(function(item, index){
var name = item['website'];
var link = item['link'];
var anchorTag = '' + name + '');
$container.appendTo(anchorTag);
});
NO need plugin, simply iterate with each function and append anchor tag with any selector tag.
var links = [
{
"website":"google",
"link":"http://google.com"
},
{
"website":"facebook",
"link":"http://fb.com"
}
];
$.each(links, function(index, object){
$("<a></a>").attr("href", object.link).
text( object.website).css("margin", "5px").appendTo("body");
})
no plugin needed, can be done without jquery too
<div id="container">
</div>
<script>
var data = [
{
"website":"google",
"link":"http://google.com"
},
{
"website":"facebook",
"link":"http://fb.com"
}
]
document.getElementById('container').innerHTML = ''+data[0]['website']+' >> '+data[0]['link']+' <br> '+data[1]['website']+' >> '+data[1]['link']
</script>

Shorten function in Javascript / Jquery

LF way to short my js/jquery function:
$.ajax({ // Start ajax post
..........
success: function (data) { // on Success statment start
..........
//1. Part
$('var#address').text(data.address);
$('var#telephone').text(data.telephone);
$('var#mobile').text(data.mobile);
$('var#fax').text(data.fax);
$('var#email').text(data.email);
$('var#webpage').text(data.webpage);
//2. Part
if (!data.address){ $('p#address').hide(); } else { $('p#address').show(); };
if (!data.telephone){ $('p#telephone').hide(); } else { $('p#telephone').show(); };
if (!data.mobile){ $('p#mobile').hide(); } else { $('p#mobile').show(); };
if (!data.fax){ $('p#fax').hide(); } else { $('p#fax').show(); };
if (!data.email){ $('p#email').hide(); } else { $('p#email').show(); };
if (!data.webpage){ $('p#webpage').hide(); } else { $('p#webpage').show(); };
}, End Ajax post success statement
Here is my html:
<p id="address">Address:<var id="address">Test Street 999 2324233</var></p>
<p id="telephone">Telephone:<var id="telephone">+1 0000009</var></p>
<p id="mobile">Mobile:<var id="mobile">+1 0000009</var></p>
<p id="email">E-mail:<var id="email">info#example</var></p>
<p id="webpage">Web Page:<var id="webpage">www.example.com</var>/p>
How can we reduce the number of selector*(1. part)* and else if the amount (2. part)?
Assuming your object's property names exactly match the spelling of your element ids you can do this:
for (var k in data) {
$('var#' + k).text(data[k]);
$('p#' + k).toggle(!!data[k]);
}
...because .toggle() accepts a boolean to say whether to show or hide. Any properties that don't have a matching element id would have no effect.
Note: your html is invalid if you have multiple elements with the same ids, but it will still work because your selectors specify the tag and id. Still, it might be tidier to just remove the ids from the var elements:
<p id="address">Address:<var>Test Street 999 2324233</var></p>
<!-- etc. -->
With this JS:
$('#' + k).toggle(!!data[k]).find('var').text(data[k]);
And then adding some code to hide any elements that aren't in the returned data object:
$('var').parent('p').hide();
...and putting it all together:
$.ajax({
// other ajax params here
success : function(data) {
$('var').parent('p').hide();
for (var k in data) {
$('#' + k).toggle(!!data[k]).find('var').text(data[k]);
}
}
});
Demo: http://jsfiddle.net/z98cw/1/
["address", "telephone", "mobile", "fax", "email", "webpage"].map(
function(key) {
if (data.hasOwnProperty(key) && !!data[key]) {
$('p#' + key).show();
} else {
$('p#' + key).hide();
}
});
But you should not.
As long as the properties of the object match the id attributes of the p tags you can iterate through the object using the property name as a selector. Also since id attributes are unique, refrain from prefixing the selector with var it is unnecessary.
var data = {
address: "address",
telephone: "telephone",
mobile: "mobile",
fax: "fax",
email: "email",
webpage: "webpage"
};
for(x in data){
var elem = $("#" + x);
if(elem.length == 1){
elem.text(data[x]);
}
}
JS Fiddle: http://jsfiddle.net/3uhx6/
This is what templating systems are created for.
If you insist on using jQuery there is a jQuery plugin: https://github.com/codepb/jquery-template
More:
What Javascript Template Engines you recommend?
I would use javascript templates for this (I've shortened the example a quite a bit, but you should get the gist).
First the template, I love Underscore.js for this so I gonna go ahead and use that.
<% if data.address %>
<p id="address">Address: {%= Test Street 999 2324233 %}</p>
to compile this inside your success function
success: function(data) {
//assuming data is a json that looks like this {'address':'my street'}
var template = _.template(path_to_your_template, data);
$('var#addresscontainer').html(template);
}
Thanks for birukaze and nnnnnn:
With your advice came function;) :
for (var key in data) {
if (data.hasOwnProperty(key) && !!data[key]) {
$('p#' + key).show().find('var').text(data[key]);
} else {
$('p#' + key).hide();
}
};
Now i can avoid for selector with var.

Categories