undefined returned by the some() method - javascript

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.

Related

Rxjs observing object updates and changes

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";

Best practice to 'combine' jQuery methods

I'm in the process of creating a customized filter plugin for jQuery.
So far' I've managed to implement the following code:
(function ($) {
$.fn.filterbyDate = function (filterValue) {
var tableDate = new Date($(':eq(3)', $(val)).text());
var days = numDaysBetween(tableDate, new Date());
if (filterValue === "-1") {
$(val).show();
} else {
switch (filterValue) {
case "This Week":
if (days > 7) {
$(val).hide();
} else {
$(val).show();
}
break;
case "This Month":
if (days > 30) {
$(val).hide();
} else {
$(val).show();
}
break;
case "This Year":
if (days > 365) {
$(val).hide();
} else {
$(val).show();
}
break;
default:
}
}
};
$.fn.filterbyClient = function (filterValue) {
var $table = $(".tablefilter");
$.each($table.find("tbody>tr"), function (ind, val) {
var name = $(':eq(2)', $(val)).text();
if (filterValue === "-1") {
$(val).show();
} else {
if (name.trim() !== filterValue) {
$(val).hide();
} else {
$(val).show();
}
}
});
};
}(jQuery));
It's implemented by:
controller1.filterByDate(date);
controller2.filterByClient(client);
This works exactly as it should separately, but when I try 'filterByClient' after 'filterByDate', it naturally overwrites the former for the latter.
So essentially I would like to filterByClient based on the results on filterByDate
Is there any best practice for somehow 'combining' methods where need be, to filter only on the latest results?
Note: The methods are called by two different controllers (select lists)
Eg:
$("#dateFilter").change(function () {
$(this).filterbyDate($(this).val());
});
$("#clientFilter").change(function() {
$(this).filterbyClient($(this).val());
});
You can use method chaining. Just return this; at the end of your functions and use them like controller.filterByDate(date).filterByClient(client);
So your methods would look like
$.fn.filterbyDate = function (filterValue) {
//Do Stuff
return this;
};
$.fn.filterbyClient = function (filterValue) {
// Do Stuff
return this;
};
EDIT:
If its used by different controllers, you have to abstract your controllers, so that the methods don't have to filter the controllers itself, but a list which they use.
So you can do something like:
var list = controller1.list.filterByDate(date);
controller2.list = list.filterByClient(client);
You could pass the list to be filtered as an argument to your function:
(function ($) {
$.fn.filterbyDate = function (list, filterValue) {
var filteredList = [];
//apply filter on list and put result into filteredList...
return filteredList;
};
$.fn.filterbyClient = function (list, filterValue) {
var filteredList = [];
//apply filter on list and put result into filteredList...
return filteredList;
};
}(jQuery));
var entireList = [...];
var filterdList = controller1.filterByDate(entireList, date);
var doubleFilteredList = controller2.filterByClient(filterdList , client);
Update:
Or merge your filter functions into 1 and allow multiple fields to be filtered at once:
$.fn.filterby = function (options) {
//apply filters
if (options.date !== undefined) {
// apply date filter based on value of options.date
}
if (options.client !== undefined) {
// apply client filter on value of options.client
}
};

LocalStorage and JSON.stringify JSON.parse

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");
}

Filtering collections in backbone

Hello I am running a search of a backbone collection, the current string I am searching is
Project Number
This should return 2 results however it only ever shows 1 result, I cannot understand why, below is the code that I using,
The code the runs when adding search parameters,
updateSearchFilter: function(e) {
var self = this;
this.collection.each(this.filterHide, this);
if($(e.currentTarget).val() === "")
{
this.collection.each(this.filterShow, this);
}
var activeLabels = $(".labels").find(".inactive");
$.each(activeLabels, function(key, index){
switch($(index).attr("id"))
{
case "pending":
status = "7";
self.filterDetails.states["pending"] = false;
break;
case "completed":
status = "5";
self.filterDetails.states["complete"] = false;
break;
case "archived":
status = "3";
self.filterDetails.states["archived"] = false;
break;
case "active":
status = "1";
self.filterDetails.states["active"] = false;
break;
}
});
var visible = this.collection.search($(e.currentTarget).val(), this.filterDetails.states);
if (visible !== undefined) {
visible.each(this.filterShow, this);
}
},
So the above code, hides the idividual results on the first key press, is then loops through an array of jquery objects and re-assigns some values in an object - this is done so we can work out what filters we need to search through.
We then run our search code,
ProjectCollection.prototype.search = function(searchTerm, filters) {
var pattern;
console.log(filters);
pattern = new RegExp(searchTerm, "gi");
if (filters.active && filters.archived) {
if (searchTerm === "") {
return this;
}
return _(this.filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.active) {
if (searchTerm === "") {
return this.active();
}
return _(this.active().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.pending) {
console.log("hello");
if (searchTerm === "") {
return this.pending();
}
return _(this.pending().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.archived) {
if (searchTerm === "") {
return this.archived();
}
return _(this.archived().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.complete) {
if (searchTerm === "") {
return this.complete();
}
return _(this.complete().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
}
};
ProjectCollection.prototype.archived = function() {
return new ProjectCollection(this.where({
status: '3'
}));
};
ProjectCollection.prototype.active = function() {
return new ProjectCollection(this.where({
status: '1'
}));
};
ProjectCollection.prototype.pending = function() {
return new ProjectCollection(this.where({
status: '7'
}))
};
ProjectCollection.prototype.complete = function() {
return new ProjectCollection(this.where({
status: '5'
}));
}
Now what I should be getting back is 2 results,
Project Number 1 & Project Number 2
However I only every get one result on this search term, Project Number 1 has the status of "Archived" and Project Number 2 has the status of "Pending". However I never seem to get go into the pending portion of the logic (above) even though filters.pending = true;
How can I make sure that I get all the matches for each status returned?
Instead of setting state of your filter individually, you could keep all filter status keys in an array. For example, your user want to filter for active, complete and pending so you would have an array of ['1','5','7']
So when you filter for relevant statuses you could do by
// filterModes is ['1', '5', '7'];
collection.filter(function(model){
return filterModes.indexOf(model.status) !== -1;
}
The rest should be simpler for you now
Note that collection.filter() and collection.where() return array and array may or may not have filter() and definitely don't have where() so be wary about chaining your function call

Add space between numbers/digits and letters/characters

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/

Categories

Resources