diff --git a/conf/localOverrides.conf.dist b/conf/localOverrides.conf.dist
index c1152042df..0fce400f38 100644
--- a/conf/localOverrides.conf.dist
+++ b/conf/localOverrides.conf.dist
@@ -330,5 +330,16 @@ $problemDefaults{max_attempts} = -1;
#$session_management_via = "session_cookie";
+################################################################################
+# Achievement Facebook Integration
+################################################################################
+
+## Because of the way facebook works, in order to use facebook integration
+## with webwork, you will need to create a facebook "app" specific to the
+## domain name of the server you are running. Once you have created the app
+## you can enable facebook integration by setting the variables below
+
+#$allowFacebooking = 1;
+#$facebookAppId = your_app_id_here;
1; #final line of the file to reassure perl that it was read properly.
diff --git a/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css b/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css
new file mode 100644
index 0000000000..36132ce019
--- /dev/null
+++ b/htdocs/js/lib/vendor/bootstrap/js/bootstrap.popover.css
@@ -0,0 +1,37 @@
+`/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
+.clearfix:after{clear:both;}
+.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
+.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
+.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
+.tooltip.top{margin-top:-3px;padding:5px 0;}
+.tooltip.right{margin-left:3px;padding:0 5px;}
+.tooltip.bottom{margin-top:3px;padding:5px 0;}
+.tooltip.left{margin-left:-3px;padding:0 5px;}
+.tooltip-inner{max-width:200px;padding:8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;}
+.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;}
+.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;}
+.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;}
+.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;}
+.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#ffffff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);white-space:normal;}.popover.top{margin-top:-10px;}
+.popover.right{margin-left:10px;}
+.popover.bottom{margin-top:10px;}
+.popover.left{margin-left:-10px;}
+.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}.popover-title:empty{display:none;}
+.popover-content{padding:9px 14px;}
+.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid;}
+.popover .arrow{border-width:11px;}
+.popover .arrow:after{border-width:10px;content:"";}
+.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0, 0, 0, 0.25);bottom:-11px;}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff;}
+.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0, 0, 0, 0.25);}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff;}
+.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0, 0, 0, 0.25);top:-11px;}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff;}
+.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0, 0, 0, 0.25);}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px;}
\ No newline at end of file
diff --git a/htdocs/themes/math4/math4.css b/htdocs/themes/math4/math4.css
index 0ede97b21f..e9817bfe6a 100644
--- a/htdocs/themes/math4/math4.css
+++ b/htdocs/themes/math4/math4.css
@@ -357,8 +357,10 @@ table.attemptResults {
border-width: 1px;
margin-bottom: 1em;
border-spacing: 1px;
+/* removed float stuff because none of the other elements nearby are
+ floated and it was causing trouble
float:left;
- clear:right;
+ clear:right; */
}
table.attemptResults td,
@@ -659,7 +661,6 @@ table caption{
#render-modal.modal {
width:1024px;
left:25%;
- top:40%;
}
#render-modal .modal-body {
@@ -802,12 +803,8 @@ table#grades_table pre{
width:60px;
}
-.tabberlive {
- margin-bottom:1ex;
-}
-
-.tabbertab {
- min-height:2em;
+.tab-pane {
+ margin-bottom:10px;
}
.small-table-text,
diff --git a/htdocs/themes/math4/math4.js b/htdocs/themes/math4/math4.js
index a969eea293..63824bc875 100644
--- a/htdocs/themes/math4/math4.js
+++ b/htdocs/themes/math4/math4.js
@@ -30,6 +30,7 @@ $(function(){
$('.viewOptions label:has(input:radio)').addClass('radio');
$('label.radio').nextUntil(':not(br)').remove();
$('.viewOptions input:submit').addClass('btn-small');
+ $('.facebookbox input:submit').addClass('btn-small');
//Reformats the problem_set_table.
$('#problem-sets-form').addClass('form-inline');
@@ -133,4 +134,15 @@ $(function(){
$('#mainform select[name=mydisplayMode]').addClass('input-small').removeClass('input-xxlarge');
$('#mainform select[name=max_shown]').addClass('input-small').removeClass('input-xxlarge');
+ //Change tabber tabs to twitter tabs
+ if ($('div.tabber').length > 0) {tabberAutomatic({});}
+ $('ul.tabbernav').removeClass('tabbernav').addClass('old-tabber nav nav-tabs');
+ $('ul.old-tabber li a').each(function () { $(this).attr('href','#'+$(this).attr('title')).attr('data-toggle','tab');});
+ $('div.tabberlive').removeClass('tabberlive').addClass('tab-content');
+ $('div.tabbertab').each(function() { $(this).removeClass('tabbertab').addClass('tab-pane').attr('id',$(this).find('h3').html())});
+ $('div.tab-pane h3').remove();
+ if ($('li.tabberactive a').length > 0) {
+ $('li.tabberactive a').tab('show');}
+
+
})
\ No newline at end of file
diff --git a/htdocs/themes/math4/system.template b/htdocs/themes/math4/system.template
index 258a078ad5..f94b44a93f 100644
--- a/htdocs/themes/math4/system.template
+++ b/htdocs/themes/math4/system.template
@@ -30,12 +30,14 @@
/images/favicon.ico"/>
/js/lib/vendor/bootstrap/css/bootstrap.css"/>
/themes/math4/math4.css"/>
-
+
/css/tabber.css"/>
@@ -44,6 +46,14 @@
+
+
+
+
+
@@ -122,6 +132,14 @@
+
+
+
+
+
+
+
+
@@ -129,12 +147,6 @@
-
-
-
-
-
-
diff --git a/lib/WeBWorK/AchievementEvaluator.pm b/lib/WeBWorK/AchievementEvaluator.pm
index 422a5623cc..f5c8fc00a6 100644
--- a/lib/WeBWorK/AchievementEvaluator.pm
+++ b/lib/WeBWorK/AchievementEvaluator.pm
@@ -169,11 +169,11 @@ sub checkForAchievements {
}
#build the cheevo message. New level messages are slightly different
- my $imgSrc;
+ my $imgSrc = $ce->{server_root_url};
if ($achievement->{icon}) {
- $imgSrc = $ce->{courseURLs}->{achievements}."/".$achievement->{icon};
+ $imgSrc .= $ce->{courseURLs}->{achievements}."/".$achievement->{icon};
} else {
- $imgSrc = $ce->{webworkURLs}->{htdocs}."/images/defaulticon.png";
+ $imgSrc .= $ce->{webworkURLs}->{htdocs}."/images/defaulticon.png";
}
$cheevoMessage .= CGI::start_div({class=>'cheevopopupouter'});
@@ -193,12 +193,12 @@ sub checkForAchievements {
}
#if facebook integration is enables then create a facebook popup
- if ($globalUserAchievement->facebooker) {
+ if ($ce->{allowFacebooking}&& $globalUserAchievement->facebooker) {
$cheevoMessage .= CGI::div({id=>'fb-root'},'');
$cheevoMessage .= CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},'');
$cheevoMessage .= CGI::start_script();
- #WCU specific appID
- $cheevoMessage .= "FB.init({appId:'193051384078348', cookie:true,status:true, xfbml:true });\n";
+
+ $cheevoMessage .= "FB.init({appId:'".$ce->{facebookAppId}."', cookie:true,status:true, xfbml:true });\n";
my $facebookmessage;
if ($achievement->category eq 'level') {
diff --git a/lib/WeBWorK/ContentGenerator/Achievements.pm b/lib/WeBWorK/ContentGenerator/Achievements.pm
index c61a355c1c..4bec2795c6 100644
--- a/lib/WeBWorK/ContentGenerator/Achievements.pm
+++ b/lib/WeBWorK/ContentGenerator/Achievements.pm
@@ -60,49 +60,57 @@ sub initialize {
}
-
-sub options {
- my ($self) = @_;
+ sub if_can {
+ my ($self, $arg) = @_;
my $r = $self->r;
my $db = $r->db;
my $ce = $r->ce;
my $authz = $r->authz;
my $globalUserAchievement = $self->{globalData};
- #Print the facebook sidepane. This allows users to turn facebook integration on and off.
+ if ($arg eq 'options' && (not $ce->{allowFacebooking} || not defined($globalUserAchievement))) {
+ return 0;
+ } else {
+ return $self->SUPER::if_can($arg);
+ }
+ }
- if (defined($globalUserAchievement)) {
-
- my $changeFacebooking = $r->param('changeFacebooking');
-
- if ($changeFacebooking) {
- $globalUserAchievement->facebooker(!$globalUserAchievement->facebooker);
- $db->putGlobalUserAchievement($globalUserAchievement);
- }
+sub options {
+ my ($self) = @_;
+ my $r = $self->r;
+ my $db = $r->db;
+ my $ce = $r->ce;
+ my $authz = $r->authz;
+ my $globalUserAchievement = $self->{globalData};
- print CGI::start_center();
+ my $changeFacebooking = $r->param('changeFacebooking');
+
+ if ($changeFacebooking) {
+ $globalUserAchievement->facebooker(!$globalUserAchievement->facebooker);
+ $db->putGlobalUserAchievement($globalUserAchievement);
+ }
+
+ print CGI::start_center();
+ print CGI::start_div({class=>'facebookbox'});
+ print CGI::start_form(-method=>'POST', -action=>$r->uri);
+ print $self->hidden_authen_fields;
+ print CGI::submit('changeFacebooking', $globalUserAchievement->facebooker
+ ? "Disable Facebook \n Integration" : "Enable Facebook \n Integration");
+ print CGI::end_form();
+ print CGI::end_div();
+
+ if ($globalUserAchievement->facebooker) {
+ #Print Facebook stuff (uses WCU specific appID)
print CGI::start_div({class=>'facebookbox'});
- print CGI::start_form(-method=>'POST', -action=>$r->uri);
- print $self->hidden_authen_fields;
- print CGI::submit('changeFacebooking', $globalUserAchievement->facebooker
- ? "Disable Facebook \n Integration" : "Enable Facebook \n Integration");
- print CGI::end_form();
+ print CGI::div({id=>'fb-root'},'');
+ print CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},"");
+ print CGI::script("FB.init({appId:'".$ce->{facebookAppId}."', cookie:true, status:true, xfbml:true });");
+ print "";
+ print "Login to FB";
+ print "";
print CGI::end_div();
-
- if ($globalUserAchievement->facebooker) {
- #Print Facebook stuff (uses WCU specific appID)
- print CGI::start_div({class=>'facebookbox'});
- print CGI::div({id=>'fb-root'},'');
- print CGI::script({src=>'http://connect.facebook.net/en_US/all.js'},"");
- print CGI::script("FB.init({appId:'193051384078348', cookie:true, status:true, xfbml:true });");
- print "";
- print "Login to FB";
- print "";
- print CGI::end_div();
- }
- print CGI::end_center();
}
-
+ print CGI::end_center();
return "";
}
diff --git a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm
index 2a03e07650..25ed1253d8 100644
--- a/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm
+++ b/lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm
@@ -245,8 +245,7 @@ sub body {
print CGI::p(CGI::b("Any changes made below will be reflected in the achievement for ALL students.")) if $editMode;
- print CGI::start_table({});
- print CGI::Tr({}, CGI::td({-colspan=>2}, "Select an action to perform:"));
+ print CGI::p($r->maketext("Select an action to perform").":");
my @formsToShow;
if ($editMode) {
@@ -259,6 +258,8 @@ sub body {
@formsToShow = @{ EXPORT_FORMS() };
}
+ print CGI::start_div({-class=>"tabber"});
+
my $i = 0;
foreach my $actionID (@formsToShow) {
@@ -266,10 +267,12 @@ sub body {
my $onChange = "document.achievementlist.action[$i].checked=true";
my %actionParams = $self->getActionParams($actionID);
- print CGI::Tr({-valign=>"top"},
- CGI::td({}, CGI::input({-type=>"radio", -name=>"action", -value=>$actionID})),
- CGI::td({}, $self->$actionForm($onChange, %actionParams))
- );
+ print CGI::div({-class=>"tabbertab"},
+ CGI::h3($r->maketext(ucfirst(WeBWorK::split_cap($actionID)))),
+ CGI::span({-class=>"radio_span"}, WeBWorK::CGI_labeled_input(-type=>"radio",
+ -id=>$actionID."_id", -label_text=>$r->maketext(ucfirst(WeBWorK::split_cap($actionID))),
+ -input_attr=>{-name=>"action", -value=>$actionID}, -label_attr=>{-class=>"radio_label"})),
+ $self->$actionForm($onChange, %actionParams));
$i++;
}
@@ -292,10 +295,11 @@ sub body {
)
);
}
- print CGI::Tr({}, CGI::td({-colspan=>2, -align=>"center"},
- CGI::submit(-value=>"Take Action!"))
- );
- print CGI::end_table();
+
+ print WeBWorK::CGI_labeled_input(-type=>"reset", -id=>"clear_entries", -input_attr=>{-value=>$r->maketext("Clear"), -class=>"button_input"});
+ print WeBWorK::CGI_labeled_input(-type=>"submit", -id=>"take_action", -input_attr=>{-value=>$r->maketext("Take Action!"), -class=>"button_input"}).CGI::br().CGI::br();
+
+ print CGI::end_div();
########## print table
@@ -1297,6 +1301,13 @@ sub output_JS{
my $site_url = $ce->{webworkURLs}->{htdocs};
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/addOnLoadEvent.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/show_hide.js"}), CGI::end_script();
+ print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/tabber.js"}), CGI::end_script();
+
+ return "";
+}
+
+# Just tells template to output the stylesheet for Tabber
+sub output_tabber_CSS{
return "";
}
diff --git a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm
index 76727894aa..c3c7895991 100644
--- a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm
+++ b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm
@@ -64,7 +64,7 @@ sub head {
print "";
- print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.7.2.min.js"}), CGI::end_script();
+ print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.8.1.min.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/bootstrap/js/bootstrap.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>$site_url.'/mathjax/MathJax.js?config=TeX-AMS_HTML-full'}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/apps/ProblemGrader/problemgrader.js"}), CGI::end_script();
@@ -181,8 +181,6 @@ sub body {
);
- my $tthPreambleCache;
-
return CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to acces the Instructor tools."))
unless $authz->hasPermissions($userID, "access_instructor_tools");
@@ -194,6 +192,7 @@ sub body {
my $set = $db->getMergedSet($userID, $setID); # checked
my $problem = $db->getMergedProblem($userID, $setID, $problemID); # checked
my $user = $db->getUser($userID);
+ return CGI::div({class=>"ResultsWithError"}, CGI::p("This set needs to be assigned to you before you can grade it.")) unless $set && $problem;
return CGI::div({class=>"ResultsWithError"}, CGI::p("This set needs to be assigned to you before you can grade it.")) unless $set && $problem;
@@ -268,6 +267,7 @@ sub body {
next unless $userProblem;
if ($userPastAnswerID && $userProblem) {
+
my $userPastAnswer = $db->getPastAnswer($userPastAnswerID);
my @scores = split(//,$userPastAnswer->scores);
my @answers = split(/\t/,$userPastAnswer->answer_string);
@@ -298,7 +298,7 @@ sub body {
local $ce->{pg}->{specialPGEnvironmentVars}->{problemPreamble}{HTML} = '';
local $ce->{pg}->{specialPGEnvironmentVars}->{problemPostamble}{HTML} = '';
- my $source = "DOCUMENT();\n loadMacros(\"PG.pl\",\"PGbasicmacros.pl\");\n BEGIN_TEXT\n";
+ my $source = "DOCUMENT();\n loadMacros(\"PG.pl\",\"PGbasicmacros.pl\",\"contextTypeset.pl\");\n Context(\"Typeset\");\n BEGIN_TEXT\n";
$source .= $answer . "\nEND_TEXT\n ENDDOCUMENT();";
my $pg = WeBWorK::PG->new(
$ce,
diff --git a/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm b/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm
index d4d6d69075..aa20e9e15d 100644
--- a/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm
+++ b/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm
@@ -2584,7 +2584,7 @@ sub output_JS{
my $ce = $r->ce;
my $site_url = $ce->{webworkURLs}->{htdocs};
- print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-1.7.1.min.js"}), CGI::end_script();
+ print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/lib/vendor/jquery-1.8.1.min.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-ui-1.8.18.custom.min.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/jquery-ui-timepicker-addon.js"}), CGI::end_script();
print CGI::start_script({type=>"text/javascript", src=>"$site_url/js/addOnLoadEvent.js"}), CGI::end_script();
diff --git a/lib/WeBWorK/DB.pm b/lib/WeBWorK/DB.pm
index 4660c494ff..fb3706373c 100644
--- a/lib/WeBWorK/DB.pm
+++ b/lib/WeBWorK/DB.pm
@@ -1355,6 +1355,12 @@ sub deleteGlobalUserAchievement {
# userAchievementID can be undefined if being called from this package
my $U = caller eq __PACKAGE__ ? "!" : "";
my ($self, $userID) = shift->checkArgs(\@_, "user_id$U");
+
+ my @achievements = $self->listUserAchievements($userID);
+ foreach my $achievement (@achievements) {
+ $self->deleteUserAchievement($userID,$achievement);
+ }
+
if ($self->{global_user_achievement}){
return $self->{global_user_achievement}->delete($userID);
} else {