');
+ var parentId = null;
+ if (isNested) {
+ // second tier, a part of optional sequence or
+ // branching
+ parentId = $('td', parent).attr('id');
+ // find last activity from sequence and put
+ // current one after it to keep ordering
+ row.insertAfter($('td[id^=' + parentId + ']',
+ container).last().parent());
+ isCurrent |= childActivity.status == 0;
+ } else {
+ parentId = container.attr('id');
+ row.appendTo(parent);
+ }
+
+ var cellId = parentId + 'child'
+ + childActivityIndex;
+ var cell = $('
').attr('id', cellId).appendTo(
+ row);
+ if (isNested) {
+ cell.hide();
+ }
+
+ // each row has its own paper
+ var paper = childActivity.bar.paper = Raphael(
+ cellId, 145, 23);
+ // draw the inner activity
+ childActivity.shape = paper
+ .path(childActivity.path);
+ childActivity.shape.attr(ActivityUtils
+ .getShapeAttributes(childActivity));
+ ActivityUtils.addDecoration(childActivity, null,
+ true);
+
+ var label = paper.text(35, childActivity.y + 11,
+ // add dash before name
+ (isNested ? '- ' : '') + childActivity.name)
+ // align to left
+ .attr('text-anchor', 'start');
+ // fix a bug in FF layout
+ $('tspan', label.node).attr('dy', 0);
+
+ var click = null;
+ if (!isNested) {
+ // only first tier inner activities
+ if (childActivityIndex == 0) {
+ click = function() {
+ // first row is the parent activity
+ // itself; hide content box when clicked
+ container.slideUp();
+ }
+ } else if (childActivity.childActivities) {
+ // show/hide 2nd tier inner activities
+ childActivity.toggleChildren = function(
+ forceCommand) {
+ if (cell.is(':visible')) {
+ var childCells = $('td[id^='
+ + cellId + 'child]', parent);
+ var isOpen = childCells
+ .is(':visible');
+ if (!forceCommand
+ || (isOpen ? forceCommand == 'close'
+ : forceCommand == 'open')) {
+ var containerHeightDelta = 27 * childCells.length;
+ childCells.toggle();
+ // resize inner content box
+ container.height(container.height()
+ + (isOpen ? -containerHeightDelta
+ : containerHeightDelta));
+ }
+ }
+ }
+
+ click = function() {
+ // show 2nd tier when 1st tier activity
+ // is clicked
+ childActivity.toggleChildren();
+ }
+ }
+ }
+ var dblclick = function() {
+ if (childActivity.url) {
+ if (childActivity.status == 1) {
+ openActivity(childActivity.url);
+ } else {
+ loadFrame(childActivity.url);
+ }
+ }
+ }
+ handleClicks(cell, click, dblclick);
+
+ if (childActivity.childActivities) {
+ isCurrent |= ActivityUtils
+ .addChildActivitiesRows(childActivity,
+ row, container, true);
+ if (isCurrent && childActivity.toggleChildren) {
+ childActivity.toggleChildren('open');
+ }
+ }
+ });
+
+ return isCurrent;
+ },
+
+ // replace single Branching activity with list of branch activities
+ expandBranch : function(bar, branchIndex, branchActivities) {
+ // hide any boxes obstructing the view
+ ActivityUtils.hideOtherComplexContent();
+
+ var activityShift = branchActivities.length - 1;
+ // how many pixels move subsequent activities down
+ var yShift = 60 * activityShift;
+ // activity just after branching
+ var afterBranchActivity = null;
+ // move down existing activities that come after Branching; start with
+ // the last one
+ var activities = bar.activities;
+ for ( var activityIndex = activities.length - 1; activityIndex > branchIndex; activityIndex--) {
+ afterBranchActivity = activities[activityIndex];
+ activities[activityIndex + activityShift] = afterBranchActivity;
+ afterBranchActivity.y += yShift;
+ afterBranchActivity.path = Raphael.transformPath(
+ afterBranchActivity.path, 'T0,' + yShift);
+ afterBranchActivity.elements.forEach(function(elem) {
+ var y = elem.attr('y');
+ var targetProperties = null;
+ // text, rectangles etc. have 'y', paths have 'path'
+ if (y) {
+ targetProperties = {
+ 'y' : elem.attr('y') + yShift
+ };
+ } else {
+ var path = elem.attr('path');
+ targetProperties = {
+ 'path' : Raphael.transformPath(path, 'T0,' + yShift)
+ };
+ }
+ elem.animate(targetProperties, 2000, "linear");
+ });
+ }
+
+ // smoothly remove Branching activity
+ activities[branchIndex].elements.forEach(function(elem) {
+ elem.animate({
+ 'opacity' : 0
+ }, 2000, "linear", function() {
+ elem.remove();
+ });
+ });
+
+ // create branch activities structures
+ for ( var activityIndex = 0; activityIndex < branchActivities.length; activityIndex++) {
+ var activityData = branchActivities[activityIndex];
+ var activity = new Activity(bar, activityIndex + branchIndex,
+ activityData.id, activityData.type, activityData.name,
+ activityData.status, activityData.url,
+ activityData.childActivities);
+ activities[activityIndex + branchIndex] = activity;
+ if (activity.status == 0) {
+ currentActivityIndex = activityIndex;
+ }
+ }
+
+ // smoothly draw branch activities
+ setTimeout(
+ function() {
+ for ( var activityIndex = 0; activityIndex < branchActivities.length; activityIndex++) {
+ ActivityUtils
+ .drawActivity(
+ activities[activityIndex + branchIndex],
+ false,
+ !afterBranchActivity
+ && activityIndex == branchActivities.length - 1);
+ }
+ }, 2000);
+ }
+}
+
+// main activities
+function Activity(bar, index, id, type, name, status, url, childActivitiesData) {
+ this.bar = bar;
+ this.index = index;
+ this.id = id;
+ this.type = type;
+ this.name = name;
+ this.status = status;
+ this.url = url;
+
+ // Optional Activities, Optional Sequences or Branching in preview mode
+ this.isComplex = type == 'o' || (isPreview && type == 'b');
+
+ if (isHorizontalBar) {
+ this.middle = 48 + 60 * index;
+ this.y = 10;
+ } else {
+ // X positioning
+ this.middle = 70;
+ // 20 is the first line segment and following activities take 60 px each
+ // (together with following vertical line)
+ this.y = 20 + 60 * index;
+ }
+
+ // first draw the inner shape, then put back the realY for background gray
+ // square
+ var finalY = this.y;
+ if (!isHorizontalBar && this.isComplex) {
+ this.y += 5;
+ }
+
+ if (type == 'g') {
+ // gate activity
+ if (isHorizontalBar) {
+ this.y -= 5;
+ }
+ ActivityUtils.shapeGateActivity(this);
+ } else {
+ ActivityUtils.shapeByStatus(this);
+ }
+
+ // special behaviour for complex activities
+ if (this.isComplex) {
+ this.y = finalY - (isHorizontalBar ? 5 : 0);
+ ActivityUtils.shapeComplexActivityContainer(this);
+
+ this.childActivities = [ new OptionalActivity(bar, name, status, url) ];
+ var childActivities = this.childActivities;
+ $.each(childActivitiesData, function(childActivityIndex,
+ childActivityData) {
+ childActivities[childActivityIndex + 1] = new OptionalActivity(bar,
+ childActivityData.name, childActivityData.status,
+ childActivityData.url, childActivityData.childActivities,
+ false);
+ });
+ }
+}
+
+// Support (floating) activities are show in separate box and behave differently
+function SupportActivity(bar, index, name, status, url) {
+ this.bar = bar;
+ this.name = name;
+ this.status = status;
+ this.url = url;
+
+ this.middle = 24;
+ this.y = 17 + 33 * index;
+
+ if (status <= 2) {
+ ActivityUtils.shapeAttemptedActivity(this);
+ } else if (status == 3) {
+ ActivityUtils.shapeToStartActivity(this);
+ }
+ this.statusTooltip = SUPPORT_ACTIVITY_LABEL;
+
+ this.transformToAttempted = function() {
+ var oldDecoration = this.decoration;
+ ActivityUtils.shapeAttemptedActivity(this);
+ this.statusTooltip = SUPPORT_ACTIVITY_LABEL;
+
+ ActivityUtils.animate(this, oldDecoration);
+ }
+}
+
+// Optional and Branching inner activities
+function OptionalActivity(bar, name, status, url, childActivitiesData, isNested) {
+ this.bar = bar;
+ this.name = name;
+ this.status = status;
+ this.url = url;
+
+ this.middle = isNested ? 22 : 15;
+ this.y = 5;
+
+ ActivityUtils.shapeByStatus(this);
+
+ // if Sequence or Branching, this is the 2nd tier of inner activities
+ if (childActivitiesData) {
+ this.childActivities = [];
+ var childActivities = this.childActivities;
+ $.each(childActivitiesData, function(childActivityIndex,
+ childActivityData) {
+ childActivities[childActivityIndex] = new OptionalActivity(bar,
+ childActivityData.name, childActivityData.status,
+ childActivityData.url, null, true);
+ });
+ }
+}
+
+// refresh progress bar on first/next activity load
+function fillProgressBar(barId) {
+ var bar = bars[barId];
+ if (!bar) {
+ // bar must be initialised first!
+ return false;
+ }
+
+ $.ajax({
+ url : LAMS_URL + 'monitoring/monitoring.do',
+ data : {
+ 'method' : 'getLearnerProgressJSON',
+ 'lessonID' : lessonId,
+ 'userID' : bar.userId
+ },
+ cache : false,
+ dataType : 'json',
+ success : function(result) {
+ // if nothing changed, don't do any calculations
+ if (!bar.currentActivityId
+ || result.currentActivityId != bar.currentActivityId) {
+ bar.currentActivityId = result.currentActivityId;
+ isPreview = result.isPreview;
+
+ var paper = bar.paper;
+ if (!paper) {
+ // create paper only the first time
+ paper = bar.paper = Raphael(bar.containerId,
+ isHorizontalBar ? 40 + 60 * result.activities.length : 140,
+ isHorizontalBar ? 60 : 60 * result.activities.length);
+ // first line on the top
+ paper.path(isHorizontalBar ? 'M 0 18 h 35'
+ : 'M 70 0 v 20');
+ }
+
+ // we need this to scroll to the current activity
+ var currentActivityIndex = 0;
+
+ for (var activityIndex = 0; activityIndex < result.activities.length; activityIndex++) {
+ var activityData = result.activities[activityIndex];
+ // prepare the Activity descriptor, but do not draw
+ // yet
+ var activity = new Activity(bar, activityIndex,
+ activityData.id, activityData.type,
+ activityData.name, activityData.status,
+ activityData.url,
+ activityData.childActivities);
+ if (activity.status == 0) {
+ currentActivityIndex = activityIndex;
+ }
+
+ var activities = bar.activities;
+ if (!activities) {
+ activities = bar.activities = [];
+ }
+
+ var existingActivity = activities[activityIndex];
+ if (existingActivity) {
+ // if in preview mode, always display all inner
+ // activities, i.e. never expand
+ if (!isPreview && existingActivity.type == 'b'
+ && existingActivity.id != activity.id) {
+
+ var branchActivityId = activityIndex;
+ var afterBranchActivityId = activityIndex + 1 < activities.length ? activities[activityIndex + 1].id
+ : null;
+ var branchActivities = [ activity ];
+ activityIndex++;
+
+ // find which activities are new (branch)
+ // and which ones already existed
+ while (activityIndex < result.activities.length) {
+ activityData = result.activities[activityIndex];
+ var activity = new Activity(bar,
+ activityIndex, activityData.id,
+ activityData.type,
+ activityData.name,
+ activityData.status,
+ activityData.url,
+ activityData.childActivities);
+ if (activity.id == afterBranchActivityId) {
+ // prepare for the next big loop
+ // iteration, which executes
+ // normally
+ activityIndex--;
+ break;
+ } else {
+ branchActivities.push(activity);
+ activityIndex++;
+ }
+ }
+
+ // resize main paper to accomodate new
+ // activities
+ paper.setSize(140, 60 * (activities.length
+ + branchActivities.length - 1));
+ ActivityUtils.expandBranch(bar,
+ branchActivityId, branchActivities);
+ } else {
+ // refresh existing bar, transform
+ // activities if needed
+ ActivityUtils.transform(existingActivity,
+ activity);
+ }
+ } else {
+ // draw new activity
+ ActivityUtils
+ .drawActivity(
+ activity,
+ true,
+ activityIndex == result.activities.length - 1);
+ }
+ }
+
+ // draw support activities if they exist
+ if (result.support
+ && !supportSeparatorRow.is(':visible')) {
+ supportSeparatorRow.show();
+ supportPart.height(17 + 33 * result.support.length)
+ .show();
+
+ // separate paper for Suppor Activities frame
+ var supportPaper = Raphael('supportPart');
+
+ $.each(result.support, function(activityIndex,
+ activityData) {
+ var activity = new SupportActivity(
+ supportPaper, activityIndex,
+ activityData.name, activityData.status,
+ activityData.url);
+ activity.shape = supportPaper
+ .path(activity.path);
+ activity.shape.attr(ActivityUtils
+ .getShapeAttributes(activity));
+ ActivityUtils.addDecoration(activity, null,
+ true);
+ ActivityUtils.addEffects(activity);
+ supportPaper.text(90, 24 + 33 * activityIndex,
+ activity.name);
+ });
+ }
+
+ resizeElements();
+ // scroll to the current activity
+ if (!isHorizontalBar) {
+ $('#' + bar.containerId).scrollTop(
+ Math.max((currentActivityIndex - 1) * 60,0)
+ );
+ }
+ }
+ }
+ });
+
+ return true;
+}
\ No newline at end of file
Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java
===================================================================
diff -u -r8634f7029afb87182dfccccd53fca4b82df4a04c -r9438790401b957cdd70a4d6ab2a76da70176c6eb
--- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java (.../LearnerAction.java) (revision 8634f7029afb87182dfccccd53fca4b82df4a04c)
+++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java (.../LearnerAction.java) (revision 9438790401b957cdd70a4d6ab2a76da70176c6eb)
@@ -26,7 +26,6 @@
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -36,11 +35,8 @@
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
-import org.apache.tomcat.util.json.JSONException;
-import org.apache.tomcat.util.json.JSONObject;
import org.lamsfoundation.lams.learning.service.ICoreLearnerService;
import org.lamsfoundation.lams.learning.service.LearnerServiceProxy;
-import org.lamsfoundation.lams.learning.web.bean.ActivityURL;
import org.lamsfoundation.lams.learning.web.util.ActivityMapping;
import org.lamsfoundation.lams.learning.web.util.LearningWebUtil;
import org.lamsfoundation.lams.learningdesign.Activity;
@@ -78,7 +74,7 @@
* @since 3/03/2005
* @version 1.1
*
- * ----------------XDoclet Tags--------------------
+ * ----------------XDoclet Tags--------------------
*
* @struts:action path="/learner" parameter="method" validate="false"
* @struts:action-forward name="displayActivity" path="/DisplayActivity.do"
@@ -134,15 +130,15 @@
*
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
*
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
*
@@ -195,15 +191,15 @@
*
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
*
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
*
@@ -263,15 +259,15 @@
* component.
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
*
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
*
@@ -365,15 +361,15 @@
*
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
*
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
@@ -385,8 +381,6 @@
LearnerAction.log.debug("Getting Flash progress data...");
}
-
-
FlashMessage message = null;
try {
@@ -402,20 +396,20 @@
message = new FlashMessage("getFlashProgressData", learnerProgress);
} catch (Exception e) {
- message = handleException(e, "getFlashProgressData", LearnerServiceProxy.getLearnerService(getServlet()
- .getServletContext()));
+ message = handleException(e, "getFlashProgressData",
+ LearnerServiceProxy.getLearnerService(getServlet().getServletContext()));
}
String wddxPacket = WDDXProcessor.serialize(message);
if (LearnerAction.log.isDebugEnabled()) {
LearnerAction.log.debug("Sending learner progress data to flash:" + wddxPacket);
}
- // LDEV-2835
+ // LDEV-2835
response.addHeader("Pragma", "no-cache");
- response.addHeader("Cache-Control", "no-cache");
- response.addDateHeader("Expires", System.currentTimeMillis() - LamsDispatchAction.HEADER_EXPIRES_VALUE);
+ response.addHeader("Cache-Control", "no-cache");
+ response.addDateHeader("Expires", System.currentTimeMillis() - LamsDispatchAction.HEADER_EXPIRES_VALUE);
- response.getWriter().print(wddxPacket);
+ response.getWriter().print(wddxPacket);
// don't need to return a action forward because it sent the wddx packet
// back already.
@@ -429,15 +423,15 @@
*
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
*
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
@@ -461,8 +455,8 @@
message = new FlashMessage("getLearnerActivityURL", activityDTO);
} catch (Exception e) {
- message = handleException(e, "getLearnerActivityURL", LearnerServiceProxy.getLearnerService(getServlet()
- .getServletContext()));
+ message = handleException(e, "getLearnerActivityURL",
+ LearnerServiceProxy.getLearnerService(getServlet().getServletContext()));
}
String wddxPacket = WDDXProcessor.serialize(message);
@@ -500,14 +494,14 @@
* Flash packet.
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
@@ -526,79 +520,19 @@
return mapping.findForward("displayProgress");
}
-
- @SuppressWarnings("unchecked")
- public ActionForward displayProgressJSON(ActionMapping mapping, ActionForm form, HttpServletRequest request,
- HttpServletResponse response) throws JSONException, IOException {
- Integer learnerId = LearningWebUtil.getUserId();
- Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID);
- ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext());
- Object[] ret = learnerService.getStructuredActivityURLs(learnerId, lessonId);
-
- JSONObject responseJSON = new JSONObject();
- responseJSON.put("currentActivityId", ret[1]);
- responseJSON.put("isPreview", ret[2]);
- for (ActivityURL activity : (List) ret[0]) {
- if (activity.getFloating()) {
- // these are support activities
- for (ActivityURL childActivity : activity.getChildActivities()) {
- responseJSON.append("support", activityToJSON(childActivity, null));
- }
- } else {
- responseJSON.append("activities", activityToJSON(activity, (Long) ret[1]));
- }
- }
-
- response.setContentType("application/json;charset=utf-8");
- response.getWriter().print(responseJSON.toString());
-
- return null;
- }
-
- private JSONObject activityToJSON(ActivityURL activity, Long currentActivityId) throws JSONException {
- JSONObject activityJSON = new JSONObject();
- activityJSON.put("id", activity.getActivityId());
- activityJSON.put("name", activity.getTitle());
- activityJSON.put("status", activity.getActivityId().equals(currentActivityId) ? 0 : activity.getStatus());
-
- if (activity.getUrl() != null) {
- activityJSON.put("url", activity.getUrl());
- }
-
- String actType = activity.getType().toLowerCase();
- String type = "a";
- if (actType.contains("gate")) {
- type = "g";
- } else if (actType.contains("options")) {
- type = "o";
- } else if (actType.contains("branching")) {
- type = "b";
- }
-
- activityJSON.put("type", type);
-
- if (activity.getChildActivities() != null) {
- for (ActivityURL childActivity : activity.getChildActivities()) {
- activityJSON.append("childActivities", activityToJSON(childActivity, currentActivityId));
- }
- }
-
- return activityJSON;
- }
-
/**
* Forces a move to a destination Activity in the learning sequence, returning a WDDX packet
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
@@ -638,14 +572,14 @@
* returning a WDDX packet.
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
@@ -744,14 +678,14 @@
* Flash packet.
*
* @param mapping
- * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to
- * send the end-user.
+ * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send
+ * the end-user.
* @param form
- * The ActionForm class that will contain any data submitted by the end-user via a form.
+ * The ActionForm class that will contain any data submitted by the end-user via a form.
* @param request
- * A standard Servlet HttpServletRequest class.
+ * A standard Servlet HttpServletRequest class.
* @param response
- * A standard Servlet HttpServletResponse class.
+ * A standard Servlet HttpServletResponse class.
* @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go
* next.
* @throws IOException
Index: lams_learning/web/css/main.css
===================================================================
diff -u -rc124a53ce3fc13192de91c935a2cc88a4a532cc9 -r9438790401b957cdd70a4d6ab2a76da70176c6eb
--- lams_learning/web/css/main.css (.../main.css) (revision c124a53ce3fc13192de91c935a2cc88a4a532cc9)
+++ lams_learning/web/css/main.css (.../main.css) (revision 9438790401b957cdd70a4d6ab2a76da70176c6eb)
@@ -55,7 +55,6 @@
div#progressBarDiv {
background-color: rgb(219,230,252);
- overflow: auto;
text-align: center;
}
@@ -122,41 +121,6 @@
padding: 0px 4px 4px 0px
}
-div#tooltip {
- display: none;
- position : absolute;
- border : 1px solid gray;
- background-color : rgb(246,238,191);
- padding : 3px;
- z-index: 5;
- width: 100px;
- font-size: 9px;
-}
-
-div.optionalActivity {
- display: none;
- position : absolute;
- left : 5px;
- border : 1px solid black;
- background-color : rgb(234,249,255);
- z-index: 6;
- width: 145px;
-}
-
-div.optionalActivity table tr:first-child td {
- border-top: none;
- background-color: rgb(197,212,251);
-}
-
-div.optionalActivity td {
- border-top: 1px solid black;
- cursor : pointer;
-}
-
-div.optionalActivity td:hover {
- background-color: rgb(246,238,191);
-}
-
.ui-layout-pane {
padding: 0px !important;
}
Index: lams_learning/web/includes/javascript/main.js
===================================================================
diff -u -rd1756abe2c97e06d69ce5069f4c973d21a7d1904 -r9438790401b957cdd70a4d6ab2a76da70176c6eb
--- lams_learning/web/includes/javascript/main.js (.../main.js) (revision d1756abe2c97e06d69ce5069f4c973d21a7d1904)
+++ lams_learning/web/includes/javascript/main.js (.../main.js) (revision 9438790401b957cdd70a4d6ab2a76da70176c6eb)
@@ -1,64 +1,12 @@
-// ------- GLOBAL VARIABLES ----------
+// ----- CONTROL FRAME & WINDOW MANIPULATION -----
-// colors used in shapes
-// dark red
-var COLOR_CURRENT_ACTIVITY = "rgb(187,0,0)";
-// dark blue
-var COLOR_COMPLETED_ACTIVITY = "rgb(0,0,153)";
-// green
-var COLOR_TOSTART_ACTIVITY = "rgb(0,153,0)";
-// black
-var COLOR_STROKE_ACTIVITY = "rgb(0,0,0)";
-// red
-var COLOR_GATE = "rgb(255,0,0)";
-// white
-var COLOR_GATE_TEXT = "rgb(255,255,255)";
-// gray
-var COLOR_COMPLEX_BACKGROUND = "rgb(153,153,153)";
-
-// SVG paths for activity shapes
-var PATH_SQUARE = " v16 h16 v-16 z";
-var PATH_BIG_SQUARE = " v26 h26 v-26 z";
-var PATH_CIRCLE = " m -8 0 a 8 8 0 1 0 16 0 a 8 8 0 1 0 -16 0";
-var PATH_QUARTER_CIRCLE = " a16 16 0 0 0 16 16 v-16 z";
-var PATH_TRIANGLE = " l8 16 l8 -16 z";
-var PATH_OCTAGON = " l-7 7 v12 l7 7 h12 l7 -7 v-12 l-7 -7 z";
-
-// other variables
-var paper = null;
-var controlFramePadding = null;
-var currentActivityId = null;
-var isPreview = false;
-var activities = [];
-
-// ----- CONTROL FRAME & WINDOW MANIPULATION -----
-
-// generic function for opening a pop up
-function openPopUp(args, title, h, w, status) {
- window.open(args, title, "HEIGHT=" + h + ",WIDTH=" + w
- + ",resizable=yes,scrollbars=yes,status="
- + status + ",menubar=no, toolbar=no");
-}
-
function exportPortfolio(){
openPopUp(APP_URL + "exportWaitingPage.jsp?mode=learner&lessonID=" + lessonId,
"ExportPortfolioLearner",
410,640,
"no");
}
-function openActivity(url) {
- openPopUp(url,
- "LearnerActivity",
- 600,800,
- "yes");
-}
-
-// loads a new activity to main content frame; alternative to opening in pop up
-function loadFrame(url) {
- $('#contentFrame').attr('src', url);
-}
-
function viewNotebookEntries(){
openPopUp(APP_URL + "notebook.do?method=viewAll&lessonID=" + lessonId,
"Notebook",
@@ -82,43 +30,6 @@
top.window.close();
}
-// adjusts elements after window resize
-function resizeElements() {
- var width = $(window).width() - 160;
- var height = $(window).height();
- // resize main content frame
- $('#contentFrame').css({
- 'width' : width + "px",
- 'height' : height + "px",
- 'position' : 'fixed'
- });
-
- if (progressPanelEnabled) {
- if (!controlFramePadding) {
- // calculate only once in the beginning
- // there will be miscalculations when trying to repeat this in the middle of resizing
- controlFramePadding = $('#controlFrame').outerHeight(true) - $('#controlFrame').height();
- }
-
- // calculate immutable chunks and what is left goes for progress bar
- var progressBarHeight = height - controlFramePadding;
- $('.progressStaticHeight').each(function(){
- var elem = $(this);
- // are notebook and/or support activities hidden?
- if (elem.is(':visible')) {
- progressBarHeight -= elem.outerHeight(true);
- }
- });
-
- $('#progressBarDiv').height(progressBarHeight);
- }
-
- if (presenceEnabled){
- // resize chat frame only if it exists
- resizeChat();
- }
-}
-
// open/close Notebook or Support Activity frames
function toggleBarPart(name) {
var part = $('#' + name + 'Part');
@@ -145,790 +56,4 @@
}
});
return formFilled;
-}
-
-// double click triggers also single click event, this method helps
-function handleClicks(elem, click, dblclick) {
- if (click) {
- elem.click(function(e) {
- setTimeout(function() {
- // if double clicked, just reduce the counter
- if (elem.clickcounter) {
- elem.clickcounter--;
- } else {
- // no double click, so execute
- click.call();
- }
- }, 300);
- });
- }
- if (dblclick) {
- elem.dblclick(function() {
- elem.clickcounter = 2;
- dblclick.call();
- });
- }
-}
-
-//------------- RAPHAEL --------------
-
-// This should be the super class for Activities, but it's hard to accomplish in JS
-// It is a set of common methods instead.
-var ActivityUtils = {
- // shape* methods are just preparing data, there is no actual drawing yet
- shapeByStatus : function(activity) {
- if (activity.status == 0) {
- ActivityUtils.shapeCurrentActivity(activity);
- } else if (activity.status == 1) {
- ActivityUtils.shapeCompletedActivity(activity);
- } else if (activity.status == 2) {
- ActivityUtils.shapeAttemptedActivity(activity);
- } else if (activity.status == 3) {
- ActivityUtils.shapeToStartActivity(activity);
- }
- },
-
- shapeCurrentActivity : function(activity) {
- // dark red square
- activity.path = "M" + (activity.middle - 8) + " " + activity.y + PATH_SQUARE;
- activity.fill = COLOR_CURRENT_ACTIVITY;
- activity.stroke = COLOR_STROKE_ACTIVITY;
- activity.statusTooltip = LABEL_CURRENT_ACTIVITY;
- },
-
- shapeCompletedActivity : function(activity) {
- // dark blue circle
- activity.path = "M" + activity.middle + " " + (activity.y + 8) + PATH_CIRCLE;
- activity.fill = COLOR_COMPLETED_ACTIVITY;
- activity.stroke = COLOR_STROKE_ACTIVITY;
- activity.statusTooltip = LABEL_COMPLETED_ACTIVITY;
- },
-
- shapeAttemptedActivity : function(activity) {
- // green square with dark red arc
- activity.path = "M" + (activity.middle - 8) + " " + activity.y + PATH_SQUARE;
- activity.fill = COLOR_TOSTART_ACTIVITY;
- activity.stroke = COLOR_STROKE_ACTIVITY;
- activity.statusTooltip = LABEL_ATTEMPTED_ACTIVITY;
-
- // this and similar methods are run when activity shape is drawn for real
- activity.addDecoration = function(act) {
- act.decoration = act.paper.set();
- // get exact Y where inner shape was drawn
- // it is different than activity.y in OptionalActivity
- // because of gray square around it
- var y = act.shape.attr('path')[0][2];
- var arc = act.paper.path("M" + (act.middle - 8) + " " + y + PATH_QUARTER_CIRCLE);
- arc.attr({
- 'fill' : COLOR_CURRENT_ACTIVITY,
- 'opacity' : 0,
- 'cursor' : 'pointer'
- });
- act.decoration.push(arc);
- }
- },
-
- shapeToStartActivity : function(activity) {
- // green triangle
- activity.path = "M" + (activity.middle - 8) + " " + activity.y + PATH_TRIANGLE;
- activity.fill = COLOR_TOSTART_ACTIVITY;
- activity.stroke = COLOR_STROKE_ACTIVITY;
- activity.statusTooltip = LABEL_TOSTART_ACTIVITY;
- },
-
- shapeGateActivity : function(activity) {
- // red octagon for STOP road sign
- activity.path = "M" + (activity.middle - 6) + " " + activity.y + PATH_OCTAGON;
- activity.fill = COLOR_GATE;
-
- activity.addDecoration = function(act) {
- act.decoration = activity.paper.set();
-
- // should be internationalised?
- var text = act.paper.text(act.middle, act.y + 13, "STOP");
- text.attr({
- 'opacity' : 0,
- 'font-size' : 9,
- 'font' : 'sans-serif',
- 'stroke' : COLOR_GATE_TEXT,
- 'cursor' : 'pointer'
- });
- act.decoration.push(text);
-
- if (act.status == 0) {
- // add dark red edge when current activity
- act.statusTooltip = LABEL_CURRENT_ACTIVITY;
-
- var edge = act.paper.path(act.path);
- edge.attr({
- 'opacity' : 0,
- 'stroke' : COLOR_CURRENT_ACTIVITY,
- 'stroke-width' : 3,
- 'cursor' : 'pointer'
- });
- act.decoration.push(edge);
- } else {
- act.statusTooltip = LABEL_TOSTART_ACTIVITY;
- }
- }
- },
-
- shapeComplexActivityContainer : function(activity) {
- var addDecoration = activity.addDecoration;
- activity.addDecoration = function(act) {
- // run previous addDecoration(), for example defined in Attempted Activity
- if (addDecoration) {
- addDecoration(act);
- }
-
- // gray square in background
- var square = act.paper.path("M" + (act.middle - 13) + " " + act.y + PATH_BIG_SQUARE);
- square.attr({
- 'opacity' : 0,
- 'fill' : COLOR_COMPLEX_BACKGROUND,
- 'cursor' : 'pointer'
- });
-
- // inform that it goes behind, not to front like other decoration
- act.decorationWraps = true;
- square.decorationWraps = true;
-
- if (!act.decoration) {
- act.decoration = act.paper.set();
- }
- act.decoration.push(square);
- }
- },
-
- // return some attributes in Raphael consumable way
- getShapeAttributes : function(activity) {
- return {
- 'path' : activity.path,
- 'fill' : activity.fill,
- 'stroke' : activity.stroke,
- 'cursor' : 'pointer'
- }
- },
-
- // does the actual drawing, based on info in Activity object
- drawActivity : function(activity, quick, isLast) {
- activities[activity.index] = activity;
- // all elements that activity consists of, so they all can be moved at once
- activity.elements = activity.paper.set();
- // only now do the read drawing, add event handlers etc.
- activity.shape = activity.paper.path(activity.path);
- // add Activity attributes
- activity.shape.attr(ActivityUtils.getShapeAttributes(activity));
- activity.elements.push(activity.shape);
- // label underneath the shape
- var label = paper.text(activity.middle, 43 + 60 * (activity.index - 1) + activity.height,
- activity.name);
- activity.elements.push(label);
- if (!isLast) {
- // line between activities; last activity does not have it
- var line = paper.path("M " + activity.middle + " " + (50 + 60 * (activity.index - 1) + activity.height)
- + " v" + (90 - activity.height));
- activity.elements.push(line);
- }
-
- if (!quick) {
- // slowly show the activity
- activity.elements.forEach(function(elem) {
- // hide first
- elem.attr('opacity', 0);
- // show in 1 second
- elem.animate({'opacity' : 1}, 1000, "linear");
- });
- }
-
- // add additional elements
- ActivityUtils.addDecoration(activity, null, quick);
- // add hover, click etc. handlers
- ActivityUtils.addEffects(activity);
- },
-
-
- // adds handlers to activity for mouse interactions
- // long method with simple actions
- addEffects : function(activity) {
- // remove any existing handlers
- ActivityUtils.removeHover(activity.shape);
- if (activity.shape.events) {
- while (activity.shape.events.length){
- // iterate over any handlers bound
- activity.shape.events.pop().unbind();
- }
- }
-
- var mouseover = function(e, x, y) {
- // add glowing effect on hover
- if (activity.decorationWraps) {
- activity.decoration.forEach(function(elem){
- // check which decoration element should glow
- if (elem.decorationWraps) {
- // glow the wrapping decoration element
- // for example gray square in Optonal Activity container
- // is bigger than inner activity shape, so it should glow
- activity.shape.glowRef = elem.glow({
- color : elem.attr('fill')
- });
- return false;
- }
- });
- } else {
- activity.shape.glowRef = activity.shape.glow({
- color : activity.shape.attr('fill')
- });
- }
-
- // add tooltip
- var tooltipText = '' + activity.name + ' ' + activity.statusTooltip;
- // move to proper place and show
- tooltipDiv.stop(true, true).css("left", 30).css("top", y + 20)
- .html(tooltipText)
- .delay(1000).fadeIn();
- }
-
- var mouseout = function() {
- // remove glow
- ActivityUtils.removeHover(activity.shape);
- }
-
- var isSupportActivity = activity instanceof SupportActivity;
- var dblclick = activity.url ? function(){
- // open pop up if it is a support or completed activity
- if (isSupportActivity || activity.status == 1) {
- openActivity(activity.url);
-
- if (isSupportActivity) {
- // do not ask server, just mark the activity as attempted
- activity.transformToAttempted();
- }
- } else {
- loadFrame(activity.url);
- }
- } : null;
-
-
- var click = activity.isComplex ? function() {
- // show complex (Optional, Branching) activity inner content
- ActivityUtils.showComplexContent(activity);
- } : null;
-
- // assign handlers
- activity.shape.hover(mouseover, mouseout);
- handleClicks(activity.shape, click, dblclick);
- if (activity.decoration) {
- // add handlers not only to shape, but also to all decoration elements
- activity.decoration.forEach(function(elem){
- elem.hover(mouseover, mouseout);
- handleClicks(elem, click, dblclick);
- });
- }
- },
-
- // remove glow when mouse leaves shape
- removeHover : function(shape){
- if (shape.glowRef) {
- shape.glowRef.remove();
- shape.glowRef = null;
- }
- tooltipDiv.stop(true, true).fadeOut();
- },
-
- // copy important properties and morph visible elements
- transform : function(sourceActivity, targetActivity) {
- var gotCompleted = false;
-
- // modify only if anything changed
- if (sourceActivity.status != targetActivity.status) {
- // was just completed
- gotCompleted = targetActivity.status == 1;
-
- sourceActivity.height = targetActivity.height;
- sourceActivity.path = targetActivity.path;
- sourceActivity.fill = targetActivity.fill;
- sourceActivity.stroke = targetActivity.stroke;
- sourceActivity.url = targetActivity.url;
- sourceActivity.status = targetActivity.status;
- sourceActivity.statusTooltip = targetActivity.statusTooltip;
- sourceActivity.addDecoration = targetActivity.addDecoration;
-
- // transform current shape to the new one
- ActivityUtils.animate(sourceActivity, sourceActivity.decoration);
- }
-
- var isCurrent = targetActivity.status == 0;
- if (sourceActivity.childActivities) {
- // run for all inner activities (Optional, Branching)
- $.each(sourceActivity.childActivities, function(childActivityIndex, childActivity){
- var targetChildActivity = targetActivity.childActivities[childActivityIndex];
- // if child activity is current, parent activity is current as well
- isCurrent |= targetChildActivity.status == 0;
- ActivityUtils.transform(childActivity, targetChildActivity);
- });
- }
-
- if (isCurrent) {
- // shows box with inner activities, if not open yet
- ActivityUtils.showComplexContent(sourceActivity);
- if (sourceActivity.toggleChildren) {
- // complex sequence just became current, show it
- sourceActivity.toggleChildren('open');
- }
- // close box with inner activities, if finished
- } else if (gotCompleted) {
- if (sourceActivity.isComplex) {
- ActivityUtils.hideOtherComplexContent();
- } else if (sourceActivity.toggleChildren) {
- sourceActivity.toggleChildren('close');
- }
- }
- },
-
- animate : function(activity, oldDecoration){
- if (activity.shape) {
- // remove old decoration and start showin new one
- ActivityUtils.addDecoration(activity, oldDecoration, false);
- // transform the shape
- activity.shape.animate(ActivityUtils.getShapeAttributes(activity), 2000, "linear", function() {
- if(!(activity instanceof OptionalActivity)){
- // inner activities do not have glow and tooltip effects
- ActivityUtils.addEffects(activity);
- }
- });
- }
- },
-
- // adds additional elements to activity basic shape
- // quick is for inital drawing, no nice effect is needed
- addDecoration : function(activity, oldDecoration, quick){
- if (oldDecoration) {
- // hide existing decoration
- oldDecoration.forEach(function(elem){
- if (activity.elements) {
- activity.elements.exclude(elem);
- }
- elem.animate({'opacity' : 0}, quick ? 0 : 1000, "linear", function(){
- elem.remove();
- });
- });
- }
-
- // run function that draws decoration
- if (activity.addDecoration) {
- var animation = Raphael.animation({'opacity' : 1}, quick ? 0 : 1000, "linear");
-
- activity.addDecoration(activity);
- activity.decoration.forEach(function(elem){
- if (activity.elements) {
- activity.elements.push(elem);
- }
- if (elem.decorationWraps) {
- // decoration element is bigger that activity shape, put it in background
- elem.toBack();
- } else {
- elem.toFront();
- }
-
- elem.animate(animation.delay(oldDecoration ? 1000 : undefined));
- });
- }
- },
-
- // hide all Optional Activities, except for the given one
- hideOtherComplexContent : function(currentOptionalContentId) {
- $('div.optionalActivity').each(function(index, contentDiv){
- var content = $(contentDiv);
- if (content.attr('id') != currentOptionalContentId) {
- content.slideUp(currentOptionalContentId ? 'fast' : 'slow');
- }
- });
- },
-
- // draw box with inner activities
- showComplexContent : function(activity) {
- if (activity.isComplex) {
- // hide glow if shown (IE)
- ActivityUtils.removeHover(activity.shape);
- // remove other boxes, if shown
- ActivityUtils.hideOtherComplexContent
- (activity.optionalContent ? activity.optionalContent.attr('id') : null);
-
- if (!activity.optionalContent) {
- // build box HTML
- var containerName = 'optionalActivityContent' + activity.y;
- activity.optionalContent = $('')
- .attr('id', containerName)
- .addClass('optionalActivity')
- .css({
- // a little higher than activity, to cover it
- 'top' : $(activity.shape.node).offset().top - 8,
- 'height' : 27 * activity.childActivities.length - 1
- })
- .appendTo('#progressBarDiv');
-
- var optionalContentTable = $('
');
- var parentId = null;
- if (isNested) {
- // second tier, a part of optional sequence or branching
- parentId = $('td', parent).attr('id');
- // find last activity from sequence and put current one after it to keep ordering
- row.insertAfter($('td[id^=' + parentId + ']', container).last().parent());
- isCurrent |= childActivity.status == 0;
- } else {
- parentId = container.attr('id');
- row.appendTo(parent);
- }
-
- var cellId = parentId + 'child' + childActivityIndex;
- var cell = $('
').attr('id', cellId).appendTo(row);
- if (isNested) {
- cell.hide();
- }
-
- // each row has its own paper
- childActivity.paper = Raphael(cellId, 145, 23);
- // draw the inner activity
- childActivity.shape = childActivity.paper.path(childActivity.path);
- childActivity.shape.attr(ActivityUtils.getShapeAttributes(childActivity));
- ActivityUtils.addDecoration(childActivity, null, true);
- var label = childActivity.paper.text(35,
- childActivity.y + 11,
- // add dash before name
- (isNested ? '- ' : '') + childActivity.name)
- // align to left
- .attr('text-anchor', 'start');
- // fix a bug in FF layout
- $('tspan', label.node).attr('dy', 0);
-
- var click = null;
- if (!isNested) {
- // only first tier inner activities
- if (childActivityIndex == 0) {
- click = function(){
- // first row is the parent activity itself; hide content box when clicked
- container.slideUp();
- }
- } else if (childActivity.childActivities){
- // show/hide 2nd tier inner activities
- childActivity.toggleChildren = function(forceCommand){
- if (cell.is(':visible')) {
- var childCells = $('td[id^=' + cellId + 'child]', parent);
- var isOpen = childCells.is(':visible');
- if (!forceCommand || (isOpen ? forceCommand == 'close' : forceCommand == 'open')) {
- var containerHeightDelta = 27 * childCells.length;
- childCells.toggle();
- // resize inner content box
- container.height(container.height() +
- (isOpen ? -containerHeightDelta : containerHeightDelta));
- }
- }
- }
-
- click = function(){
- // show 2nd tier when 1st tier activity is clicked
- childActivity.toggleChildren();
- }
- }
- }
- var dblclick = function() {
- if (childActivity.url) {
- if (childActivity.status == 1) {
- openActivity(childActivity.url);
- } else {
- loadFrame(childActivity.url);
- }
- }
- }
- handleClicks(cell, click, dblclick);
-
- if (childActivity.childActivities) {
- isCurrent |= ActivityUtils.addChildActivitiesRows(childActivity, row, container, true);
- if (isCurrent && childActivity.toggleChildren) {
- childActivity.toggleChildren('open');
- }
- }
- });
-
- return isCurrent;
- },
-
- // replace single Branching activity with list of branch activities
- expandBranch : function(branchIndex, branchActivities) {
- // hide any boxes obstructing the view
- ActivityUtils.hideOtherComplexContent();
-
- var activityShift = branchActivities.length - 1;
- // how many pixels move subsequent activities down
- var yShift = 60*activityShift;
- // activity just after branching
- var afterBranchActivity = null;
- // move down existing activities that come after Branching; start with the last one
- for (var activityIndex = activities.length - 1; activityIndex > branchIndex; activityIndex--) {
- afterBranchActivity = activities[activityIndex];
- activities[activityIndex + activityShift] = afterBranchActivity;
- afterBranchActivity.y += yShift;
- afterBranchActivity.path = Raphael.transformPath(afterBranchActivity.path, 'T0,' + yShift);
- afterBranchActivity.elements.forEach(function(elem){
- var y = elem.attr('y');
- var targetProperties = null;
- // text, rectangles etc. have 'y', paths have 'path'
- if (y) {
- targetProperties = {'y' : elem.attr('y') + yShift};
- } else {
- var path = elem.attr('path');
- targetProperties = {'path' : Raphael.transformPath(path, 'T0,' + yShift)};
- }
- elem.animate(targetProperties, 2000, "linear");
- });
- }
-
- // smoothly remove Branching activity
- activities[branchIndex].elements.forEach(function(elem) {
- elem.animate({'opacity' : 0} , 2000, "linear" , function() {
- elem.remove();
- });
- });
-
- // create branch activities structures
- for (var activityIndex = 0; activityIndex < branchActivities.length; activityIndex ++){
- var activityData = branchActivities[activityIndex];
- var activity = new Activity(paper, activityIndex + branchIndex, activityData.id,
- activityData.type, activityData.name,
- activityData.status, activityData.url,
- activityData.childActivities);
- activities[activityIndex + branchIndex] = activity;
- if (activity.status == 0) {
- currentActivityIndex = activityIndex;
- }
- }
-
- // smoothly draw branch activities
- setTimeout(function(){
- for (var activityIndex = 0; activityIndex < branchActivities.length; activityIndex ++){
- ActivityUtils.drawActivity(activities[activityIndex + branchIndex], false,
- !afterBranchActivity && activityIndex == branchActivities.length - 1);
- }
- }, 2000);
- }
-}
-
-// main activities
-function Activity(paper, index, id, type, name, status, url, childActivitiesData) {
- this.paper = paper;
- this.index = index;
- this.id = id;
- this.type = type;
- this.name = name;
- this.status = status;
- this.url = url;
-
- // Optional Activities, Optional Sequences or Branching in preview mode
- this.isComplex = type == 'o' || (isPreview && type == 'b');
- // X positioning
- this.middle = 70;
- this.height = 60;
- // 20 is the first line segment and following activities take 60 px each
- // (together with following vertical line)
- this.y = 20 + this.height * index;
-
- // first draw the inner shape, then put back the realY for background gray square
- var finalY = this.y;
- if (this.isComplex) {
- this.y += 5;
- }
-
- if (type == 'g') {
- // gate activity
- this.height = 70;
- ActivityUtils.shapeGateActivity(this);
- } else {
- ActivityUtils.shapeByStatus(this);
- }
-
-
- // special behaviour for complex activities
- if (this.isComplex) {
- this.height = 70;
- this.y = finalY;
- ActivityUtils.shapeComplexActivityContainer(this);
-
- this.childActivities = [new OptionalActivity(name, status, url)];
- var childActivities = this.childActivities;
- $.each(childActivitiesData, function(childActivityIndex, childActivityData) {
- childActivities[childActivityIndex + 1] = new OptionalActivity(childActivityData.name,
- childActivityData.status, childActivityData.url,
- childActivityData.childActivities, false);
- });
- }
-}
-
-// Support (floating) activities are show in separate box and behave differently
-function SupportActivity(paper, index, name, status, url) {
- this.paper = paper;
- this.name = name;
- this.status = status;
- this.url = url;
-
- this.middle = 24;
- this.y = 17 + 33*index;
-
- if (status <= 2) {
- ActivityUtils.shapeAttemptedActivity(this);
- } else if (status == 3) {
- ActivityUtils.shapeToStartActivity(this);
- }
- this.statusTooltip = LABEL_SUPPORT_ACTIVITY;
-
- this.transformToAttempted = function(){
- var oldDecoration = this.decoration;
- ActivityUtils.shapeAttemptedActivity(this);
- this.statusTooltip = LABEL_SUPPORT_ACTIVITY;
-
- ActivityUtils.animate(this, oldDecoration);
- }
-}
-
-// Optional and Branching inner activities
-function OptionalActivity(name, status, url, childActivitiesData, isNested) {
- this.name = name;
- this.status = status;
- this.url = url;
-
- this.middle = isNested ? 22 : 15;
- this.y = 5;
-
- ActivityUtils.shapeByStatus(this);
-
- // if Sequence or Branching, this is the 2nd tier of inner activities
- if (childActivitiesData) {
- this.childActivities = [];
- var childActivities = this.childActivities;
- $.each(childActivitiesData, function(childActivityIndex, childActivityData) {
- childActivities[childActivityIndex] = new OptionalActivity(childActivityData.name,
- childActivityData.status, childActivityData.url, null, true);
- });
- }
-}
-
-
-// refresh progress bar on first/next activity load
-function fillProgressBar() {
- $.ajax({
- url : APP_URL + 'learner.do',
- data : {
- 'method' : 'displayProgressJSON',
- 'lessonID' : lessonId
- },
- cache : false,
- dataType : 'json',
- success : function(result) {
- // if nothing changed, don't do any calculations
- if (!currentActivityId || result.currentActivityId != currentActivityId) {
- currentActivityId = result.currentActivityId;
- isPreview = result.isPreview;
-
- if (!paper) {
- // create paper only the first time
- paper = Raphael('progressBarDiv', 140, 60*result.activities.length);
- // first line on the top
- paper.path("M70 0 v20");
- }
-
- // we need this to scroll to the current activity
- var currentActivityIndex = 0;
-
-
- for (var activityIndex = 0; activityIndex < result.activities.length; activityIndex++) {
- var activityData = result.activities[activityIndex];
- // prepare the Activity descriptor, but do not draw yet
- var activity = new Activity(paper, activityIndex, activityData.id,
- activityData.type, activityData.name,
- activityData.status, activityData.url,
- activityData.childActivities);
- if (activity.status == 0) {
- currentActivityIndex = activityIndex;
- }
-
- var existingActivity = activities[activityIndex];
- if (existingActivity) {
- // if in preview mode, always display all inner activities, i.e. never expand
- if (!isPreview && existingActivity.type == 'b' && existingActivity.id != activity.id) {
-
- var branchActivityId = activityIndex;
- var afterBranchActivityId = activityIndex + 1 < activities.length
- ? activities[activityIndex + 1].id : null;
- var branchActivities = [activity];
- activityIndex++;
-
- // find which activities are new (branch) and which ones already existed
- while (activityIndex < result.activities.length) {
- activityData = result.activities[activityIndex];
- var activity = new Activity(paper, activityIndex, activityData.id,
- activityData.type, activityData.name,
- activityData.status, activityData.url,
- activityData.childActivities);
- if (activity.id == afterBranchActivityId) {
- // prepare for the next big loop iteration, which executes normally
- activityIndex--;
- break;
- } else {
- branchActivities.push(activity);
- activityIndex++;
- }
- }
-
- // resize main paper to accomodate new activities
- paper.setSize(140, 60 * (activities.length + branchActivities.length - 1));
- ActivityUtils.expandBranch(branchActivityId, branchActivities);
- } else {
- // refresh existing bar, transform activities if needed
- ActivityUtils.transform(existingActivity, activity);
- }
- } else {
- // draw new activity
- ActivityUtils.drawActivity(activity, true,
- activityIndex == result.activities.length - 1);
- }
- }
-
- // draw support activities if they exist
- if (result.support && !supportSeparatorRow.is(':visible')) {
- supportSeparatorRow.show();
- supportPart.height(17 + 33 * result.support.length).show();
-
- // separate paper for Suppor Activities frame
- var supportPaper = Raphael('supportPart');
-
- jQuery.each(result.support, function(activityIndex, activityData) {
- var activity = new SupportActivity(supportPaper, activityIndex,
- activityData.name, activityData.status, activityData.url);
- activity.shape = supportPaper.path(activity.path);
- activity.shape.attr(ActivityUtils.getShapeAttributes(activity));
- ActivityUtils.addDecoration(activity, null, true);
- ActivityUtils.addEffects(activity);
- supportPaper.text(90, 24 + 33 * activityIndex, activity.name);
- });
- }
-
- resizeElements();
- // scroll to the current activity
- $('#progressBarDiv').scrollTop(Math.max((currentActivityIndex-1)*60, 0));
- }
- }
- });
}
\ No newline at end of file
Index: lams_learning/web/main.jsp
===================================================================
diff -u -r2c442242c90c2509ed564fda945f01ff422e102b -r9438790401b957cdd70a4d6ab2a76da70176c6eb
--- lams_learning/web/main.jsp (.../main.jsp) (revision 2c442242c90c2509ed564fda945f01ff422e102b)
+++ lams_learning/web/main.jsp (.../main.jsp) (revision 9438790401b957cdd70a4d6ab2a76da70176c6eb)
@@ -30,6 +30,7 @@
+
@@ -40,31 +41,39 @@
+
+
+
@@ -254,7 +264,7 @@
@@ -288,7 +298,15 @@