I'm trying to create dynamic popovers that are generated from a 'dictionary' array that injects HTML into existing text on the page. The code was initially uses for tooltips and worked well but now I am trying to transfer over to popovers. However the html isn't injecting and I'm stuck with it. The aim is to click on a word and have the definition etc popup. I also have a standard popover on the same page that functions correctly. I'm not getting any errors in the console :(
//script.js
$(function() {
var $words = [
{
word: "ね",
kana: "",
romaji: "ne",
definition: "n postposition<br>indicates emphasis, agreement, request for confirmation, etc., is it so, hey, come on, listen, not",
note: ""
},
{
word: " 動画",
kana: "どうが",
romaji: "douga",
definition: "video, movie, moving picture, animation, animated cartoon, in-betweens (animation)",
note: ""
},
{
word: " 今日",
kana: "きょう",
romaji: "kyou",
definition: "adjective today, this day, these days, recently, nowadays",
note: ""
},
{
word: "毎日",
kana: "まいにち",
romaji: "mainichi",
definition: "every day",
note: ""
},
{
word: "も",
kana: "",
romaji: "mo",
definition: "adjective today, this day, these days, recently, nowadays",
note: " te form"
},
{
word: "頑張りましょう",
kana: "がんばりましょう",
romaji: "ganbarimashou",
definition: "verb to persevere, to persist, to keep at it, to hang on, to hold out, to do one\'s best",
note: "lets do"
},
];
$('.define').definitions({
term: $words
});
}); //end $(function()
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
});
/*==================js/jquery.define.js============================*/
var html;
$.fn.definitions = function(words) {
//$.fn alias for jQuery.prototype extends jQuery with your own functions
//console.log("words: ", words); // returns words array
var count = 0;
// Iterate over a jQuery object, executing a function for each matched element.
return this.each(function() {
var _results = [];
var _term = words["term"]; //console.log(_term); //return each definition / word pair object in a single array
var _this = $(this); //console.log(_this);
if (_term.length > 1) {
$.each(_term, function() {
for (let key in _term) {
// iterates over all properties of an object returning value only.
var val = _term[key]; //console.log(val); //returns each dict def / word pair object individually
_results.push(
_this.html(function(index, htmlContent) {
if (
_this
.text()
.toUpperCase()
.indexOf(val["word"].toUpperCase()) >= 0
) {
//console.log(html);
return (html = define_replace(
val["word"],
val["definition"],
val["kana"],
val["romaji"],
val["note"],
htmlContent,
key
)); //html injecting
}
})
);
} //end for...in
});
$("#japanese").html(html); //changed from .text()
} else {
_results.push(
_this.html(function(index, htmlContent) {
if (
_this
.text()
.toUpperCase()
.indexOf(_term["word"].toUpperCase()) >= 0
) {
return (html = define_replace(
_term["word"],
_term["definition"],
_term["kana"],
_term["romaji"],
htmlContent
));
}
})
);
}
}); //end return this.each(function()
}; //end $.fn.definitions
//inject class before and after found word in html
var define_replace = function(word, def, kan, rom, note, html, key) {
//console.log(arguments);
return html.replace(
'<a data-html="true" data-toggle="popover" title="Popover - title" data-content="' + def + '>' + word + " " + '</a>', "gi"
); //html building - replace word + space with html
(n - adv, n, ctr) time;
hours;
(P) < /span></span >
}; // end define_replace
//index.html
<div class="define">
<p id="japanese">ね 、 毎日 動画 今日 も 頑張りましょう</p>
</div>
include popper.min.js before bootstrap.js or use bootstrap.bundle.min.js and Enable popovers everywhere
$(function () {
$('[data-toggle="popover"]').popover()
})
Related
What I want to happen is to have different URLs be provided based of what the array function result is.
Basically, if collectTags is equal to "church" or "concert" it links to A.com else it links to B.com.
Here's the code I currently have:
caption : function( instance, item ) {
var caption, link, collectTags, tags;
caption = $(this).data('caption');
link = 'Download image';
collectTags = $(this).parent().attr("class").split(' ');
tags = $.map(collectTags,function(it){ if(collectTags === "church"){ return ''+ it +''} else{return ''+ it +''};});
return (caption ? caption + '<br />' : '') + link + '<br/>' + tags.slice(1);
}
I'm not sure that I can do it right, but I'll give it a try. Your problem is that you access collectTags again. That is an array, not a string, so you comparing it to a string will always be false. And never to use string concatination that will make your code harder to read & mess.
{
caption: function (instance, item) {
var caption, link, collectTags, tags;
function format(tpl, binding) {
if (typeof binding != 'function') return format(tpl, function (_, name) {
return binding[name];
});
return tpl.replace(/\$(\w+)/g, binding);
}
caption = $(this).data('caption');
link = format('Download image', item);
collectTags = $(this).parent().attr("class").split(' ');
function createTag(it) {
return format("<a href='$site/$it'>$it</a>", {
site: (it == 'church' || it == 'concert') ? 'A.com' : 'B.com',
it: it
});
}
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(tags).join('<br/>');
}
}
I got one external .json file, in which a arry is defined as:
var words = [
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"]
My plan is to import in the .json file via jquery, and then use the values in the array word as the option in a select object.
My understanding is:
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$.each(result, function (i, word) {
$(".selection").html("<option>word</option>");
});
});
});
</script>
or:
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
html = ''
for (i = 0; i < results.length; i++) {
html += "<option value=" + result[i] + ">" + result[i] + "</option>";
};
document.getElementById("myselect").innerHTML = html;
});
});
</script>
But neither works here. Please tell me how to fix that.
Your .json-file needs to be like this:
[
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"
]
Then either of the scripts should work. (First one with one small adjustment)
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$.each(result, function (i, word) {
$(".selection").append("<option>"+word+"</option>");
});
});
});
</script>
Remember that a .json-file should only contain JSON. Not javascript which is what you had.
You have some typos in your code.
Assuming that you have valid json and parsed words array
var words = [
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"];
$.each(words, function (i, word) {
$(".selection").append("<option value='"+word+"'>" + word + "</option>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<select size="7" class="selection"></select>
</div>
For your first attempt, you're doing:
$(".selection").html("<option>word</option>");
You should be using something like append, and also make sure you take "word" out of the quotes:
$(".selection").append("<option>" + word + "</option">);
.html() just replaces the data contained within the HTML element, whereas .append() will add them to the end.
This is the issue if you're only getting one value returned.
It looks like in your JSON object you have the data defined in a variable, instead it should just be:
[
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"
]
this work for me:
$.each(words, function (i, word) {
items+="<option>"+word+"</option>";
});
$(".selection").html(items);
You have several things that need to be fixed. One, is that .html() replaces the innerHTML, doesn't add to it. So, you need to build all the options and then set them. I also, as you had in the second script, put the value of the word as the option value. Note, the inner quotes are also needed. Furthermore, your jQuery of ".selection" will do this to all objects designated with the "selection" class, whereas, in your second script, you seemed to want to only assign one element with an id of "myselect".
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
var html = "";
$.each(result, function (i, word) {
html += "<option value='"+word+"'>"+word+"</option");
});
$(".selection").html(html);
});
});
</script>
You can extend jQuery. The best thing about this approach is you can reuse these extensions when needing to clear or fill a select. Just pass it an array.
$.fn.clearSelect = function() {
return this.each(function() {
if (this.tagName == 'SELECT')
this.options.length = 0;
});
}
$.fn.fillSelect = function(data) {
return this.clearSelect().each(function() {
if (this.tagName == 'SELECT') {
var dropdownList = this;
if (data.length > 0) {
this.disabled = false;
}
$.each(data, function(index, optionData) {
var option = new Option(optionData, optionData);
dropdownList.add(option, null);
});
}
});
}
This extension will allow you to pass your data directly to the select like this
$("#myselectid").fillselect(["a","able","about","account","acid","across","act"]);
I have not tested this, but the snip-it should give you the general idea.
But in your example you could call the extensions this way:
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$(".selection").fillSelect(result);
}
});
Just tested and edited the snipet. Test is located here https://jsfiddle.net/4wmj8pkk/
I'm trying to display particular json data in a form of Bullets. Each chapter data into <li>, each title into <p> and make those titles as a link. Finally, consider to the index of clicked title display related content in a second <div>. I have already some piece of code below (not working yet).
Html:
<div id="page1">
<ul id="courses"></ul>
</div>
<div id="page2">
<p id="content"></p>
</div>
JS code:
var jsonString = '[{"chapter":"General","title":"News forum","content":"Text1"},
{"chapter":"CHAPTER 1","title":"1.1 Introduction","content":"Text2"},
{"chapter":"CHAPTER 1","title":"1.2 Main Idea","content":"Text3"},
{"chapter":"CHAPTER 2","title":"2.1 Architecture","content":"Text4"},
{"chapter":"CHAPTER 3","title":"3.1 Liter.overview","content":"Text5"}]';
var myData = JSON.parse(jsonString);
$(document).ready(function() {
var $clist = $('#courses');
for(var i in myData) {
$('<li><h3>' +this.[i].chapter+ '</h3><p>' +this.title+ '</p></li>').appendTo($clist);
}
function dContent() {
var $ccontent = $('#content');
$(this.[i].content).appendTo($ccontent);
}
});
Expected result:
- General
News forum // onclick display 'Text1' in <p id="content">
- CHAPTER 1
1.1 Introduction // onclick display 'Text2' in <p id="content">
1.2 Main Idea // onclick display 'Text3' in <p id="content">
- CHAPTER 2
2.1 Architecture // onclick display 'Text4' in <p id="content">
- CHAPTER 3
3.1 Liter.overview // onclick display 'Text5' in <p id="content">
Any help would be appreciated.
UPDATE: Here is the JSFIDDLE project.
var jsonString = '[{"chapter":"General","title":"News forum","content":"Text1"},{"chapter":"CHAPTER 1","title":"1.1 Introduction","content":"Text2"},{"chapter":"CHAPTER 1","title":"1.2 Main Idea","content":"Text3"},{"chapter":"CHAPTER 2","title":"2.1 Architecture","content":"Text4"},{"chapter":"CHAPTER 3","title":"3.1 Liter.overview","content":"Text5"}]';
var myData = JSON.parse(jsonString);
var dContent = function(event) {
$ccontent.html($(this).data('content'));
}
var $clist = $('#courses');
var $ccontent = $("#content");
var html = '';
var chapterList = [];
$clist.on('click', 'li', dContent);
$.each(myData, function(index, item) {
if ($.inArray(item.chapter, chapterList) === -1) {
chapterList.push(item.chapter);
html += '<li data-content="'+ item.content +'"><h3>' + item.chapter + '</h3><p>' + item.title + '</p></li>';
}
else {
html += '<li data-content="'+ item.content +'"><p>' + item.title + '</p></li>'
}
});
$clist.html(html);
I've written a script to do this, including putting items from the same chapter together. You can see a demo fiddle here.
I used native JavaScript for most of it, with the exception of jQuery for the $(a).on('click', .. and $(document).ready to ensure compatibility. Why is it so long? Because I built the <ul> with DOM methods, instead of a html string. This made it easy to cache and append elements. Finally, the content is added via a generator function. The way I did it means the page will use slightly more memory but you can have any string that is valid in JavaScript displayed in the content section. You may want to style it with whitespace: pre-wrap; to display new lines as expected.
Anyway, here is the code
var jsonString = '[{"chapter":"General","title":"News forum","content":"Text1"},\
{"chapter":"CHAPTER 1","title":"1.1 Introduction","content":"Text2"},\
{"chapter":"CHAPTER 1","title":"1.2 Main Idea","content":"Text3"},\
{"chapter":"CHAPTER 2","title":"2.1 Architecture","content":"Text4"},\
{"chapter":"CHAPTER 3","title":"3.1 Liter.overview","content":"Text5"}]';
// the \ at line ends is to escape the new line in the string literal
var myData = JSON.parse(jsonString);
$(document).ready(function() {
var courses_ul = document.getElementById('courses'), // cache elements
content_elm = document.getElementById('content'),
i, li, h3, p, a, // vars for loop
chapters = {}, chap; // cache chapters
for (i = 0; i < myData.length; ++i) {
chap = myData[i].chapter; // shorthand since we'll use it a few times
// make <p>, <a>
p = document.createElement('p');
a = document.createElement('a'); // could append <a> to <p> here if you want
a.setAttribute('href', '#page2');
a.appendChild(document.createTextNode(myData[i].title));
// set up click
$(a).on('click', (function (content) { // generator - will give scope to
return function () { // this returned event listener.
content_elm.innerHTML = '';
content_elm.appendChild(document.createTextNode(content));
};
}(myData[i].content))); // chose `content` not `i` so no reliance on `myData`
// now check cache if chapter exists -
if (chap in chapters) { // retreive <li> for chapter from cache
li = chapters[chap]; // from cache
// append <p>, <a>
li.appendChild(p).appendChild(a);
} else { // if not in cache
li = document.createElement('li'); // make a new <li>
chapters[chap] = li; // and cache
// make & append <h3>
h3 = document.createElement('h3');
h3.appendChild(document.createTextNode(chap));
li.appendChild(h3);
// append <p>, <a> and to <ul>
courses_ul.appendChild(li).appendChild(p).appendChild(a);
}
}
});
You have an invalid JSON structure. The correct structure is below:
[
{
"chapter": "General",
"title": "News forum",
"content": "Text1"
},
{
"chapter": "CHAPTER 1",
"title": "1.1 Introduction",
"content": "Text2"
},
{
"chapter": "CHAPTER 1",
"title": "1.2 Main Idea",
"content": "Text3"
},
{
"chapter": "CHAPTER 2",
"title": "2.1 Architecture",
"content": "Text4"
},
{
"chapter": "CHAPTER 3",
"title": "3.1 Liter.overview",
"content": "Text5"
}
]
Note that comma here 3.1 Liter.overview","content":"Text5"}, in your JSON structure, it fails here
UPDATED ANSWER WITH CODE
var jsonString = '[{"chapter": "General","title": "News forum","content": "Text1"},{"chapter": "CHAPTER 1","title": "1.1 Introduction","content": "Text2"},{"chapter": "CHAPTER 1","title": "1.2 Main Idea", "content": "Text3"},{"chapter": "CHAPTER 2","title": "2.1 Architecture","content": "Text4"},{"chapter": "CHAPTER 3","title": "3.1 Liter.overview","content": "Text5"}]';
var myData = JSON.parse(jsonString);
$(document).ready(function() {
function dContent() {
$("#content").css("border","2px solid red").css("height","100px");
$("#content").html($(this).data('value'));
}
$("#courses").on('click','li', dContent)
$.each(myData, function(index,item) {
$("#courses").append("<li class='li' data-value="+item.content+">"+item.chapter+" <p>"+item.title+"</p></li>");
})
});
DEMO ON JSFIDDLE
this.[i].chapter should probably be myData[i].chapter. As it is, it's a syntax error.
Then you should rethink whether your other uses of this are correct.
Copying this into your JSFiddle and checking in jQuery as well, will make it work.
var jsonString = '[{"chapter":"General","title":"News forum","content":"Text1"},{"chapter":"CHAPTER 1","title":"1.1 Introduction","content":"Text2"},{"chapter":"CHAPTER 1","title":"1.2 Main Idea","content":"Text3"},{"chapter":"CHAPTER 2","title":"2.1 Architecture","content":"Text4"},{"chapter":"CHAPTER 3","title":"3.1 Liter.overview","content":"Text5"}]';
var myData = JSON.parse(jsonString);
$(document).ready(function() {
var $clist = $('#courses');
$.each(myData, function(i,o){
$('<li><h3>' +o.chapter+ '</h3><p>' +
'<a href="#page2" onclick="dContent(\''+o.content+'\')">' +
o.title + '</a></p></li>').appendTo($clist);
});
window.dContent = function(content) {
var $ccontent = $('#content');
$ccontent.append(content);
}
});
My scenario: I have an application that is 9 pages long for a total of about 125 inputs of varying types and sizes (only input, textarea, radio, and selects). I'd like to use local storage to save the form values. The user can move between the pages (e.g. to review before submitting the application) so I don't want to clear the local storage until they submit the application and if they change from page to page, the form should reload its values from local storage. Once they submit the form, then I'll clear the local storage but until then, the local storage should be retained.
I found this great jquery plugin and a demo page which appears to almost do what I'm looking for - well, with two exceptions:
1) The plugin prompts the user if they want to restore their previously entered info which I'd prefer to not have (I'd rather have the data just be there). My navigational buttons at the bottom of the form are simply "Previous" and "Continue" (on the first page, it is just "Continue" and on the last page they would be "Previous" and "Submit Application").
2) The plugin will prompt the user even if there is no data to load (this would be a non-issue if I can just have it load data if there is any and skip it if there is not). For example, the very first visit to the page will prompt the user to restore previously entered data.
Here is a link to the jquery.remember-state.js used in the demo page.
=======================================================
I took the demo above and tweaked the jquery.remember-state.js to try and make it do what I need but it isn't working correctly.
Here is my (jsFiddle).
NOTE 1: the jsFiddle is meant to just show my code and is not a necessarily a working example in the jsFiddle environment. If you copy the code to your local environment, you should be able to access the console.log to see if/what gets saved to the localStorage.
NOTE 2: S.O. wants formatted code inline so I'll see what I can do to make it format correctly.
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<title>LocalStorage and Unload State Save</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="../jQueryPlugins/RememberState/form.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- use the modified jquery.remember-state.js code in the JavaScript panel instead
the script tag below is the original js file
<script src="http://shaneriley.com/jquery/remember_state/jquery.remember-state.js"></script>-->
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
(function($) {
/* jQuery form remember state plugin
Name: rememberState
Version: 1.3
Description: When called on a form element, localStorage is used to
remember the values that have been input up to the point of either
saving or unloading. (closing window, navigating away, etc.) If
localStorage isn't available, nothing is bound or stored.
The plugin looks for an element with a class of remember_state to show
a note indicating there is stored data that can be repopulated by clicking
on the anchor within the remember_state container. If the element doesn't
exist, it is created and prepended to the form.
Usage: $("form").rememberState("my_object_name");
Notes: To trigger the deletion of a form's localStorage object from
outside the plugin, trigger the reset_state event on the form element
by using $("form").trigger("reset_state");
*/
if (!window.localStorage || !window.JSON) {
if (console && console.log) {
!window.localStorage && console.log("ERROR: you browser does not support" +
" localStorage (use this polyfill https://gist.github.com/350433)");
!window.JSON&& console.log("ERROR: you browser does not support" +
" JSON (use this polyfill http://bestiejs.github.com/json3/)");
}
return $.fn.rememberState = function() { return this; };
}
var remember_state = {
name: "rememberState",
clearOnSubmit: false, //default was true;
// ****************************
/*noticeDialog: (function() {
return $("<p />", {"class": "remember_state"})
.html('Do you want to restore your previously entered info?');
})(),*/
// ****************************
ignore: null,
noticeSelector: ".remember_state",
use_ids: false,
objName: false,
clickNotice: function(e) {
var data = JSON.parse(localStorage.getItem(e.data.instance.objName)),
$f = $(this).closest("form"),
$e;
for (var i in data) {
$e = $f.find("[name=\"" + data[i].name + "\"]");
if ($e.is(":radio, :checkbox")) {
$e.filter("[value=" + data[i].value + "]").prop("checked", true);
}
else if ($e.is("select")) {
$e.find("[value=" + data[i].value + "]").prop("selected", true);
}
else {
$e.val(data[i].value);
}
$e.change();
}
e.data.instance.noticeDialog.remove();
e.preventDefault();
},
chooseStorageProp: function() {
if (this.$el.length > 1) {
if (console && console.warn) {
console.warn("WARNING: Cannot process more than one form with the same" +
" object. Attempting to use form IDs instead.");
}
this.objName = this.$el.attr("id");
}
},
errorNoID: function() {
if (console && console.log) {
console.log("ERROR: No form ID or object name. Add an ID or pass" +
" in an object name");
}
},
saveState: function(e) {
var instance = e.data.instance;
var values = instance.$el.serializeArray();
// jQuery doesn't currently support datetime-local inputs despite a
// comment by dmethvin stating the contrary:
// http://bugs.jquery.com/ticket/5667
// Manually storing input type until jQuery is patched
instance.$el.find("input[type='datetime-local']").each(function() {
var $i = $(this);
values.push({ name: $i.attr("name"), value: $i.val() });
});
values = instance.removeIgnored(values);
values.length && internals.setObject(instance.objName, values);
},
save: function() {
var instance = this;
if (!this.saveState) {
instance = this.data(remember_state.name);
}
instance.saveState({ data: { instance: instance } });
},
removeIgnored: function(values) {
if (!this.ignore) { return values; }
$.each(this.ignore, function(i, name) {
$.each(values, function(j, input) {
if (name === input.name) { delete values[j]; }
});
});
return values;
},
init: function() {
var instance = this;
// ****************************
/* if (instance.noticeDialog.length && instance.noticeDialog.jquery) {
instance.noticeDialog.find("a").bind("click." + instance.name, {
instance: instance
}, instance.clickNotice);
}*/
// ****************************
instance.chooseStorageProp();
if (!instance.objName) {
instance.errorNoID();
return;
}
if (localStorage[instance.objName]) {
// ****************************
/*if (instance.noticeDialog.length && typeof instance.noticeDialog === "object") {
instance.noticeDialog.prependTo(instance.$el);
}
else {
instance.$el.find(instance.noticeSelector).show();
}*/
// ****************************
}
if (instance.clearOnSubmit) {
instance.$el.bind("submit." + instance.name, function() {
instance.$el.trigger("reset_state");
$(window).unbind("unload." + instance.name);
});
}
instance.$el.bind("reset_state." + instance.name, function() {
localStorage.removeItem(instance.objName);
});
// ****************************
/*$(window).bind("unload." + instance.name, { instance: instance }, instance.saveState);
instance.$el.find(":reset").bind("click.remember_state", function() {
$(this).closest("form").trigger("reset_state");
});*/
}
};
var internals = {
setObject: function(key, value) { localStorage[key] = JSON.stringify(value); },
getObject: function(key) { return JSON.parse(localStorage[key]); },
createPlugin: function(plugin) {
$.fn[plugin.name] = function(opts) {
var $els = this,
method = $.isPlainObject(opts) || !opts ? "" : opts;
if (method && plugin[method]) {
plugin[method].apply($els, Array.prototype.slice.call(arguments, 1));
}
else if (!method) {
$els.each(function(i) {
var plugin_instance = $.extend(true, {
$el: $els.eq(i)
}, plugin, opts);
$els.eq(i).data(plugin.name, plugin_instance);
plugin_instance.init();
});
}
else {
$.error('Method ' + method + ' does not exist on jQuery.' + plugin.name);
}
return $els;
};
}
};
internals.createPlugin(remember_state);
})(jQuery);
});//]]>
</script>
<script>
var thisPage = 'page1'; //defines the variable to use for local storage
$(function() {
$("form")
.rememberState({objName: thisPage})
.submit(function() {localStorage.setItem(thisPage, $(this).serializeArray());
return true;
});
});
</script>
</head>
<body>
<form method="post" action="page2.cfm">
<fieldset>
<dl>
<dt><label for="first_name">First Name</label></dt>
<dd><input type="text" name="first_name" id="first_name" /></dd>
<dt><label for="last_name">Last Name</label></dt>
<dd><input type="text" name="last_name" id="last_name" /></dd>
</dl>
</fieldset>
<fieldset class="actions">
<input type="submit" value="Continue" />
</fieldset>
</form>
</body>
</html>
I thought this was going to be tougher than it was. Here is the solution I came up with:
On the form page when the submit button is pressed:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var thisPageID = 'page1'; // each page gets its own
$('form').submit(function() {
var formFields = $(this).serialize();
localStorage.setItem(thisPageID, formFields);
data = localStorage.getItem(thisPageID);
return true;
});
});
</script>
Then on the final page, I retrieve the data for each page by its page id from the local storage and populate my div tags with the data.
function getLocalData(id){
var ApplicantData;
ApplicantData = localStorage.getItem(id);
if (ApplicantData){
$.each(ApplicantData.split('&'), function (index, elem) {
var vals = elem.split('=');
var $div = $("#"+vals[0]);
var separator = '';
// console.log($div);
if ($div.html().length > 0) {
separator = ', ';
}
$div.html($div.html() + separator + decodeURIComponent(vals[1].replace(/\+/g, ' ')));
});
}
}
Some of the Articles that helped me (some SO, some external):
- Clear localStorage
- http://www.simonbingham.me.uk/index.cfm/main/post/uuid/using-html5-local-storage-and-jquery-to-persist-form-data-47
- http://www.thomashardy.me.uk/using-html5-localstorage-on-a-form
There were more but this is all I still had open in tabs.
Can some one help me make the following JSON data:
{
"main": {
"label":"Main",
"url":"#main"
},
"project": {
"label":"Project",
"url":"#project"
},
"settings": {
"label":"Settings",
"url":"#settings",
"subnav":[
{
"label":"Privacy",
"url":"#privacy"
},
{
"label":"Security",
"url":"#security"
},
{
"label":"Advanced",
"url":"#advanced"
}
]
}
}
into the following bullets list using JS? Assuming you don't know what the first nodes are call labeled (e.g. "main", "project" <- these will be dynamically generated):
Main (#main)
Project (#project)
Settings (#settings)
Privacy (#privacy)
Security (#security)
Advanced (#advanced)
Thanks
Let's not use HTML string-hacking, shall we? That would break as soon as any of the data had characters like < or & in (or " in attribute values). Use DOM methods and you don't have to worry about character escaping:
function createNav(navs) {
var ul= document.createElement('ul');
for (name in navs) {
var nav= navs[name];
var a= document.createElement('a');
a.href= nav.url;
a.appendChild(document.createTextNode(nav.label));
var li= document.createElement('li');
li.id= 'nav-'+name;
li.appendChild(a)
if ('subnav' in nav)
li.appendChild(createNav(nav.subnav));
ul.appendChild(li);
}
return ul;
}
document.getElementById('navcontainer').appendChild(createNav(jsondata));
Most JS frameworks offer shortcuts to make this a bit less wordy. For example with jQuery:
function createNav(navs) {
var ul= $('<ul>');
for (name in navs) {
var nav= navs[name];
var li= $('<li>', {id: name});
li.append($('<a>', {href: nav.url, text: nav.label}));
if ('subnav' in nav)
li.append(createNav(nav.subnav));
ul.append(li);
}
}
$('#navcontainer').append(createNav(jsondata));
Note that either way, you're using an Object literal which means you get no control over the order the list of navs comes out. You have no guarantee that main will be above project. If you want a defined order, you will have to have the returned JSON data be an array.
My code is on JSfiddle.
As JSON parser I used this one.
The main code is a recursive renderer of the parsed JSON:
function recursive_parse(result) {
var html = '<ul>';
for (var k in result) {
html = html + '<li>' + result[k].label + ' (' + result[k].url + ')';
html = html + recursive_parse(result[k].subnav);
html = html + '</li>';
}
html = html + '</ul>';
return html;
}
var result = json_parse($("div#test1111").html());
var html = recursive_parse(result);
$("div#test2222").html(html);