BlackBerry 10 Cascades: How do I load data into a DropDown? - qml

I have managed to load data from a remote Json web service into a QML ListView, but there doesn't seem to be any such thing for the DropDown control.
Does someone have an example or an alternative method to accomplish a DropDown bound to attachedObjects data sources in Cascades?

I have an alternate method for you, Do note that I have used google's web service here for demonstration purpose, you need to replace it with your url & parse response according to that.
import bb.cascades 1.0
Page {
attachedObjects: [
ComponentDefinition {
id: optionControlDefinition
Option {
}
}
]
function getData() {
var request = new XMLHttpRequest()
request.onreadystatechange = function() {
if (request.readyState == 4) {
var response = request.responseText
response = JSON.parse(response)
var addressComponents = response.results[0].address_components
for (var i = 0; i < addressComponents.length; i ++) {
var option = optionControlDefinition.createObject();
option.text = addressComponents[i].long_name
dropDown.add(option)
}
}
}
// I have used goole's web service url, you can replace with your url
request.open("GET", "http://maps.googleapis.com/maps/api/geocode/json?address=" + "Ahmedabad" + "&sensor=false", true)
request.send()
}
Container {
DropDown {
id: dropDown
}
Button {
onClicked: getData()
}
}
}
Hope this helps.

Related

Interactive button doesn't work properly when using pub/sub

