SQLite access in Javascript - javascript

I want to access Sql Lite Database with JavaScript code. The JavaScript code is used in html5 and has to be deployed on blackberry 10 platform.
I use the following code without success:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<title>Prova</title>
</head>
<body>
<script type="text/javascript">
//Provenia SRL ITC - Paola Savioli
//Questa funzione apre il database SQL Lite
//Il parametro che va cambiato è il nome del database
function ApriDatabase() {
try {
if (window.openDatabase) {
var shortName = 'Ristoranti.sqllite';
var version = '1.0';
var displayName = 'Ristoranti italia';
var maxSize = 65536; // in bytes
db = openDatabase(shortName, version, displayName, maxSize);
}
} catch (e) {
alert('Apri Database' + e);
}
}
//Provenia SRL ITC - Paola Savioli
// Questa funzione eseque una query su un database aperto con la funzione ApriDatabase
function EseguiQuery($query, callback) {
try {
ApriDatabase();
if (window.openDatabase) {
db.transaction(
function (tx) {
tx.executeSql($query, [], function (tx, result) {
if (typeof (callback) == "function") {
callback(result);
} else {
if (callback != undefined) {
eval(callback + "(result)");
}
}
}, function (tx, error) {});
});
return rslt;
}
} catch (e) {
alert('Esegui Query' + e);
}
}
function VisualizzaComuni() {
try {
var schemanode = document.GetElementById('RCOMUNI');
schemanode.innerHTML = "";
var result = EseguiQuery('SELECT * FROM COMUNE');
for (var i = 0; i < result.rows.lenght; ++i) {
var row = result.row.item(i);
var notediv = document.createElement('div');
notediv.innerHTML = 'Codice Provincia:' + row['PROVINCIA'] + 'Nome:' + row['NAME'];
schemanode.appendchild(notediv);
}
} catch (e) {
alert('Visualizza Comuni' + e);
}
}
</script>
<input type="button" name='select' onClick="VisualizzaComuni()"
value='Visualizza Comuni'>
<div id="RCOMUNI"></div>
</body>
</html>

You may consider using the WebSQL API, which is supported on BlackBerry 7 and 10 according to http://caniuse.com/#feat=sql-storage.
Note that the API will never become an official standard and development on it has stopped. But if you just want to target BlackBerry, it may be a valid choice.

