PDA

View Full Version : Ext.ux.form.SuperBoxSelect as seen on facebook and hotmail



Pages : [1] 2

danh2000
20 May 2009, 10:46 PM
Hi All,

UPDATE 18/01/2010

Fixed regression where disabling the component didn't properly disable the items.

UPDATE 16/01/2010 (Part 2)

Fixed to prevent extra empty hiddenName value from being posted.

@frederickd - I'd forgotten about this one until I saw you on the forum ;)

UPDATE 16/01/2010

Fixed bug when setting disabled in config.
Updated CSS to remove gray background from input when component is disabled.

UPDATE 15/01/2010 (part 2)

Fix to disable item listeners when component is disabled.

UPDATE 15/01/2010

Fixed regression that made transforming an HTML Select incompatible with Ext 2.x
Fixed issue with setValue being used prior to rendering.
Fix to prevent passing null to setValue from causing problems.
Fixed inconsistency regarding forceFormValue config and form submits.
Fix to prevent component submitting values when disabled.
Fix to ensure that minChars does not affect a values query.


UPDATE 29/12/2009

Fixed IE8 Quirks Mode issue when transforming a HTML Select.
Fixed typo

UPDATE 29/12/2009

Fix to replace removed store records when component is destroyed.

UPDATE 28/12/2009

Fixed a silly typo which prevented setValue working with a remote store.

UPDATE 27/12/2009

Additional fix to destroy process.
Implemented addNewItem method to fix issue raised in post #242

NOTE Anybody using this component with the allowAddNewData config and a remote store is advised to use the new addNewItem method within their newitem event listeners.

For a demo, see the remote example here:

http://www.technomedia.co.uk/SuperBoxSelect/examplesRemote.html


UPDATE 26/12/2009

Fixed queryValuesIndicator typo.
Fix to ensure that blurring component behaves consistently (removing typed chars).
Fix to onResize to ensure all elements have been renderred.
Fix to unset preventMultipleRemoveEvents after all items have been removed.
Fix to normalize string in setValue method.
Fix to add a missing ;
Fixes to reset and destroy processes.
Implemented itemDelimiterKey config.
Implemented beforeselect event.


UPDATE 21/10/2009

Fix to prevent the component receiving focus when reset is called.
Removed unnecessary usage of trim.
Fixed bug in setValueEx method.
Added a new forceFormValue config to force form values (submission or BasicForm.getValues) even when no items selected

UPDATE 27/09/2009

Fix to prevent submission of empty value when doing a raw form submit.
Fix for IE8 error during transform.
Inclusion of superboxselect-gray-extend.css from the extended gray theme (https://www.extjs.com/forum/showthread.php?t=65694) (Thanks Galdaka (http://www.extjs.com/forum/member.php?u=101))

UPDATE 24/09/2009

Fix to work around Ext 3.0.0 bug - store load event not providing params to callback.
Fix to allow store to be provided as an xtype.
Fix to clean up after prevention of 'remove' events during clearValue.

UPDATE 22/09/2009

Added 'clear' event.
Added a 'record' param to the addItem and removeItem events.
Added 'supressClearValueRemoveEvents' config.
Added fix to escape internal regexp.
Added new 'supressEvents' param to clearValue method.
Removed docs for removeAllItems method - clearValue should be used instead.
Added addItems method.
Fixed scope issue in getValueEx method.
Fix to provide an originalValue (and fix reset) when remote store used.


UPDATE 07/09/2009

*NEW* Remote compatability - you are no longer limited to a local store!
Multiple bug fixes (many browser version specific).

UPDATE 03/09/2009

A few minor bug fixes and a maintenance release to make compatible with Ext 3.0.1

UPDATE 15/07/2009

Fixed a couple of bugs that occured when using setValue when the component had not been rendered (eg. hidden tab).
Enabled setValue to accept either an array of values or a delimited string.

UPDATE 28/06/2009

Fixed IE6 display issue with applyTo and transform.
Fixed a couple of dodgy non var'd variables.
Increased 'close button' target size and changed cursor to pointer.

UPDATE 27/06/2009

New Fully Supported Combo Features:
- Ability to applyTo an existing element.
- Ability to transform an existing HTML Select.

Bug Fixes and Code Tidy Up (A big contribution from Mystix - Many Thanks).

The attachment has been updated as have the example pages linked below.



There is already a similar component on this forum (http://extjs.com/forum/showthread.php?t=33794), but as development seems to have stopped, I was asked to create a component like this one which fixes the errors and adds some additional functionality.

I've put a first demo of the component here:

Ext 2 Example:

http://technomedia.co.uk/SuperBoxSelect/examples.html

Ext 3 Example:
http://technomedia.co.uk/SuperBoxSelect/examples3.html

Ext 3 Extended Gray Theme Example:
http://www.technomedia.co.uk/SuperBoxSelect/examples3gray.html

Remote Store Example:
http://technomedia.co.uk/SuperBoxSelect/examplesRemote.html

Download
18327

It's still in beta so there is some refactoring to do and I may make changes to the api methods and properties, but the functionality is pretty much all there.

Please try it out and let me know if you experience any issues.

Thanks,

Dan

mystix
21 May 2009, 12:31 AM
woot! sweet =D>

currently, pressing backspace immediately deletes the entry preceding the cursor.
you might want to add an option to highlight the entry preceding the cursor on backspace instead of immediately deleting it.

danh2000
21 May 2009, 12:43 AM
woot! sweet =D>

currently, pressing backspace immediately deletes the entry preceding the cursor.
you might want to add an option to highlight the entry preceding the cursor on backspace instead of immediately deleting it.

It was a requirement to allow the backspace deletion, but I do like your suggestion of a config option - I'm adding that, Thanks.

mystix
21 May 2009, 1:23 AM
one more thing
-- it would be good if you could stick an example of using this in a gridpanel in your examples page.

sanjshah
21 May 2009, 1:21 PM
that's cool!

aconran
21 May 2009, 2:02 PM
Awesome work.

danh2000
21 May 2009, 2:27 PM
@mystix

I'll look into adding it - It may require some additional work to support being a grid editor.


@sanjshah, @aconran

Thanks guys.

galdaka
21 May 2009, 10:39 PM
Awesome!!

Would be great add this component to Ext 3.0.

Thanks for share!!

danh2000
21 May 2009, 11:03 PM
Awesome!!

Would be great add this component to Ext 3.0.

Thanks for share!!

Thanks.

Ext 3.0 now supported:

http://technomedia.co.uk/SuperBoxSelect/examples3.html

:)

sanjshah
22 May 2009, 12:15 PM
Dan,

Is there any chance of making the beta available for testing on our own apps?

Thanks,

Sanj

danh2000
22 May 2009, 4:05 PM
Dan,

Is there any chance of making the beta available for testing on our own apps?

Thanks,

Sanj

Absolutely! I've attached a zip file to the first post.

Let me know how you get on.

Thanks.

Dan

sanjshah
23 May 2009, 6:28 AM
Thanks Dan, I'll try out and pass any other comments on. But it looks great to me!




Absolutely! I've attached a zip file to the first post.

Let me know how you get on.

Thanks.

Dan

nonyus
24 May 2009, 12:49 PM
This component is very cool.

But, I test to use it with an remote store.
It's work badly.

Can you help me to attribute defaults vlaues with an remote store ?

Thanks

danh2000
24 May 2009, 2:25 PM
This component is very cool.

But, I test to use it with an remote store.
It's work badly.

Can you help me to attribute defaults vlaues with an remote store ?

Thanks

The remote option is not currently supported - partly due to the requirement to allow new item data (as in my example 2) and partly due to the whole round-trip nature of collecting the store data from the server..

With a standard combo, it's only ever 1 value that's queried, but with this component if you performed a setValue call with 10 values - the records each have to be pulled back from the server.

I have some ideas about handling remote I just don't know if it will work in practice yet, so watch this space.

Dan

Joe
24 May 2009, 4:28 PM
Thanks for the very cool control!

nonyus
25 May 2009, 12:46 PM
OK, thanks Dan.

I test to implement this. I don't say if this is the good way, I not good with javascript.

I just add this code in the expand function (line 404), for filter the new load data :



var usedRecords = this.usedRecords;
var valueField = this.valueField;
this.store.on('load', function(store, records) {
store.filterBy(function(record, id) {
return (!usedRecords.containsKey(record.get(valueField)));
}, this);
});


Say me, if this is a good way ?

danh2000
25 May 2009, 2:15 PM
OK, thanks Dan.

I test to implement this. I don't say if this is the good way, I not good with javascript.

I just add this code in the expand function (line 404), for filter the new load data :



var usedRecords = this.usedRecords;
var valueField = this.valueField;
this.store.on('load', function(store, records) {
store.filterBy(function(record, id) {
return (!usedRecords.containsKey(record.get(valueField)));
}, this);
});


Say me, if this is a good way ?

Hi nonyus,

Thanks for posting again - there will be a bit more to it than that though as I need to accomodate for:

The preventDuplicates and removeValuesFromStore config options, a shared data store and the ability for users to enter new data (when the allowAddNewData config is true).

I did some testing yesterday and I know how I'll accomodate for this, but It will be a week or 2 until I release a new version (there are some other parts of the code that need refactoring too).

I'm going away for a few days R&R today, but will post again here when I've made some progress.


Thanks for the very cool control!

Thanks for your feedback Joe :)

Dan

grgur
26 May 2009, 3:11 AM
Excellent work!

I'm looking forward to seeing it work for remote stores.

Thumbs up!

radtad
26 May 2009, 12:48 PM
I set something up for remote validation ( from the orginal facebook thread), but it got really annoying doing a 1 field lookup each time. So I was thinking this should only do a remote lookup on all fields onBlur. That way it doesn't send too many http requests and the user using it doesn't see the field jump around ( I had the displayFieldTpl displaying something slightly different then the input).

A couple of other things that I added to original, that would be nice in here as well:
1. Pattern matching (middle of the word, etc.)
2. Comma separated list of values i.e. I'd like to be able to paste "california,delaware,texas" in the box and it should validate all three and turn them into boxes. I didn't paste this code, but I do have something if you'd like to see it. Maybe you can use some of it as your code looks a little cleaner than mine anyway :)
3. An option that doesn't turn the text into a box until onBlur happens. I've had requests that it's somewhat annoying for the displayFieldTpl to change the field and expand it when they're still trying to type in the box (i.e. they type in an email <tad> and it displays "Tad Johnston (tad)"). It would be awesome to get something like this as an option.

Hopefully all this makes sense....let me know if you want some of my awesome code to pick apart :)




The remote option is not currently supported - partly due to the requirement to allow new item data (as in my example 2) and partly due to the whole round-trip nature of collecting the store data from the server..

With a standard combo, it's only ever 1 value that's queried, but with this component if you performed a setValue call with 10 values - the records each have to be pulled back from the server.

I have some ideas about handling remote I just don't know if it will work in practice yet, so watch this space.

Dan

mishanian
26 May 2009, 9:42 PM
Wowww , Very Interesting.
Is it possible to have it for UTF8 also?
I have some Unicode Character to call (like chinese, Farsi, etc)

Thanks in Advance.
Mehran

mishanian
26 May 2009, 10:09 PM
Sorry Again,
Actually it is working fine with UTF8
but I have another question.
I want to use this in a FORM that this FORM is not generated by Ext JS and it is a normal form.
I mean I want to have just INPUT Box with your brilliant SuperBoxSelect.
Is it possible?

Thanks,
Mehran

sanjshah
28 May 2009, 9:16 AM
Hi Dan,

Is it possible to use this with a applyTo?

I have a existing standard form, I think this is also what Mehran is asking.

Thanks!

danh2000
28 May 2009, 8:41 PM
@radtad - some good suggestions thanks - I'll consider adding them. I'm not sure I see the use case for mid-word pattern matching (if I understand you correctly), but I like the others.

@mishanian, @sanjshah: I'm not sure applyTo is particularly relevent for a combo is it? Maybe transform is more relevant to transform an existing HTML select?

Perhaps you could supply a use case if it helps to clarify.

Thanks,

Dan

galdaka
28 May 2009, 11:01 PM
@radtad - some good suggestions thanks - I'll consider adding them. I'm not sure I see the use case for mid-word pattern matching (if I understand you correctly), but I like the others.

@mishanian, @sanjshah: I'm not sure applyTo is particularly relevent for a combo is it? Maybe transform is more relevant to transform an existing HTML select?

Perhaps you could supply a use case if it helps to clarify.

Thanks,

Dan

Hi,

I think that "transform" option would be great.


var converted = new Ext.form.SuperComboBox({
typeAhead: true,
triggerAction: 'all',
transform:'state',
width:135,
forceSelection:true
});


Greetings,

danh2000
28 May 2009, 11:21 PM
Hi,

I think that "transform" option would be great.


var converted = new Ext.form.SuperComboBox({
typeAhead: true,
triggerAction: 'all',
transform:'state',
width:135,
forceSelection:true
});


Greetings,

I'll add it to the requirements list - I suppose the clsField and styleField data could come from any existing style and class definition within the Option elements too....

Leave it with me - Thanks.

sanjshah
29 May 2009, 3:04 AM
Dan,

I'm not sure how the Transform works, but I can use the extension but cannot get it to pass the value to another form on, I've tried the change, newitemdata, additem, for some reason it works in IE but not Firefox.

Also when I use the newitemdata, the first/selected value is not passed only the previous values, am I doing something wrong?



<script type="text/javascript">
var tempIdCounter = 0;

Ext.onReady(function() {

Ext.QuickTips.init();

var tagStore = new Ext.data.SimpleStore({
fields: ['id', 'name'],
data: [['ID1','Name1'],['ID2','Name2'],['ID3','Name3'],['ID4','Name4'],['ID5','Name5'],['ID6','Name6']],
sortInfo: {field: 'name', direction: 'ASC'}
});

var form2 = new Ext.form.FormPanel({
id:'f2Form',
renderTo: 'f2',
title:'Email Recipients',
autoHeight: true,
bodyStyle: 'padding:10px;',
width: 650,
items: [{
allowBlank:false,
msgTarget: 'under',
allowAddNewData: true,
id:'selector2',
xtype:'superboxselect',
emptyText: 'Select Users to Email',
resizable: true,
name: 'tags',
anchor:'100%',
store: tagStore,
mode: 'local',
displayField: 'name',
valueField: 'id',
extraItemCls: 'x-tag',
listeners: {
beforeadditem: function(bs,v){
},
additem: function(bs,v){
form1.emails.value = Ext.getCmp('selector2').getValue();
},
beforeremoveitem: function(bs,v){
},
removeitem: function(bs,v){
//form1.emails.value = Ext.getCmp('selector2').getValue();
},
change: function(bs,v){
form1.emails.value = v;
},
newitemdata: function(bs,v){
v = v.slice(0,1).toUpperCase() + v.slice(1).toLowerCase();
var newObj = {
id: v,
name: v
};
bs.addItem(newObj);
}
}
}
],
buttons: [{
text: "Add Existing Tag (addItem)",
scope: this,
handler: function(){
Ext.getCmp('selector2').addItem({id:'Travel', name:'Travel'});
}
},{
text: "Add New Tag (addItem)",
scope: this,
handler: function(){
Ext.getCmp('selector2').addItem({id:'Beauty', name:'Beauty'});
}
},{
text: "Set New Values (setValueEx)",
scope: this,
handler: function(){
Ext.getCmp('selector2').setValueEx([{id:'Finance', name:'Finance'},{id:'Gardening', name:'Gardening'}]);
}
},{
text: "reset",
scope: this,
handler: function(){
Ext.getCmp('selector2').reset();
}
}]
});

});
</script>


Regards,

Sanj

danh2000
29 May 2009, 3:34 AM
Sanj,

Sorry, I'm not sure if I understood fully...

There was a bug in firing the 'additem' event in my addRecord method, the final 2 lines of code should be in this order:



this.addItemBox(val,display,caption,cls,style);
this.fireEvent('additem',this,val);


Try changing the above and trying the additem and/or change listeners.

If you are still experiencing problems please paste code (a full working page with both forms would help) and step by step instructions with expected results.

Thanks,

Dan

sanjshah
29 May 2009, 3:53 AM
Thanks Dan,

That's perfect!

Regards,


Sanj,

Sorry, I'm not sure if I understood fully...

There was a bug in firing the 'additem' event in my addRecord method, the final 2 lines of code should be in this order:



this.addItemBox(val,display,caption,cls,style);
this.fireEvent('additem',this,val);


Try changing the above and trying the additem and/or change listeners.

If you are still experiencing problems please paste code (a full working page with both forms would help) and step by step instructions with expected results.

Thanks,

Dan

stever
29 May 2009, 2:30 PM
I think the code find and alter the containing form could be done differently. I was thinking of using the HtmlEditor as an example. It keeps a form field hidden and syncs the content back to the hidden field on keypress and other things that change the content. I think this might work here as well. The getRawValue currently doesn't work, and beforeblur calls it, causing all sorts of issues. Not sure why it doesn't in your examples though...

Anyhow, nice extension! I can help with a sync system if you like...

xantus
29 May 2009, 3:23 PM
Stellar work!

mishanian
30 May 2009, 8:32 PM
Hi Dan,
we are waiting for the a separate form or ApplyTo Option.

Thanks a lot for your great job.

Regards,
Mehran

danh2000
30 May 2009, 8:43 PM
@stever

Do you have an example or can you elaborate on the getRawValue and beforeblur issues that you experienced - I actually haven't looked at or thought too much about getRawValue and how it should work - as this component has multiple values it's not quite the same as combo - if you (or anyone) has thoughts or suggestions, I'd appreciate hearing them.

@xantus Thanks!

Mehran Can you please provide additional info about what you mean?

Is applyTo really what you are looking for, and if so, what structure would you expect to see in the dom to apply the component to?

Or would you be happy to see the transform option to transform an existing combo?

Thanks,

Dan

mishanian
31 May 2009, 11:26 PM
Dear Dan,
Actually I have am using phpmaker to generate the forms.
It is generating a normal <form> with some other input box but I want to change one of the Input Text box to your great SuperBox selector. What is the best solution

Thanks in Advance,
Mehran

danh2000
1 Jun 2009, 3:48 PM
@Mehran

What have you tried so far?

The applyTo method should do the same as it does with ComboBox - if you specify the id of an input element, it should use that element and the parent form to render to.

If you would like me to take a look, please set up a test page where you use applyTo with both a ComboBox and with the SuperBoxSelect.

Thanks,

Dan

danh2000
1 Jun 2009, 4:12 PM
@Mehran

See here for an applyTo example:

http://technomedia.co.uk/SuperBoxSelect/applyTo.html

I'll add the transform (to transform an existing HTML Select) option soon.

Dan

mishanian
2 Jun 2009, 1:49 AM
Dear Dan,
Thanks a lot for your kind consider.

I did the same of your sample and it showing fine now! it is great. but the problem is I can not get the data back from the form (I have 3 fields in a form that use your SuperBox)

Can you kindly guide me what is wrong because after submit I can not see any data passed.

You can see it here:
http://niaar.com/bookadmin/applyTo.php

Thanks in advance.
Mehran

danh2000
2 Jun 2009, 2:47 AM
Dear Dan,
Thanks a lot for your kind consider.

I did the same of your sample and it showing fine now! it is great. but the problem is I can not get the data back from the form (I have 3 fields in a form that use your SuperBox)

Can you kindly guide me what is wrong because after submit I can not see any data passed.

You can see it here:
http://niaar.com/bookadmin/applyTo.php

Thanks in advance.
Mehran

I don't know - something is wrong with your PHP code because the values are submitted.

mishanian
2 Jun 2009, 9:56 PM
Dear Dan,
I found what is wrong.
"name" in this section:

var sbs = new Ext.ux.form.SuperBoxSelect({
...
name: 'states',

can not be the same of your input textbox <input name='states'

I have 2 question/requests:

1) This is your example (I just copy and post your code). After submitting, I am just getting only one of the selected Items. Please try it yourself.
http://niaar.com/bookadmin/applyTo.htm
even I did this in the same order as you mentioned:
this.addItemBox(val,display,caption,cls,style);
this.fireEvent('additem',this,val);
but still I am getting only one item after submit



2) is there any way that we can defined after how many letter show the list of selection? because now when I typed just the first letter, it gives me a long list



Again Thanks for your great job
Regards,
Mehran

danh2000
2 Jun 2009, 10:10 PM
Mehran,

1. PHP requires that you use square brackets in the name when sending arrays.

2. Yes, the same way as with ComboBox - the minChars config.

mishanian
3 Jun 2009, 12:16 AM
Dear Dan,
Everything is fine now.

You are Great! I like your works,
They are excellent and Fantastic jobs!
Keep going on..

I really appreciate your efforts,
Mehran

stever
5 Jun 2009, 7:14 AM
@stever

Do you have an example or can you elaborate on the getRawValue and beforeblur issues that you experienced - I actually haven't looked at or thought too much about getRawValue and how it should work - as this component has multiple values it's not quite the same as combo - if you (or anyone) has thoughts or suggestions, I'd appreciate hearing them.

Try using the newest version of Ext 3 from SVN (maybe RC2). I think you will see that the fields go blank on blur. Not such a great user experience! ;)

Anyhow, when content is changed (valid data that is), a hidden field ought to be updated with the value, and getRawValue would just return that.

danh2000
5 Jun 2009, 6:50 PM
Try using the newest version of Ext 3 from SVN (maybe RC2). I think you will see that the fields go blank on blur. Not such a great user experience! ;)

Anyhow, when content is changed (valid data that is), a hidden field ought to be updated with the value, and getRawValue would just return that.

Steve, I can't reproduce your blur issue - it's possible there is a bug or regression in the version of Ext 3 you are using - the recent RC 2 release actually fixed a couple of bugs that occured with this component and RC 1.1.

Your description of how you think getRawValue should work is exactly how getValue currently works - valid values are stored, and when getValue is called it returns those values (delimited).

Your suggestion is also different to how ComboBox (well Field actually) works - the getRawValue method returns the current value of the input el whether valid or not.

Obviously the biggest difference between this component and ComboBox is that there are multiple values - the input el is less relevant from a raw value point of view - it will always be different to the underlying value of the component when selection/s have been made which brings me to the dilemma of what getRawValue should return.

If you have use case/s with example data that explains your thoughts better, I'll be more than happy to have a look.

Thanks,

Dan

mjlecomte
6 Jun 2009, 4:59 AM
Try using the newest version of Ext 3 from SVN (maybe RC2). I think you will see that the fields go blank on blur.
I haven't tested / tried this ux, but you may be interested in this thread:
http://extjs.com/forum/showthread.php?p=337650#post337650

radtad
8 Jun 2009, 3:27 PM
I'm trying to use the SuperSelectBox with Ext 2.2 in a form and this is basically what I'm doing. I'm disabling the form while the data is updating the form then enabling the form. This causes problems with the box.

1. I cannot use Box.addItem() as you can't set the value if the form is disabled. Don't you think there should be an override feature? Or maybe it really shouldn't be checking for disabled. I would assume the only way in setting a value (if the person is the end user) is through some sort of button. I think the button should be checking for a disabled form rather then in the addItem function....just my thoughts.

2. I cannot use the following config at all.


renderFieldBtns: falseform disabled (it will not generate the form window)...


this.buttonClear is undefined
this.buttonClear.removeAllListeners();
SuperBoxSelect.js (line 216)
this.buttonClear is undefined
this.buttonClear.addClassOnOver('x-superboxselect-btn-over')
form enabled (everything seems fine, but it won't do addItem)...


this.buttonClear is undefined
this.buttonClear.addClassOnOver('x-superboxselect-btn-over')

radtad
8 Jun 2009, 3:50 PM
@radtad - some good suggestions thanks - I'll consider adding them. I'm not sure I see the use case for mid-word pattern matching (if I understand you correctly), but I like the others.

Let's see if I can give you an example:

I have a name "Chris" I'm trying to find because that's what he told me his name is. But his first name is actually "John" and his middle name is "Chris". So the display field would normally be {First Name} {Middle Name} {Last Name} i.e. "John Chris Doe". With no mid-word pattern matching available, if I didn't know Chris' real name was John, I'd never get his name as a return match.


A big use case for our company comes down to email addresses. Currently I have "Tad Johnston (rad)" as the display field, "rad" being the email address. A lot of people here often times do not know the person's actual name, but they always know their email address because it's something they see often. Now, if I don't have mid-word pattern matching I can never find "rad".

Another suggestion which would be even better would be matching on more then just the displayField, possibly in the store. Then I wouldn't have to worry about mid word pattern matching whatsoever.

Hope this makes sense....

danh2000
8 Jun 2009, 4:28 PM
@radtad, thanks for the reports.


I'm trying to use the SuperSelectBox with Ext 2.2 in a form and this is basically what I'm doing. I'm disabling the form while the data is updating the form then enabling the form. This causes problems with the box.

1. I cannot use Box.addItem() as you can't set the value if the form is disabled. Don't you think there should be an override feature? Or maybe it really shouldn't be checking for disabled. I would assume the only way in setting a value (if the person is the end user) is through some sort of button. I think the button should be checking for a disabled form rather then in the addItem function....just my thoughts.



Maybe I shouldn't check for the disabled state when programatically interacting with the component - I'll have a look at the other Ext form controls and follow suit.




2. I cannot use the following config at all.


renderFieldBtns: falseform disabled (it will not generate the form window)...


this.buttonClear is undefined
this.buttonClear.removeAllListeners();
SuperBoxSelect.js (line 216)
this.buttonClear is undefined
this.buttonClear.addClassOnOver('x-superboxselect-btn-over')



Thanks, in the onDisable method, the call to removeButtonEvents should have been wrapped like so:


if(this.renderFieldBtns){
this.removeButtonEvents();
}



form enabled (everything seems fine, but it won't do addItem)...


this.buttonClear is undefined
this.buttonClear.addClassOnOver('x-superboxselect-btn-over')


I can't re-create this - I've set disabled to false and used addItem without issues.

If you are still having problems, please post a link to a working example, or copy and paste code that I can use to reproduce the error.

Thanks again,

Dan

danh2000
8 Jun 2009, 4:32 PM
Let's see if I can give you an example:

I have a name "Chris" I'm trying to find because that's what he told me his name is. But his first name is actually "John" and his middle name is "Chris". So the display field would normally be {First Name} {Middle Name} {Last Name} i.e. "John Chris Doe". With no mid-word pattern matching available, if I didn't know Chris' real name was John, I'd never get his name as a return match.


A big use case for our company comes down to email addresses. Currently I have "Tad Johnston (rad)" as the display field, "rad" being the email address. A lot of people here often times do not know the person's actual name, but they always know their email address because it's something they see often. Now, if I don't have mid-word pattern matching I can never find "rad".

Another suggestion which would be even better would be matching on more then just the displayField, possibly in the store. Then I wouldn't have to worry about mid word pattern matching whatsoever.

Hope this makes sense....

Thanks, It makes sense - I think matching against all store fields would be the best way - I'll see what the effort would be and add it to the list of nice to have's.

danh2000
8 Jun 2009, 4:41 PM
I haven't tested / tried this ux, but you may be interested in this thread:
http://extjs.com/forum/showthread.php?p=337650#post337650

Thanks for the link Michael, I couldn't reproduce the issue myself - I think it's fixed with the current SVN codebase..

radtad
8 Jun 2009, 5:01 PM
Thanks, It makes sense - I think matching against all store fields would be the best way - I'll see what the effort would be and add it to the list of nice to have's.

I just added a bit of code to do mid-word pattern matching for the SuperBoxSelect from the previous facebook like box select I added there as well (you essentially have to override doQuery):



anyMatch: true,
caseSensitive: false,
createValueMatcher: function(value) {
console.log('createValueMatcher...'+value);
if (Ext.isEmpty(value, false)) {
return new RegExp('^');
}
value = Ext.escapeRe(String(value));
return new RegExp((this.anyMatch === true ? '' : '^') + '(' + Ext.escapeRe(value) + ')', this.caseSensitive ? '' : 'i');
},
prepareData : function(data) {
var result = Ext.apply({}, data);
result[this.displayField] = data[this.displayField].replace(this.createValueMatcher(this.getRawValue()), function(a, b){
if (typeof b != 'string') {
return '';
}
return '<span class="ext-combo-match">' + b + '</span>';
});
return result;
},

initList : function() {
Ext.ux.form.SuperBoxSelect.superclass.initList.apply(this, arguments);
this.view.prepareData = this.prepareData.createDelegate(this);
},

doQuery : function(q, forceAll) {
if(q === undefined || q === null) {
q = '';
}
var qe = {
query: q,
forceAll: forceAll,
combo: this,
key: ";"
};
if (this.fireEvent('beforequery', qe)===false || qe.cancel) {
return false;
}
q = qe.query;
forceAll = qe.forceAll;
if (forceAll === true || (q.length >= this.minChars)) {
if(this.lastQuery !== q){
this.lastQuery = q;
if(this.mode == 'local'){
this.selectedIndex = -1;
if(forceAll){
this.store.clearFilter();
} else {
this.store.filter(this.displayField, q, this.anyMatch);
}
this.onLoad();
} else {
this.store.baseParams[this.queryParam] = q;
this.store.load({
params: this.getParams(q)
});
this.expand();
}
} else {
this.selectedIndex = -1;
this.onLoad();
}
}
},
By the way, thanks for the quick response and nice work on the box! Much faster and cleaner than the original.

danh2000
8 Jun 2009, 7:20 PM
@radtad,

Nice - why don't you make it a standalone plugin, that way you could plug the functionality into SuperBoxSelect, or ComboBox or any component that extends ComboBox.

radtad
8 Jun 2009, 7:41 PM
@radtad,

Nice - why don't you make it a standalone plugin, that way you could plug the functionality into SuperBoxSelect, or ComboBox or any component that extends ComboBox.

I could definitely do that (never really came to mind and now that you've suggested it I probably will), I just figured it makes more sense to be part of SuperBoxSelect / ComboBox. But I'd probably be more for iterating through the fields in the store. That would be even better! ;)

radtad
9 Jun 2009, 2:52 PM
I've added a display fix so the outerbox border highlights on focus which is what all other form fields do:



onRender:function(ct, position) {
Ext.ux.form.SuperBoxSelect.superclass.onRender.call(this, ct, position);

this.el.removeClass('x-form-text');
this.el.addClass('x-superboxselect-input-field');

this.wrapEl = this.el.wrap({
tag : 'ul'
});

var extraClass = (this.stackItems === true) ? 'x-superboxselect-stacked' : '';

if(this.renderFieldBtns){
extraClass += ' x-superboxselect-display-btns';
}
this.outerWrapEl = this.wrapEl.wrap({
tag : 'div',
cls: 'x-form-text x-superboxselect ' + extraClass
});

this.on('focus', function() {
this.outerWrapEl.addClass("x-form-focus");
});

this.on('blur', function() {
this.outerWrapEl.removeClass("x-form-focus");
});

this.inputEl = this.el.wrap({
tag : 'li',
cls : 'x-superboxselect-input'
});

if(this.renderFieldBtns){
this.setupFieldButtons();
this.manageClearBtn();
}

this.setupFormInterception();
},
Also, don't know if this is a bug, but I'm not sure the parameter name should set itself to the same thing if hiddenName doesn't exist so I went ahead and fixed it:



box.hidden = this.el.insertSibling({
tag:'input',
type:'hidden',
value: itemVal,
name: (this.hiddenName || this.name+'['+itemVal+']') // could also be this.name+'[]' I assume
},'before');

danh2000
9 Jun 2009, 4:22 PM
@radtad,

Thanks - I had omitted the x-form-focus.

I'm not sure what you were aiming for with the second piece of code, but it won't work - the hidden items need to be named as per hiddenname or name so that getValues works from the parent form. What were you doing here - did you find an issue before trying to change it?

radtad
9 Jun 2009, 4:44 PM
If you just use this.name instead of this.name+'['+itemVal+']', it will return the following if you're not using a hiddenName field with more then one list value (unless I'm missing something).

If I've got 3 boxes in a field i.e. tad,john,chris the parameters posted are:


email=tad
email=john
email=chris


This doesn't form any kind of array and instead overwrites each parameter if I'm not mistaken...at least it does for me.

danh2000
9 Jun 2009, 5:01 PM
If you just use this.name instead of this.name+'['+itemVal+']', it will return the following if you're not using a hiddenName field with more then one list value (unless I'm missing something).

If I've got 3 boxes in a field i.e. tad,john,chris the parameters posted are:


email=tad
email=john
email=chris


This doesn't form any kind of array and instead overwrites each parameter if I'm not mistaken...at least it does for me.

If you are using PHP you have to declare the name with square brackets to recieve array data, so call your field email[] instead. This is not the same for other server-side technologies, so it's up to you as the implementor to name the field in this way. You would have to do the same in a standard HTML form too.



Dan

elderotaku
12 Jun 2009, 1:48 PM
I found a wierd problem which I was able to repeat on this link:
http://technomedia.co.uk/SuperBoxSelect/applyTo.html

So I am assuming it is a problem with the Box Select and wondered if anyone knew how to fix it.

If you paste text into the box select or press and hold a character key you will see that the beginning of the text is cut off, if you press any key after that it fixes itself.

Any help would be greatly appreciated.

danh2000
12 Jun 2009, 3:09 PM
I found a wierd problem which I was able to repeat on this link:
http://technomedia.co.uk/SuperBoxSelect/applyTo.html

So I am assuming it is a problem with the Box Select and wondered if anyone knew how to fix it.

If you paste text into the box select or press and hold a character key you will see that the beginning of the text is cut off, if you press any key after that it fixes itself.

Any help would be greatly appreciated.

It's the textbox grow code. I'll look into it when I get a chance and post back.

nohurge
22 Jun 2009, 9:22 AM
Hi ,
I am using this on a new project , great job thanks.

When allowAddNewData is true , let's say for tags , i type "a" and the first word coming up is attribute but i want to add "at" as new data ,i have to click and make the suggestions to lose focus , so i can add new data later.
Is there a way to avoid this? When allowAddNewData is true , the suggestions should be visible but not focused.

danh2000
22 Jun 2009, 2:31 PM
Hi ,
I am using this on a new project , great job thanks.

When allowAddNewData is true , let's say for tags , i type "a" and the first word coming up is attribute but i want to add "at" as new data ,i have to click and make the suggestions to lose focus , so i can add new data later.
Is there a way to avoid this? When allowAddNewData is true , the suggestions should be visible but not focused.

Hi, glad you like the component.

I built in a Ctrl+Enter hook for the scenario you describe. Does this help or are you talking about
mouse interaction only?

nohurge
22 Jun 2009, 10:36 PM
It works great , thanks :)

mystix
24 Jun 2009, 1:53 AM
had a need for this ux, so i took the liberty of cleaning up the code:


Ext.namespace('Ext.ux.form');
/**
* <p>SuperBoxSelect is an extension of the ComboBox component that displays selected items as labelled boxes within the form field. As seen on facebook, hotmail and other sites.</p>
* <p>The SuperBoxSelect component was inspired by and based on the BoxSelect component found here: http://efattal.fr/en/extjs/extuxboxselect/</p>
*
* @author <a href="mailto:dan.humphrey@technomedia.co.uk">Dan Humphrey</a> created for ******CENSORED******
* @class Ext.ux.form.SuperBoxSelect
* @extends Ext.form.ComboBox
* @constructor
* @component
* @version 1.0b1
* @license Unlikely
*
*/
Ext.ux.form.SuperBoxSelect = function(config) {
Ext.ux.form.SuperBoxSelect.superclass.constructor.call(this, config);

this.addEvents(
/**
* Fires before an item is added to the component via user interaction. Return false from the callback function to prevent the item from being added.
* @event beforeadditem
* @memberOf Ext.ux.form.SuperBoxSelect
* @param {SuperBoxSelect} this
* @param {Mixed} value The value of the item to be added
*/
'beforeadditem',

/**
* Fires after a new item is added to the component.
* @event additem
* @memberOf Ext.ux.form.SuperBoxSelect
* @param {SuperBoxSelect} this
* @param {Mixed} value The value of the item which was added
*/
'additem',

/**
* Fires when the allowAddNewData config is set to true, and a user attempts to add an item that is not in the data store.
* @event newitem
* @memberOf Ext.ux.form.SuperBoxSelect
* @param {SuperBoxSelect} this
* @param {Mixed} value The new item's value
*/
'newitem',

/**
* Fires when an item's remove button is clicked. Return false from the callback function to prevent the item from being removed.
* @event beforeremoveitem
* @memberOf Ext.ux.form.SuperBoxSelect
* @param {SuperBoxSelect} this
* @param {Mixed} value The value of the item to be removed
*/
'beforeremoveitem',

/**
* Fires after an item has been removed.
* @event removeitem
* @memberOf Ext.ux.form.SuperBoxSelect
* @param {SuperBoxSelect} this
* @param {Mixed} value The value of the item which was removed
*/
'removeitem'
);
};

