Skip to content

Commit

Permalink
Merge branch 'release/1.5.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
amalloy committed Nov 17, 2011
2 parents f0e1c24 + 86bf236 commit 05bec4e
Show file tree
Hide file tree
Showing 13 changed files with 281 additions and 15 deletions.
2 changes: 1 addition & 1 deletion project.clj
@@ -1,4 +1,4 @@
(defproject foreclojure "1.5.2.3"
(defproject foreclojure "1.5.3"
:description "4clojure - a website for learning Clojure"
:dependencies [[clojure "1.2.1"]
[clojure-contrib "1.2.0"]
Expand Down
15 changes: 12 additions & 3 deletions resources/public/css/style.css
Expand Up @@ -199,9 +199,18 @@ img.gravatar{

#totalcount {
float: right;
padding: 8px;
font-size: 20px;
background-color: aliceblue;
padding: 8px 8px 2px 8px;
margin: 0 0 10px 5px;
font-size: 25px;
line-height: 35px;
background-color: #eee;
border: 1px solid #aaa;
color: #000;
font-weight: normal;
font-family: Helvetica, Arial, Sans-serif;
}
#totalcount p {
margin: 0 0;
}

#footer{
Expand Down
Binary file added resources/public/images/flipCounter-medium.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions resources/public/script/foreclojure.js
@@ -1,9 +1,14 @@
var updateProblemCountDelay = 4000; // milliseconds

$(document).ready(function() {

configureDataTables();
configureCodeBox();
configureGolf();

if($("#totalcount").length > 0)
configureCounter();

$("form#run-code button#approve-button").live("click", function(e) {
e.preventDefault();
if(confirm("Are you sure you want to mark this problem as approved?"))
Expand Down Expand Up @@ -305,3 +310,35 @@ function configureGolf(){
});

}

function configureCounter() {
$("#totalcounter").html("");
$("#totalcounter").flipCounter({
number:parseInt($('#counter-value').val()),
numFractionalDigits:0,
digitClass:"counter-digit",
digitHeight:40,
digitWidth:22.5,
imagePath:"/images/flipCounter-medium.png",
easing: jQuery.easing.easeOutCubic
});
setTimeout("updateProblemCount()", updateProblemCountDelay);
}

function updateProblemCount() {
var updateDuration = updateProblemCountDelay > 2500 ? 2500 : (updateProblemCountDelay - 500);

if($("#totalcount").length > 0) {
$.get("/problems/solved", function(data) {
if($("#totalcounter").flipCounter("getNumber") != data) {
$("#totalcounter").flipCounter("stopAnimation")
$("#totalcounter").flipCounter("startAnimation", {
number: parseInt(data),
duration: updateDuration,
easing: jQuery.easing.easeOutCubic
});
}
});
setTimeout("updateProblemCount()", updateProblemCountDelay);
}
}
205 changes: 205 additions & 0 deletions resources/public/vendor/script/jquery.easing.1.3.js
@@ -0,0 +1,205 @@
/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Uses the built in easing capabilities added In jQuery 1.1
* to offer multiple easing options
*
* TERMS OF USE - jQuery Easing
*
* Open source under the BSD License.
*
* Copyright © 2008 George McGinley Smith
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
def: 'easeOutQuad',
swing: function (x, t, b, c, d) {
//alert(jQuery.easing.default);
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
},
easeInQuad: function (x, t, b, c, d) {
return c*(t/=d)*t + b;
},
easeOutQuad: function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
easeInOutQuad: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
},
easeInCubic: function (x, t, b, c, d) {
return c*(t/=d)*t*t + b;
},
easeOutCubic: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t + 1) + b;
},
easeInOutCubic: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
},
easeInQuart: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t + b;
},
easeOutQuart: function (x, t, b, c, d) {
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
easeInOutQuart: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
easeInQuint: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t*t + b;
},
easeOutQuint: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t*t*t + 1) + b;
},
easeInOutQuint: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
},
easeInSine: function (x, t, b, c, d) {
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
},
easeOutSine: function (x, t, b, c, d) {
return c * Math.sin(t/d * (Math.PI/2)) + b;
},
easeInOutSine: function (x, t, b, c, d) {
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
},
easeInExpo: function (x, t, b, c, d) {
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
},
easeOutExpo: function (x, t, b, c, d) {
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
},
easeInOutExpo: function (x, t, b, c, d) {
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
},
easeInCirc: function (x, t, b, c, d) {
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
},
easeOutCirc: function (x, t, b, c, d) {
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
},
easeInOutCirc: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
},
easeInElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
easeOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
easeInOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
},
easeInBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*(t/=d)*t*((s+1)*t - s) + b;
},
easeOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
},
easeInOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
},
easeInBounce: function (x, t, b, c, d) {
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
},
easeOutBounce: function (x, t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
},
easeInOutBounce: function (x, t, b, c, d) {
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
}
});

