Autocomplete in blockly text - blockly

I'm just starting into blockly. I have seen that you can ask inputs to the users with a js popup. Is there a way of providing the users with more complex selectors such as an autocomplete textfield? For the moment, calling a jquery and getting the value should be enough, such as
$( function() {
var availableTags = [
"aaa",
"bbb",
"ccc",
"ddd"
];
$( "#tags" ).autocomplete({
source: availableTags
});
});
(this is an example, any other available js autocomplete library is ok)

Related

Why is the JSON output different from the actual output as rendered in the browser? [duplicate]

I have a problem with logging out the contents of an array inside an object. The actual object looks like this
var stuff = { accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: ['new item1', 'new item2'] },
messageId: 'xxxxxxxxxxxxx' } }
The console.log shows the items of the first array fine but the second array is being output as [Object].
{ accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: [Object] },
messageId: 'xxxxxxxxxxxxx' } }
What is happening here and how can I get the items of the second array to show when I console.log. Thanks for any help!
UPDATE
Sorry, I forgot to add that I am working exclusively in Node.js so it's a server side log that needs to display the object exactly as it's received from a callback with a straight console.log, ie. no further stringify-ing.
I also just tried creating another random object with a similar structure like this.
var objText = {
fun: {
stuff: 'Some stuff',
list: ['this', 'it', 'takes']
}
};
The console.log for the above is:
{ fun: { stuff: 'Some stuff', list: [ 'this', 'it', 'takes' ] } }
This appears to be the same structure to me and yet the console.log works fine so it seems to be perfectly possible in Node to log arrays content even when it's embedded inside and an object inside an outer object.
It looks like this is an old topic, anyway
I've faced the same issue, embedded array printed as [Array].
It is because of console.log in the node.js uses util.inspect for print, the default depth is 2.
So, to print something which is deeper than 2 followings can be used:
const util = require('util')
console.log(util.inspect(errors, true, 10))
This is the default way for some browser and implementations of showing too complex or deep objects/arrays with console.log. An alternative is to use JSON.stringify with console.log:
var stuff = {
accepted: ['item1', 'item2'],
rejected: [],
response: 'Foo',
envelope: {
from: 'The sender',
to: ['new item1', 'new item2']
},
messageId: 'xxxxxxxxxxxxx'
}
console.log(JSON.stringify(stuff, null, 4));
EDIT:
Another alternative is to use console.dir in case you have a too complex or recursive object, see https://stackoverflow.com/a/27534731/6051261
Try it with: console.log(JSON.stringify(variable))
If you like Chrome devtools, that folds your json objects and let you observe a lot of things, you can use the --inspect flag:
node --inspect index.js
The console will then give you an URL and you just have to copy paste in Google Chrome to enjoy Google Chrome console.
More information on this link

Trying to update a mongodb document field via pug/node.js button click

This is a document from my todo mongodb:
"_id" : ObjectId("5a1e96f856f24c43b886eb54"),
"title" : "Drink coffee",
"note" : "Tomorrow morning",
"open" : true,
"duedate" : "2017-12-03"
This is the pug code that populates a todo list page
each todo in todolist
if todo.open
div
a(href="#") #{todo.title}
div
p(style='white-space:pre;')
| #{todo.note}
| Due: #{todo.duedate}
button(id="doneButton") Done
The above works fine. The todo page displays all todo items as expected.
What I want to do:
When user clicks on 'Done' button, I want to update that particular document to "open": false.
(I want to do this onclick, and not by loading the item on a new edit page with an edit button. When todo list page reloads, that todo item is removed from the list. I do not want to delete the document as I need to archive it later on.)
So my questions are:
How do I code the 'Done' button on the pug page so that it gets
associated with the particular document that needs to be updated?
How do I structure the POST code on my index.js so that it listens for
the button click and performs the relevant document update?
UPDATE
OK, so I don't know enough to understand kentor's reply (but thank you anyway!). I did a bit of research though and some copying and pasting, and I have moved the problem a couple of steps forward - I hope.
New pug code:
each todo in todolist
if todo.open
a(href="#") #{todo.title}
p #{todo.note}
p Due: #{todo.duedate}
form#form_update_item(name="updateitem", method='post', action='/updateitem')
input#input_name(type="hidden", placeholder="", name="_id", value="#{todo._id}")
button(type="submit") Done
index.js code
router.post('/updateitem', function(req, res) {
var MongoClient = mongodb.MongoClient;
var ObjectId = require('mongodb').ObjectId;
var url = 'mongodb://localhost:27017/tododb';
MongoClient.connect(url, function(err, db) {
if (err) {
console.log("can't connect", err);
}
else {
console.log('Connected to server. Woohoo!');
var collection = db.collection('todolist');
collection.findOneAndUpdate(
{"title": "Make smoothie"},
{
$set: {
"open": false
}
},
function(err, result) {
if (err) {
console.log(err);
} else {
res.redirect("todolist");
}
db.close();
});
}
});
});
What happens now:
On button click, doc with title "Make Smoothie" changes to "open": false. So button triggers the change I want. Bang! But this is only a partial solution to help me isolate the problem.
What I still need:
On button click, I want the doc's ID whose button was clicked to replace {"title": "Make smoothie"} so that the "open": false change can be made. Something like {_id: "doc ID coming from button blah blah"}.
UPDATE 2
Discovered that I was using Jade syntax not Pug, so instead of this
value="#{todo._id}
I should be using
value=todo._id
So now index.js can console.log the ID the Pug form is passing. Last challenge is to use that ID to change the corresponding mongodb document as described above.
I finally solved it
Last step, I replaced
{"title": "Make smoothie"}
with
{"_id": ObjectId(req.body._id)}
and sure enough, every time I click on a button, the server updates the corresponding document's "open": false
You could just attach a data attribute to the HTML button like this:
button(id="doneButton", data-id=todo._id) Done
Then you would just attach an event listener to this button and send a POST request containing this data-id. Using Jquery it could look like this:
.script
$('#doneButton').on("click", function (element) {
var data = $(this).data("id");
$.ajax({
type: "POST",
url: "your-url",
data: { todoId: data },
success: responseHandler
})
})

Telegram callback_data for link buttons