/**
* @private hide from doc gen
*/
Ext.ux.form.SuperBoxSelect = Ext.extend(Ext.ux.form.SuperBoxSelect, Ext.form.ComboBox, {
/**
* @cfg {Boolean} allowAddNewData When set to true, allows items to be added (via the setValueEx and addItem methods) that do not already exist in the data store. Defaults to false.
*/
allowAddNewData: false,

/**
* @cfg {Boolean} backspaceDeletesLastItem When set to false, the BACKSPACE key will focus the last selected item. When set to true, the last item will be immediately deleted. Defaults to true.
*/
backspaceDeletesLastItem: true,

/**
* @cfg {String} classField The underlying data field that will be used to supply an additional class to each item.
*/
classField: null,

/**
* @cfg {String} clearBtnCls An additional class to add to the in-field clear button.
*/
clearBtnCls: '',

/**
* @cfg {String/XTemplate} displayFieldTpl A template for rendering the displayField in each selected item. Defaults to null.
*/
displayFieldTpl: null,

/**
* @cfg {String} extraItemCls An additional css class to apply to each item.
*/
extraItemCls: '',

/**
* @cfg {String/Object/Function} extraItemStyle Additional css style(s) to apply to each item. Should be a valid argument to Ext.Element.applyStyles.
*/
extraItemStyle: '',

/**
* @cfg {String} expandBtnCls An additional class to add to the in-field expand button.
*/
expandBtnCls: '',

/**
* @cfg {Boolean} fixFocusOnTabSelect When set to true, the component will not lose focus when a list item is selected with the TAB key. Defaults to true.
*/
fixFocusOnTabSelect: true,

/**
* @cfg {Boolean} navigateItemsWithTab When set to true the tab key will navigate between selected items. Defaults to true.
*/
navigateItemsWithTab: true,

/**
* @cfg {Boolean} pinList When set to true the select list will be pinned to allow for multiple selections. Defaults to true.
*/
pinList: true,

/**
* @cfg {Boolean} preventDuplicates When set to true unique item values will be enforced. Defaults to true.
*/
preventDuplicates: true,

/**
* @cfg {Boolean} removeValuesFromStore When set to true, selected records will be removed from the store. Defaults to true.
*/
removeValuesFromStore: true,

/**
* @cfg {String} renderFieldBtns When set to true, will render in-field buttons for clearing the component, and displaying the list for selection. Defaults to true.
*/
renderFieldBtns: true,

/**
* @cfg {Boolean} stackItems When set to true, the items will be stacked 1 per line. Defaults to false which displays the items inline.
*/
stackItems: false,

/**
* @cfg {String} styleField The underlying data field that will be used to supply additional css styles to each item.
*/
styleField : null,

/**
* @cfg {String} valueDelimiter The delimiter to use when joining and splitting value arrays and strings.
*/
valueDelimiter: ',',

initComponent: function() {
Ext.apply(this, {
items : new Ext.util.MixedCollection(false),
usedRecords : new Ext.util.MixedCollection(false),
hideTrigger : true,
grow : false,
resizable : false,
multiSelectMode : false
});

Ext.ux.form.SuperBoxSelect.superclass.initComponent.call(this);
},

onRender:function(ct, position) {
Ext.ux.form.SuperBoxSelect.superclass.onRender.call(this, ct, position);

var extraClass = (this.stackItems === true) ? 'x-superboxselect-stacked' : '';
if (this.renderFieldBtns) {
extraClass += ' x-superboxselect-display-btns';
}

this.el.removeClass('x-form-text').addClass('x-superboxselect-input-field');

this.wrapEl = this.el.wrap({
tag : 'ul'
});

this.outerWrapEl = this.wrapEl.wrap({
tag : 'div',
cls: 'x-form-text x-superboxselect ' + extraClass
});

this.inputEl = this.el.wrap({
tag : 'li',
cls : 'x-superboxselect-input'
});

if (this.renderFieldBtns) {
this.setupFieldButtons();
this.manageClearBtn();
}
this.setupFormInterception();
},

setupFieldButtons : function() {
this.buttonWrap = this.outerWrapEl.createChild({
cls: 'x-superboxselect-btns'
});

this.buttonClear = this.buttonWrap.createChild({
tag:'div',
cls: 'x-superboxselect-btn-clear ' + this.clearBtnCls
});

this.buttonExpand = this.buttonWrap.createChild({
tag:'div',
cls: 'x-superboxselect-btn-expand ' + this.expandBtnCls
});

this.initButtonEvents();
},

initButtonEvents : function() {
this.buttonClear.addClassOnOver('x-superboxselect-btn-over').on('click', function(e) {
e.stopEvent();
if (this.disabled) {
return;
}
this.clearValue();
this.el.focus();
}, this);

this.buttonExpand.addClassOnOver('x-superboxselect-btn-over').on('click', function(e) {
e.stopEvent();
if (this.disabled) {
return;
}
if (this.isExpanded()) {
this.multiSelectMode = false;
} else if (this.pinList) {
this.multiSelectMode = true;
}
this.onTriggerClick();
}, this);
},

removeButtonEvents : function() {
this.buttonClear.removeAllListeners();
this.buttonExpand.removeAllListeners();
},

clearCurrentFocus : function() {
if (this.currentFocus) {
this.currentFocus.onLnkBlur();
this.currentFocus = null;
}
},

initEvents : function() {
var el = this.el;

el.on({
click : this.onClick,
focus : this.clearCurrentFocus,
blur : this.onBlur,

keydown : this.onKeyDownHandler,
keyup : this.onKeyUpBuffered,

scope : this
});

this.on({
collapse: this.onCollapse,
expand: this.clearCurrentFocus,
scope: this
});

this.wrapEl.on('click', this.onWrapClick, this);
this.outerWrapEl.on('click', this.onWrapClick, this);

// TODO: what the heck?!?! setting this.inputEl.focus = el.focus / this.el.focus doesn't work?!?!
this.inputEl.focus = function() {
el.focus();
};

Ext.ux.form.SuperBoxSelect.superclass.initEvents.call(this);

Ext.apply(this.keyNav, {
tab: function(e) {
if (this.fixFocusOnTabSelect && this.isExpanded()) {
e.stopEvent();
el.blur();
this.onViewClick(false);
this.focus(false, 10);
return true;
}

this.onViewClick(false);
if (el.dom.value !== '') {
this.setRawValue('');
}

return true;
},

down: function(e) {
if (!this.isExpanded() && !this.currentFocus) {
this.onTriggerClick();
} else {
this.inKeyMode = true;
this.selectNext();
}
},

enter: function(e) {
this.onViewClick();
this.delayedCheck = true;
this.unsetDelayCheck.defer(10, this);
return true;
}
});
},

onClick: function() {
this.clearCurrentFocus();
this.collapse();
this.autoSize();
},

beforeBlur: Ext.form.ComboBox.superclass.beforeBlur,

onFocus: function() {
this.outerWrapEl.addClass(this.focusClass);

Ext.ux.form.SuperBoxSelect.superclass.onFocus.call(this);
},

onBlur: function() {
this.outerWrapEl.removeClass(this.focusClass);

this.clearCurrentFocus();

if (this.el.dom.value !== '') {
this.applyEmptyText();
this.autoSize();
}

Ext.ux.form.SuperBoxSelect.superclass.onBlur.call(this);
},

onCollapse: function() {
this.multiSelectMode = false;
},

onWrapClick: function(e) {
e.stopEvent();
this.collapse();
this.el.focus();
this.clearCurrentFocus();
},

markInvalid : function(msg) {
var elp, t;

if (!this.rendered || this.preventMark) { // not rendered
return;
}
this.outerWrapEl.addClass(this.invalidClass);
msg = msg || this.invalidText;

switch (this.msgTarget) {
case 'qtip':
Ext.apply(this.el.dom, {
qtip : msg,
qclass : 'x-form-invalid-tip'
});
Ext.apply(this.wrapEl.dom, {
qtip : msg,
qclass : 'x-form-invalid-tip'
});
if (Ext.QuickTips) { // fix for floating editors interacting with DND
Ext.QuickTips.enable();
}
break;
case 'title':
this.el.dom.title = msg;
this.wrapEl.dom.title = msg;
this.outerWrapEl.dom.title = msg;
break;
case 'under':
if (!this.errorEl) {
elp = this.getErrorCt();
if (!elp) { // field has no container el
this.el.dom.title = msg;
break;
}
this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
this.errorEl.setWidth(elp.getWidth(true) - 20);
}
this.errorEl.update(msg);
Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
break;
case 'side':
if (!this.errorIcon) {
elp = this.getErrorCt();
if (!elp) { // field has no container el
this.el.dom.title = msg;
break;
}
this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
}
this.alignErrorIcon();
Ext.apply(this.errorIcon.dom, {
qtip : msg,
qclass : 'x-form-invalid-tip'
});
this.errorIcon.show();
this.on('resize', this.alignErrorIcon, this);
break;
default:
t = Ext.getDom(this.msgTarget);
t.innerHTML = msg;
t.style.display = this.msgDisplay;
break;
}
this.fireEvent('invalid', this, msg);
},

clearInvalid : function() {
var t;

if (!this.rendered || this.preventMark) { // not rendered
return;
}
this.outerWrapEl.removeClass(this.invalidClass);
switch (this.msgTarget) {
case 'qtip':
this.el.dom.qtip = '';
this.wrapEl.dom.qtip = '';
break;
case 'title':
this.el.dom.title = '';
this.wrapEl.dom.title = '';
this.outerWrapEl.dom.title = '';
break;
case 'under':
if (this.errorEl) {
Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
}
break;
case 'side':
if (this.errorIcon) {
this.errorIcon.dom.qtip = '';
this.errorIcon.hide();
this.un('resize', this.alignErrorIcon, this);
}
break;
default:
t = Ext.getDom(this.msgTarget);
t.innerHTML = '';
t.style.display = 'none';
break;
}
this.fireEvent('valid', this);
},

// private
alignErrorIcon : function() {
if (this.wrap) {
this.errorIcon.alignTo(this.wrap, 'tl-tr', [Ext.isIE ? 5 : 2, 3]);
}
},

expand : function() {
if (this.isExpanded() || !this.hasFocus) {
return;
}
this.list.alignTo(this.outerWrapEl, this.listAlign).show();
this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac
Ext.getDoc().on({
mousewheel: this.collapseIf,
mousedown: this.collapseIf,
scope: this
});
this.fireEvent('expand', this);
},

restrictHeight : function() {
var inner = this.innerList.dom,
st = inner.scrollTop,
pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
ha = this.getPosition()[1] - Ext.getBody().getScroll().top,
hb = Ext.lib.Dom.getViewHeight() - ha - this.getSize().height,
space = Math.max(ha, hb, this.minHeight || 0) - this.list.shadowOffset - pad - 5;

inner.style.height = '';
h = Math.min(h, space, this.maxHeight);

this.innerList.setHeight(h);
this.list.beginUpdate();
this.list.setHeight(h + pad);
this.list.alignTo(this.outerWrapEl, this.listAlign);
this.list.endUpdate();

if (this.multiSelectMode) {
inner.scrollTop = st;
}
},

validateValue: function(val) {
if (this.items.getCount() == 0) {
if (this.allowBlank) {
this.clearInvalid();
return true;
} else {
this.markInvalid(this.blankText);
return false;
}
} else {
this.clearInvalid();
return true;
}
},

setupFormInterception : function() {
//intercept form.getValues to ensure that the input element is not included as an empty field
var form;
this.findParentBy(function(p) {
if (p.getForm) {
form = p.getForm();
}
});
if (form) {
var formGet = form.getValues;
form.getValues = function(asString) {
var oldVal, vals;

if (this.items.getCount() > 0) {
this.el.dom.disabled = true;
}
oldVal = this.el.dom.value;
this.setRawValue('');
vals = formGet.call(form, asString);
this.el.dom.disabled = false;
this.setRawValue(oldVal);
return vals;
}.createDelegate(this);
}
},

onResize : function(w, h, rw, rh) {
var reduce = Ext.isIE6 ? 4 : Ext.isIE7 ? 1 : Ext.isIE8 ? 1 : 0;

this._width = w;
this.outerWrapEl.setWidth(w - reduce);
if (this.renderFieldBtns) {
reduce += (this.buttonWrap.getWidth() + 20);
this.wrapEl.setWidth(w - reduce);
}
Ext.ux.form.SuperBoxSelect.superclass.onResize.call(this, w, h, rw, rh);
this.autoSize();
},

onEnable: function() {
Ext.ux.form.SuperBoxSelect.superclass.onEnable.call(this);
this.items.each(function(item) {
item.enable();
});
this.initButtonEvents();
},

onDisable: function() {
Ext.ux.form.SuperBoxSelect.superclass.onDisable.call(this);
this.items.each(function(item) {
item.disable();
});
this.removeButtonEvents();
},

clearValue : function() {
Ext.ux.form.SuperBoxSelect.superclass.clearValue.call(this);
this.removeAllItems();
},

onKeyUp : function(e) {
if (this.editable !== false && !e.isSpecialKey() && (!e.hasModifier() || e.shiftKey)) {
this.lastKey = e.getKey();
this.dqTask.delay(this.queryDelay);
}
},

onKeyDownHandler : function(e, t) {
if ((e.getKey() === e.DELETE || e.getKey() === e.SPACE) && this.currentFocus) {
e.stopEvent();
var toDestroy = this.currentFocus,
idx = this.items.indexOfKey(this.currentFocus.key),
nextFocus;

this.on('expand', function() {
this.collapse();
}, this, {single: true});

this.clearCurrentFocus();

if (idx < (this.items.getCount() - 1)) {
nextFocus = this.items.itemAt(idx + 1);
}

toDestroy.preDestroy(true);

if (nextFocus) {
(function() {
nextFocus.onLnkFocus();
this.currentFocus = nextFocus;
}).defer(200, this);
}

return true;
}

var val = this.el.dom.value, it;
//ctrl+enter for new items
if (e.getKey() === e.ENTER) {
if (val !== "") {
e.stopEvent();
if (e.ctrlKey) {
this.collapse();
this.setRawValue('');
this.fireEvent('newitem', this, val);
}
else {
if (!this.isExpanded()) {
this.setRawValue('');
this.fireEvent('newitem', this, val);
}
else {
this.onViewClick();
this.delayedCheck = true;
this.unsetDelayCheck.defer(10, this);
}
}
} else {
if (!this.isExpanded()) {
return;
}
this.onViewClick();
this.delayedCheck = true;
this.unsetDelayCheck.defer(10, this);
}
return true;
}

if (val !== '') {
return;
}

//select first item
if (e.getKey() === e.HOME) {
e.stopEvent();
if (this.items.getCount() > 0) {
this.collapse();
it = this.items.get(0);
it.el.focus();

}
return true;
}
//backspace remove
if (e.getKey() === e.BACKSPACE) {
e.stopEvent();
if (this.currentFocus) {
toDestroy = this.currentFocus;
idx = this.items.indexOfKey(toDestroy.key);
nextFocus = null;

this.on('expand', function() {
this.collapse();
}, this, {single: true});

this.clearCurrentFocus();
if (idx < (this.items.getCount() - 1)) {
nextFocus = this.items.itemAt(idx + 1);
}

toDestroy.preDestroy(true);

if (nextFocus) {
(function() {
nextFocus.onLnkFocus();
this.currentFocus = nextFocus;
}).defer(200, this);
}

return;
} else {
it = this.items.get(this.items.getCount() - 1);
if (it) {
if (this.backspaceDeletesLastItem) {
this.on('expand', function() {
this.collapse();
}, this, {single: true});

it.preDestroy(true);
} else {
if (this.navigateItemsWithTab) {
it.onElClick();
} else {
this.on('expand', function() {
this.collapse();
this.currentFocus = it;
this.currentFocus.onLnkFocus.defer(20, this.currentFocus);
}, this, {single: true});
}
}
}
return true;
}
}

if (!e.isNavKeyPress()) {
this.multiSelectMode = false;
this.clearCurrentFocus();
return;
}
//arrow nav
if (e.getKey() === e.LEFT || (e.getKey() === e.UP && !this.isExpanded())) {
e.stopEvent();
this.collapse();
//get last item
it = this.items.get(this.items.getCount() - 1);
if (this.navigateItemsWithTab) {
//focus last el
if (it) {
it.focus();
}
} else {
//focus prev item
if (this.currentFocus) {
idx = this.items.indexOfKey(this.currentFocus.key);
this.clearCurrentFocus();

if (idx !== 0) {
this.currentFocus = this.items.itemAt(idx - 1);
this.currentFocus.onLnkFocus();
}
} else {
this.currentFocus = it;
if (it) {
it.onLnkFocus();
}
}
}
return true;
}
if (e.getKey() === e.DOWN) {
if (this.currentFocus) {
this.collapse();
e.stopEvent();
idx = this.items.indexOfKey(this.currentFocus.key);
if (idx == (this.items.getCount() - 1)) {
this.clearCurrentFocus.defer(10, this);
} else {
this.clearCurrentFocus();
this.currentFocus = this.items.itemAt(idx + 1);
if (this.currentFocus) {
this.currentFocus.onLnkFocus();
}
}
return true;
}
}
if (e.getKey() === e.RIGHT) {
this.collapse();
it = this.items.itemAt(0);
if (this.navigateItemsWithTab) {
//focus first el
if (it) {
it.focus();
}
} else {
if (this.currentFocus) {
idx = this.items.indexOfKey(this.currentFocus.key);
this.clearCurrentFocus();
if (idx < (this.items.getCount() - 1)) {
this.currentFocus = this.items.itemAt(idx + 1);
if (this.currentFocus) {
this.currentFocus.onLnkFocus();
}
}
} else {
this.currentFocus = it;
if (it) {
it.onLnkFocus();
}
}
}
}
},

reset : function() {
Ext.ux.form.SuperBoxSelect.superclass.reset.call(this);
this.autoSize();
this.setRawValue('');
this.el.focus();
},

applyEmptyText : function() {
if (this.items.getCount() > 0) {
this.el.removeClass(this.emptyClass);
this.setRawValue('');
return;
}
if (this.rendered && this.emptyText && this.getRawValue().length < 1) {
this.setRawValue(this.emptyText);
this.el.addClass(this.emptyClass);
}
},

/**
* Removes all items from the SuperBoxSelect component
* @methodOf Ext.ux.form.SuperBoxSelect
* @name removeAllItems
*/
removeAllItems: function() {
this.items.each(function(item) {
item.preDestroy(true);
}, this);

this.manageClearBtn();
},

resetStore: function() {
if (!this.removeValuesFromStore) {
return;
}
this.usedRecords.each(function(rec) {
this.store.add(rec);
}, this);
this.sortStore();
},

sortStore: function() {
var ss = this.store.getSortState();
if (ss && ss.field) {
this.store.sort(ss.field, ss.direction);
}
},

getCaption: function(dataObject) {
if (typeof this.displayFieldTpl === 'string') {
this.displayFieldTpl = new Ext.XTemplate(this.displayFieldTpl);
}
var recordData = dataObject instanceof Ext.data.Record ? dataObject.data : dataObject,
caption;

if (this.displayFieldTpl) {
caption = this.displayFieldTpl.apply(recordData);
} else if (this.displayField) {
caption = recordData[this.displayField];
}

return caption;
},

addRecord : function(record) {
var display = record.data[this.displayField],
caption = this.getCaption(record),
val = record.data[this.valueField],
cls = this.classField ? record.data[this.classField] : '',
style = this.styleField ? record.data[this.styleField] : '';

if (this.removeValuesFromStore) {
this.usedRecords.add(val, record);
this.store.remove(record);
}

this.fireEvent('additem', this, val);

this.addItemBox(val, display, caption, cls, style);
},

createRecord : function(recordData) {
if (!this.recordConstructor) {
var recordFields = [{
name: this.valueField
}, {
name: this.displayField
}];

if (this.classField) {
recordFields.push({name: this.classField});
}
if (this.styleField) {
recordFields.push({name: this.styleField});
}
this.recordConstructor = Ext.data.Record.create(recordFields);
}
return new this.recordConstructor(recordData);
},

/**
* Adds an item to the SuperBoxSelect component if the {@link #Ext.ux.form.SuperBoxSelect-allowAddNewData} config is set to true.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name addItem
* @param {Object} newItemObject An object literal containing the property names and values for an item. The property names must match those specified in {@link #Ext.ux.form.SuperBoxSelect-displayField}, {@link #Ext.ux.form.SuperBoxSelect-valueField} and {@link #Ext.ux.form.SuperBoxSelect-classField}
*/
addItem : function(newItemObject) {
var val = newItemObject[this.valueField];

if (this.disabled) {
return false;
}
if (this.preventDuplicates && this.hasValue(val)) {
return;
}

//use existing record if found
var record;
if (record = this.findRecord(this.valueField, val)) {
this.addRecord(record);
return;
} else if (!this.allowAddNewData) { // else it's a new item
return;
}

var rec = this.createRecord(newItemObject);
this.store.add(rec);
this.addRecord(rec);

return true;
},

addItemBox : function(itemVal, itemDisplay, itemCaption, itemClass, itemStyle) {
var parseStyle = function(s) {
var ret = '';
if (typeof s == 'function') {
ret = s.call();
} else if (typeof s == 'object') {
for (p in s) {
ret += p + ':' + s[p] + ';';
}
} else if (typeof s == 'string') {
ret = s + ';';
}
return ret;
};

var itemKey = Ext.id(null, 'sbx-item'),
box = new Ext.ux.form.SuperBoxSelectItem({
owner: this,
renderTo: this.wrapEl,
cls: this.extraItemCls + ' ' + itemClass,
style: parseStyle(this.extraItemStyle) + ' ' + itemStyle,
caption: itemCaption,
display: itemDisplay,
value: itemVal,
key: itemKey,
listeners: {
remove: function(item) {
if (this.fireEvent('beforeremoveitem', this, item.value) === false) {
return;
}
this.items.removeKey(item.key);
if (this.removeValuesFromStore) {
if (this.usedRecords.containsKey(item.value)) {
this.store.add(this.usedRecords.get(item.value));
this.usedRecords.removeKey(item.value);
this.sortStore();
if (this.view) {
this.view.render();
}
}
}
this.fireEvent('removeitem', this, item.value);
},
destroy: function() {
this.collapse();
this.autoSize();
this.validateValue();
this.manageClearBtn();
},
scope: this
}
});

box.render();
box.hidden = this.el.insertSibling({
tag:'input',
type:'hidden',
value: itemVal,
name: (this.hiddenName || this.name)
}, 'before');

this.items.add(itemKey, box);
this.applyEmptyText();
this.autoSize();
this.validateValue();
this.manageClearBtn();
},

manageClearBtn : function() {
if (!this.renderFieldBtns) {
return;
}
var cls = 'x-superboxselect-btn-hide';
if (this.items.getCount() == 0) {
this.buttonClear.addClass(cls);
} else {
this.buttonClear.removeClass(cls);
}
},

findInStore : function(val) {
var index = this.store.find(this.valueField, val.trim());
if (index > -1) {
return this.store.getAt(index);
}
return false;
},

/**
* Returns a String value containing a concatenated list of item values. The list is concatenated with the {@link #Ext.ux.form.SuperBoxSelect-valueDelimiter}.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name getValue
* @return {String} a String value containing a concatenated list of item values.
*/
getValue : function() {
var ret = [];
this.items.each(function(item) {
ret.push(item.value);
});
return ret.join(this.valueDelimiter);
},

/**
* Returns an Array of item objects containing the {@link #Ext.ux.form.SuperBoxSelect-displayField}, {@link #Ext.ux.form.SuperBoxSelect-valueField} and {@link #Ext.ux.form.SuperBoxSelect-classField} properties.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name getValueEx
* @return {Array} an array of item objects.
*/
getValueEx : function() {
var ret = [];
this.items.each(function(item) {
var newItem = {};
newItem[this.valueField] = item.value;
newItem[this.displayField] = item.display;
newItem[this.classField] = item.cls;
ret.push(newItem);
});
return ret;
},

/**
* Sets the value of the SuperBoxSelect component.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name setValue
* @param {String} value a String value containing a concatenated list of item values. The list should be concatenated with the {@link #Ext.ux.form.SuperBoxSelect-valueDelimiter
*/
setValue: function(value) {
var values = value.split(this.valueDelimiter);

this.removeAllItems();
this.store.clearFilter();
this.resetStore();

Ext.each(values, function(val) {
var record;
if (record = this.findRecord(this.valueField, val)) {
this.addRecord(record);
}
}, this);

},

/**
* Sets the value of the SuperBoxSelect component, adding new items that don't exist in the data store if the {@link #Ext.ux.form.SuperBoxSelect-allowAddNewData} config is set to true.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name setValue
* @param {Array} data An Array of item objects containing the {@link #Ext.ux.form.SuperBoxSelect-displayField}, {@link #Ext.ux.form.SuperBoxSelect-valueField} and {@link #Ext.ux.form.SuperBoxSelect-classField} properties.
*/
setValueEx : function(data) {
this.removeAllItems();
this.store.clearFilter();
this.resetStore();

if (!Ext.isArray(data)) {
data = [data];
}
Ext.each(data, function(item) {
this.addItem(item);
}, this);
},

/**
* Returns true if the SuperBoxSelect component has a selected item with a value matching the 'val' parameter.
* @methodOf Ext.ux.form.SuperBoxSelect
* @name hasValue
* @param {Mixed} val The value to test.
* @return {Boolean} true if the component has the selected value, false otherwise.
*/
hasValue: function(val) {
var has = false;
this.items.each(function(item) {
if (item.value == val) {
has = true;
return false;
}
}, this);
return has;
},

onSelect : function(record, index) {
var val = record.data[this.valueField];

if (this.preventDuplicates && this.hasValue(val)) {
return;
}

this.setRawValue('');
this.lastSelectionText = '';

if (this.fireEvent('beforeadditem', this, val) !== false) {
this.addRecord(record);
}
if (this.store.getCount() == 0 || !this.multiSelectMode) {
this.collapse();
} else {
this.restrictHeight();
}
},

onDestroy : function() {
this.items.each(function(item) {
item.preDestroy(true);
}, this);

if (this.renderFieldBtns) {
Ext.destroy(
this.buttonClear,
this.buttonExpand,
this.buttonWrap
);
}

Ext.destroy(
this.inputEl,
this.wrapEl,
this.outerWrapEl
);

Ext.ux.form.SuperBoxSelect.superclass.onDestroy.call(this);
},

autoSize : function() {
if (!this.rendered) {
return;
}
if (!this.metrics) {
this.metrics = Ext.util.TextMetrics.createInstance(this.el);
}
var el = this.el,
v = el.dom.value,
d = document.createElement('div');

if (v === "" && this.emptyText && this.items.getCount() < 1) {
v = this.emptyText;
}
d.appendChild(document.createTextNode(v));
v = d.innerHTML + " ";
d = null;
var w = Math.max(this.metrics.getWidth(v) + 24, 24);
if (typeof this._width != 'undefined') {
w = Math.min(this._width, w);
}
this.el.setWidth(w);

if (Ext.isIE) {
this.el.dom.style.top = '0';
}
}
});
Ext.reg('superboxselect', Ext.ux.form.SuperBoxSelect);

/*
* @private
*/
Ext.ux.form.SuperBoxSelectItem = function(config) {
Ext.apply(this, config);
Ext.ux.form.SuperBoxSelectItem.superclass.constructor.call(this);
};

/*
* @private
*/
Ext.ux.form.SuperBoxSelectItem = Ext.extend(Ext.ux.form.SuperBoxSelectItem, Ext.Component, {
initComponent : function() {
Ext.ux.form.SuperBoxSelectItem.superclass.initComponent.call(this);
},

onElClick : function(e) {
this.owner.clearCurrentFocus();
this.owner.collapse();
if (this.owner.navigateItemsWithTab) {
this.focus();
} else {
this.owner.el.focus();
(function() {
this.onLnkFocus();
this.owner.currentFocus = this;
}).defer(10, this);
}
},

onLnkClick : function(e) {
if (e) {
e.stopEvent();
}

this.preDestroy();

if (!this.owner.navigateItemsWithTab) {
this.owner.el.focus();
}
},

onLnkFocus : function() {
this.owner.outerWrapEl.addClass(this.owner.focusClass);

this.el.addClass("x-superboxselect-item-focus");
},

onLnkBlur : function(e) {
this.owner.outerWrapEl.removeClass(this.owner.focusClass);

this.el.removeClass("x-superboxselect-item-focus");
},

enableElListeners : function() {
this.el.on('click', this.onElClick, this, {stopEvent:true});
this.el.addClassOnOver('x-superboxselect-item x-superboxselect-item-hover');
},

enableLnkListeners : function() {
this.lnk.on({
click : this.onLnkClick,
focus : this.onLnkFocus,
blur : this.onLnkBlur,
scope : this
});
},

enableAllListeners : function() {
this.enableElListeners();
this.enableLnkListeners();
},

disableAllListeners : function() {
this.el.removeAllListeners();
this.lnk.removeAllListeners();
},

onRender : function(ct, position) {
Ext.ux.form.SuperBoxSelectItem.superclass.onRender.call(this, ct, position);

if (this.el) {
this.el.remove();
}

this.el = ct.createChild({ tag: 'li' }, ct.last());
this.el.addClass('x-superboxselect-item');

var btnEl = this.owner.navigateItemsWithTab ? (Ext.isSafari ? 'button' : 'a') : 'span';

Ext.apply(this.el, {
focus: function() {
this.down(btnEl + '.x-superboxselect-item-close').focus();
},

preDestroy: this.preDestroy
});

this.enableElListeners();

this.el.update(this.caption);

var cfg = {
tag: btnEl,
cls: 'x-superboxselect-item-close',
tabIndex : this.owner.navigateItemsWithTab ? '0' : '-1'
};
if (btnEl === 'a') {
cfg.href = '#';
}
this.lnk = this.el.createChild(cfg);


if (this.disabled) {
this.disableAllListeners();
} else {
this.enableLnkListeners();
}

this.on({
disable : this.disableAllListeners,
enable : this.enableAllListeners,
scope : this
});

this.setupKeyMap();
},

setupKeyMap : function() {
this.keyMap = new Ext.KeyMap(this.lnk, [{
key: [
Ext.EventObject.BACKSPACE,
Ext.EventObject.DELETE,
Ext.EventObject.SPACE
],
fn: function() {
if (this.fireEvent('remove', this) !== false) {
this.preDestroy();
this.on('expand', this.collapse, this, {single: true});
}
}.createDelegate(this)
}, {
key: [
Ext.EventObject.RIGHT,
Ext.EventObject.DOWN
],
fn: this.moveFocus.createDelegate(this, ['right'])
}, {
key: [
Ext.EventObject.LEFT,
Ext.EventObject.UP
],
fn: this.moveFocus.createDelegate(this, ['left'])
}, {
key: Ext.EventObject.HOME,
fn: function() {
this.owner.items.get(0).el.focus();
}.createDelegate(this)
}, {
key: Ext.EventObject.END,
fn: function() {
this.owner.el.focus();
}.createDelegate(this)
}]);

this.keyMap.stopEvent = true;
},

/*
* @private
*/
moveFocus : function(dir) {
var el = this.el[dir == 'left' ? 'prev' : 'next']() || this.owner.el;

el.focus();
},

/*
* @private
*/
preDestroy : function(suppressEffect) {
if (this.fireEvent('remove', this) === false) {
return;
}

var actionDestroy = function() {
if (this.owner.navigateItemsWithTab) {
this.moveFocus('right');
}
this.hidden.remove();
this.hidden = null;
this.destroy();
};

if (suppressEffect) {
actionDestroy.call(this);
} else {
this.el.hide({
duration: .2,
callback: actionDestroy,
scope: this
});
}
return this;
},

onDestroy : function() {
Ext.destroy(
this.lnk,
this.el
);

Ext.ux.form.SuperBoxSelectItem.superclass.onDestroy.call(this);
}
});


notes:

renamed the newitemdata event to newitem for consistency
cleaned up all unintentional global vars
removed all unused private vars
added onFocus() and onBlur() methods (resolves issue reported by @radtad in post #52)
collapsed multiple var declarations where possible
corrected copy-paste errors in SuperBoxSelect config descriptions
implemented Ext.destroy() where possible to reduce code
where possible, removed anonymous function wrappers used in calls to createDelegate()
added focusClass (i.e. light blue border) when any items are selected
fixed blur issue mentioned by @stever (and others too) in post #41


HTH. :)

[edit]
p.s. i didn't highlight the changes i made 'cos i'd end up highlighting most of the code.

p.s.s. i'm currently experimenting with removing all the wonky .defer() calls. imho they're unreliable and should be removed where possible -- testing in Firefox 3.0.11 and Chrome thus far hasn't revealed any problems yet.

p.s.s.s. @danh2000: feel free to rip the code. and thanks for a great working base!

danh2000
24 Jun 2009, 2:25 AM
had a need for this ux, so i took the liberty of cleaning up the code:
...

HTH. :)

[edit]
p.s. i didn't highlight the changes i made 'cos i'd end up highlighting most of the code.

p.s.s. i'm currently experimenting with removing all the wonky .defer() calls. imho they're unreliable and should be removed where possible -- testing in Firefox 3.0.11 and Chrome thus far hasn't revealed any problems yet.

p.s.s.s. @danh2000: feel free to rip the code. and thanks for a great working base!

Thanks Marc! I've been snowed under recently, so this helps loads!

I've made a few changes myself recently, but not to the extent that you did - The joys of community code :)

I haven't looked properly yet, but I'll look over this later in the week and see if/what I need to merge and I'll release again. I'm also toying with a rows option which enables the component to display X rows of items and scrolls them internally instead of the current growing field.

Thanks again and please keep me posted if you do any more :)

mystix
24 Jun 2009, 2:47 AM
Thanks again and please keep me posted if you do any more :)

will do :)

p.s. if you do update your initial post with the code i posted let me know and i'll remove my code to avoid any possible confusion.

mystix
24 Jun 2009, 5:56 PM
just read the 3.x thread for this extension -- one thing i forgot to mention is that i only tested this with the latest 2.x code from SVN. i've yet to test it on the 3.x SVN branch.

danh2000
24 Jun 2009, 6:45 PM
just read the 3.x thread for this extension -- one thing i forgot to mention is that i only tested this with the latest 2.x code from SVN. i've yet to test it on the 3.x SVN branch.

No worries - I'll do some heavy testing this week when I integrate everything. I only had a very quick look this morning.

mystix
25 Jun 2009, 7:13 PM
i found the surface area of the 'X' icon too small for easy targetting, so i tweaked one of the rules a little:


.x-superboxselect-item-close {
background:url(../images/close.png) no-repeat scroll left 0;
border:none;
cursor:default;
font-size:1px;
height:8px;
position:absolute;
right:-1px;
top:7px;
width:13px;
display:block;
padding:0;
}

that makes the 'X' icon start from the right edge of the SelectItem instead.
couldn't increase the height of the image to touch the top and bottom edges of the SelectItem though cos your sprites were too snug. :(

danh2000
25 Jun 2009, 7:21 PM
i found the surface area of the 'X' icon too small for easy targetting
...


Yep, I hear you - I'm going to change the structure of the items a little actually, so I'll address this then.

Thanks again.

danh2000
26 Jun 2009, 12:58 AM
Marc,

I'm currently working through merging everything - I just have a quick question for you:

I think there were a couple of similar occurences but I'll use this an example:

Probably trivial, but in my original code for the addRecord method, I had the following:



this.addItemBox(val,display,caption,cls,style);
this.fireEvent('additem',this,val);


You had reversed this to:



this.fireEvent('additem',this,val);
this.addItemBox(val,display,caption,cls,style);


My thinking was that the value should be added prior to firing the event because I see it as an 'after' event in which the subscriber should have access to the newest value of the component if needed. (I hope that makes sense)

What was your reasoning for reversing the order - do you have an alternate viewpoint?

Thanks,

Dan

mystix
26 Jun 2009, 1:12 AM
i think that's the only instance where i reversed it -- purely accidental :">

my bad.

danh2000
26 Jun 2009, 1:22 AM
i think that's the only instance where i reversed it -- purely accidental :">

my bad.

No problem!

With the possibilty of embarrassing myself (but who cares!) - I'd never noticed the Ext.destroy method and have always removed listeners and elements manually - Thanks!

There was something else that I noticed earlier when paging through the code (which I'll no doubt get to again soon) which made me think - "ooh that's new to me!"

It's really refreshing having someone else collaborate on my code - Thanks again :)

mystix
26 Jun 2009, 1:33 AM
There was something else that I noticed earlier when paging through the code (which I'll no doubt get to again soon) which made me think - "ooh that's new to me!"

It's really refreshing having someone else collaborate on my code - Thanks again :)


my pleasure :D

p.s. while refactoring, i was thinking of making the SuperBoxSelect inherit from TwinTriggerField instead of Combo. seemed a waste to forego the built-in triggers just to create 2 triggers which wouldn't grow with the Field. thoughts? :-?

danh2000
27 Jun 2009, 1:35 AM
I've just updated this component..

New Fully Supported Combo Features:
- Ability to applyTo an existing element.
- Ability to transform an existing HTML Select.

Bug Fixes and Code Tidy Up (A big contribution from Mystix - Many Thanks).

The attachment has been updated as have the example pages (linked in the first post here (http://extjs.com/forum/showthread.php?p=332654)).

@Mystix, Apart from the new features there are a couple of bug fixes so you'll probably want to grab this version.

Re. TwinTriggerField - A definite consideration for a future/next version - I do want to change some of the structure so I'll see how TTF fits.

galdaka
27 Jun 2009, 2:32 AM
Excellent work.

Some problems in IE6.


Greetings,

danh2000
27 Jun 2009, 2:48 AM
...
Some problems in IE6.
...


Thanks for the report - I'll look into it.

mystix
27 Jun 2009, 6:25 AM
yay! new release!

p.s. should i remove the code i posted?
p.s.s. did you forget to update the 3.x thread for this ux?

mystix
27 Jun 2009, 7:06 AM
imho it would be clearer if the cursor for the 'X' icon was a pointer as opposed to an arrow:


.x-superboxselect-item-close {
background:url(close.png) no-repeat scroll left 0;
border:none;
cursor:pointer;
font-size:1px;
height:8px;
position:absolute;
right:-1px;
top:7px;
width:13px;
display:block;
padding:0;
}


p.s. any chance of increasing the vertical spacing in the 'X' icon sprite so we could make the 'X' icon cover the full height of the SelectBoxItem for easier mouse targetting?

[edit]
also found the following bugs:

in the private parseStyle() method:


var parseStyle = function(s){
var ret = '';
if(typeof s == 'function'){
ret = s.call();
}else if(typeof s == 'object'){
for(var p in s){ // missing var declaration
ret+= p +':'+s[p]+';';
}
}else if(typeof s == 'string'){
ret = s + ';';
}
return ret;
};


in the setupKeyMap() method:


key: [Ext.EventObject.HOME],
fn: function() {
var l = this.owner.items.get(0); // missing var declaration
l.el.focus();
}.createDelegate(this)


in the onKeyDownHandler() method, the final return; statement is redundant.

danh2000
27 Jun 2009, 3:08 PM
Thanks Mystix and Galdaka for bug reports and requests.

The new update contains:

Fixed IE6 display issue with applyTo and transform.
Fixed a couple of dodgy non var'd variables.
Increased 'close button' target size and changed cursor to pointer.

Thanks,

Dan

mystix
27 Jun 2009, 10:44 PM
found a self-correcting bug in the latest css rule for .x-superboxselect-item-close
-- the cursor:default rule wasn't removed, but is overridden later by the cursor:pointer rule.

might want to remove that in the next release. ;)

danh2000
28 Jun 2009, 12:36 AM
found a self-correcting bug in the latest css rule for .x-superboxselect-item-close
-- the cursor:default rule wasn't removed, but is overridden later by the cursor:pointer rule.

might want to remove that in the next release. ;)

I'm going to start calling you HawkEye!

Thanks.

:)

galdaka
28 Jun 2009, 3:06 AM
The zip in first post still not work in IE6 (onRender fails ext-all-debug.js) and now have strange css issues in FF2.

Greetings,

danh2000
28 Jun 2009, 3:28 AM
The zip in first post still not work in IE6 (onRender fails ext-all-debug.js) and now have strange css issues in FF2.

Greetings,

I've just tried IE6 - no problems here - can you ellaborate? anyone else having problems?

The code at the following url's is/should be the same version - do you have the same problems here:

http://technomedia.co.uk/SuperBoxSelect/examples.html
http://technomedia.co.uk/SuperBoxSelect/examples3.html

I haven't tested with FF2 - it's an unsupported browser with an incredibly low percentage of users - if you have a real need to support it, the issues could probably be fixed if I knew what they were.

Thanks,

Dan

mystix
28 Jun 2009, 4:32 AM
I'm going to start calling you HawkEye!

Thanks.

:)

it pays to have a good IDE ;)
(tried IntelliJ IDEA 8 yet?)

galdaka
28 Jun 2009, 10:19 AM
I've just tried IE6 - no problems here - can you ellaborate? anyone else having problems?

The code at the following url's is/should be the same version - do you have the same problems here:

http://technomedia.co.uk/SuperBoxSelect/examples.html
http://technomedia.co.uk/SuperBoxSelect/examples3.html

I haven't tested with FF2 - it's an unsupported browser with an incredibly low percentage of users - if you have a real need to support it, the issues could probably be fixed if I knew what they were.

