Skip to content

Instantly share code, notes, and snippets.

@sherbondy
Created June 2, 2012 01:28
Show Gist options
  • Save sherbondy/2856072 to your computer and use it in GitHub Desktop.
Save sherbondy/2856072 to your computer and use it in GitHub Desktop.
externs for clojurescript
var FB = {};
FB.api = function(location, callback){};
FB.getLoginStatus = function(callback){};
FB.init = function(options){};
FB.login = function(callback, scope){};
FB.logout = function(callback){};
FB.Event = {};
FB.Event.subscribe = function(evt, callback){};
(ns sherbondy.client.main
(:require [noir.cljs.client.watcher :as watcher]
[goog.string :as gstr]
[goog.string.format :as gformat]
[clojure.string :as str]
[clojure.browser.repl :as repl]
[crate.core :as crate]
[fetch.remotes :as remotes])
(:require-macros [fetch.macros :as fm])
(:use [clojure.browser.dom :only [log log-obj]]
[jayq.core :only [$ add-class after append attr before bind document-ready
inner on prevent remove-class remove show slide-down
slide-up text toggle-class val]]
[jayq.util :only [clj->js]])
(:use-macros [crate.def-macros :only [defpartial]]))
;;************************************************
;; Dev stuff
;;************************************************
(watcher/init)
;;(repl/connect "http://localhost:9000/repl")
;;************************************************
;; Code
;;************************************************
(def FB (.-FB js/window))
(defn fb-subscribe [event-keyword response-fn]
(.subscribe (.-Event FB) (str event-keyword) response-fn))
(def $faces ($ :#faces))
(def $fb-info ($ :#fb-info))
(def $fb-login ($ :#fb-login))
(def $subdomain ($ :#subdomain))
(defpartial render-fb-info [user-data]
[:div
[:img.left {:src (gstr/format "http://graph.facebook.com/%d/picture"
(:id user-data))}]
[:h2.left "Hello, " [:em (:name user-data)]]
[:a#logout.right.big-button {:href "/logout"} "Logout"]])
(defpartial render-claim-button [user-data]
[:a#claim-button.big-button.hidden {:href "/claim"}
"Claim a subdomain!"])
(defpartial render-availability [reason]
[:span#availability {:class reason} reason])
(defn toggle-faces []
(toggle-class $fb-info "back")
(toggle-class $fb-login "back"))
(defn remove-claim []
; unclear why (remove $claim-button) does not work
(slide-up ($ :#claim-button)))
(defn login-response [response]
(if-let [resp (js->clj (.-authResponse response) :keywordize-keys true)]
(do
(fm/letrem [result (login resp)]
(if (= 0 (.-length ($ :#claim-button)))
(let [claim-button (render-claim-button result)]
(remove-claim)
(after $faces claim-button)))
(slide-down ($ :#claim-button)))
(.api FB "/me" (fn [data]
(let [clj-data (js->clj data :keywordize-keys true)]
(inner $fb-info (render-fb-info clj-data))
(toggle-faces)))))
(log "NO AUTH RESPONSE")))
(defn logout-response [response]
(fm/letrem [result (logout)]
(remove-claim)
(toggle-faces)))
(defn app-id []
(if (gstr/contains (.-URL js/document) "sherbondy.com")
"434878403190302"
"261968100569121"))
(defn fb-init []
(.init FB (clj->js
{:appId (app-id)
:status true
:cookie true
:xfbml true}))
(fb-subscribe :auth.login login-response)
(fb-subscribe :auth.logout logout-response)
(.getLoginStatus FB login-response))
(defn do-fb-logout [e]
(prevent e)
(.logout FB logout-response))
(defn do-fb-login [e]
(prevent e)
(.login FB login-response (clj->js {:scope "user_about_me,user_relationships,email"})))
(defn do-toggle-explanation [e]
(prevent e)
(toggle-class ($ :#explanation) "hidden"))
(defn do-domain-lookup [e]
(let [$availability ($ :#availability)
subdomain (gstr/trim (val $subdomain))]
(remove $availability)
(if (not (= subdomain ""))
(fm/letrem [result (check-availability subdomain)]
(let [output (condp = result true "available" false "taken" result)]
(append ($ :#subdomain-box) (render-availability output)))))))
(defn start-app
"Setup listeners for UI events."
[]
(document-ready
(do
(if FB (fb-init))
(bind $fb-login :click do-fb-login)
(on $fb-info :click :#logout nil do-fb-logout)
(bind $subdomain :blur do-domain-lookup)
(.focus $subdomain)
(on ($ :#explain) :click ($ :a) do-toggle-explanation)
(js/setTimeout #(slide-up ($ :.status-box)) 3000))))
(start-app)
(ns sherbondy.server
(:require [noir.server :as server]
[noir.session :as session]
[noir.cljs.core :as cljs]
[clj-facebook-graph.client :as client]
[clojure.string :as str])
(:use [sherbondy.models :only [create-user domain-taken? if-user]]
noir.fetch.remotes
[clj-facebook-graph.auth :only [with-facebook-auth]]))
(defn fb-auth-fn [token]
{:access-token token})
(defremote login [data]
(let [token (:accessToken data)]
(with-facebook-auth (fb-auth-fn token)
(let [me (client/get [:me] {:extract :body})]
(session/put! :access-token token)
(session/put! :name (:name me))
(session/put! :fb-id (:id me))
(if (= "sherbondy" (str/lower-case (:last_name me)))
(create-user me)
{:error "Sorry. Your last name must be Sherbondy."})))))
(defremote logout []
(session/clear!))
(defremote check-availability
"taken can either be a boolean or an error string
indicating that the domain is invalid"
[subdomain]
(if-user [user-id user]
(let [taken (domain-taken? user-id subdomain)]
(if (instance? Boolean taken)
(not taken)
taken))
"invalid"))
(server/load-views-ns 'sherbondy.views)
(def cljs-options {:advanced {:externs ["externs/facebook.js"]}})
(defn -main [& m]
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "5000"))]
(cljs/start mode cljs-options)
(server/start port {:mode mode
:ns 'sherbondy})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment