selector.ss
(module selector mzscheme
  
  (require (lib "contract.ss")
           (lib "cut.ss" "srfi" "26"))
  
  (require (file "base.ss")
           (file "core.ss"))

  ; Selectors ------------------------------------
  
  ;; node/document : -> javascript
  (define (node/document)
    (js:expr ((dot Delirium api findDocument))))
  
  ;; node/id : [javascript] (U string symbol) -> javascript
  (define node/id
    (case-lambda
      [(roots id) (js:expr ((dot Delirium api findById) #,roots ,id))]
      [(id)       (node/id (node/document) id)]))
  
  ;; node/tag : [javascript] (U string symbol) -> javascript
  (define node/tag
    (case-lambda
      [(roots tag) (js:expr ((dot Delirium api findByTag) #,roots ,tag))]
      [(tag)       (node/tag (node/document) tag)]))
  
  ;; node/xpath : [javascript] string -> jsarray
  (define node/xpath
    (case-lambda
      [(roots xpath) (js:expr ((dot Delirium api findByXpath) #,roots ,xpath))]
      [(xpath)       (node/xpath (node/document) xpath)]))
  
  ;; node/link/text : [javascript] string -> jsarray
  (define node/link/text
    (case-lambda
      [(roots text) (node/xpath roots (format "//a[contains(., '~a')]" text))]
      [(text)       (node/xpath (format "//a[contains(., '~a')]" text))]))

  ; Selector utilities ---------------------------
  
  ;; node-count : javascript -> integer
  (define (node-count selector)
    (respond/expr
     (lambda (embed-url)
       (js:expr (dot #,selector length)))))
  
  ;; node-exists? : javascript -> boolean
  (define (node-exists? selector)
    (not (zero? (node-count selector))))

  ;; check-found : selector -> void
  (define-check (check-found selector)
    (with-check-info (['selector (js (ignore #,selector))])
      (check-not-exn (cut check-true (node-exists? selector)))))
  
  ;; check-not-found : selector -> void
  (define-check (check-not-found selector)
    (with-check-info (['selector (js (ignore #,selector))])
      (check-not-exn (cut check-false (node-exists? selector)))))
  
  ; Provide statements ---------------------------
  
  ;; selector/c : [ contract ] -> contract
  (define (selector/c arg/c)
    (case-> (-> arg/c javascript-expression?)
            (-> javascript-expression? arg/c javascript-expression?)))
  
  (provide/contract
   ; Selectors and selector utilities:
   [node/document   (-> javascript-expression?)]
   [node/id         (selector/c (or/c string? symbol?))]
   [node/tag        (selector/c (or/c string? symbol?))]
   [node/xpath      (selector/c string?)]
   [node/link/text  (selector/c string?)]
   [node-count      (-> javascript-expression? integer?)]
   [node-exists?    (-> javascript-expression? boolean?)]
   [check-found     (case-> (-> javascript-expression? any)
                            (-> javascript-expression? string? any))]
   [check-not-found (case-> (-> javascript-expression? any)
                            (-> javascript-expression? string? any))])
  
  )