diff --git a/common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js b/common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
index 57457bd04d..4020fe2471 100644
--- a/common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
+++ b/common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
@@ -214,7 +214,13 @@ define('WordCloudMain', ['logme'], function (logme) {
studentWordsStr,
// By default we do not scale.
- scale = 1;
+ scale = 1,
+
+ // Caсhing of DOM element
+ cloudSectionEl = this.wordCloudEl.find('.result_cloud_section'),
+
+ // Needed for caсhing of d3 group elements
+ groupEl;
// If bounding rectangle is given, scale based on the bounding box of all the words.
if (bounds) {
@@ -227,26 +233,47 @@ define('WordCloudMain', ['logme'], function (logme) {
}
$.each(response.student_words, function (word, stat) {
- studentWordsKeys.push('' + word + ' (' + (100 * (stat / response.total_count)).toFixed(2) + '%)');
+ var percent = (response.display_percents) ? ' ' + (Math.round(100 * (stat / response.total_count))) + '%' : '';
+
+ studentWordsKeys.push('' + word + '' + percent);
});
studentWordsStr = '' + studentWordsKeys.join(', ');
- this.wordCloudEl.find('.result_cloud_section').addClass('active');
+ cloudSectionEl
+ .addClass('active')
+ .find('.your_words').html(studentWordsStr)
+ .find('.total_num_words').html(response.total_count);
- this.wordCloudEl.find('.result_cloud_section').find('.your_words').html(studentWordsStr);
- this.wordCloudEl.find('.result_cloud_section').find('.total_num_words').html(response.total_count);
-
- $(this.wordCloudEl.find('.result_cloud_section').attr('id') + ' .word_cloud').empty();
+ $(cloudSectionEl.attr('id') + ' .word_cloud').empty();
// Actual drawing of word cloud.
- d3.select('#' + this.wordCloudEl.find('.result_cloud_section').attr('id') + ' .word_cloud').append('svg')
- .attr('width', this.width)
- .attr('height', this.height)
- .append('g')
- .attr('transform', 'translate(' + (0.5 * this.width) + ',' + (0.5 * this.height) + ')')
- .selectAll('text')
- .data(words)
- .enter().append('text')
+ groupEl = d3.select('#' + cloudSectionEl.attr('id') + ' .word_cloud').append('svg')
+ .attr('width', this.width)
+ .attr('height', this.height)
+ .append('g')
+ .attr('transform', 'translate(' + (0.5 * this.width) + ',' + (0.5 * this.height) + ')')
+ .selectAll('text')
+ .data(words)
+ .enter().append('g');
+
+ groupEl
+ .append('title')
+ .text(function (d) {
+ var res = '';
+
+ $.each(response.top_words, function(index, value){
+ if (value.text === d.text) {
+ res = value.percent + '%';
+
+ return;
+ }
+ });
+
+ return res;
+ });
+
+ groupEl
+ .append('text')
.style('font-size', function (d) {
return d.size + 'px';
})
@@ -258,7 +285,7 @@ define('WordCloudMain', ['logme'], function (logme) {
.attr('transform', function (d) {
return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')scale(' + scale + ')';
})
- .text(function (d) {
+ .text(function (d) {
return d.text;
});
}; // End-of: WordCloudMain.prototype.drawWordCloud = function (words, bounds) {
diff --git a/common/lib/xmodule/xmodule/word_cloud_module.py b/common/lib/xmodule/xmodule/word_cloud_module.py
index efb5dc755e..dc9eca0cd6 100644
--- a/common/lib/xmodule/xmodule/word_cloud_module.py
+++ b/common/lib/xmodule/xmodule/word_cloud_module.py
@@ -20,11 +20,17 @@ from xblock.core import Scope, String, Object, Boolean, List, Integer
log = logging.getLogger(__name__)
+def pretty_bool(value):
+ BOOL_DICT = [True, "True", "true", "T", "t", "1"]
+ return value in BOOL_DICT
+
+
class WordCloudFields(object):
# Name of poll to use in links to this poll
display_name = String(help="Display name for this module", scope=Scope.settings)
num_inputs = Integer(help="Number of inputs", scope=Scope.settings, default=5)
num_top_words = Integer(help="Number of max words, which will be displayed.", scope=Scope.settings, default=250)
+ display_percents = Boolean(help="Dispaly usage percents for each word.", scope=Scope.settings, default=True)
submitted = Boolean(help="Whether this student has posted words to the cloud", scope=Scope.user_state, default=False)
student_words = List(help="Student answer", scope=Scope.user_state, default=[])
@@ -49,19 +55,22 @@ class WordCloudModule(WordCloudFields, XModule):
def get_state(self):
"""Return success json answer for client."""
if self.submitted:
+ total_count = sum(self.all_words.itervalues())
return json.dumps({
'status': 'success',
'submitted': True,
+ 'display_percents': pretty_bool(self.display_percents),
'student_words': {
word: self.all_words[word] for word in self.student_words
},
- 'total_count': sum(self.all_words.itervalues()),
- 'top_words': self.prepare_words(self.top_words)
+ 'total_count': total_count,
+ 'top_words': self.prepare_words(self.top_words, total_count)
})
else:
return json.dumps({
'status': 'success',
'submitted': False,
+ 'display_percents': False,
'student_words': {},
'total_count': 0,
'top_words': {}
@@ -71,10 +80,10 @@ class WordCloudModule(WordCloudFields, XModule):
"""Convert raw word to suitable word."""
return word.strip().lower()
- def prepare_words(self, words):
+ def prepare_words(self, words, total_count):
"""Convert words dictionary for client API."""
return [
- {'text': word, 'size': count} for
+ {'text': word, 'size': count, 'percent': round(100 * (count / float(total_count)))} for
word, count in words.iteritems()
]
@@ -185,5 +194,6 @@ class WordCloudDescriptor(WordCloudFields, MakoModuleDescriptor, XmlDescriptor):
xml_object.set('display_name', self.display_name)
xml_object.set('num_inputs', self.num_inputs)
xml_object.set('num_top_words', self.num_top_words)
+ xml_object.set('display_percents', pretty_bool(self.display_percents))
return xml_object