There were a few problems with the code you've posted, including a reference to .lenght instead of .length and use of try catch blocks when there are success and error handlers built-in. So I worked up a demo.
First, it does not seem to make a difference, but this is HTML5 right? Instead of an HTML 4.01 Transitional doctype, use the HTML5 doctype:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>demo by userdude</title>
...
Next, I modified the markup for the purposes of the demonstration. In this case, we have:
<body>
<input type="button" id="run" value='Run Query'>
<div id="query"></div>
<table id="table" border="1" cellspacing="1" cellpadding="5"></table>
</body>
</html>
In the head element, I use an event listener to wait for the DOM to load. Keep in mind, I do not have a Blackberry to test this with, and with Blackberry or other devices, you should probably use deviceready instead of load. I think. I also attach the event handler for button that run's the query using .addEventListener, but notice I do that within the load handler. You have to wait before trying to access the DOM.
Also, IE supports attachEvent instead of addEventListener. I would imagine Blackberry supports the latter, but I'm not sure.
window.addEventListener('load', function load(){
var run = document.getElementById('run'),
data = document.getElementById('table'),
qtext = document.getElementById('query'),
dropped = false,
created = false,
cities = ['Houston', 'Dallas', 'Paris', 'New York', 'Buenos Aires', 'London'],
shortName = 'Cities',
version = '1.0',
displayName = 'Cities Demo',
maxSize = 5 * 1024 * 1024,
db = false,
queries = [];
run.addEventListener('click', query);
This establishes my database, including running the initial call to populate() so we have some data use.
open();
This is the function I added to the run button.
function query() {
transact('SELECT * FROM Cities', view);
}
This is just meant to add data to the database. See the cities variable above.
function populate(tx) {
var city,
i = 0;
I block this from running once I've emptied the cities array of entries to INSERT. dropped and created do the same thing for the DROP and CREATE transactions.
Take special note how I'm doing this; see the transact('...', populate)? I use populate in this situation to loop back until I've finished adding all of the cities entries. This is asynchronous, so you have to setup the callbacks to wait if necessary for the previous queries to run. In this case, I could end up dropping the table after adding my rows. So I have to wait, then loop through the cities list.
if (cities) {
if (!dropped) {
dropped = true;
transact('DROP TABLE IF EXISTS Cities', populate);
return;
}
if (!created) {
created = true;
transact('CREATE TABLE IF NOT EXISTS Cities (id unique, City)', populate);
return;
}
I don't need to iterate back to populate here, since I just need to INSERT and move on.
while (city = cities.pop()) {
transact('INSERT INTO Cities (id, City) VALUES (' + i++ + ', "' + city + '")');
}
cities = false;
}
}
All this function does is give either an opened or new reference to the database, or return false. This short-circuits the execution of transact().
function open() {
if (!db && window.openDatabase) {
db = window.openDatabase(shortName, version, displayName, maxSize);
}
if (cities) {
db.transaction(populate);
}
return db;
}
This is the meat of the script. I call it from query(), and the callback in this case is view, which points to the function which runs through the result set and creates a table from the set.
function transact(query, callback) {
var cb = callback,
qel = document.createElement('p'),
qid = queries.length;
if (!open()) {
console.log('HTML5 Database not supported.');
return false;
}
db.transaction(transact_cb);
qel.innerHTML = query + ' Query Result: <span id="q' + qid + '">Pending...</span>';
qtext.appendChild(qel);
queries[qid] = query;
Note the last two arguments, transact_success, transact_error. This is how you handle these asynchronous calls.
function transact_cb(tx) {
tx.executeSql(query, [], transact_success, transact_error);
}
Not quite sure why there's an eval in there...?
function transact_success(tx, result) {
var rtext = document.getElementById('q' + qid);
rtext.className = 'success';
rtext.innerHTML = 'Success.';
if (typeof cb == "function") {
cb(result);
} else if (cb != undefined) {
eval(cb + "(result)");
}
}
Note the console.log(error);.
function transact_error(tx, error) {
var rtext = document.getElementById('q' + qid);
rtext.className = 'error';
rtext.innerHTML = 'Error logged to console.';
console.log(error);
}
}
And this function creates the table result set view. You'll probably notice I loop through each row, and each row's columns.
function view(result) {
var thead = '<thead><tr>',
tbody = '<tbody>',
row,
col;
for (var i = 0, rows = result.rows.length; i < rows; ++i) {
row = result.rows.item(i);
tbody += '<tr>';
for (col in row) {
if (i === 0) {
thead += "<th>" + col + "</th>";
}
tbody += '<td>' + row[col] + '</td>';
}
tbody += '</tr>';
}
thead += '</tr></thead>';
tbody += '</tbody>';
data.innerHTML = thead + tbody;
}
});
You can download the file and run it locally (due to a security error, it won't run on jsFiddle) by downloading the HTML file here:
http://pastebin.com/FcSiu6ZZ
So there you go. Hopefully that will help make this easier to understand. Let me know if you have any questions.

Related

How to Add an Expand All button to a javascript/HTML project

I currently have a page that has content that expands when you click on a term, but as soon as you click on a new term the old one closes and the new one expands. The terms are loaded in from a google sheet onto the page. This is on a HTML page but the javascript code to do the work is the following:
// Address of the Google Sheets Database
var public_spreadsheet_url = 'sheet link here';
// Column Names from Google Sheets Database
let questionsColumn = "Question";
let answersColumn = "Answer";
window.addEventListener('DOMContentLoaded', init) // Calls method init when Sheets has loaded
function init() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
simpleSheet: true } );
}
var unhiddenAnswer = "";
// Method that gets called when data has been pulled from Google Sheets
function showInfo(data) {
var editButton = '<center><a style="border-bottom: none" href="' + public_spreadsheet_url + '"><button class="button admin">Edit</button></a></center>';
// Injects the built HTML code into the div Dynamic
document.getElementById("dynamic").innerHTML = buildFAQTable(data) + editButton;
}
// Builds the HTML Table code from the Database Data
function buildFAQTable(data) {
var index = 0;
var content = '<h2>Title Here</h2><div style="padding:0px 5%">';
data.forEach(form => {
content += '<h1 class="faq_question" onClick="unhideAnswer(' + index + ')">' + data[index][questionsColumn] + '</h1>';
content += '<p id="answer' + index + '" class="hideAnswer">' + data[index][answersColumn] + '</p>';
index++;
});
// Extends body to accomdate for tall footer on very small devices (e.g. iPhone 5/5S/SE)
content += "<br></br><br></br>";
return content;
}
// When a FAQ Question gets clicked on, this method will hide the currently displaying answer (if any), and
// Unhide the answer corresponding to the clicked on answer.
// If the currently displaying answer is the same as the answer corresponding to the clicked on question,
// it will be hidden and no new answer will be unhidden
function unhideAnswer(number) {
var answerID = "answer" + number;
if (answerID != unhiddenAnswer) {
document.getElementById(answerID).classList.remove("hideAnswer");
}
if (unhiddenAnswer != "")
document.getElementById(unhiddenAnswer).classList.add("hideAnswer");
if (unhiddenAnswer == answerID)
unhiddenAnswer = ""
else
unhiddenAnswer = answerID;
}
I want to now add an expand all/ collapse all button to give the user the option to open and view all the terms at one if needed. However, if not using the expand all button, the regular open and close functionality above should be used. I am new to javascript and am at a loss on the best way to implement this. Any help would be appreciated.
add a answer class to every answer, then you can loop through all of them with this query selector
// in your buildFAQTable fucntion
content += '<p id="answer' + index + '" class="hideAnswer answer">' + data[index][answersColumn] + '</p>';
document.querySelectorAll('.answer').forEach(answer => {
// you can use toggle, add or remove to change the appearance of the answer
answer.classList.toggle('hideAnswer')
})
i would also recomend you to check out some of the newer javascript features like string interpolation and avoid using var, but it is not so important if you are just starting out.
(i also refactored some of your code, this might make it a bit more readable)
// Address of the Google Sheets Database
const public_spreadsheet_url = 'sheet link here';
// Column Names from Google Sheets Database
const questionsColumn = "Question";
const answersColumn = "Answer";
function toggleAnswer(num) {
const answer = document.getElementById(`answer${num}`);
answer.classList.toggle('hideAnswer');
}
function hideAll() {
document.querySelectorAll('answer').forEach(answer => {
answer.classList.add('hideAnswer');
})
}
function showAll() {
document.querySelectorAll('answer').forEach(answer => {
answer.classList.remove('hideAnswer');
})
}
function buildFAQTable(data) {
let index = 0;
let content = '<h2>Title Here</h2><div style="padding:0px 5%">';
for (i in data) {
content += `<h1 class="faq_question" onClick="unhideAnswer(${i})">${data[i][questionsColumn]}</h1>`;
content += `<p id="answer${i}" class="hideAnswer answer">${data[i][answersColumn]}</p>`;
}
content += "<br></br><br></br>";
return content;
}
function showInfo(data) {
const editButton = `<center><a style="border-bottom: none" href="${public_spreadsheet_url}"><button class="button admin">Edit</button></a></center>`;
document.getElementById("dynamic").innerHTML = buildFAQTable(data) + editButton;
}
window.addEventListener('DOMContentLoaded', () => {
Tabletop.init({
key: public_spreadsheet_url,
callback: showInfo,
simpleSheet: true
});
}, { once: true })

