Customizing easyAutoComplete - javascript

var options = {
url: function (phrase) {
return "location/autoComplete?key=" + phrase;
},
getValue: "cityName",
template: {
type: "custom",
method: function (value, item) {
return value + ", " + item.stateName;
}
},
list: {
onClickEvent: function () {
var selectedLongitude = $("#autoCompleteSearch").getSelectedItemData().longitude;
var selectedLatitude = $("#autoCompleteSearch").getSelectedItemData().latitude;
userPos = {
lat: Number(selectedLatitude),
lng: Number(selectedLongitude)
};
map.setCenter(userPos);
map.setZoom(17)
},
showAnimation: {
type: "fade", //normal|slide|fade
time: 400,
callback: function () {
}
},
hideAnimation: {
type: "slide", //normal|slide|fade
time: 400,
callback: function () {
}
}
}
};
This is the code I am using right now to fetch a remote webservice data. Now I need to get the data and remove the duplicate "city names". Also I need to show "Data not available" or some custom method when there is no data from the webservice. I am kind of stuck. Would be great if someone could point me on how to achieve this.

You can get rid of duplicates using a helper function:
function removeDuplicates(input) {
if (!input) { //Falsy input
return input;
}
var isArray = Array.isArray(input) ? [] : {};
var items = [];
var output = {};
for (var key in input) {
if (items.indexOf(input[key]) < 0) {
items.push(input[key]);
if (!isArray) {
output[key] = input[key];
}
}
}
return isArray ? items : output;
}
You can show your custom text if Array.isArray(input) ? (input.length === 0) : (Object.keys(input).length === 0 && input.constructor === Object).

Related

Vue infinite UI update loop with function as param

I'm new in Vue.js and tried to convert some legacy code for pagination. I've created a pager component which accepts a function as one of its params. But it's causing an infinite UI render loop.
Could you help me to resolve or suggest some solution for such problem?
Here is my pager component js:
const PagerComponent = {
name: "pagerComponent",
template: "#pagerComponent",
props: {
pageSize: Number,
pageIndex: Number,
totalPages: Number,
totalRecords: Number,
pageSlide: Number,
hasNextPage: Boolean,
hasPrevPage: Boolean,
pages: Array,
loadFunc: Function
},
data() {
return {
pager: {
pageSize: 0,
pageIndex: 0,
totalPages: 0,
totalCount: 0,
pageSlide: 1,
hasNextPage: false,
hasPrevPage: false,
pages: [],
loadFunc: function () { }
}
}
},
methods: {
load(index) {
this.pager.pageIndex = index;
if (this.pager.loadFunc != null) {
this.pager.loadFunc();
}
},
isActivePage(page) {
return this.pager.pageIndex + 1 == page;
},
update(newPager) {
this.pager.pageSize = newPager.pageSize;
this.pager.pageIndex = newPager.pageIndex;
this.pager.totalPages = newPager.totalPages;
this.pager.totalCount = newPager.totalCount;
this.pager.hasNextPage = newPager.hasNextPage;
this.pager.hasPrevPage = newPager.hasPrevPage;
this.generatePages();
},
generatePages() {
this.pager.pages = [];
var pageNum = this.pager.pageIndex + 1;
var pageFrom = Math.max(1, pageNum - this.pager.pageSlide);
var pageTo = Math.min(this.pager.totalPages, pageNum + this.pager.pageSlide);
pageFrom = Math.max(1, Math.min(pageTo - this.pager.pageSlide, pageFrom));
pageTo = Math.min(this.pager.totalPages, Math.max(pageFrom + this.pager.pageSlide, pageNum == 1 ? pageTo + this.pager.pageSlide : pageTo));
for (var i = pageFrom; i <= pageTo; i++) {
this.pager.pages.push(i);
}
}
},
computed: {
hasPages() {
if (this.pager.pages == null)
return false;
return this.pager.pages.length > 0;
},
doNotHavePrevPage() {
return !this.pager.hasPrevPage;
},
doNotHaveNextPage() {
return !this.pager.hasNextPage;
}
},
beforeMount() {
this.pager.pageSize = this.pageSize;
this.pager.pageIndex = this.pageIndex;
this.pager.totalPages = this.totalPages;
this.pager.totalCount = this.totalRecords;
this.pager.hasNextPage = this.hasNextPage;
this.pager.hasPrevPage = this.hasPrevPage;
this.pager.loadFunc = this.loadFunc;
this.pager.pages = this.pages || [];
this.generatePages();
},
mounted() {
}
}
Here is how it's used in html:
<pager-Component v-bind="Pager" v-bind:load-Func="GetItems" ref="pager"></pager-Component>
And GetItems funciton:
function () {
var self = this;
const data = {
Pager: self.Pager,
Filter: []
};
$.ajax({
url: self.GetItemsUrl,
type: "POST",
dataType: "json",
busy: self.Loading,
data: data
}).done(function (result) {
if (result.isSuccess) {
self.$refs.pager.update(result.data.pager);
self.Items.splice(0);
result.data.items.map(function (value, key) {
self.Items.push(value);
});
}
else {
alert(result.data.errors[0]);
}
});
}
Finally after tones of tests, the solution was found and it's pretty easy.
I just needed to use v-on:click instead of :click. I just don't know why lot of tutorials suggest to use :click if it doesn't work
So for example use
<div v-on:click="load(pageIndex)">My button</div>
instead of
<div :click="load(pageIndex)">My button</div>

Dynamically splitting strings with multiple keywords

I'm working on headless CMS using Angular.
In the content below, whatever is wrapped inside {{ }} is considered to be an anchor link.
We processes your data in accordance with the {{policy_placeholder}}. You have the right to object to the processing of your personal data. Check “Your rights” in the {{policy_placeholder}} and {{term_policy}} for more information.;`
So with the above example, below is the expected result
[
{
type: "TEXT",
content: "We processes your data in accordance with the "
},
{
type: "LINK",
content: "{{policy_placeholder}}"
},
{
type: "TEXT",
content:
". You have the right to object to the processing of your personal data. Check “Your rights” in the "
},
{
type: "LINK",
content: "{{policy_placeholder}}"
},
{
type: "TEXT",
content: " and "
},
{
type: "LINK",
content: "{{terms_placeholder}}"
},
{
type: "TEXT",
content: " for more information."
}
];
Below is what I tried
splitString = function(string, splitters) {
var list = [string];
for(var i=0, len=splitters.length; i<len; i++) {
traverseList(list, splitters[i], 0);
}
const x = flatten(list);
console.log(x);
return flatten(list);
}
traverseList = function(list, splitter, index) {
if(list[index]) {
if((list.constructor !== String) && (list[index].constructor === String))
(list[index] != list[index].split(splitter)) ? list[index] = list[index].split(splitter) : null;
(list[index].constructor === Array) ? traverseList(list[index], splitter, 0) : null;
(list.constructor === Array) ? traverseList(list, splitter, index+1) : null;
}
}
flatten = function(arr) {
return arr.reduce(function(acc, val) {
return acc.concat(val.constructor === Array ? flatten(val) : val);
},[]);
}
var splitList = ["{{policy_placeholder}}", "{{term_policy}}"];
splitString(source, splitList);
The issue is that I've to manually add the splitList, but i want to make it dynamic based on {{ }}
How can this be done?
When you spread a string, you actually split it into characters.
const source = `We processes your data in accordance with the {{policy_placeholder1}}. You have the right to object to the processing of your personal data. Check “Your rights” in the {{policy_placeholder2}} for more information.`;
function splitString(str) {
const ans = [];
const linkTokenRegex = /\{\{.+?\}\}/g;
const textsArr = str.split(linkTokenRegex);
const linksArr = str.match(linkTokenRegex);
textsArr.forEach((textPart, index) => {
ans.push({
type: "TEXT",
content: textPart,
});
if (linksArr[index]) {
ans.push({
type: "LINK",
content: linksArr[index],
});
}
});
return ans;
}
console.log(splitString(source));

Semantic UI - Search API: how I can highlight certain characters that match the query?

I have a problem when I want to highlight certain characters that match the query in search module.
an example is like this forum: https://forums.meteor.com
Previously, I already asked this issue at https://github.com/Semantic-Org/Semantic-UI/issues/4930#issuecomment-275011130, but until now not been resolved.
here is my current demo: https://jsfiddle.net/agaust/5854gae9/4/
$(document).ready(function() {
$.fn.api.settings.api = {
'search': 'https://gist.githubusercontent.com/agusmakmun/e258a3243367105c32919c083eb577fe/raw/8b0038b0141f5813c03baece0b2730e17216f8c9/result-data.json?q={query}'
};
$('.ui.search.quick-search').search({
type : 'category',
minCharacters : 1, // just under devel to make it easy
apiSettings : {
action: 'search',
onResponse: function(searchApiResponse) {
var response = {
results : {},
//action : searchApiResponse.action // dict action
};
// translate `searchApiResponse` response to work with search
var numbThreads = 0, numbUsers = 0;
$.each(searchApiResponse.items, function(index, item) {
var
model = item.model || 'Unknown',
maxResults = 6,
maxItems = maxResults/2 // max results per-Category
;
if(index >= maxResults) {
return false;
}
// create new model category
if(response.results[model] === undefined) {
response.results[model] = {
name : model,
results : []
};
}
if(item.model === 'Threads') {
if ((numbThreads < maxItems) || (numbUsers < numbThreads)) {
response.results[model].results.push({
title: item.title,
description: item.description,
url: item.url
});
}
numbThreads++;
}else if (item.model === 'Users') {
if ((numbUsers < maxItems) || (numbThreads < numbUsers)) {
response.results[model].results.push({
title: item.username,
description: item.username,
url: item.profile_url,
image: item.gravatar_url,
price: item.total_threads
});
}
numbUsers++;
}
});
// only showing the bottom action button if under limited
if (searchApiResponse.limited_items) {
response["action"] = searchApiResponse.action;
}
console.log(response);
return response;
}
}
});
});
any help would be apreciated.. :)

printing all records using only one alert

I have the following code with the JSFiddle for the same here:
var result = [
{"Id": 10004, "PageName": "club"},
{"Id": 10040, "PageName": "qaz"},
{"Id": 10059, "PageName": "jjjjjjj"}
];
$.each(result, function(i, item) {
alert(result[i].PageName);
});
In order to see all the results, I have to click Ok in alert window two times. How can I display the contents using one alert only?
//f1.js ---
var PatientReviewPage = (function () {
var cls = function () { }
var self = cls.prototype;
self.urlKey = "showmrn";
self.getData = function (mrn_) {
/*
if (isEmpty(mrn_)) { alert("Invalid mrn in getData()"); return false; }
// Lookup the AJAX web service URL
var url = regman.getWebServiceURL(self.urlKey);
if (isEmpty(url)) { alert("Invalid URL in getData()"); return false; }
var ajaxRequest = jQuery.ajax({
//beforeSend: TODO: show spinner!
data: {
registry_id: regman.registry.id,
mrn: mrn_
},
dataType: "json",
method: "GET",
url: url
})*/
//Some code related to ajax reques
this.done(function (data_, textStatus_, jqXHR_) {
// Validate the web service and retrieve the status.
if (typeof (data_) === "undefined" || data_ === null) {
alert("Invalid data returned from web service");
return false;
}
if (isEmpty(data_.webservice_status) || isEmpty(data_.webservice_status.status)) {
alert("Invalid web service status");
return false;
}
if (data_.webservice_status.status != "SUCCESS") {
alert(data_.webservice_status.message);
return false;
}
self.processdataDocuments(data_.data_document_list);
});
this.fail(function (jqXHR_, textStatus_, errorThrown_) {
alert("Error in getData(): " + errorThrown_);
return false;
});
};
// Initialize the page
self.initialize = function () {
var mrn = regman.selectedData["mrn"];
if (isEmpty(mrn)) {
alert("Invalid MRN provided by calling page");
return false;
}
self.getData(mrn);
};
self.processdataDocuments = function (collection_) {
if (isEmpty(collection_) || collection_.length < 1) {
// Populate the count and exit
jQuery("#nlpDocumentCount").html("(0)");
return true;
}
var source =
{
localdata: collection_,
datatype: "array"
};
var dataAdapter = new $.jqx.dataAdapter(source, {
loadComplete: function (data) { },
loadError: function (xhr, status, error) { }
});
$("#nlpDocumentPanel").jqxGrid(
{
source: dataAdapter,
width: '1000',
height: 150,
columns: [
{
text: 'Type', datafield: 'nc_type'
},
{
text: 'SubType', datafield: 'nc_subtype'
},
{
text: 'Concept', datafield: 'concept_text'
},
{
text: 'Date', datafield: 'nc_dos'
}
]
});
// For getting the contents of a row, I am using jqxgrid approach as mentioned in their doc here :
// http://www.jqwidgets.com/getting-the-clicked-grid-row/
$("#nlpDocumentPanel").on('rowclick', function (event) {
var row = event.args.rowindex;
var datarow = $("#nlpDocumentPanel").jqxGrid('getrowdata', row);
response = JSON.stringify(datarow, null, 10)
//alert(jsonStringify); // This alert displays the JSON data in a formatted manner
var obj = jQuery.parseJSON(response);
//alert("display Subtype "+obj.nc_subtype) // Works fine
self.mySubtype = obj.nc_subtype;
});
};
//I added this line for the demo to show 'f2' accessing this property from 'f1'. You should remove it if copying this code into your application
self.mySubtype = "Foo";
return cls;
})();
var f1 = new PatientReviewPage();
//f2.js ---
var DocumentDetailsDialog = (function () {
var cls = function () { }
var self = cls.prototype;
alert(f1.mySubtype);
/*this.getData = function (IDNumber_) {
// some code will be here
var ajaxRequest = jQuery.ajax({
// some code will be here
})
.done(function (data_, textStatus_, jqXHR_) {
// some code will be here
})
.fail(function (jqXHR_, textStatus_, errorThrown_) {
// some code will be here
});
};*/
return cls;
})();
var f2 = new DocumentDetailsDialog();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can use map() and join() and return string with page names.
var result = [
{"Id": 10004, "PageName": "club"},
{"Id": 10040, "PageName": "qaz"},
{"Id": 10059, "PageName": "jjjjjjj"}
];
var r = result.map(function(e) {
return e.PageName;
}).join(' ');
alert(r);
Build a string with the results and alert the string:
alert(result.map( _ => _.PageName).join(', '))

Undefined variable in modularized script

I've been working at making this script more modularized toady, and I am running into an error. Am I ordering my logic incorrectly?
Error Msg
Uncaught ReferenceError: accountId is not defined
Related Script Line
_.each(_.omit(accounts, _.keys(result.data.accounts)), function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);
});
Script
var debug = 0;
function paramsStr(p) {
var first = true;
var s = '';
_.each(p,function (value,key) {
if (!value) {
return;
}
if (first) {
s += '?';
first = false;
} else {
s += '&';
}
s += key+'='+value;
});
return s;
};
function parseReport(data)
{
var split = data.split('\n');
var results = [];
_.each(split,function (row) {
if (!row || row == "") {
return;
}
var myRow = JSON.parse(row);
myRow.timestamp = moment.utc(myRow.timestamp);
results.push(myRow);
});
return results;
}
function loadReport(report,granularity,startTime,endTime) {
if (debug && _.has(mock.reports,report) && _.has(mock.reports[report],granularity)) {
return jQuery.Deferred().resolve(parseReport(mock.reports[report][granularity])).promise();
}
var params = {
granularity : granularity
};
if (startTime) {
params['start-time'] = startTime.toISOString();
}
if (endTime) {
params['end-time'] = endTime.toISOString();
}
var url = '//analytics.locuslabs.com/api/reports/'+report+paramsStr(params);
return $.ajax({
url : url,
dataType : 'text'
}).then(function (data) {
return parseReport(data);
});
};
$(document).ready(function () {
var placeholder = $(".graph");
var oneMonth = moment().utc().subtract(1, 'months');
var twoWeeks = moment().utc().subtract(2, 'weeks');
//Function call to get the current time
function dateNow(target,timeFormat){
$(placeholder).siblings(target).text(moment(Date.now()).format(timeFormat));
}
function pollData(apiRoot,increment,startDate,label){
loadReport(apiRoot,increment, startDate).then(function (results) {
var totals = [];
var accounts = {};
_.each(results, function (result) {
totals.push([
result.timestamp.valueOf(),
result.data.total
]);
_.each(result.data.accounts, function (account, accountId) {
if (!_.has(accounts, accountId)) {
accounts[accountId] = {
label: account.account.name,
data: []
};
}
accounts[accountId].data.push([
result.timestamp.valueOf(),
account.total
]);
});
_.each(_.omit(accounts, _.keys(result.data.accounts)), function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);
});
});
var data = [{
data: totals,
label: label
}];
_.each(accounts, function (account) {
data.push(account);
});
$(this > ".graph").plot(data, {
grid: {
hoverable: true
},
tooltip: {
show: true
},
xaxis: {
mode: "time"
},
yaxis: {
axisLabel: label
},
legend: {
container: $(this > ".legend")
},
selection: {
mode: "x"
}
});
});
// Reload function within pollData function
document.getElementById(apiRoot + "-reload").addEventListener("click", function() {
pollData(apiRoot,increment,startDate,label);
dateNow(".status","M/D/YYYY H:mm Z");
}, false);
}
//Load Reports
pollData('total-installs', 'day', oneMonth, "Total Installs");
pollData('installs', 'hour', twoWeeks, "Installs (by hour)");
pollData('sessions', 'day', twoWeeks, "Sessions");
pollData('sessions-length', 'day', twoWeeks, "Session Length");
// Selection Feature
// TODO: Add Zoom to selection
// TODO: Overview of Available Data when zoomed.
placeholder.bind("plotselected", function (event, ranges) {
var begin = ranges.xaxis.from.valueOf();
var end = ranges.xaxis.to.valueOf();
$(this).siblings(".selection").text(moment(begin).format("M/D/YYYY H:mm Z") + " to " + moment(end).format("M/D/YYYY H:mm Z"));
/*
var zoom = $("#zoom").prop("checked");
if (zoom) {
$.each(plot.getXAxes(), function(_, axis) {
var opts = axis.options;
opts.min = ranges.xaxis.from;
opts.max = ranges.xaxis.to;
});
plot.setupGrid();
plot.draw();
plot.clearSelection();
}
*/
});
// Update on Initial Poll
// TODO: Ask for location and provide local time.
dateNow(".status","M/D/YYYY H:mm Z");
});
You have no accountId parameter in your function
function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);

Categories

Resources