Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
f4b247d2
Commit
f4b247d2
authored
Apr 19, 2013
by
Valera Rozuvan
Committed by
Vasyl Nakvasiuk
May 13, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactoring, documenting, moving all HTML generation to template.
parent
97855bb4
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
242 additions
and
153 deletions
+242
-153
common/lib/xmodule/xmodule/css/word_cloud/display.scss
+15
-2
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
+222
-149
lms/templates/word_cloud.html
+5
-2
No files found.
common/lib/xmodule/xmodule/css/word_cloud/display.scss
View file @
f4b247d2
.input-cloud
{
.input-cloud
{
margin
:
5px
;
margin
:
5px
;
}
}
\ No newline at end of file
.result_cloud_section
{
display
:
none
;
width
:
0px
;
height
:
0px
;
}
.result_cloud_section.active
{
display
:
block
;
width
:
635px
;
height
:
auto
;
margin-left
:
auto
;
margin-right
:
auto
;
}
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
View file @
f4b247d2
/**
* @file The main module definition for Word Cloud XModule.
*
* Defines a constructor function which operates on a DOM element. Either show the user text inputs so
* he can enter words, or render his selected words along with the word cloud representing the top words.
*
* @module WordCloudMain
*
* @exports WordCloudMain
*
* @requires logme
*
* @external d3
*/
(
function
(
requirejs
,
require
,
define
)
{
(
function
(
requirejs
,
require
,
define
)
{
define
(
'WordCloudMain'
,
[
'logme'
],
function
(
logme
)
{
define
(
'WordCloudMain'
,
[
'logme'
],
function
(
logme
)
{
/**
* @function WordCloudMain
*
* This function will process all the attributes from the DOM element passed, taking all of
* the configuration attributes. It will either then attach a callback handler for the click
* event on the button in the case when the user needs to enter words, or it will call the
* appropriate mehtod to generate and render a word cloud from user's enetered words along with
* all of the other words.
*
* @constructor
*
* @param {jQuery} el DOM element where the word cloud will be processed and created.
*/
var
WordCloudMain
=
function
(
el
)
{
var
_this
=
this
;
this
.
wordCloudEl
=
$
(
el
).
find
(
'.word_cloud'
);
// Get the URL to which we will post the users words.
this
.
ajax_url
=
this
.
wordCloudEl
.
data
(
'ajax-url'
);
// Dimensions of the box where the word cloud will be drawn.
this
.
width
=
635
;
this
.
height
=
635
;
// Hide WordCloud container before Ajax request done
this
.
wordCloudEl
.
hide
();
// Retriveing response from the server as an AJAX request. Attach a callback that will
// be fired on server's response.
$
.
postWithPrefix
(
_this
.
ajax_url
+
'/'
+
'get_state'
,
null
,
function
(
response
)
{
if
(
response
.
status
!==
'success'
)
{
logme
(
'ERROR: '
+
response
.
error
);
return
;
}
_this
.
configJson
=
response
;
}
)
.
done
(
function
()
{
// Show WordCloud container after Ajax request done
_this
.
wordCloudEl
.
show
();
var
hash
=
0
;
try
{
_this
.
configJson
=
_this
.
configJson
||
JSON
.
parse
(
_this
.
wordCloudEl
.
find
(
'.word_cloud_div'
).
html
());
WordCloudMain
.
prototype
=
{
}
catch
(
err
)
{
logme
(
'ERROR: Incorrect JSON config was given.'
);
'submitAnswer'
:
function
()
{
logme
(
err
.
message
);
var
_this
=
this
,
data
=
{
'student_words'
:
[]
};
this
.
wordCloudEl
.
find
(
'input.input-cloud'
).
each
(
function
(
index
,
value
){
data
.
student_words
.
push
(
$
(
value
).
val
());
});
// Send the data to the server as an AJAX request. Attach a callback that will
// be fired on server's response.
$
.
postWithPrefix
(
_this
.
ajax_url
+
'/'
+
'submit'
,
$
.
param
(
data
),
function
(
response
)
{
if
(
response
.
status
!==
'success'
)
{
logme
(
'ERROR: '
+
response
.
error
);
return
;
return
;
}
}
_this
.
showWordCloud
(
response
);
if
(
_this
.
configJson
.
submitted
)
{
}
_this
.
showWordCloud
(
_this
.
configJson
);
);
},
// End-of: 'submitAnswer': function (answer, answerEl) {
return
;
}
});
'showWordCloud'
:
function
(
response
){
$
(
el
).
find
(
'input.save'
).
on
(
'click'
,
function
()
{
var
words
,
_this
.
submitAnswer
();
_this
=
this
,
});
fill
=
d3
.
scale
.
category20
(),
};
// End-of: var WordCloudMain = function (el) {
maxSize
,
minSize
;
/**
* @function submitAnswer
*
* Callback to be executed when the user eneter his words. It will send user entries to the
* server, and upon receiving correct response, will call the function to generate the
* word cloud.
*/
WordCloudMain
.
prototype
.
submitAnswer
=
function
()
{
var
_this
=
this
,
data
=
{
'student_words'
:
[]};
// Populate the data to be sent to the server with user's words.
this
.
wordCloudEl
.
find
(
'input.input-cloud'
).
each
(
function
(
index
,
value
)
{
data
.
student_words
.
push
(
$
(
value
).
val
());
});
this
.
wordCloudEl
.
find
(
'#input-cloud-section'
).
hide
();
// Send the data to the server as an AJAX request. Attach a callback that will
// be fired on server's response.
$
.
postWithPrefix
(
_this
.
ajax_url
+
'/'
+
'submit'
,
$
.
param
(
data
),
function
(
response
)
{
if
(
response
.
status
!==
'success'
)
{
logme
(
'ERROR: '
+
response
.
error
);
words
=
response
.
top_words
;
return
;
}
maxSize
=
0
;
_this
.
showWordCloud
(
response
);
minSize
=
10000
;
}
);
$
.
each
(
words
,
function
(
index
,
word
)
{
};
// End-of: WordCloudMain.prototype.submitAnswer = function () {
if
(
word
.
size
>
maxSize
)
{
maxSize
=
word
.
size
;
/**
}
* @function showWordCloud
if
(
word
.
size
<
minSize
)
{
*
minSize
=
word
.
size
;
* @param {object} response The response from the server that contains the user's entered words
}
* along with all of the top words.
});
*
* This function will set up everything for d3 and launch the draw method. Among other things,
* iw will determine maximum word size.
*/
WordCloudMain
.
prototype
.
showWordCloud
=
function
(
response
)
{
var
words
,
_this
=
this
,
maxSize
,
minSize
,
scaleFactor
,
maxFontSize
,
minFontSize
;
this
.
wordCloudEl
.
find
(
'.input_cloud_section'
).
hide
();
words
=
response
.
top_words
;
maxSize
=
0
;
minSize
=
10000
;
scaleFactor
=
1
;
maxFontSize
=
200
;
minFontSize
=
15
;
// Find the word with the maximum percentage. I.e. the most popular word.
$
.
each
(
words
,
function
(
index
,
word
)
{
if
(
word
.
size
>
maxSize
)
{
maxSize
=
word
.
size
;
}
if
(
word
.
size
<
minSize
)
{
minSize
=
word
.
size
;
}
});
d3
.
layout
.
cloud
().
size
([
500
,
500
])
// Find the longest word, and calculate the scale appropriately. This is
.
words
(
words
)
// required so that even long words fit into the drawing area and are
.
rotate
(
function
()
{
// not simply discarded.
return
~~
(
Math
.
random
()
*
2
)
*
90
;
$
.
each
(
words
,
function
(
index
,
word
)
{
})
var
tempScaleFactor
=
1.0
,
.
font
(
'Impact'
)
size
=
((
word
.
size
/
maxSize
)
*
maxFontSize
);
.
fontSize
(
function
(
d
)
{
var
size
=
(
d
.
size
/
maxSize
)
*
100
;
size
=
size
>=
15
?
size
:
15
;
if
(
size
*
0.7
*
word
.
text
.
length
>
_this
.
width
)
{
tempScaleFactor
=
((
_this
.
width
/
word
.
text
.
length
)
/
0.7
)
/
size
;
}
return
size
;
if
(
scaleFactor
>
tempScaleFactor
)
{
})
scaleFactor
=
tempScaleFactor
;
.
on
(
'end'
,
draw
)
}
.
start
(
);
}
);
// End of executable code
.
// Update the maximum font size based on the longest word
.
return
;
maxFontSize
*=
scaleFactor
;
function
draw
(
words
)
{
// Generate the word cloud.
var
el
,
firstWord
=
false
;
d3
.
layout
.
cloud
().
size
([
this
.
width
,
this
.
height
])
.
words
(
words
)
.
rotate
(
function
()
{
return
~~
(
Math
.
random
()
*
2
)
*
90
;
})
.
font
(
'Impact'
)
.
fontSize
(
function
(
d
)
{
var
size
=
(
d
.
size
/
maxSize
)
*
maxFontSize
;
$
(
'#word_cloud_d3_'
+
_this
.
hash
).
remove
()
;
size
=
size
>=
minFontSize
?
size
:
minFontSize
;
el
=
$
(
return
size
;
'<div '
+
})
'id="'
+
'word_cloud_d3_'
+
_this
.
hash
+
'" '
+
.
on
(
'end'
,
function
(
words
,
bounds
)
{
'style="display: block; width: 500px; height: auto; margin-left: auto; margin-right: auto;" '
+
// Draw the word cloud.
'></div>'
_this
.
drawWordCloud
(
response
,
words
,
bounds
);
);
})
el
.
append
(
'<h3>Your words:</h3>'
);
.
start
();
};
// End-of: WordCloudMain.prototype.showWordCloud = function (response) {
/**
* @function drawWordCloud
*
* This function will be called when d3 has finished initing the state for our word cloud,
* and it is ready to hand off the process to the drawing routine. Basically set up everything
* necessary for the actual drwing of the words.
*
* @param {object} response The response from the server that contains the user's entered words
* along with all of the top words.
*
* @param {array} words An array of objects. Each object must have two properties. One property
* is 'text' (the actual word), and the other property is 'size' which represents the number that the
* word was enetered by the students.
*
* @param {array} bounds An array of two objects. First object is the top-left coordinates of the bounding
* box where all of the words fir, second object is the bottom-right coordinates of the bounding box. Each
* coordinate object contains two properties: 'x', and 'y'.
*/
WordCloudMain
.
prototype
.
drawWordCloud
=
function
(
response
,
words
,
bounds
)
{
var
firstWord
=
false
,
// The first word in the list of user enetered words does not get a leading comma.
fill
=
d3
.
scale
.
category20
(),
// Color words in different colors.
scale
=
bounds
?
Math
.
min
(
this
.
width
/
Math
.
abs
(
bounds
[
1
].
x
-
this
.
width
/
2
),
this
.
width
/
Math
.
abs
(
bounds
[
0
].
x
-
this
.
width
/
2
),
this
.
height
/
Math
.
abs
(
bounds
[
1
].
y
-
this
.
height
/
2
),
this
.
height
/
Math
.
abs
(
bounds
[
0
].
y
-
this
.
height
/
2
)
)
/
2
:
1
,
// Scale based on the bounding box of all the words.
studentWordsStr
=
''
;
// Get the user his entered words.
$
.
each
(
response
.
student_words
,
function
(
index
,
value
)
{
$
.
each
(
response
.
student_words
,
function
(
index
,
value
)
{
if
(
firstWord
===
false
)
{
if
(
firstWord
===
false
)
{
firstWord
=
true
;
firstWord
=
true
;
}
else
{
}
else
{
el
.
append
(
', '
)
;
studentWordsStr
+=
', '
;
}
}
el
.
append
(
index
+
': '
+
(
100.0
*
(
value
/
response
.
total_count
))
+
' %'
);
// For now we do not show the percentages for each word the user has enetered.
// el.append(index + ': ' + (100.0 * (value / response.total_count)) + ' %');
//
// Only show the words.
studentWordsStr
+=
'"'
+
index
+
'"'
;
});
});
el
.
append
(
'<br /><br /><h3>Overall number of words: '
+
response
.
total_count
+
'</h3><br />'
);
_this
.
wordCloudEl
.
append
(
el
);
d3
.
select
(
'#word_cloud_d3_'
+
_this
.
hash
).
append
(
'svg'
)
this
.
wordCloudEl
.
find
(
'.result_cloud_section'
).
addClass
(
'active'
);
.
attr
(
'width'
,
500
)
.
attr
(
'height'
,
500
)
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
();
// 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'
)
.
append
(
'g'
)
.
attr
(
'transform'
,
'translate(
190,250
)'
)
.
attr
(
'transform'
,
'translate(
'
+
(
0.5
*
this
.
width
)
+
','
+
(
0.5
*
this
.
height
)
+
'
)'
)
.
selectAll
(
'text'
)
.
selectAll
(
'text'
)
.
data
(
words
)
.
data
(
words
)
.
enter
().
append
(
'text'
)
.
enter
().
append
(
'text'
)
...
@@ -114,84 +257,14 @@ WordCloudMain.prototype = {
...
@@ -114,84 +257,14 @@ WordCloudMain.prototype = {
})
})
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'transform'
,
function
(
d
)
{
.
attr
(
'transform'
,
function
(
d
)
{
return
'translate('
+
[
d
.
x
,
d
.
y
]
+
')rotate('
+
d
.
rotate
+
')'
;
return
'translate('
+
[
d
.
x
,
d
.
y
]
+
')rotate('
+
d
.
rotate
+
')
scale('
+
scale
+
')
'
;
})
})
.
text
(
function
(
d
)
{
.
text
(
function
(
d
)
{
return
d
.
text
;
return
d
.
text
;
});
});
}
};
// End-of: WordCloudMain.prototype.drawWordCloud = function (words, bounds) {
}
};
// End-of: WordCloudMain.prototype = {
return
WordCloudMain
;
function
WordCloudMain
(
el
)
{
var
_this
=
this
;
this
.
wordCloudEl
=
$
(
el
).
find
(
'.word_cloud'
);
if
(
this
.
wordCloudEl
.
length
!==
1
)
{
// We require one question DOM element.
logme
(
'ERROR: WordCloudMain constructor requires one word cloud DOM element.'
);
return
;
}
// Later on used to create a unique DOM element.
hash
+=
1
;
this
.
hash
=
hash
;
// Get the URL to which we will post the users words.
this
.
ajax_url
=
this
.
wordCloudEl
.
data
(
'ajax-url'
);
// Hide WordCloud container before Ajax request done
this
.
wordCloudEl
.
hide
();
// Retriveing response from the server as an AJAX request. Attach a callback that will
// be fired on server's response.
$
.
postWithPrefix
(
_this
.
ajax_url
+
'/'
+
'get_state'
,
null
,
function
(
response
)
{
if
(
response
.
status
!==
'success'
)
{
logme
(
'ERROR: '
+
response
.
error
);
return
;
}
_this
.
configJson
=
response
;
}
)
.
done
(
function
(){
// Show WordCloud container after Ajax request done
_this
.
wordCloudEl
.
show
();
try
{
_this
.
configJson
=
_this
.
configJson
||
JSON
.
parse
(
_this
.
wordCloudEl
.
find
(
'.word_cloud_div'
).
html
());
}
catch
(
err
)
{
logme
(
'ERROR: Incorrect JSON config was given.'
);
logme
(
err
.
message
);
return
;
}
if
(
_this
.
configJson
.
submitted
)
{
return
WordCloudMain
;
_this
.
showWordCloud
(
_this
.
configJson
);
return
;
}
});
this
.
inputSaveEl
=
$
(
el
).
find
(
'input.save'
);
this
.
inputSaveEl
.
on
(
'click'
,
function
()
{
_this
.
submitAnswer
();
});
}
// End-of: function WordCloudMain(el) {
});
// End-of: define('WordCloudMain', ['logme'], function (logme) {
});
// End-of: define('WordCloudMain', ['logme'], function (logme) {
}(
RequireJS
.
requirejs
,
RequireJS
.
require
,
RequireJS
.
define
));
// End-of: (function (requirejs, require, define) {
// End-of: (function (requirejs, require, define) {
}(
RequireJS
.
requirejs
,
RequireJS
.
require
,
RequireJS
.
define
));
lms/templates/word_cloud.html
View file @
f4b247d2
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
data-ajax-url=
"${ajax_url}"
data-ajax-url=
"${ajax_url}"
>
>
<section
id=
"input-cloud-
section"
>
<section
class=
"input_cloud_
section"
>
% for row in range(num_inputs):
% for row in range(num_inputs):
<input
<input
class=
"input-cloud"
class=
"input-cloud"
...
@@ -19,7 +19,10 @@
...
@@ -19,7 +19,10 @@
</section>
</section>
</section>
</section>
<section
id=
"result-cloud-section"
style=
"display: none;"
>
<section
id=
"result_cloud_section_${element_id}"
class=
"result_cloud_section"
>
<h3>
Your words:
<span
class=
"your_words"
></span></h3>
<h3>
Total number of words:
<span
class=
"total_num_words"
></span></h3>
<div
class=
"word_cloud"
></div>
</section>
</section>
<!-- Hidden field to read configuration JSON from. -->
<!-- Hidden field to read configuration JSON from. -->
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment