From 127ed300b3383af457d6002fc1e4b5c85e2f3085 Mon Sep 17 00:00:00 2001 From: pjechris Date: Sun, 25 Aug 2024 18:10:38 +0000 Subject: [PATCH] Deploying Updated Jazzy Docs --- Classes.html | 194 ++ Classes/EntityStore.html | 956 ++++++++++ Classes/Subscription.html | 173 ++ Enums.html | 166 ++ Enums/StampError.html | 174 ++ Extensions.html | 245 +++ Extensions/Date.html | 175 ++ Extensions/Publisher.html | 259 +++ Protocols.html | 225 +++ Protocols/Aggregate.html | 175 ++ Protocols/EntityWrapper.html | 194 ++ Protocols/Logger.html | 286 +++ Structs.html | 223 +++ Structs/AliasKey.html | 174 ++ Structs/EntityObserver.html | 253 +++ Structs/PartialIdentifiableKeyPath.html | 411 ++++ Typealiases.html | 219 +++ badge.svg | 28 + css/highlight.css | 202 ++ css/jazzy.css | 442 +++++ docsets/.docset/Contents/Info.plist | 20 + .../Contents/Resources/Documents/Classes.html | 194 ++ .../Documents/Classes/EntityStore.html | 956 ++++++++++ .../Documents/Classes/Subscription.html | 173 ++ .../Contents/Resources/Documents/Enums.html | 166 ++ .../Resources/Documents/Enums/StampError.html | 174 ++ .../Resources/Documents/Extensions.html | 245 +++ .../Resources/Documents/Extensions/Date.html | 175 ++ .../Documents/Extensions/Publisher.html | 259 +++ .../Resources/Documents/Protocols.html | 225 +++ .../Documents/Protocols/Aggregate.html | 175 ++ .../Documents/Protocols/EntityWrapper.html | 194 ++ .../Resources/Documents/Protocols/Logger.html | 286 +++ .../Contents/Resources/Documents/Structs.html | 223 +++ .../Resources/Documents/Structs/AliasKey.html | 174 ++ .../Documents/Structs/EntityObserver.html | 253 +++ .../Structs/PartialIdentifiableKeyPath.html | 411 ++++ .../Resources/Documents/Typealiases.html | 219 +++ .../Resources/Documents/css/highlight.css | 202 ++ .../Resources/Documents/css/jazzy.css | 442 +++++ .../Resources/Documents/img/carat.png | Bin 0 -> 274 bytes .../Contents/Resources/Documents/img/dash.png | Bin 0 -> 1338 bytes .../Resources/Documents/img/spinner.gif | Bin 0 -> 1849 bytes .../Contents/Resources/Documents/index.html | 411 ++++ .../Contents/Resources/Documents/js/jazzy.js | 74 + .../Resources/Documents/js/jazzy.search.js | 74 + .../Resources/Documents/js/jquery.min.js | 2 + .../Resources/Documents/js/lunr.min.js | 6 + .../Documents/js/typeahead.jquery.js | 1695 +++++++++++++++++ .../Contents/Resources/Documents/search.json | 1 + .../.docset/Contents/Resources/docSet.dsidx | Bin 0 -> 36864 bytes docsets/.tgz | Bin 0 -> 88144 bytes img/carat.png | Bin 0 -> 274 bytes img/dash.png | Bin 0 -> 1338 bytes img/spinner.gif | Bin 0 -> 1849 bytes index.html | 411 ++++ js/jazzy.js | 74 + js/jazzy.search.js | 74 + js/jquery.min.js | 2 + js/lunr.min.js | 6 + js/typeahead.jquery.js | 1695 +++++++++++++++++ search.json | 1 + undocumented.json | 6 + 63 files changed, 14872 insertions(+) create mode 100644 Classes.html create mode 100644 Classes/EntityStore.html create mode 100644 Classes/Subscription.html create mode 100644 Enums.html create mode 100644 Enums/StampError.html create mode 100644 Extensions.html create mode 100644 Extensions/Date.html create mode 100644 Extensions/Publisher.html create mode 100644 Protocols.html create mode 100644 Protocols/Aggregate.html create mode 100644 Protocols/EntityWrapper.html create mode 100644 Protocols/Logger.html create mode 100644 Structs.html create mode 100644 Structs/AliasKey.html create mode 100644 Structs/EntityObserver.html create mode 100644 Structs/PartialIdentifiableKeyPath.html create mode 100644 Typealiases.html create mode 100644 badge.svg create mode 100644 css/highlight.css create mode 100644 css/jazzy.css create mode 100644 docsets/.docset/Contents/Info.plist create mode 100644 docsets/.docset/Contents/Resources/Documents/Classes.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Classes/EntityStore.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Classes/Subscription.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Enums.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Enums/StampError.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Extensions.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Extensions/Date.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Extensions/Publisher.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Protocols.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Protocols/Aggregate.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Protocols/EntityWrapper.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Protocols/Logger.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Structs.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Structs/AliasKey.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Structs/EntityObserver.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Structs/PartialIdentifiableKeyPath.html create mode 100644 docsets/.docset/Contents/Resources/Documents/Typealiases.html create mode 100644 docsets/.docset/Contents/Resources/Documents/css/highlight.css create mode 100644 docsets/.docset/Contents/Resources/Documents/css/jazzy.css create mode 100755 docsets/.docset/Contents/Resources/Documents/img/carat.png create mode 100755 docsets/.docset/Contents/Resources/Documents/img/dash.png create mode 100644 docsets/.docset/Contents/Resources/Documents/img/spinner.gif create mode 100644 docsets/.docset/Contents/Resources/Documents/index.html create mode 100755 docsets/.docset/Contents/Resources/Documents/js/jazzy.js create mode 100644 docsets/.docset/Contents/Resources/Documents/js/jazzy.search.js create mode 100644 docsets/.docset/Contents/Resources/Documents/js/jquery.min.js create mode 100644 docsets/.docset/Contents/Resources/Documents/js/lunr.min.js create mode 100644 docsets/.docset/Contents/Resources/Documents/js/typeahead.jquery.js create mode 100644 docsets/.docset/Contents/Resources/Documents/search.json create mode 100644 docsets/.docset/Contents/Resources/docSet.dsidx create mode 100644 docsets/.tgz create mode 100755 img/carat.png create mode 100755 img/dash.png create mode 100644 img/spinner.gif create mode 100644 index.html create mode 100755 js/jazzy.js create mode 100644 js/jazzy.search.js create mode 100644 js/jquery.min.js create mode 100644 js/lunr.min.js create mode 100644 js/typeahead.jquery.js create mode 100644 search.json create mode 100644 undocumented.json diff --git a/Classes.html b/Classes.html new file mode 100644 index 0000000..b3844eb --- /dev/null +++ b/Classes.html @@ -0,0 +1,194 @@ + + + + Classes Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Classes

+

The following classes are available globally.

+ +
+
+
+
    +
  • +
    + + + + EntityStore + +
    +
    +
    +
    +
    +
    +

    Manages entities lifecycle and synchronisation

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class EntityStore
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Subscription + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class Subscription
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Classes/EntityStore.html b/Classes/EntityStore.html new file mode 100644 index 0000000..79ed03a --- /dev/null +++ b/Classes/EntityStore.html @@ -0,0 +1,956 @@ + + + + EntityStore Class Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityStore

+
+
+ +
public class EntityStore
+ +
+
+

Manages entities lifecycle and synchronisation

+ +
+
+
+
    +
  • +
    + + + + Update + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Update<T> = (inout T) -> Void
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(queue:logger:) + +
    +
    +
    +
    +
    +
    +

    Create a new EntityStore instance optionally with a queue and a logger

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public convenience init(queue: DispatchQueue? = nil, logger: Logger? = nil)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + queue + + +
    +

    the queue on which to receive updates. If nil identitymap will create its own.

    +
    +
    + + logger + + +
    +

    a logger to follow/debug identity internal state

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store an entity in the storage. Entity will be stored only if stamp (modifiedAt) is higher than in previous +insertion.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<T: Identifiable>(
    +    entity: T,
    +    named: AliasKey<T>? = nil,
    +    modifiedAt: Stamp? = nil,
    +    ifPresent update: Update<T>? = nil
    +) -> EntityObserver<T>
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + entity + + +
    +

    the element to store in the identity map

    +
    +
    + + named + + +
    +

    an alias to reference the entity and retrieve it using it

    +
    +
    + + modifiedAt + + +
    +

    if entity was already stored it will be used to determine if the update should be applied or discarded

    +
    +
    + + ifPresent + + +
    +

    applies the closure before storing it if it’s already been stored. In this case this is similar as +calling update

    +
    +
    +
    +
    +

    Return Value

    +

    an object to observe changes on the entity

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store an aggregate in the storage. Each aggregate entities will be stored only if stamp (modifiedAt) is higher than in previous +insertion. Finally aggregate will be stored accordingly to each of its entities.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<T: Aggregate>(
    +    entity: T,
    +    named: AliasKey<T>? = nil,
    +    modifiedAt: Stamp? = nil,
    +    ifPresent update: Update<T>? = nil
    +) -> EntityObserver<T>
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + entity + + +
    +

    the aggregate to store in the identity map

    +
    +
    + + named + + +
    +

    an alias to reference the aggregate and retrieve it using it

    +
    +
    + + modifiedAt + + +
    +

    if aggregate was already stored it will be used to determine if the update should be applied or discarded

    +
    +
    + + ifPresent + + +
    +

    applies the closure before storing it if it’s already been stored. In this case this is similar as +calling update

    +
    +
    +
    +
    +

    Return Value

    +

    an object to observe changes on the entity

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store multiple entities at once

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<C: Collection>(entities: C, named: AliasKey<C>? = nil, modifiedAt: Stamp? = nil)
    +-> EntityObserver<[C.Element]> where C.Element: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    store multiple aggregates at once

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<C: Collection>(entities: C, named: AliasKey<C>? = nil, modifiedAt: Stamp? = nil)
    +-> EntityObserver<[C.Element]> where C.Element: Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + find(_:id:) + +
    +
    +
    +
    +
    +
    +

    Try to find an entity/aggregate in the storage.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<T>(_ type: T.Type, id: T.ID) -> EntityObserver<T>? where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + type + + +
    +

    the entity type

    +
    +
    + + id + + +
    +

    the entity id

    +
    +
    +
    +
    +

    Return Value

    +

    nil if not found, an EntityObserver` otherwise

    +
    +
    +
    +
  • +
  • +
    + + + + find(named:) + +
    +
    +
    +
    +
    +
    +

    Try to find an entity/aggregate registered under named alias

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<T>(named: AliasKey<T>) -> EntityObserver<T?> where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + named + + +
    +

    the alias to look for

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + find(named:) + +
    +
    +
    +
    +
    +
    +

    Try to find a collected registered under named alias

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<C>(named: AliasKey<C>) -> EntityObserver<C?> where C : Collection
    + +
    +
    +
    +

    Return Value

    +

    an observer returning the alias value. Note that the value will be an Array

    +
    +
    +
    +
  • +
+
+
+
+ + +
+ +

Update +

+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored entity using a closure. Useful to update a few properties or when you assume the entity +should already be stored. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. This is useful if you don’t have a full entity for update +but just a few attributes/modifications. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, _ update: Update<T>) -> Bool where T : Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already existing collection alias content +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
    +-> Bool where C.Element: Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already existing collection alias content + Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
    +-> Bool where C.Element: Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
+
+
+
+ + +
+ +

Delete +

+
+
+
    +
  • +
    + + + + removeAlias(named:) + +
    +
    +
    +
    +
    +
    +

    Removes an alias from the storage

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAlias<T>(named: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAlias(named:) + +
    +
    +
    +
    +
    +
    +

    Removes an alias from the storage

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAlias<C>(named: AliasKey<C>) where C : Collection
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAllAlias() + +
    +
    +
    +
    +
    +
    +

    Removes all alias from identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAllAlias()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAll() + +
    +
    +
    +
    +
    +
    +

    Removes all alias AND all objects stored weakly. You should not need this method and rather use removeAlias. +But this can be useful if you fear retain cycles

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAll()
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Classes/Subscription.html b/Classes/Subscription.html new file mode 100644 index 0000000..fa2c21e --- /dev/null +++ b/Classes/Subscription.html @@ -0,0 +1,173 @@ + + + + Subscription Class Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Subscription

+
+
+ +
public class Subscription
+ +
+
+ +
+
+
+
    +
  • +
    + + + + unsubscribe + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let unsubscribe: () -> Void
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Enums.html b/Enums.html new file mode 100644 index 0000000..7c6b3b9 --- /dev/null +++ b/Enums.html @@ -0,0 +1,166 @@ + + + + Enumerations Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Enumerations

+

The following enumerations are available globally.

+ +
+
+
+
    +
  • +
    + + + + StampError + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum StampError : Error
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Enums/StampError.html b/Enums/StampError.html new file mode 100644 index 0000000..37d6c56 --- /dev/null +++ b/Enums/StampError.html @@ -0,0 +1,174 @@ + + + + StampError Enumeration Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

StampError

+
+
+ +
public enum StampError : Error
+ +
+
+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    received stamp is smaller than current stamp

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case tooOld(current: Stamp, received: Stamp)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Extensions.html b/Extensions.html new file mode 100644 index 0000000..bacf005 --- /dev/null +++ b/Extensions.html @@ -0,0 +1,245 @@ + + + + Extensions Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Extensions

+

The following extensions are available globally.

+ +
+
+
+
    +
  • +
    + + + + Publisher + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension Publisher
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Date + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension Date
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + AliasContainer + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension AliasContainer: Equatable where T: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityNode + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension EntityNode: Hashable
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Extensions/Date.html b/Extensions/Date.html new file mode 100644 index 0000000..8cfde1e --- /dev/null +++ b/Extensions/Date.html @@ -0,0 +1,175 @@ + + + + Date Extension Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Date

+
+
+ +
extension Date
+ +
+
+ +
+
+
+
    +
  • +
    + + + + stamp + +
    +
    +
    +
    +
    +
    +

    Generate a stamp suitable to use in EntityStore. +Don’t suppose it equals unix timestamp (it is not)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var stamp: Stamp { get }
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Extensions/Publisher.html b/Extensions/Publisher.html new file mode 100644 index 0000000..a5c3e1c --- /dev/null +++ b/Extensions/Publisher.html @@ -0,0 +1,259 @@ + + + + Publisher Extension Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Publisher

+
+
+ +
extension Publisher
+ +
+
+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Stores the Identifiable upstream into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<Output, Failure> where Output: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the Aggregate upstream into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<Output, Failure> where Output: Aggregate
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the upstream collection into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<[Output.Element], Failure> where Output: Collection, Output.Element: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the upstream collection into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<[Output.Element], Failure> where Output: Collection, Output.Element: Aggregate
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Protocols.html b/Protocols.html new file mode 100644 index 0000000..f4c331e --- /dev/null +++ b/Protocols.html @@ -0,0 +1,225 @@ + + + + Protocols Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Protocols

+

The following protocols are available globally.

+ +
+
+
+
    +
  • +
    + + + + Aggregate + +
    +
    +
    +
    +
    +
    +

    An Identifiable model containing nested models

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Aggregate : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityWrapper + +
    +
    +
    +
    +
    +
    +

    A type wrapping one or more Identifiable types. +You should rarely need to use this type. However it can happens to have a non Aggregate object containing Identifiable +objects to group them (for consistency or naming). This is especially true with enum cases.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Logger + +
    +
    +
    +
    +
    +
    +

    a protocol reporting EntityStore internal information

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Logger
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Protocols/Aggregate.html b/Protocols/Aggregate.html new file mode 100644 index 0000000..991509c --- /dev/null +++ b/Protocols/Aggregate.html @@ -0,0 +1,175 @@ + + + + Aggregate Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Aggregate

+
+
+ +
public protocol Aggregate : Identifiable
+ +
+
+

An Identifiable model containing nested models

+ +
+
+
+ +
+
+
+ +
+
+ + diff --git a/Protocols/EntityWrapper.html b/Protocols/EntityWrapper.html new file mode 100644 index 0000000..f6ae01c --- /dev/null +++ b/Protocols/EntityWrapper.html @@ -0,0 +1,194 @@ + + + + EntityWrapper Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityWrapper

+
+
+ +
public protocol EntityWrapper
+ +
+
+

A type wrapping one or more Identifiable types. +You should rarely need to use this type. However it can happens to have a non Aggregate object containing Identifiable +objects to group them (for consistency or naming). This is especially true with enum cases.

+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Entities contained by all cases relative to the parent container

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func wrappedEntitiesKeyPaths<Root>(relativeTo parent: WritableKeyPath<Root, Self>) -> [PartialIdentifiableKeyPath<Root>]
    + +
    +
    +
    +

    Return Value

    +

    entities contained in the wrapper +/ +Example: +/ “`swift +enum MyEnum: EntityWrapper { + case a(A) + case b(B)

    + +

    // note: you would also need to create computed getter/setter for a and b +func wrappedEntitiesKeyPaths(relativeTo root: WritableKeyPath) -> [PartialIdentifiableKeyPath] { + [.init(root.appending(.a)), .init(root.appending(.b))] +} +}

    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Protocols/Logger.html b/Protocols/Logger.html new file mode 100644 index 0000000..04c4626 --- /dev/null +++ b/Protocols/Logger.html @@ -0,0 +1,286 @@ + + + + Logger Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Logger

+
+
+ +
public protocol Logger
+ +
+
+

a protocol reporting EntityStore internal information

+ +
+
+
+
    +
  • +
    + + + + didStore(_:id:) + +
    +
    +
    +
    +
    +
    +

    Notify when an entity was stored in the identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didStore<T>(_ type: T.Type, id: T.ID) where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + type + + +
    +

    the entity type

    +
    +
    + + id + + +
    +

    id of the stored entity

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didFailedToStore<T>(_ type: T.Type, id: T.ID, error: Error) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + didRegisterAlias(_:) + +
    +
    +
    +
    +
    +
    +

    Notify an alias is registered with new entities

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didRegisterAlias<T>(_ alias: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Notify an alias is suppressed from the identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didUnregisterAlias<T>(_ alias: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Structs.html b/Structs.html new file mode 100644 index 0000000..a73a33f --- /dev/null +++ b/Structs.html @@ -0,0 +1,223 @@ + + + + Structures Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Structures

+

The following structures are available globally.

+ +
+
+
+
    +
  • +
    + + + + AliasKey + +
    +
    +
    +
    +
    +
    +

    A value representing an Entity or set of Entity

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct AliasKey<T> : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityObserver + +
    +
    +
    +
    +
    +
    +

    A type registering observers on a given entity from identity storage

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct EntityObserver<T>
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct PartialIdentifiableKeyPath<Root>
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Structs/AliasKey.html b/Structs/AliasKey.html new file mode 100644 index 0000000..4eca7fd --- /dev/null +++ b/Structs/AliasKey.html @@ -0,0 +1,174 @@ + + + + AliasKey Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

AliasKey

+
+
+ +
public struct AliasKey<T> : Hashable
+ +
+
+

A value representing an Entity or set of Entity

+ +
+
+
+
    +
  • +
    + + + + init(named:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(named value: String)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Structs/EntityObserver.html b/Structs/EntityObserver.html new file mode 100644 index 0000000..3330f5c --- /dev/null +++ b/Structs/EntityObserver.html @@ -0,0 +1,253 @@ + + + + EntityObserver Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityObserver

+
+
+ +
public struct EntityObserver<T>
+ +
+
+

A type registering observers on a given entity from identity storage

+ +
+
+
+
    +
  • +
    + + + + OnChange + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias OnChange = (T) -> Void
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + value + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let value: T
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + observe(onChange:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func observe(onChange: @escaping OnChange) -> Subscription
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + asPublisher + +
    +
    +
    +
    +
    +
    +

    A Publisher emitting the observer current value and subscribing to any subsequents new values

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var asPublisher: AnyPublisher<T, Never> { get }
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Structs/PartialIdentifiableKeyPath.html b/Structs/PartialIdentifiableKeyPath.html new file mode 100644 index 0000000..eecb2f0 --- /dev/null +++ b/Structs/PartialIdentifiableKeyPath.html @@ -0,0 +1,411 @@ + + + + PartialIdentifiableKeyPath Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

PartialIdentifiableKeyPath

+
+
+ +
public struct PartialIdentifiableKeyPath<Root>
+ +
+
+

A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

+ +
+
+
+
    +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an Identifiable keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T>) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an Aggregate keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T>) where T : Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an optional Identifiable keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T?>) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T?>) where T : Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C>) where C : MutableCollection, C.Element : Identifiable, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C?>) where C : MutableCollection, C.Element : Identifiable, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C>) where C : MutableCollection, C.Element : Aggregate, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C?>) where C : MutableCollection, C.Element : Aggregate, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(wrapper:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<W>(wrapper keyPath: WritableKeyPath<Root, W>) where W : EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(wrapper:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<W>(wrapper keyPath: WritableKeyPath<Root, W?>) where W : EntityWrapper
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/Typealiases.html b/Typealiases.html new file mode 100644 index 0000000..2429d2a --- /dev/null +++ b/Typealiases.html @@ -0,0 +1,219 @@ + + + + Type Aliases Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Type Aliases

+

The following type aliases are available globally.

+ +
+
+
+
    +
  • +
    + + + + EntityEnumWrapper + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias EntityEnumWrapper = EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + IdentityMap + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias IdentityMap = EntityStore
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Stamp + +
    +
    +
    +
    +
    +
    +

    A type used to annotate track object modifications through time. +Most of the time you’ll just use date as stamp using Date().stamp method

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Stamp = Double
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/badge.svg b/badge.svg new file mode 100644 index 0000000..a096fec --- /dev/null +++ b/badge.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + documentation + + + documentation + + + 100% + + + 100% + + + diff --git a/css/highlight.css b/css/highlight.css new file mode 100644 index 0000000..c170357 --- /dev/null +++ b/css/highlight.css @@ -0,0 +1,202 @@ +/*! Jazzy - https://github.com/realm/jazzy + * Copyright Realm Inc. + * SPDX-License-Identifier: MIT + */ +/* Credit to https://gist.github.com/wataru420/2048287 */ +.highlight .c { + color: #999988; + font-style: italic; } + +.highlight .err { + color: #a61717; + background-color: #e3d2d2; } + +.highlight .k { + color: #000000; + font-weight: bold; } + +.highlight .o { + color: #000000; + font-weight: bold; } + +.highlight .cm { + color: #999988; + font-style: italic; } + +.highlight .cp { + color: #999999; + font-weight: bold; } + +.highlight .c1 { + color: #999988; + font-style: italic; } + +.highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; } + +.highlight .gd { + color: #000000; + background-color: #ffdddd; } + +.highlight .gd .x { + color: #000000; + background-color: #ffaaaa; } + +.highlight .ge { + color: #000000; + font-style: italic; } + +.highlight .gr { + color: #aa0000; } + +.highlight .gh { + color: #999999; } + +.highlight .gi { + color: #000000; + background-color: #ddffdd; } + +.highlight .gi .x { + color: #000000; + background-color: #aaffaa; } + +.highlight .go { + color: #888888; } + +.highlight .gp { + color: #555555; } + +.highlight .gs { + font-weight: bold; } + +.highlight .gu { + color: #aaaaaa; } + +.highlight .gt { + color: #aa0000; } + +.highlight .kc { + color: #000000; + font-weight: bold; } + +.highlight .kd { + color: #000000; + font-weight: bold; } + +.highlight .kp { + color: #000000; + font-weight: bold; } + +.highlight .kr { + color: #000000; + font-weight: bold; } + +.highlight .kt { + color: #445588; } + +.highlight .m { + color: #009999; } + +.highlight .s { + color: #d14; } + +.highlight .na { + color: #008080; } + +.highlight .nb { + color: #0086B3; } + +.highlight .nc { + color: #445588; + font-weight: bold; } + +.highlight .no { + color: #008080; } + +.highlight .ni { + color: #800080; } + +.highlight .ne { + color: #990000; + font-weight: bold; } + +.highlight .nf { + color: #990000; } + +.highlight .nn { + color: #555555; } + +.highlight .nt { + color: #000080; } + +.highlight .nv { + color: #008080; } + +.highlight .ow { + color: #000000; + font-weight: bold; } + +.highlight .w { + color: #bbbbbb; } + +.highlight .mf { + color: #009999; } + +.highlight .mh { + color: #009999; } + +.highlight .mi { + color: #009999; } + +.highlight .mo { + color: #009999; } + +.highlight .sb { + color: #d14; } + +.highlight .sc { + color: #d14; } + +.highlight .sd { + color: #d14; } + +.highlight .s2 { + color: #d14; } + +.highlight .se { + color: #d14; } + +.highlight .sh { + color: #d14; } + +.highlight .si { + color: #d14; } + +.highlight .sx { + color: #d14; } + +.highlight .sr { + color: #009926; } + +.highlight .s1 { + color: #d14; } + +.highlight .ss { + color: #990073; } + +.highlight .bp { + color: #999999; } + +.highlight .vc { + color: #008080; } + +.highlight .vg { + color: #008080; } + +.highlight .vi { + color: #008080; } + +.highlight .il { + color: #009999; } diff --git a/css/jazzy.css b/css/jazzy.css new file mode 100644 index 0000000..f84ef86 --- /dev/null +++ b/css/jazzy.css @@ -0,0 +1,442 @@ +/*! Jazzy - https://github.com/realm/jazzy + * Copyright Realm Inc. + * SPDX-License-Identifier: MIT + */ +html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { + background: transparent; + border: 0; + margin: 0; + outline: 0; + padding: 0; + vertical-align: baseline; } + +body { + background-color: #f2f2f2; + font-family: Helvetica, freesans, Arial, sans-serif; + font-size: 14px; + -webkit-font-smoothing: subpixel-antialiased; + word-wrap: break-word; } + +h1, h2, h3 { + margin-top: 0.8em; + margin-bottom: 0.3em; + font-weight: 100; + color: black; } + +h1 { + font-size: 2.5em; } + +h2 { + font-size: 2em; + border-bottom: 1px solid #e2e2e2; } + +h4 { + font-size: 13px; + line-height: 1.5; + margin-top: 21px; } + +h5 { + font-size: 1.1em; } + +h6 { + font-size: 1.1em; + color: #777; } + +.section-name { + color: gray; + display: block; + font-family: Helvetica; + font-size: 22px; + font-weight: 100; + margin-bottom: 15px; } + +pre, code { + font: 0.95em Menlo, monospace; + color: #777; + word-wrap: normal; } + +p code, li code { + background-color: #eee; + padding: 2px 4px; + border-radius: 4px; } + +pre > code { + padding: 0; } + +a { + color: #0088cc; + text-decoration: none; } + a code { + color: inherit; } + +ul { + padding-left: 15px; } + +li { + line-height: 1.8em; } + +img { + max-width: 100%; } + +blockquote { + margin-left: 0; + padding: 0 10px; + border-left: 4px solid #ccc; } + +hr { + height: 1px; + border: none; + background-color: #e2e2e2; } + +.footnote-ref { + display: inline-block; + scroll-margin-top: 70px; } + +.footnote-def { + scroll-margin-top: 70px; } + +.content-wrapper { + margin: 0 auto; + width: 980px; } + +header { + font-size: 0.85em; + line-height: 32px; + background-color: #414141; + position: fixed; + width: 100%; + z-index: 3; } + header img { + padding-right: 6px; + vertical-align: -3px; + height: 16px; } + header a { + color: #fff; } + header p { + float: left; + color: #999; } + header .header-right { + float: right; + margin-left: 16px; } + +#breadcrumbs { + background-color: #f2f2f2; + height: 26px; + padding-top: 12px; + position: fixed; + width: inherit; + z-index: 2; + margin-top: 32px; + white-space: nowrap; + overflow-x: scroll; } + #breadcrumbs #carat { + height: 10px; + margin: 0 5px; } + +.sidebar { + background-color: #f9f9f9; + border: 1px solid #e2e2e2; + overflow-y: auto; + overflow-x: hidden; + position: fixed; + top: 70px; + bottom: 0; + width: 230px; + word-wrap: normal; } + +.nav-groups { + list-style-type: none; + background: #fff; + padding-left: 0; } + +.nav-group-name { + border-bottom: 1px solid #e2e2e2; + font-size: 1.1em; + font-weight: 100; + padding: 15px 0 15px 20px; } + .nav-group-name > a { + color: #333; } + +.nav-group-tasks { + margin-top: 5px; } + +.nav-group-task { + font-size: 0.9em; + list-style-type: none; + white-space: nowrap; } + .nav-group-task a { + color: #888; } + +.main-content { + background-color: #fff; + border: 1px solid #e2e2e2; + margin-left: 246px; + position: absolute; + overflow: hidden; + padding-bottom: 20px; + top: 70px; + width: 734px; } + .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { + margin-bottom: 1em; } + .main-content p { + line-height: 1.8em; } + .main-content section .section:first-child { + margin-top: 0; + padding-top: 0; } + .main-content section .task-group-section .task-group:first-of-type { + padding-top: 10px; } + .main-content section .task-group-section .task-group:first-of-type .section-name { + padding-top: 15px; } + .main-content section .heading:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + .main-content .section-name p { + margin-bottom: inherit; + line-height: inherit; } + .main-content .section-name code { + background-color: inherit; + padding: inherit; + color: inherit; } + +.section { + padding: 0 25px; } + +.highlight { + background-color: #eee; + padding: 10px 12px; + border: 1px solid #e2e2e2; + border-radius: 4px; + overflow-x: auto; } + +.declaration .highlight { + overflow-x: initial; + padding: 0 40px 40px 0; + margin-bottom: -25px; + background-color: transparent; + border: none; } + +.section-name { + margin: 0; + margin-left: 18px; } + +.task-group-section { + margin-top: 10px; + padding-left: 6px; + border-top: 1px solid #e2e2e2; } + +.task-group { + padding-top: 0px; } + +.task-name-container a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + +.section-name-container { + position: relative; + display: inline-block; } + .section-name-container .section-name-link { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + margin-bottom: 0; } + .section-name-container .section-name { + position: relative; + pointer-events: none; + z-index: 1; } + .section-name-container .section-name a { + pointer-events: auto; } + +.item { + padding-top: 8px; + width: 100%; + list-style-type: none; } + .item a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + .item code { + background-color: transparent; + padding: 0; } + .item .token, .item .direct-link { + display: inline-block; + text-indent: -20px; + padding-left: 3px; + margin-left: 35px; + font-size: 11.9px; + transition: all 300ms; } + .item .token-open { + margin-left: 20px; } + .item .discouraged { + text-decoration: line-through; } + +.declaration-note { + font-size: .85em; + color: gray; + font-style: italic; } + +.pointer-container { + border-bottom: 1px solid #e2e2e2; + left: -23px; + padding-bottom: 13px; + position: relative; + width: 110%; } + +.pointer { + background: #f9f9f9; + border-left: 1px solid #e2e2e2; + border-top: 1px solid #e2e2e2; + height: 12px; + left: 21px; + top: -7px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + width: 12px; } + +.height-container { + display: none; + left: -25px; + padding: 0 25px; + position: relative; + width: 100%; + overflow: hidden; } + .height-container .section { + background: #f9f9f9; + border-bottom: 1px solid #e2e2e2; + left: -25px; + position: relative; + width: 100%; + padding-top: 10px; + padding-bottom: 5px; } + +.aside, .language { + padding: 6px 12px; + margin: 12px 0; + border-left: 5px solid #dddddd; + overflow-y: hidden; } + .aside .aside-title, .language .aside-title { + font-size: 9px; + letter-spacing: 2px; + text-transform: uppercase; + padding-bottom: 0; + margin: 0; + color: #aaa; + -webkit-user-select: none; } + .aside p:last-child, .language p:last-child { + margin-bottom: 0; } + +.language { + border-left: 5px solid #cde9f4; } + .language .aside-title { + color: #4b8afb; } + +.aside-warning, .aside-deprecated, .aside-unavailable { + border-left: 5px solid #ff6666; } + .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { + color: #ff0000; } + +.graybox { + border-collapse: collapse; + width: 100%; } + .graybox p { + margin: 0; + word-break: break-word; + min-width: 50px; } + .graybox td { + border: 1px solid #e2e2e2; + padding: 5px 25px 5px 10px; + vertical-align: middle; } + .graybox tr td:first-of-type { + text-align: right; + padding: 7px; + vertical-align: top; + word-break: normal; + width: 40px; } + +.slightly-smaller { + font-size: 0.9em; } + +#footer { + position: relative; + top: 10px; + bottom: 0px; + margin-left: 25px; } + #footer p { + margin: 0; + color: #aaa; + font-size: 0.8em; } + +html.dash header, html.dash #breadcrumbs, html.dash .sidebar { + display: none; } + +html.dash .main-content { + width: 980px; + margin-left: 0; + border: none; + width: 100%; + top: 0; + padding-bottom: 0; } + +html.dash .height-container { + display: block; } + +html.dash .item .token { + margin-left: 0; } + +html.dash .content-wrapper { + width: auto; } + +html.dash #footer { + position: static; } + +form[role=search] { + float: right; } + form[role=search] input { + font: Helvetica, freesans, Arial, sans-serif; + margin-top: 6px; + font-size: 13px; + line-height: 20px; + padding: 0px 10px; + border: none; + border-radius: 1em; } + .loading form[role=search] input { + background: white url(../img/spinner.gif) center right 4px no-repeat; } + form[role=search] .tt-menu { + margin: 0; + min-width: 300px; + background: #fff; + color: #333; + border: 1px solid #e2e2e2; + z-index: 4; } + form[role=search] .tt-highlight { + font-weight: bold; } + form[role=search] .tt-suggestion { + font: Helvetica, freesans, Arial, sans-serif; + font-size: 14px; + padding: 0 8px; } + form[role=search] .tt-suggestion span { + display: table-cell; + white-space: nowrap; } + form[role=search] .tt-suggestion .doc-parent-name { + width: 100%; + text-align: right; + font-weight: normal; + font-size: 0.9em; + padding-left: 16px; } + form[role=search] .tt-suggestion:hover, + form[role=search] .tt-suggestion.tt-cursor { + cursor: pointer; + background-color: #4183c4; + color: #fff; } + form[role=search] .tt-suggestion:hover .doc-parent-name, + form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { + color: #fff; } diff --git a/docsets/.docset/Contents/Info.plist b/docsets/.docset/Contents/Info.plist new file mode 100644 index 0000000..61863ec --- /dev/null +++ b/docsets/.docset/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleIdentifier + com.jazzy. + CFBundleName + + DocSetPlatformFamily + + isDashDocset + + dashIndexFilePath + index.html + isJavaScriptEnabled + + DashDocSetFamily + dashtoc + + diff --git a/docsets/.docset/Contents/Resources/Documents/Classes.html b/docsets/.docset/Contents/Resources/Documents/Classes.html new file mode 100644 index 0000000..b3844eb --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Classes.html @@ -0,0 +1,194 @@ + + + + Classes Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Classes

+

The following classes are available globally.

+ +
+
+
+
    +
  • +
    + + + + EntityStore + +
    +
    +
    +
    +
    +
    +

    Manages entities lifecycle and synchronisation

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class EntityStore
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Subscription + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class Subscription
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Classes/EntityStore.html b/docsets/.docset/Contents/Resources/Documents/Classes/EntityStore.html new file mode 100644 index 0000000..79ed03a --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Classes/EntityStore.html @@ -0,0 +1,956 @@ + + + + EntityStore Class Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityStore

+
+
+ +
public class EntityStore
+ +
+
+

Manages entities lifecycle and synchronisation

+ +
+
+
+
    +
  • +
    + + + + Update + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Update<T> = (inout T) -> Void
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(queue:logger:) + +
    +
    +
    +
    +
    +
    +

    Create a new EntityStore instance optionally with a queue and a logger

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public convenience init(queue: DispatchQueue? = nil, logger: Logger? = nil)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + queue + + +
    +

    the queue on which to receive updates. If nil identitymap will create its own.

    +
    +
    + + logger + + +
    +

    a logger to follow/debug identity internal state

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store an entity in the storage. Entity will be stored only if stamp (modifiedAt) is higher than in previous +insertion.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<T: Identifiable>(
    +    entity: T,
    +    named: AliasKey<T>? = nil,
    +    modifiedAt: Stamp? = nil,
    +    ifPresent update: Update<T>? = nil
    +) -> EntityObserver<T>
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + entity + + +
    +

    the element to store in the identity map

    +
    +
    + + named + + +
    +

    an alias to reference the entity and retrieve it using it

    +
    +
    + + modifiedAt + + +
    +

    if entity was already stored it will be used to determine if the update should be applied or discarded

    +
    +
    + + ifPresent + + +
    +

    applies the closure before storing it if it’s already been stored. In this case this is similar as +calling update

    +
    +
    +
    +
    +

    Return Value

    +

    an object to observe changes on the entity

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store an aggregate in the storage. Each aggregate entities will be stored only if stamp (modifiedAt) is higher than in previous +insertion. Finally aggregate will be stored accordingly to each of its entities.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<T: Aggregate>(
    +    entity: T,
    +    named: AliasKey<T>? = nil,
    +    modifiedAt: Stamp? = nil,
    +    ifPresent update: Update<T>? = nil
    +) -> EntityObserver<T>
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + entity + + +
    +

    the aggregate to store in the identity map

    +
    +
    + + named + + +
    +

    an alias to reference the aggregate and retrieve it using it

    +
    +
    + + modifiedAt + + +
    +

    if aggregate was already stored it will be used to determine if the update should be applied or discarded

    +
    +
    + + ifPresent + + +
    +

    applies the closure before storing it if it’s already been stored. In this case this is similar as +calling update

    +
    +
    +
    +
    +

    Return Value

    +

    an object to observe changes on the entity

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Store multiple entities at once

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<C: Collection>(entities: C, named: AliasKey<C>? = nil, modifiedAt: Stamp? = nil)
    +-> EntityObserver<[C.Element]> where C.Element: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    store multiple aggregates at once

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store<C: Collection>(entities: C, named: AliasKey<C>? = nil, modifiedAt: Stamp? = nil)
    +-> EntityObserver<[C.Element]> where C.Element: Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + find(_:id:) + +
    +
    +
    +
    +
    +
    +

    Try to find an entity/aggregate in the storage.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<T>(_ type: T.Type, id: T.ID) -> EntityObserver<T>? where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + type + + +
    +

    the entity type

    +
    +
    + + id + + +
    +

    the entity id

    +
    +
    +
    +
    +

    Return Value

    +

    nil if not found, an EntityObserver` otherwise

    +
    +
    +
    +
  • +
  • +
    + + + + find(named:) + +
    +
    +
    +
    +
    +
    +

    Try to find an entity/aggregate registered under named alias

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<T>(named: AliasKey<T>) -> EntityObserver<T?> where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + named + + +
    +

    the alias to look for

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + find(named:) + +
    +
    +
    +
    +
    +
    +

    Try to find a collected registered under named alias

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func find<C>(named: AliasKey<C>) -> EntityObserver<C?> where C : Collection
    + +
    +
    +
    +

    Return Value

    +

    an observer returning the alias value. Note that the value will be an Array

    +
    +
    +
    +
  • +
+
+
+
+ + +
+ +

Update +

+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored entity using a closure. Useful to update a few properties or when you assume the entity +should already be stored. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. This is useful if you don’t have a full entity for update +but just a few attributes/modifications. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, _ update: Update<T>) -> Bool where T : Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already stored alias using a closure. +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<T>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool where T : Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already existing collection alias content +Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
    +-> Bool where C.Element: Identifiable
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Updates an already existing collection alias content + Note: the closure is evaluated before checking modifiedAt. As such the closure execution does not mean +the change was applied

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
    +-> Bool where C.Element: Aggregate
    + +
    +
    +
    +

    Return Value

    +

    true if entity exists and might be updated, false otherwise. The update might not be applied if modifiedAt is too old

    +
    +
    +
    +
  • +
+
+
+
+ + +
+ +

Delete +

+
+
+
    +
  • +
    + + + + removeAlias(named:) + +
    +
    +
    +
    +
    +
    +

    Removes an alias from the storage

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAlias<T>(named: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAlias(named:) + +
    +
    +
    +
    +
    +
    +

    Removes an alias from the storage

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAlias<C>(named: AliasKey<C>) where C : Collection
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAllAlias() + +
    +
    +
    +
    +
    +
    +

    Removes all alias from identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAllAlias()
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + removeAll() + +
    +
    +
    +
    +
    +
    +

    Removes all alias AND all objects stored weakly. You should not need this method and rather use removeAlias. +But this can be useful if you fear retain cycles

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAll()
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Classes/Subscription.html b/docsets/.docset/Contents/Resources/Documents/Classes/Subscription.html new file mode 100644 index 0000000..fa2c21e --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Classes/Subscription.html @@ -0,0 +1,173 @@ + + + + Subscription Class Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Subscription

+
+
+ +
public class Subscription
+ +
+
+ +
+
+
+
    +
  • +
    + + + + unsubscribe + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let unsubscribe: () -> Void
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Enums.html b/docsets/.docset/Contents/Resources/Documents/Enums.html new file mode 100644 index 0000000..7c6b3b9 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Enums.html @@ -0,0 +1,166 @@ + + + + Enumerations Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Enumerations

+

The following enumerations are available globally.

+ +
+
+
+
    +
  • +
    + + + + StampError + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum StampError : Error
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Enums/StampError.html b/docsets/.docset/Contents/Resources/Documents/Enums/StampError.html new file mode 100644 index 0000000..37d6c56 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Enums/StampError.html @@ -0,0 +1,174 @@ + + + + StampError Enumeration Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

StampError

+
+
+ +
public enum StampError : Error
+ +
+
+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    received stamp is smaller than current stamp

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case tooOld(current: Stamp, received: Stamp)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Extensions.html b/docsets/.docset/Contents/Resources/Documents/Extensions.html new file mode 100644 index 0000000..bacf005 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Extensions.html @@ -0,0 +1,245 @@ + + + + Extensions Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Extensions

+

The following extensions are available globally.

+ +
+
+
+
    +
  • +
    + + + + Publisher + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension Publisher
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Date + +
    +
    +
    +
    +
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension Date
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + AliasContainer + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension AliasContainer: Equatable where T: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityNode + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    extension EntityNode: Hashable
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Extensions/Date.html b/docsets/.docset/Contents/Resources/Documents/Extensions/Date.html new file mode 100644 index 0000000..8cfde1e --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Extensions/Date.html @@ -0,0 +1,175 @@ + + + + Date Extension Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Date

+
+
+ +
extension Date
+ +
+
+ +
+
+
+
    +
  • +
    + + + + stamp + +
    +
    +
    +
    +
    +
    +

    Generate a stamp suitable to use in EntityStore. +Don’t suppose it equals unix timestamp (it is not)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var stamp: Stamp { get }
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Extensions/Publisher.html b/docsets/.docset/Contents/Resources/Documents/Extensions/Publisher.html new file mode 100644 index 0000000..a5c3e1c --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Extensions/Publisher.html @@ -0,0 +1,259 @@ + + + + Publisher Extension Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Publisher

+
+
+ +
extension Publisher
+ +
+
+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Stores the Identifiable upstream into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<Output, Failure> where Output: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the Aggregate upstream into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<Output, Failure> where Output: Aggregate
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the upstream collection into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<[Output.Element], Failure> where Output: Collection, Output.Element: Identifiable
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Stores the upstream collection into an entityStore

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func store(in entityStore: EntityStore, named: AliasKey<Output>? = nil, modifiedAt: Stamp = Date().stamp)
    +-> AnyPublisher<[Output.Element], Failure> where Output: Collection, Output.Element: Aggregate
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Protocols.html b/docsets/.docset/Contents/Resources/Documents/Protocols.html new file mode 100644 index 0000000..f4c331e --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Protocols.html @@ -0,0 +1,225 @@ + + + + Protocols Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Protocols

+

The following protocols are available globally.

+ +
+
+
+
    +
  • +
    + + + + Aggregate + +
    +
    +
    +
    +
    +
    +

    An Identifiable model containing nested models

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Aggregate : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityWrapper + +
    +
    +
    +
    +
    +
    +

    A type wrapping one or more Identifiable types. +You should rarely need to use this type. However it can happens to have a non Aggregate object containing Identifiable +objects to group them (for consistency or naming). This is especially true with enum cases.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Logger + +
    +
    +
    +
    +
    +
    +

    a protocol reporting EntityStore internal information

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol Logger
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Protocols/Aggregate.html b/docsets/.docset/Contents/Resources/Documents/Protocols/Aggregate.html new file mode 100644 index 0000000..991509c --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Protocols/Aggregate.html @@ -0,0 +1,175 @@ + + + + Aggregate Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Aggregate

+
+
+ +
public protocol Aggregate : Identifiable
+ +
+
+

An Identifiable model containing nested models

+ +
+
+
+ +
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Protocols/EntityWrapper.html b/docsets/.docset/Contents/Resources/Documents/Protocols/EntityWrapper.html new file mode 100644 index 0000000..f6ae01c --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Protocols/EntityWrapper.html @@ -0,0 +1,194 @@ + + + + EntityWrapper Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityWrapper

+
+
+ +
public protocol EntityWrapper
+ +
+
+

A type wrapping one or more Identifiable types. +You should rarely need to use this type. However it can happens to have a non Aggregate object containing Identifiable +objects to group them (for consistency or naming). This is especially true with enum cases.

+ +
+
+
+
    +
  • + +
    +
    +
    +
    +
    +

    Entities contained by all cases relative to the parent container

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func wrappedEntitiesKeyPaths<Root>(relativeTo parent: WritableKeyPath<Root, Self>) -> [PartialIdentifiableKeyPath<Root>]
    + +
    +
    +
    +

    Return Value

    +

    entities contained in the wrapper +/ +Example: +/ “`swift +enum MyEnum: EntityWrapper { + case a(A) + case b(B)

    + +

    // note: you would also need to create computed getter/setter for a and b +func wrappedEntitiesKeyPaths(relativeTo root: WritableKeyPath) -> [PartialIdentifiableKeyPath] { + [.init(root.appending(.a)), .init(root.appending(.b))] +} +}

    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Protocols/Logger.html b/docsets/.docset/Contents/Resources/Documents/Protocols/Logger.html new file mode 100644 index 0000000..04c4626 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Protocols/Logger.html @@ -0,0 +1,286 @@ + + + + Logger Protocol Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Logger

+
+
+ +
public protocol Logger
+ +
+
+

a protocol reporting EntityStore internal information

+ +
+
+
+
    +
  • +
    + + + + didStore(_:id:) + +
    +
    +
    +
    +
    +
    +

    Notify when an entity was stored in the identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didStore<T>(_ type: T.Type, id: T.ID) where T : Identifiable
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + type + + +
    +

    the entity type

    +
    +
    + + id + + +
    +

    id of the stored entity

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didFailedToStore<T>(_ type: T.Type, id: T.ID, error: Error) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + didRegisterAlias(_:) + +
    +
    +
    +
    +
    +
    +

    Notify an alias is registered with new entities

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didRegisterAlias<T>(_ alias: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Notify an alias is suppressed from the identity map

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func didUnregisterAlias<T>(_ alias: AliasKey<T>)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Structs.html b/docsets/.docset/Contents/Resources/Documents/Structs.html new file mode 100644 index 0000000..a73a33f --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Structs.html @@ -0,0 +1,223 @@ + + + + Structures Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Structures

+

The following structures are available globally.

+ +
+
+
+
    +
  • +
    + + + + AliasKey + +
    +
    +
    +
    +
    +
    +

    A value representing an Entity or set of Entity

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct AliasKey<T> : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EntityObserver + +
    +
    +
    +
    +
    +
    +

    A type registering observers on a given entity from identity storage

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct EntityObserver<T>
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct PartialIdentifiableKeyPath<Root>
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Structs/AliasKey.html b/docsets/.docset/Contents/Resources/Documents/Structs/AliasKey.html new file mode 100644 index 0000000..4eca7fd --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Structs/AliasKey.html @@ -0,0 +1,174 @@ + + + + AliasKey Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

AliasKey

+
+
+ +
public struct AliasKey<T> : Hashable
+ +
+
+

A value representing an Entity or set of Entity

+ +
+
+
+
    +
  • +
    + + + + init(named:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init(named value: String)
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Structs/EntityObserver.html b/docsets/.docset/Contents/Resources/Documents/Structs/EntityObserver.html new file mode 100644 index 0000000..3330f5c --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Structs/EntityObserver.html @@ -0,0 +1,253 @@ + + + + EntityObserver Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

EntityObserver

+
+
+ +
public struct EntityObserver<T>
+ +
+
+

A type registering observers on a given entity from identity storage

+ +
+
+
+
    +
  • +
    + + + + OnChange + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias OnChange = (T) -> Void
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + value + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public let value: T
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + observe(onChange:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func observe(onChange: @escaping OnChange) -> Subscription
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + asPublisher + +
    +
    +
    +
    +
    +
    +

    A Publisher emitting the observer current value and subscribing to any subsequents new values

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var asPublisher: AnyPublisher<T, Never> { get }
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Structs/PartialIdentifiableKeyPath.html b/docsets/.docset/Contents/Resources/Documents/Structs/PartialIdentifiableKeyPath.html new file mode 100644 index 0000000..eecb2f0 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Structs/PartialIdentifiableKeyPath.html @@ -0,0 +1,411 @@ + + + + PartialIdentifiableKeyPath Structure Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

PartialIdentifiableKeyPath

+
+
+ +
public struct PartialIdentifiableKeyPath<Root>
+ +
+
+

A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

+ +
+
+
+
    +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an Identifiable keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T>) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an Aggregate keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T>) where T : Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    +

    Creates an instance referencing an optional Identifiable keyPath

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T?>) where T : Identifiable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<T>(_ keyPath: WritableKeyPath<Root, T?>) where T : Aggregate
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C>) where C : MutableCollection, C.Element : Identifiable, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C?>) where C : MutableCollection, C.Element : Identifiable, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C>) where C : MutableCollection, C.Element : Aggregate, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(_:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<C>(_ keyPath: WritableKeyPath<Root, C?>) where C : MutableCollection, C.Element : Aggregate, C.Index : Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(wrapper:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<W>(wrapper keyPath: WritableKeyPath<Root, W>) where W : EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(wrapper:) + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public init<W>(wrapper keyPath: WritableKeyPath<Root, W?>) where W : EntityWrapper
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/Typealiases.html b/docsets/.docset/Contents/Resources/Documents/Typealiases.html new file mode 100644 index 0000000..2429d2a --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/Typealiases.html @@ -0,0 +1,219 @@ + + + + Type Aliases Reference + + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+

Type Aliases

+

The following type aliases are available globally.

+ +
+
+
+
    +
  • +
    + + + + EntityEnumWrapper + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias EntityEnumWrapper = EntityWrapper
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + IdentityMap + +
    +
    +
    +
    +
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias IdentityMap = EntityStore
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Stamp + +
    +
    +
    +
    +
    +
    +

    A type used to annotate track object modifications through time. +Most of the time you’ll just use date as stamp using Date().stamp method

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public typealias Stamp = Double
    + +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/css/highlight.css b/docsets/.docset/Contents/Resources/Documents/css/highlight.css new file mode 100644 index 0000000..c170357 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/css/highlight.css @@ -0,0 +1,202 @@ +/*! Jazzy - https://github.com/realm/jazzy + * Copyright Realm Inc. + * SPDX-License-Identifier: MIT + */ +/* Credit to https://gist.github.com/wataru420/2048287 */ +.highlight .c { + color: #999988; + font-style: italic; } + +.highlight .err { + color: #a61717; + background-color: #e3d2d2; } + +.highlight .k { + color: #000000; + font-weight: bold; } + +.highlight .o { + color: #000000; + font-weight: bold; } + +.highlight .cm { + color: #999988; + font-style: italic; } + +.highlight .cp { + color: #999999; + font-weight: bold; } + +.highlight .c1 { + color: #999988; + font-style: italic; } + +.highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; } + +.highlight .gd { + color: #000000; + background-color: #ffdddd; } + +.highlight .gd .x { + color: #000000; + background-color: #ffaaaa; } + +.highlight .ge { + color: #000000; + font-style: italic; } + +.highlight .gr { + color: #aa0000; } + +.highlight .gh { + color: #999999; } + +.highlight .gi { + color: #000000; + background-color: #ddffdd; } + +.highlight .gi .x { + color: #000000; + background-color: #aaffaa; } + +.highlight .go { + color: #888888; } + +.highlight .gp { + color: #555555; } + +.highlight .gs { + font-weight: bold; } + +.highlight .gu { + color: #aaaaaa; } + +.highlight .gt { + color: #aa0000; } + +.highlight .kc { + color: #000000; + font-weight: bold; } + +.highlight .kd { + color: #000000; + font-weight: bold; } + +.highlight .kp { + color: #000000; + font-weight: bold; } + +.highlight .kr { + color: #000000; + font-weight: bold; } + +.highlight .kt { + color: #445588; } + +.highlight .m { + color: #009999; } + +.highlight .s { + color: #d14; } + +.highlight .na { + color: #008080; } + +.highlight .nb { + color: #0086B3; } + +.highlight .nc { + color: #445588; + font-weight: bold; } + +.highlight .no { + color: #008080; } + +.highlight .ni { + color: #800080; } + +.highlight .ne { + color: #990000; + font-weight: bold; } + +.highlight .nf { + color: #990000; } + +.highlight .nn { + color: #555555; } + +.highlight .nt { + color: #000080; } + +.highlight .nv { + color: #008080; } + +.highlight .ow { + color: #000000; + font-weight: bold; } + +.highlight .w { + color: #bbbbbb; } + +.highlight .mf { + color: #009999; } + +.highlight .mh { + color: #009999; } + +.highlight .mi { + color: #009999; } + +.highlight .mo { + color: #009999; } + +.highlight .sb { + color: #d14; } + +.highlight .sc { + color: #d14; } + +.highlight .sd { + color: #d14; } + +.highlight .s2 { + color: #d14; } + +.highlight .se { + color: #d14; } + +.highlight .sh { + color: #d14; } + +.highlight .si { + color: #d14; } + +.highlight .sx { + color: #d14; } + +.highlight .sr { + color: #009926; } + +.highlight .s1 { + color: #d14; } + +.highlight .ss { + color: #990073; } + +.highlight .bp { + color: #999999; } + +.highlight .vc { + color: #008080; } + +.highlight .vg { + color: #008080; } + +.highlight .vi { + color: #008080; } + +.highlight .il { + color: #009999; } diff --git a/docsets/.docset/Contents/Resources/Documents/css/jazzy.css b/docsets/.docset/Contents/Resources/Documents/css/jazzy.css new file mode 100644 index 0000000..f84ef86 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/css/jazzy.css @@ -0,0 +1,442 @@ +/*! Jazzy - https://github.com/realm/jazzy + * Copyright Realm Inc. + * SPDX-License-Identifier: MIT + */ +html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { + background: transparent; + border: 0; + margin: 0; + outline: 0; + padding: 0; + vertical-align: baseline; } + +body { + background-color: #f2f2f2; + font-family: Helvetica, freesans, Arial, sans-serif; + font-size: 14px; + -webkit-font-smoothing: subpixel-antialiased; + word-wrap: break-word; } + +h1, h2, h3 { + margin-top: 0.8em; + margin-bottom: 0.3em; + font-weight: 100; + color: black; } + +h1 { + font-size: 2.5em; } + +h2 { + font-size: 2em; + border-bottom: 1px solid #e2e2e2; } + +h4 { + font-size: 13px; + line-height: 1.5; + margin-top: 21px; } + +h5 { + font-size: 1.1em; } + +h6 { + font-size: 1.1em; + color: #777; } + +.section-name { + color: gray; + display: block; + font-family: Helvetica; + font-size: 22px; + font-weight: 100; + margin-bottom: 15px; } + +pre, code { + font: 0.95em Menlo, monospace; + color: #777; + word-wrap: normal; } + +p code, li code { + background-color: #eee; + padding: 2px 4px; + border-radius: 4px; } + +pre > code { + padding: 0; } + +a { + color: #0088cc; + text-decoration: none; } + a code { + color: inherit; } + +ul { + padding-left: 15px; } + +li { + line-height: 1.8em; } + +img { + max-width: 100%; } + +blockquote { + margin-left: 0; + padding: 0 10px; + border-left: 4px solid #ccc; } + +hr { + height: 1px; + border: none; + background-color: #e2e2e2; } + +.footnote-ref { + display: inline-block; + scroll-margin-top: 70px; } + +.footnote-def { + scroll-margin-top: 70px; } + +.content-wrapper { + margin: 0 auto; + width: 980px; } + +header { + font-size: 0.85em; + line-height: 32px; + background-color: #414141; + position: fixed; + width: 100%; + z-index: 3; } + header img { + padding-right: 6px; + vertical-align: -3px; + height: 16px; } + header a { + color: #fff; } + header p { + float: left; + color: #999; } + header .header-right { + float: right; + margin-left: 16px; } + +#breadcrumbs { + background-color: #f2f2f2; + height: 26px; + padding-top: 12px; + position: fixed; + width: inherit; + z-index: 2; + margin-top: 32px; + white-space: nowrap; + overflow-x: scroll; } + #breadcrumbs #carat { + height: 10px; + margin: 0 5px; } + +.sidebar { + background-color: #f9f9f9; + border: 1px solid #e2e2e2; + overflow-y: auto; + overflow-x: hidden; + position: fixed; + top: 70px; + bottom: 0; + width: 230px; + word-wrap: normal; } + +.nav-groups { + list-style-type: none; + background: #fff; + padding-left: 0; } + +.nav-group-name { + border-bottom: 1px solid #e2e2e2; + font-size: 1.1em; + font-weight: 100; + padding: 15px 0 15px 20px; } + .nav-group-name > a { + color: #333; } + +.nav-group-tasks { + margin-top: 5px; } + +.nav-group-task { + font-size: 0.9em; + list-style-type: none; + white-space: nowrap; } + .nav-group-task a { + color: #888; } + +.main-content { + background-color: #fff; + border: 1px solid #e2e2e2; + margin-left: 246px; + position: absolute; + overflow: hidden; + padding-bottom: 20px; + top: 70px; + width: 734px; } + .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { + margin-bottom: 1em; } + .main-content p { + line-height: 1.8em; } + .main-content section .section:first-child { + margin-top: 0; + padding-top: 0; } + .main-content section .task-group-section .task-group:first-of-type { + padding-top: 10px; } + .main-content section .task-group-section .task-group:first-of-type .section-name { + padding-top: 15px; } + .main-content section .heading:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + .main-content .section-name p { + margin-bottom: inherit; + line-height: inherit; } + .main-content .section-name code { + background-color: inherit; + padding: inherit; + color: inherit; } + +.section { + padding: 0 25px; } + +.highlight { + background-color: #eee; + padding: 10px 12px; + border: 1px solid #e2e2e2; + border-radius: 4px; + overflow-x: auto; } + +.declaration .highlight { + overflow-x: initial; + padding: 0 40px 40px 0; + margin-bottom: -25px; + background-color: transparent; + border: none; } + +.section-name { + margin: 0; + margin-left: 18px; } + +.task-group-section { + margin-top: 10px; + padding-left: 6px; + border-top: 1px solid #e2e2e2; } + +.task-group { + padding-top: 0px; } + +.task-name-container a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + +.section-name-container { + position: relative; + display: inline-block; } + .section-name-container .section-name-link { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + margin-bottom: 0; } + .section-name-container .section-name { + position: relative; + pointer-events: none; + z-index: 1; } + .section-name-container .section-name a { + pointer-events: auto; } + +.item { + padding-top: 8px; + width: 100%; + list-style-type: none; } + .item a[name]:before { + content: ""; + display: block; + padding-top: 70px; + margin: -70px 0 0; } + .item code { + background-color: transparent; + padding: 0; } + .item .token, .item .direct-link { + display: inline-block; + text-indent: -20px; + padding-left: 3px; + margin-left: 35px; + font-size: 11.9px; + transition: all 300ms; } + .item .token-open { + margin-left: 20px; } + .item .discouraged { + text-decoration: line-through; } + +.declaration-note { + font-size: .85em; + color: gray; + font-style: italic; } + +.pointer-container { + border-bottom: 1px solid #e2e2e2; + left: -23px; + padding-bottom: 13px; + position: relative; + width: 110%; } + +.pointer { + background: #f9f9f9; + border-left: 1px solid #e2e2e2; + border-top: 1px solid #e2e2e2; + height: 12px; + left: 21px; + top: -7px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + width: 12px; } + +.height-container { + display: none; + left: -25px; + padding: 0 25px; + position: relative; + width: 100%; + overflow: hidden; } + .height-container .section { + background: #f9f9f9; + border-bottom: 1px solid #e2e2e2; + left: -25px; + position: relative; + width: 100%; + padding-top: 10px; + padding-bottom: 5px; } + +.aside, .language { + padding: 6px 12px; + margin: 12px 0; + border-left: 5px solid #dddddd; + overflow-y: hidden; } + .aside .aside-title, .language .aside-title { + font-size: 9px; + letter-spacing: 2px; + text-transform: uppercase; + padding-bottom: 0; + margin: 0; + color: #aaa; + -webkit-user-select: none; } + .aside p:last-child, .language p:last-child { + margin-bottom: 0; } + +.language { + border-left: 5px solid #cde9f4; } + .language .aside-title { + color: #4b8afb; } + +.aside-warning, .aside-deprecated, .aside-unavailable { + border-left: 5px solid #ff6666; } + .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { + color: #ff0000; } + +.graybox { + border-collapse: collapse; + width: 100%; } + .graybox p { + margin: 0; + word-break: break-word; + min-width: 50px; } + .graybox td { + border: 1px solid #e2e2e2; + padding: 5px 25px 5px 10px; + vertical-align: middle; } + .graybox tr td:first-of-type { + text-align: right; + padding: 7px; + vertical-align: top; + word-break: normal; + width: 40px; } + +.slightly-smaller { + font-size: 0.9em; } + +#footer { + position: relative; + top: 10px; + bottom: 0px; + margin-left: 25px; } + #footer p { + margin: 0; + color: #aaa; + font-size: 0.8em; } + +html.dash header, html.dash #breadcrumbs, html.dash .sidebar { + display: none; } + +html.dash .main-content { + width: 980px; + margin-left: 0; + border: none; + width: 100%; + top: 0; + padding-bottom: 0; } + +html.dash .height-container { + display: block; } + +html.dash .item .token { + margin-left: 0; } + +html.dash .content-wrapper { + width: auto; } + +html.dash #footer { + position: static; } + +form[role=search] { + float: right; } + form[role=search] input { + font: Helvetica, freesans, Arial, sans-serif; + margin-top: 6px; + font-size: 13px; + line-height: 20px; + padding: 0px 10px; + border: none; + border-radius: 1em; } + .loading form[role=search] input { + background: white url(../img/spinner.gif) center right 4px no-repeat; } + form[role=search] .tt-menu { + margin: 0; + min-width: 300px; + background: #fff; + color: #333; + border: 1px solid #e2e2e2; + z-index: 4; } + form[role=search] .tt-highlight { + font-weight: bold; } + form[role=search] .tt-suggestion { + font: Helvetica, freesans, Arial, sans-serif; + font-size: 14px; + padding: 0 8px; } + form[role=search] .tt-suggestion span { + display: table-cell; + white-space: nowrap; } + form[role=search] .tt-suggestion .doc-parent-name { + width: 100%; + text-align: right; + font-weight: normal; + font-size: 0.9em; + padding-left: 16px; } + form[role=search] .tt-suggestion:hover, + form[role=search] .tt-suggestion.tt-cursor { + cursor: pointer; + background-color: #4183c4; + color: #fff; } + form[role=search] .tt-suggestion:hover .doc-parent-name, + form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { + color: #fff; } diff --git a/docsets/.docset/Contents/Resources/Documents/img/carat.png b/docsets/.docset/Contents/Resources/Documents/img/carat.png new file mode 100755 index 0000000000000000000000000000000000000000..29d2f7fd4955fca6bc6fb740e0373a2c358c398e GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRo!3HEV4DF?Wlw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlqAi{-jv*Ddl5#RKJQ5NTUZgiPI4RUKGIKU?u8L&ndhX1t za+0CMVUnT(Gnb}ei=c~x==tMH^F1_tBocXwcoSWoO-SZY-o>!8%^=Bms)(~h;m_U( zXNixk28L}0LS5-jKyq@#2gyS|J&f#pGCLkTc<@2s1dqeyqJ*Rc0tSIETAgmODY;(s z2y|Mcp&2}7rpBprBBB~1qM1`N+}4SoxYVPqsXi&l`rxZp{(w0iSy$Nv5*Vy!RapG^ S^0y4=eg;ohKbLh*2~7a!Pg}VF literal 0 HcmV?d00001 diff --git a/docsets/.docset/Contents/Resources/Documents/img/dash.png b/docsets/.docset/Contents/Resources/Documents/img/dash.png new file mode 100755 index 0000000000000000000000000000000000000000..6f694c7a012b417908da3687a0a39aa182e91c74 GIT binary patch literal 1338 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 literal 0 HcmV?d00001 diff --git a/docsets/.docset/Contents/Resources/Documents/index.html b/docsets/.docset/Contents/Resources/Documents/index.html new file mode 100644 index 0000000..9be8ca0 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,411 @@ + + + + Index Reference + + + + + + + + + + + + +
+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+ +

CohesionKit - Single Source of Truth

+ +

+ swift + platforms + test + + twitter + +

+ +

Keep your models synchronized in your app and never have any inconsistency anymore. Designed using latest Swift features.

+

Why using CohesionKit?

+ +
    +
  • 🔁 You need realtime synchronisation (websockets)
  • +
  • 🌐 You have multiple data sources (REST, CoreData, websocket, phone Contacts, Google Maps, etc…)
  • +
  • 🪶 You look for a full Swift lightweight tool
  • +
  • 🗃️ You want to use structs
  • +
+

Features

+ +
    +
  • [x] 🦺 Thread safe
  • +
  • [x] 🪶 Lighweight (< 600 lines of code)
  • +
  • [x] 🪪 Working with plain Swift struct and Identifiable objects
  • +
  • [x] 🔀 Support for Combine
  • +
  • [x] 🧠 In-memory storage
  • +
  • [x] 🐾 Low memory footprint
  • +
  • [x] 🐪 Strongly typed
  • +
+

Where to put CohesionKit in my stack?

+ +

CohesionKit being a Single Source of Truth solution it handles your objects lifecycle and synchronization from any source.

+ +

You should put CohesionKit in front of your data sources (REST API, GraphQL, …) before returning data to your app.

+
sequenceDiagram
+    autonumber
+
+        YourApp ->>DataSource: findBooks
+        DataSource ->>GraphQL: query findBooks
+        GraphQL -->>DataSource: FindBooksQueryResult
+        DataSource ->>CohesionKit: store books [A,B,C]
+        CohesionKit -->> YourApp: Publisher<[A,B,C]>
+
+        WebSocket ->> WebSocketListener: book A updated
+        WebSocketListener ->> CohesionKit: update book A
+        CohesionKit -->> YourApp: Publisher<[A,B,C]>
+
+

Installation

+ +
    +
  • Swift Package Manager
  • +
+
dependencies: [
+    .package(url: "https://github.com/pjechris/CohesionKit.git", .upToNextMajor(from: "0.7.0"))
+]
+
+

Examples

+ +

Library comes with an example project so you can see a real case usage. It mostly shows:

+ +
    +
  • How to store data in the library
  • +
  • How to retrieve and update that data for realtime
  • +
  • How data is synchronised throughout multiple screens
  • +
+

Getting started

+

Storing an object

+ +

First create an instance of EntityStore:

+
let entityStore = EntityStore()
+
+ +

EntityStore let you store Identifiable objects:

+
struct Book: Identifiable {
+  let id: String
+  let title: String
+}
+
+let book = Book(id: "ABCD", name: "My Book")
+
+entityStore.store(book)
+
+ +

Then You can retrieve the object from anywhere in your code:

+
// somewhere else in the code
+entityStore.find(Book.self, id: "ABCD") // return Book(id: "ABCD", name: "My Book")
+
+

Observing changes

+ +

Every time data is updated in EntityStore triggers a notification to any registered observer. To register yourself as an observer just use result from store or find methods:

+
func findBooks() -> some Publisher<[Book], Error> {
+  // 1. load data using URLSession
+  URLSession(...)
+  // 2. store data inside our entityStore
+    .store(in: entityStore)
+    .sink { ... }
+    .store(in: &cancellables)
+}
+
+
entityStore.find(Book.self, id: 1)?
+  .asPublisher
+  .sink { ... }
+  .store(in: &cancellables)
+
+ +
+

CohesionKit has a weak memory policy you should read about. As such, returned value from entityStore.store must be strongly retained to not lose value.

+ +

For brievety, next examples will omit .sink { ... }.store(in:&cancellables).

+
+

Relational objects

+ +

To store objects containing nested identity objects you need to make them conform to one protocol: Aggregate.

+
struct AuthorBooks: Aggregate {
+  var id: Author.ID { author.id }
+
+  var author: Author
+  var books: [Book]
+
+  // `nestedEntitiesKeyPaths` must list all Identifiable/Aggregate this object contain
+  var nestedEntitiesKeyPaths: [PartialIdentifiableKeyPath<Self>] {
+    [.init(\.author), .init(\.books)]
+  }
+}
+
+ +

CohesionKit then handles synchronisation for the three entities:

+ +
    +
  • AuthorBook
  • +
+

Author

+ Author + +
    +
  • Book
  • +
+ +
+

Only writable keypath are accepted. Using a KeyPath (let) will result in error: “Key path value type KeyPath cannot be converted to contextual type WritableKeyPath

+
+ +

This gives you the ability to retrieve them independently from each other:

+
let authorBooks = AuthorBooks(
+    author: Author(id: 1, name: "George R.R Martin"),
+    books: [
+      Book(id: "ACK", title: "A Clash of Kings"),
+      Book(id: "ADD", title: "A Dance with Dragons")
+    ]
+)
+
+entityStore.store(authorBooks)
+
+entityStore.find(Author.self, id: 1) // George R.R Martin
+entityStore.find(Book.self, id: "ACK") // A Clash of Kings
+entityStore.find(Book.self, id: "ADD") // A Dance with Dragons
+
+ +

You can also modify any of them however you want. Notice the change is visible from the object itself AND from aggregate objects:

+
let newAuthor = Author(id: 1, name: "George R.R MartinI")
+
+entityStore.store(newAuthor)
+
+entityStore.find(Author.self, id: 1) // George R.R MartinI
+entityStore.find(AuthorBooks.self, id: 1) // George R.R MartinI + [A Clash of Kings, A Dance with Dragons]
+
+ +
+

You might think about storing books on Author directly (author.books). In this case Author needs to implement Aggregate and declare books as nested entity.

+ +

However I strongly advise you to not nest Identifiable objects into other Identifiable objects. Read Handling relationships article if you want to know more about this subject.

+
+

Storing vs Updating

+ +

For now we only focused on entityStore.store but CohesionKit comes with another method to store data: entityStore.update.

+ +

Sometimes both can be used but they each have a different purpose:

+ +
    +
  1. store is suited for storing full data retrieved from webservices, like GET /user for instance
  2. +
  3. update is usually used for partial data. It’s also the preferred method when receiving events from websockets.
  4. +
+

Advanced topics

+

Enum support

+ +

Starting with 0.13 library has support for enum types. Note that you’ll need to conform to EntityWrapper and provide computed getter/setter for each entity you’d like to store.

+
enum MediaType: EntityWrapper {
+  case book(Book)
+  case game(Game)
+  case tvShow(TvShow)
+
+  func wrappedEntitiesKeyPaths<Root>(relativeTo parent: WritableKeyPath<Root, Self>) -> [PartialIdentifiableKeyPath<Root>] {
+    [.init(parent.appending(\.book)), .init(parent.appending(\.game)), .init(parent.appending(\.tvShow))]
+  }
+
+  var book: Book? {
+    get { ... }
+    set { ... }
+  }
+
+  var game: Game? {
+    get { ... }
+    set { ... }
+  }
+
+  var tvShow: TvShow? {
+    get { ... }
+    set { ... }
+  }
+}
+
+struct AuthorMedia: Aggregate {
+  var author: Author
+  var media: MediaType
+
+  var nestedEntitiesKeyPaths: [PartialIdentifiableKeyPath<Self>] {
+    [.init(\.author), .init(wrapper: \.media)]
+  }
+}
+
+

Aliases

+ +

Sometimes you need to retrieve data without knowing the object id. Common case is current user.

+ +

CohesionKit provides a suitable mechanism: aliases. Aliases allow you to register and find entities using a key.

+
extension AliasKey where T == User {
+  static let currentUser = AliasKey("user")
+}
+
+entityStore.store(currentUser, named: .currentUser)
+
+ +

Then request it somewhere else:

+
entityStore.find(named: .currentUser) // return the current user
+
+ +

Compared to regular entities, aliased objects are long-live objects: they will be kept in the storage even if no one observes them. This allow registered observers to be notified when alias value change:

+
entityStore.removeAlias(named: .currentUser) // observers will be notified currentUser is nil.
+
+entityStore.store(newCurrentUser, named: .currentUser) // observers will be notified that currentUser changed even if currentUser was nil before
+
+

Stale data

+ +

When storing data CohesionKit actually require you to set a modification stamp on it. Stamp is used as a marker to compare data freshness: the higher stamp is the more recent data is.

+ +

By default CohesionKit will use the current date as stamp.

+
entityStore.store(book) // use default stamp: current date
+entityStore.store(book, modifiedAt: Date().stamp) // explicitly use Date time stamp
+entityStore.store(book, modifiedAt: 9000) // any Double value is valid
+
+ +

If for some reason you try to store data with a stamp lower than the already stamped stored data then the update will be discarded.

+

Weak memory management

+ +

CohesionKit has a weak memory policy: objects are kept in EntityStore as long as someone use them.

+ +

To that end you need to retain observers as long as you’re interested in the data:

+
let book = Book(id: "ACK", title: "A Clash of Kings")
+let cancellable = entityStore.store(book) // observer is retained: data is retained
+
+entityStore.find(Book.self, id: "ACK") // return  "A Clash of Kings"
+
+ +

If you don’t create/retain observers then once entities have no more observers they will be automatically discarded from the storage.

+
let book = Book(id: "ACK", title: "A Clash of Kings")
+_ = entityStore.store(book) // observer is not retained and no one else observe this book: data is released
+
+entityStore.find(Book.self, id: "ACK") // return nil
+
+
let book = Book(id: "ACK", title: "A Clash of Kings")
+var cancellable = entityStore.store(book).asPublisher.sink { ... }
+let cancellable2 = entityStore.find(Book.self, id: "ACK") // return a publisher
+
+cancellable = nil
+
+entityStore.find(Book.self, id: "ACK") // return "A Clash of Kings" because cancellable2 still observe this book
+
+

License

+ +

This project is released under the MIT License. Please see the LICENSE file for details.

+ +
+
+ +
+
+ + diff --git a/docsets/.docset/Contents/Resources/Documents/js/jazzy.js b/docsets/.docset/Contents/Resources/Documents/js/jazzy.js new file mode 100755 index 0000000..1984416 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/js/jazzy.js @@ -0,0 +1,74 @@ +// Jazzy - https://github.com/realm/jazzy +// Copyright Realm Inc. +// SPDX-License-Identifier: MIT + +window.jazzy = {'docset': false} +if (typeof window.dash != 'undefined') { + document.documentElement.className += ' dash' + window.jazzy.docset = true +} +if (navigator.userAgent.match(/xcode/i)) { + document.documentElement.className += ' xcode' + window.jazzy.docset = true +} + +function toggleItem($link, $content) { + var animationDuration = 300; + $link.toggleClass('token-open'); + $content.slideToggle(animationDuration); +} + +function itemLinkToContent($link) { + return $link.parent().parent().next(); +} + +// On doc load + hash-change, open any targetted item +function openCurrentItemIfClosed() { + if (window.jazzy.docset) { + return; + } + var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token'); + $content = itemLinkToContent($link); + if ($content.is(':hidden')) { + toggleItem($link, $content); + } +} + +$(openCurrentItemIfClosed); +$(window).on('hashchange', openCurrentItemIfClosed); + +// On item link ('token') click, toggle its discussion +$('.token').on('click', function(event) { + if (window.jazzy.docset) { + return; + } + var $link = $(this); + toggleItem($link, itemLinkToContent($link)); + + // Keeps the document from jumping to the hash. + var href = $link.attr('href'); + if (history.pushState) { + history.pushState({}, '', href); + } else { + location.hash = href; + } + event.preventDefault(); +}); + +// Clicks on links to the current, closed, item need to open the item +$("a:not('.token')").on('click', function() { + if (location == this.href) { + openCurrentItemIfClosed(); + } +}); + +// KaTeX rendering +if ("katex" in window) { + $($('.math').each( (_, element) => { + katex.render(element.textContent, element, { + displayMode: $(element).hasClass('m-block'), + throwOnError: false, + trust: true + }); + })) +} diff --git a/docsets/.docset/Contents/Resources/Documents/js/jazzy.search.js b/docsets/.docset/Contents/Resources/Documents/js/jazzy.search.js new file mode 100644 index 0000000..359cdbb --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/js/jazzy.search.js @@ -0,0 +1,74 @@ +// Jazzy - https://github.com/realm/jazzy +// Copyright Realm Inc. +// SPDX-License-Identifier: MIT + +$(function(){ + var $typeahead = $('[data-typeahead]'); + var $form = $typeahead.parents('form'); + var searchURL = $form.attr('action'); + + function displayTemplate(result) { + return result.name; + } + + function suggestionTemplate(result) { + var t = '
'; + t += '' + result.name + ''; + if (result.parent_name) { + t += '' + result.parent_name + ''; + } + t += '
'; + return t; + } + + $typeahead.one('focus', function() { + $form.addClass('loading'); + + $.getJSON(searchURL).then(function(searchData) { + const searchIndex = lunr(function() { + this.ref('url'); + this.field('name'); + this.field('abstract'); + for (const [url, doc] of Object.entries(searchData)) { + this.add({url: url, name: doc.name, abstract: doc.abstract}); + } + }); + + $typeahead.typeahead( + { + highlight: true, + minLength: 3, + autoselect: true + }, + { + limit: 10, + display: displayTemplate, + templates: { suggestion: suggestionTemplate }, + source: function(query, sync) { + const lcSearch = query.toLowerCase(); + const results = searchIndex.query(function(q) { + q.term(lcSearch, { boost: 100 }); + q.term(lcSearch, { + boost: 10, + wildcard: lunr.Query.wildcard.TRAILING + }); + }).map(function(result) { + var doc = searchData[result.ref]; + doc.url = result.ref; + return doc; + }); + sync(results); + } + } + ); + $form.removeClass('loading'); + $typeahead.trigger('focus'); + }); + }); + + var baseURL = searchURL.slice(0, -"search.json".length); + + $typeahead.on('typeahead:select', function(e, result) { + window.location = baseURL + result.url; + }); +}); diff --git a/docsets/.docset/Contents/Resources/Documents/js/jquery.min.js b/docsets/.docset/Contents/Resources/Documents/js/jquery.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 00){var c=e.utils.clone(r)||{};c.position=[a,l],c.index=s.length,s.push(new e.Token(i.slice(a,o),c))}a=o+1}}return s},e.tokenizer.separator=/[\s\-]+/,e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,r){r in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+r),t.label=r,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var r=t.label&&t.label in this.registeredFunctions;r||e.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",t)},e.Pipeline.load=function(t){var r=new e.Pipeline;return t.forEach(function(t){var i=e.Pipeline.registeredFunctions[t];if(!i)throw new Error("Cannot load unregistered function: "+t);r.add(i)}),r},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(t){e.Pipeline.warnIfFunctionNotRegistered(t),this._stack.push(t)},this)},e.Pipeline.prototype.after=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,r)},e.Pipeline.prototype.before=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");this._stack.splice(i,0,r)},e.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);t!=-1&&this._stack.splice(t,1)},e.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:sa?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},e.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},e.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var o,a=s.str.charAt(0);a in s.node.edges?o=s.node.edges[a]:(o=new e.TokenSet,s.node.edges[a]=o),1==s.str.length&&(o["final"]=!0),n.push({node:o,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(0!=s.editsRemaining){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new e.TokenSet;s.node.edges["*"]=u}if(0==s.str.length&&(u["final"]=!0),n.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&n.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),1==s.str.length&&(s.node["final"]=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}1==s.str.length&&(l["final"]=!0),n.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c,h=s.str.charAt(0),d=s.str.charAt(1);d in s.node.edges?c=s.node.edges[d]:(c=new e.TokenSet,s.node.edges[d]=c),1==s.str.length&&(c["final"]=!0),n.push({node:c,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return i},e.TokenSet.fromString=function(t){for(var r=new e.TokenSet,i=r,n=0,s=t.length;n=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},e.Builder.prototype.k1=function(e){this._k1=e},e.Builder.prototype.add=function(t,r){var i=t[this._ref],n=Object.keys(this._fields);this._documents[i]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do t=this.next(),r=t.charCodeAt(0);while(r>47&&r<58);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more())return e.QueryLexer.lexText},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var r=t.next();if(r==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(92!=r.charCodeAt(0)){if(":"==r)return e.QueryLexer.lexField;if("~"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if("^"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if("+"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if("-"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if(r.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}else t.escapeCharacter()}},e.QueryParser=function(t,r){this.lexer=new e.QueryLexer(t),this.query=r,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseClause;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},e.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},e.QueryParser.parseClause=function(t){var r=t.peekLexeme();if(void 0!=r)switch(r.type){case e.QueryLexer.PRESENCE:return e.QueryParser.parsePresence;case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(i+=" with value '"+r.str+"'"),new e.QueryParseError(i,r.start,r.end)}},e.QueryParser.parsePresence=function(t){var r=t.consumeLexeme();if(void 0!=r){switch(r.str){case"-":t.currentClause.presence=e.Query.presence.PROHIBITED;break;case"+":t.currentClause.presence=e.Query.presence.REQUIRED;break;default:var i="unrecognised presence operator'"+r.str+"'";throw new e.QueryParseError(i,r.start,r.end)}var n=t.peekLexeme();if(void 0==n){var i="expecting term or field, found nothing";throw new e.QueryParseError(i,r.start,r.end)}switch(n.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expecting term or field, found '"+n.type+"'";throw new e.QueryParseError(i,n.start,n.end)}}},e.QueryParser.parseField=function(t){var r=t.consumeLexeme();if(void 0!=r){if(t.query.allFields.indexOf(r.str)==-1){var i=t.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),n="unrecognised field '"+r.str+"', possible fields: "+i;throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.fields=[r.str];var s=t.peekLexeme();if(void 0==s){var n="expecting term, found nothing";throw new e.QueryParseError(n,r.start,r.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var n="expecting term, found '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var r=t.consumeLexeme();if(void 0!=r){t.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(void 0==i)return void t.nextClause();switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(n,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="edit distance must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="boost must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.lunr=t()}(this,function(){return e})}(); diff --git a/docsets/.docset/Contents/Resources/Documents/js/typeahead.jquery.js b/docsets/.docset/Contents/Resources/Documents/js/typeahead.jquery.js new file mode 100644 index 0000000..bcb734b --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/js/typeahead.jquery.js @@ -0,0 +1,1695 @@ +/*! + * typeahead.js 1.3.3 + * https://github.com/corejavascript/typeahead.js + * Copyright 2013-2024 Twitter, Inc. and other contributors; Licensed MIT + */ + + +(function(root, factory) { + if (typeof define === "function" && define.amd) { + define([ "jquery" ], function(a0) { + return factory(a0); + }); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(require("jquery")); + } else { + factory(root["jQuery"]); + } +})(this, function($) { + var _ = function() { + "use strict"; + return { + isMsie: function() { + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + isElement: function(obj) { + return !!(obj && obj.nodeType === 1); + }, + isJQuery: function(obj) { + return obj instanceof $; + }, + toStr: function toStr(s) { + return _.isUndefined(s) || s === null ? "" : s + ""; + }, + bind: $.proxy, + each: function(collection, cb) { + $.each(collection, reverseArgs); + function reverseArgs(index, value) { + return cb(value, index); + } + }, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + identity: function(x) { + return x; + }, + clone: function(obj) { + return $.extend(true, {}, obj); + }, + getIdGenerator: function() { + var counter = 0; + return function() { + return counter++; + }; + }, + templatify: function templatify(obj) { + return $.isFunction(obj) ? obj : template; + function template() { + return String(obj); + } + }, + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + stringify: function(val) { + return _.isString(val) ? val : JSON.stringify(val); + }, + guid: function() { + function _p8(s) { + var p = (Math.random().toString(16) + "000000000").substr(2, 8); + return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; + } + return "tt-" + _p8() + _p8(true) + _p8(true) + _p8(); + }, + noop: function() {} + }; + }(); + var WWW = function() { + "use strict"; + var defaultClassNames = { + wrapper: "twitter-typeahead", + input: "tt-input", + hint: "tt-hint", + menu: "tt-menu", + dataset: "tt-dataset", + suggestion: "tt-suggestion", + selectable: "tt-selectable", + empty: "tt-empty", + open: "tt-open", + cursor: "tt-cursor", + highlight: "tt-highlight" + }; + return build; + function build(o) { + var www, classes; + classes = _.mixin({}, defaultClassNames, o); + www = { + css: buildCss(), + classes: classes, + html: buildHtml(classes), + selectors: buildSelectors(classes) + }; + return { + css: www.css, + html: www.html, + classes: www.classes, + selectors: www.selectors, + mixin: function(o) { + _.mixin(o, www); + } + }; + } + function buildHtml(c) { + return { + wrapper: '', + menu: '
' + }; + } + function buildSelectors(classes) { + var selectors = {}; + _.each(classes, function(v, k) { + selectors[k] = "." + v; + }); + return selectors; + } + function buildCss() { + var css = { + wrapper: { + position: "relative", + display: "inline-block" + }, + hint: { + position: "absolute", + top: "0", + left: "0", + borderColor: "transparent", + boxShadow: "none", + opacity: "1" + }, + input: { + position: "relative", + verticalAlign: "top", + backgroundColor: "transparent" + }, + inputWithNoHint: { + position: "relative", + verticalAlign: "top" + }, + menu: { + position: "absolute", + top: "100%", + left: "0", + zIndex: "100", + display: "none" + }, + ltr: { + left: "0", + right: "auto" + }, + rtl: { + left: "auto", + right: " 0" + } + }; + if (_.isMsie()) { + _.mixin(css.input, { + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" + }); + } + return css; + } + }(); + var EventBus = function() { + "use strict"; + var namespace, deprecationMap; + namespace = "typeahead:"; + deprecationMap = { + render: "rendered", + cursorchange: "cursorchanged", + select: "selected", + autocomplete: "autocompleted" + }; + function EventBus(o) { + if (!o || !o.el) { + $.error("EventBus initialized without el"); + } + this.$el = $(o.el); + } + _.mixin(EventBus.prototype, { + _trigger: function(type, args) { + var $e = $.Event(namespace + type); + this.$el.trigger.call(this.$el, $e, args || []); + return $e; + }, + before: function(type) { + var args, $e; + args = [].slice.call(arguments, 1); + $e = this._trigger("before" + type, args); + return $e.isDefaultPrevented(); + }, + trigger: function(type) { + var deprecatedType; + this._trigger(type, [].slice.call(arguments, 1)); + if (deprecatedType = deprecationMap[type]) { + this._trigger(deprecatedType, [].slice.call(arguments, 1)); + } + } + }); + return EventBus; + }(); + var EventEmitter = function() { + "use strict"; + var splitter = /\s+/, nextTick = getNextTick(); + return { + onSync: onSync, + onAsync: onAsync, + off: off, + trigger: trigger + }; + function on(method, types, cb, context) { + var type; + if (!cb) { + return this; + } + types = types.split(splitter); + cb = context ? bindContext(cb, context) : cb; + this._callbacks = this._callbacks || {}; + while (type = types.shift()) { + this._callbacks[type] = this._callbacks[type] || { + sync: [], + async: [] + }; + this._callbacks[type][method].push(cb); + } + return this; + } + function onAsync(types, cb, context) { + return on.call(this, "async", types, cb, context); + } + function onSync(types, cb, context) { + return on.call(this, "sync", types, cb, context); + } + function off(types) { + var type; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + while (type = types.shift()) { + delete this._callbacks[type]; + } + return this; + } + function trigger(types) { + var type, callbacks, args, syncFlush, asyncFlush; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + args = [].slice.call(arguments, 1); + while ((type = types.shift()) && (callbacks = this._callbacks[type])) { + syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); + asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); + syncFlush() && nextTick(asyncFlush); + } + return this; + } + function getFlush(callbacks, context, args) { + return flush; + function flush() { + var cancelled; + for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { + cancelled = callbacks[i].apply(context, args) === false; + } + return !cancelled; + } + } + function getNextTick() { + var nextTickFn; + if (window.setImmediate) { + nextTickFn = function nextTickSetImmediate(fn) { + setImmediate(function() { + fn(); + }); + }; + } else { + nextTickFn = function nextTickSetTimeout(fn) { + setTimeout(function() { + fn(); + }, 0); + }; + } + return nextTickFn; + } + function bindContext(fn, context) { + return fn.bind ? fn.bind(context) : function() { + fn.apply(context, [].slice.call(arguments, 0)); + }; + } + }(); + var highlight = function(doc) { + "use strict"; + var defaults = { + node: null, + pattern: null, + tagName: "strong", + className: null, + wordsOnly: false, + caseSensitive: false, + diacriticInsensitive: false + }; + var accented = { + A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Aa]", + B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Bb]", + C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Cc]", + D: "[DdĎďDŽ-džDZ-dzᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Dd]", + E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ee]", + F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ff-fflFf]", + G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Gg]", + H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Hh]", + I: "[IiÌ-Ïì-ïĨ-İIJijǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕fiffiIi]", + J: "[JjIJ-ĵLJ-njǰʲᴶⅉ⒥ⒿⓙⱼJj]", + K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Kk]", + L: "[LlĹ-ŀLJ-ljˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿flfflLl]", + M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Mm]", + N: "[NnÑñŃ-ʼnNJ-njǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Nn]", + O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Oo]", + P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Pp]", + Q: "[Qqℚ⒬Ⓠⓠ㏃Qq]", + R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Rr]", + S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜stSs]", + T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ſtstTt]", + U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Uu]", + V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Vv]", + W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ww]", + X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Xx]", + Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Yy]", + Z: "[ZzŹ-žDZ-dzᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Zz]" + }; + return function hightlight(o) { + var regex; + o = _.mixin({}, defaults, o); + if (!o.node || !o.pattern) { + return; + } + o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; + regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive); + traverse(o.node, hightlightTextNode); + function hightlightTextNode(textNode) { + var match, patternNode, wrapperNode; + if (match = regex.exec(textNode.data)) { + wrapperNode = doc.createElement(o.tagName); + o.className && (wrapperNode.className = o.className); + patternNode = textNode.splitText(match.index); + patternNode.splitText(match[0].length); + wrapperNode.appendChild(patternNode.cloneNode(true)); + textNode.parentNode.replaceChild(wrapperNode, patternNode); + } + return !!match; + } + function traverse(el, hightlightTextNode) { + var childNode, TEXT_NODE_TYPE = 3; + for (var i = 0; i < el.childNodes.length; i++) { + childNode = el.childNodes[i]; + if (childNode.nodeType === TEXT_NODE_TYPE) { + i += hightlightTextNode(childNode) ? 1 : 0; + } else { + traverse(childNode, hightlightTextNode); + } + } + } + }; + function accent_replacer(chr) { + return accented[chr.toUpperCase()] || chr; + } + function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) { + var escapedPatterns = [], regexStr; + for (var i = 0, len = patterns.length; i < len; i++) { + var escapedWord = _.escapeRegExChars(patterns[i]); + if (diacriticInsensitive) { + escapedWord = escapedWord.replace(/\S/g, accent_replacer); + } + escapedPatterns.push(escapedWord); + } + regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; + return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); + } + }(window.document); + var Input = function() { + "use strict"; + var specialKeyCodeMap; + specialKeyCodeMap = { + 9: "tab", + 27: "esc", + 37: "left", + 39: "right", + 13: "enter", + 38: "up", + 40: "down" + }; + function Input(o, www) { + var id; + o = o || {}; + if (!o.input) { + $.error("input is missing"); + } + www.mixin(this); + this.$hint = $(o.hint); + this.$input = $(o.input); + this.$menu = $(o.menu); + id = this.$input.attr("id") || _.guid(); + this.$menu.attr("id", id + "_listbox"); + this.$hint.attr({ + "aria-hidden": true + }); + this.$input.attr({ + "aria-owns": id + "_listbox", + "aria-controls": id + "_listbox", + role: "combobox", + "aria-autocomplete": "list", + "aria-expanded": false + }); + this.query = this.$input.val(); + this.queryWhenFocused = this.hasFocus() ? this.query : null; + this.$overflowHelper = buildOverflowHelper(this.$input); + this._checkLanguageDirection(); + if (this.$hint.length === 0) { + this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; + } + this.onSync("cursorchange", this._updateDescendent); + } + Input.normalizeQuery = function(str) { + return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + }; + _.mixin(Input.prototype, EventEmitter, { + _onBlur: function onBlur() { + this.resetInputValue(); + this.trigger("blurred"); + }, + _onFocus: function onFocus() { + this.queryWhenFocused = this.query; + this.trigger("focused"); + }, + _onKeydown: function onKeydown($e) { + var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; + this._managePreventDefault(keyName, $e); + if (keyName && this._shouldTrigger(keyName, $e)) { + this.trigger(keyName + "Keyed", $e); + } + }, + _onInput: function onInput() { + this._setQuery(this.getInputValue()); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + _managePreventDefault: function managePreventDefault(keyName, $e) { + var preventDefault; + switch (keyName) { + case "up": + case "down": + preventDefault = !withModifier($e); + break; + + default: + preventDefault = false; + } + preventDefault && $e.preventDefault(); + }, + _shouldTrigger: function shouldTrigger(keyName, $e) { + var trigger; + switch (keyName) { + case "tab": + trigger = !withModifier($e); + break; + + default: + trigger = true; + } + return trigger; + }, + _checkLanguageDirection: function checkLanguageDirection() { + var dir = (this.$input.css("direction") || "ltr").toLowerCase(); + if (this.dir !== dir) { + this.dir = dir; + this.$hint.attr("dir", dir); + this.trigger("langDirChanged", dir); + } + }, + _setQuery: function setQuery(val, silent) { + var areEquivalent, hasDifferentWhitespace; + areEquivalent = areQueriesEquivalent(val, this.query); + hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; + this.query = val; + if (!silent && !areEquivalent) { + this.trigger("queryChanged", this.query); + } else if (!silent && hasDifferentWhitespace) { + this.trigger("whitespaceChanged", this.query); + } + }, + _updateDescendent: function updateDescendent(event, id) { + this.$input.attr("aria-activedescendant", id); + }, + bind: function() { + var that = this, onBlur, onFocus, onKeydown, onInput; + onBlur = _.bind(this._onBlur, this); + onFocus = _.bind(this._onFocus, this); + onKeydown = _.bind(this._onKeydown, this); + onInput = _.bind(this._onInput, this); + this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); + if (!_.isMsie() || _.isMsie() > 9) { + this.$input.on("input.tt", onInput); + } else { + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { + if (specialKeyCodeMap[$e.which || $e.keyCode]) { + return; + } + _.defer(_.bind(that._onInput, that, $e)); + }); + } + return this; + }, + focus: function focus() { + this.$input.focus(); + }, + blur: function blur() { + this.$input.blur(); + }, + getLangDir: function getLangDir() { + return this.dir; + }, + getQuery: function getQuery() { + return this.query || ""; + }, + setQuery: function setQuery(val, silent) { + this.setInputValue(val); + this._setQuery(val, silent); + }, + hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { + return this.query !== this.queryWhenFocused; + }, + getInputValue: function getInputValue() { + return this.$input.val(); + }, + setInputValue: function setInputValue(value) { + this.$input.val(value); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + resetInputValue: function resetInputValue() { + this.setInputValue(this.query); + }, + getHint: function getHint() { + return this.$hint.val(); + }, + setHint: function setHint(value) { + this.$hint.val(value); + }, + clearHint: function clearHint() { + this.setHint(""); + }, + clearHintIfInvalid: function clearHintIfInvalid() { + var val, hint, valIsPrefixOfHint, isValid; + val = this.getInputValue(); + hint = this.getHint(); + valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; + isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); + !isValid && this.clearHint(); + }, + hasFocus: function hasFocus() { + return this.$input.is(":focus"); + }, + hasOverflow: function hasOverflow() { + var constraint = this.$input.width() - 2; + this.$overflowHelper.text(this.getInputValue()); + return this.$overflowHelper.width() >= constraint; + }, + isCursorAtEnd: function() { + var valueLength, selectionStart, range; + valueLength = this.$input.val().length; + selectionStart = this.$input[0].selectionStart; + if (_.isNumber(selectionStart)) { + return selectionStart === valueLength; + } else if (document.selection) { + range = document.selection.createRange(); + range.moveStart("character", -valueLength); + return valueLength === range.text.length; + } + return true; + }, + destroy: function destroy() { + this.$hint.off(".tt"); + this.$input.off(".tt"); + this.$overflowHelper.remove(); + this.$hint = this.$input = this.$overflowHelper = $("
"); + }, + setAriaExpanded: function setAriaExpanded(value) { + this.$input.attr("aria-expanded", value); + } + }); + return Input; + function buildOverflowHelper($input) { + return $('').css({ + position: "absolute", + visibility: "hidden", + whiteSpace: "pre", + fontFamily: $input.css("font-family"), + fontSize: $input.css("font-size"), + fontStyle: $input.css("font-style"), + fontVariant: $input.css("font-variant"), + fontWeight: $input.css("font-weight"), + wordSpacing: $input.css("word-spacing"), + letterSpacing: $input.css("letter-spacing"), + textIndent: $input.css("text-indent"), + textRendering: $input.css("text-rendering"), + textTransform: $input.css("text-transform") + }).insertAfter($input); + } + function areQueriesEquivalent(a, b) { + return Input.normalizeQuery(a) === Input.normalizeQuery(b); + } + function withModifier($e) { + return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; + } + }(); + var Dataset = function() { + "use strict"; + var keys, nameGenerator; + keys = { + dataset: "tt-selectable-dataset", + val: "tt-selectable-display", + obj: "tt-selectable-object" + }; + nameGenerator = _.getIdGenerator(); + function Dataset(o, www) { + o = o || {}; + o.templates = o.templates || {}; + o.templates.notFound = o.templates.notFound || o.templates.empty; + if (!o.source) { + $.error("missing source"); + } + if (!o.node) { + $.error("missing node"); + } + if (o.name && !isValidName(o.name)) { + $.error("invalid dataset name: " + o.name); + } + www.mixin(this); + this.highlight = !!o.highlight; + this.name = _.toStr(o.name || nameGenerator()); + this.limit = o.limit || 5; + this.displayFn = getDisplayFn(o.display || o.displayKey); + this.templates = getTemplates(o.templates, this.displayFn); + this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; + this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; + this._resetLastSuggestion(); + this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); + } + Dataset.extractData = function extractData(el) { + var $el = $(el); + if ($el.data(keys.obj)) { + return { + dataset: $el.data(keys.dataset) || "", + val: $el.data(keys.val) || "", + obj: $el.data(keys.obj) || null + }; + } + return null; + }; + _.mixin(Dataset.prototype, EventEmitter, { + _overwrite: function overwrite(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (this.async && this.templates.pending) { + this._renderPending(query); + } else if (!this.async && this.templates.notFound) { + this._renderNotFound(query); + } else { + this._empty(); + } + this.trigger("rendered", suggestions, false, this.name); + }, + _append: function append(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length && this.$lastSuggestion.length) { + this._appendSuggestions(query, suggestions); + } else if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (!this.$lastSuggestion.length && this.templates.notFound) { + this._renderNotFound(query); + } + this.trigger("rendered", suggestions, true, this.name); + }, + _renderSuggestions: function renderSuggestions(query, suggestions) { + var $fragment; + $fragment = this._getSuggestionsFragment(query, suggestions); + this.$lastSuggestion = $fragment.children().last(); + this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); + }, + _appendSuggestions: function appendSuggestions(query, suggestions) { + var $fragment, $lastSuggestion; + $fragment = this._getSuggestionsFragment(query, suggestions); + $lastSuggestion = $fragment.children().last(); + this.$lastSuggestion.after($fragment); + this.$lastSuggestion = $lastSuggestion; + }, + _renderPending: function renderPending(query) { + var template = this.templates.pending; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _renderNotFound: function renderNotFound(query) { + var template = this.templates.notFound; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _empty: function empty() { + this.$el.empty(); + this._resetLastSuggestion(); + }, + _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { + var that = this, fragment; + fragment = document.createDocumentFragment(); + _.each(suggestions, function getSuggestionNode(suggestion) { + var $el, context; + context = that._injectQuery(query, suggestion); + $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); + fragment.appendChild($el[0]); + }); + this.highlight && highlight({ + className: this.classes.highlight, + node: fragment, + pattern: query + }); + return $(fragment); + }, + _getFooter: function getFooter(query, suggestions) { + return this.templates.footer ? this.templates.footer({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _getHeader: function getHeader(query, suggestions) { + return this.templates.header ? this.templates.header({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _resetLastSuggestion: function resetLastSuggestion() { + this.$lastSuggestion = $(); + }, + _injectQuery: function injectQuery(query, obj) { + return _.isObject(obj) ? _.mixin({ + _query: query + }, obj) : obj; + }, + update: function update(query) { + var that = this, canceled = false, syncCalled = false, rendered = 0; + this.cancel(); + this.cancel = function cancel() { + canceled = true; + that.cancel = $.noop; + that.async && that.trigger("asyncCanceled", query, that.name); + }; + this.source(query, sync, async); + !syncCalled && sync([]); + function sync(suggestions) { + if (syncCalled) { + return; + } + syncCalled = true; + suggestions = (suggestions || []).slice(0, that.limit); + rendered = suggestions.length; + that._overwrite(query, suggestions); + if (rendered < that.limit && that.async) { + that.trigger("asyncRequested", query, that.name); + } + } + function async(suggestions) { + suggestions = suggestions || []; + if (!canceled && rendered < that.limit) { + that.cancel = $.noop; + var idx = Math.abs(rendered - that.limit); + rendered += idx; + that._append(query, suggestions.slice(0, idx)); + that.async && that.trigger("asyncReceived", query, that.name); + } + } + }, + cancel: $.noop, + clear: function clear() { + this._empty(); + this.cancel(); + this.trigger("cleared"); + }, + isEmpty: function isEmpty() { + return this.$el.is(":empty"); + }, + destroy: function destroy() { + this.$el = $("
"); + } + }); + return Dataset; + function getDisplayFn(display) { + display = display || _.stringify; + return _.isFunction(display) ? display : displayFn; + function displayFn(obj) { + return obj[display]; + } + } + function getTemplates(templates, displayFn) { + return { + notFound: templates.notFound && _.templatify(templates.notFound), + pending: templates.pending && _.templatify(templates.pending), + header: templates.header && _.templatify(templates.header), + footer: templates.footer && _.templatify(templates.footer), + suggestion: templates.suggestion ? userSuggestionTemplate : suggestionTemplate + }; + function userSuggestionTemplate(context) { + var template = templates.suggestion; + return $(template(context)).attr("id", _.guid()); + } + function suggestionTemplate(context) { + return $('
').attr("id", _.guid()).text(displayFn(context)); + } + } + function isValidName(str) { + return /^[_a-zA-Z0-9-]+$/.test(str); + } + }(); + var Menu = function() { + "use strict"; + function Menu(o, www) { + var that = this; + o = o || {}; + if (!o.node) { + $.error("node is required"); + } + www.mixin(this); + this.$node = $(o.node); + this.query = null; + this.datasets = _.map(o.datasets, initializeDataset); + function initializeDataset(oDataset) { + var node = that.$node.find(oDataset.node).first(); + oDataset.node = node.length ? node : $("
").appendTo(that.$node); + return new Dataset(oDataset, www); + } + } + _.mixin(Menu.prototype, EventEmitter, { + _onSelectableClick: function onSelectableClick($e) { + this.trigger("selectableClicked", $($e.currentTarget)); + }, + _onRendered: function onRendered(type, dataset, suggestions, async) { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetRendered", dataset, suggestions, async); + }, + _onCleared: function onCleared() { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetCleared"); + }, + _propagate: function propagate() { + this.trigger.apply(this, arguments); + }, + _allDatasetsEmpty: function allDatasetsEmpty() { + return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) { + var isEmpty = dataset.isEmpty(); + this.$node.attr("aria-expanded", !isEmpty); + return isEmpty; + }, this)); + }, + _getSelectables: function getSelectables() { + return this.$node.find(this.selectors.selectable); + }, + _removeCursor: function _removeCursor() { + var $selectable = this.getActiveSelectable(); + $selectable && $selectable.removeClass(this.classes.cursor); + }, + _ensureVisible: function ensureVisible($el) { + var elTop, elBottom, nodeScrollTop, nodeHeight; + elTop = $el.position().top; + elBottom = elTop + $el.outerHeight(true); + nodeScrollTop = this.$node.scrollTop(); + nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); + if (elTop < 0) { + this.$node.scrollTop(nodeScrollTop + elTop); + } else if (nodeHeight < elBottom) { + this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); + } + }, + bind: function() { + var that = this, onSelectableClick; + onSelectableClick = _.bind(this._onSelectableClick, this); + this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); + this.$node.on("mouseover", this.selectors.selectable, function() { + that.setCursor($(this)); + }); + this.$node.on("mouseleave", function() { + that._removeCursor(); + }); + _.each(this.datasets, function(dataset) { + dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); + }); + return this; + }, + isOpen: function isOpen() { + return this.$node.hasClass(this.classes.open); + }, + open: function open() { + this.$node.scrollTop(0); + this.$node.addClass(this.classes.open); + }, + close: function close() { + this.$node.attr("aria-expanded", false); + this.$node.removeClass(this.classes.open); + this._removeCursor(); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.attr("dir", dir); + }, + selectableRelativeToCursor: function selectableRelativeToCursor(delta) { + var $selectables, $oldCursor, oldIndex, newIndex; + $oldCursor = this.getActiveSelectable(); + $selectables = this._getSelectables(); + oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; + newIndex = oldIndex + delta; + newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; + newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; + return newIndex === -1 ? null : $selectables.eq(newIndex); + }, + setCursor: function setCursor($selectable) { + this._removeCursor(); + if ($selectable = $selectable && $selectable.first()) { + $selectable.addClass(this.classes.cursor); + this._ensureVisible($selectable); + } + }, + getSelectableData: function getSelectableData($el) { + return $el && $el.length ? Dataset.extractData($el) : null; + }, + getActiveSelectable: function getActiveSelectable() { + var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); + return $selectable.length ? $selectable : null; + }, + getTopSelectable: function getTopSelectable() { + var $selectable = this._getSelectables().first(); + return $selectable.length ? $selectable : null; + }, + update: function update(query) { + var isValidUpdate = query !== this.query; + if (isValidUpdate) { + this.query = query; + _.each(this.datasets, updateDataset); + } + return isValidUpdate; + function updateDataset(dataset) { + dataset.update(query); + } + }, + empty: function empty() { + _.each(this.datasets, clearDataset); + this.query = null; + this.$node.addClass(this.classes.empty); + function clearDataset(dataset) { + dataset.clear(); + } + }, + destroy: function destroy() { + this.$node.off(".tt"); + this.$node = $("
"); + _.each(this.datasets, destroyDataset); + function destroyDataset(dataset) { + dataset.destroy(); + } + } + }); + return Menu; + }(); + var Status = function() { + "use strict"; + function Status(options) { + this.$el = $("", { + role: "status", + "aria-live": "polite" + }).css({ + position: "absolute", + padding: "0", + border: "0", + height: "1px", + width: "1px", + "margin-bottom": "-1px", + "margin-right": "-1px", + overflow: "hidden", + clip: "rect(0 0 0 0)", + "white-space": "nowrap" + }); + options.$input.after(this.$el); + _.each(options.menu.datasets, _.bind(function(dataset) { + if (dataset.onSync) { + dataset.onSync("rendered", _.bind(this.update, this)); + dataset.onSync("cleared", _.bind(this.cleared, this)); + } + }, this)); + } + _.mixin(Status.prototype, { + update: function update(event, suggestions) { + var length = suggestions.length; + var words; + if (length === 1) { + words = { + result: "result", + is: "is" + }; + } else { + words = { + result: "results", + is: "are" + }; + } + this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate."); + }, + cleared: function() { + this.$el.text(""); + } + }); + return Status; + }(); + var DefaultMenu = function() { + "use strict"; + var s = Menu.prototype; + function DefaultMenu() { + Menu.apply(this, [].slice.call(arguments, 0)); + } + _.mixin(DefaultMenu.prototype, Menu.prototype, { + open: function open() { + !this._allDatasetsEmpty() && this._show(); + return s.open.apply(this, [].slice.call(arguments, 0)); + }, + close: function close() { + this._hide(); + return s.close.apply(this, [].slice.call(arguments, 0)); + }, + _onRendered: function onRendered() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onRendered.apply(this, [].slice.call(arguments, 0)); + }, + _onCleared: function onCleared() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onCleared.apply(this, [].slice.call(arguments, 0)); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); + return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); + }, + _hide: function hide() { + this.$node.hide(); + }, + _show: function show() { + this.$node.css("display", "block"); + } + }); + return DefaultMenu; + }(); + var Typeahead = function() { + "use strict"; + function Typeahead(o, www) { + var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; + o = o || {}; + if (!o.input) { + $.error("missing input"); + } + if (!o.menu) { + $.error("missing menu"); + } + if (!o.eventBus) { + $.error("missing event bus"); + } + www.mixin(this); + this.eventBus = o.eventBus; + this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; + this.input = o.input; + this.menu = o.menu; + this.enabled = true; + this.autoselect = !!o.autoselect; + this.active = false; + this.input.hasFocus() && this.activate(); + this.dir = this.input.getLangDir(); + this._hacks(); + this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); + onFocused = c(this, "activate", "open", "_onFocused"); + onBlurred = c(this, "deactivate", "_onBlurred"); + onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); + onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); + onEscKeyed = c(this, "isActive", "_onEscKeyed"); + onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); + onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); + onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); + onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); + onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); + onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); + this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); + } + _.mixin(Typeahead.prototype, { + _hacks: function hacks() { + var $input, $menu; + $input = this.input.$input || $("
"); + $menu = this.menu.$node || $("
"); + $input.on("blur.tt", function($e) { + var active, isActive, hasActive; + active = document.activeElement; + isActive = $menu.is(active); + hasActive = $menu.has(active).length > 0; + if (_.isMsie() && (isActive || hasActive)) { + $e.preventDefault(); + $e.stopImmediatePropagation(); + _.defer(function() { + $input.focus(); + }); + } + }); + $menu.on("mousedown.tt", function($e) { + $e.preventDefault(); + }); + }, + _onSelectableClicked: function onSelectableClicked(type, $el) { + this.select($el); + }, + _onDatasetCleared: function onDatasetCleared() { + this._updateHint(); + }, + _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) { + this._updateHint(); + if (this.autoselect) { + var cursorClass = this.selectors.cursor.substr(1); + this.menu.$node.find(this.selectors.suggestion).first().addClass(cursorClass); + } + this.eventBus.trigger("render", suggestions, async, dataset); + }, + _onAsyncRequested: function onAsyncRequested(type, dataset, query) { + this.eventBus.trigger("asyncrequest", query, dataset); + }, + _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { + this.eventBus.trigger("asynccancel", query, dataset); + }, + _onAsyncReceived: function onAsyncReceived(type, dataset, query) { + this.eventBus.trigger("asyncreceive", query, dataset); + }, + _onFocused: function onFocused() { + this._minLengthMet() && this.menu.update(this.input.getQuery()); + }, + _onBlurred: function onBlurred() { + if (this.input.hasQueryChangedSinceLastFocus()) { + this.eventBus.trigger("change", this.input.getQuery()); + } + }, + _onEnterKeyed: function onEnterKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + if (this.select($selectable)) { + $e.preventDefault(); + $e.stopPropagation(); + } + } else if (this.autoselect) { + if (this.select(this.menu.getTopSelectable())) { + $e.preventDefault(); + $e.stopPropagation(); + } + } + }, + _onTabKeyed: function onTabKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + this.select($selectable) && $e.preventDefault(); + } else if (this.autoselect) { + if ($selectable = this.menu.getTopSelectable()) { + this.autocomplete($selectable) && $e.preventDefault(); + } + } + }, + _onEscKeyed: function onEscKeyed() { + this.close(); + }, + _onUpKeyed: function onUpKeyed() { + this.moveCursor(-1); + }, + _onDownKeyed: function onDownKeyed() { + this.moveCursor(+1); + }, + _onLeftKeyed: function onLeftKeyed() { + if (this.dir === "rtl" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onRightKeyed: function onRightKeyed() { + if (this.dir === "ltr" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onQueryChanged: function onQueryChanged(e, query) { + this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); + }, + _onWhitespaceChanged: function onWhitespaceChanged() { + this._updateHint(); + }, + _onLangDirChanged: function onLangDirChanged(e, dir) { + if (this.dir !== dir) { + this.dir = dir; + this.menu.setLanguageDirection(dir); + } + }, + _openIfActive: function openIfActive() { + this.isActive() && this.open(); + }, + _minLengthMet: function minLengthMet(query) { + query = _.isString(query) ? query : this.input.getQuery() || ""; + return query.length >= this.minLength; + }, + _updateHint: function updateHint() { + var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; + $selectable = this.menu.getTopSelectable(); + data = this.menu.getSelectableData($selectable); + val = this.input.getInputValue(); + if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { + query = Input.normalizeQuery(val); + escapedQuery = _.escapeRegExChars(query); + frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); + match = frontMatchRegEx.exec(data.val); + match && this.input.setHint(val + match[1]); + } else { + this.input.clearHint(); + } + }, + isEnabled: function isEnabled() { + return this.enabled; + }, + enable: function enable() { + this.enabled = true; + }, + disable: function disable() { + this.enabled = false; + }, + isActive: function isActive() { + return this.active; + }, + activate: function activate() { + if (this.isActive()) { + return true; + } else if (!this.isEnabled() || this.eventBus.before("active")) { + return false; + } else { + this.active = true; + this.eventBus.trigger("active"); + return true; + } + }, + deactivate: function deactivate() { + if (!this.isActive()) { + return true; + } else if (this.eventBus.before("idle")) { + return false; + } else { + this.active = false; + this.close(); + this.eventBus.trigger("idle"); + return true; + } + }, + isOpen: function isOpen() { + return this.menu.isOpen(); + }, + open: function open() { + if (!this.isOpen() && !this.eventBus.before("open")) { + this.input.setAriaExpanded(true); + this.menu.open(); + this._updateHint(); + this.eventBus.trigger("open"); + } + return this.isOpen(); + }, + close: function close() { + if (this.isOpen() && !this.eventBus.before("close")) { + this.input.setAriaExpanded(false); + this.menu.close(); + this.input.clearHint(); + this.input.resetInputValue(); + this.eventBus.trigger("close"); + } + return !this.isOpen(); + }, + setVal: function setVal(val) { + this.input.setQuery(_.toStr(val)); + }, + getVal: function getVal() { + return this.input.getQuery(); + }, + select: function select($selectable) { + var data = this.menu.getSelectableData($selectable); + if (data && !this.eventBus.before("select", data.obj, data.dataset)) { + this.input.setQuery(data.val, true); + this.eventBus.trigger("select", data.obj, data.dataset); + this.close(); + return true; + } + return false; + }, + autocomplete: function autocomplete($selectable) { + var query, data, isValid; + query = this.input.getQuery(); + data = this.menu.getSelectableData($selectable); + isValid = data && query !== data.val; + if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) { + this.input.setQuery(data.val); + this.eventBus.trigger("autocomplete", data.obj, data.dataset); + return true; + } + return false; + }, + moveCursor: function moveCursor(delta) { + var query, $candidate, data, suggestion, datasetName, cancelMove, id; + query = this.input.getQuery(); + $candidate = this.menu.selectableRelativeToCursor(delta); + data = this.menu.getSelectableData($candidate); + suggestion = data ? data.obj : null; + datasetName = data ? data.dataset : null; + id = $candidate ? $candidate.attr("id") : null; + this.input.trigger("cursorchange", id); + cancelMove = this._minLengthMet() && this.menu.update(query); + if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) { + this.menu.setCursor($candidate); + if (data) { + if (typeof data.val === "string") { + this.input.setInputValue(data.val); + } + } else { + this.input.resetInputValue(); + this._updateHint(); + } + this.eventBus.trigger("cursorchange", suggestion, datasetName); + return true; + } + return false; + }, + destroy: function destroy() { + this.input.destroy(); + this.menu.destroy(); + } + }); + return Typeahead; + function c(ctx) { + var methods = [].slice.call(arguments, 1); + return function() { + var args = [].slice.call(arguments); + _.each(methods, function(method) { + return ctx[method].apply(ctx, args); + }); + }; + } + }(); + (function() { + "use strict"; + var old, keys, methods; + old = $.fn.typeahead; + keys = { + www: "tt-www", + attrs: "tt-attrs", + typeahead: "tt-typeahead" + }; + methods = { + initialize: function initialize(o, datasets) { + var www; + datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); + o = o || {}; + www = WWW(o.classNames); + return this.each(attach); + function attach() { + var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor; + _.each(datasets, function(d) { + d.highlight = !!o.highlight; + }); + $input = $(this); + $wrapper = $(www.html.wrapper); + $hint = $elOrNull(o.hint); + $menu = $elOrNull(o.menu); + defaultHint = o.hint !== false && !$hint; + defaultMenu = o.menu !== false && !$menu; + defaultHint && ($hint = buildHintFromInput($input, www)); + defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); + $hint && $hint.val(""); + $input = prepInput($input, www); + if (defaultHint || defaultMenu) { + $wrapper.css(www.css.wrapper); + $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); + $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); + } + MenuConstructor = defaultMenu ? DefaultMenu : Menu; + eventBus = new EventBus({ + el: $input + }); + input = new Input({ + hint: $hint, + input: $input, + menu: $menu + }, www); + menu = new MenuConstructor({ + node: $menu, + datasets: datasets + }, www); + status = new Status({ + $input: $input, + menu: menu + }); + typeahead = new Typeahead({ + input: input, + menu: menu, + eventBus: eventBus, + minLength: o.minLength, + autoselect: o.autoselect + }, www); + $input.data(keys.www, www); + $input.data(keys.typeahead, typeahead); + } + }, + isEnabled: function isEnabled() { + var enabled; + ttEach(this.first(), function(t) { + enabled = t.isEnabled(); + }); + return enabled; + }, + enable: function enable() { + ttEach(this, function(t) { + t.enable(); + }); + return this; + }, + disable: function disable() { + ttEach(this, function(t) { + t.disable(); + }); + return this; + }, + isActive: function isActive() { + var active; + ttEach(this.first(), function(t) { + active = t.isActive(); + }); + return active; + }, + activate: function activate() { + ttEach(this, function(t) { + t.activate(); + }); + return this; + }, + deactivate: function deactivate() { + ttEach(this, function(t) { + t.deactivate(); + }); + return this; + }, + isOpen: function isOpen() { + var open; + ttEach(this.first(), function(t) { + open = t.isOpen(); + }); + return open; + }, + open: function open() { + ttEach(this, function(t) { + t.open(); + }); + return this; + }, + close: function close() { + ttEach(this, function(t) { + t.close(); + }); + return this; + }, + select: function select(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.select($el); + }); + return success; + }, + autocomplete: function autocomplete(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.autocomplete($el); + }); + return success; + }, + moveCursor: function moveCursoe(delta) { + var success = false; + ttEach(this.first(), function(t) { + success = t.moveCursor(delta); + }); + return success; + }, + val: function val(newVal) { + var query; + if (!arguments.length) { + ttEach(this.first(), function(t) { + query = t.getVal(); + }); + return query; + } else { + ttEach(this, function(t) { + t.setVal(_.toStr(newVal)); + }); + return this; + } + }, + destroy: function destroy() { + ttEach(this, function(typeahead, $input) { + revert($input); + typeahead.destroy(); + }); + return this; + } + }; + $.fn.typeahead = function(method) { + if (methods[method]) { + return methods[method].apply(this, [].slice.call(arguments, 1)); + } else { + return methods.initialize.apply(this, arguments); + } + }; + $.fn.typeahead.noConflict = function noConflict() { + $.fn.typeahead = old; + return this; + }; + function ttEach($els, fn) { + $els.each(function() { + var $input = $(this), typeahead; + (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); + }); + } + function buildHintFromInput($input, www) { + return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop({ + readonly: true, + required: false + }).removeAttr("id name placeholder").removeClass("required").attr({ + spellcheck: "false", + tabindex: -1 + }); + } + function prepInput($input, www) { + $input.data(keys.attrs, { + dir: $input.attr("dir"), + autocomplete: $input.attr("autocomplete"), + spellcheck: $input.attr("spellcheck"), + style: $input.attr("style") + }); + $input.addClass(www.classes.input).attr({ + spellcheck: false + }); + try { + !$input.attr("dir") && $input.attr("dir", "auto"); + } catch (e) {} + return $input; + } + function getBackgroundStyles($el) { + return { + backgroundAttachment: $el.css("background-attachment"), + backgroundClip: $el.css("background-clip"), + backgroundColor: $el.css("background-color"), + backgroundImage: $el.css("background-image"), + backgroundOrigin: $el.css("background-origin"), + backgroundPosition: $el.css("background-position"), + backgroundRepeat: $el.css("background-repeat"), + backgroundSize: $el.css("background-size") + }; + } + function revert($input) { + var www, $wrapper; + www = $input.data(keys.www); + $wrapper = $input.parent().filter(www.selectors.wrapper); + _.each($input.data(keys.attrs), function(val, key) { + _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); + }); + $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); + if ($wrapper.length) { + $input.detach().insertAfter($wrapper); + $wrapper.remove(); + } + } + function $elOrNull(obj) { + var isValid, $el; + isValid = _.isJQuery(obj) || _.isElement(obj); + $el = isValid ? $(obj).first() : []; + return $el.length ? $el : null; + } + })(); +}); \ No newline at end of file diff --git a/docsets/.docset/Contents/Resources/Documents/search.json b/docsets/.docset/Contents/Resources/Documents/search.json new file mode 100644 index 0000000..09b8f88 --- /dev/null +++ b/docsets/.docset/Contents/Resources/Documents/search.json @@ -0,0 +1 @@ +{"Typealiases.html#/s:11CohesionKit17EntityEnumWrappera":{"name":"EntityEnumWrapper"},"Typealiases.html#/s:11CohesionKit11IdentityMapa":{"name":"IdentityMap"},"Typealiases.html#/s:11CohesionKit5Stampa":{"name":"Stamp","abstract":"

A type used to annotate track object modifications through time."},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__Gcs0D0Rd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an Identifiable keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcAA9AggregateRd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an Aggregate keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcs0D0Rd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an optional Identifiable keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcAA9AggregateRd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcSMRd__s0D07ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcSMRd__s0D07ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcSMRd__AA9Aggregate7ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcSMRd__AA9Aggregate7ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathV7wrapperACyxGs08WritableeF0Cyxqd__G_tcAA13EntityWrapperRd__lufc":{"name":"init(wrapper:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathV7wrapperACyxGs08WritableeF0Cyxqd__SgG_tcAA13EntityWrapperRd__lufc":{"name":"init(wrapper:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV8OnChangea":{"name":"OnChange","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV5valuexvp":{"name":"value","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV7observe8onChangeAA12SubscriptionCyxc_tF":{"name":"observe(onChange:)","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV11asPublisher7Combine03AnyF0Vyxs5NeverOGvp":{"name":"asPublisher","abstract":"

A Publisher emitting the observer current value and subscribing to any subsequents new values

","parent_name":"EntityObserver"},"Structs/AliasKey.html#/s:11CohesionKit8AliasKeyV5namedACyxGSS_tcfc":{"name":"init(named:)","parent_name":"AliasKey"},"Structs/AliasKey.html":{"name":"AliasKey","abstract":"

A value representing an Entity or set of Entity

"},"Structs/EntityObserver.html":{"name":"EntityObserver","abstract":"

A type registering observers on a given entity from identity storage

"},"Structs/PartialIdentifiableKeyPath.html":{"name":"PartialIdentifiableKeyPath","abstract":"

A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP8didStore_2idyqd__m_2IDQyd__ts12IdentifiableRd__lF":{"name":"didStore(_:id:)","abstract":"

Notify when an entity was stored in the identity map

","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP16didFailedToStore_2id5erroryqd__m_2IDQyd__s5Error_pts12IdentifiableRd__lF":{"name":"didFailedToStore(_:id:error:)","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP16didRegisterAliasyyAA0F3KeyVyqd__GlF":{"name":"didRegisterAlias(_:)","abstract":"

Notify an alias is registered with new entities

","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP18didUnregisterAliasyyAA0F3KeyVyqd__GlF":{"name":"didUnregisterAlias(_:)","abstract":"

Notify an alias is suppressed from the identity map

","parent_name":"Logger"},"Protocols/EntityWrapper.html#/s:11CohesionKit13EntityWrapperP23wrappedEntitiesKeyPaths10relativeToSayAA019PartialIdentifiableG4PathVyqd__GGs08WritablegM0Cyqd__xG_tlF":{"name":"wrappedEntitiesKeyPaths(relativeTo:)","abstract":"

Entities contained by all cases relative to the parent container

","parent_name":"EntityWrapper"},"Protocols/Aggregate.html#/s:11CohesionKit9AggregateP22nestedEntitiesKeyPathsSayAA019PartialIdentifiableF4PathVyxGGvp":{"name":"nestedEntitiesKeyPaths","abstract":"

keypaths to nested models

","parent_name":"Aggregate"},"Protocols/Aggregate.html":{"name":"Aggregate","abstract":"

An Identifiable model containing nested models

"},"Protocols/EntityWrapper.html":{"name":"EntityWrapper","abstract":"

A type wrapping one or more Identifiable types."},"Protocols/Logger.html":{"name":"Logger","abstract":"

a protocol reporting EntityStore internal information

"},"Extensions/Date.html#/s:10Foundation4DateV11CohesionKitE5stampSdvp":{"name":"stamp","abstract":"

Generate a stamp suitable to use in EntityStore.","parent_name":"Date"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0Vy6OutputQz7FailureQzGAD11EntityStoreC_AD8AliasKeyVyALGSgSdts12IdentifiableALRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the Identifiable upstream into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0Vy6OutputQz7FailureQzGAD11EntityStoreC_AD8AliasKeyVyALGSgSdtAD9AggregateALRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the Aggregate upstream into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0VySay6Output_7ElementQZG7FailureQzGAD11EntityStoreC_AD8AliasKeyVyAKQzGSgSdtSlAVRQs12IdentifiableAMRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the upstream collection into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0VySay6Output_7ElementQZG7FailureQzGAD11EntityStoreC_AD8AliasKeyVyAKQzGSgSdtSlAVRQAD9AggregateAMRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the upstream collection into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html":{"name":"Publisher"},"Extensions/Date.html":{"name":"Date"},"Extensions.html#/s:11CohesionKit14AliasContainerV":{"name":"AliasContainer"},"Extensions.html#/s:11CohesionKit10EntityNodeC":{"name":"EntityNode"},"Enums/StampError.html#/s:11CohesionKit10StampErrorO6tooOldyACSd_SdtcACmF":{"name":"tooOld(current:received:)","abstract":"

received stamp is smaller than current stamp

","parent_name":"StampError"},"Enums/StampError.html":{"name":"StampError"},"Classes/Subscription.html#/s:11CohesionKit12SubscriptionC11unsubscribeyycvp":{"name":"unsubscribe","parent_name":"Subscription"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6Updatea":{"name":"Update","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5queue6loggerACSo012OS_dispatch_E0CSg_AA6Logger_pSgtcfc":{"name":"init(queue:logger:)","abstract":"

Create a new EntityStore instance optionally with a queue and a logger

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store6entity5named10modifiedAt9ifPresentAA0C8ObserverVyxGx_AA8AliasKeyVyxGSgSdSgyxzcSgts12IdentifiableRzlF":{"name":"store(entity:named:modifiedAt:ifPresent:)","abstract":"

Store an entity in the storage. Entity will be stored only if stamp (modifiedAt) is higher than in previous","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store6entity5named10modifiedAt9ifPresentAA0C8ObserverVyxGx_AA8AliasKeyVyxGSgSdSgyxzcSgtAA9AggregateRzlF":{"name":"store(entity:named:modifiedAt:ifPresent:)","abstract":"

Store an aggregate in the storage. Each aggregate entities will be stored only if stamp (modifiedAt) is higher than in previous","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store8entities5named10modifiedAtAA0C8ObserverVySay7ElementQzGGx_AA8AliasKeyVyxGSgSdSgtSlRzs12IdentifiableAKRQlF":{"name":"store(entities:named:modifiedAt:)","abstract":"

Store multiple entities at once

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store8entities5named10modifiedAtAA0C8ObserverVySay7ElementQzGGx_AA8AliasKeyVyxGSgSdSgtSlRzAA9AggregateAKRQlF":{"name":"store(entities:named:modifiedAt:)","abstract":"

store multiple aggregates at once

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find_2idAA0C8ObserverVyxGSgxm_2IDQzts12IdentifiableRzlF":{"name":"find(_:id:)","abstract":"

Try to find an entity/aggregate in the storage.

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find5namedAA0C8ObserverVyxSgGAA8AliasKeyVyxG_ts12IdentifiableRzlF":{"name":"find(named:)","abstract":"

Try to find an entity/aggregate registered under named alias

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find5namedAA0C8ObserverVyxSgGAA8AliasKeyVyxG_tSlRzlF":{"name":"find(named:)","abstract":"

Try to find a collected registered under named alias

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update_2id10modifiedAtADSbxm_2IDQzSdSgyxzXEts12IdentifiableRzlF":{"name":"update(_:id:modifiedAt:update:)","abstract":"

Updates an already stored entity using a closure. Useful to update a few properties or when you assume the entity","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update_2id10modifiedAt_Sbxm_2IDQzSdSgyxzXEtAA9AggregateRzlF":{"name":"update(_:id:modifiedAt:_:)","abstract":"

Updates an already stored alias using a closure. This is useful if you don’t have a full entity for update","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEts12IdentifiableRzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already stored alias using a closure.","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtAA9AggregateRzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already stored alias using a closure.","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtSlRzs12Identifiable7ElementRpzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already existing collection alias content","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtSlRzAA9Aggregate7ElementRpzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already existing collection alias content","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC11removeAlias5namedyAA0F3KeyVyxG_tlF":{"name":"removeAlias(named:)","abstract":"

Removes an alias from the storage

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC11removeAlias5namedyAA0F3KeyVyxG_tSlRzlF":{"name":"removeAlias(named:)","abstract":"

Removes an alias from the storage

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC14removeAllAliasyyF":{"name":"removeAllAlias()","abstract":"

Removes all alias from identity map

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC9removeAllyyF":{"name":"removeAll()","abstract":"

Removes all alias AND all objects stored weakly. You should not need this method and rather use removeAlias.","parent_name":"EntityStore"},"Classes/EntityStore.html":{"name":"EntityStore","abstract":"

Manages entities lifecycle and synchronisation

"},"Classes/Subscription.html":{"name":"Subscription"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Enums.html":{"name":"Enumerations","abstract":"

The following enumerations are available globally.

"},"Extensions.html":{"name":"Extensions","abstract":"

The following extensions are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"},"Typealiases.html":{"name":"Type Aliases","abstract":"

The following type aliases are available globally.

"}} \ No newline at end of file diff --git a/docsets/.docset/Contents/Resources/docSet.dsidx b/docsets/.docset/Contents/Resources/docSet.dsidx new file mode 100644 index 0000000000000000000000000000000000000000..dbb6f9caf12e49e1fdce6cbfd8b401a4567ec6cb GIT binary patch literal 36864 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 jI?H0FWjQ4)NwswG_b=_Y&iFS4^z?I literal 0 HcmV?d00001 diff --git a/docsets/.tgz b/docsets/.tgz new file mode 100644 index 0000000000000000000000000000000000000000..efef75660e0c660065d71b52a13676d5ba565eec GIT binary patch literal 88144 zcmZs>QZQK0Xwr1P5wbxqvKl|)6#<|IQBdRj8;v%Xt zMm~g5P(ZoPlV(7mmp!oFxTBs#2+CySO2wkQt)}aazXIv7o5Lxg;|nFFkqnd{DX7O= zs~2Pp1*@CaLfkOPh;*T)EtnCQ8qVxo`Ih^bXT607q6fCdE!as0%1z#RKQ&?t+?4&W#YA3YF8hz8nx zKV@^#gN=I;y zS<)j)9mYm@wX%00zlJKLHW@s02h&tl0&UIhk5b#$)2GUor4n?I47)w@aBM7G#Kc2@ zRZ7x3`j7>3GLZ!`IvZx5C@h{;AJNu-4ubK#9Yf;ksw?6OKLxPp{{Dzq$Y7a#_94$+ zuA_Ft0GpX-!@TS9)uv*s{sx*WvwZxiDJ`ry{jn|Gp*Lj{xVoq3+lisQx$SWK756Z?UaIME-24sNc&=L0HK(zDZ&JH3Wbir! z6nF3;5=v}M%gHOu__MN(%8Q#5fQ(WSo`bgIGI74`;$6vnpt?(bU)s9=-ug7S-EF;m z72y3Y`S@|8?Cf1}9c|S-nbhg)atIEshFAN${wPg*ri+FHsYV|RzxGZ~!4yp`u^#B39lESkQqo%0A4frz?x>2I8GjdNU#1 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ð0X}fVRoJSKxf<6cj6gNtlSHG+HHQ2 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

K?m@>ShNMj$VpNtxK%CNqX@NHdF2w2NINL?d| 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 E08SIoN&o-= literal 0 HcmV?d00001 diff --git a/img/carat.png b/img/carat.png new file mode 100755 index 0000000000000000000000000000000000000000..29d2f7fd4955fca6bc6fb740e0373a2c358c398e GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRo!3HEV4DF?Wlw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlqAi{-jv*Ddl5#RKJQ5NTUZgiPI4RUKGIKU?u8L&ndhX1t za+0CMVUnT(Gnb}ei=c~x==tMH^F1_tBocXwcoSWoO-SZY-o>!8%^=Bms)(~h;m_U( zXNixk28L}0LS5-jKyq@#2gyS|J&f#pGCLkTc<@2s1dqeyqJ*Rc0tSIETAgmODY;(s z2y|Mcp&2}7rpBprBBB~1qM1`N+}4SoxYVPqsXi&l`rxZp{(w0iSy$Nv5*Vy!RapG^ S^0y4=eg;ohKbLh*2~7a!Pg}VF literal 0 HcmV?d00001 diff --git a/img/dash.png b/img/dash.png new file mode 100755 index 0000000000000000000000000000000000000000..6f694c7a012b417908da3687a0a39aa182e91c74 GIT binary patch literal 1338 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..9be8ca0 --- /dev/null +++ b/index.html @@ -0,0 +1,411 @@ + + + + Index Reference + + + + + + + + + + + + +

+
+

Docs (100% documented)

+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+ +

CohesionKit - Single Source of Truth

+ +

+ swift + platforms + test + + twitter + +

+ +

Keep your models synchronized in your app and never have any inconsistency anymore. Designed using latest Swift features.

+

Why using CohesionKit?

+ +
    +
  • 🔁 You need realtime synchronisation (websockets)
  • +
  • 🌐 You have multiple data sources (REST, CoreData, websocket, phone Contacts, Google Maps, etc…)
  • +
  • 🪶 You look for a full Swift lightweight tool
  • +
  • 🗃️ You want to use structs
  • +
+

Features

+ +
    +
  • [x] 🦺 Thread safe
  • +
  • [x] 🪶 Lighweight (< 600 lines of code)
  • +
  • [x] 🪪 Working with plain Swift struct and Identifiable objects
  • +
  • [x] 🔀 Support for Combine
  • +
  • [x] 🧠 In-memory storage
  • +
  • [x] 🐾 Low memory footprint
  • +
  • [x] 🐪 Strongly typed
  • +
+

Where to put CohesionKit in my stack?

+ +

CohesionKit being a Single Source of Truth solution it handles your objects lifecycle and synchronization from any source.

+ +

You should put CohesionKit in front of your data sources (REST API, GraphQL, …) before returning data to your app.

+
sequenceDiagram
+    autonumber
+
+        YourApp ->>DataSource: findBooks
+        DataSource ->>GraphQL: query findBooks
+        GraphQL -->>DataSource: FindBooksQueryResult
+        DataSource ->>CohesionKit: store books [A,B,C]
+        CohesionKit -->> YourApp: Publisher<[A,B,C]>
+
+        WebSocket ->> WebSocketListener: book A updated
+        WebSocketListener ->> CohesionKit: update book A
+        CohesionKit -->> YourApp: Publisher<[A,B,C]>
+
+

Installation

+ +
    +
  • Swift Package Manager
  • +
+
dependencies: [
+    .package(url: "https://github.com/pjechris/CohesionKit.git", .upToNextMajor(from: "0.7.0"))
+]
+
+

Examples

+ +

Library comes with an example project so you can see a real case usage. It mostly shows:

+ +
    +
  • How to store data in the library
  • +
  • How to retrieve and update that data for realtime
  • +
  • How data is synchronised throughout multiple screens
  • +
+

Getting started

+

Storing an object

+ +

First create an instance of EntityStore:

+
let entityStore = EntityStore()
+
+ +

EntityStore let you store Identifiable objects:

+
struct Book: Identifiable {
+  let id: String
+  let title: String
+}
+
+let book = Book(id: "ABCD", name: "My Book")
+
+entityStore.store(book)
+
+ +

Then You can retrieve the object from anywhere in your code:

+
// somewhere else in the code
+entityStore.find(Book.self, id: "ABCD") // return Book(id: "ABCD", name: "My Book")
+
+

Observing changes

+ +

Every time data is updated in EntityStore triggers a notification to any registered observer. To register yourself as an observer just use result from store or find methods:

+
func findBooks() -> some Publisher<[Book], Error> {
+  // 1. load data using URLSession
+  URLSession(...)
+  // 2. store data inside our entityStore
+    .store(in: entityStore)
+    .sink { ... }
+    .store(in: &cancellables)
+}
+
+
entityStore.find(Book.self, id: 1)?
+  .asPublisher
+  .sink { ... }
+  .store(in: &cancellables)
+
+ +
+

CohesionKit has a weak memory policy you should read about. As such, returned value from entityStore.store must be strongly retained to not lose value.

+ +

For brievety, next examples will omit .sink { ... }.store(in:&cancellables).

+
+

Relational objects

+ +

To store objects containing nested identity objects you need to make them conform to one protocol: Aggregate.

+
struct AuthorBooks: Aggregate {
+  var id: Author.ID { author.id }
+
+  var author: Author
+  var books: [Book]
+
+  // `nestedEntitiesKeyPaths` must list all Identifiable/Aggregate this object contain
+  var nestedEntitiesKeyPaths: [PartialIdentifiableKeyPath<Self>] {
+    [.init(\.author), .init(\.books)]
+  }
+}
+
+ +

CohesionKit then handles synchronisation for the three entities:

+ +
    +
  • AuthorBook
  • +
+

Author

+ Author + +
    +
  • Book
  • +
+ +
+

Only writable keypath are accepted. Using a KeyPath (let) will result in error: “Key path value type KeyPath cannot be converted to contextual type WritableKeyPath

+
+ +

This gives you the ability to retrieve them independently from each other:

+
let authorBooks = AuthorBooks(
+    author: Author(id: 1, name: "George R.R Martin"),
+    books: [
+      Book(id: "ACK", title: "A Clash of Kings"),
+      Book(id: "ADD", title: "A Dance with Dragons")
+    ]
+)
+
+entityStore.store(authorBooks)
+
+entityStore.find(Author.self, id: 1) // George R.R Martin
+entityStore.find(Book.self, id: "ACK") // A Clash of Kings
+entityStore.find(Book.self, id: "ADD") // A Dance with Dragons
+
+ +

You can also modify any of them however you want. Notice the change is visible from the object itself AND from aggregate objects:

+
let newAuthor = Author(id: 1, name: "George R.R MartinI")
+
+entityStore.store(newAuthor)
+
+entityStore.find(Author.self, id: 1) // George R.R MartinI
+entityStore.find(AuthorBooks.self, id: 1) // George R.R MartinI + [A Clash of Kings, A Dance with Dragons]
+
+ +
+

You might think about storing books on Author directly (author.books). In this case Author needs to implement Aggregate and declare books as nested entity.

+ +

However I strongly advise you to not nest Identifiable objects into other Identifiable objects. Read Handling relationships article if you want to know more about this subject.

+
+

Storing vs Updating

+ +

For now we only focused on entityStore.store but CohesionKit comes with another method to store data: entityStore.update.

+ +

Sometimes both can be used but they each have a different purpose:

+ +
    +
  1. store is suited for storing full data retrieved from webservices, like GET /user for instance
  2. +
  3. update is usually used for partial data. It’s also the preferred method when receiving events from websockets.
  4. +
+

Advanced topics

+

Enum support

+ +

Starting with 0.13 library has support for enum types. Note that you’ll need to conform to EntityWrapper and provide computed getter/setter for each entity you’d like to store.

+
enum MediaType: EntityWrapper {
+  case book(Book)
+  case game(Game)
+  case tvShow(TvShow)
+
+  func wrappedEntitiesKeyPaths<Root>(relativeTo parent: WritableKeyPath<Root, Self>) -> [PartialIdentifiableKeyPath<Root>] {
+    [.init(parent.appending(\.book)), .init(parent.appending(\.game)), .init(parent.appending(\.tvShow))]
+  }
+
+  var book: Book? {
+    get { ... }
+    set { ... }
+  }
+
+  var game: Game? {
+    get { ... }
+    set { ... }
+  }
+
+  var tvShow: TvShow? {
+    get { ... }
+    set { ... }
+  }
+}
+
+struct AuthorMedia: Aggregate {
+  var author: Author
+  var media: MediaType
+
+  var nestedEntitiesKeyPaths: [PartialIdentifiableKeyPath<Self>] {
+    [.init(\.author), .init(wrapper: \.media)]
+  }
+}
+
+

Aliases

+ +

Sometimes you need to retrieve data without knowing the object id. Common case is current user.

+ +

CohesionKit provides a suitable mechanism: aliases. Aliases allow you to register and find entities using a key.

+
extension AliasKey where T == User {
+  static let currentUser = AliasKey("user")
+}
+
+entityStore.store(currentUser, named: .currentUser)
+
+ +

Then request it somewhere else:

+
entityStore.find(named: .currentUser) // return the current user
+
+ +

Compared to regular entities, aliased objects are long-live objects: they will be kept in the storage even if no one observes them. This allow registered observers to be notified when alias value change:

+
entityStore.removeAlias(named: .currentUser) // observers will be notified currentUser is nil.
+
+entityStore.store(newCurrentUser, named: .currentUser) // observers will be notified that currentUser changed even if currentUser was nil before
+
+

Stale data

+ +

When storing data CohesionKit actually require you to set a modification stamp on it. Stamp is used as a marker to compare data freshness: the higher stamp is the more recent data is.

+ +

By default CohesionKit will use the current date as stamp.

+
entityStore.store(book) // use default stamp: current date
+entityStore.store(book, modifiedAt: Date().stamp) // explicitly use Date time stamp
+entityStore.store(book, modifiedAt: 9000) // any Double value is valid
+
+ +

If for some reason you try to store data with a stamp lower than the already stamped stored data then the update will be discarded.

+

Weak memory management

+ +

CohesionKit has a weak memory policy: objects are kept in EntityStore as long as someone use them.

+ +

To that end you need to retain observers as long as you’re interested in the data:

+
let book = Book(id: "ACK", title: "A Clash of Kings")
+let cancellable = entityStore.store(book) // observer is retained: data is retained
+
+entityStore.find(Book.self, id: "ACK") // return  "A Clash of Kings"
+
+ +

If you don’t create/retain observers then once entities have no more observers they will be automatically discarded from the storage.

+
let book = Book(id: "ACK", title: "A Clash of Kings")
+_ = entityStore.store(book) // observer is not retained and no one else observe this book: data is released
+
+entityStore.find(Book.self, id: "ACK") // return nil
+
+
let book = Book(id: "ACK", title: "A Clash of Kings")
+var cancellable = entityStore.store(book).asPublisher.sink { ... }
+let cancellable2 = entityStore.find(Book.self, id: "ACK") // return a publisher
+
+cancellable = nil
+
+entityStore.find(Book.self, id: "ACK") // return "A Clash of Kings" because cancellable2 still observe this book
+
+

License

+ +

This project is released under the MIT License. Please see the LICENSE file for details.

+ +
+
+ +
+
+ + diff --git a/js/jazzy.js b/js/jazzy.js new file mode 100755 index 0000000..1984416 --- /dev/null +++ b/js/jazzy.js @@ -0,0 +1,74 @@ +// Jazzy - https://github.com/realm/jazzy +// Copyright Realm Inc. +// SPDX-License-Identifier: MIT + +window.jazzy = {'docset': false} +if (typeof window.dash != 'undefined') { + document.documentElement.className += ' dash' + window.jazzy.docset = true +} +if (navigator.userAgent.match(/xcode/i)) { + document.documentElement.className += ' xcode' + window.jazzy.docset = true +} + +function toggleItem($link, $content) { + var animationDuration = 300; + $link.toggleClass('token-open'); + $content.slideToggle(animationDuration); +} + +function itemLinkToContent($link) { + return $link.parent().parent().next(); +} + +// On doc load + hash-change, open any targetted item +function openCurrentItemIfClosed() { + if (window.jazzy.docset) { + return; + } + var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token'); + $content = itemLinkToContent($link); + if ($content.is(':hidden')) { + toggleItem($link, $content); + } +} + +$(openCurrentItemIfClosed); +$(window).on('hashchange', openCurrentItemIfClosed); + +// On item link ('token') click, toggle its discussion +$('.token').on('click', function(event) { + if (window.jazzy.docset) { + return; + } + var $link = $(this); + toggleItem($link, itemLinkToContent($link)); + + // Keeps the document from jumping to the hash. + var href = $link.attr('href'); + if (history.pushState) { + history.pushState({}, '', href); + } else { + location.hash = href; + } + event.preventDefault(); +}); + +// Clicks on links to the current, closed, item need to open the item +$("a:not('.token')").on('click', function() { + if (location == this.href) { + openCurrentItemIfClosed(); + } +}); + +// KaTeX rendering +if ("katex" in window) { + $($('.math').each( (_, element) => { + katex.render(element.textContent, element, { + displayMode: $(element).hasClass('m-block'), + throwOnError: false, + trust: true + }); + })) +} diff --git a/js/jazzy.search.js b/js/jazzy.search.js new file mode 100644 index 0000000..359cdbb --- /dev/null +++ b/js/jazzy.search.js @@ -0,0 +1,74 @@ +// Jazzy - https://github.com/realm/jazzy +// Copyright Realm Inc. +// SPDX-License-Identifier: MIT + +$(function(){ + var $typeahead = $('[data-typeahead]'); + var $form = $typeahead.parents('form'); + var searchURL = $form.attr('action'); + + function displayTemplate(result) { + return result.name; + } + + function suggestionTemplate(result) { + var t = '
'; + t += '' + result.name + ''; + if (result.parent_name) { + t += '' + result.parent_name + ''; + } + t += '
'; + return t; + } + + $typeahead.one('focus', function() { + $form.addClass('loading'); + + $.getJSON(searchURL).then(function(searchData) { + const searchIndex = lunr(function() { + this.ref('url'); + this.field('name'); + this.field('abstract'); + for (const [url, doc] of Object.entries(searchData)) { + this.add({url: url, name: doc.name, abstract: doc.abstract}); + } + }); + + $typeahead.typeahead( + { + highlight: true, + minLength: 3, + autoselect: true + }, + { + limit: 10, + display: displayTemplate, + templates: { suggestion: suggestionTemplate }, + source: function(query, sync) { + const lcSearch = query.toLowerCase(); + const results = searchIndex.query(function(q) { + q.term(lcSearch, { boost: 100 }); + q.term(lcSearch, { + boost: 10, + wildcard: lunr.Query.wildcard.TRAILING + }); + }).map(function(result) { + var doc = searchData[result.ref]; + doc.url = result.ref; + return doc; + }); + sync(results); + } + } + ); + $form.removeClass('loading'); + $typeahead.trigger('focus'); + }); + }); + + var baseURL = searchURL.slice(0, -"search.json".length); + + $typeahead.on('typeahead:select', function(e, result) { + window.location = baseURL + result.url; + }); +}); diff --git a/js/jquery.min.js b/js/jquery.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 00){var c=e.utils.clone(r)||{};c.position=[a,l],c.index=s.length,s.push(new e.Token(i.slice(a,o),c))}a=o+1}}return s},e.tokenizer.separator=/[\s\-]+/,e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,r){r in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+r),t.label=r,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var r=t.label&&t.label in this.registeredFunctions;r||e.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",t)},e.Pipeline.load=function(t){var r=new e.Pipeline;return t.forEach(function(t){var i=e.Pipeline.registeredFunctions[t];if(!i)throw new Error("Cannot load unregistered function: "+t);r.add(i)}),r},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(t){e.Pipeline.warnIfFunctionNotRegistered(t),this._stack.push(t)},this)},e.Pipeline.prototype.after=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,r)},e.Pipeline.prototype.before=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");this._stack.splice(i,0,r)},e.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);t!=-1&&this._stack.splice(t,1)},e.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:sa?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},e.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},e.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var o,a=s.str.charAt(0);a in s.node.edges?o=s.node.edges[a]:(o=new e.TokenSet,s.node.edges[a]=o),1==s.str.length&&(o["final"]=!0),n.push({node:o,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(0!=s.editsRemaining){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new e.TokenSet;s.node.edges["*"]=u}if(0==s.str.length&&(u["final"]=!0),n.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&n.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),1==s.str.length&&(s.node["final"]=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}1==s.str.length&&(l["final"]=!0),n.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c,h=s.str.charAt(0),d=s.str.charAt(1);d in s.node.edges?c=s.node.edges[d]:(c=new e.TokenSet,s.node.edges[d]=c),1==s.str.length&&(c["final"]=!0),n.push({node:c,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return i},e.TokenSet.fromString=function(t){for(var r=new e.TokenSet,i=r,n=0,s=t.length;n=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},e.Builder.prototype.k1=function(e){this._k1=e},e.Builder.prototype.add=function(t,r){var i=t[this._ref],n=Object.keys(this._fields);this._documents[i]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do t=this.next(),r=t.charCodeAt(0);while(r>47&&r<58);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more())return e.QueryLexer.lexText},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var r=t.next();if(r==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(92!=r.charCodeAt(0)){if(":"==r)return e.QueryLexer.lexField;if("~"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if("^"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if("+"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if("-"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if(r.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}else t.escapeCharacter()}},e.QueryParser=function(t,r){this.lexer=new e.QueryLexer(t),this.query=r,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseClause;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},e.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},e.QueryParser.parseClause=function(t){var r=t.peekLexeme();if(void 0!=r)switch(r.type){case e.QueryLexer.PRESENCE:return e.QueryParser.parsePresence;case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(i+=" with value '"+r.str+"'"),new e.QueryParseError(i,r.start,r.end)}},e.QueryParser.parsePresence=function(t){var r=t.consumeLexeme();if(void 0!=r){switch(r.str){case"-":t.currentClause.presence=e.Query.presence.PROHIBITED;break;case"+":t.currentClause.presence=e.Query.presence.REQUIRED;break;default:var i="unrecognised presence operator'"+r.str+"'";throw new e.QueryParseError(i,r.start,r.end)}var n=t.peekLexeme();if(void 0==n){var i="expecting term or field, found nothing";throw new e.QueryParseError(i,r.start,r.end)}switch(n.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expecting term or field, found '"+n.type+"'";throw new e.QueryParseError(i,n.start,n.end)}}},e.QueryParser.parseField=function(t){var r=t.consumeLexeme();if(void 0!=r){if(t.query.allFields.indexOf(r.str)==-1){var i=t.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),n="unrecognised field '"+r.str+"', possible fields: "+i;throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.fields=[r.str];var s=t.peekLexeme();if(void 0==s){var n="expecting term, found nothing";throw new e.QueryParseError(n,r.start,r.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var n="expecting term, found '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var r=t.consumeLexeme();if(void 0!=r){t.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(void 0==i)return void t.nextClause();switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(n,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="edit distance must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="boost must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.lunr=t()}(this,function(){return e})}(); diff --git a/js/typeahead.jquery.js b/js/typeahead.jquery.js new file mode 100644 index 0000000..bcb734b --- /dev/null +++ b/js/typeahead.jquery.js @@ -0,0 +1,1695 @@ +/*! + * typeahead.js 1.3.3 + * https://github.com/corejavascript/typeahead.js + * Copyright 2013-2024 Twitter, Inc. and other contributors; Licensed MIT + */ + + +(function(root, factory) { + if (typeof define === "function" && define.amd) { + define([ "jquery" ], function(a0) { + return factory(a0); + }); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(require("jquery")); + } else { + factory(root["jQuery"]); + } +})(this, function($) { + var _ = function() { + "use strict"; + return { + isMsie: function() { + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + isElement: function(obj) { + return !!(obj && obj.nodeType === 1); + }, + isJQuery: function(obj) { + return obj instanceof $; + }, + toStr: function toStr(s) { + return _.isUndefined(s) || s === null ? "" : s + ""; + }, + bind: $.proxy, + each: function(collection, cb) { + $.each(collection, reverseArgs); + function reverseArgs(index, value) { + return cb(value, index); + } + }, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + identity: function(x) { + return x; + }, + clone: function(obj) { + return $.extend(true, {}, obj); + }, + getIdGenerator: function() { + var counter = 0; + return function() { + return counter++; + }; + }, + templatify: function templatify(obj) { + return $.isFunction(obj) ? obj : template; + function template() { + return String(obj); + } + }, + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + stringify: function(val) { + return _.isString(val) ? val : JSON.stringify(val); + }, + guid: function() { + function _p8(s) { + var p = (Math.random().toString(16) + "000000000").substr(2, 8); + return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; + } + return "tt-" + _p8() + _p8(true) + _p8(true) + _p8(); + }, + noop: function() {} + }; + }(); + var WWW = function() { + "use strict"; + var defaultClassNames = { + wrapper: "twitter-typeahead", + input: "tt-input", + hint: "tt-hint", + menu: "tt-menu", + dataset: "tt-dataset", + suggestion: "tt-suggestion", + selectable: "tt-selectable", + empty: "tt-empty", + open: "tt-open", + cursor: "tt-cursor", + highlight: "tt-highlight" + }; + return build; + function build(o) { + var www, classes; + classes = _.mixin({}, defaultClassNames, o); + www = { + css: buildCss(), + classes: classes, + html: buildHtml(classes), + selectors: buildSelectors(classes) + }; + return { + css: www.css, + html: www.html, + classes: www.classes, + selectors: www.selectors, + mixin: function(o) { + _.mixin(o, www); + } + }; + } + function buildHtml(c) { + return { + wrapper: '', + menu: '
' + }; + } + function buildSelectors(classes) { + var selectors = {}; + _.each(classes, function(v, k) { + selectors[k] = "." + v; + }); + return selectors; + } + function buildCss() { + var css = { + wrapper: { + position: "relative", + display: "inline-block" + }, + hint: { + position: "absolute", + top: "0", + left: "0", + borderColor: "transparent", + boxShadow: "none", + opacity: "1" + }, + input: { + position: "relative", + verticalAlign: "top", + backgroundColor: "transparent" + }, + inputWithNoHint: { + position: "relative", + verticalAlign: "top" + }, + menu: { + position: "absolute", + top: "100%", + left: "0", + zIndex: "100", + display: "none" + }, + ltr: { + left: "0", + right: "auto" + }, + rtl: { + left: "auto", + right: " 0" + } + }; + if (_.isMsie()) { + _.mixin(css.input, { + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" + }); + } + return css; + } + }(); + var EventBus = function() { + "use strict"; + var namespace, deprecationMap; + namespace = "typeahead:"; + deprecationMap = { + render: "rendered", + cursorchange: "cursorchanged", + select: "selected", + autocomplete: "autocompleted" + }; + function EventBus(o) { + if (!o || !o.el) { + $.error("EventBus initialized without el"); + } + this.$el = $(o.el); + } + _.mixin(EventBus.prototype, { + _trigger: function(type, args) { + var $e = $.Event(namespace + type); + this.$el.trigger.call(this.$el, $e, args || []); + return $e; + }, + before: function(type) { + var args, $e; + args = [].slice.call(arguments, 1); + $e = this._trigger("before" + type, args); + return $e.isDefaultPrevented(); + }, + trigger: function(type) { + var deprecatedType; + this._trigger(type, [].slice.call(arguments, 1)); + if (deprecatedType = deprecationMap[type]) { + this._trigger(deprecatedType, [].slice.call(arguments, 1)); + } + } + }); + return EventBus; + }(); + var EventEmitter = function() { + "use strict"; + var splitter = /\s+/, nextTick = getNextTick(); + return { + onSync: onSync, + onAsync: onAsync, + off: off, + trigger: trigger + }; + function on(method, types, cb, context) { + var type; + if (!cb) { + return this; + } + types = types.split(splitter); + cb = context ? bindContext(cb, context) : cb; + this._callbacks = this._callbacks || {}; + while (type = types.shift()) { + this._callbacks[type] = this._callbacks[type] || { + sync: [], + async: [] + }; + this._callbacks[type][method].push(cb); + } + return this; + } + function onAsync(types, cb, context) { + return on.call(this, "async", types, cb, context); + } + function onSync(types, cb, context) { + return on.call(this, "sync", types, cb, context); + } + function off(types) { + var type; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + while (type = types.shift()) { + delete this._callbacks[type]; + } + return this; + } + function trigger(types) { + var type, callbacks, args, syncFlush, asyncFlush; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + args = [].slice.call(arguments, 1); + while ((type = types.shift()) && (callbacks = this._callbacks[type])) { + syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); + asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); + syncFlush() && nextTick(asyncFlush); + } + return this; + } + function getFlush(callbacks, context, args) { + return flush; + function flush() { + var cancelled; + for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { + cancelled = callbacks[i].apply(context, args) === false; + } + return !cancelled; + } + } + function getNextTick() { + var nextTickFn; + if (window.setImmediate) { + nextTickFn = function nextTickSetImmediate(fn) { + setImmediate(function() { + fn(); + }); + }; + } else { + nextTickFn = function nextTickSetTimeout(fn) { + setTimeout(function() { + fn(); + }, 0); + }; + } + return nextTickFn; + } + function bindContext(fn, context) { + return fn.bind ? fn.bind(context) : function() { + fn.apply(context, [].slice.call(arguments, 0)); + }; + } + }(); + var highlight = function(doc) { + "use strict"; + var defaults = { + node: null, + pattern: null, + tagName: "strong", + className: null, + wordsOnly: false, + caseSensitive: false, + diacriticInsensitive: false + }; + var accented = { + A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Aa]", + B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Bb]", + C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Cc]", + D: "[DdĎďDŽ-džDZ-dzᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Dd]", + E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ee]", + F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ff-fflFf]", + G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Gg]", + H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Hh]", + I: "[IiÌ-Ïì-ïĨ-İIJijǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕fiffiIi]", + J: "[JjIJ-ĵLJ-njǰʲᴶⅉ⒥ⒿⓙⱼJj]", + K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Kk]", + L: "[LlĹ-ŀLJ-ljˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿flfflLl]", + M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Mm]", + N: "[NnÑñŃ-ʼnNJ-njǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Nn]", + O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Oo]", + P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Pp]", + Q: "[Qqℚ⒬Ⓠⓠ㏃Qq]", + R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Rr]", + S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜stSs]", + T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ſtstTt]", + U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Uu]", + V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Vv]", + W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ww]", + X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Xx]", + Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Yy]", + Z: "[ZzŹ-žDZ-dzᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Zz]" + }; + return function hightlight(o) { + var regex; + o = _.mixin({}, defaults, o); + if (!o.node || !o.pattern) { + return; + } + o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; + regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive); + traverse(o.node, hightlightTextNode); + function hightlightTextNode(textNode) { + var match, patternNode, wrapperNode; + if (match = regex.exec(textNode.data)) { + wrapperNode = doc.createElement(o.tagName); + o.className && (wrapperNode.className = o.className); + patternNode = textNode.splitText(match.index); + patternNode.splitText(match[0].length); + wrapperNode.appendChild(patternNode.cloneNode(true)); + textNode.parentNode.replaceChild(wrapperNode, patternNode); + } + return !!match; + } + function traverse(el, hightlightTextNode) { + var childNode, TEXT_NODE_TYPE = 3; + for (var i = 0; i < el.childNodes.length; i++) { + childNode = el.childNodes[i]; + if (childNode.nodeType === TEXT_NODE_TYPE) { + i += hightlightTextNode(childNode) ? 1 : 0; + } else { + traverse(childNode, hightlightTextNode); + } + } + } + }; + function accent_replacer(chr) { + return accented[chr.toUpperCase()] || chr; + } + function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) { + var escapedPatterns = [], regexStr; + for (var i = 0, len = patterns.length; i < len; i++) { + var escapedWord = _.escapeRegExChars(patterns[i]); + if (diacriticInsensitive) { + escapedWord = escapedWord.replace(/\S/g, accent_replacer); + } + escapedPatterns.push(escapedWord); + } + regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; + return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); + } + }(window.document); + var Input = function() { + "use strict"; + var specialKeyCodeMap; + specialKeyCodeMap = { + 9: "tab", + 27: "esc", + 37: "left", + 39: "right", + 13: "enter", + 38: "up", + 40: "down" + }; + function Input(o, www) { + var id; + o = o || {}; + if (!o.input) { + $.error("input is missing"); + } + www.mixin(this); + this.$hint = $(o.hint); + this.$input = $(o.input); + this.$menu = $(o.menu); + id = this.$input.attr("id") || _.guid(); + this.$menu.attr("id", id + "_listbox"); + this.$hint.attr({ + "aria-hidden": true + }); + this.$input.attr({ + "aria-owns": id + "_listbox", + "aria-controls": id + "_listbox", + role: "combobox", + "aria-autocomplete": "list", + "aria-expanded": false + }); + this.query = this.$input.val(); + this.queryWhenFocused = this.hasFocus() ? this.query : null; + this.$overflowHelper = buildOverflowHelper(this.$input); + this._checkLanguageDirection(); + if (this.$hint.length === 0) { + this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; + } + this.onSync("cursorchange", this._updateDescendent); + } + Input.normalizeQuery = function(str) { + return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + }; + _.mixin(Input.prototype, EventEmitter, { + _onBlur: function onBlur() { + this.resetInputValue(); + this.trigger("blurred"); + }, + _onFocus: function onFocus() { + this.queryWhenFocused = this.query; + this.trigger("focused"); + }, + _onKeydown: function onKeydown($e) { + var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; + this._managePreventDefault(keyName, $e); + if (keyName && this._shouldTrigger(keyName, $e)) { + this.trigger(keyName + "Keyed", $e); + } + }, + _onInput: function onInput() { + this._setQuery(this.getInputValue()); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + _managePreventDefault: function managePreventDefault(keyName, $e) { + var preventDefault; + switch (keyName) { + case "up": + case "down": + preventDefault = !withModifier($e); + break; + + default: + preventDefault = false; + } + preventDefault && $e.preventDefault(); + }, + _shouldTrigger: function shouldTrigger(keyName, $e) { + var trigger; + switch (keyName) { + case "tab": + trigger = !withModifier($e); + break; + + default: + trigger = true; + } + return trigger; + }, + _checkLanguageDirection: function checkLanguageDirection() { + var dir = (this.$input.css("direction") || "ltr").toLowerCase(); + if (this.dir !== dir) { + this.dir = dir; + this.$hint.attr("dir", dir); + this.trigger("langDirChanged", dir); + } + }, + _setQuery: function setQuery(val, silent) { + var areEquivalent, hasDifferentWhitespace; + areEquivalent = areQueriesEquivalent(val, this.query); + hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; + this.query = val; + if (!silent && !areEquivalent) { + this.trigger("queryChanged", this.query); + } else if (!silent && hasDifferentWhitespace) { + this.trigger("whitespaceChanged", this.query); + } + }, + _updateDescendent: function updateDescendent(event, id) { + this.$input.attr("aria-activedescendant", id); + }, + bind: function() { + var that = this, onBlur, onFocus, onKeydown, onInput; + onBlur = _.bind(this._onBlur, this); + onFocus = _.bind(this._onFocus, this); + onKeydown = _.bind(this._onKeydown, this); + onInput = _.bind(this._onInput, this); + this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); + if (!_.isMsie() || _.isMsie() > 9) { + this.$input.on("input.tt", onInput); + } else { + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { + if (specialKeyCodeMap[$e.which || $e.keyCode]) { + return; + } + _.defer(_.bind(that._onInput, that, $e)); + }); + } + return this; + }, + focus: function focus() { + this.$input.focus(); + }, + blur: function blur() { + this.$input.blur(); + }, + getLangDir: function getLangDir() { + return this.dir; + }, + getQuery: function getQuery() { + return this.query || ""; + }, + setQuery: function setQuery(val, silent) { + this.setInputValue(val); + this._setQuery(val, silent); + }, + hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { + return this.query !== this.queryWhenFocused; + }, + getInputValue: function getInputValue() { + return this.$input.val(); + }, + setInputValue: function setInputValue(value) { + this.$input.val(value); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + resetInputValue: function resetInputValue() { + this.setInputValue(this.query); + }, + getHint: function getHint() { + return this.$hint.val(); + }, + setHint: function setHint(value) { + this.$hint.val(value); + }, + clearHint: function clearHint() { + this.setHint(""); + }, + clearHintIfInvalid: function clearHintIfInvalid() { + var val, hint, valIsPrefixOfHint, isValid; + val = this.getInputValue(); + hint = this.getHint(); + valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; + isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); + !isValid && this.clearHint(); + }, + hasFocus: function hasFocus() { + return this.$input.is(":focus"); + }, + hasOverflow: function hasOverflow() { + var constraint = this.$input.width() - 2; + this.$overflowHelper.text(this.getInputValue()); + return this.$overflowHelper.width() >= constraint; + }, + isCursorAtEnd: function() { + var valueLength, selectionStart, range; + valueLength = this.$input.val().length; + selectionStart = this.$input[0].selectionStart; + if (_.isNumber(selectionStart)) { + return selectionStart === valueLength; + } else if (document.selection) { + range = document.selection.createRange(); + range.moveStart("character", -valueLength); + return valueLength === range.text.length; + } + return true; + }, + destroy: function destroy() { + this.$hint.off(".tt"); + this.$input.off(".tt"); + this.$overflowHelper.remove(); + this.$hint = this.$input = this.$overflowHelper = $("
"); + }, + setAriaExpanded: function setAriaExpanded(value) { + this.$input.attr("aria-expanded", value); + } + }); + return Input; + function buildOverflowHelper($input) { + return $('').css({ + position: "absolute", + visibility: "hidden", + whiteSpace: "pre", + fontFamily: $input.css("font-family"), + fontSize: $input.css("font-size"), + fontStyle: $input.css("font-style"), + fontVariant: $input.css("font-variant"), + fontWeight: $input.css("font-weight"), + wordSpacing: $input.css("word-spacing"), + letterSpacing: $input.css("letter-spacing"), + textIndent: $input.css("text-indent"), + textRendering: $input.css("text-rendering"), + textTransform: $input.css("text-transform") + }).insertAfter($input); + } + function areQueriesEquivalent(a, b) { + return Input.normalizeQuery(a) === Input.normalizeQuery(b); + } + function withModifier($e) { + return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; + } + }(); + var Dataset = function() { + "use strict"; + var keys, nameGenerator; + keys = { + dataset: "tt-selectable-dataset", + val: "tt-selectable-display", + obj: "tt-selectable-object" + }; + nameGenerator = _.getIdGenerator(); + function Dataset(o, www) { + o = o || {}; + o.templates = o.templates || {}; + o.templates.notFound = o.templates.notFound || o.templates.empty; + if (!o.source) { + $.error("missing source"); + } + if (!o.node) { + $.error("missing node"); + } + if (o.name && !isValidName(o.name)) { + $.error("invalid dataset name: " + o.name); + } + www.mixin(this); + this.highlight = !!o.highlight; + this.name = _.toStr(o.name || nameGenerator()); + this.limit = o.limit || 5; + this.displayFn = getDisplayFn(o.display || o.displayKey); + this.templates = getTemplates(o.templates, this.displayFn); + this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; + this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; + this._resetLastSuggestion(); + this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); + } + Dataset.extractData = function extractData(el) { + var $el = $(el); + if ($el.data(keys.obj)) { + return { + dataset: $el.data(keys.dataset) || "", + val: $el.data(keys.val) || "", + obj: $el.data(keys.obj) || null + }; + } + return null; + }; + _.mixin(Dataset.prototype, EventEmitter, { + _overwrite: function overwrite(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (this.async && this.templates.pending) { + this._renderPending(query); + } else if (!this.async && this.templates.notFound) { + this._renderNotFound(query); + } else { + this._empty(); + } + this.trigger("rendered", suggestions, false, this.name); + }, + _append: function append(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length && this.$lastSuggestion.length) { + this._appendSuggestions(query, suggestions); + } else if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (!this.$lastSuggestion.length && this.templates.notFound) { + this._renderNotFound(query); + } + this.trigger("rendered", suggestions, true, this.name); + }, + _renderSuggestions: function renderSuggestions(query, suggestions) { + var $fragment; + $fragment = this._getSuggestionsFragment(query, suggestions); + this.$lastSuggestion = $fragment.children().last(); + this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); + }, + _appendSuggestions: function appendSuggestions(query, suggestions) { + var $fragment, $lastSuggestion; + $fragment = this._getSuggestionsFragment(query, suggestions); + $lastSuggestion = $fragment.children().last(); + this.$lastSuggestion.after($fragment); + this.$lastSuggestion = $lastSuggestion; + }, + _renderPending: function renderPending(query) { + var template = this.templates.pending; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _renderNotFound: function renderNotFound(query) { + var template = this.templates.notFound; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _empty: function empty() { + this.$el.empty(); + this._resetLastSuggestion(); + }, + _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { + var that = this, fragment; + fragment = document.createDocumentFragment(); + _.each(suggestions, function getSuggestionNode(suggestion) { + var $el, context; + context = that._injectQuery(query, suggestion); + $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); + fragment.appendChild($el[0]); + }); + this.highlight && highlight({ + className: this.classes.highlight, + node: fragment, + pattern: query + }); + return $(fragment); + }, + _getFooter: function getFooter(query, suggestions) { + return this.templates.footer ? this.templates.footer({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _getHeader: function getHeader(query, suggestions) { + return this.templates.header ? this.templates.header({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _resetLastSuggestion: function resetLastSuggestion() { + this.$lastSuggestion = $(); + }, + _injectQuery: function injectQuery(query, obj) { + return _.isObject(obj) ? _.mixin({ + _query: query + }, obj) : obj; + }, + update: function update(query) { + var that = this, canceled = false, syncCalled = false, rendered = 0; + this.cancel(); + this.cancel = function cancel() { + canceled = true; + that.cancel = $.noop; + that.async && that.trigger("asyncCanceled", query, that.name); + }; + this.source(query, sync, async); + !syncCalled && sync([]); + function sync(suggestions) { + if (syncCalled) { + return; + } + syncCalled = true; + suggestions = (suggestions || []).slice(0, that.limit); + rendered = suggestions.length; + that._overwrite(query, suggestions); + if (rendered < that.limit && that.async) { + that.trigger("asyncRequested", query, that.name); + } + } + function async(suggestions) { + suggestions = suggestions || []; + if (!canceled && rendered < that.limit) { + that.cancel = $.noop; + var idx = Math.abs(rendered - that.limit); + rendered += idx; + that._append(query, suggestions.slice(0, idx)); + that.async && that.trigger("asyncReceived", query, that.name); + } + } + }, + cancel: $.noop, + clear: function clear() { + this._empty(); + this.cancel(); + this.trigger("cleared"); + }, + isEmpty: function isEmpty() { + return this.$el.is(":empty"); + }, + destroy: function destroy() { + this.$el = $("
"); + } + }); + return Dataset; + function getDisplayFn(display) { + display = display || _.stringify; + return _.isFunction(display) ? display : displayFn; + function displayFn(obj) { + return obj[display]; + } + } + function getTemplates(templates, displayFn) { + return { + notFound: templates.notFound && _.templatify(templates.notFound), + pending: templates.pending && _.templatify(templates.pending), + header: templates.header && _.templatify(templates.header), + footer: templates.footer && _.templatify(templates.footer), + suggestion: templates.suggestion ? userSuggestionTemplate : suggestionTemplate + }; + function userSuggestionTemplate(context) { + var template = templates.suggestion; + return $(template(context)).attr("id", _.guid()); + } + function suggestionTemplate(context) { + return $('
').attr("id", _.guid()).text(displayFn(context)); + } + } + function isValidName(str) { + return /^[_a-zA-Z0-9-]+$/.test(str); + } + }(); + var Menu = function() { + "use strict"; + function Menu(o, www) { + var that = this; + o = o || {}; + if (!o.node) { + $.error("node is required"); + } + www.mixin(this); + this.$node = $(o.node); + this.query = null; + this.datasets = _.map(o.datasets, initializeDataset); + function initializeDataset(oDataset) { + var node = that.$node.find(oDataset.node).first(); + oDataset.node = node.length ? node : $("
").appendTo(that.$node); + return new Dataset(oDataset, www); + } + } + _.mixin(Menu.prototype, EventEmitter, { + _onSelectableClick: function onSelectableClick($e) { + this.trigger("selectableClicked", $($e.currentTarget)); + }, + _onRendered: function onRendered(type, dataset, suggestions, async) { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetRendered", dataset, suggestions, async); + }, + _onCleared: function onCleared() { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetCleared"); + }, + _propagate: function propagate() { + this.trigger.apply(this, arguments); + }, + _allDatasetsEmpty: function allDatasetsEmpty() { + return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) { + var isEmpty = dataset.isEmpty(); + this.$node.attr("aria-expanded", !isEmpty); + return isEmpty; + }, this)); + }, + _getSelectables: function getSelectables() { + return this.$node.find(this.selectors.selectable); + }, + _removeCursor: function _removeCursor() { + var $selectable = this.getActiveSelectable(); + $selectable && $selectable.removeClass(this.classes.cursor); + }, + _ensureVisible: function ensureVisible($el) { + var elTop, elBottom, nodeScrollTop, nodeHeight; + elTop = $el.position().top; + elBottom = elTop + $el.outerHeight(true); + nodeScrollTop = this.$node.scrollTop(); + nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); + if (elTop < 0) { + this.$node.scrollTop(nodeScrollTop + elTop); + } else if (nodeHeight < elBottom) { + this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); + } + }, + bind: function() { + var that = this, onSelectableClick; + onSelectableClick = _.bind(this._onSelectableClick, this); + this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); + this.$node.on("mouseover", this.selectors.selectable, function() { + that.setCursor($(this)); + }); + this.$node.on("mouseleave", function() { + that._removeCursor(); + }); + _.each(this.datasets, function(dataset) { + dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); + }); + return this; + }, + isOpen: function isOpen() { + return this.$node.hasClass(this.classes.open); + }, + open: function open() { + this.$node.scrollTop(0); + this.$node.addClass(this.classes.open); + }, + close: function close() { + this.$node.attr("aria-expanded", false); + this.$node.removeClass(this.classes.open); + this._removeCursor(); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.attr("dir", dir); + }, + selectableRelativeToCursor: function selectableRelativeToCursor(delta) { + var $selectables, $oldCursor, oldIndex, newIndex; + $oldCursor = this.getActiveSelectable(); + $selectables = this._getSelectables(); + oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; + newIndex = oldIndex + delta; + newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; + newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; + return newIndex === -1 ? null : $selectables.eq(newIndex); + }, + setCursor: function setCursor($selectable) { + this._removeCursor(); + if ($selectable = $selectable && $selectable.first()) { + $selectable.addClass(this.classes.cursor); + this._ensureVisible($selectable); + } + }, + getSelectableData: function getSelectableData($el) { + return $el && $el.length ? Dataset.extractData($el) : null; + }, + getActiveSelectable: function getActiveSelectable() { + var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); + return $selectable.length ? $selectable : null; + }, + getTopSelectable: function getTopSelectable() { + var $selectable = this._getSelectables().first(); + return $selectable.length ? $selectable : null; + }, + update: function update(query) { + var isValidUpdate = query !== this.query; + if (isValidUpdate) { + this.query = query; + _.each(this.datasets, updateDataset); + } + return isValidUpdate; + function updateDataset(dataset) { + dataset.update(query); + } + }, + empty: function empty() { + _.each(this.datasets, clearDataset); + this.query = null; + this.$node.addClass(this.classes.empty); + function clearDataset(dataset) { + dataset.clear(); + } + }, + destroy: function destroy() { + this.$node.off(".tt"); + this.$node = $("
"); + _.each(this.datasets, destroyDataset); + function destroyDataset(dataset) { + dataset.destroy(); + } + } + }); + return Menu; + }(); + var Status = function() { + "use strict"; + function Status(options) { + this.$el = $("", { + role: "status", + "aria-live": "polite" + }).css({ + position: "absolute", + padding: "0", + border: "0", + height: "1px", + width: "1px", + "margin-bottom": "-1px", + "margin-right": "-1px", + overflow: "hidden", + clip: "rect(0 0 0 0)", + "white-space": "nowrap" + }); + options.$input.after(this.$el); + _.each(options.menu.datasets, _.bind(function(dataset) { + if (dataset.onSync) { + dataset.onSync("rendered", _.bind(this.update, this)); + dataset.onSync("cleared", _.bind(this.cleared, this)); + } + }, this)); + } + _.mixin(Status.prototype, { + update: function update(event, suggestions) { + var length = suggestions.length; + var words; + if (length === 1) { + words = { + result: "result", + is: "is" + }; + } else { + words = { + result: "results", + is: "are" + }; + } + this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate."); + }, + cleared: function() { + this.$el.text(""); + } + }); + return Status; + }(); + var DefaultMenu = function() { + "use strict"; + var s = Menu.prototype; + function DefaultMenu() { + Menu.apply(this, [].slice.call(arguments, 0)); + } + _.mixin(DefaultMenu.prototype, Menu.prototype, { + open: function open() { + !this._allDatasetsEmpty() && this._show(); + return s.open.apply(this, [].slice.call(arguments, 0)); + }, + close: function close() { + this._hide(); + return s.close.apply(this, [].slice.call(arguments, 0)); + }, + _onRendered: function onRendered() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onRendered.apply(this, [].slice.call(arguments, 0)); + }, + _onCleared: function onCleared() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onCleared.apply(this, [].slice.call(arguments, 0)); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); + return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); + }, + _hide: function hide() { + this.$node.hide(); + }, + _show: function show() { + this.$node.css("display", "block"); + } + }); + return DefaultMenu; + }(); + var Typeahead = function() { + "use strict"; + function Typeahead(o, www) { + var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; + o = o || {}; + if (!o.input) { + $.error("missing input"); + } + if (!o.menu) { + $.error("missing menu"); + } + if (!o.eventBus) { + $.error("missing event bus"); + } + www.mixin(this); + this.eventBus = o.eventBus; + this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; + this.input = o.input; + this.menu = o.menu; + this.enabled = true; + this.autoselect = !!o.autoselect; + this.active = false; + this.input.hasFocus() && this.activate(); + this.dir = this.input.getLangDir(); + this._hacks(); + this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); + onFocused = c(this, "activate", "open", "_onFocused"); + onBlurred = c(this, "deactivate", "_onBlurred"); + onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); + onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); + onEscKeyed = c(this, "isActive", "_onEscKeyed"); + onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); + onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); + onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); + onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); + onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); + onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); + this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); + } + _.mixin(Typeahead.prototype, { + _hacks: function hacks() { + var $input, $menu; + $input = this.input.$input || $("
"); + $menu = this.menu.$node || $("
"); + $input.on("blur.tt", function($e) { + var active, isActive, hasActive; + active = document.activeElement; + isActive = $menu.is(active); + hasActive = $menu.has(active).length > 0; + if (_.isMsie() && (isActive || hasActive)) { + $e.preventDefault(); + $e.stopImmediatePropagation(); + _.defer(function() { + $input.focus(); + }); + } + }); + $menu.on("mousedown.tt", function($e) { + $e.preventDefault(); + }); + }, + _onSelectableClicked: function onSelectableClicked(type, $el) { + this.select($el); + }, + _onDatasetCleared: function onDatasetCleared() { + this._updateHint(); + }, + _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) { + this._updateHint(); + if (this.autoselect) { + var cursorClass = this.selectors.cursor.substr(1); + this.menu.$node.find(this.selectors.suggestion).first().addClass(cursorClass); + } + this.eventBus.trigger("render", suggestions, async, dataset); + }, + _onAsyncRequested: function onAsyncRequested(type, dataset, query) { + this.eventBus.trigger("asyncrequest", query, dataset); + }, + _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { + this.eventBus.trigger("asynccancel", query, dataset); + }, + _onAsyncReceived: function onAsyncReceived(type, dataset, query) { + this.eventBus.trigger("asyncreceive", query, dataset); + }, + _onFocused: function onFocused() { + this._minLengthMet() && this.menu.update(this.input.getQuery()); + }, + _onBlurred: function onBlurred() { + if (this.input.hasQueryChangedSinceLastFocus()) { + this.eventBus.trigger("change", this.input.getQuery()); + } + }, + _onEnterKeyed: function onEnterKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + if (this.select($selectable)) { + $e.preventDefault(); + $e.stopPropagation(); + } + } else if (this.autoselect) { + if (this.select(this.menu.getTopSelectable())) { + $e.preventDefault(); + $e.stopPropagation(); + } + } + }, + _onTabKeyed: function onTabKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + this.select($selectable) && $e.preventDefault(); + } else if (this.autoselect) { + if ($selectable = this.menu.getTopSelectable()) { + this.autocomplete($selectable) && $e.preventDefault(); + } + } + }, + _onEscKeyed: function onEscKeyed() { + this.close(); + }, + _onUpKeyed: function onUpKeyed() { + this.moveCursor(-1); + }, + _onDownKeyed: function onDownKeyed() { + this.moveCursor(+1); + }, + _onLeftKeyed: function onLeftKeyed() { + if (this.dir === "rtl" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onRightKeyed: function onRightKeyed() { + if (this.dir === "ltr" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onQueryChanged: function onQueryChanged(e, query) { + this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); + }, + _onWhitespaceChanged: function onWhitespaceChanged() { + this._updateHint(); + }, + _onLangDirChanged: function onLangDirChanged(e, dir) { + if (this.dir !== dir) { + this.dir = dir; + this.menu.setLanguageDirection(dir); + } + }, + _openIfActive: function openIfActive() { + this.isActive() && this.open(); + }, + _minLengthMet: function minLengthMet(query) { + query = _.isString(query) ? query : this.input.getQuery() || ""; + return query.length >= this.minLength; + }, + _updateHint: function updateHint() { + var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; + $selectable = this.menu.getTopSelectable(); + data = this.menu.getSelectableData($selectable); + val = this.input.getInputValue(); + if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { + query = Input.normalizeQuery(val); + escapedQuery = _.escapeRegExChars(query); + frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); + match = frontMatchRegEx.exec(data.val); + match && this.input.setHint(val + match[1]); + } else { + this.input.clearHint(); + } + }, + isEnabled: function isEnabled() { + return this.enabled; + }, + enable: function enable() { + this.enabled = true; + }, + disable: function disable() { + this.enabled = false; + }, + isActive: function isActive() { + return this.active; + }, + activate: function activate() { + if (this.isActive()) { + return true; + } else if (!this.isEnabled() || this.eventBus.before("active")) { + return false; + } else { + this.active = true; + this.eventBus.trigger("active"); + return true; + } + }, + deactivate: function deactivate() { + if (!this.isActive()) { + return true; + } else if (this.eventBus.before("idle")) { + return false; + } else { + this.active = false; + this.close(); + this.eventBus.trigger("idle"); + return true; + } + }, + isOpen: function isOpen() { + return this.menu.isOpen(); + }, + open: function open() { + if (!this.isOpen() && !this.eventBus.before("open")) { + this.input.setAriaExpanded(true); + this.menu.open(); + this._updateHint(); + this.eventBus.trigger("open"); + } + return this.isOpen(); + }, + close: function close() { + if (this.isOpen() && !this.eventBus.before("close")) { + this.input.setAriaExpanded(false); + this.menu.close(); + this.input.clearHint(); + this.input.resetInputValue(); + this.eventBus.trigger("close"); + } + return !this.isOpen(); + }, + setVal: function setVal(val) { + this.input.setQuery(_.toStr(val)); + }, + getVal: function getVal() { + return this.input.getQuery(); + }, + select: function select($selectable) { + var data = this.menu.getSelectableData($selectable); + if (data && !this.eventBus.before("select", data.obj, data.dataset)) { + this.input.setQuery(data.val, true); + this.eventBus.trigger("select", data.obj, data.dataset); + this.close(); + return true; + } + return false; + }, + autocomplete: function autocomplete($selectable) { + var query, data, isValid; + query = this.input.getQuery(); + data = this.menu.getSelectableData($selectable); + isValid = data && query !== data.val; + if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) { + this.input.setQuery(data.val); + this.eventBus.trigger("autocomplete", data.obj, data.dataset); + return true; + } + return false; + }, + moveCursor: function moveCursor(delta) { + var query, $candidate, data, suggestion, datasetName, cancelMove, id; + query = this.input.getQuery(); + $candidate = this.menu.selectableRelativeToCursor(delta); + data = this.menu.getSelectableData($candidate); + suggestion = data ? data.obj : null; + datasetName = data ? data.dataset : null; + id = $candidate ? $candidate.attr("id") : null; + this.input.trigger("cursorchange", id); + cancelMove = this._minLengthMet() && this.menu.update(query); + if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) { + this.menu.setCursor($candidate); + if (data) { + if (typeof data.val === "string") { + this.input.setInputValue(data.val); + } + } else { + this.input.resetInputValue(); + this._updateHint(); + } + this.eventBus.trigger("cursorchange", suggestion, datasetName); + return true; + } + return false; + }, + destroy: function destroy() { + this.input.destroy(); + this.menu.destroy(); + } + }); + return Typeahead; + function c(ctx) { + var methods = [].slice.call(arguments, 1); + return function() { + var args = [].slice.call(arguments); + _.each(methods, function(method) { + return ctx[method].apply(ctx, args); + }); + }; + } + }(); + (function() { + "use strict"; + var old, keys, methods; + old = $.fn.typeahead; + keys = { + www: "tt-www", + attrs: "tt-attrs", + typeahead: "tt-typeahead" + }; + methods = { + initialize: function initialize(o, datasets) { + var www; + datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); + o = o || {}; + www = WWW(o.classNames); + return this.each(attach); + function attach() { + var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor; + _.each(datasets, function(d) { + d.highlight = !!o.highlight; + }); + $input = $(this); + $wrapper = $(www.html.wrapper); + $hint = $elOrNull(o.hint); + $menu = $elOrNull(o.menu); + defaultHint = o.hint !== false && !$hint; + defaultMenu = o.menu !== false && !$menu; + defaultHint && ($hint = buildHintFromInput($input, www)); + defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); + $hint && $hint.val(""); + $input = prepInput($input, www); + if (defaultHint || defaultMenu) { + $wrapper.css(www.css.wrapper); + $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); + $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); + } + MenuConstructor = defaultMenu ? DefaultMenu : Menu; + eventBus = new EventBus({ + el: $input + }); + input = new Input({ + hint: $hint, + input: $input, + menu: $menu + }, www); + menu = new MenuConstructor({ + node: $menu, + datasets: datasets + }, www); + status = new Status({ + $input: $input, + menu: menu + }); + typeahead = new Typeahead({ + input: input, + menu: menu, + eventBus: eventBus, + minLength: o.minLength, + autoselect: o.autoselect + }, www); + $input.data(keys.www, www); + $input.data(keys.typeahead, typeahead); + } + }, + isEnabled: function isEnabled() { + var enabled; + ttEach(this.first(), function(t) { + enabled = t.isEnabled(); + }); + return enabled; + }, + enable: function enable() { + ttEach(this, function(t) { + t.enable(); + }); + return this; + }, + disable: function disable() { + ttEach(this, function(t) { + t.disable(); + }); + return this; + }, + isActive: function isActive() { + var active; + ttEach(this.first(), function(t) { + active = t.isActive(); + }); + return active; + }, + activate: function activate() { + ttEach(this, function(t) { + t.activate(); + }); + return this; + }, + deactivate: function deactivate() { + ttEach(this, function(t) { + t.deactivate(); + }); + return this; + }, + isOpen: function isOpen() { + var open; + ttEach(this.first(), function(t) { + open = t.isOpen(); + }); + return open; + }, + open: function open() { + ttEach(this, function(t) { + t.open(); + }); + return this; + }, + close: function close() { + ttEach(this, function(t) { + t.close(); + }); + return this; + }, + select: function select(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.select($el); + }); + return success; + }, + autocomplete: function autocomplete(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.autocomplete($el); + }); + return success; + }, + moveCursor: function moveCursoe(delta) { + var success = false; + ttEach(this.first(), function(t) { + success = t.moveCursor(delta); + }); + return success; + }, + val: function val(newVal) { + var query; + if (!arguments.length) { + ttEach(this.first(), function(t) { + query = t.getVal(); + }); + return query; + } else { + ttEach(this, function(t) { + t.setVal(_.toStr(newVal)); + }); + return this; + } + }, + destroy: function destroy() { + ttEach(this, function(typeahead, $input) { + revert($input); + typeahead.destroy(); + }); + return this; + } + }; + $.fn.typeahead = function(method) { + if (methods[method]) { + return methods[method].apply(this, [].slice.call(arguments, 1)); + } else { + return methods.initialize.apply(this, arguments); + } + }; + $.fn.typeahead.noConflict = function noConflict() { + $.fn.typeahead = old; + return this; + }; + function ttEach($els, fn) { + $els.each(function() { + var $input = $(this), typeahead; + (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); + }); + } + function buildHintFromInput($input, www) { + return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop({ + readonly: true, + required: false + }).removeAttr("id name placeholder").removeClass("required").attr({ + spellcheck: "false", + tabindex: -1 + }); + } + function prepInput($input, www) { + $input.data(keys.attrs, { + dir: $input.attr("dir"), + autocomplete: $input.attr("autocomplete"), + spellcheck: $input.attr("spellcheck"), + style: $input.attr("style") + }); + $input.addClass(www.classes.input).attr({ + spellcheck: false + }); + try { + !$input.attr("dir") && $input.attr("dir", "auto"); + } catch (e) {} + return $input; + } + function getBackgroundStyles($el) { + return { + backgroundAttachment: $el.css("background-attachment"), + backgroundClip: $el.css("background-clip"), + backgroundColor: $el.css("background-color"), + backgroundImage: $el.css("background-image"), + backgroundOrigin: $el.css("background-origin"), + backgroundPosition: $el.css("background-position"), + backgroundRepeat: $el.css("background-repeat"), + backgroundSize: $el.css("background-size") + }; + } + function revert($input) { + var www, $wrapper; + www = $input.data(keys.www); + $wrapper = $input.parent().filter(www.selectors.wrapper); + _.each($input.data(keys.attrs), function(val, key) { + _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); + }); + $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); + if ($wrapper.length) { + $input.detach().insertAfter($wrapper); + $wrapper.remove(); + } + } + function $elOrNull(obj) { + var isValid, $el; + isValid = _.isJQuery(obj) || _.isElement(obj); + $el = isValid ? $(obj).first() : []; + return $el.length ? $el : null; + } + })(); +}); \ No newline at end of file diff --git a/search.json b/search.json new file mode 100644 index 0000000..09b8f88 --- /dev/null +++ b/search.json @@ -0,0 +1 @@ +{"Typealiases.html#/s:11CohesionKit17EntityEnumWrappera":{"name":"EntityEnumWrapper"},"Typealiases.html#/s:11CohesionKit11IdentityMapa":{"name":"IdentityMap"},"Typealiases.html#/s:11CohesionKit5Stampa":{"name":"Stamp","abstract":"

A type used to annotate track object modifications through time."},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__Gcs0D0Rd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an Identifiable keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcAA9AggregateRd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an Aggregate keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcs0D0Rd__lufc":{"name":"init(_:)","abstract":"

Creates an instance referencing an optional Identifiable keyPath

","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcAA9AggregateRd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcSMRd__s0D07ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcSMRd__s0D07ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__GcSMRd__AA9Aggregate7ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathVyACyxGs08WritableeF0Cyxqd__SgGcSMRd__AA9Aggregate7ElementRpd__SH5IndexRpd__lufc":{"name":"init(_:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathV7wrapperACyxGs08WritableeF0Cyxqd__G_tcAA13EntityWrapperRd__lufc":{"name":"init(wrapper:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/PartialIdentifiableKeyPath.html#/s:11CohesionKit26PartialIdentifiableKeyPathV7wrapperACyxGs08WritableeF0Cyxqd__SgG_tcAA13EntityWrapperRd__lufc":{"name":"init(wrapper:)","parent_name":"PartialIdentifiableKeyPath"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV8OnChangea":{"name":"OnChange","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV5valuexvp":{"name":"value","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV7observe8onChangeAA12SubscriptionCyxc_tF":{"name":"observe(onChange:)","parent_name":"EntityObserver"},"Structs/EntityObserver.html#/s:11CohesionKit14EntityObserverV11asPublisher7Combine03AnyF0Vyxs5NeverOGvp":{"name":"asPublisher","abstract":"

A Publisher emitting the observer current value and subscribing to any subsequents new values

","parent_name":"EntityObserver"},"Structs/AliasKey.html#/s:11CohesionKit8AliasKeyV5namedACyxGSS_tcfc":{"name":"init(named:)","parent_name":"AliasKey"},"Structs/AliasKey.html":{"name":"AliasKey","abstract":"

A value representing an Entity or set of Entity

"},"Structs/EntityObserver.html":{"name":"EntityObserver","abstract":"

A type registering observers on a given entity from identity storage

"},"Structs/PartialIdentifiableKeyPath.html":{"name":"PartialIdentifiableKeyPath","abstract":"

A KeyPath wrapper allowing only Identifiable/Aggregate keypaths

"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP8didStore_2idyqd__m_2IDQyd__ts12IdentifiableRd__lF":{"name":"didStore(_:id:)","abstract":"

Notify when an entity was stored in the identity map

","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP16didFailedToStore_2id5erroryqd__m_2IDQyd__s5Error_pts12IdentifiableRd__lF":{"name":"didFailedToStore(_:id:error:)","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP16didRegisterAliasyyAA0F3KeyVyqd__GlF":{"name":"didRegisterAlias(_:)","abstract":"

Notify an alias is registered with new entities

","parent_name":"Logger"},"Protocols/Logger.html#/s:11CohesionKit6LoggerP18didUnregisterAliasyyAA0F3KeyVyqd__GlF":{"name":"didUnregisterAlias(_:)","abstract":"

Notify an alias is suppressed from the identity map

","parent_name":"Logger"},"Protocols/EntityWrapper.html#/s:11CohesionKit13EntityWrapperP23wrappedEntitiesKeyPaths10relativeToSayAA019PartialIdentifiableG4PathVyqd__GGs08WritablegM0Cyqd__xG_tlF":{"name":"wrappedEntitiesKeyPaths(relativeTo:)","abstract":"

Entities contained by all cases relative to the parent container

","parent_name":"EntityWrapper"},"Protocols/Aggregate.html#/s:11CohesionKit9AggregateP22nestedEntitiesKeyPathsSayAA019PartialIdentifiableF4PathVyxGGvp":{"name":"nestedEntitiesKeyPaths","abstract":"

keypaths to nested models

","parent_name":"Aggregate"},"Protocols/Aggregate.html":{"name":"Aggregate","abstract":"

An Identifiable model containing nested models

"},"Protocols/EntityWrapper.html":{"name":"EntityWrapper","abstract":"

A type wrapping one or more Identifiable types."},"Protocols/Logger.html":{"name":"Logger","abstract":"

a protocol reporting EntityStore internal information

"},"Extensions/Date.html#/s:10Foundation4DateV11CohesionKitE5stampSdvp":{"name":"stamp","abstract":"

Generate a stamp suitable to use in EntityStore.","parent_name":"Date"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0Vy6OutputQz7FailureQzGAD11EntityStoreC_AD8AliasKeyVyALGSgSdts12IdentifiableALRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the Identifiable upstream into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0Vy6OutputQz7FailureQzGAD11EntityStoreC_AD8AliasKeyVyALGSgSdtAD9AggregateALRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the Aggregate upstream into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0VySay6Output_7ElementQZG7FailureQzGAD11EntityStoreC_AD8AliasKeyVyAKQzGSgSdtSlAVRQs12IdentifiableAMRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the upstream collection into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html#/s:7Combine9PublisherP11CohesionKitE5store2in5named10modifiedAtAA03AnyB0VySay6Output_7ElementQZG7FailureQzGAD11EntityStoreC_AD8AliasKeyVyAKQzGSgSdtSlAVRQAD9AggregateAMRQrlF":{"name":"store(in:named:modifiedAt:)","abstract":"

Stores the upstream collection into an entityStore

","parent_name":"Publisher"},"Extensions/Publisher.html":{"name":"Publisher"},"Extensions/Date.html":{"name":"Date"},"Extensions.html#/s:11CohesionKit14AliasContainerV":{"name":"AliasContainer"},"Extensions.html#/s:11CohesionKit10EntityNodeC":{"name":"EntityNode"},"Enums/StampError.html#/s:11CohesionKit10StampErrorO6tooOldyACSd_SdtcACmF":{"name":"tooOld(current:received:)","abstract":"

received stamp is smaller than current stamp

","parent_name":"StampError"},"Enums/StampError.html":{"name":"StampError"},"Classes/Subscription.html#/s:11CohesionKit12SubscriptionC11unsubscribeyycvp":{"name":"unsubscribe","parent_name":"Subscription"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6Updatea":{"name":"Update","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5queue6loggerACSo012OS_dispatch_E0CSg_AA6Logger_pSgtcfc":{"name":"init(queue:logger:)","abstract":"

Create a new EntityStore instance optionally with a queue and a logger

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store6entity5named10modifiedAt9ifPresentAA0C8ObserverVyxGx_AA8AliasKeyVyxGSgSdSgyxzcSgts12IdentifiableRzlF":{"name":"store(entity:named:modifiedAt:ifPresent:)","abstract":"

Store an entity in the storage. Entity will be stored only if stamp (modifiedAt) is higher than in previous","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store6entity5named10modifiedAt9ifPresentAA0C8ObserverVyxGx_AA8AliasKeyVyxGSgSdSgyxzcSgtAA9AggregateRzlF":{"name":"store(entity:named:modifiedAt:ifPresent:)","abstract":"

Store an aggregate in the storage. Each aggregate entities will be stored only if stamp (modifiedAt) is higher than in previous","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store8entities5named10modifiedAtAA0C8ObserverVySay7ElementQzGGx_AA8AliasKeyVyxGSgSdSgtSlRzs12IdentifiableAKRQlF":{"name":"store(entities:named:modifiedAt:)","abstract":"

Store multiple entities at once

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC5store8entities5named10modifiedAtAA0C8ObserverVySay7ElementQzGGx_AA8AliasKeyVyxGSgSdSgtSlRzAA9AggregateAKRQlF":{"name":"store(entities:named:modifiedAt:)","abstract":"

store multiple aggregates at once

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find_2idAA0C8ObserverVyxGSgxm_2IDQzts12IdentifiableRzlF":{"name":"find(_:id:)","abstract":"

Try to find an entity/aggregate in the storage.

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find5namedAA0C8ObserverVyxSgGAA8AliasKeyVyxG_ts12IdentifiableRzlF":{"name":"find(named:)","abstract":"

Try to find an entity/aggregate registered under named alias

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC4find5namedAA0C8ObserverVyxSgGAA8AliasKeyVyxG_tSlRzlF":{"name":"find(named:)","abstract":"

Try to find a collected registered under named alias

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update_2id10modifiedAtADSbxm_2IDQzSdSgyxzXEts12IdentifiableRzlF":{"name":"update(_:id:modifiedAt:update:)","abstract":"

Updates an already stored entity using a closure. Useful to update a few properties or when you assume the entity","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update_2id10modifiedAt_Sbxm_2IDQzSdSgyxzXEtAA9AggregateRzlF":{"name":"update(_:id:modifiedAt:_:)","abstract":"

Updates an already stored alias using a closure. This is useful if you don’t have a full entity for update","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEts12IdentifiableRzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already stored alias using a closure.","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtAA9AggregateRzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already stored alias using a closure.","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtSlRzs12Identifiable7ElementRpzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already existing collection alias content","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC6update5named10modifiedAtADSbAA8AliasKeyVyxG_SdSgyxzXEtSlRzAA9Aggregate7ElementRpzlF":{"name":"update(named:modifiedAt:update:)","abstract":"

Updates an already existing collection alias content","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC11removeAlias5namedyAA0F3KeyVyxG_tlF":{"name":"removeAlias(named:)","abstract":"

Removes an alias from the storage

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC11removeAlias5namedyAA0F3KeyVyxG_tSlRzlF":{"name":"removeAlias(named:)","abstract":"

Removes an alias from the storage

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC14removeAllAliasyyF":{"name":"removeAllAlias()","abstract":"

Removes all alias from identity map

","parent_name":"EntityStore"},"Classes/EntityStore.html#/s:11CohesionKit11EntityStoreC9removeAllyyF":{"name":"removeAll()","abstract":"

Removes all alias AND all objects stored weakly. You should not need this method and rather use removeAlias.","parent_name":"EntityStore"},"Classes/EntityStore.html":{"name":"EntityStore","abstract":"

Manages entities lifecycle and synchronisation

"},"Classes/Subscription.html":{"name":"Subscription"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Enums.html":{"name":"Enumerations","abstract":"

The following enumerations are available globally.

"},"Extensions.html":{"name":"Extensions","abstract":"

The following extensions are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"},"Typealiases.html":{"name":"Type Aliases","abstract":"

The following type aliases are available globally.

"}} \ No newline at end of file diff --git a/undocumented.json b/undocumented.json new file mode 100644 index 0000000..a27d575 --- /dev/null +++ b/undocumented.json @@ -0,0 +1,6 @@ +{ + "warnings": [ + + ], + "source_directory": "/Users/runner/work/CohesionKit/CohesionKit" +} \ No newline at end of file