Sencha Touch - List with Search-Field (XMLStore) - list

I have a external XML-file which I use to filling my list. This works great.
But now I want to filter(search) the XML-data with a search-field on top of the list.
My List looks like this:
ToolbarDemo.views.Beitrage = Ext.extend(Ext.List, {
title: "Beiträge",
iconCls: "btnbeitraege",
id: 'disclosurelist',
store: storeXML,
itemTpl: '<div class="contact"><img src="{bild}" width="96" height="52" border="0"/> {titel}</div>',
grouped: true,
onItemDisclosure: function(record, btn, index) {
Ext.Msg.alert('', '<video width="200" height="200" x-webkit-airplay="allow" poster="'+ record.get('bild') +'" controls="controls" id="video_player" style="" tabindex="0"><source src="'+ record.get('video') +'"></source></video>', Ext.emptyFn);
} });storeXML.load();
And my XML-input looks like this:
Ext.regModel('beitrag', {fields: ['datum', 'titel', 'video', 'bild']});
var storeXML = new Ext.data.Store({
model: 'beitrag',
sorters: [
{
property : 'Datum',
direction: 'DESC'
}],
getGroupString : function(record) {
var month = record.get('datum').split('-');
return month[2] + '.' + month[1] + '.' + month[0];
},
method: 'GET',
proxy: {
url: 'beitraege.xml',
type: 'ajax',
reader: {
type: 'xml',
record: 'beitrag',
root: 'beitraege'
},
}});

