Bootbox Prompt multiline input text - prompt

I want to create a bootbox with a multiline prompt. It is the default example:
bootbox.prompt({
title: "What is your real name?",
value: "makeusabrew",
callback: function(result) {
if (result === null) {
Example.show("Prompt dismissed");
} else {
Example.show("Hi <b>"+result+"</b>");
}
}
});
But it just allow to have a inline value. I need to show a multiline value and have a multiline input text.

I just had to add inputType: "textarea"
bootbox.prompt({
title: "What is your real name?",
value: "makeusabrew",
inputType: "textarea",
callback: function(result) {
if (result === null) {
Example.show("Prompt dismissed");
} else {
Example.show("Hi <b>"+result+"</b>");
}
}
});
It works like a charm now :)

Related

NodeJS String.replace() problem while filtering

I can't modify the filtering parameter with
String.replace()
I can get the filtering keys from the URL as an object but its badly fromatted from me.
Filtering: {{URL}}/api/v1/bootcamps?averageCost[lt]=10000
Current format: { averageCost: { lt: '10000' } }
Right fromat: { averageCost: { $lt: '10000' } }
So I tried to convert it as a String and replace that value. But that value can be: lt, lte, gt, gte, in but it has some problem because the line after the .replace() method doesnt executed and of course the catch block cathes the error...
My code snippet:
try {
console.log(req.query);
const queryStr = JSON.stringify(req.query);
console.log(queryStr); //thats the last thing I get
queryStr = queryStr.replace(
/\b(gt|gte|lt|lte|in)\b/g,
match => `$${match}`
);
console.log(queryStr); // I dont get this
const bootcamps = await Bootcamp.find();
res.status(200).json({
succes: true,
count: bootcamps.length,
data: bootcamps
});
} catch (err) {
return res.status(404).json({ succes: false });
}
To replace it correctly you should use something like this:
let queryStr = '{ "averageCost": { "lt": "10000" }, "test": { "gt": "12345"} }';
const regex = /\b(gt|gte|lt|lte|in)\b/g;
queryStr = queryStr.replace(regex, '$$' + "$1"); // <-- here is the correct replace
This will replace queryStr with:
{ "averageCost": { "$lt": "10000" }, "test": { "$gt": "12345"} }
JSFiddle https://jsfiddle.net/c52z8ewr/
If you need the object back just do JSON.parse(queryStr)
You can also Try This
const queryCpy = { ...this.query };
// console.log(queryCpy, 'before filter');
console.log(queryCpy, 'after filter');
let queryString = JSON.stringify(queryCpy);
queryString = queryString.replace(
/\b(gt|gte|lt|lte)\b/g,
(rep) => `$${rep}`,
);
console.log(queryString, 'after filter');
If want an object in return do:
const bootcamps = await Bootcamp.find(JSON.parse(queryStr));

Setting body value doesn't work on MAC Outlook 2016

I'm using the 1.3 requirement set for setting/getting the body value of an appointment/meeting: Office.context.mailbox.item.body.getAsync(...) and Office.context.mailbox.item.body.setAsync(...)
This works just fine literally everywhere and for all account types(Exchange on-premise and Outlook/Office365 accounts) except Outlook 2016 for MAC, where it fails to apply the html/text value of the body.
Checking the requirement sets (https://dev.office.com/reference/add-ins/outlook/tutorial-api-requirement-sets) MAC Outlook is listed as supporting all the requirement set versions(1.1 to 1.5) so it should support also the getAsync and setAsync methods for body property.
Any idea why it does not work?
UPDATE:
For setting value:
function applyBody() {
const $dBod = $.Deferred();
try {
Office.context.mailbox.item.body.setAsync(_appointmentInfo.body.value, { coercionType: _appointmentInfo.body.type }, function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Succeeded) {
$dBod.resolve();
}
else {
$dBod.reject(translate.getTranslation('ERROR_SETTING_BODY'));
}
});
}
catch (e) {
$dBod.reject(e);
}
return $dBod.promise();
}
For getting value:
function getBody() {
const $dBod = $.Deferred();
getBodyType()
.done(function (bodyType) {
try {
Office.context.mailbox.item.body.getAsync(bodyType, function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Succeeded) {
$dBod.resolve({ value: asyncResult.value, type: bodyType });
}
else {
$dBod.reject(translate.getTranslation('ERROR_GETTING_BODY_VALUE'));
}
});
}
catch (e) {
$dBod.reject(e);
}
})
.fail($dBod.reject);
return $dBod.promise();
}
For getting body type:
function getBodyType() {
const $dBod = $.Deferred();
try {
Office.context.mailbox.item.body.getTypeAsync(function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Succeeded) {
$dBod.resolve(asyncResult.value);
}
else {
$dBod.reject(translate.getTranslation('ERROR_GETTING_BODY_TYPE'));
}
});
}
catch (e) {
$dBod.reject(e);
}
return $dBod.promise();
}
UPDATE2:
Method I use for concatenating initial body value with my html:
const filterNullsAndUndefined = function (array, char) {
return array.filter(function (val) { return val; }).join(char);
};
I call it like this filterNullsAndUndefined([intialBodyValue, myHtml],'');
Where in my case the initialBodyValue is the value I get using body.getAsync(...) before appending myHtml to it( in order to preserve any text the user inserted before myHtml template gets appended).
If I set myHtml directly on the body (overwrite) it works.
UPDATE 3:
Below the result we got when we appended the word 'Christmass':
appointment body as text
We are able to reproduce the issue. Adding a <b>Text</b> after the </html> works on Outlook 2016 desktop, but not on the Mac. We will be fixing this soon.

