jemt / fit.ui Goto Github PK
View Code? Open in Web Editor NEWFit.UI is a JavaScript based UI framework built on Object Oriented principles
Home Page: http://fitui.org
License: GNU Lesser General Public License v3.0
Fit.UI is a JavaScript based UI framework built on Object Oriented principles
Home Page: http://fitui.org
License: GNU Lesser General Public License v3.0
Unfortunately there are a few consistency problems with the Text function. It was ment to deal with pure text, but it can obviously be used to manipulate or get text from elements with more complex structures.
In Internet Explorer Fit.Dom.Text(elm, "New value")
destroys any child elements of 'elm' - they no longer work and cannot be re-added to the DOM. This is due to the use of innerText internally which is destructive in Internet Explorer.
https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
Getting text using Fit.Dom.Text(elm) relies on .textContent if available, otherwise .innerText - but they are not consistent (https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent). For instance innerText takes styling into account (e.g. leaves out hidden elements) while textContent include the content of script tags.
Using innerText seems like the simple solution, but Firexox only recently (2016) added support for this, so all it leaves us with is textContent in Firefox. On the other hand textContent is not available in IE8. On top of that textContent is significantly faster than innerText.
Nested classes such as Fit.Controls.TreeView.Node are not supported in typings (Fit and Controls are declared as namespaces and not classes). To work around this we currently move nested classes and enums to an alternative namespace and declare a property of the moved type on the parent class. For instance Fit.Controls.TreeView.Node is declared like so on the TreeView class:
public static Node : typeof __FitInternals.FitControlsTreeViewNode;
Unfortunately this prevents us from type casting like so:
(obj as Fit.Controls.TreeView.Node).AddChild(..);
or like so:
tree.OnSelect((sender:Fit.Controls.TreeView, node:Fit.Controls.TreeView.Node) => {});
Furthermore Enums are declared as interfaces on the internal namespace as they too cannot be nested within classes. They are also implemented like properties:
public Type(val?:typeof Fit.Controls.Button.Type[keyof __FitInternals.IFitControlsButtonType]):typeof Fit.Controls.Button.Type[keyof __FitInternals.IFitControlsButtonType];
The way Enums are implemented results in Enum values not being considered a common type - take this example:
var type = Fit.Controls.Input.Type.Color;
type = Fit.Controls.Input.Type.Email;
The second assignment produces the following error: [ts] Type '"Email"' is not assignable to type '"Color"'.
Async. operations such as HTTP Requests should return a thenable or promise to support await and .then(..).
A good article on the subject can be found here:
https://developers.google.com/web/fundamentals/primers/promises
Quick and dirty example of the concept of thenables which would be cross browser compatible - the use of promises would not: https://caniuse.com/#feat=promises
async function getData()
{
var callbacks = { resolve: undefined, reject: undefined };
var promise = { then: function(resolve, reject) { callbacks.resolve = resolve; callbacks.reject = reject; } };
setTimeout(function() { callbacks.resolve("Hello world"); }, 2000);
return promise;
}
// Test using .then(..)
getData().then(function(res) { console.log("Thenable result: ", res); });
// Test using await
var result = await getData();
console.log("Awaited result: ", result);
A DropDown control with a TreeView picker throws an error if a selected node is disposed, and the user attempts to make a new selection. The TreeView which is in "picker mode" keeps a reference to the last selected node. But if that node is disposed (destroyed) that object reference will cause errors if any function is invoked on the object (e.g. activeNode.GetDomElement()).
JSFiddle reproducing bug with Fit.UI 1.0.20:
https://fiddle.jshell.net/6ovv6u92/6/
We need to be able to format numbers with both decimal and thousand separators.
Toggling MultiSelectionMode(..) makes it impossible to deselect a node in Single Selection Mode using the TreeView.
Adding a button to a Dialog instant that has not been instantiated with an ID will trigger an error when the dialog is disposed.
http://jsfiddle.net/Jemt/wqfzus50/2/
Work around: Pass an ID to the button in the constructor.
The following exception is thrown when generating documentation, unless an empty line is found in the end of each JS file:
Unhandled Exception:
System.Xml.XmlException: The 'documentation' start tag on line 2 position 2 does not match the end tag of 'container'. Line 2760, position 3.
at SimpleDocs.Parser.Parse (System.String xmlComments, System.Boolean includePrivate) [0x00099] in <555d6fe1509346ed93a3c5aeee8b59bd>:0
at SimpleDocs.MainClass.Main (System.String[] args) [0x001f2] in <555d6fe1509346ed93a3c5aeee8b59bd>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Xml.XmlException: The 'documentation' start tag on line 2 position 2 does not match the end tagof 'container'. Line 2760, position 3.
at SimpleDocs.Parser.Parse (System.String xmlComments, System.Boolean includePrivate) [0x00099] in <555d6fe1509346ed93a3c5aeee8b59bd>:0
at SimpleDocs.MainClass.Main (System.String[] args) [0x001f2] in <555d6fe1509346ed93a3c5aeee8b59bd>:0
To reproduce, simply remove the last empty line in e.g. Controls/Dialog/Dialog.js and execute
cd build && ./Build
DropDown.Dispose() and WSDropDown.Dispose() disposes itself AND contained picker(s).
Dialog.Dispose() disposes itself AND all buttons.
TreeView.Dispose() disposes itself AND all nodes
It seems that at least TreeView.Dispose misbehaves and is inconsistent with the general implementation. While the current implementation allows for multiple trees to share one common ContextMenu instance, nothing is worse than inconsistency and potential memory leaks. We should fix this. If we don't want TreeView.Dispose() to dispose the ContextMenu instance, we can unset it first like so:
tv.ContextMenu(null);
tv.Dispose();
This will prevent TreeView from disposing the instance.
We currently have now good way to indicate that a function argument can be null. A work around is to set default="undefined" but that is used to indicate that the argument can be omitted. We have already applied this work around a couple of times:
Implement support for something like nullable="true|false" in SimpleDocs and make TypingsGenerator support this addition. AND - make sure to update commits listed above to use the new approach.
Consider the following call:
Fit.Validation.ExpectInstance(sender, {});
The following error will be thrown because {} is not callable:
VM1662:1 Uncaught TypeError: Right-hand side of 'instanceof' is not callable
The function is expected to throw: "Unsupported object type passed"
https://github.com/Jemt/Fit.UI/blob/master/Core/Validation.js#L358
The line causing the problem is this:
if ((val instanceof instanceType) === true || Fit.Core.Extends(val, instanceType) === true)
https://github.com/Jemt/Fit.UI/blob/master/Core/Validation.js#L355
Use Try/Catch to make sure Fit.UI is capable of throwing the intended error.
It would be useful being able to populate a TreeView and DropDown from a JSON object.
Example: http://fiddle.jshell.net/3cr27m6g
JavaScript (and Fit.UI) does midpoint (.5) rounding like shown below (always up towards positive).
1.5 = 2
-1.5 = -1
In financial systems we may want to round negative numbers (e.g. a discount in a web shop) away from zero like so:
1.5 = 2
-1.5 = -2
The last implementation is the default behaviour of round(..) in PHP while .NET has a strange default implementation that rounds differently depending on whether the integer part is odd or even:
1.5 = 2 (rounds up towards even number)
2.5 = 2 (rounds down towards even number)
-1.5 = -2 (rounds down towards even negative number)
-2.5 = -2 (rounds up towards even negative number)
.NET has two rounding techniques (AwayFromZero and ToEven: https://msdn.microsoft.com/da-dk/library/system.midpointrounding(v=vs.110).aspx) while PHP has four (PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD: http://php.net/round).
I recommend implementing the three approaches to rounding outlined below. They does rounding consistently (contrary to .NET). There might be scientific reasons for supporting other rounding techniques, but let's focus on those that makes sense to most people right now.
MidpointRounding.AwayFromZero, precision 0 (PHP default)
1.5 = 2
-1.5 = -2
MidpointRounding.Up, precision 0 (JavaScript behaviour)
1.5 = 2
-1.5 = -1
MidpointRounding.Down, precision 0 (If we have .Up it makes sense to have the opposite as well)
1.5 = 1
-1.5 = -2
Remember, MidpointRounding only affects the midpoint (.5). By default rounding is always "Away from zero" for both positive and negative values. Therefore it seems to make sense to have Fit.Math.Round use Fit.Math.MidpointRounding.AwayFromZero by default.
Not all controls/components inherit from a common interface.
Base classes:
Inheriting from ControlBase (edit controls):
Inheriting from PickerBase (defined by DropDown):
Not inheriting from anything:
These components have to implement the same logic again and again (e.g. support for Fit.Controls.Find(..)). But what's equally annoying, is that we have to use feature detection to determine whether a component is for instance disposable or not - we cannot simply rely on type information.
We actually have other objects that also doesn't inherit from anything, but that's alright as they are not intended for use as separate components, but as child components:
What we want is for all objects useful as separate UI components to at least implement the following basic functionality. First and foremost to reduce duplicated code and ensure consistency, and to ensure that all components can reliably be disposed without relying on feature detection.
Input (not HTML editor) and DatePicker does not dispose well when the controls have focus while being disposed. This JSFiddle demonstrates the problem:
http://jsfiddle.net/Jemt/1v5fjszn/12/
Set focus in the traditionel input field or in the datepicker (either date portion or time portion), change the value, and close the dialog using ESC on the keyboard. An error is now thrown in Developer Tools.
Notice that I sometimes experienced that the error was suppressed unless I enabled "Pause on exceptions", and even in that case nothing happened on the Source tab - I had to investigate the issue using the Console tab.
The bug has been reported to the Chrome team:
https://bugs.chromium.org/p/chromium/issues/detail?id=866242
Everything works as expected in Safari, Firefox, and Edge.
This bug has been extracted from #18 (second issue described).
When the value of a picker control in a drop down control is changed, the picker control fires OnItemSelectionChanged which the drop down control uses to receive information about changes to selected values in the picker control. When this event is fired, the DropDown control assumes it is fired because the user changed the value by interacting with the control. But the picker control's value could in fact also have been changed programmatically, in which case the drop down control should not gain focus.
Ideally the OnItemSelectionChanged event should pass a flag indicating whether changes to picker value was programmatically triggered or not.
A screenshot has been attached suggesting the use case of such a flag in the Drop Down control. See line 582 and 625.
EDIT: It would probably be prettier to use the eventArgs to carry this information!
This is considered a minor bug. Most often the value would have been assigned to the drop down control rather than the internal picker control obtained through dropDown.GetPicker().
The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
var obj = { Name: "Jimmy", Age: Infinity };
var ob2 = Fit.Core.Clone(obj);
Fit.Core.IsEqual(obj, ob2); // Returns False, expected True
The dialog component automatically scales to content, but to no more than 40% (max-width) of the total width of the screen. On lower resolutions it increases the max-width.
This takes away control from the developer. Who says 40% is desired?
If the content is set to a fixed width of let's say 800px, and the screen is 1024px wide,
then the dialog will reduce its size to 410px, causing the content (with a fixed size) to overflow the boundaries of the dialog.
It might be a good idea to provide some control over the width of the dialog using the API, for instance:
dia.Width(50, "%");
dia.MaxWidth(800);
dia.minWidth(600, "px");
This will allow the content within the dialog to adjust to the size of the dialog instead of the other way around. It would also allow for easy mobile optimization.
The developer should be able to return back to "auto sizing", e.g. by calling:
dia.Width(-1) as defined by ControlBase.
DropDown should open menu above itself if sufficient space is not available below control.
If sufficient space is not available above control either, determine whether most space is available above or below control, resize menu height to make it fit, and position menu where appropriate.
Code: https://github.com/Jemt/Fit.UI/blob/master/Controls/DropDown/DropDown.js#L1235
Repositioning is possible using margin-top with a negative margin (see screenshot above).
Make sure behaviour can be enabled/disabled - it should be On by default.
Note to self: It should probably be disabled in CF if hosted within a frame to avoid breaking "overflow boundaries". Something like:
var isFramed = (window.parent !== window);
dropdown.DetectBoundaries(isFramed === false);
Using the recursion functions you're often faced with a situation where you need to extract information from the parent path or current recursion path, like e.g. figuring out the current recursion level or coordinate.
Please include a Path parameter to the callback signature and populate this with the items "above" current item in the hierarchy.
Opening a ContextMenu within a dialog causes the ContextMenu to become hidden behind the dialog. That's because the Z-Index of Dialog is greater than the Z-Index of ContextMenu.
If a dialog is opened from a context menu this approach makes sense. But in most cases the context menu will close in this case. Therefore it probably makes better sense to make the Z-Index of ContextMenu greater than the Z-Index of Dialog.
In reality the problem is that the ContextMenu DOM element is placed in <body>
rather than the DOM element representing the Dialog, but the ContextMenu should not have any knowledge about the container in which it is being used so we'll have to handle this using Z-Index.
Starting a request to an unknown/invalid domain does not trigger OnFailure, but ends up failing with message net::ERR_NAME_NOT_RESOLVED
Minor issue:
Although the use of ValidationExpression and ValidationCallback is probably rare on TreeView, the feature is still exposed and could potentially be used. It's inherited from ControlBase.
The control container hides overflowing elements. Therefore, the tooltip revealing the cause of the validation problem does not show.
The best option is probably to do some alternative positioning for the tooltip, although it will almost certainly require use of JavaScript in case scroll is enabled within the control (if Height is set) or on the page, if we want the tooltip to stay within the visible area. But since a control that fails validation is clearly highlighted, it's fair to have the user check the validation error at the top - at least for now. Therefore, the solution is fairly simple. Below is an example of the CSS override necessary for the tooltip on modern browsers:
.FitUiControlTreeView[data-valid="false"][data-errormessage][data-focused="false"]:not(#LegacyIE):hover:before,
.FitUiControlTreeView[data-valid="false"][data-errormessage][data-focused="true"]:not(#LegacyIE):before
{
-webkit-transform: inherit;
transform: inherit;
position: static;
display: block;
}
This will cause the tooltip to be shown at the top of the control, and push nodes below the tooltip to prevent them from being hidden below the tooltip, which would have made it impossible to change the selection for the first couple of nodes.
See attached screenshot.
When control is contained in a scrollable parent, and control has been partially scrolled out of view, the drop down element is stilled positioned relative to the control which creates an odd "hole" in the page between the drop down element and the control. It would make better sense to position the drop down element relative to the visible portion of the control which would be the start of the scrollable parent (excluding margin and border).
The box with the red border is scrollable, and the control has been scrolled out of view. Scrollbars are hidden on MacOS by default.
Use https://jsfiddle.net/towy2skm/8/ to reproduce the error.
Simply click the "Create editor" button to trigger the error (check Console in Developer Tools).
ckeditor.js:332 Uncaught TypeError: Cannot read property 'setSize' of undefined
at a.CKEDITOR.editor.resize (ckeditor.js:332)
at updateDesignEditorSize (Fit.UI.js:14525)
at Fit.Controls.Input.Width (Fit.UI.js:14058)
at window.createEditor ((index):53)
at HTMLButtonElement.onclick ((index):78)
A Required Checkbox should cause IsValid() to return false and control should be highlighted with a red border.
FilePicker throws the following error in Legacy Mode (Internet Explorer 8).
https://jsfiddle.net/f9pzm604/2/
Fit.UI.js:994 Uncaught Error: Unable to insert element - target is not rooted
at Object.Fit.Validation.ThrowError (VM61 Fit.UI.js:994)
at Object.Fit.Dom.InsertBefore (VM61 Fit.UI.js:3584)
at VM61 Fit.UI.js:13717
at Object.Fit.Array.ForEach (VM61 Fit.UI.js:1119)
at Fit.Controls.FilePicker.Upload (VM61 Fit.UI.js:13588)
at (index):205
at VM61 Fit.UI.js:7583
at Object.Fit.Array.ForEach (VM61 Fit.UI.js:1119)
at Fit.Controls.Button.Click (VM61 Fit.UI.js:7581)
at HTMLDivElement.<anonymous> (VM61 Fit.UI.js:7368)
Fit.Validation.ThrowError @ Fit.UI.js:994
Fit.Dom.InsertBefore @ Fit.UI.js:3584
(anonymous) @ Fit.UI.js:13717
Fit.Array.ForEach @ Fit.UI.js:1119
Upload @ Fit.UI.js:13588
(anonymous) @ (index):205
(anonymous) @ Fit.UI.js:7583
Fit.Array.ForEach @ Fit.UI.js:1119
Click @ Fit.UI.js:7581
(anonymous) @ Fit.UI.js:7368
Please include an index parameter to the callback signature of Fit.Array.ForEach. Currently only the iteration item is passed.
See https://github.com/Jemt/Fit.UI/blob/master/Core/ControlBase.js#L478
The function set using ControlBase.SetValidationCallback(..) is only provided with the updated value, not the control (sender) triggering the callback.
Rather than a callback like:
control.SetValidationCallback(function(value) { ... }, "Error!")
we instead want something like:
control.SetValidationCallback(function(sender, value) { ... }, "Error!")
This is a breaking change unless we introduce a new setter function - e.g.:
control.SetValidation**Handler**(function(sender, value) { ... }, "Error!")
If we introduce a new function, make sure the old emits a deprecation warning (but probably only one - we do not want to spam the log!)
It is not possible to add a white space to the input field in the DropDown control if the picker control being used is TreeView, because Spacebar is used to toggle selections. The following snippet demonstrates the problem:
https://jsfiddle.net/72q6torz/
The toggle behaviour should be suppressed when the input field is not empty.
Consider the following example:
var t = new Fit.Template();
t.LoadHtml("{MyControl}");
t.Content.MyControl = new Fit.Controls.Input();
t.Render(document.body);
If we want to get rid of the template above, there is no way of disposing it.
Fit.Template.Dispose() is missing!
Also, consider this example:
var t = new Fit.Template(true); // True = allow updates
t.LoadHtml("{[MyControl]}");
t.Content.MyControl = new Fit.Controls.Input();
t.Render(document.body);
t.Content.MyControl = null;
t.Update();
MyControl is not disposed when calling Update() since Render() did not store the control internally to allow Update to get rid of it again.
Work around for second example:
Rather than posting "false", an empty string is posted to the server if the checkbox is initially unchecked.
Loading Fit.UI using a module loader may prevent it from obtaining its path to resources, so we need to introduce something like Fit.SetUrl(..). We already have Fit.SetPath(..) which can be used when loading Fit.UI as a module from the same domain, but that too only works when loading happens from a script block without a src attribute - otherwise Fit.UI assumes it can parse its location from the src attribute which may be a completely different script ensuring Fit.UI using a module loader.
Using Fit.Template in a React like style where everything is re-created and re-rendered multiple times results in increased memory consumption over time if previously added UI controls are not either disposed or reused.
Allowing Fit.Template to automatically dispose controls that have been removed after pushing changes to DOM would eliminate the need for the developer to manually handle memory usage.
However, we need to make sure that developers that wants to be switch different controls in and out of the view over time can do so without Fit.Template disposing their controls, so we should be able to disable the behaviour. I suggest that auto disposing is ON by default and can be disabled when creating the template instance:
Fit.Template = function(refreshable = false, autoDispose = true)
So basically Fit.Template keeps an index of all Fit.UI controls added, and after pushing updates it makes a diff between the new collection of UI controls and the old, and disposes all the old controls that are no longer part of the view.
DropDown magically gains focus if Clear() or ClearSelections() is called programmatically. These functions may also be used internally, e.g. when Value(newVal) is invoked.
The problem seems to be related to communication with the picker control which fires OnItemSelectionChanged to keep DropDown informed about changed selections in picker control. The OnItemSelectionChanged callback registered in DropDown assigns focus to the DropDown control because the event is assumed to be triggered when values are changed by interacting with the picker control - but the event is also fired when programmatically changing/clearing the control value using e.g. DropDown.Clear().
Calling Clear() or ClearSelections() should make DropDown suppress/ignore OnItemSelectionChanged when fired. We only need to handle this event when changes to data comes from the picker control (which is not the case when calling e.g. DropDown.Clear()). Ignoring the event will fix the problem when programmatically changing the value like so (control must already have a value set to trigger bug):
dropDown.Clear();
dropDown.ClearSelections(); // TODO: Set flag to have OnItemSelectionChanged ignored
dropDown.Value("James Thompson=jat");
Ideally, the OnItemSelectionChanged event should also pass a flag to event handlers indicating whether a selection was made by user interaction or programmatically. The fix suggested above (1) will NOT prevent focus from being assigned if value is assigned programmatically using the internal picker like so (in this case the control can be both empty and have a value set - the bug will be triggered in any case):
var treeView = dropDown.GetPicker();
treeView.Value("James Thompson=jat");
It would be convenient if Fit.Http provided support for file downloads. Either on Fit.Http.Request or as a separate class. The solution should provide all the options to include data and headers in the request, so including it in Fit.Http.Request would allow the functionality to extend to all the request classes.
Downloading a file requires setting reponseType like so:
request.RequestProperties({ responseType: "blob" }); // IE10+ and modern browsers
To retrieve the file and serve it to the client we can do the following in the OnSuccess handler:
var blob = sender.GetResponse();
var filename = "Data.xlsx";
if (window.navigator.msSaveOrOpenBlob) // IE
{
if (filename)
window.navigator.msSaveOrOpenBlob(blob, filename);
else
window.navigator.msSaveOrOpenBlob(blob);
}
else // Modern browsers
{
var a = document.createElement("a");
var url = window.URL.createObjectURL(blob);
a.href = url;
if (filename)
a.download = "MyFile.xlsx";
a.style.display = "none";
document.body.appendChild(a); // Must be appended to DOM to work in FireFox
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}
NOTICE that the responseType property requires IE10+.
Is support for IE8-9 achievable? Perhaps look at this:
When WSDropDown is configured with MultiSelectionMode(true), nodes loading using WebService need not set Selectable flag to become selectable. However, nodes are not selectable by default in Single Selection Mode.
Demo: http://fiddle.jshell.net/kd9nw2vk/1/
See source code for Fit.Browser.GetQueryString(..):
https://github.com/Jemt/Fit.UI/blob/master/Core/Browser.js#L125
Notice how parameter values are decoded but parameter keys are not. This seems wrong since both keys and values may contain encoded characters.
Expanding and loading data for multiple nodes simultaneously might trigger the following error and cause one (or more) of the loading indicators to get stuck (not removed):
Uncaught Error: Value 'null' is not a DOMElement
WSTreeView does not take into account that data can be loaded for multiple nodes simultaneously.
The loading indicator should be associated with a request, and not be a "global" variable for all requests within the WSTreeView instance.
Calling the
Fit.Events.RemoveHandler(elm, eventType, function) or
Fit.Events.RemoveHandler(elm, eventType, capture, function) overloaded functions multiple times on the same element result in the following error:
Fit.UI.js:4845 Uncaught TypeError: Cannot read property 'Event' of null
The bug can be reproduced using the following example.
var d = Fit.Dom.CreateElement("<div>");
var f = function(e) { console.log("Test"); };
var eId1 = Fit.Events.AddHandler(d, "click", f);
var eId2 = Fit.Events.AddHandler(d, "mousedown", f);
var eId3 = Fit.Events.AddHandler(d, "mouseup", f);
Fit.Events.RemoveHandler(d, "click", f);
Fit.Events.RemoveHandler(d, "mousedown", f); // Throws error because we removed eId2
Work around
Use the Fit.Events.RemoveHandler(elm, eventId) function instead to work around this bug until it is resolved.
See JSFiddle that demonstrates the problem and suggests a fix:
https://fiddle.jshell.net/gnnxt31t/3/
Being able to disable a control seems rather fundamental, so we need to implement such functionality on ControlBase. Until implemented the work around below may be helpful to some.
(function()
{
var dd = Fit.Controls.Find("DropDown1");
var val = dd.Value();
var dom = dd.GetDomElement();
Fit.Events.AddHandler(dom, "click", true, function(e) { Fit.Events.StopPropagation(e); });
Fit.Events.AddHandler(dom, "mousedown", true, function(e) { Fit.Events.StopPropagation(e); });
Fit.Events.AddHandler(dom, "mouseup", true, function(e) { Fit.Events.StopPropagation(e); });
Fit.Array.ForEach(dom.querySelectorAll("input"), function(inp) { inp.setAttribute("tabindex", "-1"); });
dd.OnChange(function(sender) { if (dd.Value() !== val) dd.Value(val); });
dom.style.opacity = "0.5";
})();
Testing 1-2-3
Being able to determine when a control is rooted in DOM would be helpful.
When calling Dispose() on WSDropDown, not all internal resources are cleaned up properly. Creating a new control with the same ID is not possible - an error is emitted:
ThrowError: Control with ID 'CTL_DropDown1__WSListView' has already been defined - Control IDs must be unique!
Also, DropDown, from which WSDropDown inherits, defines an OnClick handler on 'document' which is not removed when disposing control, causing an error when clicking anywhere on the page after the control is disposed. Search for the code below in DropDown.js to find the event handler causing the problem:
Fit.Events.AddHandler(document, "click", function(e)
See https://jsfiddle.net/Jemt/1v5fjszn/4/
Notice how the DatePicker's calendar widgets is hidden behind the dialog. We need to raise it's z-index to 1300 like done for ContextMenu (#28). The problem with the calendar widget is identical to the one we had for ContextMenu.
new Fit.Controls.Input(Fit.Data.CreateGuid())
A DropDown configured with a responsive width (e.g. dropdown.Width(80, "%")) may throw the following error when disposed:
VM2994 Fit.UI.js:12254 Uncaught TypeError: Cannot read property 'MultiSelectionMode' of null
at optimizeTabOrder (VM34 Fit.UI.js:12254)
at VM34 Fit.UI.js:10846
JSFiddle reproducing the problem: https://jsfiddle.net/3uo6a7fj/12/
The DropDown in the fiddle is automatically disposed at the critical moment where the bug can be triggered,
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.