I have been working on a project that allows the user to submit memories about a place they have visited and tracks the location of when the memory was submitted. My only problem is trying to use localStorage with the app, I read about the JSON.stringify and JSON.parse, and don't understand how to use them in my code yet.
This is my form.js
It processes the form and grabs the text fields. It clears the form when the add button(on the display details page) or the enter details button is clicked. Finally it receives the information and sends out the message back to the window.
function processForm(){
var locate = document.myform.locate.value;
var details = document.myform.details.value;
var storeData = [];
localStorage.setItem("locate", JSON.stringify(locate));
localStorage.setItem("details", JSON.stringify(details));
alert("Saved: " + localStorage.getItem("locate") + ", and " + localStorage.getItem("details"));
var date = new Date,
day = date.getDate(),
month = date.getMonth() + 1,
year = date.getFullYear(),
hour = date.getHours(),
minute = date.getMinutes(),
ampm = hour > 12 ? "PM" : "AM";
hour = hour % 12;
hour = hour ? hour : 12; // zero = 12
minute = minute > 9 ? minute : "0" + minute;
hour = hour > 9 ? hour : "0" + hour;
date = month + "/" + day + "/" + year + " " + hour + ":" + minute + " " + ampm;
localStorage.setItem("date", JSON.stringify(date));
storeData.push(locate, details, date);
localStorage.setItem("storeData", JSON.stringify(storeData));
}
function clearForm(){
$('#myform').get(0).reset();
}
function retrieveFormInfo(){
var data = JSON.parse(localStorage.getItem("storeData"));
var locate = JSON.parse(localStorage.getItem("locate"));
$("#locate2").html("Place: " + locate);
var details = JSON.parse(localStorage.getItem("details"));
$("#details2").html("Description: " + details);
var date = JSON.parse(localStorage.getItem("date"));
$("#date").html(date);
}
But the major problem I am running into is I do know how to take that information in correctly using the JSON.stringify and JSON.parse and appending it to the window with html elements dynamically, Mainly like a list of memories.
Any help is appreciated!
localStorage stores key value pairs as strings only (you can use integer for keys but they get converted to string automatically).
Storage objects are simple key-value stores, similar to objects, but they stay intact through page loads. The keys and the values are always strings (note that, as with objects, integer keys will be automatically converted to strings) reference
let's say you have an array to be stored with each item being a json object.
You got 2 options:
Option 1:
stringify every item and store in locaStorage
var item = {input1: 'input1value', input2: 'input2value' };
localStorage.setItem( itemIndex, JSON.stringify(item) );
to retrive the items iterate over localStorage items and then convert the item to JSON object:
for(var i=0;i<localStorage.length; i++) {
var key = localStorage.key( i );
var item = JSON.parse( localStorage.getItem( key ) );
}
Option 2:
stringify the entire array and store in localStorage
localStorage.setItem( 'memoriesdata', JSON.stringify( arr ) );
to read the data read the item as string then convert to JSON object
var arr = JSON.parse( localStorage.getItem('memoriesdata') );
First get values of your input fields into a javascript object.
var myMemory = {};
myMemory.location = document.getElementById('location').value;
myMemory.description = document.getElementById('description').value;
Now save myMemory to localStorage,this can be done on a form submission or a button press. We can store as an array of memories and add item to it every time.
//if user already has memories in local, get that array and push into it.
//else create a blank array and add the memory.
memories = localStorage.getItem('memories') ?
JSON.parse(localStorage.getItem('memories')) :
[];
memories.push(myMemory);
localStorage.setItem('memories', JSON.stringify(memories));
I use this Storage implementation. It's inspired by many storage plugins out there... It handles any value serilizable by JSON.stringify function, and should work xbrowser (and in 'cookie-disabled' firefox):
//
// api:
//
// .clear() empties storage
// .each() loops storage (key, value) pairs
// .fetch() get a value by key
// .has() checks if there is a key set
// .ls() lists all keys
// .raw() string value actually stored
// .reload() reads in serialized data
// .rm() removes key(s)
// .set() setup value(s)
// .type() storage type used 'localStorage/globalStorage/userData'
// .valid() is storage engine setup correctly
//
;
((function(name, def, glob, doc) {
// add 'store' id to globals
this[name] = def(glob, doc);
}).call(
this, "store", function(glob, doc) {
// private (function) store version
var stclient;
var driver = {
// obj : storage_native{},
// type : storage_type
};
var engine = {
// read : (func),
// write : (func)
};
var _ = {
a: Array.prototype,
del: function(node) { // , ...fields
_.slc(arguments, 1).
forEach(function(field) {
delete this[field];
}, node);
return node;
},
each: function(array, callback, context) {
context ||
(context = array);
array.
some(function() {
return false === callback.apply(context, arguments);
});
return array;
},
hasown: Function.prototype.call.bind(Object.prototype.hasOwnProperty),
jsdc: JSON.parse, // decode
jsec: JSON.stringify, // encode
keys: Object.keys, // shimed .keys
ns: "storage5", // single property name to keep serialized storage data under
object: null, // parsed storage data
slc: Function.prototype.call.bind(Array.prototype.slice),
test: {
isemptyobj: function(node) {
for (var x in node)
return false;
return true;
},
isplainobj: function(node) {
return '[object Object]' == Object.prototype.toString.call(node);
},
},
testval: 'storage' + Math.random(), // test value for implementation check
rig: function(target, items) {
for (var field in items)
if (items.hasOwnProperty(field))
target[field] = items[field];
return target;
},
clone: function(node) {
return _.jsdc(_.jsec(node));
},
puts: function() {
engine.write(_.jsec(_.object));
},
};
stclient = function storage5() {
return arguments.length ?
storage5.set.apply(storage5, arguments) :
storage5.fetch();
};
// _init on load|ready
window.addEventListener('load', _init, false);
return _.rig(stclient, {
clear: function() {
return _.object = {}, _.puts(), this;
},
each: function(callback, context) {
context ||
(context = this.fetch());
_.each(this.ls(), function(field) {
return callback.call(context, field, this.fetch(field));
}, this);
return this;
},
fetch: function(key) {
return (arguments.length) ?
_.object[key] : _.clone(_.object);
},
has: function(name) {
return _.hasown(_.object, name);
},
ls: function() {
return _.keys(_.object);
},
raw: function() {
return engine.read();
},
reload: _load,
rm: function() {
_.del.apply(null, _.a.concat.apply([_.object], arguments));
return _.puts(), this;
},
set: function(input, value) {
var len = arguments.length;
var flag = 1;
if (len) {
if (_.test.isplainobj(input)) {
_.keys(input).
forEach(function(field) {
_.object[field] = input[field];
});
} else {
if (1 < len)
_.object[input] = value;
else
flag = 0;
}
flag && _.puts();
}
return this;
},
type: function() {
return driver.type || null;
},
valid: function() {
return !_.test.isemptyobj(driver);
},
});
function _init() {
var flag = 0;
var stnative;
if ("localStorage" in glob) {
try {
if ((stnative = glob["localStorage"])) {
// inits localStorage
_initlocst(stnative, driver, engine);
flag = 1;
}
} catch (e) {}
}
if (!flag) {
if ("globalStorage" in glob) {
try {
if ((stnative = glob["globalStorage"])) {
// inits globalStorage
_initglobst(stnative, driver, engine);
flag = 1;
}
} catch (e) {}
}
if (!flag) {
// inits userDataStorage
_initusrdatast(doc.createElement(_.ns), driver, engine);
}
}
// parse serialized storage data
_load();
}
function _initlocst(stnative, driver, engine) {
stnative[_.testval] = _.testval;
if (_.testval === stnative[_.testval]) {
try {
stnative.removeItem(_.testval);
} catch (e) {
try {
delete stnative[_.testval];
} catch (e) {}
}
driver.obj = stnative;
driver.type = "localStorage";
engine.read = function() {
return driver.obj[_.ns];
};
engine.write = function(stringvalue) {
driver.obj[_.ns] = stringvalue;
return stringvalue;
};
}
}
function _initglobst(stnative, driver, engine) {
var host = glob.location.hostname;
driver.obj = (/localhost/i).test(host) ?
stnative["localhost.localdomain"] : stnative[host];
driver.type = "globalStorage";
engine.read = function() {
return driver.obj[_.ns];
};
engine.write = function(stringvalue) {
driver.obj[_.ns] = stringvalue;
return stringvalue;
};
}
function _initusrdatast(node, driver, engine) {
try {
node.id = _.ns;
node.style.display = "none";
node.style.behavior = "url('#default#userData')";
doc.
getElementsByTagName("head")[0].
appendChild(node);
node.load(_.ns);
node.setAttribute(_.testval, _.testval);
node.save(_.ns);
if (_.testval === node.getAttribute(_.testval)) {
try {
node.removeAttribute(_.testval);
node.save(_.ns);
} catch (e) {}
driver.obj = node;
driver.type = "userData";
engine.read = function() {
return driver.obj.getAttribute(_.ns);
};
engine.write = function(stringvalue) {
driver.obj.setAttribute(_.ns, stringvalue);
driver.obj.save(_.ns);
return stringvalue;
};
}
} catch (e) {
doc.
getElementsByTagName("head")[0].
removeChild(node);
}
node = null;
}
function _load() {
try {
_.object = _.jsdc((engine.read() || engine.write("{}")));
} catch (e) {
_.object = {};
}
}
}, window, document));
//eof
Vanilla JS:
var printStorageBody = function () {
var body = document.querySelector("body");
var pre = document.createElement("pre");
body.innerHTML = "";
pre.innerText = JSON.stringify(localStorage, null, '\t');
body.appendChild(pre);
}
jQuery:
var printStorageBody = function () {
$("body").html("");
$("<pre>")
.text(JSON.stringify(localStorage, null, '\t'))
.appendTo("body");
}
Related
I'm trying to prevent an object that has a bunch of arrays that will contain objects from having duplicated objects (I know it looks weid but try to see my code below you will understand what I'm saying)
JavaScript
var UIController = (function() {
var DOMstrings = {
inputDay: ".optionList",
inputTimeF: ".inputTime",
inputTimeT: ".inputTime2",
inputText: ".inputText",
goingToCkecked: ".checkboxx",
inputBtn: ".add__btn",
planContainer: ".container",
errorCase: ".error-case",
optionList: ".optionList",
optionListId: "#optionList",
errorDes: "error-description",
};
return {
getInput: function() {
return {
inputDay: document.querySelector(DOMstrings.inputDay).value,
inputTimeF: document.querySelector(DOMstrings.inputTimeF).value,
inputTimeT: document.querySelector(DOMstrings.inputTimeT).value,
inputText: document.querySelector(DOMstrings.inputText).value,
goingToCkecked: document.querySelector(DOMstrings.goingToCkecked).checked,
};
},
getDOMstrings: function() {
return DOMstrings;
},
};
})(); //END OF THE UICONTROLLER MODULE
var internalController = (function(UICtrl) {
var Plan = function(id, from, to, text, goingToCkecked) {
this.id = id;
this.from = from;
this.to = to;
this.text = text;
this.goingToCkecked = goingToCkecked;
};
var data = {
Monday: [],
Tuesday: [],
Wednesday: [],
Thursday: [],
Friday: [],
Saturday: [],
Sunday: []
};
function hasObject( day, object ) {
const dataset = data[day];
// console.log(object.inputTimeF);
return dataset.some(el => {
return (
console.log(el.inputTimeF)
//el.inputTimeF=== object.inputTimeF
// el.to === object.to
// el.txt === object.txt
);
});
}
var Dom = UICtrl.getDOMstrings();
return {
addItem: function(day, from, to, text, goingToCkecked) {
var newPlan, ID;
//CREATE NEW ID
if (data[day].length > 0) {
ID = data[day][data[day].length - 1].id + 1;
} else {
ID = 0;
}
//CREATE NEW PLAN BASED ON THE PICKED DAY
if (day === "Monday" || day === "Tuesday" || day === "Wednesday" || day === "Thursday" || day === "Friday" || day === "Saturday" || day === "Sunday") {
newPlan = new Plan(ID, from, to, text, goingToCkecked);
}
//PUSH IT INTO OUR DATA STRUCTURE
data[day].push(newPlan);
//RETURN THE NEW ELEMENT
return newPlan;
}, //END OF THE ADD ITEM METHOD
duplicatedObject: function(day,object) {
return hasObject(day,object);
}
}; //end of the return object of the internal controller module
})(UIController);
var controller = (function(interCtrl, UICtrl) {
var input, newPlan, DOM;
DOM = UICtrl.getDOMstrings();
function setupEventListeners() {
document.querySelector(DOM.inputBtn).addEventListener("click", ctrlAddPlans);
document.addEventListener("keypress", function(e) {
if (e.keyCode === 13) {
document.activeElement.blur();
ctrlAddPlans();
}
});
}
var ctrlAddPlans = function() {
//3.get the filed input data
input = UICtrl.getInput();
// console.log(input);
//5.add the plan to the internalController
newPlan = interCtrl.addItem(input.inputDay, input.inputTimeF, input.inputTimeT, input.inputText, input.goingToCkecked);
// 4.Refuse duplicated plans
var res = interCtrl.duplicatedObject(input.inputDay, input);
console.log(res)
};
return {
init: function() {
console.log('the app has started');
setupEventListeners();
},
};
})(internalController, UIController);
controller.init();
that big object is the data object and he has a bunch of arrays as you are seeing and these arrays will contain objects from some inputs that the user will input.
So when I'm trying to tackle this problem(I don't wanna any array to have duplicated object) I'm using the some() method (try to see the has object function in my code above).
I'm comparing the object's from parmeter and the el's from parameter but I'm getting always false as a returned value so when I tried to debug my code I found that the el.inputTimeF is returning undefined
screenshot
I googled this but I didn't found anything useful
First, make sure that el.inputTimeF is not undefined then you can chage your code like the following:
return dataset.some(el => {
return el.inputTimeF;
});
Last, do not return console.log because it will return undefined.
This is the first function:
jQuery.fn.serializeObject = function(){
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
jQuery.each(jQuery(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = jQuery.extend(true, json, merge);
});
return json;
};
This function to serialize the form's values but the problem of this function that it's not getting the value of the unchecked inputs because that I make this function:
jQuery.fn.mySerialize = function() {
var $container = jQuery(this),
$checkboxes = $container.find("input[type='checkbox']").each(function() {
jQuery(this).val(this.checked ? 1 : 0).prop('checked', true);
});
var serialized = ($container.serializeObject());
$checkboxes.each(function() {
jQuery(this).prop('checked', jQuery(this).val() == 1);
});
return serialized;
};
And it's working as I need by directly using mySerialize function now I want to merge the edits that I make at mySerialize function to the serializeObject function because I failed to do that directly into serializeObject function because that I created the mySerialize function.
Thanks in advance and really hope anyone helps me on this.
I am currently trying to observe any changes to a given object including all of it's elements.
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
<script>
var elem = document.getElementById("test1");
var log = function(x) {
elem.innerHTML += x + "<br/><br/><br/>";
};
var a = [{a:1,b:2},
{a:2,b:5}
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x) {
return JSON.stringify(x);
});
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1];
</script>
This code runs and fires correctly.
however. if I instead to this
a[0]['a'] = 3;
Then nothing happens.
EDIT
A better way to phrase this, how can I observe changes from an array of objects?
If you want only the nested object changes:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
})
);
The flatMap or selectMany (they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
http://reactivex.io/documentation/operators/flatmap.html
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
var a = [
{a:1,b:2},
{a:2,b:5}
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x) {
return JSON.stringify(x);
});
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) { return [o, i]; }))
.flatMap(function(oi) {
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x) {
var y = {
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
};
return JSON.stringify(y);
});
})
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1]
a[1]['b'] = 7
Thanks to #electrichead here we're not using concatMap because the sources that we made by ofObjectChanges and ofArrayChanges never complete.
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj) {
if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
return new Rx.AnonymousObservable(function(observer) {
function observerFn(changes) {
for(var i = 0, len = changes.length; i < len; i++) {
observer.onNext(changes[i]);
}
}
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn){
for(var i=0;i<Object.keys(element).length;i++){
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object"){
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
}
}
}
return function () {
Object.unobserve(obj, observerFn);
};
});
};
//Test
var json = {
element : {
name : "Yocto",
job : {
title: "Designer"
}
},
element1: {
name : "Mokto"
}
};
setTimeout(function(){
json.element.job.title = "A Great Designer";
},3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
json.element.name = "Candy Joe";
In my code for a React.createClass() class, I have a getDefaultProps() method that returns a dictionary with initial_text set to a text value.
getDefaultProps: function()
{
return {
initial_text: "**I am *terribly* " +
...
Then, in render(), I try to access this.props.initial_text:
render: function()
{
var tokenize = function(original)
{
var workbench = original;
var result = [];
while (workbench)
{
if (workbench[0] === '<')
{
length = workbench.indexOf('>');
if (length > -1)
{
length = 1;
}
}
else
{
length = 1;
}
result.push(workbench.substr(0, length));
workbench = workbench.substr(length);
}
return result;
}
var initial_tokens = tokenize(converter.makeHtml(
this.props.initial_text));
Chrome's console shows:
Uncaught ReferenceError: initial_text is not defined
What do I need to do to set a string in default properties, and accessing code, to get the string back?
I have a code like this
(function($, window, document, undefined) {
$.fn.quicksearch = function (target, opt) {
var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({
delay: 100,
selector: null,
stripeRows: null,
loader: null,
noResults: '',
bind: 'keyup',
onBefore: function () {
return;
},
onAfter: function () {
return;
},
show: function () {
this.style.display = "";
},
hide: function () {
this.style.display = "none";
},
prepareQuery: function (val) {
return val.toLowerCase().split(' ');
},
testQuery: function (query, txt, _row) {
for (var i = 0; i < query.length; i += 1) {
if (txt.indexOf(query[i]) === -1) {
return false;
}
}
return true;
}
}, opt);
this.go = function () {
var i = 0,
noresults = true,
query = options.prepareQuery(val),
val_empty = (val.replace(' ', '').length === 0);
for (var i = 0, len = rowcache.length; i < len; i++) {
if (val_empty || options.testQuery(query, cache[i], rowcache[i])) {
options.show.apply(rowcache[i]);
noresults = false;
} else {
options.hide.apply(rowcache[i]);
}
}
if (noresults) {
this.results(false);
} else {
this.results(true);
this.stripe();
}
this.loader(false);
options.onAfter();
return this;
};
this.stripe = function () {
if (typeof options.stripeRows === "object" && options.stripeRows !== null)
{
var joined = options.stripeRows.join(' ');
var stripeRows_length = options.stripeRows.length;
jq_results.not(':hidden').each(function (i) {
$(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]);
});
}
return this;
};
this.strip_html = function (input) {
var output = input.replace(new RegExp('<[^<]+\>', 'g'), "");
output = $.trim(output.toLowerCase());
return output;
};
this.results = function (bool) {
if (typeof options.noResults === "string" && options.noResults !== "") {
if (bool) {
$(options.noResults).hide();
} else {
$(options.noResults).show();
}
}
return this;
};
this.loader = function (bool) {
if (typeof options.loader === "string" && options.loader !== "") {
(bool) ? $(options.loader).show() : $(options.loader).hide();
}
return this;
};
this.cache = function () {
jq_results = $(target);
if (typeof options.noResults === "string" && options.noResults !== "") {
jq_results = jq_results.not(options.noResults);
}
var t = (typeof options.selector === "string") ? jq_results.find(options.selector) : $(target).not(options.noResults);
cache = t.map(function () {
return e.strip_html(this.innerHTML);
});
rowcache = jq_results.map(function () {
return this;
});
return this.go();
};
this.trigger = function () {
this.loader(true);
options.onBefore();
window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
e.go();
}, options.delay);
return this;
};
this.cache();
this.results(true);
this.stripe();
this.loader(false);
return this.each(function () {
$(this).bind(options.bind, function () {
val = $(this).val();
e.trigger();
});
});
};
}(jQuery, this, document));
I try to figure out where and how I can make a split/add space between numbers and letters. Cause some people type for example "ip1500" and the script cant match the input with an element that is like "ip 1500". My problem ist that Im a js beginner.
I was trying and trying but i cant get it work. I also tried this
I found this spot and I think it can be done here where the everything get splitted by an " " (space):
prepareQuery: function (val) {
return val.toLowerCase().split(' ');
},
Would be very nice if somebody can help me.
If you want "123abc345def" to "123 abc 345 def". The replace function may help. The code is like this.
var str = "123abc345def";
str = str.replace(/(\d+)/g, function (_, num){
console.log(num);
return ' ' + num + ' ';
});
str = str.trim();
The code you linked didn't work mainly because it's using a different programming language to javascript. In theory, it should work, but javascript does not support regular expression lookbehinds (at this present time)..
Instead, I have re-wrote that fragment of code:
prepareQuery: function (val) {
function isNotLetter(a){
return (/[0-9-_ ]/.test(a));
}
var val=val.toLowerCase().split("");
var tempArray=val.join("").split("");
var currentIndex=1;
for (var i=0;i<val.length-1;i++){
if (isNotLetter(val[i]) !== isNotLetter(val[i+1])){
tempArray.splice(i+currentIndex, 0, " ");
currentIndex++;
}
}
return tempArray.join("");
}
Since you're new to javascript, I'm going to explain what it does.
It declares a function in prepareQuery to check whether or not a string contains a letter [this can be moved somewhere else]
It then splits val into an array and copies the content of val into tempArray
An index is declared (explained later)
A loop is made, which goes through every single character in val
The if statement detects whether or not the current character (val[i] as set by the loop) is the same as the character next to it (val[i+1]).
IF either one are different to the other (ie the current character is a letter while the next isn't) then a space is added to the tempArray at that "index"
The index is incremented and used as an offset in #6
The loop finishes, joins the "array" into a string and outputs the result.
DEMO:
http://jsbin.com/ebitus/1/edit
(JSFiddle was down....)
EDIT:
Sorry, but I completely misinterpreted your question... You failed to mention that you were using "quicksearch" and jQuery. In that case I'm assuming that you have a list of elements that have names and you want to search through them with the plugin...
A much easier way to match the user's query (if there is no space) is to strip the space from the search table along with the query itself - though original reverse method will work (just not as efficiently) [aka: expanding the user's query]
In this case, stripping the space from both the search table and user input would be a better method
prepareQuery: function (val) {
return val.toLowerCase().replace(/ /ig,'').split(" ");
},
testQuery: function (query, txt, _row) {
txt=txt.toLowerCase().replace(/ /ig,'');
for (var i = 0; i < query.length; i += 1) {
if (txt.indexOf(query[i]) === -1) {
return false;
}
}
return true;
}
DEMO:
http://jsfiddle.net/q9k9Y/3/
Edit 2:
It seems like your real intent is to create a fully functioning search feature on your website, not to just add spaces between letters and numbers. With this, I suggest using Quicksilver. I would love to work out an algorithm to extend quickSearcher but at the current time I cannot (timezones). Instead, I suggest using Quicksilver
http://jsbin.com/oruhet/12/