Adding students wheel see #1791

skala
Julio Montoya 12 years ago
parent cec719d15b
commit 31cad46fe7
  1. 5
      main/admin/skills_wheel.php
  2. 14
      main/inc/ajax/skill.ajax.php
  3. 11
      main/inc/lib/skill.lib.php
  4. 48
      main/social/skills_wheel.php
  5. 499
      main/template/default/skill/skill_wheel.js.tpl
  6. 504
      main/template/default/skill/skill_wheel.tpl
  7. 934
      main/template/default/skill/skill_wheel_student.tpl

@ -27,9 +27,6 @@ $htmlHeadXtra[] = api_get_js('d3/jquery.xcolor.js');
$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
$htmlHeadXtra[] = '<link href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
//$htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/d3/colorbrewer.css');
$tpl = new Template(null, false, false);
$load_user = 0;
@ -52,4 +49,4 @@ $tpl->assign('url', $url);
$content = $tpl->fetch('default/skill/skill_wheel.tpl');
$tpl->assign('content', $content);
$tpl->display_no_layout_template();
$tpl->display_no_layout_template();

@ -100,9 +100,21 @@ switch ($action) {
break;
case 'get_skill_info':
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$skill_info = $skill->get_skill_info($id);
$skill_info = $skill->get_skill_info($id);
echo json_encode($skill_info);
break;
case 'get_skill_course_info':
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$courses = $skill->get_courses_by_skill($id);
$html = null;
if (!empty($courses)) {
foreach ($courses as $course) {
$html .= $course['title'].'<br />';
}
}
echo $html;
break;
case 'get_skills_tree_json':
$user_id = isset($_REQUEST['load_user']) && $_REQUEST['load_user'] == 1 ? api_get_user_id() : 0;
$skill_id = isset($_REQUEST['skill_id']) ? $_REQUEST['skill_id'] : 0;

@ -837,6 +837,15 @@ class Skill extends Model {
return $result[0];
}
return 0;
}
function get_courses_by_skill($skill_id) {
$skill_id = intval($skill_id);
$sql = "SELECT c.title, c.code FROM {$this->table_gradebook} g INNER JOIN {$this->table_skill_rel_gradebook} sg ON g.id = sg.gradebook_id
INNER JOIN {$this->table_course} c ON c.code = g.course_code
WHERE sg.skill_id = $skill_id";
$result = Database::query($sql);
return Database::store_result($result, 'ASSOC');
}
}

@ -0,0 +1,48 @@
<?php
/* For licensing terms, see /license.txt */
/**
* @package chamilo.admin
*/
// Language files that need to be included.
$language_file = array('admin');
$cidReset = true;
require_once '../inc/global.inc.php';
$this_section = SECTION_SOCIAL;
if (api_get_setting('allow_skills_tool') != 'true') {
api_not_allowed();
}
//Adds the JS needed to use the jqgrid
$htmlHeadXtra[] = api_get_js('d3/d3.v2.min.js');
$htmlHeadXtra[] = api_get_js('d3/colorbrewer.js');
$htmlHeadXtra[] = api_get_js('d3/jquery.xcolor.js');
$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
$htmlHeadXtra[] = '<link href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
$tpl = new Template(null, false, false);
$load_user = api_get_user_id();
$skill_condition = '';
if (isset($_GET['skill_id'])) {
$skill_condition = '&skill_id='.intval($_GET['skill_id']);
$tpl->assign('skill_id_to_load', $_GET['skill_id']);
}
$url = api_get_path(WEB_AJAX_PATH)."skill.ajax.php?a=get_skills_tree_json&load_user=$load_user";
$tpl->assign('wheel_url', $url);
$url = api_get_path(WEB_AJAX_PATH).'skill.ajax.php?1=1';
$tpl->assign('url', $url);
$content = $tpl->fetch('default/skill/skill_wheel_student.tpl');
$tpl->assign('content', $content);
$tpl->display_no_layout_template();