Preserve JSON arrays while sorting

I have two JSON arrays coming from an external website. I sort and merge the two arrays, decode them and then sort them from highest to lowest by ID.
Currently, when the option 'alphabetical' is clicked, ?sort=alphabetical is added onto the end of the URL and when the page has finished reloading, the JSON arrays are once again decoded and merged.
This is not my desired outcome: I do not want the JSON arrays to be decoded and merged again when the option is clicked - I simply want the already decoded and merged JSON arrays to be sorted alphabetically.
Arrays:
$homepage = array();
$homepage[]= '{
"info":{
"collection":[
{
"Name":"Charlie",
"ID":"7"
},
{
"Name":"Emma",
"ID":"9"
}
]
}
}';
$homepage[] = '{
"info":{
"collection":[
{
"Name":"Bob",
"ID":"5"
}
]
}
}';
Sorting:
$data = array();
foreach ($homepage as $homepage2) {
$tmp=json_decode($homepage2, false);
$data = array_merge($data,$tmp->info->collection);
}
if(!empty($_GET['sort']) && $_GET['sort'] == 'alphabetical') {
usort($data, function ($a, $b) {
return strcmp($a->Name, $b->Name);
});
}else{
usort($data, function ($a, $b) {
return $b->ID - $a->ID;
});
}
echo'
<select onchange="location.href = this.value;">
<option value="example.php?sort=alphabetical">Alphabetical</option>
</select>
';
foreach($data as $key) {
echo'
<a href="test.com">
<p>'.$key->ID.'</p>
<p>'.$key->Name.'</p>
</a>
';
}
You could use JavaScript for doing the sorting on click, and use PHP only for passing the JSON to it.
After you provided the HTML structure you want to display the list in, I updated this answer to use div elements for the records and p elements for the fields.
We could replace the select list, for selecting the sort order, by two buttons.
Here is the PHP code:
<?php
$homepage = array();
$homepage[]= '{
"info":{
"collection":[
{
"Name":"Charlie",
"ID":"13"
},
{
"Name":"Emma",
"ID":"9"
}
]
}
}';
$homepage[] = '{
"info":{
"collection":[
{
"Name":"Bob",
"ID":"10"
}
]
}
}';
$data = array();
foreach ($homepage as $homepage2) {
$tmp=json_decode($homepage2, false);
$data = array_merge($data,$tmp->info->collection);
}
?>
<div id="container"></div>
<button id="sort1">Alphabetical</button>
<button id="sort2">High to Low</button>
<script>
var collection = <?=json_encode($data)?>;
function populate(compareFunc) {
collection.sort(compareFunc);
var container = document.getElementById('container');
container.innerHTML = '';
collection.forEach(function (key) {
var div = document.createElement("div");
div.className = "inventory";
var span = document.createElement("span");
span.textContent = key.ID;
div.appendChild(span);
span = document.createElement("span");
span.textContent = key.Name;
div.appendChild(span);
container.appendChild(div);
});
}
var populateById = populate.bind(null, function (a, b) {
return a.ID - b.ID;
});
var populateByName = populate.bind(null, function (a, b) {
return a.Name.localeCompare(b.Name);
});
document.getElementById("sort1").addEventListener('click', populateByName);
document.getElementById("sort2").addEventListener('click', populateById);
document.addEventListener('DOMContentLoaded', populateById);
</script>
For the sample data this will result in the following JavaScript/HTML, which you can test here:
var collection = [{"Name":"Charlie","ID":"13"},{"Name":"Emma","ID":"9"},{"Name":"Bob","ID":"10"}];
function populate(compareFunc) {
collection.sort(compareFunc);
var container = document.getElementById('container');
container.innerHTML = '';
collection.forEach(function (key) {
var div = document.createElement("div");
div.className = "inventory";
var span = document.createElement("span");
span.textContent = key.ID;
div.appendChild(span);
span = document.createElement("span");
span.textContent = key.Name;
div.appendChild(span);
container.appendChild(div);
});
}
var populateById = populate.bind(null, function (a, b) {
return a.ID - b.ID;
});
var populateByName = populate.bind(null, function (a, b) {
return a.Name.localeCompare(b.Name);
});
document.getElementById("sort1").addEventListener('click', populateByName);
document.getElementById("sort2").addEventListener('click', populateById);
document.addEventListener('DOMContentLoaded', populateById);
span { margin-left: 5px }
div.inventory { border-bottom: 1px solid gray }
<div id="container"></div>
<button id="sort1">Alphabetical</button>
<button id="sort2">High to Low</button>
Note that I gave the three items different ID values than in your question, since otherwise the sort order would be the same for both ID and Name.
Using tables: alternative
There are nice JavaScript libraries which give much more features to represent data sets. Here is an example using jQuery with DataTables:
var collection = [{"Name":"Charlie","ID":"13"},{"Name":"Emma","ID":"9"},{"Name":"Bob","ID":"5"}];
function populate() {
var tbody = $('#collection>tbody');
collection.forEach(function (key) {
var row = $('<tr>');
row.append($('<td>').text(key.ID));
row.append($('<td>').text(key.Name));
tbody.append(row);
});
}
$(document).ready(function(){
populate();
$('#collection').DataTable();
});
<script src="http://code.jquery.com/jquery-1.12.3.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<table id="collection">
<thead>
<tr><th>ID</th><th>Name</th></tr>
</thead>
<tbody/>
</table>
The actual code is even smaller (not counting the included library) than a pure JavaScript solution would be with a basic table. But this has sorting up and down, filtering, pagination, nice styles, ...
There are several alternatives for this answer, so I will present a simple one:
Send the data already sorted, a default one, if the user made no choices. Then, set a function that sorts the data as needed, and redraws tables/divs/whatever you are using to present them.
As an quick example:
function sortAlpha(){
for each (stuff in data){
document.getElementById("aTable").textContent=data.StringRepresentation;
}
}
Then a function for sortSize, sortEtc, etc... in each function, you clear a div content, and populate it again. This way, you do not need to request new content from servers
getElementById documentation
There are multiple solutions in which you can achieve the desired results. If you want it pure PHP way what you can do is save the data in PHP Sessions and retrive them as need.
Here is the trick comes, You create function to get the result data in which you pass single parameter whether you want to get the data from external URL or from your saved data.
Now, in your application whenever you want to refresh the saved data call the same function with parameter denoting to refresh the saved data in SESSIONS to get replaced with data from external source.
Using this method you can reuse the data you've already fetched from external source without re-fetching it every-time you reload the function.
You can make another function which will return true for all cases in which application has to re-fetch the resultset from external source.
I've written pseudo code for you to understand what I'm trying to convey,
Function check whether we've to re-fetch the result from external source:
function hasToRefreshResult() {
if(/* CERTAIN CONDITIONS */) {
return true;
}
return false;
}
Couple of functions to get the data from local/external source according to the parameter passed:
function getResultArray($getdatafromlocal) {
if(!hasToRefreshResult() && $getdatafromlocal && array_key_exists("filertereddata",$_SESSION) && isset($_SESSION["filertereddata"])) {
$data=$_SESSION["filertereddata"];
} else {
$data=getDataFromExternalURL();
}
if(!empty($_GET['sort']) && $_GET['sort'] == 'alphabetical') {
usort($data, function ($a, $b) {
return strcmp($a->Name, $b->Name);
});
} else {
usort($data, function ($a, $b) {
return $b->ID - $a->ID;
});
}
return $data;
}
function getDataFromExternalURL() {
/*****
YOUR LOGIC TO GET DATA FROM EXTERNAL URL;
*****/
$data = array();
foreach ($homepage as $homepage2) {
$tmp=json_decode($homepage2, false);
$data = array_merge($data,$tmp->info->collection);
}
$_SESSION["filertereddata"]=$data;
return $data;
}
I hope this will solve your issue strictly using PHP.
Also don't forget the write session_start(); at the top of the PHP file you will be using this functions.

