Dynamically Injecting Pages with JQuery Mobile and Json - json

and thanks for looking at my question. I am new to HTML, JQuery, and JSon. I am trying to teach myself with some online tutorials and www.lynda.com training. I'm trying to make a glossary that dynamically displays a list of terms on page, and when clicked displays the term in the header and the definition below that. After searching and experimentation I've made progress, I've got my ul populating from the JSon object and linked to the display page. But I am at a loss as how to get the display page working. I thought the answer was in here: http://jquerymobile.com/demos/1.1.1/docs/pages/page-dynamic.html but I can't seem to pull it off, even in Dreamweaver.
Here is the JSFiddle: http://jsfiddle.net/LParker/PSntK/3/
HTML:
<!-- Glossary -->
<div data-role="page" id="glossary">
<div data-role="header">
<h3>
Glossary
</h3>
</div>
<ul data-role='listview' data-inset='true' id='resultsList'>
<!-- keep empty for dynamically added items -->
</ul>
</div>
<!-- display -->
<div data-role="page" id="display">
<div data-role="header">
<h3>
Name Goes Here
</h3>
</div>
<div data-role="content">
<div>Definition goes here</div>
</div>
JavaScript:
var jsonObject = {
"results": [{
"term": "Term One",
"definition": "This is the definition for Term Two",
},
{
"term": "Term Two",
"definition": "This is the definition of Term Two",
}, {
"term": "Term Three",
"definition": "This is the definition for Term Three",
}],
"ok": "true"
}
var resultLength = jsonObject.results.length;
var listItems = [];
for (var i = 0; i < resultLength; i++) {
var term = jsonObject.results[i].term;
//Add result to array
listItems.push("<li><a href='#display'>" + term + " </a></li>");
}
//Append array to list and refresh
$('#resultsList').append(listItems.join(' '));
$('#resultsList').listview('refresh');
Any help would be appreciated!

First of all lets get a few things out of the way:
Ditch extra commas after each definition member of your json object.
Put your #resultsList listview in a <div data-role="content"></div> container.
Provide the means to navigate from #display page back to #glossary page e.g. by adding a standard jQM back button <a data-role="button" data-rel="back" data-icon="back">Back</a> in the header of the #display page.
While working with jQM you need to use proper event handlers
For brevity I renamed your variable jsonObject to json.
You can populate the listview in a more succinct way:
$.each(json.results, function(i, term){
$('#resultsList').append('<li>' + term.term + '</li>')
});
$('#resultsList').listview('refresh');
Now in that particular case IMHO you don't need to inject pages (although it certainly possible) you can just change content in #display page on pagebeforeshow event.
For that to happen, since your json object globally available, you can just get an index of a clicked list item, pass it to your #display page, use it to access results array of your json object to extract and show term and it's definition.
The simplest way to pass an index is to use a global variable which you set in a click event handler.
var currentItem = 0;
...
$('#resultsList li').click(function(){
currentItem = $(this).index();
});
Now in pagebeforeshow event you do
$('#display').on('pagebeforeshow', function(){
$(this).find('[data-role=header] .ui-title').text(json.results[currentItem].term);
$('#definition').html(json.results[currentItem].definition);
});
Finally here is working jsFiddle for you.

Related

How to properly use JSON to exchange data between separate pages

I have the following html code which is just an item name from a view cart page. I want to be able to transfer this data (amongst others once i get the basic idea down) to a separate html page that'll automatically generate a list of multiple items, with multiple prices and output a total price.
<div class="product-name-options">
<!--START: itemnamelink--><a id="itemName" href="product.asp?itemid=[ITEM_CATALOGID]">[ITEM_NAME]</a><!--END: itemnamelink-->
<button type="button" onclick="window.location='Quote_ep_78-1.html'" id="vc_ChkButton" class="btn"><i class="icon-basket"></i> Get Quote</button>
</div>
I have the following Json code on the cart page.
<script>
window.onload =
function createStudent(){
// this is how you set it
var newProduct = new Object();
newProduct.itemName= document.getElementById('itemName');
if(localStorage.product)
{
product= JSON.parse(localStorage.getItem('product'));
}else{
product=[];
}
product.push(newProduct)
localStorage.setItem('product', JSON.stringify(product));
}
</script>
This is the quote page.
<script>
window.onload= function jsonStarter(){
var retrievedObject = localStorage.getItem('product');
/* document.getElementById("demo").innerHTML = retrievedObject;*/
console.log('retrievedObject: ', JSON.parse(retrievedObject));
}
</script>
</head>
<body>
<div id = ".myDivClass">
</div>
</body>
I can't seem to get the jSON data appear in the div that i've made furthermore at the moment i get the following.
"retrievedObject: (2) [{…}, {…}]"
I get the above console.log which i believe is correct as it reflects the number of items in my cart but i can't get it to print anything else. This is my first ever time using JSON so i'm a bit out of my depth but i'm eager to learn how to do this.
The quote page div after all this looks like this;
<div id=".myDivClass">[{"itemName":{"__hj_mutation_summary_node_map_id__":1063}},{"itemName":{"__hj_mutation_summary_node_map_id__":1063}},{"itemName":{"__hj_mutation_summary_node_map_id__":1063}}]</div>

