From 2bee266c8e9c0dcdb40d1a37c2f6f14a11ace141 Mon Sep 17 00:00:00 2001 From: pjechris Date: Sat, 10 Aug 2024 16:19:46 +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 -> 88143 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..df47f99 --- /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..758bbc8 --- /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..855b63d --- /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..1453b5f --- /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..7d66284 --- /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..a1b3100 --- /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..dfcd1ba --- /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..afb9f2f --- /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..7a020f6 --- /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..42dc816 --- /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..1676717 --- /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..5359466 --- /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..5688553 --- /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..4c3df2c --- /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..78d0029 --- /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..8d21fb2 --- /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..f378f7c --- /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..df47f99 --- /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..758bbc8 --- /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..855b63d --- /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..1453b5f --- /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..7d66284 --- /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..a1b3100 --- /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..dfcd1ba --- /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..afb9f2f --- /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..7a020f6 --- /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..42dc816 --- /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..1676717 --- /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..5359466 --- /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..5688553 --- /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..4c3df2c --- /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..78d0029 --- /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..8d21fb2 --- /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..f378f7c --- /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..1611ed6 --- /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..9dec278bedd9116c6976a279f20dcc09aa3ffdc8 GIT binary patch literal 88143 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 b1) 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..1611ed6 --- /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