get file contents from a url using jquery

Is there any way to get the city and state name from zip code from google api using jquery(not using ajax).
I can get the details from here http://maps.googleapis.com/maps/api/geocode/json?address=17078&sensor=true.
and my code is
var googleAPI = "http://maps.googleapis.com/maps/api/geocode/json?address=17078&sensor=true";
$.getJSON(googleAPI, function (response) {
console.log("JSON Data: " + response.items);
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
// in production code, item.text should have the HTML entities escaped.
//document.getElementById("content").innerHTML += "<br>" + item.volumeInfo.title;
alert(item.address_components);
}
});
but this is not working
You have to find the administrative_area_level_1 and administrative_area_level_2 which gives you the state and city names.
Read Geocoding docs
Try this,
<script>
// let you got the items.address_components
for(var a=0,len=items.address_components.length;a<len;a++)
{
ac=items.address_components[a];
if(ac.types)
{
for(var t=0,tl=ac.types.length;t<tl;t++)
{
ty=ac.types[t];
if(ty=='administrative_area_level_1')
{
alert('State'+ac.long_name);
}
if(ty=='administrative_area_level_2')
{
alert('City'+ac.long_name);
}
}
}
}
</script>

Local Storage to hold form N pages data until final submit

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.

Javascript not displaying unicode

