Accent insensitive searching in RadComboBox - asp.net

I'm relatively new to using ASP webforms and Telerik, but I'm looking for a way that allows me to type special characters (é, ù, à, ...) in a RadComboBox.
Lets say I have a name in my ObjectDataSource called "René Somebody". I need to be able to find him by searching for "Rene" and "René", but so far no luck.
In the application they managed to do this on a RadGrid with filters, but this same solution doesn't work for the RadComboBox as far as I know.
The solution they used in the RadGrid: http://www.telerik.com/forums/accent-insensitive-filtering-filtering-on-a-different-column#YS1QT8P1U0-cRPFNfjvDzA

I have no access to the backend components but the demo you linked contains frontend code and it looks like you can hack in there. It looks like this control may be both client-server and client-side only. For client-side only hacks looks kind of complicated and invloves non-public API (_onInputChange) but for client-server case (which is probably your case) the doc on client side of RadComboBox Object mentions requestItems method so hacking it is probably reasonably future safe:
var hackRadComboBoxFilter = function (combobox, filterProcessingFunction) {
var oldRequestItems = combobox.requestItems;
combobox.requestItems = function() {
var args = Array.prototype.slice.call(arguments);
// requestItems has several arguments but the text seems to be the
// first one, so let's modify it and call the original method
var origFilter = args[0];
args[0] = filterProcessingFunction(origFilter);
oldRequestItems.apply(this, args);
}
};
Unfortunately I don't know a built-in way to deal with accents in JS but you can hack something simple here as well:
var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
var mappedAccents = "AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZz";
var removeAccents = function (origStr) {
var components = [];
var len = origStr.length;
var afterLastAccent = 0;
for (var i = 0; i < len; i++) {
var mapPos = accents.indexOf(origStr[i]);
if (mapPos != -1) {
components.push(origStr.substr(afterLastAccent, i - afterLastAccent) + mappedAccents[mapPos]);
afterLastAccent = i + 1;
}
}
if (afterLastAccent < len)
components.push(origStr.substr(afterLastAccent, len - afterLastAccent));
return components.join('');
};
So now you can combine it in something like this:
// In real app you probably want something like this
// var targetComboBox = $find("<%= RadComboBox1.ClientID %>");
// but for test let's just hack first combobox on the page
var targetComboBox = Telerik.Web.UI.RadComboBox.ComboBoxes[0];
hackRadComboBoxFilter(targetComboBox, removeAccents);
or if you want to modify all the comboboxes on the page, you can change prototype using the same trick:
hackRadComboBoxFilter(Telerik.Web.UI.RadComboBox.prototype, removeAccents)

Related

Somebody know best way how to controll Meteor.methods result from client-Side

I just wonder about Meteor.methods result stub. When i used Meteor.call, i tried handle result set but when result set out of range from Meteor.call area that return undefined. So I think if i use Session it can be solve. but sometime that way isn't work. So, if you guys, have you know best way to controll that topic, let me know your solutions!!
Thank you for comment, but I can't split up my logic. Because i want take javaScript library module from our old project-code. It had handle front-end of jQuery by html context for iframe. FirstTime, i tried figured out by use just iframe tag. but it had made issue for cross-domain. So i tried found solution about cross-domain on Meteor, but anywhere no solution. Therefore, i thinking how to solve it that issue and then i decided used Meteor.http! That was successed tool html.content from server-side and inside block of the callback function from client-side. but i can't hand over result out of callback function. i should give result of methods(iframe html content) to our old javascript-code... that's why i try that way! Any idea about this? i include javascript-code, it will help understanding.
...
drawSvg2: function(){
var objIFrame = $("#iFrame_"+m.canvasIdx()).contents();
var objList = objIFrame.find('.page');
var len = objList.length;
for (i=0; i<len; i++){
var obj = objList[i];
var children = obj.children; //childNodes;
var num = 0;
for (var k = 0; k < children.length; k++) {
var children2 = children[k].children;
for (var j = 0; j < children2.length; j++) {
if(children2[j].children[0].nodeName == "P"){
m.textArray(num, new Object());
c.canvasFetch(children[k], children2[j], "", m.textArray()[num], num);
}else{
m.textArray(num, new Object());
c.canvasFetch(children[k], children2[j], children2[j].children[0], m.textArray()[num], num);
}
num++;
}
}
}
v.drawSvg3();
},
...
That is huge function and handled front-end by jQuery, So i can't put inside Meteor.methods..
The way to use Meteor.call:
Meteor.call('methodName', param1Value, param2Value,..., function (error, result) { ... } );
The last parameter is a callback. Meteor invokes this callback function when the result is ready. Inside the body of the callback function, you can do whatever you want with the result. Why do you need to return this result to the calling function? Can you split up the logic so that it invoke Meteor.call, and handle the rest inside the callback?

Method/property does not exist

I'm trying to convert the JavaScript code
if (window.ifEdit.editIsDirty()) { }
into Typescript. I got as far as the following
var iframe = document.getElementById('ifEdit');
var iWindow = <HTMLIFrameElement>(iframe).contentWindow;
var _editIsDirty = iWindow.editIsDirty();
I get the red squiggles under 'contentWindow' and 'editIsDirty' saying the method/property does not exist on the type. The .ts doesn't compile to a .js file.
I have searched, but did not manage to find a solution.
For the contentWindow part, the problem with your code is that the casting is done wrong, should be:
var iWindow = (<HTMLIFrameElement> iframe).contentWindow;
As for the editIsDirty, it's not a standard property of Window.
If it's something which is added in the environment in which you are running your javascript then you need to declare it like so:
interface IfEdit {
editIsDirty(): boolean;
}
interface Window {
ifEdit: IfEdit;
}
var iframe = document.getElementById("ifEdit");
var iWindow = (<HTMLIFrameElement> iframe).contentWindow;
var _editIsDirty = iWindow.ifEdit.editIsDirty();
Use the code in Playground.
Casting will be through as. this assures .contentWindow is accessible.
const iframe = document.getElementById('embed-player') as HTMLIFrameElement;
if (!iframe) {
// Handle case where iframe not found
return;
}
const contentWindow = iframe.contentWindow;
// Note: You will likely need more null handling for contentWindow's properties
console.log(contentWindow?.document);

Select option value - selectedchoice is not working

I am binding a SELECT HTML tag with some dynamic values using knockout JS. Additionally, i am trying to set a selected choice which is failing. Please suggest where i am going wrong.
self.level1Choices.selectedChoice = ko.observable(2); - this line does not seem to work.
The JSFiddle for this code is at http://jsfiddle.net/oarp7gwj/7/
The dropdown is not loading in the JSFiddle for some reason. I dont think i have referenced the knockout JS correctly. In my local environment, I am able to load the select box with the values. However, i am not able to set the selected value.
#Wayne Ellery, #QBM5 - please advise since you know about this already :)
You should use var to declare your model object to avoid scoping issues
var viewModel = new DataModel();
The main issue was you need to add to the Datamodel by exposing it through the this variable in the Datamodel.
var DataModel = function (client) {
var self = this;
self.level1Choices = ko.observableArray();
};
Take a look at the Helo World example as to how to do this:
http://knockoutjs.com/examples/helloWorld.html
I've scoped this to self as it's a best practice to not worry about this referring to something else mentioned here: http://knockoutjs.com/documentation/computedObservables.html.
I moved the loadAllApprovers method inside the DataModel as this is where it belongs and so that it has access to populate the datamodel.
I added the mobile services client to the constructor so that it can be mocked for testing your model.
var DataModel = function (client) {
var self = this;
self.level1Choices = ko.observableArray();
var loadAllApprovers = function () {
var allAppprovers = client.getTable('TABLE');
var query = allAppprovers.select("ID", "FirstName").read().done(function (approverResults) {
self.level1Choices(approverResults);
}, function (err) {
console.log("Error: " + err);
});
};
loadAllApprovers();
};
You were also missing knockout in your jsfiddle.
http://jsfiddle.net/az4rox0q/6/

embedding sources dynamically

