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
bb9bc421
Commit
bb9bc421
authored
Apr 04, 2013
by
Alexander Kryklia
Committed by
Vasyl Nakvasiuk
May 13, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adds initial word_cloud_module files
parent
e5daeb41
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
557 additions
and
0 deletions
+557
-0
common/lib/xmodule/setup.py
+1
-0
common/lib/xmodule/xmodule/js/src/word_cloud/logme.js
+54
-0
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud.js
+323
-0
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
+5
-0
common/lib/xmodule/xmodule/word_cloud_module.py
+166
-0
lms/templates/word_cloud.html
+8
-0
No files found.
common/lib/xmodule/setup.py
View file @
bb9bc421
...
...
@@ -52,6 +52,7 @@ setup(
"graphical_slider_tool = xmodule.gst_module:GraphicalSliderToolDescriptor"
,
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor"
,
"foldit = xmodule.foldit_module:FolditDescriptor"
,
"word_cloud = xmodule.word_cloud_module:WordCloudDescriptor"
,
"hidden = xmodule.hidden_module:HiddenDescriptor"
,
"raw = xmodule.raw_module:RawDescriptor"
,
],
...
...
common/lib/xmodule/xmodule/js/src/word_cloud/logme.js
0 → 100644
View file @
bb9bc421
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
// define() functions from Require JS available inside the anonymous function.
(
function
(
requirejs
,
require
,
define
)
{
define
(
'logme'
,
[],
function
()
{
var
debugMode
;
// debugMode can be one of the following:
//
// true - All messages passed to logme will be written to the internal
// browser console.
// false - Suppress all output to the internal browser console.
//
// Obviously, if anywhere there is a direct console.log() call, we can't do
// anything about it. That's why use logme() - it will allow to turn off
// the output of debug information with a single change to a variable.
debugMode
=
true
;
return
logme
;
/*
* function: logme
*
* A helper function that provides logging facilities. We don't want
* to call console.log() directly, because sometimes it is not supported
* by the browser. Also when everything is routed through this function.
* the logging output can be easily turned off.
*
* logme() supports multiple parameters. Each parameter will be passed to
* console.log() function separately.
*
*/
function
logme
()
{
var
i
;
if
(
(
typeof
debugMode
===
'undefined'
)
||
(
debugMode
!==
true
)
||
(
typeof
window
.
console
===
'undefined'
)
)
{
return
;
}
for
(
i
=
0
;
i
<
arguments
.
length
;
i
++
)
{
window
.
console
.
log
(
arguments
[
i
]);
}
}
// End-of: function logme
});
// End of wrapper for RequireJS. As you can see, we are passing
// namespaced Require JS variables to an anonymous function. Within
// it, you can use the standard requirejs(), require(), and define()
// functions as if they were in the global namespace.
}(
RequireJS
.
requirejs
,
RequireJS
.
require
,
RequireJS
.
define
));
// End-of: (function (requirejs, require, define)
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud.js
0 → 100644
View file @
bb9bc421
(
function
(
requirejs
,
require
,
define
)
{
define
(
'PollMain'
,
[
'logme'
],
function
(
logme
)
{
PollMain
.
prototype
=
{
'showAnswerGraph'
:
function
(
poll_answers
,
total
)
{
var
_this
,
totalValue
;
totalValue
=
parseFloat
(
total
);
if
(
isFinite
(
totalValue
)
===
false
)
{
return
;
}
_this
=
this
;
$
.
each
(
poll_answers
,
function
(
index
,
value
)
{
var
numValue
,
percentValue
;
numValue
=
parseFloat
(
value
);
if
(
isFinite
(
numValue
)
===
false
)
{
return
;
}
percentValue
=
(
numValue
/
totalValue
)
*
100.0
;
_this
.
answersObj
[
index
].
statsEl
.
show
();
_this
.
answersObj
[
index
].
numberEl
.
html
(
''
+
value
+
' ('
+
percentValue
.
toFixed
(
1
)
+
'%)'
);
_this
.
answersObj
[
index
].
percentEl
.
css
({
'width'
:
''
+
percentValue
.
toFixed
(
1
)
+
'%'
});
});
},
'submitAnswer'
:
function
(
answer
,
answerObj
)
{
var
_this
;
// Make sure that the user can answer a question only once.
if
(
this
.
questionAnswered
===
true
)
{
return
;
}
this
.
questionAnswered
=
true
;
_this
=
this
;
console
.
log
(
'submit answer'
);
answerObj
.
buttonEl
.
addClass
(
'answered'
);
// 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
+
'/'
+
answer
,
{},
function
(
response
)
{
console
.
log
(
'success! response = '
);
console
.
log
(
response
);
_this
.
showAnswerGraph
(
response
.
poll_answers
,
response
.
total
);
if
(
_this
.
canReset
===
true
)
{
_this
.
resetButton
.
show
();
}
// Initialize Conditional constructors.
if
(
_this
.
wrapperSectionEl
!==
null
)
{
$
(
_this
.
wrapperSectionEl
).
find
(
'.xmodule_ConditionalModule'
).
each
(
function
(
index
,
value
)
{
new
window
.
Conditional
(
value
,
_this
.
id
.
replace
(
/^poll_/
,
''
));
});
}
}
);
},
// End-of: 'submitAnswer': function (answer, answerEl) {
'submitReset'
:
function
()
{
var
_this
;
_this
=
this
;
console
.
log
(
'submit reset'
);
// 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
+
'/'
+
'reset_poll'
,
{},
function
(
response
)
{
console
.
log
(
'success! response = '
);
console
.
log
(
response
);
if
(
(
response
.
hasOwnProperty
(
'status'
)
!==
true
)
||
(
typeof
response
.
status
!==
'string'
)
||
(
response
.
status
.
toLowerCase
()
!==
'success'
))
{
return
;
}
_this
.
questionAnswered
=
false
;
_this
.
questionEl
.
find
(
'.button.answered'
).
removeClass
(
'answered'
);
_this
.
questionEl
.
find
(
'.stats'
).
hide
();
_this
.
resetButton
.
hide
();
// Initialize Conditional constructors. We will specify the third parameter as 'true'
// notifying the constructor that this is a reset operation.
if
(
_this
.
wrapperSectionEl
!==
null
)
{
$
(
_this
.
wrapperSectionEl
).
find
(
'.xmodule_ConditionalModule'
).
each
(
function
(
index
,
value
)
{
new
window
.
Conditional
(
value
,
_this
.
id
.
replace
(
/^poll_/
,
''
));
});
}
}
);
},
// End-of: 'submitAnswer': function (answer, answerEl) {
'postInit'
:
function
()
{
var
_this
;
// Access this object inside inner functions.
_this
=
this
;
if
(
(
this
.
jsonConfig
.
poll_answer
.
length
>
0
)
&&
(
this
.
jsonConfig
.
answers
.
hasOwnProperty
(
this
.
jsonConfig
.
poll_answer
)
===
false
)
)
{
this
.
questionEl
.
append
(
'<h3>Error!</h3>'
+
'<p>XML data format changed. List of answers was modified, but poll data was not updated.</p>'
);
return
;
}
// Get the DOM id of the question.
this
.
id
=
this
.
questionEl
.
attr
(
'id'
);
// Get the URL to which we will post the users answer to the question.
this
.
ajax_url
=
this
.
questionEl
.
data
(
'ajax-url'
);
this
.
questionHtmlMarkup
=
$
(
'<div />'
).
html
(
this
.
jsonConfig
.
question
).
text
();
this
.
questionEl
.
append
(
this
.
questionHtmlMarkup
);
// When the user selects and answer, we will set this flag to true.
this
.
questionAnswered
=
false
;
this
.
answersObj
=
{};
this
.
shortVersion
=
true
;
$
.
each
(
this
.
jsonConfig
.
answers
,
function
(
index
,
value
)
{
if
(
value
.
length
>=
18
)
{
_this
.
shortVersion
=
false
;
}
});
$
.
each
(
this
.
jsonConfig
.
answers
,
function
(
index
,
value
)
{
var
answer
;
answer
=
{};
_this
.
answersObj
[
index
]
=
answer
;
answer
.
el
=
$
(
'<div class="poll_answer"></div>'
);
answer
.
questionEl
=
$
(
'<div class="question"></div>'
);
answer
.
buttonEl
=
$
(
'<div class="button"></div>'
);
answer
.
textEl
=
$
(
'<div class="text"></div>'
);
answer
.
questionEl
.
append
(
answer
.
buttonEl
);
answer
.
questionEl
.
append
(
answer
.
textEl
);
answer
.
el
.
append
(
answer
.
questionEl
);
answer
.
statsEl
=
$
(
'<div class="stats"></div>'
);
answer
.
barEl
=
$
(
'<div class="bar"></div>'
);
answer
.
percentEl
=
$
(
'<div class="percent"></div>'
);
answer
.
barEl
.
append
(
answer
.
percentEl
);
answer
.
numberEl
=
$
(
'<div class="number"></div>'
);
answer
.
statsEl
.
append
(
answer
.
barEl
);
answer
.
statsEl
.
append
(
answer
.
numberEl
);
answer
.
statsEl
.
hide
();
answer
.
el
.
append
(
answer
.
statsEl
);
answer
.
textEl
.
html
(
value
);
if
(
_this
.
shortVersion
===
true
)
{
$
.
each
(
answer
,
function
(
index
,
value
)
{
if
(
value
instanceof
jQuery
)
{
value
.
addClass
(
'short'
);
}
});
}
answer
.
el
.
appendTo
(
_this
.
questionEl
);
answer
.
textEl
.
on
(
'click'
,
function
()
{
_this
.
submitAnswer
(
index
,
answer
);
});
answer
.
buttonEl
.
on
(
'click'
,
function
()
{
_this
.
submitAnswer
(
index
,
answer
);
});
if
(
index
===
_this
.
jsonConfig
.
poll_answer
)
{
answer
.
buttonEl
.
addClass
(
'answered'
);
_this
.
questionAnswered
=
true
;
}
});
console
.
log
(
this
.
jsonConfig
.
reset
);
if
((
typeof
this
.
jsonConfig
.
reset
===
'string'
)
&&
(
this
.
jsonConfig
.
reset
.
toLowerCase
()
===
'true'
))
{
this
.
canReset
=
true
;
this
.
resetButton
=
$
(
'<div class="button reset-button">Change your vote</div>'
);
if
(
this
.
questionAnswered
===
false
)
{
this
.
resetButton
.
hide
();
}
this
.
resetButton
.
appendTo
(
this
.
questionEl
);
this
.
resetButton
.
on
(
'click'
,
function
()
{
_this
.
submitReset
();
});
}
else
{
this
.
canReset
=
false
;
}
// If it turns out that the user already answered the question, show the answers graph.
if
(
this
.
questionAnswered
===
true
)
{
this
.
showAnswerGraph
(
this
.
jsonConfig
.
poll_answers
,
this
.
jsonConfig
.
total
);
}
}
// End-of: 'postInit': function () {
};
// End-of: PollMain.prototype = {
return
PollMain
;
function
PollMain
(
el
)
{
var
_this
;
this
.
questionEl
=
$
(
el
).
find
(
'.poll_question'
);
if
(
this
.
questionEl
.
length
!==
1
)
{
// We require one question DOM element.
logme
(
'ERROR: PollMain constructor requires one question DOM element.'
);
return
;
}
// Just a safety precussion. If we run this code more than once, multiple 'click' callback handlers will be
// attached to the same DOM elements. We don't want this to happen.
if
(
this
.
questionEl
.
attr
(
'poll_main_processed'
)
===
'true'
)
{
logme
(
'ERROR: PolMain JS constructor was called on a DOM element that has already been processed once.'
);
return
;
}
// This element was not processed earlier.
// Make sure that next time we will not process this element a second time.
this
.
questionEl
.
attr
(
'poll_main_processed'
,
'true'
);
// Access this object inside inner functions.
_this
=
this
;
// DOM element which contains the current poll along with any conditionals. By default we assume that such
// element is not present. We will try to find it.
this
.
wrapperSectionEl
=
null
;
(
function
(
tempEl
,
c1
)
{
while
(
tempEl
.
tagName
.
toLowerCase
()
!==
'body'
)
{
tempEl
=
$
(
tempEl
).
parent
()[
0
];
c1
+=
1
;
if
(
(
tempEl
.
tagName
.
toLowerCase
()
===
'section'
)
&&
(
$
(
tempEl
).
hasClass
(
'xmodule_WrapperModule'
)
===
true
)
)
{
_this
.
wrapperSectionEl
=
tempEl
;
break
;
}
else
if
(
c1
>
50
)
{
// In case something breaks, and we enter an endless loop, a sane
// limit for loop iterations.
break
;
}
}
}(
$
(
el
)[
0
],
0
));
try
{
this
.
jsonConfig
=
JSON
.
parse
(
this
.
questionEl
.
children
(
'.poll_question_div'
).
html
());
$
.
postWithPrefix
(
''
+
this
.
questionEl
.
data
(
'ajax-url'
)
+
'/'
+
'get_state'
,
{},
function
(
response
)
{
_this
.
jsonConfig
.
poll_answer
=
response
.
poll_answer
;
_this
.
jsonConfig
.
total
=
response
.
total
;
$
.
each
(
response
.
poll_answers
,
function
(
index
,
value
)
{
_this
.
jsonConfig
.
poll_answers
[
index
]
=
value
;
});
_this
.
questionEl
.
children
(
'.poll_question_div'
).
html
(
JSON
.
stringify
(
_this
.
jsonConfig
));
_this
.
postInit
();
}
);
return
;
}
catch
(
err
)
{
logme
(
'ERROR: Invalid JSON config for poll ID "'
+
this
.
id
+
'".'
,
'Error messsage: "'
+
err
.
message
+
'".'
);
return
;
}
}
// End-of: function PollMain(el) {
});
// End-of: define('PollMain', ['logme'], function (logme) {
// End-of: (function (requirejs, require, define) {
}(
RequireJS
.
requirejs
,
RequireJS
.
require
,
RequireJS
.
define
));
common/lib/xmodule/xmodule/js/src/word_cloud/word_cloud_main.js
0 → 100644
View file @
bb9bc421
window
.
Poll
=
function
(
el
)
{
RequireJS
.
require
([
'PollMain'
],
function
(
PollMain
)
{
new
PollMain
(
el
);
});
};
common/lib/xmodule/xmodule/word_cloud_module.py
0 → 100644
View file @
bb9bc421
"""Word cloud is ungraded xblock used by students to
generate and view word cloud..
On the client side we show:
If student does not yet anwered - five text inputs.
If student have answered - words he entered and cloud.
Stunent can change his answer.
"""
import
cgi
import
json
import
logging
from
copy
import
deepcopy
from
collections
import
OrderedDict
from
lxml
import
etree
from
pkg_resources
import
resource_string
from
xmodule.x_module
import
XModule
from
xmodule.stringify
import
stringify_children
from
xmodule.mako_module
import
MakoModuleDescriptor
from
xmodule.xml_module
import
XmlDescriptor
from
xblock.core
import
Scope
,
String
,
Object
,
Boolean
,
List
log
=
logging
.
getLogger
(
__name__
)
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
)
submitted
=
Boolean
(
help
=
"Whether this student has voted on the poll"
,
scope
=
Scope
.
student_state
,
default
=
False
)
student_words
=
List
(
help
=
"Student answer"
,
scope
=
Scope
.
student_state
,
default
=
[])
all_words
=
Object
(
help
=
"All possible words from other students"
,
scope
=
Scope
.
content
)
top_words
=
Object
(
help
=
"Top N words for word cloud"
,
scope
=
Scope
.
content
)
top_low_border
=
Int
(
help
=
"Number to distinguish top from all words"
,
scope
=
Scope
.
content
)
class
WordCloudModule
(
WordCloudFields
,
XModule
):
"""WordCloud Module"""
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/javascript_loader.coffee'
)],
'js'
:
[
resource_string
(
__name__
,
'js/src/word_cloud/logme.js'
),
resource_string
(
__name__
,
'js/src/word_cloud/word_cloud.js'
),
resource_string
(
__name__
,
'js/src/word_cloud/word_cloud_main.js'
)]
}
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/word_cloud/display.scss'
)]}
js_module_name
=
"Word_Cloud"
Number_of_top_words
=
250
def
handle_ajax
(
self
,
dispatch
,
get
):
"""Ajax handler.
Args:
dispatch: string request slug
get: dict request get parameters
Returns:
json string
"""
if
dispatch
==
'submit'
:
# self.all_words[word] -= 1
# FIXME: fix this, when xblock will support mutable types.
# Now we use this hack.
# speed issues
temp_all_words
=
self
.
all_words
temp_top_words
=
self
.
top_words
if
self
.
submitted
:
for
word
in
self
.
student_words
:
temp_all_words
[
word
]
-=
1
if
word
in
temp_top_words
:
temp_top_words
-=
1
else
:
self
.
submitted
=
True
self
.
student_words
=
get
[
'student_words'
]
question_words
=
{}
for
word
in
self
.
student_words
:
temp_all_words
[
word
]
+=
1
if
word
in
temp_top_words
:
temp_top_words
+=
1
else
:
if
temp_all_words
[
word
]
>
top_low_border
:
question_words
[
word
]
=
temp_all_words
[
word
]
self
.
all_words
=
temp_all_words
self
.
top_words
=
self
.
update_top_words
(
question_words
,
temp_top_words
)
return
json
.
dumps
({
'student_words'
:
self
.
student_words
,
'top_words'
:
self
.
top_words
,
})
elif
dispatch
==
'get_state'
:
return
json
.
dumps
({
'student_answers'
:
self
.
student_answers
,
'top_words'
:
self
.
top_words
)
})
else
:
# return error message
return
json
.
dumps
({
'error'
:
'Unknown Command!'
})
def
update_top_words
(
question_words
,
top_words
):
for
word
,
number
in
question_words
:
for
top_word
,
top_number
in
top_words
[:]:
if
top_number
<
number
:
del
top_words
[
top_word
]
top_words
[
word
]
-
number
break
return
top_words
def
get_html
(
self
):
"""Renders parameters to template."""
params
=
{
'element_id'
:
self
.
location
.
html_id
(),
'element_class'
:
self
.
location
.
category
,
'ajax_url'
:
self
.
system
.
ajax_url
,
'configuration_json'
:
json
.
dumps
({}),
}
self
.
content
=
self
.
system
.
render_template
(
'word_cloud.html'
,
params
)
return
self
.
content
class
WordCloudDescriptor
(
WordCloudFields
,
MakoModuleDescriptor
,
XmlDescriptor
):
_tag_name
=
'word_cloud'
module_class
=
WordCloudModule
template_dir_name
=
'word_cloud'
stores_state
=
True
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
"""Pull out the data into dictionary.
Args:
xml_object: xml from file.
system: `system` object.
Returns:
(definition, children) - tuple
"""
definition
=
{}
children
=
[]
return
(
definition
,
children
)
def
definition_to_xml
(
self
,
resource_fs
):
"""Return an xml element representing to this definition."""
poll_str
=
'<{tag_name}/>'
.
format
(
tag_name
=
self
.
_tag_name
)
xml_object
=
etree
.
fromstring
(
poll_str
)
xml_object
.
set
(
'display_name'
,
self
.
display_name
)
return
xml_object
lms/templates/word_cloud.html
0 → 100644
View file @
bb9bc421
<section
id=
"poll_${element_id}"
class=
"${element_class}"
data-ajax-url=
"${ajax_url}"
>
<!-- Hidden field to read configuration JSON from. -->
<div
class=
"${element_class}_div"
id=
"${element_id}_json"
style=
"display: none;"
>
${configuration_json}
</div>
</section>
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