Firebase Flashlight (ElasticSearch) filtering, sorting, pagination

I am using Flashlight Firebase plugin
I am using this example and it's working fine
In the example you can see example.js file have method for query as below
// display search results
function doSearch(index, type, query) {
var ref = database.ref().child(PATH);
var key = ref.child('request').push( { index: index, type: type, query: query } ).key;
ref.child('response/'+key).on('value', showResults);
}
above function returning me the results when I pass values like following JSON
{ index: index, type: type, query: query }
It returning me nothing when i am trying to pass values like following JSON
{ index: index, type: type, query: { "from" : 1, "size" : 5 , "query": query }
but the following ElasticSearch API returning me the result
http://localhost:9200/firebase/user/_search?q=*mani*&pretty&size=5&from=1
and How do i filtering the query using Flashlight like following
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "drama"
}
},
"filter": {
//Filter to apply to the query
}
}
}
}
I am using following security rules
{
"rules": {
".read": false,
".write": false,
"search": {
"request": {
"$recid": {
// I can only read records assigned to me
".read": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
// I can only write new records that don't exist yet
".write": "!data.exists() && (newData.child('id').val() === auth.id || newData.child('id').val() === auth.uid)",
".validate": "newData.hasChildren(['query', 'index', 'type'])",
"index": {
// accepts arrays or strings
".validate": "(newData.isString() && newData.val().length < 1000) || newData.hasChildren()",
"$child": {
".validate": "newData.isString() && newData.val().length < 1000"
}
},
"type": {
// accepts arrays or strings
".validate": "(newData.isString() && newData.val().length < 1000) || newData.hasChildren()",
"$child": {
".validate": "newData.isString() && newData.val().length < 1000"
}
},
"query": {
// structure of the query object is pretty open-ended
".validate": "newData.isString() || newData.hasChildren()"
},
"$other": {
".validate": false
}
}
},
"response": {
"$recid": {
// I can only read/write records assigned to me
".read": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
".write": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
// Assumes that Flashlight will be writing the records using a secret or a token that has admin: true
// The only thing a logged in user needs to do is delete results after reading them
".validate": false
}
}
}
}
}
Please let me know how to perform complex queries and filtering with Flashlight
Finally I did it myself
here is the solution
You need to update SearchQueue.js
_process: function (snap) {
var dat = snap.val();
var key = snap.key;
if (this._assertValidSearch(key, dat)) {
// get your query string
var q = dat.query.query;
console.log('search', "test", JSON.stringify(dat, null, 2));
// build your ES query
//var q1 = {"query":{"match":{"_all":q}}};
// Perform (a very simple) ElasticSearch query
this.esc.search({
index: dat.index,
type: dat.type,
// add options
from : dat.query.from,
size : dat.query.size,
// add ES Query
//body : q1
q:dat.query.query
}, function (error, response) {
if (error) {
this._reply(key, {error: error, total: 0});
} else {
this._reply(key, response);
}
}.bind(this));
}
}
and update Example.js
// display search results
function doSearch(index, type, query) {
var ref = database.ref().child(PATH);
var jsonOBJ = {
index: index,
type: type,
query: { size:1, from:0, query:query},
};
var key = ref.child('request').push(jsonOBJ).key;
console.log('search', key, JSON.stringify(jsonOBJ, null, 2));
ref.child('response/'+key).on('value', showResults);
}