/*
*
* TERMS OF USE - EASING EQUATIONS
*
* Open source under the BSD License.
*
* Copyright © 2001 Robert Penner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/foreclojure/mongo.clj
Expand Up @@ -31,6 +31,7 @@
(defn prepare-users []
(add-index! :users [:user] :unique true)
(add-index! :users [[:solved -1]])
(add-index! :users [:email])
(update! :users
{:user {:$in (:contributors config)}}
{:$set {:contributor true}}
Expand Down
5 changes: 4 additions & 1 deletion src/foreclojure/problems.clj
Expand Up @@ -574,9 +574,12 @@ Return a map, {:message, :error, :url, :num-tests-passed}."
(flash-msg "/problems" (str "Problem " id " was rejected and deleted.")))
(flash-error "/problems" "You do not have permission to access this page")))

(defn total-solved-count []
(html (:total @solved-stats)))

(defroutes problems-routes
(GET "/problems" [] (problem-list-page))
(GET "/problems/solved" [] (:total @solved-stats))
(GET "/problems/solved" [] (total-solved-count))
(GET "/problem/:id" [id]
(if-let [id-int (as-int id)]
(problem-page id-int)
Expand Down
8 changes: 5 additions & 3 deletions src/foreclojure/register.clj
Expand Up @@ -4,7 +4,7 @@
(:import [org.jasypt.util.password StrongPasswordEncryptor])
(:use [hiccup.form-helpers :only [form-to text-field password-field]]
[compojure.core :only [defroutes GET POST]]
[foreclojure.utils :only [form-row assuming flash-error]]
[foreclojure.utils :only [form-row assuming flash-error plausible-email?]]
[foreclojure.template :only [def-page]]
[somnium.congomongo :only [insert! fetch-one]]))

Expand Down Expand Up @@ -36,8 +36,10 @@
"Password must be at least seven characters long",
(= pwd repeat-pwd)
"Passwords don't match",
(not (empty? email))
"Please enter a valid email address"]
(plausible-email? email)
"Please enter a valid email address"
(nil? (fetch-one :users :where {:email email}))
"User with this email address already exists"]
(do
(insert! :users
{:user lower-user
Expand Down
10 changes: 6 additions & 4 deletions src/foreclojure/settings.clj
Expand Up @@ -3,7 +3,7 @@
[ring.util.response :as response])
(:import [org.jasypt.util.password StrongPasswordEncryptor])
(:use [hiccup.form-helpers :only [form-to label text-field password-field check-box]]
[foreclojure.utils :only [from-mongo flash-error flash-msg with-user form-row assuming send-email login-url]]
[foreclojure.utils :only [from-mongo flash-error flash-msg with-user form-row assuming send-email login-url plausible-email?]]
[foreclojure.template :only [def-page content-page]]
[foreclojure.users :only [disable-codebox? hide-solutions? gravatar-img]]
[compojure.core :only [defroutes GET POST]]
Expand Down Expand Up @@ -83,8 +83,10 @@
(or (empty? new-pwd)
(.checkPassword encryptor old-pwd pwd))
"Current password incorrect"
(not (empty? email))
"Please enter a valid email address"]
(plausible-email? email)
"Please enter a valid email address"
(nil? (fetch-one :users :where {:email email :user {:$ne user}}))
"User with this email address already exists"]
(do
(update! :users {:user user}
{:$set {:pwd (if (not-empty new-pwd) new-pwd-hash pwd) :user new-lower-user :email email
Expand All @@ -98,4 +100,4 @@
(defroutes settings-routes
(GET "/settings" [] (settings-page))
(POST "/settings" {{:strs [new-username old-pwd pwd repeat-pwd email disable-codebox hide-solutions]} :form-params}
(do-update-settings! new-username old-pwd pwd repeat-pwd email disable-codebox hide-solutions)))
(do-update-settings! new-username old-pwd pwd repeat-pwd email disable-codebox hide-solutions)))
7 changes: 5 additions & 2 deletions src/foreclojure/static.clj
Expand Up @@ -3,7 +3,8 @@
[foreclojure.problems :only [solved-stats]]
[foreclojure.config :only [repo-url]]
[foreclojure.ring-utils :only [static-url]]
[foreclojure.template :only [def-page]]))
[foreclojure.template :only [def-page]]
[hiccup.form-helpers :only [hidden-field]]))

(def df
(let [df (java.text.DecimalFormat.)
Expand All @@ -18,7 +19,9 @@
:content
[:div#welcome
[:div#totalcount
(.format df (:total @solved-stats)) " problems solved and counting!"]
(hidden-field :counter-value (:total @solved-stats))
[:p
[:span#totalcounter (.format df (:total @solved-stats))] " problems solved and counting!"]]
[:div
[:h3 "What is 4Clojure?"]
[:p "4Clojure is a resource to help fledgling clojurians learn the language through interactive problems. The first few problems are easy enough that even someone with no prior experience should find the learning curve forgiving. See 'Help' for more information."]]
Expand Down

0 comments on commit 05bec4e

Please sign in to comment.