Reusing pages in WinJS's Pivot

I'm developing app for Windows Phone 8.1 using WinJS and I used Visual Studio's template for pivot application. My Applications queries external API and displays results in PivotItem. Since there are three very similar queries that reurn same type of data, I'd like to reuse one code for all the sections in Pivot. The PivotItem page consist basically only of ListView with items received from API. My section page javascript looks like this:
var ControlConstructor = WinJS.UI.Pages.define("/pages/bookmarks/sectionPage.html", {
ready: function(element, options) {
//Here I call API based on received option and render the page
}
}
WinJS.Namespace.define("bookmarksApps_SectionControls", {
SectionControl: ControlConstructor
});
My page declaring the Pivot looks like this:
<div class="bookmarks" data-win-control="WinJS.UI.Pivot" data-win-res="{ winControl: {'title': 'BookmarksTitle'} }">
<div class="section1 section" data-win-control="WinJS.UI.PivotItem" data-win-options="{ isHeaderStatic: true }" data-win-res="{ winControl: {'header': 'BookmarksNew'} }">
<div class="sectioncontrol" id="section1contenthost" data-win-control="bookmarksApps_SectionControls.SectionControl" data-win-options="{'section': 'new'}"></div>
</div>
<div class="section2 section" data-win-control="WinJS.UI.PivotItem" data-win-options="{ isHeaderStatic: true }" data-win-res="{ winControl: {'header': 'BookmarksAll'} }">
<div class="sectioncontrol" id="section2contenthost" data-win-control="bookmarksApps_SectionControls.SectionControl" data-win-options="{'section': 'all'}"></div>
</div>
<div class="section3 section" data-win-control="WinJS.UI.PivotItem" data-win-options="{ isHeaderStatic: true }" data-win-res="{ winControl: {'header': 'BookmarksHistory'} }">
<div class="sectioncontrol" id="section3contenthost" data-win-control="bookmarksApps_SectionControls.SectionControl" data-win-options="{'section': 'history'}"></div>
</div>
</div>
Now, when I open the app,pivot page correctly loads and displays first section with data. But when I swipe the different section, new data is loaded (so the ready function is called, but nothing is displayed (page is blank, only PivotItems' headers are visible). But if I swipe back to section1, it contains data, that I want to display in section2.
Is it possible to reuse my SectionPage.html and SectionPage.js in different PivotItems, preferably without too much of boilerplate code?
You need to create custom HTML control which will host these pages, custom control can accept uri as data-win-options, then inside your control you can have updateLayout() which will render the page and append to parentElement.
Sample code in update layout method:
var options = {} //Page options
if (!this._isLoaded) {
this._isLoaded = true;
WinJS.UI.Pages.render(this.uri, this._pageElement, options);
}
I found source of my problem. In page /pages/bookmarks/sectionPage.html I had <div> with an id meant for holding my ListVIew. And I was getting win control for listview using document.getElementById("listViewId").winControl. This is wrong, because then I had three divs with same id (each for every section), so getElementById was always returning same list (the one on the first section).
So I changed getting of the wincontrol to
var discussionList = document.querySelector("#" + contentHost + " .disucssionsListView").winControl;
where contentHost depends on data-win-options received from main page and everything works as expected.

angularjs: dynamic html dependent on json data

I want to show the content of my json model in a dynamic way, depending on the provided json. I use ng-repeat to loop through my data and want to display a html template to fill with data dependent on the encountered data type.
JSON
{
"elements": [
{
"type": "input-text",
"desc": "Full Name"
},
{
"type": "input-checkbox",
"desc": "Accept Terms"
}
]
}
This should result in different html code, appropriate filled with the json content.
E.g.
<div><label>Full Name</label> <input type="text"></div>
<div><input type="checkbox"> <label>Accept Terms</label></div>
Right now what I do is to use an angularjs directive to create an element and add the json values to the right spot. e.g. element.html('<div><input type="checkbox"> <label>' + scope.item.desc + '</label></div>') That seems like the jquery way (or worse) to do it although I want to do it the 'right' angularjs way.
How can I use a different HTML template filled with content, dependent on the encountered JSON data?
PS: The above example is a simple one, the encountered data is far more complex than switching the position of the label and input field.
All you need to do is set the data on the scope, then use the ng-repeat directive in your HTML to output it:
Controller:
.controller('MyData', function ($scope) {
$scope.myModel = {
elements: [ { desc: .. }, .. ]
};
})
You would be using the $http service or some other appropriate method in this controller to populate myModel with data, but in the end the data needs to end up on the $scope object somehow. Then it's the template's job to display that data:
<div ng-controller="MyData">
<ul>
<li ng-repeat="element in myModel.elements">
{{ element.desc }}
</li>
</ul>
</div>
A simple solution seems to use ngSwitch with different HTML paths, e.g.:
<div ng-switch="item.type">
<div ng-switch-when="input-text">
<div><label>{{item.desc}}</label> <input type="text"></div>
</div>
<div ng-switch-when="input-checkbox">
<div><input type="checkbox"> <label>{{item.desc}}</label></div>
</div>
<div ng-switch-default>Unknown item.type: {{item.type}}</div>
</div>
Seems the approach using an angularjs directive (which I took first) may be a good solution for complex scenarios as "Huy Hoang Pham" points out in his blog post: http://onehungrymind.com/angularjs-dynamic-templates/ (thanks!)

How do I generate nested DOM elements based on an AJAX result in Angular?

I'm new to Angular so be gentle with me! I'm looking at rendering subsection DOM elements based on an AJAX response, how do I go about implementing the below in Angular?
On page load a list of section headers is returned from the controller:
Clicking on any of these sections (red) would show a subsection list (blue), each of these blue headers can be clicked to show another list (black), bearing in mind I only want to show the immediate-child sections for each section/subsection/sub-subsection header click:
I've got the template code I want to use for each of these, but how do I go about bringing these templates together?
So far from looking around I get the impression I should be creating a directive for the section, sub-section and sub-sub-section (yes?), can I then bind a template to the result of an HTTP Service call? I.e expanding as the detail screenshot above:
<div area="PSED">
Personal, Social and Emotional Development
<div aspect="MH">
Making Relationships
<div goal="BLAH">
<input type="checkbox"> Blah, Blah, Blah
</div>
</div>
</div>
I was hoping to reduce page load time by returning as little data as necessary and populating sections as-required by the user.
I hope this is a reasonable question as I couldn't find anything demonstrating what I need (perhaps my ignorance of ng was causing me to omit an important keyword from my searches).
Thanks in advance for any advice provided.
Andy
If I understand the question, you are trying to dynamically add nodes to a tree-like structure after an ajax call. You can use a combination of ng-include and a recursive template to do this. Here's a rough example that doesn't include the logic for collapsing nodes but I think it gets the idea across.
View:
<script type="text/ng-template" id="tree_item_renderer.html">
<span ng-click="add(data)">{{data.name}}</span>
<ul>
<li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'">
</li>
</ul>
</script>
<ul ng-app="Application" ng-controller="TreeController">
<li ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></li>
</ul>
Controller:
angular.module("myApp", []).
controller("TreeController", function($scope, $http) {
$scope.delete = function(data) {
data.nodes = [];
};
$scope.add = function(data) {
var post = data.nodes.length + 1;
var newName = data.name + '-' + post;
//make your call here and set your child node data
//$http.get('...').then(function(res){
// data.nodes.push({name: newName,nodes: res.data});
//});
//test data
data.nodes.push({name: newName,nodes: []});
};
$scope.tree = [{name: "Top Node", nodes: []}];
});
Working jsFiddle: http://jsfiddle.net/nfreeze/c9mrhxf2/1/

Creating search box using links in html file?

I will preface this question with the fact that I am extremely new to HTML and CSS.
I currently have an engineering page at my company I have inherited that has a ton of links. I have organized into some general categories. However, it has been expressed that they would love a searchbox to search links.
I do not have PHP available to me due to circumstances out of my control. What I do have is all the links in my index.html file with the text they display associated with them.
My thought it that I can create the engine such that it recognizes the tag, and then searches the "name" associated with the link in the tag. However, I really have no idea where to start in terms of implementing such a script.
Of course, there may be a much easier way. I am open to any new approaches. I am not biased toward any programming method or language. Thank you so much for the help everyone, and I can provide any other non-NDA information I can.
I would look at the jQuery UI Automcomplete library http://jqueryui.com/demos/autocomplete/, specifically the custom data demo.
I imagine the code something like this (note this is untested and definitely not complete for your purposes):
<head>
<script type='text/javascript'>
var urls = [
{
value: "url-text",
label: "URL Text",
desc: "URL"
},
{
value: "url2-text",
label: "URL2 Text",
desc: "URL2"
}
];
$('#search').autocomplete({
minLength: 0,
source: urls,
focus: function (event, ui) {
$('#search').val(ui.item.label);
return false;
},
select: function (event, ui) {
$('#search').val(ui.item.label);
$('#url').val(ui.item.desc);
return false;
}
})
.data ("autocomplete")._renderItem= function(ul,item) {
return $('<li></li>")
.data( 'item.autocomplete', item )
.append( '<a>' + item.label + '<br />' + item.desc + '&lt/a>' )
.appendTo( ul );
};
</script>
</head>
<body>
<input id="search" />
<p id='url'></p>
</body>
Doing it this way does mean you have to keep a separate list of URLs and text in a javascript variable.
You'll need to include jQuery in your index.html.
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js' />
Give each link a common class. You can then use jQuery to find the link the user is searching for:
var search = $("#searchBox").val();
$("a.myLinks[href*="+search+"]"); // uses jQuery to select the link, see jQuery selectors
Now you can do things with that link, like show it or navigate to it.