I'm writing a Hangouts Chat bot in C# that uses pub/sub so I can host the bot on our side of a firewall. Everything seems to work well except interactive buttons within cards. If I create a button with a specific action method name, the bot does receive the CARD_CLICKED message with the appropriate action method name. However, it doesn't seem like the card in the Hangouts Chat app knows a response was sent because the bot ends up getting the CARD_CLICKED message three times before the Hangouts Chat app finally says "Unable to contact Bot. Try again later". I've been using the Google.Apis.HangoutsChat.v1 and Google.Cloud.PubSub.V1 packages from NuGet for the bot.
This is speculation, but it seems like the issue might be that interactive buttons don't work properly through pub/sub. Any help would be appreciated.
Here is a snippet of the code I have:
SubscriptionName subscriptionName = new SubscriptionName(PROJECT_ID, SUBSCRIPTION_ID);
SubscriberServiceApiClient client = SubscriberServiceApiClient.Create();
GoogleCredential credential = GoogleCredential.FromFile(CREDENTIALS_PATH_ENV_PROPERTY).CreateScoped(HANGOUTS_CHAT_API_SCOPE);
HangoutsChatService chatService = new HangoutsChatService(new BaseClientService.Initializer
{
ApplicationName = "My Bot",
HttpClientInitializer = credential
});
while (true)
{
PullResponse response = client.Pull(subscriptionName, false, 3, CallSettings.FromCallTiming(CallTiming.FromExpiration(Expiration.FromTimeout(TimeSpan.FromSeconds(90)))));
if ((response.ReceivedMessages == null) || (response.ReceivedMessages.Count == 0))
Console.WriteLine("Pulled no messages.");
else
{
foreach (ReceivedMessage message in response.ReceivedMessages)
{
try
{
byte[] jsonBytes = message.Message.Data.ToByteArray();
JObject json = JObject.Parse(Encoding.UTF8.GetString(jsonBytes));
string messageType = (string)json["type"];
switch (messageType)
{
case "MESSAGE":
{
// Get text
string messageText = (string)json["message"]["text"];
Console.WriteLine($"[{messageType}] {messageText}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
Cards = new[]
{
new Card
{
Header = new CardHeader
{
Title = "Message Received!"
},
Sections = new[]
{
new Section
{
Widgets = new[]
{
new WidgetMarkup
{
Buttons = new[]
{
new Button
{
TextButton = new TextButton
{
Text = "Click Me!",
OnClick = new OnClick
{
Action = new FormAction
{
ActionMethodName = "ClickedAction"
}
}
}
}
}
}
}
}
}
}
},
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
case "CARD_CLICKED":
{
string actionMethodName = (string)json["action"]["actionMethodName"];
Console.WriteLine($"[{messageType}] {actionMethodName} at {((DateTime)json["message"]["createTime"]).ToString()}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
ActionResponse = new ActionResponse
{
Type = "UPDATE_MESSAGE"
},
Text = $"You clicked on '{actionMethodName}'.",
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
default:
{
Console.WriteLine($"[{messageType}]");
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error parsing message: {ex}");
}
}
// Acknowledge the message so we don't see it again.
string[] ackIds = new string[response.ReceivedMessages.Count];
for (int i = 0; i < response.ReceivedMessages.Count; ++i)
ackIds[i] = response.ReceivedMessages[i].AckId;
client.Acknowledge(subscriptionName, ackIds);
}
}
Using buttons with Hangouts Chat API requires a custom answer including:
{
'thread': {
'name': thread_id
},
'actionResponse': {
'type': 'UPDATE_MESSAGE'
}
}
I'd recommend using Hangouts Chat API with a bot URL.

Logs for Protractor

I am new to protractor and want to create logs for my test cases. I used if and else to write logs. I wanted to know if there is any better way of writing logs for protractor test cases?
My Code:
var colors = require('colors/safe');
var mapFeedBackpage=require('./mapFeedBack-page.js')
describe("Map feedback Automation",function()
{
var mapFeedBack= new mapFeedBackpage();
it("Check if the Url works ",function() //spec1
{
console.log("Checking the url :"+browser.params.url+'\n')
browser.get(browser.params.url);
browser.getCurrentUrl().then(function(value){
if(/report/.test(value) === false) {
fail("Result: URL doesnt works-FAIL \n");
}
else
{
console.log(colors.green("PASS :")+browser.params.url+ "is reachable \n");
}
});
});
it("test browser should reach report road option",function() //spec2s
{
console.log("Checking if road report option is available \n");
mapFeedBack.REPORT_ROAD.click();
expect(browser.getCurrentUrl()).toContain("report_road");
browser.getCurrentUrl().then(function(value){
if(/report_road/.test(value) === false) {
fail("Result: URL doesnt works-FAIL");
}
else
{
console.log(colors.green("PASS")+" Road report option is available");
}
});
});
Yes, you can use https://www.npmjs.com/package/log4js which is basically log4j module for nodejs apps. Since protractor is nodejs program it would certainly support this. It's very easy to implement this-
var log4js = require('log4js');
var logger = log4js.getLogger();
logger.debug("Some debug messages");
or you could write a custom logger:
var logger = exports;
logger.debugLevel = 'warn';
logger.log = function(level, message) {
var levels = ['error', 'warn', 'info'];
if (levels.indexOf(level) >= levels.indexOf(logger.debugLevel) ) {
if (typeof message !== 'string') {
message = JSON.stringify(message);
};
console.log(level+': '+message);
}
}
and then use this in your scripts as :
var logger = require('./logger');
logger.debugLevel = 'warn';
logger.log('info', 'Everything started properly.');
logger.log('warn', 'Running out of memory...');
logger.log('error', { error: 'flagrant'});

Getting post objects from ACS with photo_id

I'm developing an App that gets data from ACS, the post objects.
In my app there is button and when the users click that button it get the posts data.
In every post there is also a photo_id, which allows me to get the photo url from the cloud.
But there is a problem, it has a callback function and by the time the callback occurs it is too late.
Anyway, the code below only shows the last post with a photo, the first post doesn't have a photo.
(there are only 2 post objects so far).
I believe the problem is in the callback, but I can't seem to fix it.
Hope you guys can help me out, thanks in advance!
Here is my code:
function getCarsClick() {
Cloud.Posts.query({
page: 1,
per_page: 20
}, function (e) {
if (e.success) {
var tableData = [];
for (var i = 0; i < e.posts.length; i++) {
var post = e.posts[i];
var row = Titanium.UI.createTableViewRow();
var title = Titanium.UI.createLabel({
text:post.title,
font:{fontSize:18,fontWeight:'bold'},
color:'#ef349d',
width:'auto',
textAlign:'left',
top:2,
left:40,
height:30
});
var subtitle = Titanium.UI.createLabel({
text:post.content,
font:{fontSize:12,fontWeight:'normal'},
color:'#000000',
width:'auto',
textAlign:'left',
bottom:10,
left:60,
height:32
});
row.add(title);
row.add(subtitle);
row.hasChild=true;
row.height = 80;
row.selectedBackgroundColor = '#ef349d';
Cloud.Photos.show({
photo_id: post.photo_id
}, function (e) {
if (e.success) {
var photo = e.photos[0];
var img1 = Ti.UI.createImageView({image:photo.urls.square_75,width:30,height:30,left:2, top:2});
row.add(img1);
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
tableData.push(row);
}
//add table data
$.tableview1.setData(tableData);
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
If you pass a photo into the post using the default parameter provided, the image should come back by default and not require you to make an additonal API call to get the photo.
I would also suggest if you are just starting out to use Alloy and more importantly use ListViews not TableView
https://github.com/aaronksaunders/AppC-Alloy-Book-Misc

Creating a pdf from a Knockout JS view & viewModel

Scenario: In our application a user can create a invoice by filling in certain fields on a Knockout view. This invoice can be previewed, via another Knockout page. I want to use the preview url within our PDF creator (EVOPdf), so we can provide the user with a PDF from this invoice.
To preview the invoice we load the data (on document ready) via an ajax-request:
var InvoiceView = function(){
function _start() {
$.get("invoice/GetInitialData", function (response) {
var viewModel = new ViewModel(response.Data);
ko.applyBindings(viewModel, $("#contentData").get(0));
});
};
return{
Start: _start
};
}();
My problem is within the data-binding when the PDF creator is requesting the url: the viewModel is empty. This makes sense because the GetInitialData action is not called when the PDF creator is doing the request. Calling this _start function from the preview page directly at the end of the page does not help either.
<script type="text/javascript">
$(document).ready(function() {
InvoiceView.Start();
});
</script>
Looking at the documentation of EvoPdf, JavaScript should be executed, as the JavaScriptEnabled is true by default: http://www.evopdf.com/api/index.aspx
How could I solve this, or what is the best approach to create an pdf from a knockout view?
Controller action code:
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter();
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(url);
return new FileContentResult(pdfBytes, "application/pdf");
}
Javascript:
var model = this;
model.invoiceToEdit = ko.observable(null);
model.downloadInvoice = function (invoice) {
model.invoiceToEdit(invoice);
var url = '/invoice/preview';
window.location.href = '/invoice/pdfDownload?url=' + url;
};
The comment of xdumaine prompted me to think into another direction, thank you for that!
It did take some time for the Ajax request to load, but I also discovered some JavaScript (e.g. knockout binding) errors along the way after I put a ConversionDelay on the pdf creator object
pdfConverter.ConversionDelay = 5; //time in seconds
So here is my solution for this moment, which works for me now:
To start the process a bound click event:
model.downloadInvoice = function (invoice) {
var url = '/invoice/preview/' + invoice.Id() + '?isDownload=true';
window.open('/invoice/pdfDownload?url=' + url);
};
which result in a GET resquest on the controller action
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter { JavaScriptEnabled = true };
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
pdfConverter.ConversionDelay = 5;
var absolutUrl = ToAbsulte(url);
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(absolutUrl);
return new FileContentResult(pdfBytes, "application/pdf");
}
The Pdf creator is requesting this action on the controller, with isDownload = true (see bound click event):
public ActionResult Preview(string id, bool isDownload = false)
{
return PartialView("PdfInvoice", new InvoiceViewModel
{
IsDownload = isDownload,
InvoiceId = id
});
}
Which returns this partial view:
PartialView:
// the actual div with bindings etc.
#if (Model.IsDownload)
{
//Include your javascript and css here if needed
#Html.Hidden("invoiceId", Model.InvoiceId);
<script>
$(document).ready(function () {
var invoiceId = $("#invoiceId").val();
DownloadInvoiceView.Start(invoiceId);
});
</script>
}
JavaScript for getting the invoice and apply the knockout bindings:
DownloadInvoiceView = function() {
function _start(invoiceId) {
$.get("invoice/GetInvoice/" + invoiceId, function(response) {
var viewModel = new DownloadInvoiceView.ViewModel(response.Data);
ko.applyBindings(viewModel, $("#invoiceDiv").get(0));
});
};
return {
Start: _start
};
}();
DownloadInvoiceView.ViewModel = function (data) {
var model = this;
var invoice = new Invoice(data); //Invoice is a Knockout model
return model;
};

CasperJS looking for 404 error on links site

I'm beginner programmer. I found nice script
http://planzero.org/blog/2013/03/07/spidering_the_web_with_casperjs
I tried to rewrite this script with CasperJS test framework.
I would to get xunit report from this code
var startUrl = 'http://yoursite.foo';
var visitedUrls = [], pendingUrls = [];
var casper = require('casper').create({
pageSettings: {
loadImages: false,
loadPlugins: false
}});
var utils = require('utils')
var helpers = require('helpers')
// Spider from the given URL
casper.test.begin('href' , function(test) {
casper.start(startUrl, function() {
function spider(url) {
// Add the URL to the visited stack
visitedUrls.push(url);
// Open the URL
casper.open(url).then(function() {
test.assertHttpStatus(200, ":" + url);
// Find links present on this page
var links = this.evaluate(function() {
var links = [];
Array.prototype.forEach.call(__utils__.findAll('a'), function(e) {
links.push(e.getAttribute('href'));
});
return links;
});
// Add newly found URLs to the stack
var baseUrl = this.getGlobal('location').origin;
Array.prototype.forEach.call(links, function(link) {
var newUrl = helpers.absoluteUri(baseUrl, link);
if (pendingUrls.indexOf(newUrl) == -1 && visitedUrls.indexOf(newUrl) == -1 && !(link.search(startUrl) == -1)) {
pendingUrls.push(newUrl);
}
});
// If there are URLs to be processed
if (pendingUrls.length > 0) {
var nextUrl = pendingUrls.shift();
spider(nextUrl);
}
else {
console.log('links ended');
this.break;
}
});
}
spider(startUrl);
}).run(function(){
test.done();
});
});
Script is running but when he and Job I can't get report.
If you're trying to learn how to use CasperJS you need to start with a smaller example than that. That script is a mess which goes after a site named yoursite.foo (maybe you put that name in there?)
I would take small steps. I have a video which may help explain how to use CasperJS.
http://www.youtube.com/watch?v=Kefil5tCL9o