I know it's an old question, but I have managed to filter my list using a filter function in it's store. Here is how I did:
In my view I have a text field (xtype: 'searchfield').
In the controller for this view I have registered for 2 events by using the 'control' property
control: {
'searchfield': {
clearicontap: 'onSearchClearIconTap',
keyup: 'onSearchKeyUp'
}
}
onSearchKeyUp function looks like this (note: the field I'm going to filter is 'docName')
onSearchKeyUp: function(field)
{
var value = field.getValue(),
store = this.getMaster().getStore();
store.clearFilter();
if (value)
{
var searches = value.split(' '),
regexps = [],
i;
for (i = 0; i < searches.length; i++)
{
//if it is nothing, continue
if (!searches[i]) continue;
//if found, create a new regular expression which is case insenstive
regexps.push(new RegExp(searches[i], 'i'));
}
store.filter(function(record)
{
var matched = [];
//loop through each of the regular expressions
for (i = 0; i < regexps.length; i++)
{
var search = regexps[i],
didMatch = record.get('docName').match(search);
//if it matched the first or last name, push it into the matches array
matched.push(didMatch);
} //if nothing was found, return false (dont so in the store)
if (regexps.length > 1 && matched.indexOf(false) != -1) {
return false;
} else {
//else true true (show in the store)
return matched[0];
}
});
}
}
The 'onSearchClearIconTap' function instead is called when the user taps on the clear icon that is the 'X' included in the searchfield component, that clears the text, so the only thing we want to do is to reset the filter for our list:
onSearchClearIconTap: function()
{
this.getMaster().getStore().clearFilter();
}

Related

Duplicate existing contacts alert

In Vtiger 6.5.0 open source, I wants to create a alert function to warn users that the conact's mobile is existing? could you please help me. I'm fresher.
Thanks,
Loi
You can refer the function wich exist in Account module for checking Duplicate Account Name.
Please follow this files you will get an idea.
This is the code flow how its done In Account Module
Registring Pre Save Event
http://code.vtiger.com/vtiger/vtigercrm/blob/master/layouts/vlayout/modules/Accounts/resources/Edit.js#L250
This teh Fucntion to check Duplicate in cache, If not calls the Helper function
http://code.vtiger.com/vtiger/vtigercrm/blob/master/layouts/vlayout/modules/Accounts/resources/Edit.js#L83
This the Helper function which makes the call to server
http://code.vtiger.com/vtiger/vtigercrm/blob/master/resources/helper.js#L166
This is the action function which is responsible for Serving the request which came from Helper Function
http://code.vtiger.com/vtiger/vtigercrm/blob/master/modules/Accounts/actions/CheckDuplicate.php#L30
And this is the function which checks for Duplicate
http://code.vtiger.com/vtiger/vtigercrm/blob/master/modules/Accounts/models/Record.php#L57
Hope this helps.
Hi Victor please follow this steps
modules\Leads\actions\Checkprimaryemail.php
<?php
class Leads_Checkprimaryemail_Action extends Vtiger_BasicAjax_Action {
public function checkPermission(Vtiger_Request $request) {
return;
}
public function process(Vtiger_Request $request) {
global $adb;
$moduleName = $request->get('module');
$recordId = $request->get('recordId');
$primary_email = $request->get('primary_email');
/*Lead Details*/
$lead_query = "select * from vtiger_leaddetails
inner join vtiger_crmentity on vtiger_crmentity.crmid=vtiger_leaddetails.leadid
where vtiger_crmentity.deleted = 0 and vtiger_leaddetails.email='".$primary_email."'";
$lead_result = $adb->query($lead_query);
$lead_email = $adb->query_result($lead_result,0,'email');
$lead_numrows = $adb->num_rows($lead_result);
/*Contact Details*/
$cont_query = "select * from vtiger_contactdetails
inner join vtiger_crmentity on vtiger_crmentity.crmid=vtiger_contactdetails.contactid
where vtiger_crmentity.deleted = 0 and vtiger_contactdetails.email='".$primary_email."'";
$cont_result = $adb->query($cont_query);
$cont_email = $adb->query_result($cont_result,0,'email');
$cont_numrows = $adb->num_rows($cont_result);
if($recordId != '' ){
if($primary_email == $lead_email && $lead_numrows == 1 ){
$emailtrue = 0;
} elseif($primary_email == $cont_email && $cont_numrows >= 1 ) {
$emailtrue = 1;
}
} else {
if(($lead_numrows >=1 || $cont_numrows >=1 ) || ($lead_numrows >=1 && $cont_numrows >= 1) ){
$emailtrue = 1;
} else {
$emailtrue = 0;
}
}
$emailData = array($emailtrue);
$response = new Vtiger_Response();
$response->setResult($emailData);
$response->emit();
}
}
?>
After Create One other file
layouts\vlayout\modules\Leads\resources\Edit.js
Vtiger_Edit_Js("Leads_Edit_Js", {
}, {
changeEvent: function (container) {
jQuery('input[name="email"]').on('focusout', function (e) {
var email = jQuery('input[name="email"]').val();
var recordId = jQuery('input[name="record"]').val();
var email_length = email.length;
if (email != '') {
if (email_length > 100) {
var errorMessage = app.vtranslate('JS_EMAIL_LENGTH_VALIDATION');
params = {
text: errorMessage,
'type': 'error',
};
Vtiger_Helper_Js.showMessage(params);
}
var progressIndicatorElement = jQuery.progressIndicator({
'position': 'html',
'blockInfo': {
'enabled': true
}
});
var postData = {
"module": 'Leads',
"action": "Checkprimaryemail",
"primary_email": email,
"recordId": recordId
}
AppConnector.request(postData).then(
function (data) {
progressIndicatorElement.progressIndicator({'mode': 'hide'});
if (data['result'] == 1) {
jQuery('#emailalready_exists').val(1);
var errorMessage = app.vtranslate('JS_EMAIL_EXIST');
params = {
text: errorMessage,
'type': 'error',
};
Vtiger_Helper_Js.showMessage(params);
} else {
jQuery('#emailalready_exists').val(0);
}
},
function (error, err) {}
);
e.preventDefault();
}
});
},
registerBasicEvents: function (container) {
this._super(container);
this.changeEvent(container);
}
});
To check duplicate records in vTiger follow below steps:
Register checkDuplicate function in registerBasicEvents
1: \layouts\vlayout\modules\Contacts\resources\Edit.js
getmobile : function(container){
return jQuery('input[name="mobile"]',container).val();
},
getRecordId : function(container){
return jQuery('input[name="record"]',container).val();
},
DuplicateCheck : function(form) {
var thisInstance = this;
if(typeof form == 'undefined') {
form = this.getForm();
}
jQuery( "#mobileFieldId" ).change(function() {
var mobile = thisInstance.getmobile(form);
var recordId = thisInstance.getRecordId(form);
var params = {
'module' : "Contacts",
'action' : "CheckDuplicate",
'mobile' : mobile,
'record' : recordId
}
AppConnector.request(params).then(
function(data) {
var response = data['result'];
var result = response['success'];
if(result == true) {
var message_params = {
title : app.vtranslate('JS_MESSAGE'),
text: response['message'],
animation: 'show',
type: 'error'
};
Vtiger_Helper_Js.showPnotify(message_params);
jQuery(".btn-success").attr('disabled',true);
return false;
} else {
jQuery(".btn-success").attr('disabled',false);
}
}
);
});
},
2: Create new file in** \modules\Contacts\actions\CheckDuplicate.php
Follow the same process / code as given in \modules\Accounts\actions\CheckDuplicate.php
3: Add new function checkDuplicate() in \modules\Contacts\models\Record.php
And follow same process as given in \modules\Accounts\models\Record.php having function checkDuplicate()
Note: Don't forget to change the db table name, class name module wise.
Hope this will help you. Thank you.

How to search each document field individually for specific value?

I have a search bar so that when the user presses enter, the string in the search bar is sent to my ExpressJS server. The server then needs to look through every document in the MongoDB; a document is found if any of its fields matches what was in the search bar.
My current code technically works, but it seems very redundant and probably very inefficient. I use the find() method on each field, saving the matches in an array. After searching each field individually, I prune the array of found matches, removing any duplicates.
Is there a better way to do this? See my current code below:
router.get('/', function(req, res) {
var regSearch = new RegExp('.*'+searchdata+'.*', 'i'); //Create regular expression of search data -> (text in search bar)
var arr = [];
InventoryObject.find({productId: {$regex: regSearch}}).limit(100).exec(function (err, data) { //Get all docs with a matching productId
InventoryObject.find({scannerIn: {$regex: regSearch}}).limit(100).exec(function (err, data1) { //Get all docs with a matching scannerIn
InventoryObject.find({scannerOut: {$regex: regSearch}}).limit(100).exec(function (err, data2) { //Get all docs with a matching scannerOut....
InventoryObject.find({dateIn: {$regex: regSearch}}).limit(100).exec(function (err, data3) {
InventoryObject.find({dateOut: {$regex: regSearch}}).limit(100).exec(function (err, data4) {
InventoryObject.find({productName: {$regex: regSearch}}).limit(100).exec(function (err, data5) {
InventoryObject.find({purchaseOrder: {$regex: regSearch}}).limit(100).exec(function (err, data6) {
InventoryObject.find({productDestination: {$regex: regSearch}}).limit(100).exec(function (err, data7) {
InventoryObject.find({productCost: parseFloat(searchdata)}).limit(100).exec(function (err, data8) {
//Concatenate all matched documents into single array
arr = arr.concat(data, data1, data2, data3, data4, data5, data6, data7, data8);
//Remove undefined last element...
arr.splice(arr.length-1, 1);
//Iterate through array and remove any documents that are duplicates
for (var i = 0; i < arr.length; i++) {
for (var j = i+1; j < arr.length; j++) {
if (arr[i]._id.toString() === arr[j]._id.toString()) {
arr.splice(j, 1);
j--;
}
}
}
//Sort the documents by their _id property
arr.sort(function (a, b) {
if (a._id < b._id) return +1;
if (a._id > b._id) return -1;
return 0;
});
//If the array is longer than 100, truncate it.
if (arr.length > 100)
arr.length = 100; //truncate to 100 elements sorted by the order they were inputted
//console.log(arr);
res.render('index', {'inventoryObjects': arr});
searchdata = ''; //Clear search data
});
});
});
});
});
});
});
});
});
});
Here is my Schema for reference:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var InventoryObject = new Schema({
productId: String,
scannerIn: String,
scannerOut: String,
dateIn: String,
dateOut: String,
productName: String,
purchaseOrder: String,
productDestination: String,
productCost: Number
});
mongoose.model('InventoryObject', InventoryObject);
Unfortunately that's not possible in current Mongo DB versions.
You should optimise your query like this:
InventoryObject.find({
$or:[
{productId: {$regex: regSearch}},
{scannerIn: {$regex: regSearch}},
...
]
});
But if you really need to optimise speed of such queries, you should change your schema to something like:
{
attributes: [
{key: 'productId', value: 'product ID'},
{key: 'scannerId', value: 'scanner ID'},
...
]
}

ArrayComputed: Groupby and computed properties not resolved from promises

I have a group model that contains some bets from several user. Every user can have more than one bet. In order to display the end result I want to group the bets by user and then sum up the points. this is my bet model that contains the point logic:
App.GameBet = DS.Model.extend({
scoreT1: DS.attr(),
scoreT2: DS.attr(),
betRound: DS.belongsTo('betround'),
game: DS.belongsTo('game', {async:true}),
user: DS.belongsTo('user', {async:true}),
points: function(){
var game = this.get('game');
var sc1 = this.get('game.scoreT1');
var sc2 = this.get('game.scoreT2');
var b1 = this.get('scoreT1');
var b2 = this.get('scoreT2');
if(sc1 == b1 && sc2 == b2) {
return 7;
} else if ((sc1 - sc2) == (b1 - b2)) {
return 5;
// Exakte Punktzahl
} else if ((sc1 - sc2) * (b1 - b2) > 0) {
return 3;
// Tendenz
} else {
return 0;
}
}.property('scoreT1', 'scoreT2', 'game.scoreT1', 'game.scoreT2')
});
This is working perfectly fine when I just render all bets with their points. But when I am using my own groupby ArrayComputeed function, it isn't working:
App.betGroupBy = function (dependentKey) {
var options = {
initialValue: Ember.A([]),
initialize: function (array, changeMeta, instanceMeta) {
return instanceMeta.previousKeys = {};
},
addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
console.log(item.get('id') + " " + item.get('points'));
var user = item.get('user');
var key = user.get('id');
var group = accumulatedValue.findBy('key', key);
if (!group) {
group = Ember.Object.create({
key: key,
user: user,
bets: Ember.A([]),
betPoints: Ember.computed.mapBy('bets', 'points'),
points: Ember.computed.sum('betPoints')
});
accumulatedValue.pushObject(group);
}
group.get('bets').pushObject(item);
instanceMeta.previousKeys[Ember.guidFor(item)] = key;
return accumulatedValue;
},
removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
var key = item.get(property);
var group = accumulatedValue.findBy('key', key);
if (!group) {
return;
}
var userBets = group.get('bets');
userBets.removeObject(item);
if (userBets.length === 0) {
accumulatedValue.removeObject(group);
}
return accumulatedValue;
}
};
return Ember.arrayComputed(dependentKey, options);
};
Somehow my "points" in the grouped function are always zero.
It seems that the promises are not early enough resolved or something.

