-
Notifications
You must be signed in to change notification settings - Fork 684
Peformance 3 and Dimensions #735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1. Converted _makeOption to plain JS for speed. This is the last specific jQuery-to-plain-JS conversion that I am planning. 2. Added addInputNames option to allow opting out (false value) of creating name properties for inputs. These names sometimes duplicate what is already in use for the native select and just cause more inputs to be serialized and posted to the server than is needed. (slower) 3. Added caching of button width value, menu width value, menu height value, and positioned status and mechanisms to invalidate the cached status for each. The caching minimizes the recalculation of each of these values when the menu is successively opened. (Just calculated on first open and re-used.) 4. Re-wrote _setMenuHeight: - a. Implement a new "size" keyword for the menuHeight option that sets the menu height based on the number of rows specified in the native select's "size" attribute. If "size" is specified, but no attribute is found on the native select, a default size value of 4 rows is used like is the default for native multiple selects. - b. Also, _setMenuHeight is optimized to execute the least loop iterations to determine the appropriate menu height to use. - c. Lastly, the menu height is limited to the available window.innerHeight value. 5. Changed from using self.element.parent().outerWidth() to using self.element.parent().innerWidth() in _getMinWidth() to fix errors in % width calculations. 6. Tweaked the css file to remove unnecessary tag qualifications that degrade layout efficiency. 7. Tweaked the css file to replace descendent selectors with child selectors where possible for improved layout efficiency.
CHANGELOG.MD
Outdated
| @@ -0,0 +1,13 @@ | |||
| Summary of Code Changes for jQuery UI Multiselect Widget, Version 3.0.0: | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need a changelog file, we'll detail all the enhancements when we release the version 3 tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
css/jquery.multiselect.css
Outdated
| @@ -1,25 +1,29 @@ | |||
| /* References: | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to stop including these reference comments. I was planning on going through and removing all of them from the old code once you were done merging changes.
I don't think they're really necessary and practices will change as web technologies evolve anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you added the auto method anyway. The algorithm you went with appears to be
checking the element to be appended to's width and using that. You're also appending the
menu to the body first, and then appending it to the appendEl. Does this cause excessive
reflowing of elements? Does grabbing the width on the body, and then putting it into another
element reliably work when the menu is inside a dialog?
src/jquery.multiselect.js
Outdated
| // default options | ||
| options: { | ||
| header: true, // (true | false) If true, the header is shown. | ||
| height: 175, // (int | 'size') Sets the height of the menu in pixels. If 'size' is instead specified, the native select's size attribute is instead for height. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your comment here is kind of confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'size' setting just makes the height of the multiselect accommodate what is needed for the # of rows specified via the size setting of the native select. This is actually very useful... it is something I use a lot w/ my implemented version of my old fork in my web app.
I am totally open to less confusing wording.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's mostly a grammar thing:
the native select's size attribute is instead for height.
could maybe be
the native select's size in rows attribute is used instead for height
src/jquery.multiselect.js
Outdated
| var elSelect = $element.get(0); // This would be expected to be the underlying native select element. | ||
| // Performs the initial creation of the widget | ||
| _create: function() { | ||
| var $element = this.element.hide(); // element property is a jQuery object per http://api.jqueryui.com/jQuery.widget/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really see a need for comments describing what a jQuery object is within a jQuery widget. I think you deleted them before too.
src/jquery.multiselect.js
Outdated
| // Performs the initial creation of the widget | ||
| _create: function() { | ||
| var $element = this.element.hide(); // element property is a jQuery object per http://api.jqueryui.com/jQuery.widget/ | ||
| var elSelect = $element.get(0); // This would be expected to be the underlying native select element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's expected to be... Is it not?
src/jquery.multiselect.js
Outdated
|
|
||
| this.$buttonlabel = $( document.createElement('span') ) | ||
| .addClass('ui-multiselect ui-widget ui-state-default ui-corner-all' + (classes ? ' ' + classes : '')) | ||
| .attr({ 'type': 'button', 'title': elSelect.title, 'tabIndex': elSelect.tabIndex, 'id': elSelect.id ? elSelect.id + '_ms' : null }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer you expanded it again, easier to read with the ternary hidden in there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
src/jquery.multiselect.js
Outdated
| if (inputAttribs[name] !== null) | ||
| input.setAttribute(name,inputAttribs[name]); | ||
| } | ||
| if ('dataset' in option) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dataset attribute isn't supported in IE 10, it only got added in 11 and for the time being I would prefer to maintain IE 10 support.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Let me see if I can find a work around.
src/jquery.multiselect.js
Outdated
| $menu.appendTo('body').css({visibility:'hidden', width:'auto', display:'inline'}).find('ul').css('display', 'inline'); | ||
| var autoWidth = $menu.width(); | ||
| $menu.css({visibility:cssVisibility, width:cssWidth, display:cssDisplay}).find('ul').css('display', cssulDisplay).appendTo( appendEl ); | ||
| console.log('AUTO WIDTH: ', cssWidth, autoWidth); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete the console statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Sorry about that. Will remove.
Also, I goofed as I did not intend to include this auto width functionality in this. I am still fiddling with it. I will remove it, also. (sorry)
src/jquery.multiselect.js
Outdated
| var width = self.options.menuWidth; | ||
|
|
||
| if (!width) { // Exact width not provided; determine appropriate width. | ||
| width = self._savedButtonWidth || self.$button.outerWidth(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're in the recalc section here, and still using the saved value. Is that intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not the same width... please examine it more closely.
It is referencing a button width in the setMenuWidth function. Since the button width was just likely already calculated, this just tries to use the recently recalculated cached value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. That makes sense.
|
You're killing me with these whitespace changes... Was it necessary to switch from |
|
My apologies. I apparently was a bit hasty in posting this, and I overlooked some things, and inadvertantly included some things I did not intend to include. Also I will revert some of the things you mention. |
- Removed extra self variables where possible. - Removed reference URLs (against my better judgement). - Used a simple alternative to dataset in _makeOptions (reference _getDataset() in (https://gist.github.com/ShirtlessKirk/6cdc2c32ddd97dc9c706)[https://gist.github.com/ShirtlessKirk/6cdc2c32ddd97dc9c706]) - Deleted spurious console.log statement - Ditched 'auto' setting for minWidth... not really done yet. - Deleted jQuery object comments.
|
I think this should be ready for you to take another look. Thank you for your patience with me. |
|
I'll try to get this code reviewed again today and test it out. I saw this comment in my e-mail, although it doesn't appear to be on this chain anymore. It's worth discussing so I'm going to quote it in and reply anyway:
Useful code comments document document parameters, side effects, and purpose when it isn't clear. Your comment here is an example of a good comment. At first glance, it wouldn't necessarily be obvious to someone new why there are two of these. Reference comments require a contributor to follow a link, that may eventually be dead, and may no longer really apply, rather than actually explaining what the code below did that was so unusual that it required a comment instead of being clear on it's own what the purpose was.
It's not comments I take issue with, I'd love for this source code to eventually adhere to the Google style guide for documentation. There are also a couple of places in this source code where jQuery issues are referenced. Those are useful pieces of information and I have no intention of deleting them.
I would prefer the comments that do need to be in place directly, and in plain language, explain the purpose (or side effects) of the code they are describing. Excessive comments can be just as detrimental to understanding as a lack of comments. Especially if they're used as a band-aid over confusing code that could be made less confusing. |
You're contributing a lot of really helpful changes to the widget, so you're not testing my patience at all. I expect there to be some changes changes necessary on any code review that big. |
|
Looks like this reduced the load time on the speed test from ~1 second on my work computer to .3 seconds. Impressive. |
Converted _makeOption to plain JS for speed. This is the last specific jQuery-to-plain-JS conversion that I am planning.
Added addInputNames option to allow opting out (false value) of creating name properties for inputs.
These names sometimes duplicate what is already in use for the native select and just cause more inputs to be serialized and posted to the server than is needed. (slower)
Added caching of button width value, menu width value, menu height value, and positioned status and mechanisms to invalidate the cached status for each. The caching minimizes the recalculation of each of these values when the menu is successively opened. (Just calculated on first open and re-used.)
Re-wrote _setMenuHeight:
Changed from using self.element.parent().outerWidth() to using self.element.parent().innerWidth() in _getMinWidth() to fix errors in % width calculations.
Tweaked the css file to remove unnecessary tag qualifications that degrade layout efficiency.
Tweaked the css file to replace descendent selectors with child selectors where possible for improved layout efficiency.