Thanks,

Dan

I tried with old example in local. With new example all OK.

Excellent work!!

Greetings,

danh2000
29 Jun 2009, 3:39 PM
@mystix,

I've never tried 'IntelliJ IDEA 8' - I've always used Eclipse. I'll have a look though - thanks.

@galdaka,

Thanks for trying again and reporting back :)

galdaka
2 Jul 2009, 1:22 AM
Hi,

Fully integrated in my xtheme-gray-extend. Awesome extension!!

Greetings,

danh2000
2 Jul 2009, 1:46 AM
Hi,

Fully integrated in my xtheme-gray-extend. Awesome extension!!

Greetings,

It looks fantastic in gray - well done! and glad you like it :)

MarkBOneSmart
2 Jul 2009, 7:40 PM
IE 7 but probably all IE:
When a SuperBoxSelect is drawn on a tab, the first onResize fails because the w isNaN .. Here is my modified code.


onResize : function(w, h, rw, rh) {
var reduce = Ext.isIE6 ? 4 : Ext.isIE7 ? 1 : Ext.isIE8 ? 1 : 0;
if (isNaN(w)) {
//Control not rendered
} else {
this._width = w;
if (this.outerWrapEl) {
this.outerWrapEl.setWidth(w - reduce);
if (this.renderFieldBtns) {
reduce += (this.buttonWrap.getWidth() + 20);
this.wrapEl.setWidth(w - reduce);
}
Ext.ux.form.SuperBoxSelect.superclass.onResize.call(this, w, h, rw, rh);
this.autoSize();
}
}
},

On BasicForm.Load, if the store is not populated, setValue blows out the store value. I decided to use the allowAddNewData functionality so that the control at least doesn't delete the value until the store does get populated.


setValue: function(value){
var values = value.split(this.valueDelimiter);
this.removeAllItems().resetStore();

Ext.each(values,function(val){
var record = this.findRecord(this.valueField, val);
if(record){
this.addRecord(record);
} else if (this.allowAddNewData) {
var item = new Object;
item[this.valueField] = val;
item[this.displayField] = val;

this.addItem(item);
}
},this);

},
The most severe problem is that when doing a load, I loose the ability to open the drop down via the drop button BUT the down arrow still works and the hold left click near the last item will also bring the list down as long as the left mouse button is clicked.

From tracing, it seems that it goes into the function twice and self closes. I'm stuck on that one.




[edit]
Figured out my last issue ..


this.buttonExpand.addClassOnOver('x-superboxselect-btn-over').on('click', function(e) {
e.stopEvent();
if (this.disabled) {
return;
}
if (this.isExpanded()) {
return;
//this.multiSelectMode = false;
} else if (this.pinList) {
this.multiSelectMode = true;
}
this.onTriggerClick();
}, this);


It seems that the the click event was being called multiple times - so the first click would show the drop down and then the second click would close it. The reason it worked on the demo was the click was being called 3 times, so it was remaining open.

Test code .. yeah .. its so nested in my little application, but here is me loading the SuperBoxSelect after a BasicForm.Load



var cmb = Ext.getCmp('cmb_Skill');
if (cmb) { if (JSON.Skill) { var JSONrec = JSON.Skill; if (cmb) cmb.store.loadRecords(cmb.store.reader.readRecords(JSONrec),false); } cmb.setDisabled(!JSON.Skill); if (clearValues) cmb.reset(); else {
var cmbV = cmb.getValue();
cmb.lastSelectionText = cmbV;
if(cmb.hiddenField){
cmb.hiddenField.value = cmbV;
}
cmb.setValue( cmbV );
}}


My SuperBoxSelect ..


{xtype:'superboxselect', id:'cmb_Skill', name:'cmb_Skill', hiddenName:'Skill', fieldLabel:'Skill', allowBlank:false,mode:'local',displayField:'Skillname' ,valueField:'Skillvalue',store: new Ext.data.SimpleStore({fields:['Linkvalue','Skillvalue','Skillname'], data:MyArea.BLANK}) , lastQuery:''}

mystix
2 Jul 2009, 7:43 PM
@MarkBOneSmart, you should probably post the test code you used so everyone else can carry on debugging from where you left off.

danh2000
2 Jul 2009, 8:31 PM
@MarkBOneSmart Thanks for reporting the problems, but I'm on a deadline at the moment and it will take some time to setup a test environment to replicate what you are doing. Unless you have a public facing demo that I can debug it will take me a few days before I can respond.

Cheers,

Dan

kveeiv
10 Jul 2009, 9:58 AM
This is a great component!

I've found it helpful to also be able to pass in an array of values to setValue (instead of having to join() just for the value to be re-split()), so I made the following change:

setValue: function(value){
var values = Ext.isArray(value) ? value : ((typeof value == "string") ? value.split(this.valueDelimiter) : []);
this.removeAllItems().resetStore();
....

danh2000
14 Jul 2009, 8:34 PM
This is a great component!


Thanks.



I've found it helpful to also be able to pass in an array of values to setValue (instead of having to join() just for the value to be re-split()), so I made the following change:

setValue: function(value){
var values = Ext.isArray(value) ? value : ((typeof value == "string") ? value.split(this.valueDelimiter) : []);
this.removeAllItems().resetStore();
....



I imagined that most people would use the same format as returned by getValue, which is a delimited string (ie. What comes out goes back in), I have included this though as it may help those who split the values into an array.

danh2000
14 Jul 2009, 8:41 PM
I've just updated the first post with a new version containing:


-Fixed a couple of bugs that occured when using setValue when the component had not been rendered (eg. hidden tab).
-Enabled setValue to accept either an array of values or a delimited string.

radtad
17 Jul 2009, 2:21 PM
form enabled (everything seems fine, but it won't do addItem)...


this.buttonClear is undefined
this.buttonClear.addClassOnOver('x-superboxselect-btn-over') I can't re-create this - I've set disabled to false and used addItem without issues.

If you are still having problems, please post a link to a working example, or copy and paste code that I can use to reproduce the error.

Thanks again,

This happens on a call to initButtonEvents (within onEnable). I think the following code for that should read :



onEnable: function(){
Ext.ux.form.SuperBoxSelect.superclass.onEnable.call(this);
this.items.each(function(item){
item.enable();
});
if(this.renderFieldBtns){
this.initButtonEvents();
}
},

danh2000
17 Jul 2009, 2:43 PM
@radtad

You are correct - thanks for the report.

arconen
23 Jul 2009, 1:49 AM
Please help me :-?

Then I try to use transform feature in IE8 (maybe for all from IE6) for SELECT tags, I'll receive the next one:

Object doesn't support this property or method

in next construction


var N=R.ownerDocument.createRange();
on ext-all.js (ExtJS 2.2)

- Try to use component like this:


SelectDepartmentID = new Ext.ux.form.SuperBoxSelect({
transform: 'DepartmentID',
allowBlank: false,
resizable: true,
name: 'DepartmentID',
width: 500,
displayField: 'text',
valueField: 'value',
classField: 'cls',
styleField: 'style',
extraItemCls: 'x-flag',
extraItemStyle: 'border-width:2px',
stackItems: false
});


<select id="DepartmentID" multiple size=5" onchange="frm.submit()">
<option value="value0" selected>text0</option>
<option value="value1">text1</option>
<!-- and more option in this place -->
<option value="valueN">textN</option>
</select>
- Try to expand the SuperSelectBox on the page after rendering it
- And now I receive this error.
Also reproducing then I try to select one of the items from the list

What can I do for fix this? Or this is a bug?

arconen
23 Jul 2009, 5:32 AM
Question are closed. Sorry

gianpaulo
30 Jul 2009, 9:44 PM
It would be good to add token searching config. Just like facebook. :D

danh2000
30 Jul 2009, 11:32 PM
It would be good to add token searching config. Just like facebook. :D

Thanks for the suggestion, but I've never used Facebook - can you elaborate on what token searching means?

Thanks,

Dan

qooleot
3 Aug 2009, 2:16 PM
First off, very nice widget! I found two small issues, however, that might cause others issues when first starting out:

1) You mention allowNewData in the notes for example 2, but its really allowAddNewData in the example.

2) For example 2, the store fields seem to be required to be ['id','name']. If I change the store fields 2 index to 'test' instead of 'name' and the displayField to 'test' from 'name' for the superboxselect, then type in a new value (selecting one from the pulldown works fine), then the text is not displayed.

I was able to work past those, so no worries, but just a heads up. Keep up the good work!

danh2000
3 Aug 2009, 3:13 PM
First off, very nice widget! I found two small issues, however, that might cause others issues when first starting out:

1) You mention allowNewData in the notes for example 2, but its really allowAddNewData in the example.


Yes I changed the name from a previous version - I'll update the text on the example page, Thanks!



2) For example 2, the store fields seem to be required to be ['id','name']. If I change the store fields 2 index to 'test' instead of 'name' and the displayField to 'test' from 'name' for the superboxselect, then type in a new value (selecting one from the pulldown works fine), then the text is not displayed.


I think you've misunderstood how it works - you can use any field names you want, but if you are changing the field names you must also change the 'newitem' callback to use the same.

Thanks for the feedback,

Dan

MH61
19 Aug 2009, 10:57 AM
I'm using this extension on a wizard. I need 2 fields, Principal Investigator, and Co-Investigators. both work from the same ds, and no item can appear in both fields. Superbox select is perfect for this since it removes items from the store.

A few things i want to achieve:
-Principal Investigator should be single select, and for the most part look like a standard combo except for ability to delete selection
-Co-Investigators should be a set height, and once the items exceed the height it the box should be scrollable instead of growing

How can i achieve this. thanks

akannu
19 Aug 2009, 1:27 PM
Dan,
we are experimenting with this control and like it so far. If we use the stackItems config and have one entry per row, can we also have drag and drop? We have one need where the order is important. I was thinking d&d is the easier way without adding up/down icons to the screen. Is it doable?

danh2000
19 Aug 2009, 3:03 PM
Principal Investigator should be single select, and for the most part look like a standard combo except for ability to delete selection


A forceSingleSelection config wouldn't be too difficult to add, I'll add it to the list of features to add. Combined with renderFieldBtns: false I believe this would give you what you need.



-Co-Investigators should be a set height, and once the items exceed the height it the box should be scrollable instead of growing.

This will be a bit more work - I was going to add this functionality but stopped when I realised it would be a bigger job than I anticipated - I'd have to re-write some of the existing code and change the structure of how items are rendered.

I'd still like to do this, but it's going to be sat at the bottom of the pile whilst competing with paid work or until I have a need for the functionality myself.

danh2000
19 Aug 2009, 3:08 PM
Dan,
we are experimenting with this control and like it so far. If we use the stackItems config and have one entry per row, can we also have drag and drop? We have one need where the order is important. I was thinking d&d is the easier way without adding up/down icons to the screen. Is it doable?

I would think it's achievable, but it isn't high on my priority list and I'm afraid it's likely to stay that way whilst I'm busy with other jobs. I'll add a To-Do item to look into this when/if other work calms down a bit.

MH61
20 Aug 2009, 6:01 AM
A forceSingleSelection config wouldn't be too difficult to add, I'll add it to the list of features to add. Combined with renderFieldBtns: false I believe this would give you what you need.


Thanks, I'll give this a try

Edit: I added the forceSingleSelect config, and edited addItemBox so that the first action it performs is:



if(this.forceSingleSelection){
this.removeAllItems();
};


I'm sure this isn't the best way since I'm a novice at this, but it works for me - each selection will replace the previous selection - works well with pinList: false.

However this still will expand the box thinking that a second item will be added, so i need to find out how to stop this bit from happening when this config is set to true. but as i said before i don't understend how this is happening so i guess i can't do anything to stop it

I tried renderFieldBtns: false but this removes both buttons... but i do still want the drop down button, i just want it to look the same as the standard drop down button, and i'd like the box to look like a standard combo (as this one has a little more padding in the height), can i just add a cls config for this? i'm terrible with css. Actually i guess there would be no harm in this looking exactly the same as a regular combo box, i probably don't even need the X next to the added item.



This will be a bit more work - I was going to add this functionality but stopped when I realised it would be a bigger job than I anticipated - I'd have to re-write some of the existing code and change the structure of how items are rendered.

I'd still like to do this, but it's going to be sat at the bottom of the pile whilst competing with paid work or until I have a need for the functionality myself.


I was trying to do this myself, but i couldn't actually figure out what is making the field expand. can you please point me in the right direction and hopefully i can create a workaround for myself

thanks

imran
21 Aug 2009, 7:00 AM
Great extension!

I would suggest improving the renderFieldBtns property to accept an Object like: {"expand":true, "clear":false}

This would allow greater control for folks who would like to show one icon and not the other. Currently it's either all or nothing.

danh2000
22 Aug 2009, 12:09 AM
I was trying to do this myself, but i couldn't actually figure out what is making the field expand. can you please point me in the right direction and hopefully i can create a workaround for myself

If you look at the structure, it's just an unordered list wrapped in a couple of divs - it grows to accomodate the child list items.


I'll add scrolling to a future version when I have time, but if you want to jump in yourself...

The basic approach would be to wrap the UL element in a fixed height div with overflow or oveflow-y set to auto. This is easy enough to achieve, but the structure of the list items and the delete buttons will likely need to change to accomodate for focusing elements that are outside of the scrollable viewport..... you'll have to try it to see what I mean.


Great extension!

I would suggest improving the renderFieldBtns property to accept an Object like: {"expand":true, "clear":false}

This would allow greater control for folks who would like to show one icon and not the other. Currently it's either all or nothing.

That's might be a good idea - I'll could add the ability to overload the config and use boolean or an object. It is currently achievable with css though:


.x-superboxselect-btn-clear {
display: none;
}

And


.x-superboxselect-btn-expand {
display: none;
}

qooleot
31 Aug 2009, 12:46 PM
Edit: A print function turns out to be a bad idea, read next post down to add CSS to make the widget more printer-friendly.

It seems printing a page with a superboxselect makes the data appear pretty funny. Just go to the example page and hit print. You get the input textbox at the end and its lined up vertically in a list. Firefox vs IE printing is not consistent.

I was thinking about creating a printFormat() function that hides the superboxselect and puts a normal comma separated text list in the place, but I wanted to see if:

1) has anyone already solved this problem
2) anyone have a better idea?

Thanks!

qooleot
31 Aug 2009, 1:38 PM
Ok I got the printing to behave much better by adding this CSS:



@media print {
.x-superboxselect {
padding: 1px !important;
margin: 1px !important;
overflow: auto !important;
}

.x-superboxselect-display-btns {
padding: 1px !important;
margin: 1px !important;
overflow: auto !important;
}

.x-superboxselect ul {
list-style: none;
overflow: auto !important;
}

.x-superboxselect ul li {
float:left;
padding-left: 1px !important;
text-align: left;
overflow: auto !important;

}
.x-superboxselect-input{
display: none;
}
}

stever
1 Sep 2009, 3:23 PM
Is there a better download location? I get unsetDelayCheck is undefined errors.

danh2000
1 Sep 2009, 3:38 PM
Is there a better download location? I get unsetDelayCheck is undefined errors.

I've just downloaded it myself and uploaded it here:

http://www.technomedia.co.uk/SuperBoxSelect/SuperBoxSelect.zip

This is the same version as attached to the first post as I don't have the source here.

Expect a new version within the next 7 or 10 days.

danh2000
1 Sep 2009, 3:39 PM
Ok I got the printing to behave much better by adding this CSS:
...


I haven't had a need to print (yet), but I may do in future. Thanks for posting.

stever
1 Sep 2009, 4:55 PM
I've just downloaded it myself and uploaded it here:

http://www.technomedia.co.uk/SuperBoxSelect/SuperBoxSelect.zip

This is the same version as attached to the first post as I don't have the source here.

Expect a new version within the next 7 or 10 days.

I added:


unsetDelayCheck: function(){
this.delayedCheck=false;
}

To make parts of it work. What is delayedCheck?

danh2000
1 Sep 2009, 5:37 PM
I added:


unsetDelayCheck: function(){
this.delayedCheck=false;
}

To make parts of it work. What is delayedCheck?

You don't make it clear what 'parts' they were, but your method above is overriding ComboBox not SuperBoxSelect.

delayedCheck comes from ComboBox to prevent the 'specialkey' event firing to work around an Enter key issue - although I'm not sure exactly what that issue is.

mystix
1 Sep 2009, 6:37 PM
You don't make it clear what 'parts' they were, but your method above is overriding ComboBox not SuperBoxSelect.

delayedCheck comes from ComboBox to prevent the 'specialkey' event firing to work around an Enter key issue - although I'm not sure exactly what that issue is.

that no longer exists in SVN 'cos it's no longer required.

substantial refactorings were carried out in recent weeks to resolve editorgrid / editor / field issues, and most of the funky delayed stuff for combos were removed in the process.

danh2000
1 Sep 2009, 7:06 PM
Thanks @mystix.

I'll have to branch a new version when those changes get out - do you think it's likely to be a support/maintenance release or the next larger point version?

I don't want to maintain 2 codebases (especially for the remote store compatability that I'm working on this week), so I'll have to test the extent of the changes and hope to accomodate 2 and 3 pre and post this change.

mystix
1 Sep 2009, 10:31 PM
the changes are already in the 3.0.1 maintenance release. :)

danh2000
2 Sep 2009, 8:56 PM
Updated the first post (http://extjs.com/forum/showthread.php?p=332654) with a new version containing:

A few minor bug fixes and a maintenance release to make compatible with Ext 3.0.1

MarkB
3 Sep 2009, 3:17 AM
Is this the new version that was mentioned a couple of posts back or is there another 'update' coming in 5-8 days?

danh2000
3 Sep 2009, 3:47 AM
it's just a maintenance release - I'm currently working on the remote store.

MarkB
3 Sep 2009, 7:39 AM
This makes me very happy ...

mystix
3 Sep 2009, 7:41 AM
This makes me very happy ...

quick, buy him a beer. ~o)

danh2000
3 Sep 2009, 7:47 PM
quick, buy him a beer. ~o)

I'll need a beer when I've finished this.


This makes me very happy ...

Then I may PM you if you fancy helping with some private early beta testing...?

swarnendude
4 Sep 2009, 9:55 AM
Awesome work man!! Thank you very much for sharing!!

nadim
4 Sep 2009, 6:56 PM
I am using a few of these superboxselects inside a fieldset within a form.

When I add items and run getValues() everything works as expected. When I remove items, the removed items still show up in getValues. Any suggestions?

-N

nadim
4 Sep 2009, 7:04 PM
Here is how I am using it:

var wdCombo = new Ext.ux.form.SuperBoxSelect({
id: 'wd',
displayField: 'description',
emptyText: '(All...)',
fieldLabel: 'wd',
name: 'wd',
mode: 'local',
store: jsonwdStore,
triggerAction: 'all',
valueField: 'pk',
width: 213,
listeners: {
additem: a_func,
removeitem: a_func
}

both a_func is the same function and called for both events. When I remove something, a_func calls getValues() and still sees old values present in the list.

danh2000
4 Sep 2009, 7:10 PM
Hi Nadim,

I've just tested this and everything works as expected using Ext 2.2.1 - Ext 3.0.1

When did you download the SBS component - is it possible that you have an old version of the code that has since been fixed?

If you are still having issues, please post an isolated test case that I can copy and paste, and some instructions about how to re-produce the error. Also please let me know the browsers tested and the version of Ext you are using.

Thanks,

Dan

nadim
4 Sep 2009, 7:14 PM
I downloaded it within the last week, i'm working on isolating it right now. If I find the problem on my own I will post back here.

-N

danh2000
4 Sep 2009, 7:18 PM
Here's what I just tried:



removeitem: function(sbs,v){
console.log(sbs.getValue());
}


I'd like to know what your listener looks like - I'll take a look when you post a test case.

Thanks.

danh2000
4 Sep 2009, 7:26 PM
I've found a problem when using BasicForm.getValues() in the listener - I guess you were using this too?

If this is the case, don't worry about the test case.

nadim
4 Sep 2009, 7:35 PM
yes that's what i'm using.

ignoring the test case.

thx.

danh2000
4 Sep 2009, 7:51 PM
Thanks for the report - I'm posting a new version within the next 24 or 48 hours - this will include bug fixes and remote store support.

Thanks again,

Dan

nadim
6 Sep 2009, 10:12 AM
I'm using getFieldValues() for now - it seems to work just fine.

-N

danh2000
6 Sep 2009, 11:20 PM
UPDATE 07/09/2009

*NEW* Remote compatability - you are no longer limited to a local store!
Multiple bug fixes (many browser version specific).

Updated the First Post (http://extjs.com/forum/showthread.php?p=332654) and uploaded new attachment (http://www.extjs.com/forum/attachment.php?attachmentid=16094).
----------------------------------------------------------------------

Please see the new example page (http://www.technomedia.co.uk/SuperBoxSelect/examplesRemote.html) for 2 remote store demo's.

Note. There are still a few small refactorings that I would like to do, but I'm primarily concerned with getting bug reports and some feedback on the remote functionality as I work towards releasing the current features as a stable version 1 release.

Thanks,

Dan

boonkerz
7 Sep 2009, 5:05 AM
Special Thanks really nice extension.

mratzloff
10 Sep 2009, 12:30 PM
UPDATE 07/09/2009

*NEW* Remote compatability - you are no longer limited to a local store!
Multiple bug fixes (many browser version specific).

Updated the First Post (http://extjs.com/forum/showthread.php?p=332654) and uploaded new attachment (http://www.extjs.com/forum/attachment.php?attachmentid=16094).
----------------------------------------------------------------------

Please see the new example page (http://www.technomedia.co.uk/SuperBoxSelect/examplesRemote.html) for 2 remote store demo's.

Note. There are still a few small refactorings that I would like to do, but I'm primarily concerned with getting bug reports and some feedback on the remote functionality as I work towards releasing the current features as a stable version 1 release.

Thanks,

DanDan, you rock! This is a great component. I was using a ScriptTagProxy to get around the remote problems, but I was able to remove all that and use a simple JsonStore now.

danh2000
10 Sep 2009, 3:47 PM
@boonkerz - thanks for the feedback.

@mratzloff - I presume then that everything's working well for you - thanks for posting - that's good to hear.

:D

mratzloff
11 Sep 2009, 7:19 AM
@mratzloff - I presume then that everything's working well for you - thanks for posting - that's good to hear.It is, thanks. I have a couple of relatively simple suggestions for the component, though.

* Add an addItems({Array<Object>}) method that calls addItem() for each object in an array.



Ext.ux.form.SuperBoxSelect.prototype.addItems = function(items) {
if (Ext.isArray(items)) {
Ext.each(items, function(item) {
this.addItem(item);
}, this);
} else {
this.addItem(items);
}
};


* When you clear the box, it should fire a removeallitems event, and there should be a config parameter for whether or not you want removeAllItems() to fire the removeitem event. Here's the problem: say I have an alert box that pops up for every deleted item: "Are you sure you want to delete this item?" The removeAllItems() method makes this alert appear for every item in the box--very inconvenient. (You might respond that I should not have an alert box appear, but the data I'm using for this is more comprehensive than simple text tags. It's mapping complex objects together, and in this case deletes should happen rarely.)

* Split up the renderFieldBtns option into separate configs for each button. For a remote store with thousands of items, the drop-down button doesn't really make sense.

Thanks again!

mystix
11 Sep 2009, 9:41 AM
...When you clear the box, it should fire a removeallitems event...

might i suggest an event name of clear or clearAll instead?

mratzloff
11 Sep 2009, 11:29 AM
might i suggest an event name of clear or clearAll instead?I actually originally had that, but I saw that the method was removeAllItems(). :)

danh2000
11 Sep 2009, 3:19 PM
@mratzloff Thanks for your suggestions - I agree and will implement them soon :)

I suppose you know that you could add the following to 'remove' the expand button:


.x-superboxselect-btn-expand {
display: none;
}

@mystix Agreed - I prefer the event name clear!

Thanks,

Dan

mratzloff
14 Sep 2009, 7:15 AM
In initComponent() I think you need to put the highlighted code below the parent call, instead of before. Otherwise the store might not be initialized.


Ext.ux.form.SuperBoxSelect.superclass.initComponent.call(this);

if(this.mode === 'remote' && this.store){
this.store.on('load', this.onStoreLoad, this);
}


Also, could you give an example of how you intended users to load initial data directly from a remote data store, so that it populates the data store count?

danh2000
14 Sep 2009, 1:26 PM
I can't think of a scenario where the order would matter there - although I'm possibly still half asleep..!

With regards to the store and the count - wouldn't you just use the totalProperty and root configs like a regular combo?

mratzloff
14 Sep 2009, 3:53 PM
I can't think of a scenario where the order would matter there - although I'm possibly still half asleep..!

With regards to the store and the count - wouldn't you just use the totalProperty and root configs like a regular combo?Well, I'm new to Ext JS, but I was getting an error (no function by that name, I believe) in Safari prior to changing the order, and now I'm not. It appears that the parent class initializes all of the xtype classes. Manually generating the store class (via Ext.ComponentMgr.create()) prior to using it also worked for me.

danh2000
14 Sep 2009, 4:32 PM
.. of course, when using an xtype it would matter! I tend not to use them myself.

Thanks - I'll include that change in the next version.

Stju
15 Sep 2009, 2:10 AM
Hi!
It would be very nice if this component in some stage have possibility to add icon not only in selected result line but, in dropdown list same as it is IconCombo made by Saki B)
Actually icon class is already passed to component, it needs to just rendered with some template or like that..
Once again thanks for this great stuff!
Stju

danh2000
15 Sep 2009, 2:21 PM
@Stju,

Thanks for the feedback - I have considered this myself.. I'll probably add it in a future release.

dennispg
21 Sep 2009, 1:11 PM
I am attempting to wrap this amazing extension within an asp.net control and need the ability to read out the value and display fields for the selected items, and discovered a bug in the getValueEx method in the process.

It seems the scope is not being set on the call to this.items.each() and thus this.valueField, etc are undefined. I'm including the fixed version below:

getValueEx: function() {
var ret = [];
this.items.each(function(item) {
var newItem = {};
newItem[this.valueField] = item.value;
newItem[this.displayField] = item.display;
newItem[this.classField] = item.cls;
ret.push(newItem);
}, this);
return ret;
},

Along these lines, is there any easy way to have the value which is automatically written back into the applyTo element be the JSON encoded return from getValueEx?

Thanks!

cmendez21
21 Sep 2009, 4:00 PM
Hi first of all cool extension =D>

but i have a question:
:-? Is there a way (property , override) to let the control grow at certain height and display a scroll bar if its needed ? cause i use some forms that need to be a certain height tabs and so on

thanks

danh2000
21 Sep 2009, 4:24 PM
@dennispg,

Thanks for the report regarding getValueEx :)

Sorry, but I didn't quite follow the question about applyTo - can you please elaborate?

@cmendez21,

Thanks for the feedback, unfortunately that is not available in the current version, although I have plans to enable this in future.

dennispg
21 Sep 2009, 4:38 PM
Sorry, I was trying to transform a textbox and initialize the data that way, but I've now abandoned that idea and instead handle the additem and removeitem events and update the textbox from there manually.

I did however have to make a couple other changes to accommodate what I'm trying to do.. For example, I'm not sure I fully understand how to initialize the box with selections when using a remote store.. I dont want to have to make roundtrip calls back to the server again if I already have the data to be injected... I ended up writing my own method that just calls addRecord(createRecord(data)). Is there a better way that I should have followed instead?

Also, I pass back some extra data from my remote json store that I would like to be able to read from the additem event for other handling elsewhere in my form. To accomodate for that I changed the fireEvent call in addRecord to be:
this.fireEvent('additem', this, record);

Is there a better to have done this as well?

Thanks for the great extension, it is a life saver!

danh2000
21 Sep 2009, 6:22 PM
@dennispg

When setting values with a remoteStore, the trip to the server is to accomodate for allowAddNewData - if it's true, I need to ensure that the record doesn't exist, if false I'm ensuring that it does.

I understand why this doesn't suit you if you know the value and display data already, but I think the small overhead of a single call to the server isn't an issue in most cases, and as you point out can be bypassed.

One point to beware of with your override is the scenario where the component hasn't yet been rendered (container uses CardLayout for instance) - in this scenario, I internally store the value (preRenderValue) and set the value once the component has been rendered - this won't work with your addRecord(createRecord(data)) method, so beware of this if you get caught out.

Regarding the additional record data - I think it's a valid use case and will likely extend the addItem and removeItem events to include the record as an additional param.

Thanks again,

Dan

danh2000
21 Sep 2009, 8:54 PM
I've attached a new version to the first post (http://extjs.com/forum/showthread.php?p=332654).

Summary of changes:

Added 'clear' event.
Added a 'record' param to the addItem and removeItem events.
Added 'supressClearValueRemoveEvents' config.
Fix to escape internal regexp.
Added new 'supressEvents' param to clearValue method.
Removed docs for removeAllItems method - clearValue should be used instead.
Added addItems method.
Fixed scope issue in getValueEx method.
Fix to provide an originalValue (and fix reset) when remote store used.

dennispg
22 Sep 2009, 12:40 PM
Thank you so much! I am seriously loving this extension..

I've run into a new issue now though. I am getting an error on this line:

var re = new RegExp(Ext.escapeRe(q) + '.*', 'i');q is undefined and so Ext.escapeRe fails. I notice this was just added in with your latest update and it worked fine before. options.params only contains 'limit' and 'start', and queryParam isnt there which is why q comes back undefined..

I have to be honest that I'm pretty new to extjs so I'm pretty sure I'm doing something wrong when I create my store in the first place. Yet it all seems to be working fine when i add this line in:

if (typeof q == 'undefined') q = '';Here is how I am creating my store:

store: new Ext.data.JsonStore({
url: params.jsonUrl,
baseParams: params.parameters,
root: 'people'
}),Did I mess something up? params just contains the configuration data for my server side handler...

danh2000
22 Sep 2009, 1:33 PM
@dennispg

Do you share the store or load it yourself outside of the SBS?

I'd love to get a test case if possible so that I can debug it as I can't reproduce the issuse in any of my tests.

Thanks,

Dan

dennispg
22 Sep 2009, 2:25 PM
I am working on putting together a useful test case for you, I'll have it shortly..

In the meantime, I believe I have found another bug.



this.preventMultipleRemoveEvents = supressRemoveEvent || this.supressClearValueRemoveEvents || false;
this.removeAllItems();
this.preventMultipleRemoveEvents = false;I added the last line because I think once you have finished clearing all the items, regular removals should still trigger the event right? As it is, one call to clearValue(true) and the removeitem event will never trigger again.

thanks!

danh2000
22 Sep 2009, 2:34 PM
this.preventMultipleRemoveEvents = supressRemoveEvent || this.supressClearValueRemoveEvents || false;
this.removeAllItems();
this.preventMultipleRemoveEvents = false;I added the last line because I think once you have finished clearing all the items, regular removals should still trigger the event right? As it is, one call to clearValue(true) and the removeitem event will never trigger again.


***Sorry, my mistake - I'll correct this***

I'll await your test case regarding the first issue.

dennispg
22 Sep 2009, 3:34 PM
here is my test case:


<html>
<head>
<link rel="stylesheet" type="text/css" href="extjs/ext.css" />
<script src="extjs/ext.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="SuperBoxSelect.css" />
<script src="SuperBoxSelect.js" type="text/javascript"></script>
<script type="text/javascript">
Ext.onReady(function(){
var store = new Ext.data.JsonStore({
url: 'PeopleLookup.aspx',
root: 'people',
fields: ['alias', 'fullname']
});
new Ext.ux.form.SuperBoxSelect({
valueField: 'alias',
displayField: 'fullname',
allowAddNewData: true,
store: store,
renderFieldBtns: false,
itemSelector: 'div.search-item',
minChars: 3,
width: 600,
renderTo: 'container'
});
});
</script>
</head>
<body><div id="container" /></body>
</html>

danh2000
22 Sep 2009, 3:54 PM
here is my test case:


<html>
<head>
<link rel="stylesheet" type="text/css" href="extjs/ext.css" />
<script src="extjs/ext.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="SuperBoxSelect.css" />
<script src="SuperBoxSelect.js" type="text/javascript"></script>
<script type="text/javascript">
Ext.onReady(function(){
var store = new Ext.data.JsonStore({
url: 'PeopleLookup.aspx',
root: 'people',
fields: ['alias', 'fullname']
});
new Ext.ux.form.SuperBoxSelect({
valueField: 'alias',
displayField: 'fullname',
allowAddNewData: true,
store: store,
renderFieldBtns: false,
itemSelector: 'div.search-item',
minChars: 3,
width: 600,
renderTo: 'container'
});
});
</script>
</head>
<body><div id="container" /></body>
</html>


Thanks,

Although very strange - I cannot see how you wouldn't get params in the callback - the query param will be the first 3 characters that you type.

I notice you aren't using:


mode: 'remote'

I'm not sure how you would ever execute the line of code that you reported without this, so I'll presume that you have omitted it from the test case by mistake.

Can you please provide steps to reproduce the error - do you simply start typing?

danh2000
22 Sep 2009, 3:57 PM
I also notice the itemSelector config - should that be there, or have you also used a custom tpl?

dennispg
22 Sep 2009, 4:14 PM
That code was the result of stripping away from my big project for purposes of narrowing down the issue. The itemSelector was just leftover after I stripped it, however the mode is not something I have ever set and it seems to work just fine without it..

I tried adding it in mode: 'remote' anyway to see if that is the issue after all, but it still happens. All I do is start typing and it blows up. Could it have something to do with the fact that I am setting the fields property manually on the store?

Here is a dummy data page written in aspx that I am using to trigger the problem with the previous code snippet:

<%@ Page Language="C#" %>
<script runat="server">
protected override void OnInit(EventArgs e)
{
Response.ContentType = "application/json";
Response.Write("{people:[{alias:\"TestUser1\",fullname:\"User1, Test\"}]}");
Response.End();
}
</script>Again if I change the code to read like this it works fine:

if (typeof q == 'undefined') q = '';
var re = new RegExp(Ext.escapeRe(q) + '.*', 'i');

danh2000
22 Sep 2009, 4:17 PM
@dennispg,

Without having your backend in place, I have replicated your test case as closely as possible and I cannot reproduce the error:


Ext.onReady(function() {
Ext.QuickTips.init();
var store = new Ext.data.JsonStore({
root:'rows',
fields:['tag', 'name'],
url: 'fetchTags.php'
});

new Ext.ux.form.SuperBoxSelect({
valueField: 'tag',
displayField: 'name',
allowAddNewData: true,
store: store,
renderFieldBtns: false,
//itemSelector: 'div.search-item',
minChars: 3,
width: 600,
renderTo: 'container'
});
});

Not that the above really differs from my original examples.

Can you shed any more light on this - do you perhaps have overrides in place?

danh2000
22 Sep 2009, 4:24 PM
Here's my replication of your test case:

http://www.technomedia.co.uk/SuperBoxSelect/examplesRemoteBugTest.html

Please take a look and let me know if you see anything obviously different from your own.

Thanks,

Dan

PS. I've tried with both Ext 2 and Ext 3.

PPS. The test case SBS accepts values such as 'Nature', 'Architecture', 'Sport'

dennispg
22 Sep 2009, 4:51 PM
I am stumped... I can see no difference between what you've done and what I have done.. Yet I am able to replicate it over and over on different boxes, and from different servers. Yet I have no issue from your site.

Here is my page hosted:
http://pulimootil.com/testcase.html

I am using extjs3 and I've tried it with FF3 and IE7 both, and both show the issue.

danh2000
22 Sep 2009, 5:05 PM
I do get an error on your URL, but it is

'c is undefined'

Are you using ext-base adapter?

dennispg
22 Sep 2009, 5:11 PM
'c is undefined' happens after the call passes through to Ext.escapeRe(undefined). the bigger problem is that q is undefined in the first place, and that is not happening with your site..

yes i am using ext-base adapter.. i just combined them into one ext.js file. im also using 3.0.0, and i noticed you are using 3.0.1.. could there be an issue there maybe? nothing in the changelogs stuck out to me to indicate that would be the case though?

i am stumped. :-/

danh2000
22 Sep 2009, 8:00 PM
'c is undefined' happens after the call passes through to Ext.escapeRe(undefined). the bigger problem is that q is undefined in the first place, and that is not happening with your site..

yes i am using ext-base adapter.. i just combined them into one ext.js file. im also using 3.0.0, and i noticed you are using 3.0.1.. could there be an issue there maybe? nothing in the changelogs stuck out to me to indicate that would be the case though?

i am stumped. :-/

There is something wrong with your file - I can ONLY reproduce the error using your merged scripts.

I have tried 3 different versions of Ext and all work without error - If I replace these with your merged file, the error occurs.

I'd suggest that you use the distro files or attempt merging again.

galdaka
22 Sep 2009, 10:12 PM
Hi,

Does this component support pagingtoolbar?

Any example?

P.D: I think that this component is definitive solution for multiselect / newitems. And should be added to Ext core.


Thanks and greetings,

danh2000
22 Sep 2009, 10:55 PM
Hi,

Does this component support pagingtoolbar?

Any example?

P.D: I think that this component is definitive solution for multiselect / newitems. And should be added to Ext core.


Thanks and greetings,

Thanks galdaka.

I've never used the PagingToolbar, but if it can be used with ComboBox, I don't think there's any reason that it wouldn't work here.... however, if it doesn't I'll gladly look into supporting it.

dennispg
23 Sep 2009, 7:40 AM
I have updated my hosted testcase to use a pristine and untouched copy of extjs 3.0.0, freshly downloaded from the site and a fresh copy of latest SuperBoxSelect.js from the first post to be sure.. I even hooked it up to the debug version (its large), and the error is still present.

So the problem is definitely not the merged file that I am using.. I have attached my files here if youre still interested in looking at it.

radtad
23 Sep 2009, 9:36 AM
It would be really nice to have vtypes added to this. When adding an email address as new data, I would like to check and see if the entered data is a valid email address. I think this would be a very useful addition.

Also, addressing an earlier suggestion do you think it would be possible to add a comma separated list support?

mratzloff
23 Sep 2009, 11:58 AM
Hi,

When using the latest release, the onStoreLoad problem (this.store.on is not a function) still exists. If I have to use an instantiated store instead of an xtype that's fine, but please call that out in the examples or documentation.

Unfortunately, I also couldn't get the latest version to work. It kept failing in the onStoreLoad() method when it was trying to call Ext.escapeRe(), and I don't have the time to debug it at the moment. Reverting to the previous version works.

danh2000
23 Sep 2009, 1:10 PM
I have updated my hosted testcase to use a pristine and untouched copy of extjs 3.0.0, freshly downloaded from the site and a fresh copy of latest SuperBoxSelect.js from the first post to be sure.. I even hooked it up to the debug version (its large), and the error is still present.

So the problem is definitely not the merged file that I am using.. I have attached my files here if youre still interested in looking at it.

@dennispg

I will continue to look into it - I'm against blindly converting the param to a string - it may work and fix your issue, but I'd like to understand the root cause - as you know I've tried and have not yet been able to replicate the problem.


It would be really nice to have vtypes added to this. When adding an email address as new data, I would like to check and see if the entered data is a valid email address. I think this would be a very useful addition.

Also, addressing an earlier suggestion do you think it would be possible to add a comma separated list support?

@radtad

Apologies, but new features a low on my priority list at the moment. I will consider these in future.


Hi,

When using the latest release, the onStoreLoad problem (this.store.on is not a function) still exists. If I have to use an instantiated store instead of an xtype that's fine, but please call that out in the examples or documentation.

Unfortunately, I also couldn't get the latest version to work. It kept failing in the onStoreLoad() method when it was trying to call Ext.escapeRe(), and I don't have the time to debug it at the moment. Reverting to the previous version works.

Finally, what is the approach you recommend for deferring saving until a user clicks a Save button? I'm using a remote store and currently it does not appear possible to do this easily. But perhaps I'm missing something. :-/

@mratzloff

Sorry I missed the xtype instantiation.
I'm looking into the onStoreLoad issue as previously reported by @dennispg.
I didn't understand the saving question at all - what do you mean by saving?

danh2000
23 Sep 2009, 2:17 PM
@dennispg,

I downloaded a fresh Ext 3.0.0 and can now replicate it - it seems the Ext 3.0.0 version I had was a later version from SVN

There is obviously a bug in Ext 3.0.0 (params in the load callback are empty) that didn't exist in Ext 2.2.1 and doesn't exist in Ext 3.0.1 and later, however trying to locate what that bug was (I've been searching the forum and the release notes) is like looking for a needle in a haystack - locating bugs and fixes here is harder than it should be IMHO.

I'm looking into a solution - probably to grab the query param from the store.baseParams if it's not present in the callback args.

I'll upload a new version soon.

Edit: And sorry, I must thank you for your persistence in helping to track this down.

radtad
23 Sep 2009, 3:21 PM
@radtad

Apologies, but new features a low on my priority list at the moment. I will consider these in future.


No worries :). This thing just gets better all the time! You're doing a great job with the active development!

danh2000
23 Sep 2009, 3:33 PM
Thanks @radtad!

danh2000
24 Sep 2009, 12:11 AM
I've updated the first post (http://extjs.com/forum/showthread.php?p=332654) with a new version containing the following changes:

Fix to work around Ext 3.0.0 bug - store load event not providing params to callback.
Fix to allow store to be provided as an xtype.
Fix to clean up after prevention of 'remove' events during clearValue.

mratzloff
24 Sep 2009, 2:13 PM
I've updated the first post (http://extjs.com/forum/showthread.php?p=332654) with a new version containing the following changes:

Fix to work around Ext 3.0.0 bug - store load event not providing params to callback.
Fix to allow store to be provided as an xtype.
Fix to clean up after prevention of 'remove' events during clearValue.Dan, great timing! Your latest version fixes all of the outstanding issues I was facing.

I'm seeing one last issue, which is easy to handle on the server side. The component seems to be passing an extra empty value at the end when wrapped in a FormPanel and saved that way (I do it this way because I need remote loading with a save button and without automatic persisting to the server when a tag is added).

I'd also like to make a request (not urgent) to add loadMask and maskDisabled parameters like Ext.grid.GridPanel has. When loading the initial set of records from the server there can occasionally be a bit of a delay.

Thanks for all your hard work!

danh2000
24 Sep 2009, 2:21 PM
@mratzloff - Thanks for the feedback.

The input element used for typing is the extra data you see when submitting the form - I have accomodated for this when using BasicForm.getValues, but if the raw form is submitted, I don't think I can do anything about it... is this the case in your instance - do you access the raw form and call submit?

I'll add your request to my list.

Thanks,

Dan

mystix
24 Sep 2009, 9:27 PM
@mratzloff - Thanks for the feedback.

The input element used for typing is the extra data you see when submitting the form - I have accomodated for this when using BasicForm.getValues, but if the raw form is submitted, I don't think I can do anything about it... is this the case in your instance - do you access the raw form and call submit?

I'll add your request to my list.

Thanks,

Dan

you could simply keep a reference to an <input> element which does not have a name attribute. that will automatically take care of raw <form> submissions.

danh2000
24 Sep 2009, 9:38 PM
you could simply keep a reference to an <input> element which does not have a name attribute. that will automatically take care of raw <form> submissions.

Doh! Of course that would work - I'll just kill the name attribute. Thanks :)

galdaka
25 Sep 2009, 12:01 AM
Hi,

Superboxselect with xtheme-gray-extend (http://www.extjs.com/forum/showthread.php?p=118979#post118979) looks beatiful.

Greetings

danh2000
25 Sep 2009, 12:12 AM
Hi,

Superboxselect with xtheme-gray-extend (http://www.extjs.com/forum/showthread.php?p=118979#post118979) looks beatiful.

Greetings

@galdaka,

It does indeed look very nice - can I include the css with the download or would you prefer that I link to your thread?

Can I also create and promote a new example page using this css?

Thanks,

Dan

galdaka
25 Sep 2009, 12:22 AM
@galdaka,

It does indeed look very nice - can I include the css with the download or would you prefer that I link to your thread?

Can I also create and promote a new example page using this css?

Thanks,

Dan

Yes, you can include CSS with your Download and yes, you can create and promote new example in your page. ;) ;)

1) One bug / problem with component.



{
id: 'tFunciones',
fieldLabel: 'Funciones',
xtype: 'superboxselect',
mode: 'local',
store: new Ext.data.SimpleStore({
fields: ['abc'],
data: [['uno'], ['dos']],
sortInfo: {field: 'abc', direction: 'ASC'}
}),
allowAddNewData: true,
resizable: true,
displayField: 'abc',
valueField: 'abc',
extraItemCls: 'font-normal',
stackItems: true
}


When I add new data, is not visible in component. If I add this:

listeners: {
newitem: function(bs,v){
bs.addItemBox(v, v, v);
}
}

Works nice.

2) One question.

Is posible use your component without a Store?

3) is posible a demo with paggingtoolbar?

4) You have a error in IE8 (http://technomedia.co.uk/SuperBoxSelect/examples3.html)


Line 328: o.getAttributeNode('style').specified

Thanks in advance and greetings,

danh2000
25 Sep 2009, 12:42 AM
Yes, you can include CSS with your Download and yes, you can create and promote new example in your page. ;) ;)

1) One bug / problem with component.



{
id: 'tFunciones',
fieldLabel: 'Funciones',
xtype: 'superboxselect',
mode: 'local',
store: new Ext.data.SimpleStore({
fields: ['abc'],
data: [['uno'], ['dos']],
sortInfo: {field: 'abc', direction: 'ASC'}
}),
allowAddNewData: true,
resizable: true,
displayField: 'abc',
valueField: 'abc',
extraItemCls: 'font-normal',
stackItems: true
}


When I add new data, is not visible in component. If I add this:

listeners: {
newitem: function(bs,v){
bs.addItemBox(v, v, v);
}
}

Works nice.

2) One question.

Is posible use your component without a Store?

3) is posible a demo with paggingtoolbar?

4) You have a error in IE8 (http://technomedia.co.uk/SuperBoxSelect/examples3.html)


Line 328: o.getAttributeNode('style').specified

Thanks in advance and greetings,

Thanks @galdaka, I'll include your CSS in the next release :)

Regarding the issue you've raised above (point 1), the allowAddNewData config simply enables the component to recognize that new data is being added and enables it to fire the 'newitem' callback - it doesn't actually add the new item as it is up to the end developer to configure the value, display, class etc and add that to the component.

I would typically use the addItem method to do this as per the examples.

Regarding point 2 - as it extends ComboBox, I'm typically following suit from it's use cases - meaning the store is necessary - even if it's just a local store.

Point 3 was asked of me quite recently - I've never actually use paging toolbar, but if it works with ComboBox, it will probably work with SBS - I'll look into adding support if not.

Regarding point 4 - thanks for the report - I'll look into it and apply the necessary fix.

Thanks again,

Dan

JorisA
25 Sep 2009, 1:01 AM
Awesome component!!!
Found a small bug though:

findInStore : function(val){
var index = this.store.find(this.valueField, val.trim());
if(index > -1){
return this.store.getAt(index);
}
return false;
},

the val.trim() will generate an error when the value is an integer (when removing items from the list)

danh2000
25 Sep 2009, 1:05 AM
Thanks JorisA,

Fixed, and I'll include in the next release.



Awesome component!!!
Found a small bug though:

findInStore : function(val){
var index = this.store.find(this.valueField, val.trim());
if(index > -1){
return this.store.getAt(index);
}
return false;
},

the val.trim() will generate an error when the value is an integer (when removing items from the list)

l0ga4
25 Sep 2009, 9:39 AM
some problem with your extension:

http://www.extjs.com/forum/showthread.php?t=81343

bad render in window panel

danh2000
25 Sep 2009, 12:37 PM
some problem with your extension:

http://www.extjs.com/forum/showthread.php?t=81343

bad render in window panel

The component renders fine in a window - the extension is not at fault - you must have done something wrong.

I'll reply to your other post.

radtad
25 Sep 2009, 4:42 PM
So I went ahead and made an attempt to use vtypes. Here is the code I added / changed (I'm sure it could be better):




/**
* @cfg {String} vtype The validation type to use if validating.
*/
vtype: null,


// changed the following function

validateValue: function(val){
if(this.items.getCount() === 0){
if(this.allowBlank){
this.clearInvalid();
return true;
}else{
this.markInvalid(this.blankText);
return false;
}
}

if(this.vtype){
var vt = Ext.form.VTypes;
var ret = this.getValueEx();

for (var i = 0; i < ret.length; i++) {
if(!vt[this.vtype](ret[i][this.valueField], this)){
this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
return false;
}
}
}

this.clearInvalid();
return true;
},
Also, any function call consisting of '.validateValue()' should be the following '.validateValue(itemVal)'.

danh2000
26 Sep 2009, 8:04 PM
So I went ahead and made an attempt to use vtypes. Here is the code I added / changed (I'm sure it could be better):




/**
* @cfg {String} vtype The validation type to use if validating.
*/
vtype: null,


// changed the following function

validateValue: function(val){
if(this.items.getCount() === 0){
if(this.allowBlank){
this.clearInvalid();
return true;
}else{
this.markInvalid(this.blankText);
return false;
}
}

if(this.vtype){
var vt = Ext.form.VTypes;
var ret = this.getValueEx();

for (var i = 0; i < ret.length; i++) {
if(!vt[this.vtype](ret[i][this.valueField], this)){
this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
return false;
}
}
}

this.clearInvalid();
return true;
},
Also, any function call consisting of '.validateValue()' should be the following '.validateValue(itemVal)'.

Hey @radtad

Thanks - what are your test cases around this functionality - would it be useful only for new item data?

At what point would you expect vtype validation to occur, and have you got any test cases?

Thanks,

Dan

danh2000
26 Sep 2009, 11:16 PM
Update:

Fix to prevent submission of empty value when doing a raw form submit.
Fix for IE8 error during transform.
Inclusion of superboxselect-gray-extend.css from the extended gray theme (https://www.extjs.com/forum/showthread.php?t=65694) (Thanks Galdaka (http://www.extjs.com/forum/member.php?u=101))


Ext 2 Example:

http://technomedia.co.uk/SuperBoxSelect/examples.html

Ext 3 Example:
http://technomedia.co.uk/SuperBoxSelect/examples3.html

Ext 3 Extended Gray Theme Example:
http://www.technomedia.co.uk/SuperBoxSelect/examples3gray.html

Remote Store Example:
http://technomedia.co.uk/SuperBoxSelect/examplesRemote.html

Download
16454

mratzloff
27 Sep 2009, 11:16 AM
Update:

Fix to prevent submission of empty value when doing a raw form submit.Awesome, great work. Thanks!

One last feature improvement suggestion and then I'll shut up. The following would be really convenient:



load: function(params) {
params = params || {};
params.loadqry = true;

this.removeAllItems().resetStore();

if (Ext.isEmpty(mapper.el.dom.value)) {
this.applyEmptyText();
this.autoSize();
}

var that = this;
this.store.load({
params: params,
callback: function(records, options, success) {
Ext.each(records, function(record) {
that.addRecord(record);
});
}
});
}


This works for me, but there are probably little checks that you do that I'm missing. You'll probably want to move logic around or something, too. I originally tried to call onBlur() but that didn't seem to work. I also noticed that removeAllItems() used in this context also didn't play well with a remove event, so I removed mine until it's working.

danh2000
27 Sep 2009, 9:52 PM
Thanks, I'm not sure I see the benefit of pulling this functionality into the component though as it can so easily be achieved externally to the component.. I'll think on it.


Awesome, great work. Thanks!

One last feature improvement suggestion and then I'll shut up. The following would be really convenient:



load: function(params) {
params = params || {};
params.loadqry = true;

var that = this;
this.store.load({
params: params,
callback: function(records, options, success) {
Ext.each(records, function(record) {
that.addRecord(record);
});
}
});
}


This works for me, but there are probably little checks that you do that I'm missing.

mratzloff
28 Sep 2009, 7:03 AM
Thanks, I'm not sure I see the benefit of pulling this functionality into the component though as it can so easily be achieved externally to the component.. I'll think on it.Encapsulation. I have to access and manipulate the data store directly, and any validation that you have outside of addRecord() is not called.

frankthetank
28 Sep 2009, 8:25 AM
Thanks for the update ! I've been waiting for the remote option !! :D

radtad
28 Sep 2009, 9:39 AM
Hey @radtad

Thanks - what are your test cases around this functionality - would it be useful only for new item data?

At what point would you expect vtype validation to occur, and have you got any test cases?

Thanks,

Dan

Yes, this would be only for new item data. So this really should include an if statement wrapped around.



if(this.allowAddNewData){
if(this.vtype){
var vt = Ext.form.VTypes;
var ret = this.getValueEx();

for (var i = 0; i < ret.length; i++) {
if(!vt[this.vtype](ret[i][this.valueField], this)){
this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
return false;
}
}
}
}

With the code I wrote, validation is happening on any new box item. This works out great because it tells you right away that the box you entered is invalid. However, doing validation like this could happen onBlur. The only problem is, you won't know which item box is invalid unless you put some kind of class on the invalid box to mark it invalid.

I don't have the resources at the moment to give you a full on test case, but you could plug in the following code in an example. I should be able to provide a test case in the next day or so.



var emailstore = new Ext.data.SimpleStore({
fields: ['email']
});

// this would match either "FirstName LastName user@domain.com" or "user@domain.com"
Ext.form.VTypes["emailaddress"] = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
Ext.form.VTypes["emailaddressText"] = 'This field should be an e-mail address in the format "FirstName LastName user@domain.com"';

var emailbox = {
fieldLabel: 'Email Addresses',
resizable: true,
name: 'emailaddr',
anchor:'100%',
id: 'emailaddr',
store: emailstore,
mode: 'local',
minChars: 2,
emptyText: 'FirstName LastName user@domain.com',
displayField: 'email',
valueField: 'email',
vtype: 'emailaddress',
xtype: 'superboxselect',
allowAddNewData: true,
renderFieldBtns: false,
listeners: {
newitem: function(bs,v){
bs.addItem({email: v});
}
}
};

danh2000
28 Sep 2009, 11:37 PM
@radtad, Thanks, leave it with me - I'll have a look in the next few days.

dcw
30 Sep 2009, 2:55 AM
Hey there,

I am new and not really familar with Ajax. So, is there any manual how to get this component working?

I downloaded the example page but it doesn't work, although javascript is on client side.

thanks a lot

Dennis

danh2000
30 Sep 2009, 12:57 PM
Dennis,

This component extends ComboBox - it's essentially a form field. Have you used ComboBox or any other form fields?

When you say doesn't work - what do you mean? What did you try and what are the symptoms of doesn't work?

I would suggest familiarizing yourself with the ext examples. Copy and paste code, read the docs and try different configuration options to see what they do.

I think once you understand the basics of ext, this component is very easy to use as it follows the same principles.

JorisA
1 Oct 2009, 4:40 AM
reset : function(){
Ext.ux.form.SuperBoxSelect.superclass.reset.call(this);
this.addedRecords = [];
this.autoSize().setRawValue('');
//this.el.focus();
},

I think the focus on reset should be removed, since this is not consistent with other fields, and will have the element rendered as invalid when allowBlank=false.

Also I'm having some problems parsing the data in php when I'm using form.submit(). Data is sent as multipart/form, and that prevents me from parsing array's in POST data. Is there a way to submit a comma seperated list (as with getValue())?

pilotsnipes
1 Oct 2009, 8:30 AM
I just added a bit of code to do mid-word pattern matching for the SuperBoxSelect from the previous facebook like box select I added there as well (you essentially have to override doQuery):



@radtad,

Nice - why don't you make it a standalone plugin, that way you could plug the functionality into SuperBoxSelect, or ComboBox or any component that extends ComboBox.




I would love to have this feature too, did it ever make it into the official version, or did it become a plugin somewhere?

Thanks for the work on this project. Much appreciated.

danh2000
1 Oct 2009, 3:47 PM
@JorisA

Thanks, I'll have a look at the reset method.

With regards to your form submission; I use PHP without any problems.

Are you aware that you need to name your form elements with square brackets to enable array processing:

ie:


name: 'states[]'

This seems to catch a few people out, but it's the same with regular HTML forms too.

@pilotsnipes

I believe @radtad was going to make a plugin of this functionality - he may respond here.

radtad
1 Oct 2009, 4:49 PM
I actually ended up extending the functionality with an override. The two config options to use with this are:



anyMatch: (true|false) // default: true
caseSensitive: (true|false) // default: false
Enjoy.

pilotsnipes
2 Oct 2009, 1:16 AM
I actually ended up extending the functionality with an override. The two config options to use with this are:
Enjoy.



@radtad - Thank you so much for this! What a difference it makes to my script. Very easy to setup as well (I still think this should be in the main superboxselect but I'm happy just to add it at the moment!)

Thanks again!


@JorisA
With regards to your form submission; I use PHP without any problems.

[....]

name: 'states[]'This seems to catch a few people out, but it's the same with regular HTML forms too.



@danh2000 - no doubt you receive too many requests for help, but would it be possible for you to post a full copy of a demo/simplified code showing this, I find it's so much easier to learn when I have a working example to study from. I would really appreciate it. Thank you for the help so far.

danh2000
2 Oct 2009, 3:54 PM
@danh2000 - no doubt you receive too many requests for help, but would it be possible for you to post a full copy of a demo/simplified code showing this, I find it's so much easier to learn when I have a working example to study from. I would really appreciate it. Thank you for the help so far.

There are many examples available:

http://technomedia.co.uk/SuperBoxSelect/examples.html
http://technomedia.co.uk/SuperBoxSelect/examples3.html
http://technomedia.co.uk/SuperBoxSelect/examples3gray.html
http://technomedia.co.uk/SuperBoxSelect/examplesRemote.html

If you specifically mean using PHP and the array access, it's pretty simple - PHP requires square brackets at the end of form field names to indicate that it is array data. Therefore if you are using PHP and you are submitting the raw form - put square brackets at the end of the name.

Eg:

If your field is named states then name it states[] instead.

Additional info: http://us2.php.net/manual/en/faq.html.php#faq.html.arrays

jheid
4 Oct 2009, 11:49 AM
Please change



findInStore : function(val){
var index = this.store.find(this.valueField, val.trim());


to



findInStore : function(val){
var index = this.store.find(this.valueField, Ext.isString (val) ? val.trim() : val);


so that values other than strings are supported.

Cheers,
Jörm

nadim
7 Oct 2009, 3:34 PM
the .reset() method doesn't seem to be working correctly for me. If I use it and then immediately click on the drop down arrow I get a "this.list" is not defined.

Suggestions?

nadim
7 Oct 2009, 3:35 PM
I'm using basicform.reset.

nadim
7 Oct 2009, 4:06 PM
I mean .suspendEvents() and .resumeEvents(), not .reset() :)

danh2000
7 Oct 2009, 7:48 PM
All,

@jheid - Will do!

@nadim - I got a bit lost - are you using suspendEvents, then resumeEvents, then clicking the arrow?

Even better do you have a test case. And please let me know which browser/version you tried.

Thanks.

@all - Apologies for lack of responses/updates - I am very busy at the moment, but will aim to get a new release out within a week.

nadim
8 Oct 2009, 12:02 AM
I find that when I use suspendEvents() and then resumeEvents() I get the error I described above.

nadim
11 Oct 2009, 1:36 PM
I've re-worked parts of my code and here is what is currently tripping me up.
I reset the sbs and then the emptytext isn't set anymore. I've tried calling .applyEmptyText() but it adds the empty text and remains in a greyed out state. I have to click elsewhere and then click back on the sbs to get it to work correctly.

If it makes any difference I call a reset on the entire form, then call setValues on the entire form. The sbs values get populated correctly but the first sbs in the form has focus and when I start typing the text is light grey and autocomplete doesn't work. Here is the exact sequence of calls I make:
ss.suspendEvents(false);
ss.reset();
ss.setValues(valObj);
ss.resumeEvents();

Any suggestions?

nadim
11 Oct 2009, 1:45 PM
I also made the following change to findinstore:

findInStore : function(val){
if(typeof(val) === 'string') {
val = val.trim();
}
var index = this.store.find(this.valueField, val);
if(index > -1){
return this.store.getAt(index);
}
return false;
},

It was getting called with val as a number and val.trim() was failing.

danh2000
12 Oct 2009, 2:01 PM
@nadim,

Using the example page here (http://www.technomedia.co.uk/SuperBoxSelect/examples3.html)

I have reset the component and emptyText still works and reset the form and the emptyText still works - you can try yourself with the firebug console :


Ext.getCmp('f1Form').getForm().reset();

If you are having problems, please provide a bug report and isolated test case as per this thread and I'll have a look for you:

http://www.extjs.com/forum/showthread.php?t=71015

Thanks,

Dan

nadim
13 Oct 2009, 10:38 AM
Here is an example, current code in example is:
buttons: [{ 152 text: "setValue('AK,NY,CO')",
153 scope: this,
154 handler: function(){
155 Ext.getCmp('selector1').setValue('AK,NY,CO');
156 }

Change line 155 to be:
Ext.getCmp('selector1').setValue('');

Empty text doesn't get set. Calling reset right after doesn't fix this, nor does .applyEmptyText().


Is there some way I can have it reset to it's original state (with empty text) after calling .setValue('') ?

danh2000
13 Oct 2009, 12:03 PM
@nadim,

you are confusing me - you keep posting different issues, none of which are accompanied with a decent bug report or test case. Have you looked at the post I referred you to:

http://www.extjs.com/forum/showthread.php?t=71015

So your current issue appears to be that you can't use setValue with an empty string? What about your previous report of empty text or resetting the form or suspending then resuming events?

I'm happy to help, but I cannot follow what you are trying to do or what you are having problems with.

Please see this thread:

http://www.extjs.com/forum/showthread.php?t=71015

Thanks

nadim
13 Oct 2009, 12:47 PM
Sorry for the confusion, please try this, it is as isolated as I can get my example.
Go to your page:
http://www.technomedia.co.uk/SuperBoxSelect/examples3.html

Open firebug, paste the following in the console and run it:
Ext.getCmp('selector1').setValue('AK,NY,CO');
Ext.getCmp('selector1').suspendEvents();
Ext.getCmp('selector1').reset();
Ext.getCmp('selector1').setValue('');
Ext.getCmp('selector1').enable();
Ext.getCmp('selector1').applyEmptyText();
Ext.getCmp('selector1').resumeEvents();

Now if you click on the superselectbox, notice that the empty text is applied but clicking doesn't empty the text, what i type is after the empty text and it remains greyed out. Screenshot of the behaviour I'm seeing attached as an image. If you don't get this behaviour, hit run a couple times and you should see it.

danh2000
13 Oct 2009, 1:06 PM
@nadim,

applyEmptyText is a private method - do not use it.

Apart from that, (and excuse me for being blunt) how ridiculous - what on earth are you trying to achieve with those method calls.

Do you not have a sensible use case?

nadim
13 Oct 2009, 1:11 PM
if i remove .applyEmptyText() the empty text is not applied upon .setValues('').

This is an actual scenario that is coming up in my application. I simply reduced all the calls to the relevant ones. I am saving the form state and then setting it back. When I set it back to a previous state I don't want events to fire so I suspend them. Everything works fine, except I can't get the empty text back.

I don't mind you being blunt at all. Thank you very much for this component! If there is a better way for me to achieve what I'm trying to do then I definitely want to know about it.

Thanks.

danh2000
13 Oct 2009, 1:22 PM
@nadim,

I'm still unsure what you are trying to achieve - if you simply want to clear the values down then use the clearValue method intead of setValue with an empty string. If you don't want the remove event to fire for each removed item then pass true to clearValue


var sbs = Ext.getCmp('selector1');
sbs.clearValue(true);



Does that do what you want?

nadim
13 Oct 2009, 1:30 PM
What I actually do is get the entire form and then set the entire form.
So:
formValues = this.formPanel.getForm().getValues();

and then later:
this.formPanel.getForm().setValues(formValues);

I'm not ever calling .setValues(''), it's just sometimes that it the old value was blank. I suppose I could call .getValue() for each element in the form and then .setValue() to set it back, and if it's blank then call clearValue() instead. Is this what you would suggest?

danh2000
13 Oct 2009, 1:36 PM
@nadim,

This is exactly why I asked for a test case - you are providing code that doesn't actually match what are you are doing.

I have no idea why you would suspendEvents, then reset, then set a blank value, then enable etc..

I'm not able to help because I don't understand.

If the component has a bug that you can show me with an isolated test case (that uses public methods) then I can debug it and provide a fix, otherwise I am sorry, I just don't know.

elderotaku
15 Oct 2009, 6:57 AM
First thank you for fixing the bug witht the text hiding if you hold it down.
I have a different bug in Google Chrome. After 3 or 4 characters my text is being pushed behind the previously created item.

I can't repeat the problem with your examples, so I was wondering if anyone else hads run into this problem, who might know what we are doing wrong.

Thanks,

Zolcsi
16 Oct 2009, 6:10 AM
Very nice work, I'm definitely gonna use it.
Thanks! :)

hongtj
19 Oct 2009, 5:53 AM
Firstly, this extension is amazing!!!

Secondly, i got some problem in ie6 with the SuperBoxSelect released at 27/09/2009.
Environment: Extjs 3.0, ie6, SuperBoxSelect in Ext.grid.EditorGridPanel

After option, "Shade", is selected in ie6:
16839

After option, "Shade", is selected in ff 3.5.3:
16840

Anyone got idea for it???
Many thanks.

matthewcrist
19 Oct 2009, 10:14 AM
I'm having an issue with setting values. I am retrieving an object of values and when I try to set them using setValuesEx() I only get one item added when there are four total. There aren't any errors showing up in the console.



var editInternalParty = new Ext.ux.form.SuperBoxSelect({
allowBlank: false,
allowAddNewData: true,
msgTarget: 'under',
renderFieldBtns: false,
id: 'filepropEditInternalParty',
xtype: 'superboxselect',
fieldLabel: 'Organization(s)',
emptyText: 'Enter an Organization name',
resizable: true,
name: 'editInternalParty',
anchor: '100%',
store: editOrgStore,
displayField: 'nodeName',
valueField: 'nodeId',
styleField: 'style',
extraItemCls: 'x-flag',
extraItemStyle: 'border-width:2px',
stackItems: true,
queryParam: 'search_string',
minChars: 1,
queryDelay: 0,
mode: 'remote'
});


Here's the code where I'm trying to set the value...



Ext.getCmp("filepropEditInternalParty").setValueEx([{nodeId: "12345", nodeName: "Test"},{nodeId: "23456", nodeName: "Test 2"}]);


Since this is remote, I checked the console and only the first items is having a query run on it.

danh2000
19 Oct 2009, 6:40 PM
@elderotaku,

If it's not happening on my example pages, I wonder if you have some custom CSS that is causing this? Difficult to diagnose without seeing the issue - do you have a public test case available?

@Zolcsi

Glad you like it - thanks for the feedback.

@hongtj

Thanks for the feedback. I'm afraid I'm not currently supporting use of the component in an EditorGrid - maybe in a future version.

@matthewcrist

Thanks - I've just been playing with this - there was a bug which I've just fixed (I've also removed an unecessary trip to the server when setValueEx is used along with allowAddNewData).

I'll release a new version here within 24 hours.

Regards,

Dan

matthewcrist
19 Oct 2009, 6:53 PM
Thanks for the heads up.

hongtj
19 Oct 2009, 7:17 PM
@hongtj

Thanks for the feedback. I'm afraid I'm not currently supporting use of the component in an EditorGrid - maybe in a future version.

I'll release a new version here within 24 hours.

Regards,

Dan

Thanks Dan for your quick response.
As I tested, the SuperBoxSelect, released at 27/09/2009, is work well on ff 3.5.3 and ie8 in an EditorGrid. Not test in ie7.
It looks like my problem is a css issue in ie6, but i have no idea to fix it.

Look forward to your new release!!!
Look forward to your officially support for EditorGrid.

Thanks and Regards.
Kevin.

danh2000
20 Oct 2009, 11:05 PM
I've update the first post (http://www.extjs.com/forum/showthread.php?p=332654#post332654) with a new version containing:

-Fix to prevent the component receiving focus when reset is called.
-Removed unnecessary usage of trim.
-Fixed bug in setValueEx method.
-Added a new forceFormValue config to force form values (submission or BasicForm.getValues) even when no items selected

The amount of functionality X Ext Versions X Browser Combinations are quite an overhead to test, so please go easy on me if I've broken anything and you find errors - I'll do what I can to resolve any issues in a timely manner.

Regards,

Dan

sdavids
22 Oct 2009, 6:26 AM
I would like to make a suggestion with the SuperBoxSelect's onSelect function - can you add code to call the beforeSelect listener so we can get the same expected functionality with the comboBox?

All you need to do is wrap your onSelect logic with the following:


if (this.fireEvent('beforeselect', this, record, index) !== false){

//............Current Code.............
}

But all in all, really enjoying your work.

antoniode
26 Oct 2009, 1:04 PM
Hi danh2000, I've been trying your hack, and I must say that I really like it.

But trying to implement in a try, I have realized that when the text is too long, it just crop it and don't show in any way. I tried using \n and other stuff, but nothing worked.

Right now I am using a normal combobox, but I do have to repeat it several times to simulate it. With the normal combobox I managed to show the text from a concrete item in different lines (still being selectable as one) in order to completely show it, but I can't do it with SuperBoxSelect.

Any suggestion?

danh2000
26 Oct 2009, 2:39 PM
@antoniode yes it's easy enough - just add the following css to your css file:



.x-superboxselect li {
white-space:normal;
}

antoniode
27 Oct 2009, 11:16 PM
Thank you ;)

That was for the items, and .x-combo-list-item for the combo.

Thank you so much!!

crxtech
29 Oct 2009, 10:45 AM
I've tried with both Ext 2 and 3 and get the same "p is undefined" error on line 690 of superboxselect.js. Anyone else have this error or know how to fix it?

The first superboxselect displays, but doesn't do anything and that as far as the form loads.


var main = new Ext.FormPanel({
id: 'main',
labelAlign: 'side',
labelWidth: 20,
bodyStyle:'padding:5px',
width: 896,
items: [{
xtype: 'superboxselect',
id:'to',
fieldLabel: 'To',
labelStyle: 'font-weight:bold; width:30;',
resizable: true,
name: 'to',
anchor:'95%',
store: emailDS,
mode: 'local',
displayField: 'userName',
displayFieldTpl: '{userName} ({email})',
valueField: 'email',
renderFieldBtns:false
},{
xtype: 'superboxselect',
id:'cc',
fieldLabel: 'Cc',
labelStyle: 'font-weight:bold; width:30;',
resizable: true,
name: 'cc',
anchor:'95%',
store: emailDS,
mode: 'local',
displayField: 'userName',
displayFieldTpl: '{userName} ({email})',
valueField: 'email',
renderFieldBtns:false
}...

danh2000
29 Oct 2009, 5:08 PM
I've tried with both Ext 2 and 3 and get the same "p is undefined" error on line 690 of superboxselect.js. Anyone else have this error or know how to fix it?

...


Impossible to tell because you have snipped your code so I can't reproduce the problem or see where you've gone wrong - I'd guess that your store isn't defined well or that your displayFieldTpl's don't match your records.... you should be able to debug and step through your code to see what's going wrong though.

This is as close an example as I could make, which works without problem:



Ext.onReady(function() {

Ext.QuickTips.init();

var states = new Ext.data.SimpleStore({
fields : ['abbr', 'state', 'nick', 'cls'],
data : Ext.exampledata.states,
sortInfo : {
field : 'state',
direction : 'ASC'
}
});

var main = new Ext.FormPanel({
renderTo : 'f1',
id : 'main',
labelAlign : 'side',
labelWidth : 20,
bodyStyle : 'padding:5px',
width : 896,
items : [{
xtype : 'superboxselect',
id : 's1',
fieldLabel : 'S1',
labelStyle : 'font-weight:bold; width:30;',
resizable : true,
name : 's1',
anchor : '95%',
store : states,
mode : 'local',
displayField : 'state',
valueField : 'abbr',
renderFieldBtns : false
},{
xtype : 'superboxselect',
id : 's2',
fieldLabel : 'S2',
labelStyle : 'font-weight:bold; width:30;',
resizable : true,
name : 's2',
anchor : '95%',
store : states,
mode : 'local',
displayField : 'state',
valueField : 'abbr',
renderFieldBtns : false
}]
});
});

crxtech
30 Oct 2009, 9:36 AM
Impossible to tell because you have snipped your code so I can't reproduce the problem or see where you've gone wrong - I'd guess that your store isn't defined well or that your displayFieldTpl's don't match your records.... you should be able to debug and step through your code to see what's going wrong though.


Thanks for your response. I pasted your example into my code and it still didn't work. After some more digging I found that it conflicts with a dollarfield (http://www.extjs.com/forum/showthread.php?t=35741&highlight=dollarfield) plugin that I am also using on the form. I haven't been able to figure out why the two won't work together, but I have at least been able to get the superboxselect to work in my code without the other plugin. Its very nice. Thanks for your contribution!

Any thoughts on why the two won't work together? I was using boxselect and dollarfield on the form together previously with no problems.

crxtech
30 Oct 2009, 10:03 AM
It seems to be this block of code from dollarfield.js that doesn't get along with superboxselect.js


Ext.override(Ext.Component, {
/* override by Animal (http://extjs.com/forum/showthread.php?t=26484)
that allows us to find the dollar fields parent form. Very nice.
*/
findParentBy: function(fn) {
for (var p = this.ownerCt; (p != null) && !fn(p); p = p.ownerCt);
return p;
},

findParentByType: function(xtype) {
return typeof xtype == 'function' ?
this.findParentBy(function(p){
return p.constructor === xtype;
}) :
this.findParentBy(function(p){
return p.constructor.xtype === xtype;
});
}
});

MarkB
30 Oct 2009, 10:58 AM
Danh,

Have you tried putting SuperBoxSelect on a window and destroyed the window?

I can't destroy a tab panel with your component on it.

It breaks code in ext-base.js ...


if(el.getBoundingClientRect){b=el.getBoundingClientRect();_10=fly(document).getScroll();return[b.left+_10.left,b.top+_10.top];


ExtJS recommended this line of code be moved to a beforedestroy event ..


this.autoSize().manageClearBtn().validateValue();


but that does not help.

Just wondering if you have any ideas.

antoniode
31 Oct 2009, 3:41 AM
Hi again danh2000, I've found what I thing is a bug.

I am using events beforeadd and beforeremove in order to confirm that they really want to do it in some cases, but... I've found the problem, that, despite when I return false in beforeadd, it doesn't add anything, if I return false in beforeremove, it actually does remove it, regardless of the return value.

Should it be that way?

grahamda
3 Nov 2009, 5:15 AM
Hi,

This is a fantastic component thank you very much for making it available.

After some initial trials I think I may have spotted a bug:

The bug can be seen in example 2 on your examplesRemote.html page. If you type in some numbers quickly and hit enter (ie before the ajax data store load happens) the numbers will be added as a new item (in my view this is correct behaviour). If you type in a set of numbers slowly (alowing the ajax store lookup to happen) then press enter the new item is not added correctly it just dissapears.

I also have a question:

In my application i have a number of text fields and in order to achieve a common look and feel I would like the superboxselect to be the same height as the rest of the text boxes. I can achieve this by increacing the height of my text fields to match the superboxselect however this is undesireable. Is there any way to reduce the height of the superboxselect to be the same as the height of a default textfield? (I note that the boxselect upon which your component is based can be the same height as a default textfield see http://www.extjs.com/forum/showthread.php?t=33794)

Thanks very much for all of your work to create this component it is much appreciated.

dj
5 Nov 2009, 10:29 AM
danh2000 thanks for releasing this great component! Am I correct that "@licence TBA" means that you have to decide which licence it will be (TBA = to be announced)?

Did you decide on a licence? What licences do you consider? If you opt for an open source licence (with all the patches others provided here that's probably the only option) http://www.extjs.com/products/ux-exception.php has a rather big list of candidates. Not all of them compatible with using them together with a commercial licenced Ext JS App.

frankthetank
5 Nov 2009, 2:24 PM
Hi,

I love this ux !! I'm using it with 2.2 and everything is working great !
I have one question :

When I click on the Triangle to get the complete list, I can select multiple choices without the list to be closed. I want the same thing to happen when I type the first letters and get multiple choices, when I select a choice, the list is closing so I have to retype again the same first letters.

If there anyway to let the list open till the user is done selecting when he's typing ?

Thanks,
François

radtad
5 Nov 2009, 2:48 PM
Hi,

I love this ux !! I'm using it with 2.2 and everything is working great !
I have one question :

When I click on the Triangle to get the complete list, I can select multiple choices without the list to be closed. I want the same thing to happen when I type the first letters and get multiple choices, when I select a choice, the list is closing so I have to retype again the same first letters.

If there anyway to let the list open till the user is done selecting when he's typing ?

Thanks,
François

How would you know when the user is done typing?

frankthetank
5 Nov 2009, 3:54 PM
How would you know when the user is done typing?

The same way you know he is done selecting on the complete list. You simply click outside of the list.

charleshimmer
16 Nov 2009, 1:54 PM
Great looking plugin. Has anybody tried making it work with a htmleditor? I think this would be perfect for an email template editor where the user can insert data tokens to be replicated by dynamic data.

danh2000
18 Nov 2009, 6:37 PM
Sorry for my lack of responses - I've just moved house to an island that's only accessible by boat. This has been a massive undertaking (especially with a 7 month old baby).

I'll get round to answering questions and fixing bugs when I catch up with my paid jobs.

Thanks,

Dan

antoniode
18 Nov 2009, 10:32 PM
Don't worry, just be fine!

And we will wait till them!

travisbell
20 Nov 2009, 8:48 AM
Hey guys,

I am using a remote store, as well as allowing new data… everything else is working (adding new data, searching for existing records) but I just can't seem to get any initial values to show up.

I am trying to just use:




value: '7,6'



And I can see the 2 requests being made, with the results coming back via ajax but nothing shows up in the superselect. Is there something not so obvious I might be missing?