how to create an exact search using Js and Jquery - javascript

I'm trying to create an expanded search where you can find people not only using there names but some combinations... for instance i have this list of players and this peace of code work fine, but if i want to find for such features like - keeper England. this line of code doesn't work ((val.position.search(myExp) != -1) || (val.nationality.search(myExp) != -1))
$("#search").keyup(function() {
var field = $("#search").val();
var myExp = new RegExp(field, "i");
$.getJSON("players.json", function(data) {
var output = "<ul>";
$.each(data, function(key, val) {
if ((val.name.search(myExp) != -1) || (val.position.search(myExp) != -1) || ((val.position.search(myExp) != -1) || (val.nationality.search(myExp) != -1))) {
output += "<li>";
output += '<p class="name">' + val.name + '</p>';
output += '<p>' + val.position + '</p>';
output += '<p>' + val.dateOfBirth + '</p>';
output += '<p>' + val.nationality + '</p>';
output += '<p>' + val.contractUntil + '</p>';
output += '<p>' + val.marketValue + '</p>';
output += "</li>";
}
});
output += "</ul>";
$("#update").html(output);
});
});
{
"id":2138,
"name":"Thibaut Courtois",
"position":"Keeper",
"jerseyNumber":13,
"dateOfBirth":"1992-05-11",
"nationality":"Belgium",
"contractUntil":"2019-06-30",
"marketValue":"35,000,000 ˆ"
},
{
"id":2140,
"name":"Jamal Blackman",
"position":"Keeper",
"jerseyNumber":27,
"dateOfBirth":"1993-10-27",
"nationality":"England",
"contractUntil":"2019-06-30",
"marketValue":"250,000 ˆ"
},