@ -0,0 +1,499 @@
<script>
/* Skill wheel settings */
var url = '{{ url }}';
var skill_to_load_from_get = '{{ skill_id_to_load }}';
var my_domain = [1,2,3,4,5,6,7,8,9];
var col = 9;
var color_patterns = [];
color_patterns[1] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[col]);
color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Purples[col]);
//color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[6]);
color_patterns[3] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greens[col]);
color_patterns[4] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Reds[col]);
color_patterns[5] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Oranges[col]);
color_patterns[6] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrBr[col]);
color_patterns[7] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGn[col]);
color_patterns[8] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGnBu[col]);
color_patterns[9] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.GnBu[col]);
color_patterns[10] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuGn[col]);
color_patterns[11] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBuGn[col]);
color_patterns[12] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBu[col]);
color_patterns[13] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuPu[col]);
color_patterns[14] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.RdPu[col]);
color_patterns[15] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuRd[col]);
color_patterns[16] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.OrRd[col]);
color_patterns[17] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrRd[col]);
color_patterns[18] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greys[col]);
//var normal_fill = d3.scale.category10().domain(my_domain);
var main_depth = 1000;
var colors1 = $.xcolor.analogous('#da0'); //8 colors
var colors = colors1;
// Generating array of colors
color_loops = 4;
for (i= 0; i < color_loops; i++) {
last_color = colors[colors.length-1].getHex();
glue_color = $.xcolor.complementary(last_color);
//colors.push(glue_color.getHex());
colors2 = $.xcolor.analogous(glue_color);
colors = $.merge(colors, colors2);
}
/* Interpolate the scales! */
function arcTween(d, arc, x, y, r) {
var my = maxY(d),
xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, my]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, r]);
return function(d) {
return function(t) {
x.domain(xd(t));
y.domain(yd(t)).range(yr(t));
return arc(d);
};
};
}
/* */
function maxY(d) {
return d.children ? Math.max.apply(Math, d.children.map(maxY)) : d.y + d.dy;
}
/* Use a formula for contrasting colour
http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
*/
function brightness(rgb) {
return rgb.r * .299 + rgb.g * .587 + rgb.b * .114;
}
/* Returns whether p is parent of c */
function isParentOf(p, c) {
if (p === c) return true;
if (p.children) {
return p.children.some(function(d) {
return isParentOf(d, c);
});
}
return false;
}
function get_color(d) {
depth = d.depth;
if (d.family_id) {
/*var p = color_patterns[d.family_id];
color = p(depth -1 + d.counter);
d.color = color;*/
if (depth > 1) {
family1 = colors[d.family_id];
family2 = colors[d.family_id + 2];
position = d.depth*d.counter;
//part_color = $.xcolor.gradientlevel(family1, family2, position, 100);
part_color = $.xcolor.lighten(family1, position, 15);
color = part_color.getHex();
//console.log(d.depth + " - " + d.name + " + "+ color+ "+ " +d.counter);
} else {
color = colors[d.family_id];
}
return color;
}
color = '#fefefe';
return color; //missing colors
}
/*
gray tones for all skills that have no particular property ("Basic skills wheel" view)
yellow tones for skills that are provided by courses in Chamilo ("Teachable skills" view)
bright blue tones for personal skills already acquired by the student currently looking at the weel ("My skills" view)
dark blue tones for skills already acquired by a series of students, when looking at the will in the "Owned skills" view.
bright green for skills looked for by a HR director ("Profile search" view)
dark green for skills most searched for, summed up from the different saved searches from HR directors ("Most wanted skills")
bright red for missing skills, in the "Required skills" view for a student when looking at the "Most wanted skills" (or later, when we will have developed that, for the "Matching position" view)
*/
function set_skill_style(d, attribute) {
//Nice rainbow colors
return_fill = get_color(d);
/*var p = color_patterns[18];
color = p(depth -1 + d.counter);
return_fill = d.color = color;*/
//return_fill = 'grey';
return_stroke = 'black';
//If user achieved that skill
if (d.achieved) {
return_fill = 'cornflowerblue';
//return_stroke = '#FCD23A';
}
//darkblue
//If the skill has a gradebook attached
if (d.skill_has_gradebook) {
return_fill = '#FEF664';
//return_stroke = 'grey';
}
switch (attribute) {
case 'fill':
//In order to the text could identify the background
d.color = return_fill;
return return_fill;
break;
case 'stroke':
return return_stroke;
break;
}
}
function click_partition(d, path, text, icon, arc, x, y, r, p) {
if (d.depth == 2) {
/*main_depth +=1;
load_nodes(main_depth);*/
}
var duration = 1000;
path.transition()
.duration(duration)
.attrTween("d", arcTween(d, arc, x, y, r));
/* Updating text position */
// Somewhat of a hack as we rely on arcTween updating the scales.
text.style("visibility", function(e) {
return isParentOf(d, e) ? null : d3.select(this).style("visibility");
})
.transition().duration(duration)
.attrTween("text-anchor", function(d) {
return function() {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
};
})
.attrTween("transform", function(d) {
var multiline = (d.name || "").split(" ").length > 1;
return function() {
var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle + (multiline ? -.5 : 0);
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
};
})
.style("fill-opacity", function(e) {
return isParentOf(d, e) ? 1 : 1e-6;
})
.each("end", function(e) {
d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
});
/* Updating icon position */
icon.transition().duration(duration)
.attrTween("text-anchor", function(d) {
return function() {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
};
})
.attrTween("transform", function(d) {
return function() {
var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle;
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
};
})
.style("fill-opacity", function(e) {
//return isParentOf(d, e) ? 1 : 1e-6;
})
.each("end", function(e) {
//d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
});
}
function handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding) {
switch (d3.event.which) {
case 1:
//alert('Left mouse button pressed');
click_partition(d, path, text, icon, arc, x, y, r, padding);
break;
case 2:
//alert('Middle mouse button pressed');
break;
case 3:
open_popup(d.id);
//alert('Right mouse button pressed');
break;
default:
//alert('You have a strange mouse');
}
}
function load_nodes(load_skill_id, main_depth) {
/** Define constants and size of the wheel */
/** Total width of the wheel (also counts for the height) */
var w = 900,
h = w,
r = w / 2,
/** x/y positionning of the center of the wheel */
x = d3.scale.linear().range([0, 2 * Math.PI]),
y = d3.scale.pow().exponent(1.1).domain([0, 1]).range([0, r]),
/** Padding in pixels before the string starts */
padding = 3,
/** Duration of click animations */
duration = 1000,
/** Levels to show */
levels_to_show = 3;
reduce_top = 1;
/* Locate the #div id element */
$("#skill_wheel").remove();
$("#wheel_container").html('');
$("#wheel_container").append('<div id="skill_wheel"></div>');
var div = d3.select("#skill_wheel");
/* Remove the image (make way for the dynamic stuff */
div.select("img").remove();
/* Append an element "svg" to the #vis section */
var vis = div.append("svg")
//.attr("class", "Blues")
.attr("width", w + padding * 2)
.attr("height", h + padding * 2)
.append("g")
.attr("transform", "translate(" + (r + padding) + "," + (r/reduce_top + padding) + ")");
/* ...update translate variables to change coordinates of wheel's center */
/* Add a small label to help the user */
div.append("p")
.attr("id", "intro")
.text("{{ "ClickToZoom"|get_lang }}");
/* Generate the partition layout */
var partition = d3.layout.partition()
.sort(null)
/** Value here seems to be a calculation of the size of the elements
depending on the level of depth they're at. Changing it makes
elements pass over the limits of others... */
//.size([1, 2])
.value(function(d) {
//return 5.8 - d.depth;
//When having more than 4 children seems that the code above doesn't work
return 1;
});
/* Generate an arc which will define the whole wheel context */
var arc = d3.svg.arc()
.startAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
})
.endAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
})
.innerRadius(function(d) {
return Math.max(0, d.y ? y(d.y) : d.y);
})
.outerRadius(function(d) {
return Math.max(0, y(d.y + d.dy));
});
load_skill_condition = '';
//First the $_GET value
if (skill_to_load_from_get != 0) {
load_skill_condition = 'skill_id=' + skill_to_load_from_get;
}
//The JS load
if (load_skill_id != 0) {
load_skill_condition = 'skill_id=' + load_skill_id;
}
d3.json("{{ wheel_url }}&main_depth="+main_depth+"&"+load_skill_condition, function(json) {
/** Define the list of nodes based on the JSON */
var nodes = partition.nodes({
children: json
});
/* Setting all skills */
var path = vis.selectAll("path").data(nodes);
/* Setting all texts */
var text = vis.selectAll("text").data(nodes);
/* Setting icons */
var icon = vis.selectAll("icon").data(nodes);
/* Path settings */
path.enter().append("path")
.attr("id", function(d, i) {
return "path-" + i;
})
.attr("d", arc)
.attr("fill-rule", "evenodd")
.attr("class", "skill_partition skill_background")
// .style("fill", colour)
.style("fill", function(d) {
return set_skill_style(d, 'fill');
})
.style("stroke", function(d) {
return set_skill_style(d, 'stroke');
})
.on("mouseover", function(d, i) {
$("#icon-" + i).show();
})
.on("mouseout", function(d, i) {
$("#icon-" + i).hide();
})
.on("mousedown", function(d, i) {
//Handles 2 mouse clicks
handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding);
})
.on("click", function(d){
//click_partition(d, path, text, icon, arc, x, y, r, padding);
});
/* End setting skills */
/* Text settings */
var textEnter = text.enter().append("text")
.style("fill-opacity", 1)
.style("fill", function(d) {
return brightness(d3.rgb(d.color)) < 125 ? "#eee" : "#000";
})
.attr("text-anchor", function(d) {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
})
.attr("dy", ".2em")
.attr("transform", function(d) {
/** Get the text details and define the rotation and general position */
var multiline = (d.name || "").split(" ").length > 1,
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle + (multiline ? -.5 : 0);
return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
})
.on("mouseover", function(d, i) {
$("#icon-" + i).show();
})
.on("mouseout", function(d, i) {
$("#icon-" + i).hide();
})
.on("mousedown", function(d, i) {
//Handles 2 mouse clicks
handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding);
})
.on("click", function(d){
//click_partition(d, path, text, icon, arc, x, y, r, padding);
});
/** Managing text - always maximum two words */
textEnter.append("tspan")
.attr("x", 0)
.text(function(d) {
return d.depth ? d.name.split(" ")[0] : "";
});
textEnter.append("tspan")
.attr("x", 0)
.attr("dy", "1em")
.text(function(d) {
return d.depth ? d.name.split(" ")[1] || "" : "";
});
/* Icon settings */
/*
var icon_click = icon.enter().append("text")
.style("fill-opacity", 1)
.style("fill", function(d) {
//return "#000";
})
.attr("text-anchor", function(d) {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
})
.attr("dy", ".2em")
.attr("transform", function(d) {
///Get the text details and define the rotation and general position
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle;
return "rotate(" + rotate + ")translate(" + (y(d.y) + padding +80) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
})
.on("click", function(d){
open_popup(d);
});
icon_click.append("tspan")
.attr("id", function(d, i) {
return "icon-" + i;
})
.attr("x", 0)
.attr("display", 'none')
.text(function(d) {
//return "Click";
});*/
});
}
/* Skill ajax calls */
function get_skill_info(my_id) {
var skill = false;
$.ajax({
url: url+'&a=get_skill_info&id='+my_id,
async: false,
success: function(json) {
skill = jQuery.parseJSON(json);
return skill;
}
});
return skill;
}
function get_gradebook_info(id) {
var item = false;
$.ajax({
url: url+'&a=get_gradebook_info&id='+id,
async: false,
success: function(json) {
item = jQuery.parseJSON(json);
return item;
}
});
return item;
}
$(document).ready(function() {
});
</script>

