Componette

Componette

naja-js

naja-js / naja 3.0.0

Modern AJAX library for Nette Framework

Naja

Build Status Code Coverage latest version license minified size minzipped size monthly downloads downloads total

Naja. a genus of venomous elapid snakes comprising the true cobras. (Also, German for "Well" at the beginning of a sentence.)

Naja is a full-featured JS client-side AJAX library for Nette Framework.

It is written using modern-day JavaScript, but compiled into a bundle that works in all modern browsers. Every build of Naja is thoroughly tested and therefore guaranteed to work in the latest versions of Chromium (Chrome and Edge), Firefox, and WebKit (Safari).

Very quick start

$ npm install naja
import naja from 'naja';
naja.initialize();

Documentation

You can find the documentation here.

  • 3.0.0 3.0.0

    Naja 3.0 is an evolutionary release and should not come with any breaking changes for the majority of users. The breaking changes are mostly expected to affect advanced users, and developers who build custom extensions on top of Naja.

    That said, there have been some changes in the inner workings of the snippet cache that may alter the behaviour, so it is strongly recommended that you properly test your application against the 3.x release.

    New features

    • SnippetHandler supports asynchronous snippet update operations, such as using View Transitions API. (#383) You can now wrap snippet updates in transitions, and rely on Naja dispatching the afterUpdate event only after the update has been completed.

      • SnippetHandler dispatches a new pendingUpdate event. The event is dispatched right before the now asynchronous update is invoked, and only if the update has not been prevented in the beforeUpdate event.

      • ⚠️ BREAKING CHANGE: if you are using SnippetHandler.updateSnippet() or SnippetHandler.updateSnippets() method directly, please note that the method is now asynchronous and the DOM is guaranteed to be updated only after its returned promise resolves.

      • ⚠️ BREAKING CHANGE: due to the asynchronicity, it is no longer guaranteed that all snippets have been updated by the time success and complete events are dispatched.

    • SnippetCache stores raw snippet content. (#368) This makes snippet restoration more deterministic for snippet update event listeners.

      The afterUpdate event is the preferred way to e.g. initialize third-party scripts and widgets. Previously, snippet cache wasn't populated until after updating the snippets, and thus snippets stored in the cache might already have contained these DOM modifications; as a result, the same afterUpdate listener would receive different inputs in different scenarios: one pristine when updating from the server, and one already modified when restoring the snippet from cache during history navigation.

      In Naja 3.0, snippets are cached in the original form whenever possible, so that afterUpdate event listeners receive the same, unaltered input, regardless of where it comes from.

      • ⚠️ BREAKING CHANGE: if you are implementing your own snippet update operation, it is now expected to be an object implementing a pair of methods:

        • updateElement(snippet: Element, content: string): void | Promise<void>

          This method should just wrap the original, pre-3.0 snippet update operation: it updates the snippet element with the content received from the server. As per the previous section, the update can now be asynchronous.

        • updateIndex(currentContent: string, newContent: string): string

          This method has been added to integrate with the enhanced snippet cache capabilities. It applies the newContent received from the server onto the snippet's cached currentContent, and returns the result. This method works entirely with the raw snippet contents, no DOM involved.

          For example, the built-in replace operation implements this method so that it returns newContent, whereas the append operation does return a concatenation of currentContent + newContent.

        Current snippet update operation implementations are backward-compatible, with updateIndex() falling back to simply returning newContent received from the server. It is recommended that you update your implementation to include the newly added method, so that you have full control over the implementation and its behaviour.

  • 3.0.0-rc.1 3.0.0-rc.1

    This is a release candidate of the upcoming Naja 3.0. This is an evolutionary release and should not come with any breaking changes for the majority of users. The breaking changes are mostly expected to affect advanced users, and developers who build custom extensions on top of Naja.

    That said, there have been some changes in the inner workings of the snippet cache that may alter the behaviour, so it is strongly recommended that you properly test your application against the 3.x release, and report any issues.

    New features

    • SnippetHandler supports asynchronous snippet update operations, such as using View Transitions API. (#383) You can now wrap snippet updates in transitions, and rely on Naja dispatching the afterUpdate event only after the update has been completed.

      • SnippetHandler dispatches a new pendingUpdate event. The event is dispatched right before the now asynchronous update is invoked, and only if the update has not been prevented in the beforeUpdate event.

      • ⚠️ BREAKING CHANGE: if you are using SnippetHandler.updateSnippet() or SnippetHandler.updateSnippets() method directly, please note that the method is now asynchronous and the DOM is guaranteed to be updated only after its returned promise resolves.

      • ⚠️ BREAKING CHANGE: due to the asynchronicity, it is no longer guaranteed that all snippets have been updated by the time success and complete events are dispatched.

    • SnippetCache stores raw snippet content. (#368) This makes snippet restoration more deterministic for snippet update event listeners.

      The afterUpdate event is the preferred way to e.g. initialize third-party scripts and widgets. Previously, snippet cache wasn't populated until after updating the snippets, and thus snippets stored in the cache might already have contained these DOM modifications; as a result, the same afterUpdate listener would receive different inputs in different scenarios: one pristine when updating from the server, and one already modified when restoring the snippet from cache during history navigation.

      In Naja 3.0, snippets are cached in the original form whenever possible, so that afterUpdate event listeners receive the same, unaltered input, regardless of where it comes from.

      • ⚠️ BREAKING CHANGE: if you are implementing your own snippet update operation, it is now expected to be an object implementing a pair of methods:

        • updateElement(snippet: Element, content: string): void | Promise<void>

          This method should just wrap the original, pre-3.0 snippet update operation: it updates the snippet element with the content received from the server. As per the previous section, the update can now be asynchronous.

        • updateIndex(currentContent: string, newContent: string): string

          This method has been added to integrate with the enhanced snippet cache capabilities. It applies the newContent received from the server onto the snippet's cached currentContent, and returns the result. This method works entirely with the raw snippet contents, no DOM involved.

          For example, the built-in replace operation implements this method so that it returns newContent, whereas the append operation does return a concatenation of currentContent + newContent.

        Current snippet update operation implementations are backward-compatible, with updateIndex() falling back to simply returning newContent received from the server. It is recommended that you update your implementation to include the newly added method, so that you have full control over the implementation and its behaviour.

  • 2.6.1 2.6.1

    Minor changes and bugfixes

    • 🐞 SnippetCache no longer needs to call loadScripts() manually since ScriptLoader now hooks directly onto snippet's afterUpdate event.

    Full Changelog: 2.6.0...2.6.1

  • 2.6.0 2.6.0

    New features

    • HistoryHandler's restoreState event contains the direction of the history navigation: a negative number representing going back in history, and a positive number for going forward.
    • HistoryHandler's buildState event contains the operation, indicating whether the current state is being replaced, or a new state is being pushed. (#380)
    • RedirectHandler's redirect event provides the setUrl() method, allowing developers to programmatically alter the target URL.

    Minor changes and bugfixes

    • 🐞 HTML element overrides uniqueness options only if the attribute is explicitly set. (#375)
    • 🐞 HistoryHandler no longer replaces the history state with a stale URL after async redirection. (#385)
    • 🐞 ScriptLoader hooks more precisely onto the afterUpdate event, executing scripts only from snippets that have actually been updated.
    • 🔧 The type of snippet in updateSnippet() has been relaxed to Element. (#379)
    • 🔧 Dependencies have been updated and revised, so that Naja now has zero runtime dependencies.

    Full Changelog: 2.5.0...2.6.0

  • 2.6.0-beta.0 2.6.0-beta.0

    🚧 This is a beta release to show some changes that should be coming to Naja in near future. Please help me test these changes by installing the beta tag of Naja:

    npm install naja@beta

    New features

    • SnippetCache tries to cache the raw markup of snippets as returned from the server, prior to applying any afterUpdate changes. (#368)

    • HistoryHandler now includes more information about the history state change: (#380)

      • buildState event includes information about the performed operation (pushState or replaceState),
      • restoreState event includes information about the direction of the user's navigation that triggered the popstate.

    Minor changes and bugfixes

    • 🔧 Relax the type of snippet in updateSnippet() (#379)
    • 🐞UniqueExtension: only override option from element if it has an explicit attribute (#375)
  • 2.5.0 2.5.0

    New features

    • There is a new payload event that is dispatched just before success and allows you to configure options for Naja's internal components based on the server response payload.

    Minor changes and bugfixes

    • 🔧 The options in the interaction event are now prepopulated with configured default options.
    • 🔧 AbortExtension has been refactored to better handle multiple concurrent requests.

    Full changelog: 2.4.0...2.5.0

  • 2.4.0 2.4.0

    New features

    • HistoryHandler is now initialized only when a history-enabled request is made. This should improve interoperability with other history-altering tools, especially when Naja's History API integration is disabled globally. (#362, credits for the original idea go to #356)
    • ✨ Complementary to the previous change, the history state produced by Naja is now explicitly marked so.

    Minor changes and bugfixes

    • 🔧 Type definitions now allow async event listeners.
    • 🐞 A potential race condition issue in HistoryHandler has been fixed.

    Full changelog: 2.3.0...2.4.0

  • 2.3.0 2.3.0

    Changes

    • 🔧 The dist package of Naja comes without polyfills that are no longer necessary (#348), making Naja half the size 🎉
      ⚠️ This means that Naja no longer supports legacy Edge and older versions of Safari (< 14). If you still need to support these browsers, you need to include the polyfills in your application codebase. Learn more in #347.
  • 2.2.1 2.2.1

    Bugfixes

    • 🐞 ScriptLoader: record IDs of scripts loaded on initial page load (#345)
  • 2.2.0 2.2.0

    New features

    • SnippetCache has been extracted into a separate component and the feature now has its own documentation page.

      • The historyUiCache option has been deprecated in favour of the new snippetCache option.
      • The HistoryHandler.uiCache flag has been deprecated in favour of the snippetCache option. You can configure it via naja.initialize(defaultOptions).
      • The data-naja-history-no-cache attribute has been deprecated in favour of data-naja-snippet-cache="off".
      • An alternative snippet cache storage has been added, utilizing SessionStorage which might offer a larger data quota than history entries. If your snippets are too large for history state, you might try this storage using the snippetCache: 'session' option.
      • The SnippetCache component exposes three events, store, fetch and restore, that allow you to tweak the caching behaviour or bypass it altogether.
    • HistoryHandler exposes two new events, buildState and restoreState. These allow you to hook into the History API integration, and the SnippetCache is built on top of them.

    • ScriptLoader is now able to deduplicate loaded scripts by a unique identifier (suggested in #336). You can add a data-naja-script-id attribute to the <script> element inside a snippet. ScriptLoader will only load each identified script once, even if it repeatedly appears in multiple snippet responses.

    Minor changes and bugfixes

    • 🐞 Naja no longer adds submitter to form data if it has an empty name (#333).
    • 🐞 Naja is able to correctly serialize top-level arrays in data into (#315).
    • 🔧 naja.initialize() is no longer required to be called after the DOM is loaded, Naja makes sure of that internally where necessary.
    • 🔧 Naja now sends a proper Accept: application/json header (#314).
    • 📖 Documentation has been extended with more explanatory sections and code examples (#211).
  • 2.1.5 2.1.5

    • 🐞 UIHandler: refactor isUrlAllowed() to support protocol-relative URLs
    • 🔧 types: allow event names to be any string in EventTarget method overloads (#294)
  • 2.1.4 2.1.4

    • 🐞 Nullish values are now omitted from serialized data (#254).
  • 2.1.3 2.1.3

    • 🐞 Naja now properly serializes POJO data of any depth (#202, #224)
  • 2.1.2 2.1.2

    • 🐞 UIHandler: ignore rejections from the underlying makeRequest() call in UI interactions (94d3ad4)
    • 🐞 UIHandler: fix incomplete type assertion (#197)
    • 🐞 build: fix path to type declarations (#198)
  • 2.1.1 2.1.1

    • 🐞 FormsHandler: add missing undefined check to condition in processForm (#184)
  • 2.1.0 2.1.0

    • UIHandler: manual dispatch methods clickElement() and submitForm() now return the promise from the underlying request call (#177).
    • naja.makeRequest() now serializes simple POJO data into query string for GET and HEAD requests (#178).
  • 2.0.1 2.0.1

    • 🐞 Fixed reading historyUiCache setting from defaultOptions (#85)
    • 🐞 Fixed type definitions file path in package.json (#91, #92, thanks @dakur)
  • 2.0.0 2.0.0

    New features

    • SnippetHandler: allow changing snippet update operation in "before" event. You can change the planned snippet update operation (i.e. replace, prepend, or append) in the beforeUpdate event. You can also provide your own implementation of the snippet update mechanism, e.g. using a Virtual DOM library.
    • UniqueExtension: add support for multiple groups of uniqueness. You can now provide a custom string key via the unique option or data-naja-unique attribute to create a new unique group. Only requests from the same group are aborted when a new one is started.

    Breaking changes

    • Naja now uses Fetch API instead of XMLHttpRequest.
    • All EventTargets in Naja codebase now dispatch proper CustomEvents.
    • The interaction event has moved to UIHandler.
    • The load event has been removed.
    • Extensions API has been greatly refactored.
    • Options are no longer read from response payload.
    • Dropped support for Internet Explorer.

    Please refer to the migration guide for further details.

  • 2.0.0-alpha.3 2.0.0-alpha.3

    2.0.0-alpha.3

  • 2.0.0.-alpha.2 2.0.0-alpha.2

  • 1.8.3 1.8.3

    • Made support for submitting forms via GET even more reliable.
  • 1.8.2 1.8.2

    • Fixed submitting forms via GET (#63).
  • 1.8.1 1.8.1

    • Reverted a commit that got into 1.8.0 as a result of a brain fart.
  • 1.8.0 1.8.0

    • SnippetHandler events now have the fromCache flag. The beforeUpdate and afterUpdate events now carry the information about whether the snippet is being updated from cache after user navigation (i.e. going back in history), or as a result of an AJAX request to the server.
    • RedirectHandler detects local redirects via UIHandler.allowedOrigins. Until now, redirects leading to the same origin were done via another AJAX request (unless forced otherwise). This detection now takes into account the configured allowed origins, which means that redirects to any of the allowed origins is processed asynchronously by default.
    • RedirectHandler dispatches the redirect event prior to redirection. This event allows you to override the soft vs. hard redirection settings, or even entirely prevent the redirection from happening.
  • 2.0.0-alpha.1 2.0.0-alpha1

  • 1.7.0 1.7.0

    • Deprecate reading options from response payload (#44). After some thought, I consider passing options such as replaceHistory or forceRedirect to Naja via the response payload to be a cul-de-sac; server should not be able to affect the client-side processing of the request in such direct way. Therefore, Naja now emits a deprecation warning if it encounters such options in the payload, and will stop supporting them in 2.0.

    • RedirectHandler: pass original options to the new "redirection" request (#45). If the target redirection URL is local (i.e. relative, or absolute pointing to the same origin), RedirectHandler sends another AJAX request instead of redirecting. Since redirect sequences are usually perceived as a single request, Naja now mimics such flow by passing the options of the original request to the redirected request, so that the intended behaviour of the request is preserved.

  • 1.6.0 1.6.0

    • Refactor UIHandler and FormsHandler to only rebind updated snippets (#19). This is a simple internal refactoring which could lead to a better performance. As a side effect, the UIHandler now exposes the bindUI() method which you can use to manually bind the AJAX handler to DOM nodes that are created dynamically via a different mechanism than Nette snippets.

    • Accept defaultOptions in naja.initialize() (#24). The naja.initialize() method now accepts defaultOptions, adding a second way to configure them in addition to modyfing naja.defaultOptions directly. The default options passed to the initialize method are also provided to the init event listeners.

    • HistoryHandler: implement disabling UI cache (#17). This is an advanced feature that entirely disables the UI state cache; this helps prevent errors caused by big snippets that exceed the maximum storage quota. During navigation through the browser history, requests are actually sent again rather than artificially replayed from the history entry state. Be sure that you know what you're doing before using this feature.

    • Optimized SnippetHandler prepend/append (#20). Thanks @vitkutny!

  • 1.5.1 1.5.1

    • Fixed: HistoryHandler now respects naja.defaultOptions.history and does not override it to true when data-naja-history attribute is not set on the element. (Thanks @brosland for investigation!)
  • 1.5.0 1.5.0

    • FormsHandler now optionally accepts a reference to nette-forms (#15). This is handy if you import the nette-forms script manually. If you provide the reference, FormsHandler will use it instead of relying on global window.Nette.
  • 1.4.0 1.4.0

    • Added UIHandler.clickElement() and UIHandler.submitForm() helper methods (#12) that allow you to dispatch UI-bound events manually. This is especially useful if you need to submit a form programmatically (e.g. on change of select box), because form.submit() does not trigger the form's submit event.
      • ⚠️ The helper methods trigger the interaction event with originalEvent set to undefined. This potentially breaks BC if you choose to use the newly introduced methods!
    • Simplified initial pop detection (#10). It doesn't appear to be a problem anymore, but in browsers where it still is a problem (some ancient Chromes and Safaris), this solution should work too while being elegantly simple. As a side effect, this should also prevent popstate behaviour in HistoryHandler being triggered on hashchange.
      • ⚠️ This also removes a few attributes from HistoryHandler that are no longer necessary: initialUrl, initialState, and popped. They were part of the internal API and were never documented, thus I don't consider their removal to be a BC break.
bar-chart-fill

Statistics

download-cloud-fill
N/A
star-fill
109
bug-fill
4
flashlight-fill
8d
price-tag-2-line

Badges

Componette Componette felix@nette.org