Blackberry 10 Cascades - search-ahead drop-down + tag field - blackberry

My question is related to Filipe Figueiredo's query (see: Blackberry 10 Cascades - Images inside Text Area)
My Cascades BB10 App requires a search-ahead drop-down with the ability to have multiple items selected and displayed as Tag Fields. Look & feel and behavior same as BB10 email composer's "To" address field - but with different data (e.g. country names).
Questions:
Is there a way to do this using Cascades components / controls?
(FlowListLayout does not meet exact requirements)
Can we achieve this using QML + javascript?
Or is there a way using C++ and QML for achieving this?
Is there a Component market Place for procuring custom controls for Cascades?
My development is stalled. Please help.

It should be possible. This is a prototype. It doesn't work well, but it's an idea. This is how it looks:
Code (yeah, it's bad. but it should work out of the box):
import bb.cascades 1.2
Page {
Container {
ListView {
id: tagList
dataModel: tagModel
layout: FlowListLayout {
headerMode: ListHeaderMode.None
}
preferredHeight: 200
function itemType(data, indexPath) {
return (data.add == 1 ? 'add' : '');
}
function mload(text) {
myList.load(text);
}
function showDropDown() {
myList.visible = true;
}
listItemComponents: [
ListItemComponent {
type: "add"
Container {
id: myAdd
TextField {
id: searchBox
preferredWidth: 300
onTextChanging: {
myAdd.ListItem.view.mload(searchBox.text);
}
onFocusedChanged: {
if (focused)
myAdd.ListItem.view.showDropDown();
}
}
}
},
ListItemComponent {
Container {
background: Color.create("#660000FF")
leftPadding: 10
rightPadding: 10
topPadding: 10
bottomPadding: 10
leftMargin: 10
bottomMargin: 10
Label {
id: country
textStyle.fontSize: FontSize.Medium
text: ListItemData.country
}
}
}
]
onTriggered: {
//todo: make it possible to remove a tag
console.log("item touched.. yay!")
}
attachedObjects: [
ArrayDataModel {
id: tagModel
}
]
}
ListView {
id: myList
visible: false
dataModel: mdataModel
preferredHeight: 400
attachedObjects: [
ArrayDataModel {
id: mdataModel
}
]
onTriggered: {
var selected = dataModel.data(indexPath);
var tmp = new Object();
tmp.country = selected;
tagModel.insert(tagModel.size() - 1, tmp);
console.log("removing: " + (tagModel.size() - 1 ) + " at size " + tagModel.size())
visible = false;
}
function load(text) {
var cities = [ "Slovenia", "Italy", "Slovakia", "Croatia", "Sweden", "Norway", "Poland", "Finland", "Spain",
"Indonesia", "Ireland" ]
var tmp = [];
for (var i = 0; i < cities.length; i ++)
if (cities[i].toLowerCase().indexOf(text.toLowerCase()) >= 0)
tmp.push(cities[i]);
mdataModel.clear();
mdataModel.insert(0, tmp);
}
function insertEdit() {
var edit = new Object();
edit["add"] = "1";
tagModel.insert(tagModel.size(), edit);
}
}
}
onCreationCompleted: {
myList.load("");
myList.insertEdit(); // insert item with TextField
}
}

Related

Angular UI-grid not sorting by date

I am using UI-grid, and I have a bunch of JS date objects like so:
"dob": new Date('1942-11-19')
I want to be able to filter the column by date when you click the "sort ascending/descending" buttons. As such, I have set the colDef up like so:
{
field: 'dob'
, displayName: 'D.O.B.'
, width: '130'
, editableCellTemplate: '<div><form name="inputForm"><input type="INPUT_TYPE" ng-class="\'colt\' + col.uid" ui-grid-editor ng-model="MODEL_COL_FIELD" style="border-bottom-color: #74B3CE; border-bottom-width: 2px;"></form></div>'
, headerCellClass: $scope.highlightFilteredHeader
, cellTemplate: '<div class="ui-grid-cell-contents" >{{grid.getCellValue(row, col)| date:\'MM-dd-yyyy\'}}</div>'
, cellFilter: 'date'
, type: 'date'
},
however, the column simply does not sort correctly. I even tried to set up a function to sort it from an external button like so:
function mostRecent(){
console.log('clicked mostRecent');
$scope.gridApi.grid.sortColumn(
$scope.gridApi.grid.getColumn('dob'), uiGridConstants.DESC
);
$scope.gridApi.grid.notifyDataChange(uiGridConstants.dataChange.ALL); //this line updates the rest of the columns accordingly
};
But it also causes a mish-mush sort that is not correct. Does anyone know what the issue is? I thought it might have to do with my cellTemplate, but after removing the template, there wasn't a difference...
Yes you are right, ui-grid doesn't support sorting of Date type columns.
However you can define a sortingAlgorithm in the columnDef.
Here is how your column definition should look like:
...
columnDefinition.sortingAlgorithm = function (firstDateString, secondDateString) {
var dateFormat = 'YYYY-MM-DD';
return function (firstDateString, secondDateString, dateFormat) {
if (!firstDateString && !secondDateString) {
return 0;
}
if (!firstDateString) {
return 1;
}
if (!secondDateString) {
return -1;
}
var firstDate = $window.moment(firstDateString, dateFormat);
if (!firstDate.isValid()) {
throw new Error('Invalid date: ', firstDateString);
}
var secondDate = $window.moment(secondDateString, dateFormat);
if (!firstDate.isValid()) {
throw new Error('Invalid date: ', secondDateString);
}
if (firstDate.isSame(secondDate)) {
return 0;
} else {
return firstDate.isBefore(secondDate) ? -1 : 1;
}
};
};
...
Please note that in this example Moment.js is used. It is a very useful library so you might probably find also another place in your project where to use it.
$scope.gridOptions = {
data: 'gridData',
columnDefs: [
{field: 'name', displayName: 'Name'},
{field:'age',
displayName:'Birth Date',
sortFn: function (aDate, bDate) {
var a=new Date(aDate);
var b=new Date(bDate);
if (a < b) {
return -1;
}
else if (a > b) {
return 1;
}
else {
return 0;
}
}
}]
};
Try this
http://plnkr.co/edit/0VD3X5YvuNSWAZlig95X?p=info
reference :
https://github.com/angular-ui/ui-grid/issues/222
You can define the Sorting Algorithm for the date fields in UI Grid like below
columnDefs: [
{
field: 'DateFrom', displayName: 'From',
sortingAlgorithm: function (aDate, bDate, rowA, rowB, direction) {
var a = new Date(moment(aDate, "DD-MM-YYYY").format("YYYY-MM-DD"));
//here DD-MM-YYYY is the current format in which the dates are returned
var b = new Date(moment(bDate, "DD-MM-YYYY").format("YYYY-MM-DD"));
if (a < b) {
return -1;
}
else if (a > b) {
return 1;
}
else {
return 0;
}
}
}
]
We can sort the ui-grid column containing date field in a simplest way.
Make use of cellTemplate in this way:
{
name: "Date",
field: 'date',
cellTemplate:'<div>{{row.entity.date | date:"dd/MM/yyyy"}}</div>'
},
So, you can choose any format for date, for eg. date:"dd-MM" etc.

Are the yahoo.finance related data api's change (YQL Console)?

I am trying to use yql for yahoo financial data. I checked the Show Community Table on the YQL console to see the database under the Yahoo tag.
I can see the tables under it but i am not getting results
here it is as follows:::
select * from yahoo.finance.analystestimate where symbol in ('YHOO')
{
"query": {
"count": 1,
"created": "2016-03-28T10:25:01Z",
"lang": "en-US",
"diagnostics": {
"url": [
{
"execution-start-time": "1",
"execution-stop-time": "767",
"execution-time": "766",
"content": "http://www.datatables.org/yahoo/finance/yahoo.finance.analystestimate.xml"
},
{
"execution-start-time": "771",
"execution-stop-time": "1821",
"execution-time": "1050",
"content": "http://finance.yahoo.com/q/ae?s=YHOO"
}
],
"publiclyCallable": "true",
"javascript": {
"execution-start-time": "769",
"execution-stop-time": "1823",
"execution-time": "1054",
"instructions-used": "5139",
"table-name": "yahoo.finance.analystestimate"
},
"user-time": "1824",
"service-time": "1806",
"build-version": "0.2.842"
},
"results": {
"results": {
"symbol": "YHOO"
}
}
}
}
here results are shown as empty ..
Has something changed? How can I find out what happened?
Is there an alternative solution I can use to obtain this data?
The JS the developer used to create the table us no longer working. This is it partially formatted. You can see that he's grabbing the page and then screen scraping it.
function getelement(row) {
if (row.hasOwnProperty("p")) return (row.p.text());
return (row.font.text());
} // Setup Query from finance.yahoo.com
var url = "http://finance.yahoo.com/q/ae?s=" + symbol;
var restquery = y.rest(url);
var rawresult = restquery.accept("text/html").get().response;
var aequery = y.xpath(rawresult, "//table[#class='yfnc_tableout1']/tr[count(td)=0]/parent::*|" + "//table[#class='yfnc_tableout1']/tr/td/table");
// Process Results
var aedata = < results symbol = {
symbol
} > < /results>; var i = 0; while(i < aequery.length()) { var table = aequery[i]; var thead = table.tr[0]; var tname = thead.th[0].strong.text().toString().replace(/ / g,
"");
var fname1 = thead.th[1].p.text().toString().replace(/\n.*/, "");
var fname2 = thead.th[2].p.text().toString().replace(/\n.*/, "");
var fname3 = thead.th[3].p.text().toString().replace(/\n.*/, "");
var fname4 = thead.th[4].p.text().toString().replace(/\n.*/, "");
fname1 = fname1.replace(/[\s\.]+/g, "").replace(/\&/, "");
fname2 = fname2.replace(/[\s\.]+/g, "").replace(/\&/, "");
fname3 = fname3.replace(/[\s\.]+/g, "").replace(/\&/, "");
fname4 = fname4.replace(/[\s\.]+/g, "").replace(/\&/, "");
var tblval = < {
tname
} > < /{tname}>; var j = 1; while(j < table.tr.length()) { var row = table.tr[j].td; var rname = row[0].p.text().toString().replace(/ [\s\.] + /g, ""); rname = rname.replace(/\ (.*\) / g,
"").replace(/\%/, "").replace(/^(\d)/, "_$1");
rname = rname.replace(/\//, "");
var rval1 = getelement(row[1]);
var rval2 = getelement(row[2]);
var rval3 = getelement(row[3]);
var rval4 = getelement(row[4]);
tblval.appendChild( < {
rname
} > < {
fname1
} > {
rval1
} < /{fname1}> <{fname2}>{rval2}</ {
fname2
} > < {
fname3
} > {
rval3
} < /{fname3}> <{fname4}>{rval4}</ {
fname4
} > < /{rname}>); j = j + 1; } aedata.appendChild(tblval); i = i + 1; }
// Return aedata strucuture
response.object = aedata;
Yes, the HTML structure for finance.yahoo.com has been changed somewhere in beginning of 2015, so YQL table implementation needs updating.
Please check the following GH pull requests which aims to fix the current outstanding issues:
GH-449: Update yahoo.finance.analystestimate.xml to new HTML structure
GH-457: Update yahoo.finance.analystestimate.xml
They're bit in overlap, so you may test them both (preferably check the first one).
Or you can check my fork of yql-tables (which consist loads of other fixes as well) where I've merged this PR into it, so find updated yahoo.finance.analystestimate.xml in here, the other one doesn't merge on top of the other one.

How to show specific point to show specific information in HighCharts

I am new to highcharts and I am working on a cricket app in which I have to display Run rate per over and number of wickets in an over. If there is a wicket(s) in the specific over I want to show a ball(s) to the point and on hover or click to that point it show the information about player and bowler etc.
What I want is you can view from this Link Crichq Graphs
I want the same think like in crichq graphs, but don't know how to do.
Please help me out of this issue.
You can use the point marker settings to indicate where the wickets fell. e.g. make it a different colour and size. http://api.highcharts.com/highcharts#series.data.marker
I would process the data as follows:
var ausData = [ { x:1, y:1 },
{ x:2, y:24, out:{num:2,names:['john','doe']} },
{ x:3, y:5 },
{ x:4, y:8 },
{ x:5, y:22 },
{ x:6, y:11 } ];
for (var p in ausData) {
var point = ausData[p];
if (point.out !== undefined) {
point.marker = {fillColor:'red',radius:4*point.out.num};
} else {
point.marker = {radius:5};
}
}
This start with the basic info, and then adds custom point markers depending on how the wickets fill.
The only other thing to do is customise the tooltip to give the names e.g.:
tooltip: {
formatter: function () {
var text = 'Over: ' + this.x +
' Runs: ' + this.y;
if (this.point.out !== undefined) {
text = text + '<br>Out: ' + this.point.out.num;
for (var n in this.point.out.names) {
text = text + ' ' + this.point.out.names[n];
}
}
return text;
}
},
http://jsfiddle.net/d6fgwg14/

Setting Context Item position in Firefox addons SDK

I'm writing an extension that involving adding an item to Firefox's context menu, but it appends to the end of the menu and I couldn't find any pointers customizing item's position using Addon SDK (insertBefore/insertAfter), I know how this can be done using XUL, but I'm trying to do it using Addon SDK or some sort of Addon SDK/XUL combination
This is the code snippet related to context menu
main.js
var pageMod = require("sdk/page-mod");
var data = require("sdk/self").data;
var tabs = require("sdk/tabs");
var cm = require("sdk/context-menu");
pageMod.PageMod({
include: "*.youtube.com",
contentScriptFile: data.url("page.js"),
onAttach: function (worker) {
worker.port.emit('link', data.url('convertbutton.png'));
}});
cm.Item({
label: "Convert File",
image: data.url("bighdconverterlogo128png.png"),
context: [
cm.URLContext(["*.youtube.com"]),
cm.PageContext()
],
contentScriptFile: data.url("menu.js"),
onMessage: function(vUrl){
tabs.open(vUrl);
}
});
data/menu.js
self.on("click", function(){
self.postMessage('http://hdconverter.co/' + 'c.php?url=' + window.location.href);
});
Thanks
i dont know about sdk but for non-sdk addons its easy. but because you dont have the boiler plate setup its going to look long. add this code to your addon at the bottom:
var positionToInsertMenu = 0; //set the position you want it at here
var myLabelText = 'Convert File';
const {interfaces: Ci,utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
/*start - windowlistener*/
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
aDOMWindow.addEventListener("load", function () {
aDOMWindow.removeEventListener("load", arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
var contentAreaContextMenu = aDOMWindow.document.getElementById('contentAreaContextMenu');
var myMenuItem;
if (contentAreaContextMenu) {
var menuItems = contentAreaContextMenu.querySelector('menuitem');
[].forEach.call(menuItems, function(item) {
if (item.getAttribute('label') == myLabelText) {
myMenuItem = item;
}
});
contentAreaContextMenu.removeChild(myMenuItem);
if (contentAreaContextMenu.childNodes.length >= positionToInsertMenu) { //position is greater then number of childNodes so append to end
contentAreaContextMenu.appendChild(myMenuItem);
} else {
contentAreaContextMenu.insertBefore(myMenuItem, contentAreaContextMenu.childNodes[thePosition]);
}
}
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
var myMenuItem = aDOMWindow.document.getElementById('myMenuItem');
if (myMenuItem) {
myMenuItem.parentNode.removeChild(myMenuItem);
}
}
};
windowListener.register();
on unload of your addon add this:
windowListener.unregister();
i copied pasted from a template and modded it real fast. for position to be accurate you probably have to consider which menuitems are hidden and which are not

Override Minimum length string of Select2

Select2 Jquery Plugin
I was having hard time how to override the default message for minimum length input in jquery Select2.
by default the plugin gives the following message.
Default Text
Please enter 1 more characters
My requirement was to show, the following text
Required Text
Enter 1 Character
please share the solution.
Thanks.
The accepted answer does not work for Select2 v4. Expanding on the comment by #IsaacKleinman, the way to override the default messages for an individual Select2 instance is through the language property:
var opts = {
language: {
inputTooShort: function(args) {
// args.minimum is the minimum required length
// args.input is the user-typed text
return "Type more stuff";
},
inputTooLong: function(args) {
// args.maximum is the maximum allowed length
// args.input is the user-typed text
return "You typed too much";
},
errorLoading: function() {
return "Error loading results";
},
loadingMore: function() {
return "Loading more results";
},
noResults: function() {
return "No results found";
},
searching: function() {
return "Searching...";
},
maximumSelected: function(args) {
// args.maximum is the maximum number of items the user may select
return "Error loading results";
}
}
};
$('#mySelect').select2(opts);
To override the functions globally, call the set function on the defaults (according to the docs):
$.fn.select2.defaults.set("key", "value")
However, in our code we do it like this:
$.fn.select2.defaults.defaults['language'].searching = function(){
return 'Custom searching message'
};
I don't know why we don't follow the docs, but it works.
Solution
Here is the solution that i have found out.
Prior to v4
Initialize
$("input[name='cont_responsible'],input[name='corr_responsible'],input[name='prev_responsible'],input[name='pfmea_responsible']").select2({
minimumInputLength: 1,
formatInputTooShort: function () {
return "Enter 1 Character";
},
});
Note
Do not forget to add this code in your document. ready function.
$(document).ready(function () {
});
I shared my solution, any better solutions are welcome.
Thanks.
Using v4 and onwards
The following worked for V4. #Isaac Kleinman
language: { inputTooShort: function () { return ''; } },
You can try this on version 4.0 or higher
you can see reference for answer frome this link :
issues reference
$("#select2").select2({
minimumInputLength: 1,
language: {
inputTooShort: function() {
return 'Please Add More Text';
}
}
});
If you are using django-select2, just add attributes to your form in forms.py:
widget=BookSelect2Widget(
attrs={'data-minimum-input-length': 1}
)
Override the function behaviour like below
$.fn.select2.defaults = $.extend($.fn.select2.defaults, {
formatMatches: function(matches) {
return matches + $filter('translate')('label.matches.found');
},
formatNoMatches: function() {
return $filter('translate')('noMatches.found');
},
formatInputTooShort: function(input, min) {
var n = min - input.length;
return $filter('translate')('label.please.enter ') + n + $filter('translate')(' more.characters') + (n == 1 ? "" : "s");
},
formatInputTooLong: function(input, max) {
var n = input.length - max;
return $filter('translate')('please.delete ') + n + $filter('translate')('')('delete.characters') + (n == 1 ? "" : "s");
},
formatSelectionTooBig: function(limit) {
return $filter('translate')('select.only') + limit + $filter('translate')('select.item ') + (limit == 1 ? "" : "s");
},
formatLoadMore: function(pageNumber) {
return $filter('translate')('load.results');
},
formatSearching: function() {
return $filter('translate')('label.search');
}
});
}

Resources