@ -1,35 +1,6 @@
<script>
/* For licensing terms, see /license.txt */
var url = '{{ url }}';
{% include 'default/skill/skill_wheel.js.tpl' %}
var skill_to_load_from_get = '{{ skill_id_to_load }}';
function get_skill_info(my_id) {
var skill = false;
$.ajax({
url: url+'&a=get_skill_info&id='+my_id,
async: false,
success: function(json) {
skill = jQuery.parseJSON(json);
return skill;
}
});
return skill;
}
function get_gradebook_info(id) {
var item = false;
$.ajax({
url: url+'&a=get_gradebook_info&id='+id,
async: false,
success: function(json) {
item = jQuery.parseJSON(json);
return item;
}
});
return item;
}
<script>
function add_skill(params) {
$.ajax({
@ -88,7 +59,6 @@ function check_skills_sidebar() {
}
function fill_skill_search_li(skill_id, skill_name, checked) {
checked_condition = '';
if (checked == 1) {
checked_condition = 'checked=checked';
@ -320,8 +290,7 @@ $(document).ready(function() {
add_skill_in_profile_list(skill_id, skill_info.name);
});
submit_profile_search_form();
submit_profile_search_form();
}
});
@ -391,274 +360,9 @@ $(document).ready(function() {
width : 500,
height : 400
});
/* ...adding "+1" to "y" function's params is really funny */
/* Exexute the calculation based on a JSON file provided */
/*d3.json("wheel.json", function(json) {*/
/** Get the JSON list of skills and work on it */
var my_domain = [1,2,3,4,5,6,7,8,9];
var col = 9;
var color_patterns = [];
color_patterns[1] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[col]);
color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Purples[col]);
//color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[6]);
color_patterns[3] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greens[col]);
color_patterns[4] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Reds[col]);
color_patterns[5] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Oranges[col]);
color_patterns[6] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrBr[col]);
color_patterns[7] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGn[col]);
color_patterns[8] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGnBu[col]);
color_patterns[9] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.GnBu[col]);
color_patterns[10] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuGn[col]);
color_patterns[11] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBuGn[col]);
color_patterns[12] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBu[col]);
color_patterns[13] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuPu[col]);
color_patterns[14] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.RdPu[col]);
color_patterns[15] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuRd[col]);
color_patterns[16] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.OrRd[col]);
color_patterns[17] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrRd[col]);
color_patterns[18] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greys[col]);
//var normal_fill = d3.scale.category10().domain(my_domain);
var main_depth = 1000;
load_nodes(0, main_depth);
function load_nodes(load_skill_id, main_depth) {
/** Define constants and size of the wheel */
/** Total width of the wheel (also counts for the height) */
var w = 900,
h = w,
r = w / 2,
/** x/y positionning of the center of the wheel */
x = d3.scale.linear().range([0, 2 * Math.PI]),
y = d3.scale.pow().exponent(1.1).domain([0, 1]).range([0, r]),
/** Padding in pixels before the string starts */
padding = 3,
/** Duration of click animations */
duration = 1000,
/** Levels to show */
levels_to_show = 3;
reduce_top = 1;
/* Locate the #div id element */
$("#skill_wheel").remove();
$("#wheel_container").html('');
$("#wheel_container").append('<div id="skill_wheel"></div>');
var div = d3.select("#skill_wheel");
/* Remove the image (make way for the dynamic stuff */
div.select("img").remove();
/* Append an element "svg" to the #vis section */
var vis = div.append("svg")
//.attr("class", "Blues")
.attr("width", w + padding * 2)
.attr("height", h + padding * 2)
.append("g")
.attr("transform", "translate(" + (r + padding) + "," + (r/reduce_top + padding) + ")");
/* ...update translate variables to change coordinates of wheel's center */
/* Add a small label to help the user */
div.append("p")
.attr("id", "intro")
.text("{{ "ClickToZoom"|get_lang }}");
/* Generate the partition layout */
var partition = d3.layout.partition()
.sort(null)
/** Value here seems to be a calculation of the size of the elements
depending on the level of depth they're at. Changing it makes
elements pass over the limits of others... */
//.size([1, 2])
.value(function(d) {
//return 5.8 - d.depth;
//When having more than 4 children seems that the code above doesn't work
return 1;
});
/* Generate an arc which will define the whole wheel context */
var arc = d3.svg.arc()
.startAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
})
.endAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
})
.innerRadius(function(d) {
return Math.max(0, d.y ? y(d.y) : d.y);
})
.outerRadius(function(d) {
return Math.max(0, y(d.y + d.dy));
});
load_skill_condition = '';
//First the $_GET value
if (skill_to_load_from_get != 0) {
load_skill_condition = 'skill_id=' + skill_to_load_from_get;
}
//The JS load
if (load_skill_id != 0) {
load_skill_condition = 'skill_id=' + load_skill_id;
}
d3.json("{{ wheel_url }}&main_depth="+main_depth+"&"+load_skill_condition, function(json) {
/** Define the list of nodes based on the JSON */
var nodes = partition.nodes({
children: json
});
/* Setting all skills */
var path = vis.selectAll("path").data(nodes);
/* Setting all texts */
var text = vis.selectAll("text").data(nodes);
/* Setting icons */
var icon = vis.selectAll("icon").data(nodes);
/* Path settings */
path.enter().append("path")
.attr("id", function(d, i) {
return "path-" + i;
})
.attr("d", arc)
.attr("fill-rule", "evenodd")
.attr("class", "skill_partition skill_background")
// .style("fill", colour)
.style("fill", function(d) {
return set_skill_style(d, 'fill');
})
.style("stroke", function(d) {
return set_skill_style(d, 'stroke');
})
.on("mouseover", function(d, i) {
$("#icon-" + i).show();
})
.on("mouseout", function(d, i) {
$("#icon-" + i).hide();
})
.on("mousedown", function(d, i) {
//Handles 2 mouse clicks
handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding);
})
.on("click", function(d){
//click_partition(d, path, text, icon, arc, x, y, r, padding);
});
/* End setting skills */
/* Text settings */
var textEnter = text.enter().append("text")
.style("fill-opacity", 1)
.style("fill", function(d) {
return brightness(d3.rgb(d.color)) < 125 ? "#eee" : "#000";
})
.attr("text-anchor", function(d) {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
})
.attr("dy", ".2em")
.attr("transform", function(d) {
/** Get the text details and define the rotation and general position */
var multiline = (d.name || "").split(" ").length > 1,
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle + (multiline ? -.5 : 0);
return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
})
.on("mouseover", function(d, i) {
$("#icon-" + i).show();
})
.on("mouseout", function(d, i) {
$("#icon-" + i).hide();
})
.on("mousedown", function(d, i) {
//Handles 2 mouse clicks
handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding);
})
.on("click", function(d){
//click_partition(d, path, text, icon, arc, x, y, r, padding);
});
/** Managing text - always maximum two words */
textEnter.append("tspan")
.attr("x", 0)
.text(function(d) {
return d.depth ? d.name.split(" ")[0] : "";
});
textEnter.append("tspan")
.attr("x", 0)
.attr("dy", "1em")
.text(function(d) {
return d.depth ? d.name.split(" ")[1] || "" : "";
});
/* Icon settings */
/*
var icon_click = icon.enter().append("text")
.style("fill-opacity", 1)
.style("fill", function(d) {
//return "#000";
})
.attr("text-anchor", function(d) {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
})
.attr("dy", ".2em")
.attr("transform", function(d) {
///Get the text details and define the rotation and general position
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle;
return "rotate(" + rotate + ")translate(" + (y(d.y) + padding +80) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
})
.on("click", function(d){
open_popup(d);
});
icon_click.append("tspan")
.attr("id", function(d, i) {
return "icon-" + i;
})
.attr("x", 0)
.attr("display", 'none')
.text(function(d) {
//return "Click";
});*/
});
}
function handle_mousedown_event(d, path, text, icon, arc, x, y, r, padding) {
switch (d3.event.which) {
case 1:
//alert('Left mouse button pressed');
click_partition(d, path, text, icon, arc, x, y, r, padding);
break;
case 2:
//alert('Middle mouse button pressed');
break;
case 3:
open_popup(d.id);
//alert('Right mouse button pressed');
break;
default:
//alert('You have a strange mouse');
}
}
function open_save_profile_popup() {
$("#dialog-form-profile").dialog({
@ -803,166 +507,11 @@ $(document).ready(function() {
$("#dialog-form").dialog("open");
}
}
var colors1 = $.xcolor.analogous('#da0'); //8 colors
var colors = colors1;
// Generating array of colors
color_loops = 4;
for (i= 0; i < color_loops; i++) {
last_color = colors[colors.length-1].getHex();
glue_color = $.xcolor.complementary(last_color);
//colors.push(glue_color.getHex());
colors2 = $.xcolor.analogous(glue_color);
colors = $.merge(colors, colors2);
}
function get_color(d) {
depth = d.depth;
if (d.family_id) {
/*var p = color_patterns[d.family_id];
color = p(depth -1 + d.counter);
d.color = color;*/
if (depth > 1) {
family1 = colors[d.family_id];
family2 = colors[d.family_id + 2];
position = d.depth*d.counter;
//part_color = $.xcolor.gradientlevel(family1, family2, position, 100);
part_color = $.xcolor.lighten(family1, position, 15);
color = part_color.getHex();
//console.log(d.depth + " - " + d.name + " + "+ color+ "+ " +d.counter);
} else {
color = colors[d.family_id];
}
return color;
}
color = '#fefefe';
return color; //missing colors
}
/*
gray tones for all skills that have no particular property ("Basic skills wheel" view)
yellow tones for skills that are provided by courses in Chamilo ("Teachable skills" view)
bright blue tones for personal skills already acquired by the student currently looking at the weel ("My skills" view)
dark blue tones for skills already acquired by a series of students, when looking at the will in the "Owned skills" view.
bright green for skills looked for by a HR director ("Profile search" view)
dark green for skills most searched for, summed up from the different saved searches from HR directors ("Most wanted skills")
bright red for missing skills, in the "Required skills" view for a student when looking at the "Most wanted skills" (or later, when we will have developed that, for the "Matching position" view)
*/
function set_skill_style(d, attribute) {
//Nice rainbow colors
return_fill = get_color(d);
/*var p = color_patterns[18];
color = p(depth -1 + d.counter);
return_fill = d.color = color;*/
//return_fill = 'grey';
return_stroke = 'black';
//If user achieved that skill
if (d.achieved) {
return_fill = 'cornflowerblue';
//return_stroke = '#FCD23A';
}
//darkblue
//If the skill has a gradebook attached
if (d.skill_has_gradebook) {
return_fill = '#FEF664';
//return_stroke = 'grey';
}
switch (attribute) {
case 'fill':
//In order to the text could identify the background
d.color = return_fill;
return return_fill;
break;
case 'stroke':
return return_stroke;
break;
}
}
function click_partition(d, path, text, icon, arc, x, y, r, p) {
if (d.depth == 2) {
/*main_depth +=1;
load_nodes(main_depth);*/
}
var duration = 1000;
path.transition()
.duration(duration)
.attrTween("d", arcTween(d, arc, x, y, r));
/* Updating text position */
// Somewhat of a hack as we rely on arcTween updating the scales.
text.style("visibility", function(e) {
return isParentOf(d, e) ? null : d3.select(this).style("visibility");
})
.transition().duration(duration)
.attrTween("text-anchor", function(d) {
return function() {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
};
})
.attrTween("transform", function(d) {
var multiline = (d.name || "").split(" ").length > 1;
return function() {
var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle + (multiline ? -.5 : 0);
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
};
})
.style("fill-opacity", function(e) {
return isParentOf(d, e) ? 1 : 1e-6;
})
.each("end", function(e) {
d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
});
/* Updating icon position */
icon.transition().duration(duration)
.attrTween("text-anchor", function(d) {
return function() {
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
};
})
.attrTween("transform", function(d) {
return function() {
var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
rotate = angle;
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
};
})
.style("fill-opacity", function(e) {
//return isParentOf(d, e) ? 1 : 1e-6;
})
.each("end", function(e) {
//d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
});
}
/* Returns whether p is parent of c */
function isParentOf(p, c) {
if (p === c) return true;
if (p.children) {
return p.children.some(function(d) {
return isParentOf(d, c);
});
}
return false;
}
/* Generated random colour */
/*
function colour(d) {
if (d.children) {
@ -974,34 +523,8 @@ $(document).ready(function() {
return d3.hsl((a.h + b.h) / 2, a.s * 1.2, a.levels_to_show / 1.2);
}
return d.colour || "#fff";
}
}*/
/* Interpolate the scales! */
function arcTween(d, arc, x, y, r) {
var my = maxY(d),
xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, my]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, r]);
return function(d) {
return function(t) {
x.domain(xd(t));
y.domain(yd(t)).range(yr(t));
return arc(d);
};
};
}
/* */
function maxY(d) {
return d.children ? Math.max.apply(Math, d.children.map(maxY)) : d.y + d.dy;
}
/* Use a formula for contrasting colour
http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
*/
function brightness(rgb) {
return rgb.r * .299 + rgb.g * .587 + rgb.b * .114;
}
});
</script>
@ -1051,21 +574,6 @@ $(document).ready(function() {
<div id="saved_profiles">
</div>
<h3>{{ 'MySkills'|get_lang }}</h3>
<hr>
<div id="my_skills">
</div>
<h3>{{ 'GetNewSkills'|get_lang }}</h3>
<hr>
<h3>{{ 'SkillInfo'|get_lang }}</h3>
<hr>
</div>
</div>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save