Skip to content

Commit

Permalink
improves autocomplete-field
Browse files Browse the repository at this point in the history
documents it
adds example of it
makes throttle configurable
  • Loading branch information
slagyr committed Dec 18, 2013
1 parent 0d84256 commit 7eb0623
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 69 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,6 +5,7 @@
/js
/.idea
pom.xml
pom.xml.asc
*.jar
*.class
.lein-deps-sum
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
@@ -0,0 +1,4 @@
# 1.1.2

* autocomplete field - improved key event handling
* autocomplete field does not throttle by default. Throttling is configurable.
12 changes: 12 additions & 0 deletions example/.gitignore
@@ -0,0 +1,12 @@
/target
/lib
/classes
/checkouts
/js
pom.xml
*.jar
*.class
.lein-deps-sum
.lein-failures
.lein-plugins
.lein-repl-history
1 change: 1 addition & 0 deletions example/README.md
@@ -0,0 +1 @@
# example
20 changes: 20 additions & 0 deletions example/bin/specljs
@@ -0,0 +1,20 @@
#! /usr/bin/env phantomjs

var fs = require("fs");
var p = require('webpage').create();
var sys = require('system');

p.onConsoleMessage = function (x) {
fs.write("/dev/stdout", x, "w");
};

p.injectJs(phantom.args[0]);

var result = p.evaluate(function () {
specljs.run.standard.armed = true;
return specljs.run.standard.run_specs(
cljs.core.keyword("color"), true
);
});

phantom.exit(result);
30 changes: 30 additions & 0 deletions example/example.css
@@ -0,0 +1,30 @@
.autocomplete-dropdown {
background-color: white;
border: 1px solid #25a8e0;
border-top-width: 0;
margin: 1px 0 2px 0;
padding: 0;
position: absolute;
z-index: 2900;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0px 1px 5px rgba(64, 56, 41, 0.4);
-moz-box-shadow: 0px 1px 5px rgba(64, 56, 41, 0.4);
box-shadow: 0px 1px 5px rgba(64, 56, 41, 0.4);
}

.autocomplete-dropdown li {
list-style: none;
width: 100%;
padding-left: 10px;
}

.autocomplete-dropdown li:hover {
background-color: #ccc;
}

.autocomplete-dropdown .highlighted {
background-color: #25a8e0;
color: white;
}
16 changes: 16 additions & 0 deletions example/example.html
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>Filament Example</title>
<script src="js/example_dev.js" type="text/javascript"></script>
<link href="example.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Filament Examples</h1>

<script type="text/javascript">//<![CDATA[
example.main.init();
//]]></script>
</body>
</html>
27 changes: 27 additions & 0 deletions example/project.clj
@@ -0,0 +1,27 @@
(defproject example "1.0.0"
:description "Example App using com.8thlight/Filament"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}

:dependencies [[com.8thlight/filament "1.1.2"]
[com.8thlight/hiccup "1.1.1"]
[org.clojure/clojure "1.5.1"]]

:profiles {:dev {:dependencies [[org.clojure/clojurescript "0.0-2014"]
[speclj "2.9.1"]
[specljs "2.9.1"]]}}
:plugins [[speclj "2.9.1"]
[specljs "2.9.1"]
[lein-cljsbuild "1.0.0"]]

:cljsbuild ~(let [run-specs ["bin/specljs" "js/example_dev.js"]]
{:builds {:dev {:source-paths ["src/cljs" "spec/cljs"]
:compiler {:output-to "js/example_dev.js"
:optimizations :whitespace
:pretty-print true}
:notify-command run-specs}}

:test-commands {"test" run-specs}})

:source-paths ["src/clj" "src/cljs"]
:test-paths ["spec/clj"])
8 changes: 8 additions & 0 deletions example/spec/cljs/example/main_spec.cljs
@@ -0,0 +1,8 @@
(ns example.main-spec
(:require-macros [specljs.core :refer [describe it should=]])
(:require [specljs.core]
[example.main]))

(describe "A ClojureScript test"

)
32 changes: 32 additions & 0 deletions example/src/cljs/example/autocomplete_demo.cljs
@@ -0,0 +1,32 @@
(ns example.autocomplete-demo
(:require-macros [hiccup.core :as h])
(:require [clojure.string :as string]
[com.eighthlight.filament.autocomplete-field :as autocomplete]
[domina :as dom]
[hiccup.core]))

(def colors ["red"
"orange"
"yellow"
"green"
"blue"
"indigo"
"violet"])

(def dom [:form {:action "/fooey" :autocomplete "off"}
[:label {:for "autocomplete-field"} "Autocomplete:"]
[:input#autocomplete-field {:type "text"}]])

(defn autocomplete-on-select [[name value]]
(dom/set-value! (dom/by-id "autocomplete-field") value))

(defn autocomplete-on-search [q]
(autocomplete/show-dropdown (dom/by-id "autocomplete-field")
(map #(vector % %)
(filter #(re-find (re-pattern q) %) colors))))

(defn demo-autocomplete []
(dom/append! (.-body js/document) (h/html dom))
(let [field (dom/by-id "autocomplete-field")]
(autocomplete/arm-field field {:on-select autocomplete-on-select
:on-search autocomplete-on-search})))
5 changes: 5 additions & 0 deletions example/src/cljs/example/main.cljs
@@ -0,0 +1,5 @@
(ns example.main
(:require [example.autocomplete-demo :refer [demo-autocomplete]]))

(defn ^:export init []
(demo-autocomplete))
2 changes: 1 addition & 1 deletion project.clj
@@ -1,4 +1,4 @@
(defproject com.8thlight/filament "1.1.1"
(defproject com.8thlight/filament "1.1.2"
:description "Rich client utilities"
:url "http://github.com/8thlight/filament"
:license {:name "Eclipse Public License"
Expand Down
41 changes: 32 additions & 9 deletions spec/cljs/com/eighthlight/filament/autocomplete_field_spec.cljs
@@ -1,6 +1,6 @@
(ns com.eighthlight.filament.autocomplete-field-spec
(:require-macros [hiccups.core :as h]
[specljs.core :refer [describe context it should= should-contain with before around]])
[specljs.core :refer [describe context it should= should-contain with before around should-invoke should-not-invoke]])
(:require [com.eighthlight.filament.async :as async]
[com.eighthlight.filament.autocomplete-field :as ac]
[com.eighthlight.filament.fx :as fx]
Expand All @@ -18,28 +18,47 @@
(dom/set-html! (css/sel "body") (h/html [:input#testfield {:type "text" :name "testfield"}])))
(with input (dom/by-id "testfield"))
(with trail (atom []))
(around [it]
(with-redefs [async/handle-throttled-events event/listen!]
(it)))

(it "arms a text field with search behavior"
(ac/arm-field @input {:on-search #(swap! @trail conj :armed)})
(dom/set-value! @input "change")
(event/dispatch! @input :keyup {})
(should= [:armed] @@trail))
(should-not-invoke
async/handle-throttled-events {}
(ac/arm-field @input {:on-search #(swap! @trail conj :armed)})
(dom/set-value! @input "change")
(event/dispatch! @input :keyup {})
(should= [:armed] @@trail)))

(it "arms a text field with throttled search behavior"
(should-invoke
async/handle-throttled-events {:with [:* :* :* 500]}
(ac/arm-field @input {:throttle 500 :on-search #(swap! @trail conj :armed)})
(dom/set-value! @input "change")
(event/dispatch! @input :keyup {})))

(it "returns the value of the armed text field when searching"
(ac/arm-field @input {:on-search #(swap! @trail conj %)})
(dom/set-value! @input "Piper")
(event/dispatch! @input :keyup {})
(should= ["Piper"] @@trail))

(it "does invoke callback if text hasn't changed"
(it "DOESN'T invoke callback if text hasn't changed"
(dom/set-value! @input "Piper")
(ac/arm-field @input {:on-search #(swap! @trail conj %)})
(event/dispatch! @input :keyup {})
(should= [] @@trail))

(it "DOES invoke callback if text hasn't changed but arrow is pressed"
(dom/set-value! @input "Piper")
(ac/arm-field @input {:on-search #(swap! @trail conj %)})
(event/dispatch! @input :keyup {"keyCode" util/DOWN_ARROW})
(should= ["Piper"] @@trail))

(it "DOESN'T invoke callback if text hasn't changed, arrow is pressed, but dropdown is open"
(dom/set-value! @input "Piper")
(ac/arm-field @input {:on-search #(swap! @trail conj %)})
(ac/show-dropdown @input [])
(event/dispatch! @input :keyup {"keyCode" util/DOWN_ARROW})
(should= [] @@trail))

(context "Dropdown"

(with dropdown (ac/show-dropdown @input [["one" "1"] ["two" "2"] ["three" "3"]]))
Expand Down Expand Up @@ -87,6 +106,10 @@
(event/dispatch! @input :blur {})
(should= nil (ac/dropdown)))

(it "goes away on ECS pressed"
(event/dispatch! @input :keydown {"keyCode" util/ESC})
(should= nil (ac/dropdown)))

)
)

16 changes: 9 additions & 7 deletions src/cljs/com/eighthlight/filament/async.cljs
Expand Up @@ -36,11 +36,13 @@
(recur ::init last (pop cs))))))))
c))

(defn handle-throttled-events [element event-type handler]
(let [event-channel (:chan (event-chan element event-type))
throttled (throttle event-channel 1000)]
(go
(while true
(let [e (<! throttled)]
(handler e))))))
(defn handle-throttled-events
([element event-type handler] (handle-throttled-events element event-type handler 1000))
([element event-type handler msecs]
(let [event-channel (:chan (event-chan element event-type))
throttled (throttle event-channel msecs)]
(go
(while true
(let [e (<! throttled)]
(handler e)))))))

0 comments on commit 7eb0623

Please sign in to comment.