I am using Javascript to display headers on a SharePoint site, according to a column that I have specified HTML in. Here is the HTML.
<DIV style ='text-align:center; font-weight:bold; font-size: 20px;'>◆</DIV>
The problem is that the script, while rendering the HTML properly within the page, does not do the same for header. It works 90% of the way, but instead of displaying the unicode "◆", it renders "â".
I've already tried modifying the Javascript to try to account for the unicode \u25c6, but I'm failing miserably. Can anyone help me out or provide me some clues as to why this is happening?
Here is the Javascript.
<script type="text/javascript">
// Find all Web Parts in the page
var listWP = [],
calWP = [],
divs = document.getElementById("MSO_ContentTable").getElementsByTagName("div");
var count=divs.length;
for (i=0;i<count;i++) {
try {
if (divs[i].id.indexOf("WebPartWPQ")==0){
if (divs[i].innerHTML.indexOf("ViewDefault_CalendarView")>=0) {
// Calendars
calWP.push(divs[i].id);
} else {
// Other Web Parts
listWP.push(divs[i].id);
}
}
}
catch(e){}
}
function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i=0;
while (i < NodeSet.length){
try {
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent)) {
NodeSet[i].innerHTML = CellContent;
}
}
catch(err){}
i=i+1;
}
}
var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
var WP = new Object;
function UpdateWP() {
if (calWP.length>0){
for (i=0;i<calWP.length;i++) {
WP=document.getElementById(calWP[i]);
if (WP.innerHTML.indexOf("&lt\;")>=0) {
TextToHTML(WP.getElementsByTagName ("a"),regexpA);
}
}
}
if (listWP.length>0){
for (i=0;i<listWP.length;i++) {
WP=document.getElementById(listWP[i]);
if (WP.innerHTML.indexOf("&lt\;")>=0) {
TextToHTML(WP.getElementsByTagName ("td"),regexpTD);
}
}
}
// Check every 200000000 ms, forever
setTimeout("UpdateWP()",200000000);
}
UpdateWP();
function HeaderToHTML(){
var headers=document.getElementById("MSO_ContentTable").getElementsByTagName("li");
var regexpTR1 = new RegExp("FilterValue1=([\\S\\s]*)'\\)");
var regexpTR2 = new RegExp("FilterValue2=([\\S\\s]*)'\\)");
for (i=0;i<headers.length;i++) {
try{
var sp=headers[i].getElementsByTagName("span");
for (j=0;j<sp.length;j++) {
var test = sp[j].innerText || sp[j].textContent || " ";
//var test = sp[j].innerText;
if (test.indexOf("...")>0) {
//alert(test);
//var value = regexpTR1.exec(headers[i].innerHTML)[1];
var inner = headers[i].innerHTML;
var value = (inner.indexOf("FilterValue2")>0) ? regexpTR2.exec(headers[i].innerHTML) [1] : regexpTR1.exec(headers[i].innerHTML)[1];
//alert(value);
//alert(value.replace(/\\u00/g,"\%"));
value=value.replace(/\\u00/g,"%");
sp[j].innerHTML=unescape(unescape(value)).replace(/8_/," ");
}
}
}catch(e){}
}
}
setInterval(function(){HeaderToHTML();},100);
</script>
I would suggest using the html dex/dec for the symbols.
that is,
◆ = ◆
◆ = ◆
Wikipedia has a nice list of them broken into categories here.
I found the black diamond you're trying to write here
I think a solution could be to render your character in its encoding and let browser know about it via:
<meta http-equiv="Content-Type" content="text/html; charset="...">
For example, if you are using UTF-8:
<meta http-equiv="Content-Type" content="text/html; charset="UTF-8">

Categories