EXTJS grid store load - adding parameters?

I'm in the process on converting an asp repeater into an EXTJS grid. Above the repeater is a dropdown and a radiobutton list. The dropdown selects which clients' data the repeater shows, and the radiobuttonlist selects the query type (default, resource, or role). Currently, when the ddl or radiobutton is changed, the page postsback with the new data.
I'm not sure how to pass the value of these two objects into my static webservice on the backend via the extjs store api GET call.
The extjs store code...
store: Ext.create('Ext.data.Store', {
autoLoad: true,
autoSync: false,
model: 'Assembly',
proxy: {
type: 'ajax',
headers: { "Content-Type": 'application/json' },
api: {
read: '/Admin/BillRateData.aspx/Get'
},
reader: {
type: 'json',
root: function (o) {
if (o.d) {
return o.d;
} else {
return o.children;
}
}
},
writer: {
type: 'json',
root: 'jsonData',
encode: false,
allowSingle: false
},
listeners: {
exception: function (proxy, response, operation) {
Ext.MessageBox.show({
title: "Workflow Groups Error",
msg: operation.action + ' Operation Failed: ' + operation.getError().statusText,
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
And the webservice...(with some psuedocode)
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public static List<BillRate> Get()
{
using (TimEntities db = new TimEntities())
{
int tableId = Int32.Parse(ddlTable.SelectedValue);
var defaultQry = from t1 in db.BillCostTableDatas
where t1.TableId == tableId
&& t1.ResourceId == 0 && t1.RoleId == 0
orderby t1.Rate
select new
{
id = t1.Id,
resource = "",
role = "",
rate = t1.Rate,
TierName = ""
};
var resourceQry = from t1 in db.BillCostTableDatas
join t2 in db.Machines on t1.ResourceId equals t2.Machine_ID
join t3 in db.TOMIS_USER on t2.Machine_User_ID equals t3.User_ID
join t4 in db.PricingTierNames on t1.PricingTierID equals t4.TierID
where t1.TableId == tableId
&& t1.ResourceId != 0
&& t1.RoleId == 0
orderby t3.LName, t3.FName, t1.Rate, t4.TierName
select new
{
id = t1.Id,
resource = t3.LName + ", " + t3.FName,
role = "",
rate = t1.Rate,
TierName = t4.TierName
};
var roleQry = from t1 in db.BillCostTableDatas
join t2 in db.TaskRoles on t1.RoleId equals t2.Id
where t1.TableId == tableId
&& t1.ResourceId == 2 && t1.RoleId != 0
orderby t2.Name, t1.Rate
select new
{
id = t1.Id,
resource = "",
role = t2.Name,
rate = t1.Rate,
TierName = ""
};
if (this.rblOptions.SelectedValue == "resource")
{
var results = from Res in resourceQry.ToList()
select new BillRate
{
};
return results.ToList();
}
else if (this.rblOptions.SelectedValue == "role")
{
var results = from Res in roleQry.ToList()
select new BillRate
{
};
return results.ToList();
}
else
{
var results = from Res in defaultQry.ToList()
select new BillRate
{
};
return results.ToList();
}
return null;
}
}
If you trigger your store loading manually, you can pass the params options to the load method.
Example:
var store = Ext.create('Ext.data.Store', {
// prevent the store from loading before we told it to do so
autoLoad: false
...
});
store.load({
params: {clientId: 123, queryType: 'default'}
...
});
If you want the params to be sent for multiple subsequent queries, you can write them in the extraParams property of the proxy.
Example:
var store = Ext.create('Ext.data.Store', { ... });
Ext.apply(store.getProxy().extraParams, {
clientId: 321
,queryType: 'role'
});
// the store will still need a refresh
store.reload();
The way these params are passed to the server will depend on the type of request. For GET ones, they will be appended as query params; for POST they will be embedded in the request body.

jQuery DatePicker calendar not returning correct month

I am soooo close here. I'm hoping a guru can help me with this last piece. I'm populating a jQuery DatePicker calendar with XML from an RSS feed. Upon clicking a highlighted date where there's an event, I'm creating a URL with a query string so I can display all the event for the clicked day. Everything is working... until I change the month by clicking previous or next month. My script will return the correct day, but is only returning the current month. For example, I navigate to May and click the 5th, my URL will be events.htm?month=june&day=5. Any ideas on why it will not return my selected month? Here's my code:
var data = $.ajax({
url: "news.xml",
type: "GET",
dataType: "xml",
async:false,
success: function(xml){
return xml;
}
} ).responseText;
$(document).ready(function() {
var events = getSelectedDates();
$("div.datepicker").datepicker({
beforeShowDay: function(date) {
var result = [true, '', null];
var matching = $.grep(events, function(event) {
return event.published.getDate() === date.getDate() && event.published.getMonth() === date.getMonth() && event.published.getFullYear() === date.getFullYear();
});
if (matching.length) {
result = [true, 'highlight', null];
}
return result;
},
onSelect: function(dateText) {
var date, selectedDate = new Date(dateText),
i = 0,
event = null;
while (i < events.length && !event) {
date = events[i].published;
if (selectedDate.getFullYear() === date.getFullYear() &&
selectedDate.getMonth() === date.getMonth() &&
selectedDate.getDate() === date.getDate()) {
event = events[i];
}
i++;
}
if (event) {
var eMonNum = event.published.getMonth();
var d = new Date();
var eMonNum = new Array();
eMonNum[0] = "january";
eMonNum[1] = "february";
eMonNum[2] = "march";
eMonNum[3] = "april";
eMonNum[4] = "may";
eMonNum[5] = "june";
eMonNum[6] = "july";
eMonNum[7] = "august";
eMonNum[8] = "september";
eMonNum[9] = "october";
eMonNum[10] = "november";
eMonNum[11] = "december";
var eMon = eMonNum[d.getMonth()];
var eDay = event.published.getDate();
window.location = "events.htm?month="+eMon+"&day="+eDay;
}
}
});
});
function getSelectedDates() {
return $(data).find('entry').map(function() {
return {
title: $('title', this).text(),
published: new Date($('published', this).text())
};
}).get();
}
Found the problem, when you copied this list from a resource, you forgot to replace the variables.
CHANGE (at the end of month list)
var eMon = eMonNum[d.getMonth()];
TO:
var eMon = eMonNum[event.published.getMonth()];
All I did was get rid of the bad variable and reassigned your month variable to the one you used for the day. You can also remove the declaration of the d variable, as you will not need it.
Best of luck!