fit-ui 2.10.13 → 2.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Documentation.html +2 -2
- package/dist/Fit.UI.js +199 -96
- package/dist/Fit.UI.min.js +1 -1
- package/dist/Resources/CKEditor/contents.css +208 -208
- package/dist/Resources/CKEditor/plugins/autocomplete/skins/default.css +38 -38
- package/dist/Resources/CKEditor/plugins/dialog/styles/dialog.css +18 -18
- package/dist/Resources/CKEditor/plugins/emoji/skins/default.css +237 -237
- package/dist/Resources/CKEditor/skins/moono-lisa/dialog.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/dialog_ie.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/dialog_ie8.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/dialog_iequirks.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/editor.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/editor_gecko.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/editor_ie.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/editor_ie8.css +4 -4
- package/dist/Resources/CKEditor/skins/moono-lisa/editor_iequirks.css +4 -4
- package/dist/Resources/CKEditor/styles.js +137 -137
- package/package.json +1 -1
- package/types/index.d.ts +35 -6
package/dist/Fit.UI.js
CHANGED
|
@@ -682,7 +682,7 @@ Fit._internal =
|
|
|
682
682
|
{
|
|
683
683
|
Core:
|
|
684
684
|
{
|
|
685
|
-
VersionInfo: { Major: 2, Minor:
|
|
685
|
+
VersionInfo: { Major: 2, Minor: 11, Patch: 2 } // Do NOT modify format - version numbers are programmatically changed when releasing new versions - MUST be on a separate line!
|
|
686
686
|
}
|
|
687
687
|
};
|
|
688
688
|
|
|
@@ -2219,17 +2219,29 @@ for (var i in vals = [1,3,6,8])
|
|
|
2219
2219
|
Fit.Browser = {};
|
|
2220
2220
|
Fit._internal.Browser = {};
|
|
2221
2221
|
|
|
2222
|
+
// Allow Fit.Browser unit tests to override user agent information
|
|
2223
|
+
// to test parsing of a range of different user agent strings.
|
|
2224
|
+
Fit._internal.Browser.UserAgent = navigator.userAgent;
|
|
2225
|
+
|
|
2222
2226
|
/// <function container="Fit.Browser" name="GetBrowser" access="public" static="true" returns='"Edge" | "Chrome" | "Safari" | "MSIE" | "Firefox" | "Opera" | "Unknown"'>
|
|
2223
2227
|
/// <description>
|
|
2224
|
-
/// Returns name of browser
|
|
2225
|
-
///
|
|
2228
|
+
/// Returns name of browser useful for adjusting behaviour based on render engine.
|
|
2229
|
+
/// Possible values are: Chrome (both WebKit and Blink based - also returned for modern versions of
|
|
2230
|
+
/// Opera and Edge), Safari (also returned for Edge, Chrome, Opera, and Firefox on iOS), Edge (version 12-18),
|
|
2231
|
+
/// MSIE (version 8-11), Firefox, Opera (version 1-12), and Unknown.
|
|
2226
2232
|
/// </description>
|
|
2227
2233
|
/// <param name="returnAppId" type="false" default="false"> Set True to have app specific identifier returned </param>
|
|
2228
2234
|
/// </function>
|
|
2229
|
-
/// <function container="Fit.Browser" name="GetBrowser" access="public" static="true" returns='"Edge" | "
|
|
2235
|
+
/// <function container="Fit.Browser" name="GetBrowser" access="public" static="true" returns='"Edge" | "Chrome" | "Safari" | "MSIE" | "Firefox" | "Opera" | "Unknown"'>
|
|
2230
2236
|
/// <description>
|
|
2231
|
-
/// Returns browser app
|
|
2232
|
-
///
|
|
2237
|
+
/// Returns browser app name useful for adjusting behaviour based on actual
|
|
2238
|
+
/// application, regardless of render engine and platform. Possible values are:
|
|
2239
|
+
/// Chrome (both Webkit and Blink based), Safari, Edge (both legacy and modern),
|
|
2240
|
+
/// MSIE (version 8-11), Firefox, Opera (both legacy and modern), and Unknown.
|
|
2241
|
+
/// Be careful not to check against browser app name and app version alone.
|
|
2242
|
+
/// For instance Opera 3 on a touch device is newer than Opera 60 on a Desktop
|
|
2243
|
+
/// device, as they are two completely different browsers. Check whether the browser runs on
|
|
2244
|
+
/// a tablet or phone using e.g. Fit.Browser.IsMobile(true) or Fit.Browser.GetInfo(true).IsMobile.
|
|
2233
2245
|
/// </description>
|
|
2234
2246
|
/// <param name="returnAppId" type="true"> Set True to have app specific identifier returned </param>
|
|
2235
2247
|
/// </function>
|
|
@@ -2237,7 +2249,7 @@ Fit.Browser.GetBrowser = function(returnAppId)
|
|
|
2237
2249
|
{
|
|
2238
2250
|
Fit.Validation.ExpectBoolean(returnAppId, true);
|
|
2239
2251
|
|
|
2240
|
-
var agent =
|
|
2252
|
+
var agent = Fit._internal.Browser.UserAgent;
|
|
2241
2253
|
|
|
2242
2254
|
// IMPORTANT: The order in which browsers are detected matters! For instance, several browsers define both Chrome and Safari as part of their user agent string. Examples:
|
|
2243
2255
|
// Firefox 46 "Mozilla/5.0 (Windows NT 5.2; rv:46.0) Gecko/20100101 Firefox/46.0"
|
|
@@ -2251,20 +2263,18 @@ Fit.Browser.GetBrowser = function(returnAppId)
|
|
|
2251
2263
|
// Edge 18 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363"
|
|
2252
2264
|
// Edge 85 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.41"
|
|
2253
2265
|
|
|
2254
|
-
if (agent.indexOf("Edge/") > -1)
|
|
2255
|
-
return "Edge";
|
|
2256
|
-
if (returnAppId === true && agent.indexOf("Edg/") > -1)
|
|
2257
|
-
return "EdgeChromium";
|
|
2266
|
+
if (agent.indexOf("Edge/") > -1 || (returnAppId === true && (agent.indexOf("Edg/") > -1 || agent.indexOf("EdgiOS/") > -1 || agent.indexOf("EdgA/") > -1)))
|
|
2267
|
+
return "Edge"; // Legacy Edge is identified by "Edge/", Chromium based Edge is identified by "Edg/", Edge on iOS is identified by "EdgiOS/", and Edge on Android is identified by "EdgA/"
|
|
2258
2268
|
if (agent.indexOf("MSIE") > -1 || agent.indexOf("Trident") > -1)
|
|
2259
2269
|
return "MSIE";
|
|
2260
|
-
if (agent.indexOf("
|
|
2261
|
-
return "
|
|
2262
|
-
if (agent.indexOf("
|
|
2263
|
-
return "Opera";
|
|
2264
|
-
if (returnAppId === true && agent.indexOf("
|
|
2265
|
-
return "
|
|
2266
|
-
if (agent.indexOf("Chrome") > -1)
|
|
2267
|
-
return "Chrome";
|
|
2270
|
+
if (agent.indexOf("Opera") > -1 || (returnAppId === true && (agent.indexOf("OPR/") > -1 || agent.indexOf("OPT/") > -1)))
|
|
2271
|
+
return "Opera"; // Legacy Opera is identified by "Opera", Chromium based Opera is identified by "OPR/", and Opera on iOS is identified by "OPT/"
|
|
2272
|
+
if (agent.indexOf("OPT/") > -1 && (agent.indexOf("iPhone;") > -1 || agent.indexOf("iPad;") > -1))
|
|
2273
|
+
return "Safari"; // Opera on iOS does not contain "Opera", nor "Safari" to identify the engine like other browsers using WebView - we can use "OPT/" plus "iPhone;" or "iPad;" instead
|
|
2274
|
+
if (agent.indexOf("Firefox") > -1 || (returnAppId === true && agent.indexOf("FxiOS/") > -1))
|
|
2275
|
+
return "Firefox"; // Firefox is identified by "Firefox" except on iOS where "FxiOS/" identifies it instead
|
|
2276
|
+
if (agent.indexOf("Chrome") > -1 || (returnAppId === true && agent.indexOf("CriOS/") > -1))
|
|
2277
|
+
return "Chrome"; // Chrome is identified by "Chrome" except on iOS where "CriOS/" identifies it instead
|
|
2268
2278
|
if (agent.indexOf("Safari") > -1)
|
|
2269
2279
|
return "Safari";
|
|
2270
2280
|
|
|
@@ -2298,37 +2308,56 @@ Fit.Browser.GetVersion = function(returnAppVersion)
|
|
|
2298
2308
|
|
|
2299
2309
|
var start = 0;
|
|
2300
2310
|
var end = 0;
|
|
2301
|
-
var agent =
|
|
2311
|
+
var agent = Fit._internal.Browser.UserAgent;
|
|
2302
2312
|
|
|
2303
2313
|
if (browser === "Edge")
|
|
2304
2314
|
{
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
}
|
|
2310
|
-
if (browser === "EdgeChromium")
|
|
2311
|
-
{
|
|
2312
|
-
start = agent.indexOf("Edg/");
|
|
2313
|
-
start = (start !== -1 ? start + 4 : 0);
|
|
2315
|
+
var search = agent.indexOf("Edge/") > -1 && "Edge/" || agent.indexOf("Edg/") > -1 && "Edg/" || agent.indexOf("EdgiOS/") > -1 && "EdgiOS/" || agent.indexOf("EdgA/") > -1 && "EdgA/" || null;
|
|
2316
|
+
|
|
2317
|
+
start = search !== null && agent.indexOf(search) || -1;
|
|
2318
|
+
start = (start !== -1 ? start + search.length : 0);
|
|
2314
2319
|
end = agent.indexOf(".", start);
|
|
2315
2320
|
end = (end !== -1 ? end : 0);
|
|
2316
2321
|
}
|
|
2317
|
-
if (browser === "Chrome")
|
|
2322
|
+
else if (browser === "Chrome")
|
|
2318
2323
|
{
|
|
2319
|
-
|
|
2320
|
-
|
|
2324
|
+
var search = agent.indexOf("Chrome/") > -1 && "Chrome/" || agent.indexOf("CriOS/") > -1 && "CriOS/" || null;
|
|
2325
|
+
|
|
2326
|
+
start = search !== null && agent.indexOf(search) || -1;
|
|
2327
|
+
start = (start !== -1 ? start + search.length : 0);
|
|
2321
2328
|
end = agent.indexOf(".", start);
|
|
2322
2329
|
end = (end !== -1 ? end : 0);
|
|
2323
2330
|
}
|
|
2324
|
-
if (browser === "Safari")
|
|
2331
|
+
else if (browser === "Safari")
|
|
2325
2332
|
{
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2333
|
+
var search = agent.indexOf("CriOS/") > -1 && "CriOS/" || agent.indexOf("FxiOS/") > -1 && "FxiOS/" || agent.indexOf("EdgiOS/") > -1 && "EdgiOS/" || agent.indexOf("OPT/") > -1 && "OPT/" || null;
|
|
2334
|
+
|
|
2335
|
+
if (search !== null) // Browser based on WebView on iOS - Chrome, Firefox, Edge, or Opera
|
|
2336
|
+
{
|
|
2337
|
+
if (returnAppVersion !== true) // Return Safari version parsed from OS version
|
|
2338
|
+
{
|
|
2339
|
+
start = agent.indexOf(" OS ");
|
|
2340
|
+
start = (start !== -1 ? start + 4 : 0);
|
|
2341
|
+
end = agent.indexOf("_", start);
|
|
2342
|
+
end = (end !== -1 ? end : 0);
|
|
2343
|
+
}
|
|
2344
|
+
else // Return application version
|
|
2345
|
+
{
|
|
2346
|
+
start = agent.indexOf(search);
|
|
2347
|
+
start = (start !== -1 ? start + search.length : 0);
|
|
2348
|
+
end = agent.indexOf(".", start);
|
|
2349
|
+
end = (end !== -1 ? end : 0);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
else // Real Safari or Firefox on iPad which does not identify itself as Firefox
|
|
2353
|
+
{
|
|
2354
|
+
start = agent.indexOf("Version/");
|
|
2355
|
+
start = (start !== -1 ? start + 8 : 0);
|
|
2356
|
+
end = agent.indexOf(".", start);
|
|
2357
|
+
end = (end !== -1 ? end : 0);
|
|
2358
|
+
}
|
|
2330
2359
|
}
|
|
2331
|
-
if (browser === "MSIE")
|
|
2360
|
+
else if (browser === "MSIE")
|
|
2332
2361
|
{
|
|
2333
2362
|
if (agent.indexOf("MSIE") > -1)
|
|
2334
2363
|
{
|
|
@@ -2345,37 +2374,21 @@ Fit.Browser.GetVersion = function(returnAppVersion)
|
|
|
2345
2374
|
end = (end !== -1 ? end : 0);
|
|
2346
2375
|
}
|
|
2347
2376
|
}
|
|
2348
|
-
if (browser === "Firefox")
|
|
2377
|
+
else if (browser === "Firefox")
|
|
2349
2378
|
{
|
|
2350
|
-
|
|
2351
|
-
start = (start !== -1 ? start + 8 : 0);
|
|
2352
|
-
end = agent.indexOf(".", start);
|
|
2353
|
-
end = (end !== -1 ? end : 0);
|
|
2354
|
-
}
|
|
2355
|
-
if (browser === "Opera")
|
|
2356
|
-
{
|
|
2357
|
-
start = agent.indexOf("Version/");
|
|
2358
|
-
start = (start !== -1 ? start + 8 : -1);
|
|
2359
|
-
|
|
2360
|
-
if (start === -1)
|
|
2361
|
-
{
|
|
2362
|
-
start = agent.indexOf("Opera/");
|
|
2363
|
-
start = (start !== -1 ? start + 6 : -1);
|
|
2364
|
-
}
|
|
2365
|
-
|
|
2366
|
-
if (start === -1)
|
|
2367
|
-
{
|
|
2368
|
-
start = agent.indexOf("Opera ");
|
|
2369
|
-
start = (start !== -1 ? start + 6 : -1);
|
|
2370
|
-
}
|
|
2379
|
+
var search = agent.indexOf("Firefox/") > -1 && "Firefox/" || agent.indexOf("FxiOS/") > -1 && "FxiOS/" || null;
|
|
2371
2380
|
|
|
2381
|
+
start = search !== null && agent.indexOf(search) || -1;
|
|
2382
|
+
start = (start !== -1 ? start + search.length : 0);
|
|
2372
2383
|
end = agent.indexOf(".", start);
|
|
2373
2384
|
end = (end !== -1 ? end : 0);
|
|
2374
2385
|
}
|
|
2375
|
-
if (browser === "
|
|
2386
|
+
else if (browser === "Opera")
|
|
2376
2387
|
{
|
|
2377
|
-
|
|
2378
|
-
|
|
2388
|
+
var search = agent.indexOf("Version/") > -1 && "Version/" || agent.indexOf("Opera ") > -1 && "Opera " || agent.indexOf("Opera/") > -1 && "Opera/" || agent.indexOf("OPR/") > -1 && "OPR/" || agent.indexOf("OPT/") > -1 && "OPT/" || null;
|
|
2389
|
+
|
|
2390
|
+
start = search !== null && agent.indexOf(search) || -1;
|
|
2391
|
+
start = (start !== -1 ? start + search.length : 0);
|
|
2379
2392
|
end = agent.indexOf(".", start);
|
|
2380
2393
|
end = (end !== -1 ? end : 0);
|
|
2381
2394
|
}
|
|
@@ -2909,7 +2922,22 @@ Fit.Browser.GetScreenDimensions = function(onlyAvailable)
|
|
|
2909
2922
|
}
|
|
2910
2923
|
|
|
2911
2924
|
/// <function container="Fit.Browser" name="IsMobile" access="public" static="true" returns="boolean">
|
|
2912
|
-
/// <description>
|
|
2925
|
+
/// <description>
|
|
2926
|
+
/// Returns value indicating whether device is a mobile device or not.
|
|
2927
|
+
/// Notice that some phones and tablets may identify as desktop devices,
|
|
2928
|
+
/// in which case IsMobile(..) will return False. In this case consider
|
|
2929
|
+
/// using Fit.Browser.IsTouchEnabled(), e.g. in combination with
|
|
2930
|
+
/// Fit.Browser.GetBrowser(), or a check against the size of the viewport,
|
|
2931
|
+
/// which will provide some indication as to whether device should be treated
|
|
2932
|
+
/// as a mobile device or not. As an example, Safari on iPad identifies as
|
|
2933
|
+
/// a Mac computer by default (it has "Request Desktop Website" enabled by default).
|
|
2934
|
+
/// To always detect iPad and iPhone as a mobile device, no matter the configuration
|
|
2935
|
+
/// of "Request Desktop Website"), simply use:
|
|
2936
|
+
/// var isMobile = Fit.Browser.IsMobile(true) || (Fit.Browser.GetBrowser() === "Safari" && Fit.Browser.IsTouchEnabled())
|
|
2937
|
+
/// We will not be able to distinguish between an iPhone and an iPad though, not even
|
|
2938
|
+
/// by looking at the viewport size, since this approach is unreliable with high resolution
|
|
2939
|
+
/// iPhones and support for split screen which affects the viewport size.
|
|
2940
|
+
/// </description>
|
|
2913
2941
|
/// <param name="includeTablets" type="boolean" default="true"> Value indicating whether tablets are considered mobile devices or not </param>
|
|
2914
2942
|
/// </function>
|
|
2915
2943
|
Fit.Browser.IsMobile = function(includeTablets)
|
|
@@ -2919,7 +2947,7 @@ Fit.Browser.IsMobile = function(includeTablets)
|
|
|
2919
2947
|
// Based on http://detectmobilebrowsers.com
|
|
2920
2948
|
// See About section for Tablet support: http://detectmobilebrowsers.com/about
|
|
2921
2949
|
|
|
2922
|
-
var nav =
|
|
2950
|
+
var nav = Fit._internal.Browser.UserAgent;
|
|
2923
2951
|
|
|
2924
2952
|
if (includeTablets !== false && /android|ipad|playbook|silk/i.test(nav))
|
|
2925
2953
|
return true;
|
|
@@ -2935,7 +2963,6 @@ Fit.Browser.IsTouchEnabled = function()
|
|
|
2935
2963
|
return ("ontouchstart" in window);
|
|
2936
2964
|
}
|
|
2937
2965
|
|
|
2938
|
-
|
|
2939
2966
|
/// <function container="Fit.Browser" name="Log" access="public" static="true">
|
|
2940
2967
|
/// <description> Log message or object </description>
|
|
2941
2968
|
/// <param name="msg" type="object"> Message or object to log </param>
|
|
@@ -8442,7 +8469,9 @@ Fit.Events.AddMutationObserver = function(elm, obs, deep)
|
|
|
8442
8469
|
Fit.Events.AddHandler(document, "touchstart", Fit._internal.Events.CheckMutations);
|
|
8443
8470
|
Fit.Events.AddHandler(document, "touchend", Fit._internal.Events.CheckMutations);
|
|
8444
8471
|
Fit.Events.AddHandler(document, "touchcancel", Fit._internal.Events.CheckMutations);
|
|
8445
|
-
|
|
8472
|
+
|
|
8473
|
+
var checkInterval = Fit._internal.Events.Browser.Name !== "MSIE" ? 500 : 1000;
|
|
8474
|
+
Fit._internal.Events.MutationObserverIntervalId = setInterval(Fit._internal.Events.CheckMutations, checkInterval);
|
|
8446
8475
|
}
|
|
8447
8476
|
|
|
8448
8477
|
// Add mutation observer
|
|
@@ -22782,12 +22811,25 @@ Fit.Controls.Input = function(ctlId)
|
|
|
22782
22811
|
}
|
|
22783
22812
|
}
|
|
22784
22813
|
|
|
22814
|
+
// Guard against disposed control in case Focused(false) was called and an OnBlur handler disposed the control.
|
|
22815
|
+
// As the code further up shows, we call me._internal.FireOnBlur() if a dialog is currently open. This results
|
|
22816
|
+
// in OnBlur firing immediately, while normally it happens asynchronously due to how OnFocus and OnBlur is handled
|
|
22817
|
+
// in ControlBase, in which case we do not need to worry that the control might be disposed. It happens "later".
|
|
22818
|
+
// The situation can easily arise if an OnScroll handler is reponsible for removing focus from a control,
|
|
22819
|
+
// and if that control also has an OnBlur handler registered which disposes the control. Scrolling with a
|
|
22820
|
+
// dialog open will then trigger the situation which we guard against here.
|
|
22821
|
+
if (me === null)
|
|
22822
|
+
{
|
|
22823
|
+
return false;
|
|
22824
|
+
}
|
|
22825
|
+
|
|
22785
22826
|
if (me.DesignMode() === true)
|
|
22786
22827
|
{
|
|
22787
22828
|
// If a dialog is open and it belongs to this control instance, and focus is found within dialog, then control is considered having focus.
|
|
22788
22829
|
// However, if <body> is focused while dialog is open, control is also considered to have focus, since dialog temporarily assigns focus to
|
|
22789
22830
|
// <body> when tabbing between elements within the dialog. This seems safe as no other control can be considered focused if <body> has focus.
|
|
22790
|
-
if (
|
|
22831
|
+
// We also consider the control focused if an associated dialog (modal) is currently loading (Fit._internal.Controls.Input.ActiveDialogForEditor is null).
|
|
22832
|
+
if (Fit._internal.Controls.Input.ActiveEditorForDialog === me && (Fit._internal.Controls.Input.ActiveDialogForEditor === null || Fit.Dom.Contained(Fit._internal.Controls.Input.ActiveDialogForEditor.getElement().$, Fit.Dom.GetFocused()) === true || Fit.Dom.GetFocused() === document.body))
|
|
22791
22833
|
return true;
|
|
22792
22834
|
|
|
22793
22835
|
// If a toolbar dialog/callout is open and contains the element currently having focus, then control is considered having focus.
|
|
@@ -22834,12 +22876,48 @@ Fit.Controls.Input = function(ctlId)
|
|
|
22834
22876
|
});
|
|
22835
22877
|
|
|
22836
22878
|
updateDesignEditorPlaceholder();
|
|
22879
|
+
updateDesignEditorSize(); // In case auto grow is enabled, in which case editor must adjust its height to its new content
|
|
22837
22880
|
}
|
|
22838
22881
|
else
|
|
22839
22882
|
{
|
|
22840
22883
|
input.value = val;
|
|
22841
22884
|
}
|
|
22842
22885
|
|
|
22886
|
+
// Notice: Identical logic is NOT found in DesignMode(true, config) as with RevokeExternalBlobUrlsOnDispose below.
|
|
22887
|
+
// When the RevokeUnreferencedBlobUrlsOnValueSet mechanism is in play, the control has already been used as an HTML editor
|
|
22888
|
+
// before, as we are expecting the control to be re(-used) to manipulate different values. In this case we already have
|
|
22889
|
+
// designEditorConfig available, although it could theoretically be changed over time so RevokeUnreferencedBlobUrlsOnValueSet
|
|
22890
|
+
// is sometimes enabled and sometimes not - but we don't care to support poor design like this:
|
|
22891
|
+
// input.DesignMode(true, configWithRevokeUnreferencedBlobUrlsOnValueSetDISBLED);
|
|
22892
|
+
// input.Value("New HTML value");
|
|
22893
|
+
// input.DesignMode(true, configWithRevokeUnreferencedBlobUrlsOnValueSetENABLED); // This will not clean up image blobs no longer referenced
|
|
22894
|
+
if (designEditorConfig !== null && designEditorConfig.Plugins && designEditorConfig.Plugins.Images && designEditorConfig.Plugins.Images.RevokeUnreferencedBlobUrlsOnValueSet === true)
|
|
22895
|
+
{
|
|
22896
|
+
// Remove image blobs from memory when a new value is set, unless some (or all)
|
|
22897
|
+
// of these image blobs are still referenced in the new value, of course.
|
|
22898
|
+
// This is useful if an editor instance is being (re-)used to modify different values.
|
|
22899
|
+
// NOTICE: There is a major memory leak in CKEditor related to bulk pasting images
|
|
22900
|
+
// from the file system, and the last image pasted always remains in memory:
|
|
22901
|
+
// https://github.com/ckeditor/ckeditor4/issues/5124
|
|
22902
|
+
|
|
22903
|
+
var blobUrlsReferenced = Fit.String.ParseImageBlobUrls(val);
|
|
22904
|
+
var newImageBlobUrls = [];
|
|
22905
|
+
|
|
22906
|
+
Fit.Array.ForEach(imageBlobUrls, function(blobUrl)
|
|
22907
|
+
{
|
|
22908
|
+
if (Fit.Array.Contains(blobUrlsReferenced, blobUrl) === true)
|
|
22909
|
+
{
|
|
22910
|
+
newImageBlobUrls.push(blobUrl); // Keep - still referenced in new value
|
|
22911
|
+
}
|
|
22912
|
+
else
|
|
22913
|
+
{
|
|
22914
|
+
URL.revokeObjectURL(blobUrl); // Revoke - no longer referenced in new value
|
|
22915
|
+
}
|
|
22916
|
+
});
|
|
22917
|
+
|
|
22918
|
+
imageBlobUrls = newImageBlobUrls;
|
|
22919
|
+
}
|
|
22920
|
+
|
|
22843
22921
|
// Notice: Identical logic found in DesignMode(true, config)!
|
|
22844
22922
|
if (designEditorConfig !== null && designEditorConfig.Plugins && designEditorConfig.Plugins.Images && designEditorConfig.Plugins.Images.RevokeExternalBlobUrlsOnDispose === true)
|
|
22845
22923
|
{
|
|
@@ -22848,8 +22926,11 @@ Fit.Controls.Input = function(ctlId)
|
|
|
22848
22926
|
// is allowed (and expected) to take control over memory management for these blobs
|
|
22849
22927
|
// based on the rule set in RevokeBlobUrlsOnDispose.
|
|
22850
22928
|
// This code is also found in DesignMode(true, config) since images might be added before
|
|
22851
|
-
//
|
|
22852
|
-
// the desired behaviour.
|
|
22929
|
+
// DesignMode is enabled, in which case we do not yet have the editor configuration needed
|
|
22930
|
+
// to determine the desired behaviour.
|
|
22931
|
+
// NOTICE: There is a major memory leak in CKEditor related to bulk pasting images
|
|
22932
|
+
// from the file system, and the last image pasted always remains in memory:
|
|
22933
|
+
// https://github.com/ckeditor/ckeditor4/issues/5124
|
|
22853
22934
|
|
|
22854
22935
|
var blobUrls = Fit.String.ParseImageBlobUrls(val);
|
|
22855
22936
|
|
|
@@ -23598,6 +23679,12 @@ Fit.Controls.Input = function(ctlId)
|
|
|
23598
23679
|
/// These images are furthermore subject to the rule set in RevokeBlobUrlsOnDispose.
|
|
23599
23680
|
/// Defaults to False.
|
|
23600
23681
|
/// </member>
|
|
23682
|
+
/// <member name="RevokeUnreferencedBlobUrlsOnValueSet" type="boolean" default="undefined">
|
|
23683
|
+
/// This option is in effect when EmbedType is blob.
|
|
23684
|
+
/// Dispose images from blob storage (revoke blob URLs) when value is changed with Value(..),
|
|
23685
|
+
/// but keep any images still referenced in new value. This is useful if an editor instance
|
|
23686
|
+
/// is being used to modify different HTML values over time.
|
|
23687
|
+
/// </member>
|
|
23601
23688
|
/// </container>
|
|
23602
23689
|
|
|
23603
23690
|
/// <container name="Fit.Controls.InputTypeDefs.DesignModeConfigPlugins">
|
|
@@ -25453,6 +25540,8 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25453
25540
|
{
|
|
25454
25541
|
if (me.DesignMode() === true && designEditorHeightMonitorId === -1)
|
|
25455
25542
|
{
|
|
25543
|
+
// Postpone if editor is not ready yet
|
|
25544
|
+
|
|
25456
25545
|
if (designEditorUpdateSizeDebouncer !== -1)
|
|
25457
25546
|
{
|
|
25458
25547
|
clearTimeout(designEditorUpdateSizeDebouncer);
|
|
@@ -25468,7 +25557,7 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25468
25557
|
// This is a problem because CKEditor uses setTimeout(..) to for instance
|
|
25469
25558
|
// allow early registration of events, and because resources are loaded
|
|
25470
25559
|
// in an async. manner.
|
|
25471
|
-
designEditorUpdateSizeDebouncer = setTimeout(function()
|
|
25560
|
+
designEditorUpdateSizeDebouncer = setTimeout(function() // Timer is stopped if control is disposed
|
|
25472
25561
|
{
|
|
25473
25562
|
designEditorUpdateSizeDebouncer = -1;
|
|
25474
25563
|
updateDesignEditorSize();
|
|
@@ -25477,19 +25566,8 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25477
25566
|
return;
|
|
25478
25567
|
}
|
|
25479
25568
|
|
|
25480
|
-
//
|
|
25481
|
-
|
|
25482
|
-
|
|
25483
|
-
// Default control width is 200px (defined in Styles.css).
|
|
25484
|
-
// NOTICE: resize does not work reliably when editor is hidden, e.g. behind a tab with display:none.
|
|
25485
|
-
// The height set will not have the height of the toolbar substracted since the height can not be
|
|
25486
|
-
// determined for hidden objects, so the editor will become larger than the value set (height specified + toolbar height).
|
|
25487
|
-
// http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-resize
|
|
25488
|
-
designEditorSuppressOnResize = true;
|
|
25489
|
-
designEditor.resize("100%", h.Value > -1 ? h.Value + h.Unit : "100%"); // A height of 100% allow editor to automatically adjust the height of the editor's content area to the height of its content (data-autogrow="true" must be set to make control container adjust to its content as well)
|
|
25490
|
-
designEditorSuppressOnResize = false;
|
|
25491
|
-
|
|
25492
|
-
// Set mutation observer responsible for updating editor size once it becomes visible
|
|
25569
|
+
// Postpone update to editor size if control is currently hidden or not
|
|
25570
|
+
// rooted in DOM, in which case designEditor.resize(..) will throw an error.
|
|
25493
25571
|
|
|
25494
25572
|
if (mutationObserverId !== -1) // Cancel any mutation observer previously registered
|
|
25495
25573
|
{
|
|
@@ -25497,22 +25575,43 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25497
25575
|
mutationObserverId = -1;
|
|
25498
25576
|
}
|
|
25499
25577
|
|
|
25500
|
-
|
|
25501
|
-
|
|
25502
|
-
if (concealer !== null) // Editor is hidden - adjust size when it becomes visible
|
|
25578
|
+
if (Fit.Dom.IsVisible(me.GetDomElement()) === false) // Hidden (e.g. display:none or not rooted in DOM)
|
|
25503
25579
|
{
|
|
25504
|
-
|
|
25580
|
+
// Mutation observer is triggered when element changes, including when rooted, in which case
|
|
25581
|
+
// width and height becomes measurable, and changes to dimensions also trigger mutation observer.
|
|
25582
|
+
mutationObserverId = Fit.Events.AddMutationObserver(me.GetDomElement(), function(elm)
|
|
25505
25583
|
{
|
|
25506
25584
|
if (Fit.Dom.IsVisible(me.GetDomElement()) === true)
|
|
25507
25585
|
{
|
|
25508
|
-
|
|
25509
|
-
|
|
25510
|
-
designEditorSuppressOnResize = false;
|
|
25586
|
+
disconnect();
|
|
25587
|
+
mutationObserverId = -1;
|
|
25511
25588
|
|
|
25512
|
-
|
|
25589
|
+
updateDesignEditorSize(); // Does nothing if DesignMode is no longer enabled
|
|
25513
25590
|
}
|
|
25514
25591
|
});
|
|
25592
|
+
|
|
25593
|
+
return;
|
|
25515
25594
|
}
|
|
25595
|
+
|
|
25596
|
+
//var w = me.Width();
|
|
25597
|
+
var h = me.Height();
|
|
25598
|
+
|
|
25599
|
+
// If editor is configured with AutoGrow enabled and toolbar is configured with HideWhenInactive,
|
|
25600
|
+
// then editor won't be able to adjust its height when not focused, since a fixed height is applied
|
|
25601
|
+
// to the editable area while the toolbar is hidden. Therefore, temporarily show the toolbar, update
|
|
25602
|
+
// the editor size, and then hide the toolbar again.
|
|
25603
|
+
var showHideToolbar = me.Focused() === false;
|
|
25604
|
+
|
|
25605
|
+
// Default control width is 200px (defined in Styles.css).
|
|
25606
|
+
// NOTICE: resize does not work reliably when editor is hidden, e.g. behind a tab with display:none.
|
|
25607
|
+
// The height set will not have the height of the toolbar substracted since the height can not be
|
|
25608
|
+
// determined for hidden objects, so the editor will become larger than the value set (height specified + toolbar height).
|
|
25609
|
+
// http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-resize
|
|
25610
|
+
designEditorSuppressOnResize = true;
|
|
25611
|
+
showHideToolbar && restoreHiddenToolbarInDesignEditor(true); // Does nothing unless HideWhenInactive is enabled - true argument prevents call back to updateDesignEditorSize again, hence preventing a "maximum call stack exceeded" error
|
|
25612
|
+
designEditor.resize("100%", h.Value > -1 ? h.Value + h.Unit : "100%"); // A height of 100% allow editor to automatically adjust the height of the editor's content area to the height of its content (data-autogrow="true" must be set to make control container adjust to its content as well)
|
|
25613
|
+
showHideToolbar && hideToolbarInDesignMode(true); // Does nothing unless HideWhenInactive is enabled - true argument prevents call back to updateDesignEditorSize again, hence preventing a "maximum call stack exceeded" error
|
|
25614
|
+
designEditorSuppressOnResize = false;
|
|
25516
25615
|
}
|
|
25517
25616
|
}
|
|
25518
25617
|
|
|
@@ -25560,8 +25659,10 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25560
25659
|
return (toolbarContainer !== null && toolbarContainer.style.display === "none");
|
|
25561
25660
|
}
|
|
25562
25661
|
|
|
25563
|
-
function hideToolbarInDesignMode()
|
|
25662
|
+
function hideToolbarInDesignMode(suppressUpdateEditorSize)
|
|
25564
25663
|
{
|
|
25664
|
+
Fit.Validation.ExpectBoolean(suppressUpdateEditorSize, true);
|
|
25665
|
+
|
|
25565
25666
|
if (designModeEnabledAndReady() === true && designEditorConfig !== null && designEditorConfig.Toolbar && designEditorConfig.Toolbar.HideWhenInactive === true)
|
|
25566
25667
|
{
|
|
25567
25668
|
var toolbarContainer = designEditorDom.Top || designEditorDom.Bottom; // Top is null if editor is placed at the bottom
|
|
@@ -25593,12 +25694,14 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25593
25694
|
toolbarContainer.style.display = "none";
|
|
25594
25695
|
|
|
25595
25696
|
// Make editable area adjust to take up space previously consumed by toolbar
|
|
25596
|
-
updateSize === true && updateDesignEditorSize();
|
|
25697
|
+
updateSize === true && suppressUpdateEditorSize !== true && updateDesignEditorSize();
|
|
25597
25698
|
}
|
|
25598
25699
|
}
|
|
25599
25700
|
|
|
25600
|
-
function restoreHiddenToolbarInDesignEditor()
|
|
25701
|
+
function restoreHiddenToolbarInDesignEditor(suppressUpdateEditorSize)
|
|
25601
25702
|
{
|
|
25703
|
+
Fit.Validation.ExpectBoolean(suppressUpdateEditorSize, true);
|
|
25704
|
+
|
|
25602
25705
|
if (designModeEnabledAndReady() === true && designEditorConfig !== null && designEditorConfig.Toolbar && designEditorConfig.Toolbar.HideWhenInactive === true)
|
|
25603
25706
|
{
|
|
25604
25707
|
// Toolbar has been initially hidden - make it appear again
|
|
@@ -25642,7 +25745,7 @@ Fit.Controls.Input = function(ctlId)
|
|
|
25642
25745
|
// Update size of editable area in case auto grow is not enabled, in which case
|
|
25643
25746
|
// toolbar will now have taken up space outside of control's container (overflowing).
|
|
25644
25747
|
// Make editable area fit control container again.
|
|
25645
|
-
updateDesignEditorSize();
|
|
25748
|
+
suppressUpdateEditorSize !== true && updateDesignEditorSize();
|
|
25646
25749
|
}
|
|
25647
25750
|
else
|
|
25648
25751
|
{
|