I am a novice in Sencha Touch 2 & Ext too. I have jquery knowledge, so I am relating few things similar for quick understanding but got stuck in selector query.
I am creating dynamic textfields like:
var autoSuggestField = 'people_' + counter; // suppose counter is looping 5 times
var field = new Ext.field.Text({
name: autoSuggestField,
itemId: 'testing', // just for testing
// itemId: autoSuggestField, // actual code
inputCls:'auto-suggest',
placeHolder:'Select People',
cls:'place-holder',
listeners: {
clearicontap:function(obj, e, eOpts) {
// tried option 1
var allPeople = Ext.ComponentQuery.query('.place-holder .auto-suggest');
console.log(allPeople); // console says '[]'
// tried option 2
var allPeople = Ext.ComponentQuery.query('.place-holder');
console.log(allPeople); // console says '[]'
// tried option 3
var allPeople = Ext.ComponentQuery.query('.auto-suggest');
console.log(allPeople); // console says '[]'
// tried option 4
var allPeople = Ext.ComponentQuery.query('#testing');
console.log(allPeople); // console says '[class , class, class]'
}
}
});
But I am looking for something:
// var allPeople = Ext.ComponentQuery.query('[name^=people_]'); // as we do jquery
Or anything similar to it, which should work. Please clear what I am doing wrong in option[1,2,3] as most of the post says that using id[option 4] is bad. An how can we achieve using [name^=] "which says any element starting with people_". Is it possible in Ext? Is it possible through REGEX?(just for an idea)
Please add explanations for better understanding of selectors.
Instead of looking for regular expressinons you can add a an extra config like type:'people' for all the people related textfiled components and you can query it using the
var allPeopleComponents = Ext.ComponentQuery.query('textfield[type=people]');
The above will return the array of components having type='people'.
Please take a look here and for better understanding of ComponentQuery options here
Hope it helps you.
Related
I've been working with Liferay 7 for a while and needed to create a feedback form with prefilled values. I created a feedback form and a page, where it's shown and where I could add Javascript.
The user clicks on a link ("Did you find this helpful? Yes/No") and it takes you to the feedback page with the page and answer as URL parameters.
URL: {feedback-page-url/} ?pageUrl=/services&answer=Yes
Now here's where the problems began. Liferay updates it's values very confusingly and while generic document.getElementsByName(...) etc. seemed to work at first, they updated back when clicking the page. The difficult thing is to update the right values in right elements, so they won't be overrun by Liferay.
I provided an answer to my question below. Feel free to ask me anything, I'll try to help :)
Full code block in the end!
So I found out a solution to this problem. Liferay creates an instance (_com_liferay...) and uses it's values to be up to date, so we need to get a hold of it and update it's values. You can do it manually by inspecting and finding your instance, but I have an automatic code that should get it for you.
The id we are searching for is for DDMFormPortlet and the String we get this way is close to perfect. The String that document.querySelector() finds begins with p_p_id_com..., so we can use .substring to remove the unnecessary part and then add +"form" in the end to make it complete. If you find a better way to find this, please share it :)
// _com_liferay_dynamic_data_mapping_form_web_portlet_DDMFormPortlet_INSTANCE_randomkey_form
const idFinder = function() {
const idString = document.querySelector('[id*="DDMFormPortlet"]').id;
return(idString.substring(6) + "form");
}
Now that we have the correct String text, we'll find the element, that corresponds to it:
const formFieldArray = window[idFinder()];
Now if you try it just by itself, it most likely won't find anything, because it's loads slowly. I put all of this into try-catch with setTimeout() to make sure everything works as intended. Now all we need to do is collect the information from our URL and set it to the correct places.
const params = new URLSearchParams(location.search);
const formAutoFiller = function (params) {
try {
const formFieldArray = window[idFinder()];
// make sure you have the numbers according to your form!
formFieldArray.pages[0].rows[0].columns[0].fields[0].value=params.get('pageUrl');
formFieldArray.pages[0].rows[1].columns[0].fields[0].value=params.get('answer');
// ...
}
}
And finally, as the changed values update to the form after clicking an input field, we'll move the selection focus to one of the input fields after the other code is ran:
document.getElementsByClassName("ddm-field-text")[1].focus();
A bit cleanup for myself and we're done! Full Javascript here:
const params = new URLSearchParams(location.search);
const idFinder = function() {
const idString = document.querySelector('[id*="DDMFormPortlet"]').id;
return(idString.substring(6) + "form");
}
const formAutoFiller = function (params) {
try {
const formFieldRows = window[idFinder()].pages[0].rows;
formFieldRows[0].columns[0].fields[0].value=params.get('pageUrl');
formFieldRows[1].columns[0].fields[0].value=params.get('answer');
document.getElementsByClassName("ddm-field-text")[1].focus();
} catch (e) {
setTimeout(formAutoFiller, 500, params);
}
}
formAutoFiller(params);
Messing around with an autocomplete plugin available at https://www.npmjs.com/package/bootstrap-4-autocomplete, and the following works:
$('#id').autocomplete({
source: {'test1':1, 'test2':2, 'test1':3}
});
Instead of local JSON, will need to make an XMLHttpRequest and was thinking something like the following, and while I don't get an error, I also don't get anything:
$('#id').autocomplete({
source: function() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
return JSON.parse(this.responseText);
}
};
xhttp.open(method, url, true);
xhttp.send();
}
});
The plugin's author made the following remark a while back:
I don't have plans to directly invoke any url inside the lib. What you
can do is set autocomplete to your textfield after your ajax call
returns, which you can do with jQuery, like this:
$.ajax('myurl').then((data) => $('#myTextfield').autocomplete({
source: data }));
You don't have to worry about setting autocomplete to a field multiple
times, it is supposed to work like this when you need to change the
source.
Tried it and as expected, $.ajax() initiated an XMLHttpRequest request upon page load, and not as desired when the user enters a character into the search input.
How am I able to make an XMLHttpRequest to source the data into the plugin? I am assuming that I should be using a promise, however, if not, still would appreciate any assistance.
Thanks
Well, that's how plugin supposed to work. Its meat and potatoes is createItems function, called on keyup event - and responsible for filling out that dropdown with items. And here's its key part (1.3.0 version):
function createItems(field: JQuery < HTMLElement > , opts: AutocompleteOptions) {
const lookup = field.val() as string;
// ...
let count = 0;
const keys = Object.keys(opts.source);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const object = opts.source[key];
const item = {
label: opts.label ? object[opts.label] : key,
value: opts.value ? object[opts.value] : object,
};
if (item.label.toLowerCase().indexOf(lookup.toLowerCase()) >= 0) {
items.append(createItem(lookup, item, opts));
if (opts.maximumItems > 0 && ++count >= opts.maximumItems) {
break;
}
}
}
// skipped the rest
}
As you can see, each time createItems is called, it goes through source object, grepping all the items containing lookup string.
So all the data parts are expected to be there - and to be processable synchronously. That's the plugin's way, with all good and bad coming out of this approach.
The best thing the plugin's author could've suggested here (without going against what plugin is about) is using AJAX to prepopulate the data before calling autocomplete. And that's what he did in that comment actually.
Now, what can be done here? One might think it's enough just to transform createItems into an async function - for example, calling source if it's a function and expecting its result to be a Promise. It seems to be seductively simple excluding that lookup loop in process - and just take the the results of that AJAX call to repopulate source...
But that's not so simple, unfortunately: there are several caveats to be aware of. What should happen, for example, if user stops typing (triggering first AJAX call), then types some more, then stops once again (triggering another AJAX call) - but the first one actually arrives later? The corresponding bug was plaguing a lot of autocomplete implementations I've been working with, sadly - it's not that easy to reproduce if you're testing only with fast network connections (let alone only on localhost).
That's just one of the reasons the author decided against extending that plugin, it seems. After all, it was built to solve one specific task - and it does this well. So unless you want to fork it and essentially rewrite it into 'two strategies' one, I'd suggest considering looking somewhere else.
drawBarChart = function (data) {
//few statements goes here which sets options which are being passed to chartDraw i.e. t.options.chart.options
gChart = new google.visualization.BarChart(chartingPlace);
//setTimeout(function () {
// t.options.chart.options.height = ((t.chart.size.height) - 40) + "px";
////console.log(JSON.stringify(t.options.chart.options));
//google.visualization.events.addListener(gChart, 'ready', function () {
// grab a few details before redirecting
google.visualization.events.addListener(gChart, 'select', function () {
var selectedItem = gChart.getSelection()[0];
console.log(gChart.getSelection());
if (selectedItem) {
var topping = data.getValue(selectedItem.row, 0);
alert('The user selected ' + topping);
}
// });
});
gChart.draw(data, t.options.chart.options);
}
My app having a number of charts displaying for different scenarios. My requirement is, click on a bar from google bar chart and open a new tab associated with the name of the bar. For this purpose, I tried using direct 'select' event on bar chart as follows:
google.visualization.events.addListener(gChart, 'select', function () {
var selectedItem = gChart.getSelection()[0];
console.log(gChart.getSelection());
if (selectedItem) {
var topping = data.getValue(selectedItem.row, 0);
alert('The user selected ' + topping);
}
});
But I could not get, this returned empty array for gChart.getSelection(), so I tried the code with 'ready' event mentioned in as first code above.
It works, but not output is not consistent. sometimes it gives empty array and sometimes with selected object.
I am still not able to find why it is showing this kind of behavior
More info: my application is having different tabs, showing number of bar,line,area,combo charts on it. getSelection() works well with line chart but not able to get the consistent output with bars.
Any help is appreciable.
Please do not mark it as duplicate, as I have gone through other similar questions but they does not answer my issue, I do not have that privilege so I could not comment in replies asking for more clarification.
Similar question here : google visualization-Click event on barchart isStacked: true
Please help!
Thank you in advance!
Updates :
I could not get any answer or any response from here.
This is really very disappointing.
Solution:
This is how i worked out the solution for this problem :
The getSelection could not work for me so i tried click event on bar text. Through the click event i could get the text on bar and i linked it to opn new tab.
If anyone need solution in code, please let me know.
Thank you.
Please go through below code snippet, I corrected or you can say organised the code in different way. If you need further explanation please let me know.
google.visualization.events.addListener(googleChartObj, 'select', function () {
var selectedBar = googleChartObj.getSelection();
////console.log(selectedBar);
data.getRowLabel(selectedBar[0].row);
/// for Bar charts, normally row-parameters are used
/// manipulate on 'data' which refers to data-table to get desired results
});
I have a rather big knockout model and I want to validate all nested models in it:
self.errors = ko.validation.group(self, { deep: true });
Validator found an error:
> self.errors()
["This field is required."]
I don't know which field of my huge model is invalid. How can I find out it?
I guess you should be looking for something like this
// Getting errors
var errors = ko.validation.group(this, {
deep: true,
observable: false
});
// New method: getting extended details
var details = errors.getDetails();
for (var i = 0; i < details.length; i++) {
var d = details[i];
/*
Every element contains the following fields:
"observable" - a reference to the target observable.
"error" - the error message.
"rule" - the name of the failed validation rule.
"data" - an object that contains extension data (provided via "extend" method) for every rule. E.g. "data.required == true".
*/
}
PS: You need to add few lines in your validation file to make getDetails() work i.e which may not be there in validation script file you have .(check reference link & check code)
Reference Here and credits to volpav it helped me long back .
Just incase if someone looking for working sample check here
In jsTree ,How to get Node information by node id ?
I know id of following node i.e 295 then how to get complete node information
<item id="295" parent_id="192" title="itemTitle" version="1">
<content><name>Bhushan Sambhus</name></content>
</item>
above xml part rendered into jsTree is as follows
$("#treeViewDiv").jstree({
"xml_data" : {
"data" : "" +
"<root>" +
"<item id="295" parent_id="192" title="itemTitle" version="1">"+
"<content><name>Bhushan Sambhus</name></content> "+
"</item>"
}
"plugins" : [ "themes", "xml_data","ui" ]
});
Something like following psudo code
function getNodeByNodeID(node_id){
// some code
// $.jstree.get_node ...... etc ?
//
return relatedNodeInformation;
}
var nodeInfo = getNodeByNodeID(providedNodeID) // psudo code
// any api in jstree to get nodeInfo by providedNodeID?
var parent_id_value = nodInfo.attr("parent_id");
var title_value = nodInfo.attr("title");
var version_value = nodInfo.attr("version");
var node_name = nodInfo.children("a").text()
alert(parent_id_value+" :: "+title_value+" :: "+version_value+" :: "+node_name);
Input : 295
Output: 192 :: node_name :: 1 :: node_name
Any help or guidance in this matter would be appreciated
If I'm understanding your question correctly, you can accomplish what you want to do like this:
var nodInfo = $("#" + providedNodeId);
var parent_id_value = nodInfo.attr("parent_id");
var title_value = nodInfo.attr("title");
var version_value = nodInfo.attr("version");
var node_name = nodInfo.children("a").text();
alert(parent_id_value+" :: "+title_value+" :: "+version_value+" :: "+node_name);
Just want to help keep the answer up-to-date. Using jstree 3.1.0, node objects (not DOM objects) are fetched by using this code:
var treeMain; // reference holder
$(document).ready( function () { // when the DOM is ready
treeMain = $('#treeMenus').jstree(); // create the tree and get the reference
});
function getNode( sNodeID)
{
return $.jstree.reference(treeMain).get_node(sNodeID); // use the tree reference to fetch a node
}
I've seen several answers to this question on StackOverflow that all talk about getting back to the DOM object of a tree item. I'm willing to bet that most people asking this question really want to get back to the underlying JSON data object of a tree item, which is why they say they want the node object (which has the .original property). Specifically, you need this for implementing things like "create" functionality where you need to create a new JSON data object with a ParentID that is set to the ID of the parent JSON data object. I searched for 2 days and didn't find anything clear in the jstree documentation that explained this:
$.jstree.reference(treeMain).get_node(sNodeID);
simple call. In their defense, they do have a 1 line example buried in here:
http://www.jstree.com/docs/interaction/
but it's an example most people won't care about (the user will be selecting nodes most of the time), and certainly not clear for what it is actually capable of doing. Anyways... hope this is helps save someone else a couple of days. =)