PageSourceSearch

https://www.ami.ca/profiles/ami/themes/custom/corp2026/static/infu…/framework/core/js/FluidRequests.js?v=1.x

js ami.ca collected 2026-10-02 03:25:42 UTC 17,691 bytes, 434 lines download raw bytes

1/*
2Copyright The Infusion copyright holders
3See the AUTHORS.md file at the top-level directory of this distribution and at
4https://github.com/fluid-project/infusion/raw/master/AUTHORS.md.
5
6Licensed under the Educational Community License (ECL), Version 2.0 or the New
7BSD license. You may not use this file except in compliance with one these
8Licenses.
9
10You may obtain a copy of the ECL 2.0 License and BSD License at
11https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
12*/
13
14var fluid_3_0_0 = fluid_3_0_0 || {};
15
16(function ($, fluid) {
17    "use strict";
18
19    /** NOTE: All contents of this file are DEPRECATED and no entry point should be considered a supported API **/
20
21    fluid.explodeLocalisedName = function (fileName, locale, defaultLocale) {
22        var lastDot = fileName.lastIndexOf(".");
23        if (lastDot === -1 || lastDot === 0) {
24            lastDot = fileName.length;
25        }
26        var baseName = fileName.substring(0, lastDot);
27        var extension = fileName.substring(lastDot);
28
29        var segs = locale.split("_");
30
31        var exploded = fluid.transform(segs, function (seg, index) {
32            var shortSegs = segs.slice(0, index + 1);
33            return baseName + "_" + shortSegs.join("_") + extension;
34        });
35        if (defaultLocale) {
36            exploded.unshift(baseName + "_" + defaultLocale + extension);
37        }
38        return exploded;
39    };
40
41    /** Framework-global caching state for fluid.fetchResources **/
42
43    var resourceCache = {};
44
45    var pendingClass = {};
46
47    /** Accepts a hash of structures with free keys, where each entry has either
48     * href/url or nodeId set - on completion, callback will be called with the populated
49     * structure with fetched resource text in the field "resourceText" for each
50     * entry. Each structure may contain "options" holding raw options to be forwarded
51     * to jQuery.ajax().
52     */
53
54    fluid.fetchResources = function (resourceSpecs, callback, options) {
55        var that = {
56            options: fluid.copy(options || {})
57        };
58        that.resourceSpecs = resourceSpecs;
59        that.callback = callback;
60        that.operate = function () {
61            fluid.fetchResources.fetchResourcesImpl(that);
62        };
63        fluid.each(resourceSpecs, function (resourceSpec, key) {
64            resourceSpec.recurseFirer = fluid.makeEventFirer({name: "I/O completion for resource \"" + key + "\""});
65            resourceSpec.recurseFirer.addListener(that.operate);
66            if (resourceSpec.url && !resourceSpec.href) {
67                resourceSpec.href = resourceSpec.url;
68            }
69
70            // If options.defaultLocale is set, it will replace any
71            // defaultLocale set on an individual resourceSpec
72            if (that.options.defaultLocale) {
73                resourceSpec.defaultLocale = that.options.defaultLocale;
74            }
75            if (!resourceSpec.locale) {
76                resourceSpec.locale = resourceSpec.defaultLocale;
77            }
78
79        });
80        if (that.options.amalgamateClasses) {
81            fluid.fetchResources.amalgamateClasses(resourceSpecs, that.options.amalgamateClasses, that.operate);
82        }
83        fluid.fetchResources.explodeForLocales(resourceSpecs);
84        that.operate();
85        return that;
86    };
87
88    fluid.fetchResources.explodeForLocales = function (resourceSpecs) {
89        fluid.each(resourceSpecs, function (resourceSpec, key) {
90            if (resourceSpec.locale) {
91                var exploded = fluid.explodeLocalisedName(resourceSpec.href, resourceSpec.locale, resourceSpec.defaultLocale);
92                for (var i = 0; i < exploded.length; ++i) {
93                    var newKey = key + "$localised-" + i;
94                    var newRecord = $.extend(true, {}, resourceSpec, {
95                        href: exploded[i],
96                        localeExploded: true
97                    });
98                    resourceSpecs[newKey] = newRecord;
99                }
100                resourceSpec.localeExploded = exploded.length;
101            }
102        });
103        return resourceSpecs;
104    };
105
106    fluid.fetchResources.condenseOneResource = function (resourceSpecs, resourceSpec, key, localeCount) {
107        var localeSpecs = [resourceSpec];
108        for (var i = 0; i < localeCount; ++i) {
109            var localKey = key + "$localised-" + i;
110            localeSpecs.unshift(resourceSpecs[localKey]);
111            delete resourceSpecs[localKey];
112        }
113        var lastNonError = fluid.find_if(localeSpecs, function (spec) {
114            return !spec.fetchError;
115        });
116        if (lastNonError) {
117            resourceSpecs[key] = lastNonError;
118        }
119    };
120
121    fluid.fetchResources.condenseForLocales = function (resourceSpecs) {
122        fluid.each(resourceSpecs, function (resourceSpec, key) {
123            if (typeof(resourceSpec.localeExploded) === "number") {
124                fluid.fetchResources.condenseOneResource(resourceSpecs, resourceSpec, key, resourceSpec.localeExploded);
125            }
126        });
127    };
128
129    fluid.fetchResources.notifyResources = function (that, resourceSpecs, callback) {
130        fluid.fetchResources.condenseForLocales(resourceSpecs);
131        callback(resourceSpecs);
132    };
133
134    /*
135     * This function is unsupported: It is not really intended for use by implementors.
136     */
137    // Add "synthetic" elements of *this* resourceSpec list corresponding to any
138    // still pending elements matching the PROLEPTICK CLASS SPECIFICATION supplied
139    fluid.fetchResources.amalgamateClasses = function (specs, classes, operator) {
140        fluid.each(classes, function (clazz) {
141            var pending = pendingClass[clazz];
142            fluid.each(pending, function (pendingrec, canon) {
143                specs[clazz + "!" + canon] = pendingrec;
144                pendingrec.recurseFirer.addListener(operator);
145            });
146        });
147    };
148
149    /*
150     * This function is unsupported: It is not really intended for use by implementors.
151     */
152    fluid.fetchResources.timeSuccessCallback = function (resourceSpec) {
153        if (resourceSpec.timeSuccess && resourceSpec.options && resourceSpec.options.success) {
154            var success = resourceSpec.options.success;
155            resourceSpec.options.success = function () {
156                var startTime = new Date();
157                var ret = success.apply(null, arguments);
158                fluid.log("External callback for URL " + resourceSpec.href + " completed - callback time: " +
159                        (new Date().getTime() - startTime.getTime()) + "ms");
160                return ret;
161            };
162        }
163    };
164
165    // TODO: Integrate punch-through from old Engage implementation
166    function canonUrl(url) {
167        return url;
168    }
169
170    fluid.fetchResources.clearResourceCache = function (url) {
171        if (url) {
172            delete resourceCache[canonUrl(url)];
173        }
174        else {
175            fluid.clear(resourceCache);
176        }
177    };
178
179    /*
180     * This function is unsupported: It is not really intended for use by implementors.
181     */
182    fluid.fetchResources.handleCachedRequest = function (resourceSpec, response, fetchError) {
183        var canon = canonUrl(resourceSpec.href);
184        var cached = resourceCache[canon];
185        if (cached.$$firer$$) {
186            fluid.log("Handling request for " + canon + " from cache");
187            var fetchClass = resourceSpec.fetchClass;
188            if (fetchClass && pendingClass[fetchClass]) {
189                fluid.log("Clearing pendingClass entry for class " + fetchClass);
190                delete pendingClass[fetchClass][canon];
191            }
192            var result = {response: response, fetchError: fetchError};
193            resourceCache[canon] = result;
194            cached.fire(response, fetchError);
195        }
196    };
197
198    /*
199     * This function is unsupported: It is not really intended for use by implementors.
200     */
201    fluid.fetchResources.completeRequest = function (thisSpec) {
202        thisSpec.queued = false;
203        thisSpec.completeTime = new Date();
204        fluid.log("Request to URL " + thisSpec.href + " completed - total elapsed time: " +
205            (thisSpec.completeTime.getTime() - thisSpec.initTime.getTime()) + "ms");
206        thisSpec.recurseFirer.fire();
207    };
208
209    /*
210     * This function is unsupported: It is not really intended for use by implementors.
211     */
212    fluid.fetchResources.makeResourceCallback = function (thisSpec) {
213        return {
214            success: function (response) {
215                thisSpec.resourceText = response;
216                thisSpec.resourceKey = thisSpec.href;
217                if (thisSpec.forceCache) {
218                    fluid.fetchResources.handleCachedRequest(thisSpec, response);
219                }
220                fluid.fetchResources.completeRequest(thisSpec);
221            },
222            error: function (response, textStatus, errorThrown) {
223                thisSpec.fetchError = {
224                    status: response.status,
225                    textStatus: response.textStatus,
226                    errorThrown: errorThrown
227                };
228                if (thisSpec.forceCache) {
229                    fluid.fetchResources.handleCachedRequest(thisSpec, null, thisSpec.fetchError);
230                }
231                fluid.fetchResources.completeRequest(thisSpec);
232            }
233
234        };
235    };
236
237
238    /*
239     * This function is unsupported: It is not really intended for use by implementors.
240     */
241    fluid.fetchResources.issueCachedRequest = function (resourceSpec, options) {
242        var canon = canonUrl(resourceSpec.href);
243        var cached = resourceCache[canon];
244        if (!cached) {
245            fluid.log("First request for cached resource with url " + canon);
246            cached = fluid.makeEventFirer({name: "cache notifier for resource URL " + canon});
247            cached.$$firer$$ = true;
248            resourceCache[canon] = cached;
249            var fetchClass = resourceSpec.fetchClass;
250            if (fetchClass) {
251                if (!pendingClass[fetchClass]) {
252                    pendingClass[fetchClass] = {};
253                }
254                pendingClass[fetchClass][canon] = resourceSpec;
255            }
256            options.cache = false; // TODO: Getting weird "not modified" issues on Firefox
257            $.ajax(options);
258        }
259        else {
260            if (!cached.$$firer$$) {
261                if (cached.response) {
262                    options.success(cached.response);
263                } else {
264                    options.error(cached.fetchError);
265                }
266            }
267            else {
268                fluid.log("Request for cached resource which is in flight: url " + canon);
269                cached.addListener(function (response, fetchError) {
270                    if (response) {
271                        options.success(response);
272                    } else {
273                        options.error(fetchError);
274                    }
275                });
276            }
277        }
278    };
279
280    /*
281     * This function is unsupported: It is not really intended for use by implementors.
282     */
283    // Compose callbacks in such a way that the 2nd, marked "external" will be applied
284    // first if it exists, but in all cases, the first, marked internal, will be
285    // CALLED WITHOUT FAIL
286    fluid.fetchResources.composeCallbacks = function (internal, external) {
287        return external ? (internal ?
288        function () {
289            try {
290                external.apply(null, arguments);
291            }
292            catch (e) {
293                fluid.log("Exception applying external fetchResources callback: " + e);
294            }
295            internal.apply(null, arguments);
295 // call the internal callback without fail
296        } : external ) : internal;
297    };
298
299    // unsupported, NON-API function
300    fluid.fetchResources.composePolicy = function (target, source) {
301        return fluid.fetchResources.composeCallbacks(target, source);
302    };
303
304    fluid.defaults("fluid.fetchResources.issueRequest", {
305        mergePolicy: {
306            success: fluid.fetchResources.composePolicy,
307            error: fluid.fetchResources.composePolicy,
308            url: "reverse"
309        }
310    });
311
312    // unsupported, NON-API function
313    fluid.fetchResources.issueRequest = function (resourceSpec, key) {
314        var thisCallback = fluid.fetchResources.makeResourceCallback(resourceSpec);
315        var options = {
316            url:     resourceSpec.href,
317            success: thisCallback.success,
318            error:   thisCallback.error,
319            dataType: resourceSpec.dataType || "text"
320        };
321        fluid.fetchResources.timeSuccessCallback(resourceSpec);
322        options = fluid.merge(fluid.defaults("fluid.fetchResources.issueRequest").mergePolicy,
323                      options, resourceSpec.options);
324        resourceSpec.queued = true;
325        resourceSpec.initTime = new Date();
326        fluid.log("Request with key " + key + " queued for " + resourceSpec.href);
327
328        if (resourceSpec.forceCache) {
329            fluid.fetchResources.issueCachedRequest(resourceSpec, options);
330        }
331        else {
332            $.ajax(options);
333        }
334    };
335
336
337    fluid.fetchResources.fetchResourcesImpl = function (that) {
338        var complete = true;
339        var resourceSpecs = that.resourceSpecs;
340        for (var key in resourceSpecs) {
341            var resourceSpec = resourceSpecs[key];
342            if (resourceSpec.href && !resourceSpec.completeTime) {
343                if (!resourceSpec.queued) {
344                    fluid.fetchResources.issueRequest(resourceSpec, key);
345                }
346                if (resourceSpec.queued) {
347                    complete = false;
348                }
349            }
350            else if (resourceSpec.nodeId && !resourceSpec.resourceText) {
351                var node = document.getElementById(resourceSpec.nodeId);
352                // upgrade this to somehow detect whether node is "armoured" somehow
353                // with comment or CDATA wrapping
354                resourceSpec.resourceText = fluid.dom.getElementText(node);
355                resourceSpec.resourceKey = resourceSpec.nodeId;
356            }
357        }
358        if (complete && that.callback && !that.callbackCalled) {
359            that.callbackCalled = true;
360            // Always defer notification in an anti-Zalgo scheme to ease problems like FLUID-6202
361            // In time this will be resolved by i) latched events, ii) global async ginger world
362            setTimeout(function () {
363                fluid.fetchResources.notifyResources(that, resourceSpecs, that.callback);
364            }, 1);
365        }
366    };
367
368    // TODO: This framework function is a stop-gap before the "ginger world" is capable of
369    // asynchronous instantiation. It currently performs very poor fidelity expansion of a
370    // component's options to discover "resources" only held in the static environment
371    fluid.fetchResources.primeCacheFromResources = function (componentName) {
372        var resources = fluid.defaults(componentName).resources;
373        var expanded = (fluid.expandOptions ? fluid.expandOptions : fluid.identity)(fluid.copy(resources));
374        fluid.fetchResources(expanded);
375    };
376
377    /** Utilities invoking requests for expansion **/
378    fluid.registerNamespace("fluid.expander");
379
380    /*
381     * This function is unsupported: It is not really intended for use by implementors.
382     */
383    fluid.expander.makeDefaultFetchOptions = function (successdisposer, failid, options) {
384        return $.extend(true, {dataType: "text"}, options, {
385            success: function (response, environmentdisposer) {
386                var json = JSON.parse(response);
387                environmentdisposer(successdisposer(json));
388            },
389            error: function (response, textStatus) {
390                fluid.log("Error fetching " + failid + ": " + textStatus);
391            }
392        });
393    };
394
395    /*
396     * This function is unsupported: It is not really intended for use by implementors.
397     */
398    fluid.expander.makeFetchExpander = function (options) {
399        return { expander: {
400            type: "fluid.expander.deferredFetcher",
401            href: options.url,
402            options: fluid.expander.makeDefaultFetchOptions(options.disposer, options.url, options.options),
403            resourceSpecCollector: "{resourceSpecCollector}",
404            fetchKey: options.fetchKey
405        }};
406    };
407
408    fluid.expander.deferredFetcher = function (deliverer, source, expandOptions) {
409        var expander = source.expander;
410        var spec = fluid.copy(expander);
411        // fetch the "global" collector specified in the external environment to receive
412        // this resourceSpec
413        var collector = fluid.expand(expander.resourceSpecCollector, exp
413andOptions);
414        delete spec.type;
415        delete spec.resourceSpecCollector;
416        delete spec.fetchKey;
417        var environmentdisposer = function (disposed) {
418            deliverer(disposed);
419        };
420        // replace the callback which is there (taking 2 arguments) with one which
421        // directly responds to the request, passing in the result and OUR "disposer" -
422        // which once the user has processed the response (say, parsing JSON and repackaging)
423        // finally deposits it in the place of the expander in the tree to which this reference
424        // has been stored at the point this expander was evaluated.
425        spec.options.success = function (response) {
426            expander.options.success(response, environmentdisposer);
427        };
428        var key = expander.fetchKey || fluid.allocateGuid();
429        collector[key] = spec;
430        return fluid.NO_VALUE;
431    };
432
433
434})(jQuery, fluid_3_0_0);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.