is it possible to embed sources dynamically. instead of doing this
[Embed(source = '../../../../assets/levels/test.xml')]
I could probably do something like this
var src = '../../../../assets/levels/test.xml'
[Embed(source = src )]
It's not possible for anything within metadata annotations to be dynamic :/. That is, you can't place variables into metadata annotations. If that was possible, there would be SO many cool possibilities. So your first option is the only way to directly embed xml.
You could, however, write a custom metadata parser that figured out how to load (not embed) your xml file. Something like:
[LoadFile]
public var source:String = "../../../../assets/levels/test.xml";
I would implement that like the code below (just wrote this right now, haven't tested it). And then you'd "process" your class via something like MyMetadataUtil.process(this). Lots of ways to do that.
public function extractMetadata(target:Object):void
{
var description:XML = flash.utils.describeType(target);
var tag:String = "LoadFile"
var metadata:XMLList = description.accessor.metadata.(#name == tag);
metadata += description.variable.metadata.(#name == tag);
var i:int = 0;
var n:int = metadata.length();
// usually called a 'directive'
// holds values from metadata annotation
var token:Object = {};
for (i; i < n; i++)
{
metadataXML = metadata[i];
token.property = metadataXML.parent().#name;
// token.source = myClass.source;
token.source = target[token.property];
var request:URLRequest = new URLRequest(token.source);
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, loader_completeHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, loader_ioErrorHandler);
loader.load(request);
}
}
protected function loader_completeHandler(event:Event):void
{
event.currentTarget.removeEventListener(event.type, loader_completeHandler);
trace("SUCCESSFULLY LOADED FILE!");
}
protected function loader_ioErrorHandler(event:Event):void
{
event.currentTarget.removeEventListener(event.type, loader_ioErrorHandler);
}
That stuff would go into some util/manager/processor class. Then anywhere in your code, you could use this:
[LoadFile]
public var source:String = "myFile.xml";
And that could be dynamic. Check out the Swiz Framework for some example source code on how to implement custom metadata processors. Or even better, Openflux's MetaUtil. Once you set that up once, you can do some hardcore stuff in your code. Makes coding fun and fast.
Hope that helps,
Lance
Your use case is basically why I created the ability to add extra frames to Flex SWFs that are treated as late-loaded modules. Instead of embedding your level, stream it in after the main application.
Documentation on -frame is sparse. Sorry! Here's some external stuff, that links back to stuff I wrote and Alex Harui wrote. Good luck!
http://www.richinternet.de/blog/index.cfm?entry=FF295F89-DAD8-CCDC-960413842BC0D478

Get item by index in a tree control

I'm doing a drag and drop operation on a tree using some help from Adobe's quick Starts:
http://www.adobe.com/devnet/flex/quickstart/working_with_tree/
The code suggested is roughly this:
var dropTarget:Tree = Tree(evt.currentTarget);
var i:int = dropTarget.calculateDropIndex(evt);
myTree.selectedIndex = i;
var node:XML = myTree.selectedItem as XML;
var drugXML:XML = XML(Tree(evt.dragInitiator).selectedItem);
if(node.localName() != drugXML.localName()){
DragManager.showFeedback(DragManager.NONE);
return;
}else{
DragManager.showFeedback(DragManager.COPY);
}
This is all well and good, but I don't like the way it is selecting(highlighting) each item in the tree I'm dropping on, it's less clear where the item is going to drop. I want to implement this without the selection but there doesn't seem to be a way to get the XML of the node using just the index. I would like something like this:
var dropTarget:Tree = Tree(evt.currentTarget);
var i:int = dropTarget.calculateDropIndex(evt);
var node:XML = myTree.itemAt(i) as XML;
//AFAIK itemAt(i) or anything like it does not exist
var drugXML:XML = XML(Tree(evt.dragInitiator).selectedItem);
if(node.localName() != drugXML.localName()){
DragManager.showFeedback(DragManager.NONE);
return;
}else{
DragManager.showFeedback(DragManager.COPY);
}
So does anyone know what function is, or what I can do to extend the tree to have a function, like "itemAt(i)"
Thanks
~Mike
EDIT: I forgot to post that my current workaround is setting the selectedIndex = -1 after I get my node:XML. I'm afraid that if something bogs on the processor the user may see it select then deselect.
Much simpler, though there may be gotchas:
var index:int = ...
var renderer:IListItemRenderer = tree.indexToItemRenderer(index);
var item:Object = renderer.data;
This won't work if the index is offscreen (since there might not be an active itemRenderer); shouldn't be an issue for drag and drop.
If your dataProvider is explicitly or implicitly a collection (see the linked docs for conversion rules), you should be able to use getItemAt to resolve the index.
It appears that an XML provider will be converted implicitly:
var tree:Tree = ...;
var data:XML = ...;
tree.dataProvider = data; // could just as well be from MXML
var provider:ICollectionView = tree.collection; // tree converted it for us
trace(provider.getItemAt(index));
If you have something other than the convertible types (XML, Array, etc.), you might consider wrapping your dataProvider in an XMLListCollection or what have you to gain access to that method.
The above is aiming in the right direction but missing.
Turns out you don't want the dataProvider since Tree overrides that; you want the collection property (protected). So you could override Tree and provide an indexToItem method to go with the thisToThat methods already present in Tree.

Resources