I'm sending a link button throught a Telegram bot and I would like to get the callback_data after the user opens the url.
My options are:
var options = {
parse_mode: "Markdown",
reply_markup: {
inline_keyboard: btns
}
};
where btns is
[
[{ text: "Read first", url: "http://any", callback_data: "any_relevant_data }]
]
The button shows perfectly, the link works, but no callback is triggered and I never hit
bot.on('callback_query', (callback_message) => { //any action });
Is this a missing feature or it's me, doing something wrong?
According to API Document, you can't use url and text in the same time.
This object represents one button of an inline keyboard.
You must use exactly one of the optional fields.

Fetch Backbone collection with search parameters

I'd like to implement a search page using Backbone.js. The search parameters are taken from a simple form, and the server knows to parse the query parameters and return a json array of the results. My model looks like this, more or less:
App.Models.SearchResult = Backbone.Model.extend({
urlRoot: '/search'
});
App.Collections.SearchResults = Backbone.Collection.extend({
model: App.Models.SearchResult
});
var results = new App.Collections.SearchResults();
I'd like that every time I perform results.fetch(), the contents of the search form will also be serialized with the GET request. Is there a simple way to add this, or am I doing it the wrong way and should probably be handcoding the request and creating the collection from the returned results:
$.getJSON('/search', { /* search params */ }, function(resp){
// resp is a list of JSON data [ { id: .., name: .. }, { id: .., name: .. }, .... ]
var results = new App.Collections.SearchResults(resp);
// update views, etc.
});
Thoughts?
Backbone.js fetch with parameters answers most of your questions, but I put some here as well.
Add the data parameter to your fetch call, example:
var search_params = {
'key1': 'value1',
'key2': 'value2',
'key3': 'value3',
...
'keyN': 'valueN',
};
App.Collections.SearchResults.fetch({data: $.param(search_params)});
Now your call url has added parameters which you can parse on the server side.
Attention: code simplified and not tested
I think you should split the functionality:
The Search Model
It is a proper resource in your server side. The only action allowed is CREATE.
var Search = Backbone.Model.extend({
url: "/search",
initialize: function(){
this.results = new Results( this.get( "results" ) );
this.trigger( "search:ready", this );
}
});
The Results Collection
It is just in charge of collecting the list of Result models
var Results = Backbone.Collection.extend({
model: Result
});
The Search Form
You see that this View is making the intelligent job, listening to the form.submit, creating a new Search object and sending it to the server to be created. This created mission doesn't mean the Search has to be stored in database, this is the normal creation behavior, but it does not always need to be this way. In our case create a Search means to search the DB looking for the concrete registers.
var SearchView = Backbone.View.extend({
events: {
"submit form" : "createSearch"
},
createSearch: function(){
// You can use things like this
// http://stackoverflow.com/questions/1184624/convert-form-data-to-js-object-with-jquery
// to authomat this process
var search = new Search({
field_1: this.$el.find( "input.field_1" ).val(),
field_2: this.$el.find( "input.field_2" ).val(),
});
// You can listen to the "search:ready" event
search.on( "search:ready", this.renderResults, this )
// this is when a POST request is sent to the server
// to the URL `/search` with all the search information packaged
search.save();
},
renderResults: function( search ){
// use search.results to render the results on your own way
}
});
I think this kind of solution is very clean, elegant, intuitive and very extensible.
Found a very simple solution - override the url() function in the collection:
App.Collections.SearchResults = Backbone.Collection.extend({
urlRoot: '/search',
url: function() {
// send the url along with the serialized query params
return this.urlRoot + "?" + $("#search-form").formSerialize();
}
});
Hopefully this doesn't horrify anyone who has a bit more Backbone / Javascript skills than myself.
It seems the current version of Backbone (or maybe jQuery) automatically stringifies the data value, so there is no need to call $.param anymore.
The following lines produce the same result:
collection.fetch({data: {filter:'abc', page:1}});
collection.fetch({data: $.param({filter:'abc', page:1})});
The querystring will be filter=abc&page=1.
EDIT: This should have been a comment, rather than answer.

CouchApp: List function with include_docs=true

I'm writing a simple CMS CouchApp as a pet project. I'm running CouchDB 1.2.0 on OS X 10.7.4 and using the Python CouchApp development tool.
Basically I wanna have pages as documents and a page would refer to another document that contains the shared layout of the site.
Example of a page document:
{
"_id": "index",
"_rev": "3-d5451ea54212ae6ec0d8d2d95c5f225d",
"content": "<img src=\"/images/img.jpg\"/> <p>Lorem ipsum dolor sit amet.</p>",
"layout": "layouts/default"
}
Example of a layout document:
{
"_id": "layouts/default",
"_rev": "1-d2fa96e15ab8768828b262d81265f3d2",
"content": "<!DOCTYPE html> <html><head> <title>Foo</title> </head><body><div>{{content}}</div></body> </html>"
}
So basically to render a page I will need to fetch two documents. I would then render the page into the layout using Mustache.
I fiddled around with show functions for a while but couldn't figure out a way to get the layout document in the function. I then stumbled upon include_docs and I'm now trying to get this to work using a list function and a view. My map function is as follows:
function(doc) {
if (doc.layout) {
emit([doc._id, 1], doc);
emit([doc._id, 0], {_id: doc.layout });
}
};
When I navigate to the view itself in a browser giving the parameters include_docs=true&startkey=["index",0]&endkey=["index",1], it works just fine and is loading the layout documents.
However, the layout document doesn't get passed to list functions. Running this list function on the aforementioned view
function(head, req) {
var doc = null;
var row = getRow();
do
{
if (!row.value.layout){
doc = row.value;
}
} while (row = getRow())
for (i in doc) {
send(i);
}
}
... with the same parameters renders:
_id
I did a bit of googling and noticed that there was a bug in CouchDB where linked documents didn't get passed onto the list function. As far as I can tell, this should be fixed already. Is this a case of regression or me being retarded?
The value of the row is stored in row.value, but the doc for the row is in row.doc. :)

Resources