add custom buttons on alertify confirm dialog box

I am using Alertify js 1.6.1 to show dialog box when user leaves a page. Apart from Ok and Cancel, I need to add one extra button "continue" in alertify js confirm dialog box. Is there a way to add custom button functionality? Let me know if you have any ideas on it. Thanks
You can build your own or extend the existing confirm:
alertify.dialog('myConfirm', function() {
var settings;
return {
setup: function() {
var settings = alertify.confirm().settings;
for (var prop in settings)
this.settings[prop] = settings[prop];
var setup = alertify.confirm().setup();
setup.buttons.push({
text: '<u>C</u>ontinue',
key: 67 /*c*/ ,
scope: 'auxiliary',
});
return setup;
},
settings: {
oncontinue: null
},
callback: function(closeEvent) {
if (closeEvent.index == 2) {
if (typeof this.get('oncontinue') === 'function') {
returnValue = this.get('oncontinue').call(this, closeEvent);
if (typeof returnValue !== 'undefined') {
closeEvent.cancel = !returnValue;
}
}
} else {
alertify.confirm().callback.call(this, closeEvent);
}
}
};
}, false, 'confirm');
see example

how to set time interval for a specific function?

Presently I have set time interval in such a way that every 1 seconds,a function is executed.The problem is that,i am displaying notification through this function.There are notification buttons in notification.When I click on the notification action button,mulitple windows are being open.I found out that it is because I have set Timer.But in my extension , timer is necessary in order to check the output of a server file everytime.Anyone please help me.Is there any other way to deal this problem
Here is my background.js
var myNotificationID = null;
var oldChromeVersion = !chrome.runtime;
setInterval(function() {
updateIcon();
}, 1000);
function onInit() {
updateIcon();
if (!oldChromeVersion) {
chrome.alarms.create('watchdog',{periodInMinutes:5,delayInMinutes: 0});
}
}
function onAlarm(alarm) {
if (alarm && alarm.name == 'watchdog') {
onWatchdog();
}
else {
updateIcon();
}
}
function onWatchdog() {
chrome.alarms.get('refresh', function(alarm) {
if (alarm) {
console.log('Refresh alarm exists. Yay.');
}
else {
updateIcon();
}
});
}
if (oldChromeVersion) {
updateIcon();
onInit();
}
else {
chrome.runtime.onInstalled.addListener(onInit);
chrome.alarms.onAlarm.addListener(onAlarm);
}
function updateIcon(){
if(//something)
//something
else{
chrome.notifications.create(
'id1',{
type: 'basic',
iconUrl: '/calpine_not_logged_in.png',
title: 'Warning : Attendance',
message: 'Please mark your Attendance !',
buttons: [{ title: 'Mark',
iconUrl: '/tick.jpg'
},{ title: 'Ignore',
iconUrl: '/cross.jpg'}],
priority: 0},
function(id) { myNotificationID = id;}
);
chrome.notifications.onButtonClicked.addListener(function(notifId, btnIdx) {
if (notifId === myNotificationID) {
if (btnIdx === 0) {
window.open("http://www.calpinemate.com/");
} else if (btnIdx === 1) {
notification.close();
}
}
});
chrome.notifications.onClosed.addListener(function() {
notification.close();
});
}
} }
});
}
}
onInit();
Here i found out that,when i remove the delayInminutes and laso the set timeineterval it opens only one tab,as i want.But both of them are necessary to do continuous checking of a server file.because whole my operation is based on the server file output.Is there any way to cope with this problem.Is there any way to set time interval for only that function?
The problem has nothing to do with what you "suspect". The problem is that you add a listener for chrome.notifications.onButtonClicked events inside the updateIcon() function. So this is what happens:
Every second you execute updateIcon().
Inside updateIcon() you set a new listener that listens for notification-buttons being clicked.
So, after 1 second there will be 1 listener, after 2 seconds there will be 2 listeners, after n seconds there will be n listeners.
When you click the button, each listener will catch the onButtonClicked event and open a new window. (So there will be so many windows as many seconds have elapsed since you loaded your extension.
How to fix this:
You need to create the listener only once (and not every second). To remove the following piece of code from inside the updateIcon() function:
chrome.notifications.onButtonClicked.addListener(function(notifId, btnIdx) {
if (notifId === myNotificationID) {
if (btnIdx === 0) {
window.open("http://www.calpinemate.com/");
} else if (btnIdx === 1) {
notification.close();
}
}
});
And place it at the end of your background-page (just before onInit();). Make sure you don't place it inside any function.

Resources