You have to do multiple search queries because you have multiple words in your query:
"england keeper" => "england" and "keeper"
So you want to filter the items by "england" and also by "keeper"..
The best would be to create a small functions, each will do a part of it:
// Note: this function returns the filter function
var myFilter = function(regex) {
return function(item) {
return regex.test(item.name)
|| regex.test(item.position)
|| regex.test(item.nationality)
}
}
// this is a higher order function, takes the items and the full searchString as arguments
var findMatches = function(items, searchString) {
// make a copy of the items / data
var found = items.slice(0, item.length);
// split the searchString, and filter the items by it
searchString.split(' ').forEach(function(part) {
found = found.filter(myFilter(new RegEx(part, 'i'))
});
return found;
}
Now you can use it in your code:
...
var output = "<ul>";
var filteredData = findMatches(data, field);
$.each(filteredData, function(key, val) {
// filteredData should be fine, you can just render it
}
...

Related

How to use higher order functions instead of FOR Loop for Line items in Suitelet printouts (Netsuite)?

i have been tasked by my senior to print values of line items using higher order functions (.filter/.map/.reject/.reduce). I m confused how to write the higher order function instead of a for loop(for printing the line values in Invoice Printout). I need to print the line only when the qty is more than 3. I m an intern and i dont know how it will work, kindly help.
Link to The code snippet: https://drive.google.com/file/d/1uVQQb0dsg_bo53fT3vk9f0G8WwZomgQg/view?usp=sharing
I always used if condition for printing the row only when the quantity field has value more than 3. I even know how to .filter but i dont know how to call it and where to call it. Please help
I don't believe Array.from works in server side code. If it does then use that. What I have been using are the following functions. They don't conform to the higher order functions specified but they work with Netsuite syntax and go a long way towards simplifying sublist handling and encapsulating code:
//SS2.x
//I have this as a snippet that can be included in server side scripts
function iter(rec, listName, cb){
var lim = rec.getLineCount({sublistId:listName});
var i = 0;
var getV = function (fld){
return rec.getSublistValue({sublistId:listName, fieldId:fld, line:i});
};
for(; i< lim; i++){
cb(i, getV);
}
}
// to use it:
iter(ctx.newRecord, 'item', function(idx, getV){
if(parseInt(getV('quantity')) >3){
...
}
});
or for SS1 scripts I have the following which allows code to be shared between UserEvent and Scheduled scripts or Suitelets
function forRecordLines(rec, machName, op, doReverse) {
var i, pred, incr;
var getVal = rec ? function(fld) {
return rec.getLineItemValue(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemValue(machName, fld, i);
};
var getText = rec ? function(fld) {
return rec.getLineItemText(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemText(machName, fld, i);
};
var setVal = rec ? function(fld, val) {
rec.setLineItemValue(machName, fld, i, val);
} : function(fld, val) {
nlapiSetLineItemValue(machName, fld, i, val);
};
var machCount = rec ? rec.getLineItemCount(machName) : nlapiGetLineItemCount(machName);
if(!doReverse){
i = 1;
pred = function(){ return i<= machCount;};
incr = function(){ i++;};
}else{
i = machCount;
pred = function(){ return i>0;};
incr = function(){ i--;};
}
while(pred()){
var ret = op(i, getVal, getText, setVal);
incr();
if (typeof ret != 'undefined' && !ret) break;
}
}
// User Event Script:
forRecordLines(null, 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
// in a Scheduled Script:
forRecordLines(nlapiLoadRecord('salesorder', id), 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
Usually its a straight forward task, but since you are getting length and based on that you are iterating, you can use Array.from. Its signature is:
Array.from(ArrayLikeObject, mapFunction);
var tableData = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var quantity = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return { item, description, quantity}
});
var htmlData = tableData.filter(...).map(getRowMarkup).join('');
function getRowMarkup(data) {
const { itemName, descript, quantity } = data;
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}
Or if you like to use more functional approach:
Create a function that reads and give you all data in Array format. You can use this data for any task.
Create a function that will accept an object of specified properties and returns a markup.
Pass the data to this markup after any filter condition.
Idea is to isolate both the task:
- Getting data that needs to be processed
- Presentation logic and style related code
var htmlString = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var qty = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return getRowMarkup(item, description, qty)
}).join('');
function getRowMarkup(itemName, descript, quantity) {
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}

Live Search from multiple JSON files, Javascript, AJAX

I have to implement a search bar using AJAX and jQuery that displays results from 3 JSON files. At the moment I have it working with one but I am not sure how I might adapt this to live search 3 separate JSON files simultaneously.
const search = document.querySelector('#search');
search.addEventListener('keydown', liveSearch);
function liveSearch() {
const searchField = search.value;
const myExp = new RegExp(searchField, "i");
$.getJSON('weekday.json', function(data) {
var output = '<ul>';
$.each(data, function(key, val) {
if ((val.Title.search(myExp) !== -1) || (val.Description.search(myExp) !== -1)) {
output += '<li>';
output += '<strong>' + val.Title + '</strong>';
output += '<p>' + val.Description + ' - ' + val.Price + '</p>';
output += '</li>';
}
});
output += '</ul>';
$('#output').html(output);
});
}
Any help would be appreciated.
you can use $.when to execute multiple async promise
```
$.when(
$.getJSON('weekday1.json'),
$.getJSON('weekday2.json'),
$.getJSON('weekday3.json')
).then(function (results) {
var r1 = results[0]; // result in weekday1.json
var r2 = results[1]; // result in weekday2.json
var r3 = results[2]; // result in weekday3.json
})
Note: the promise(.then function) will only be resolved after all async task are resolved.
Ref: https://api.jquery.com/jquery.when/
'results' in the code provided by arfai1213 does not return an array that can be used as suggested.
Splitting results as per the code below returns separate arrays that can be used.
$.when(
$.getJSON('./data/file1.json'),
$.getJSON('./data/file2.json')
).then(function (r1, r2) {
$.each(r1[0], function(key, val){
//do something
})
$.each(r2[0], function(key, val){
//do something
})
});

Modifying innerHTML in nested get() jQuery

I'm currently using the jQuery get method to read a table in another page which has a list with files to download and links to others similar webpages.
$.get(filename_page2, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find(target_element_type_page2 + '#' + target_element_id_page2)[0];
var container = document.getElementById(element_change_content_page1);
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var isFolder = table.getAttribute("CType") == "Folder";
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link = elem.getElementsByTagName("A")[0].getAttribute("href");
if (!isFolder) {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + link + "\">" + text + "</a></li>";
} else {
container.innerHTML += "<li class=\"folderlist\">" + "<a class=\"folderlink\" onclick=\"open_submenu(this)\" href=\"#\">" + text + "</a><ul></ul></li>";
var elem_page1 = container.getElementsByTagName("li");
var container_page1 = elem_page1[elem_page1.length - 1].getElementsByTagName("ul")[0];
create_subfolder(container_page1, link);
}
}
} else {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + "#" + "\">" + "Error..." + "</a></li>";
}
}, page2_datatype);
This is working fine, and all the folders and files are being listed. But when I try to do the same thing with the folders (calling the create_subfolder function) and create sublists with their subfolders and files, I'm getting a weird behavior.
function create_subfolder(container2, link1) {
$.get(link1, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find("table" + "#" + "onetidDoclibViewTbl0")[0];
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link2 = elem.getElementsByTagName("A")[0].getAttribute("href");
//nothing is changed in the webpage. The modifications in the html don't appear
container2.innerHTML += "<li>" + text + "</li>";
}
}
alert(container2.innerHTML); // Print the html with all the modifications
}, "html");
}
The second get(), inside the create_subfolder() function are not changing anything in the webpage, so no sublist is created. But, when I call the alert() function at the end of the get() function, it prints the code with all the modifications it should have made in the html at the second get callback. I believe the problem is related with the asynchronous behavior of the get function but I don't know exactly why. Any guess?

How to get text from textarea including the newline characters?

In jquery, I am trying to get the text from a textarea tag, with the new lines as \n and not br tags. The problem is if I select it and get its val, the firefox debugger does not even show the \n or br. If I alert it, then I see there is two lines, but then if I insert it into the DOM, it removes all the new lines. I want it to keep its new lines.
I get it like this:
var handleSend = function(thread_id) {
var user = GLOBAL_DATA.user;
$(context).find("#message-form").unbind('submit').submit(function() {
var field = $(this).find("textarea");
runAJAXSerial($(this).serialize(), {
page : 'message/setmessage',
id : user['id'],
thread_id : thread_id
}, function(response) {
var user = GLOBAL_DATA.user;
var obj = {
user_id : user['id'],
message : field[0].value.replace(/<br\s*\/?>/mg,"\n"),
date_sent : getDate() + ' ' + getTime()
};
alert(obj.message);
cleanResponse(obj);
field.val("").focus();
displayMessages([obj], true);
}, function(data,status,xhr) {
});
return false;
});
};
function cleanResponse(response) {
if (Object.prototype.toString.call( response ) === '[object Array]') {
var i = 0, l = response.length;
for (i=0; i<l; i+=1) {
response[i] = cleanResponse(response[i]);
}
} else if (Object.prototype.toString.call( response ) === '[object Object]') {
for (var property in response) {
if (response.hasOwnProperty(property)) {
response[property] = cleanResponse(response[property]);
}
}
} else {
response = escapeHTML(response);
}
return response;
}
function escapeHTML(str) {
return $("<p/>").text(str).html();
}
var displayMessages = function(response, onBottom) {
var user = GLOBAL_DATA.user, i=0, l=response.length, acc = '';
for(i=0; i<l; i+=1) {
var obj = response[i];
var acc_temp = "";
acc_temp += '<div class="message ' + (obj['user_id']==user['id'] ? 'message-right' : 'message-left') + '">';
acc_temp += '<img src="' + getImage(obj['user_id']) + '" align="right" class="message-image" />';
acc_temp += '<div>' + Autolinker.link(obj['message']) + '</div>';
acc_temp += '<br/>';
if (obj['user_id']!=user['id']) {
acc_temp += '<div class="message-details">' + obj['first_name'] + ' ' + obj['last_name'] + '</div>';
}
acc_temp += '<div class="message-details">' + obj['date_sent'] + '</div>';
acc_temp += '</div>';
acc = acc_temp + acc;
}
addMessage(acc, onBottom);
};
var addMessage = function(html, onBottom) {
var list = $(context).find("#message-list");
if (onBottom) {
list.append(html);
scrollBot();
} else {
list.prepend(html);
}
};
displayMessages inserts the text into the DOM.
cleanResponse encodes the text so that the user can't execute scripts.
Does anyone know whats wrong?
Thanks
New lines in the DOM are treated like any other whitespace. You are getting the expected behaviour of adding the new lines.
If you want an new line to be rendered then you need to use a <br> element or modify the white-space CSS property.

How can I open with blank page on this rss javascript nor html?

I have a website which includes this RSS JavaScript. When I click feed, it opens same page, but I don't want to do that. How can I open with blank page? I have my current HTML and JavaScript below.
HTML CODE
<tr>
<td style="background-color: #808285" class="style23" >
<script type="text/javascript">
$(document).ready(function () {
$('#ticker1').rssfeed('http://www.demircelik.com.tr/map.asp').ajaxStop(function () {
$('#ticker1 div.rssBody').vTicker({ showItems: 3 });
});
});
</script>
<div id="ticker1" >
<br />
</div>
</td>
</tr>
JAVASCRIPT CODE
(function ($) {
var current = null;
$.fn.rssfeed = function (url, options) {
// Set pluign defaults
var defaults = {
limit: 10,
header: true,
titletag: 'h4',
date: true,
content: true,
snippet: true,
showerror: true,
errormsg: '',
key: null
};
var options = $.extend(defaults, options);
// Functions
return this.each(function (i, e) {
var $e = $(e);
// Add feed class to user div
if (!$e.hasClass('rssFeed')) $e.addClass('rssFeed');
// Check for valid url
if (url == null) return false;
// Create Google Feed API address
var api = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;
if (options.limit != null) api += "&num=" + options.limit;
if (options.key != null) api += "&key=" + options.key;
// Send request
$.getJSON(api, function (data) {
// Check for error
if (data.responseStatus == 200) {
// Process the feeds
_callback(e, data.responseData.feed, options);
}
else {
// Handle error if required
if (options.showerror) if (options.errormsg != '') {
var msg = options.errormsg;
}
else {
var msg = data.responseDetails;
};
$(e).html('<div class="rssError"><p>' + msg + '</p></div>');
};
});
});
};
// Callback function to create HTML result
var _callback = function (e, feeds, options) {
if (!feeds) {
return false;
}
var html = '';
var row = 'odd';
// Add header if required
if (options.header) html += '<div class="rssHeader">' + '' + feeds.title + '' + '</div>';
// Add body
html += '<div class="rssBody">' + '<ul>';
// Add feeds
for (var i = 0; i < feeds.entries.length; i++) {
// Get individual feed
var entry = feeds.entries[i];
// Format published date
var entryDate = new Date(entry.publishedDate);
var pubDate = entryDate.toLocaleDateString() + ' ' + entryDate.toLocaleTimeString();
// Add feed row
html += '<li class="rssRow ' + row + '">' + '<' + options.titletag + '>' + entry.title + '</' + options.titletag + '>'
if (options.date) html += '<div>' + pubDate + '</div>'
if (options.content) {
// Use feed snippet if available and optioned
if (options.snippet && entry.contentSnippet != '') {
var content = entry.contentSnippet;
}
else {
var content = entry.content;
}
html += '<p>' + content + '</p>'
}
html += '</li>';
// Alternate row classes
if (row == 'odd') {
row = 'even';
}
else {
row = 'odd';
}
}
html += '</ul>' + '</div>'
$(e).html(html);
};
})(jQuery);
try change this:
html += '<li class="rssRow '+row+'">' +
'<'+ options.titletag +'>'+ entry.title +'</'+ options.titletag +'>'
to
html += '<li class="rssRow '+row+'">' +
'<'+ options.titletag +'>'+ entry.title +'</'+ options.titletag +'>'

Categories

Resources