diff --git a/common/lib/xmodule/xmodule/js/src/sequence/display.js b/common/lib/xmodule/xmodule/js/src/sequence/display.js
index 5cf9653c05..899c7bcc20 100644
--- a/common/lib/xmodule/xmodule/js/src/sequence/display.js
+++ b/common/lib/xmodule/xmodule/js/src/sequence/display.js
@@ -1,288 +1,463 @@
-class @Sequence
- constructor: (element) ->
- @updatedProblems = {}
- @requestToken = $(element).data('request-token')
- @el = $(element).find('.sequence')
- @path = $('.path')
- @contents = @$('.seq_contents')
- @content_container = @$('#seq_content')
- @sr_container = @$('.sr-is-focusable')
- @num_contents = @contents.length
- @id = @el.data('id')
- @ajaxUrl = @el.data('ajax-url')
- @nextUrl = @el.data('next-url')
- @prevUrl = @el.data('prev-url')
- @base_page_title = " | " + document.title
- @initProgress()
- @bind()
- @render parseInt(@el.data('position'))
+// Generated by CoffeeScript 1.6.1
+(function() {
+ var _this = this;
- $: (selector) ->
- $(selector, @el)
+ this.Sequence = (function() {
- bind: ->
- @$('#sequence-list .nav-item').click @goto
- @el.on 'bookmark:add', @addBookmarkIconToActiveNavItem
- @el.on 'bookmark:remove', @removeBookmarkIconFromActiveNavItem
- @$('#sequence-list .nav-item').on('focus mouseenter', @displayTabTooltip)
- @$('#sequence-list .nav-item').on('blur mouseleave', @hideTabTooltip)
+ function Sequence(element) {
+ var _this = this;
+ this.removeBookmarkIconFromActiveNavItem = function(event) {
+ return Sequence.prototype.removeBookmarkIconFromActiveNavItem.apply(_this, arguments);
+ };
+ this.addBookmarkIconToActiveNavItem = function(event) {
+ return Sequence.prototype.addBookmarkIconToActiveNavItem.apply(_this, arguments);
+ };
+ this._change_sequential = function(direction, event) {
+ return Sequence.prototype._change_sequential.apply(_this, arguments);
+ };
+ this.selectPrevious = function(event) {
+ return Sequence.prototype.selectPrevious.apply(_this, arguments);
+ };
+ this.selectNext = function(event) {
+ return Sequence.prototype.selectNext.apply(_this, arguments);
+ };
+ this.goto = function(event) {
+ return Sequence.prototype.goto.apply(_this, arguments);
+ };
+ this.toggleArrows = function() {
+ return Sequence.prototype.toggleArrows.apply(_this, arguments);
+ };
+ this.updateProgress = function() {
+ return Sequence.prototype.updateProgress.apply(_this, arguments);
+ };
+ this.addToUpdatedProblems = function(problem_id, new_content_state, new_state) {
+ return Sequence.prototype.addToUpdatedProblems.apply(_this, arguments);
+ };
+ this.hideTabTooltip = function(event) {
+ return Sequence.prototype.hideTabTooltip.apply(_this, arguments);
+ };
+ this.displayTabTooltip = function(event) {
+ return Sequence.prototype.displayTabTooltip.apply(_this, arguments);
+ };
+ this.updatedProblems = {};
+ this.requestToken = $(element).data('request-token');
+ this.el = $(element).find('.sequence');
+ this.path = $('.path');
+ this.contents = this.$('.seq_contents');
+ this.content_container = this.$('#seq_content');
+ this.sr_container = this.$('.sr-is-focusable');
+ this.num_contents = this.contents.length;
+ this.id = this.el.data('id');
+ this.ajaxUrl = this.el.data('ajax-url');
+ this.nextUrl = this.el.data('next-url');
+ this.prevUrl = this.el.data('prev-url');
+ this.base_page_title = " | " + document.title;
+ this.initProgress();
+ this.bind();
+ this.render(parseInt(this.el.data('position')));
+ }
- displayTabTooltip: (event) =>
- $(event.currentTarget).find('.sequence-tooltip').removeClass('sr')
+ Sequence.prototype.$ = function(selector) {
+ return $(selector, this.el);
+ };
- hideTabTooltip: (event) =>
- $(event.currentTarget).find('.sequence-tooltip').addClass('sr')
+ Sequence.prototype.bind = function() {
+ this.$('#sequence-list .nav-item').click(this.goto);
+ this.el.on('bookmark:add', this.addBookmarkIconToActiveNavItem);
+ this.el.on('bookmark:remove', this.removeBookmarkIconFromActiveNavItem);
+ this.$('#sequence-list .nav-item').on('focus mouseenter', this.displayTabTooltip);
+ return this.$('#sequence-list .nav-item').on('blur mouseleave', this.hideTabTooltip);
+ };
- initProgress: ->
- @progressTable = {} # "#problem_#{id}" -> progress
+ Sequence.prototype.displayTabTooltip = function(event) {
+ return $(event.currentTarget).find('.sequence-tooltip').removeClass('sr');
+ };
- updatePageTitle: ->
- # update the page title to include the current section
- position_link = @link_for(@position)
- if position_link and position_link.data('page-title')
- document.title = position_link.data('page-title') + @base_page_title
+ Sequence.prototype.hideTabTooltip = function(event) {
+ return $(event.currentTarget).find('.sequence-tooltip').addClass('sr');
+ };
- hookUpContentStateChangeEvent: ->
- $('.problems-wrapper').bind(
- 'contentChanged',
- (event, problem_id, new_content_state, new_state) =>
- @addToUpdatedProblems problem_id, new_content_state, new_state
- )
+ Sequence.prototype.initProgress = function() {
+ /*
+ "#problem_#{id}" -> progress
+ */
+ return this.progressTable = {};
+ };
- addToUpdatedProblems: (problem_id, new_content_state, new_state) =>
- # Used to keep updated problem's state temporarily.
- # params:
- # 'problem_id' is problem id.
- # 'new_content_state' is the updated content of the problem.
- # 'new_state' is the updated state of the problem.
+ Sequence.prototype.updatePageTitle = function() {
+ /*
+ update the page title to include the current section
+ */
- # initialize for the current sequence if there isn't any updated problem
- # for this position.
- if not @anyUpdatedProblems @position
- @updatedProblems[@position] = {}
+ var position_link;
+ position_link = this.link_for(this.position);
+ if (position_link && position_link.data('page-title')) {
+ return document.title = position_link.data('page-title') + this.base_page_title;
+ }
+ };
- # Now, put problem content and score against problem id for current active sequence.
- @updatedProblems[@position][problem_id] = [new_content_state, new_state]
+ Sequence.prototype.hookUpContentStateChangeEvent = function() {
+ var _this = this;
+ return $('.problems-wrapper').bind('contentChanged', function(event, problem_id, new_content_state, new_state) {
+ return _this.addToUpdatedProblems(problem_id, new_content_state, new_state);
+ });
+ };
- anyUpdatedProblems:(position) ->
- # check for the updated problems for given sequence position.
- # params:
- # 'position' can be any sequence position.
- return @updatedProblems[position] != undefined
+ Sequence.prototype.addToUpdatedProblems = function(problem_id, new_content_state, new_state) {
+ /*
+ Used to keep updated problem's state temporarily.
+ */
- hookUpProgressEvent: ->
- $('.problems-wrapper').bind 'progressChanged', @updateProgress
+ /*
+ params:
+ */
- mergeProgress: (p1, p2) ->
- # if either is "NA", return the other one
- if p1 == "NA"
- return p2
- if p2 == "NA"
- return p1
+ /*
+ 'problem_id' is problem id.
+ */
- # Both real progresses
- if p1 == "done" and p2 == "done"
- return "done"
+ /*
+ 'new_content_state' is the updated content of the problem.
+ */
- # not done, so if any progress on either, in_progress
- w1 = p1 == "done" or p1 == "in_progress"
- w2 = p2 == "done" or p2 == "in_progress"
- if w1 or w2
- return "in_progress"
+ /*
+ 'new_state' is the updated state of the problem.
+ */
- return "none"
+ /*
+ initialize for the current sequence if there isn't any updated problem
+ */
- updateProgress: =>
- new_progress = "NA"
- _this = this
- $('.problems-wrapper').each (index) ->
- progress = $(this).data 'progress_status'
- new_progress = _this.mergeProgress progress, new_progress
+ /*
+ for this position.
+ */
+ if (!this.anyUpdatedProblems(this.position)) {
+ this.updatedProblems[this.position] = {};
+ }
+ /*
+ Now, put problem content and score against problem id for current active sequence.
+ */
- @progressTable[@position] = new_progress
+ return this.updatedProblems[this.position][problem_id] = [new_content_state, new_state];
+ };
- enableButton: (button_class, button_action) ->
- @$(button_class).removeClass('disabled').removeAttr('disabled').click(button_action)
+ Sequence.prototype.anyUpdatedProblems = function(position) {
+ /*
+ check for the updated problems for given sequence position.
+ */
- disableButton: (button_class) ->
- @$(button_class).addClass('disabled').attr('disabled', true)
+ /*
+ params:
+ */
- setButtonLabel: (button_class, button_label) ->
- @$(button_class + ' .sr').html(button_label)
+ /*
+ 'position' can be any sequence position.
+ */
+ return this.updatedProblems[position] !== void 0;
+ };
- updateButtonState: (button_class, button_action, action_label_prefix, is_at_boundary, boundary_url) ->
- if is_at_boundary and boundary_url == 'None'
- @disableButton(button_class)
- else
- button_label = action_label_prefix + (if is_at_boundary then ' Subsection' else ' Unit')
- @setButtonLabel(button_class, button_label)
- @enableButton(button_class, button_action)
+ Sequence.prototype.hookUpProgressEvent = function() {
+ return $('.problems-wrapper').bind('progressChanged', this.updateProgress);
+ };
- toggleArrows: =>
- @$('.sequence-nav-button').unbind('click')
+ Sequence.prototype.mergeProgress = function(p1, p2) {
+ /*
+ if either is "NA", return the other one
+ */
- # previous button
- is_first_tab = @position == 1
- previous_button_class = '.sequence-nav-button.button-previous'
- @updateButtonState(
- previous_button_class,
- @selectPrevious,
- 'Previous',
- is_first_tab,
- @prevUrl
- )
+ var w1, w2;
+ if (p1 === "NA") {
+ return p2;
+ }
+ if (p2 === "NA") {
+ return p1;
+ }
+ /*
+ Both real progresses
+ */
- # next button
- is_last_tab = @position >= @contents.length # use inequality in case contents.length is 0 and position is 1.
- next_button_class = '.sequence-nav-button.button-next'
- @updateButtonState(
- next_button_class,
- @selectNext,
- 'Next',
- is_last_tab,
- @nextUrl
- )
+ if (p1 === "done" && p2 === "done") {
+ return "done";
+ }
+ /*
+ not done, so if any progress on either, in_progress
+ */
- render: (new_position) ->
- if @position != new_position
- if @position != undefined
- @mark_visited @position
- modx_full_url = "#{@ajaxUrl}/goto_position"
- $.postWithPrefix modx_full_url, position: new_position
+ w1 = p1 === "done" || p1 === "in_progress";
+ w2 = p2 === "done" || p2 === "in_progress";
+ if (w1 || w2) {
+ return "in_progress";
+ }
+ return "none";
+ };
- # On Sequence change, fire custom event "sequence:change" on element.
- # Added for aborting video bufferization, see ../video/10_main.js
- @el.trigger "sequence:change"
- @mark_active new_position
+ Sequence.prototype.updateProgress = function() {
+ var new_progress;
+ new_progress = "NA";
+ _this = this;
+ $('.problems-wrapper').each(function(index) {
+ var progress;
+ progress = $(this).data('progress_status');
+ return new_progress = _this.mergeProgress(progress, new_progress);
+ });
+ return this.progressTable[this.position] = new_progress;
+ };
- current_tab = @contents.eq(new_position - 1)
+ Sequence.prototype.enableButton = function(button_class, button_action) {
+ return this.$(button_class).removeClass('disabled').removeAttr('disabled').click(button_action);
+ };
- bookmarked = if @el.find('.active .bookmark-icon').hasClass('bookmarked') then true else false
- @content_container.html(current_tab.text()).attr("aria-labelledby", current_tab.attr("aria-labelledby")).data('bookmarked', bookmarked)
+ Sequence.prototype.disableButton = function(button_class) {
+ return this.$(button_class).addClass('disabled').attr('disabled', true);
+ };
- # update the data-attributes with latest contents only for updated problems.
- if @anyUpdatedProblems new_position
- $.each @updatedProblems[new_position], (problem_id, latest_data) =>
- latest_content = latest_data[0]
- latest_response = latest_data[1]
- @content_container
- .find("[data-problem-id='#{ problem_id }']")
- .data('content', latest_content)
- .data('problem-score', latest_response.current_score)
- .data('problem-total-possible', latest_response.total_possible)
- .data('attempts-used', latest_response.attempts_used)
+ Sequence.prototype.setButtonLabel = function(button_class, button_label) {
+ return this.$(button_class + ' .sr').html(button_label);
+ };
- XBlock.initializeBlocks(@content_container, @requestToken)
+ Sequence.prototype.updateButtonState = function(button_class, button_action, action_label_prefix, is_at_boundary, boundary_url) {
+ var button_label;
+ if (is_at_boundary && boundary_url === 'None') {
+ return this.disableButton(button_class);
+ } else {
+ button_label = action_label_prefix + (is_at_boundary ? ' Subsection' : ' Unit');
+ this.setButtonLabel(button_class, button_label);
+ return this.enableButton(button_class, button_action);
+ }
+ };
- window.update_schematics() # For embedded circuit simulator exercises in 6.002x
+ Sequence.prototype.toggleArrows = function() {
+ var is_first_tab, is_last_tab, next_button_class, previous_button_class;
+ this.$('.sequence-nav-button').unbind('click');
+ /*
+ previous button
+ */
- @position = new_position
- @toggleArrows()
- @hookUpContentStateChangeEvent()
- @hookUpProgressEvent()
- @updatePageTitle()
+ is_first_tab = this.position === 1;
+ previous_button_class = '.sequence-nav-button.button-previous';
+ this.updateButtonState(previous_button_class, this.selectPrevious, 'Previous', is_first_tab, this.prevUrl);
+ /*
+ next button
+ */
- sequence_links = @content_container.find('a.seqnav')
- sequence_links.click @goto
+ /*
+ use inequality in case contents.length is 0 and position is 1.
+ */
- @path.text(@el.find('.nav-item.active').data('path'))
+ is_last_tab = this.position >= this.contents.length;
+ next_button_class = '.sequence-nav-button.button-next';
+ return this.updateButtonState(next_button_class, this.selectNext, 'Next', is_last_tab, this.nextUrl);
+ };
- @sr_container.focus()
+ Sequence.prototype.render = function(new_position) {
+ var bookmarked, current_tab, modx_full_url, sequence_links,
+ _this = this;
+ if (this.position !== new_position) {
+ if (this.position !== void 0) {
+ this.mark_visited(this.position);
+ modx_full_url = "" + this.ajaxUrl + "/goto_position";
+ $.postWithPrefix(modx_full_url, {
+ position: new_position
+ });
+ }
+ /*
+ On Sequence change, fire custom event "sequence:change" on element.
+ */
- goto: (event) =>
- event.preventDefault()
- if $(event.currentTarget).hasClass 'seqnav' # Links from courseware ..., was .target
- new_position = $(event.currentTarget).attr('href')
- else # Tab links generated by backend template
- new_position = $(event.currentTarget).data('element')
+ /*
+ Added for aborting video bufferization, see ../video/10_main.js
+ */
- if (1 <= new_position) and (new_position <= @num_contents)
- is_bottom_nav = $(event.target).closest('nav[class="sequence-bottom"]').length > 0
- if is_bottom_nav
- widget_placement = 'bottom'
- else
- widget_placement = 'top'
- Logger.log "edx.ui.lms.sequence.tab_selected", # Formerly known as seq_goto
- current_tab: @position
- target_tab: new_position
- tab_count: @num_contents
- id: @id
+ this.el.trigger("sequence:change");
+ this.mark_active(new_position);
+ current_tab = this.contents.eq(new_position - 1);
+ bookmarked = this.el.find('.active .bookmark-icon').hasClass('bookmarked') ? true : false;
+ this.content_container.html(current_tab.text()).attr("aria-labelledby", current_tab.attr("aria-labelledby")).data('bookmarked', bookmarked);
+ /*
+ update the data-attributes with latest contents only for updated problems.
+ */
+
+ if (this.anyUpdatedProblems(new_position)) {
+ $.each(this.updatedProblems[new_position], function(problem_id, latest_data) {
+ var latest_content, latest_response;
+ latest_content = latest_data[0];
+ latest_response = latest_data[1];
+ return _this.content_container.find("[data-problem-id='" + problem_id + "']").data('content', latest_content).data('problem-score', latest_response.current_score).data('problem-total-possible', latest_response.total_possible).data('attempts-used', latest_response.attempts_used);
+ });
+ }
+ XBlock.initializeBlocks(this.content_container, this.requestToken);
+ /*
+ For embedded circuit simulator exercises in 6.002x
+ */
+
+ window.update_schematics();
+ this.position = new_position;
+ this.toggleArrows();
+ this.hookUpContentStateChangeEvent();
+ this.hookUpProgressEvent();
+ this.updatePageTitle();
+ sequence_links = this.content_container.find('a.seqnav');
+ sequence_links.click(this.goto);
+ this.path.text(this.el.find('.nav-item.active').data('path'));
+ return this.sr_container.focus();
+ }
+ };
+
+ Sequence.prototype.goto = function(event) {
+ var alert_template, alert_text, is_bottom_nav, new_position, widget_placement;
+ event.preventDefault();
+ /*
+ Links from courseware ..., was .target
+ */
+
+ if ($(event.currentTarget).hasClass('seqnav')) {
+ new_position = $(event.currentTarget).attr('href');
+ /*
+ Tab links generated by backend template
+ */
+
+ } else {
+ new_position = $(event.currentTarget).data('element');
+ }
+ if ((1 <= new_position) && (new_position <= this.num_contents)) {
+ is_bottom_nav = $(event.target).closest('nav[class="sequence-bottom"]').length > 0;
+ if (is_bottom_nav) {
+ widget_placement = 'bottom';
+ } else {
+ widget_placement = 'top';
+ }
+ /*
+ Formerly known as seq_goto
+ */
+
+ Logger.log("edx.ui.lms.sequence.tab_selected", {
+ current_tab: this.position,
+ target_tab: new_position,
+ tab_count: this.num_contents,
+ id: this.id,
+ widget_placement: widget_placement
+ });
+ /*
+ On Sequence change, destroy any existing polling thread
+ */
+
+ /*
+ for queued submissions, see ../capa/display.js
+ */
+
+ if (window.queuePollerID) {
+ window.clearTimeout(window.queuePollerID);
+ delete window.queuePollerID;
+ }
+ return this.render(new_position);
+ } else {
+ alert_template = gettext("Sequence error! Cannot navigate to %(tab_name)s in the current SequenceModule. Please contact the course staff.");
+ alert_text = interpolate(alert_template, {
+ tab_name: new_position
+ }, true);
+ return alert(alert_text);
+ }
+ };
+
+ Sequence.prototype.selectNext = function(event) {
+ return this._change_sequential('next', event);
+ };
+
+ Sequence.prototype.selectPrevious = function(event) {
+ return this._change_sequential('previous', event);
+ };
+
+ /*
+ `direction` can be 'previous' or 'next'
+ */
+
+
+ Sequence.prototype._change_sequential = function(direction, event) {
+ /*
+ silently abort if direction is invalid.
+ */
+
+ var analytics_event_name, is_bottom_nav, new_position, offset, widget_placement;
+ if (direction !== 'previous' && direction !== 'next') {
+ return;
+ }
+ event.preventDefault();
+ analytics_event_name = "edx.ui.lms.sequence." + direction + "_selected";
+ is_bottom_nav = $(event.target).closest('nav[class="sequence-bottom"]').length > 0;
+ if (is_bottom_nav) {
+ widget_placement = 'bottom';
+ } else {
+ widget_placement = 'top';
+ }
+ /*
+ Formerly known as seq_next and seq_prev
+ */
+
+ Logger.log(analytics_event_name, {
+ id: this.id,
+ current_tab: this.position,
+ tab_count: this.num_contents,
widget_placement: widget_placement
+ });
+ if ((direction === 'next') && (this.position >= this.contents.length)) {
+ return window.location.href = this.nextUrl;
+ } else if ((direction === 'previous') && (this.position === 1)) {
+ return window.location.href = this.prevUrl;
+ } else {
+ /*
+ If the bottom nav is used, scroll to the top of the page on change.
+ */
- # On Sequence change, destroy any existing polling thread
- # for queued submissions, see ../capa/display.js
- if window.queuePollerID
- window.clearTimeout(window.queuePollerID)
- delete window.queuePollerID
+ if (is_bottom_nav) {
+ $.scrollTo(0, 150);
+ }
+ offset = {
+ next: 1,
+ previous: -1
+ };
+ new_position = this.position + offset[direction];
+ return this.render(new_position);
+ }
+ };
- @render new_position
- else
- alert_template = gettext("Sequence error! Cannot navigate to %(tab_name)s in the current SequenceModule. Please contact the course staff.")
- alert_text = interpolate(alert_template, {tab_name: new_position}, true)
- alert alert_text
+ Sequence.prototype.link_for = function(position) {
+ return this.$("#sequence-list .nav-item[data-element=" + position + "]");
+ };
- selectNext: (event) => @_change_sequential 'next', event
+ Sequence.prototype.mark_visited = function(position) {
+ /*
+ Don't overwrite class attribute to avoid changing Progress class
+ */
- selectPrevious: (event) => @_change_sequential 'previous', event
+ var element;
+ element = this.link_for(position);
+ return element.removeClass("inactive").removeClass("active").addClass("visited");
+ };
- # `direction` can be 'previous' or 'next'
- _change_sequential: (direction, event) =>
- # silently abort if direction is invalid.
- return unless direction in ['previous', 'next']
+ Sequence.prototype.mark_active = function(position) {
+ /*
+ Don't overwrite class attribute to avoid changing Progress class
+ */
- event.preventDefault()
+ var element;
+ element = this.link_for(position);
+ return element.removeClass("inactive").removeClass("visited").addClass("active");
+ };
- analytics_event_name = "edx.ui.lms.sequence.#{direction}_selected"
- is_bottom_nav = $(event.target).closest('nav[class="sequence-bottom"]').length > 0
+ Sequence.prototype.addBookmarkIconToActiveNavItem = function(event) {
+ event.preventDefault();
+ this.el.find('.nav-item.active .bookmark-icon').removeClass('is-hidden').addClass('bookmarked');
+ return this.el.find('.nav-item.active .bookmark-icon-sr').text(gettext('Bookmarked'));
+ };
- if is_bottom_nav
- widget_placement = 'bottom'
- else
- widget_placement = 'top'
+ Sequence.prototype.removeBookmarkIconFromActiveNavItem = function(event) {
+ event.preventDefault();
+ this.el.find('.nav-item.active .bookmark-icon').removeClass('bookmarked').addClass('is-hidden');
+ return this.el.find('.nav-item.active .bookmark-icon-sr').text('');
+ };
- Logger.log analytics_event_name, # Formerly known as seq_next and seq_prev
- id: @id
- current_tab: @position
- tab_count: @num_contents
- widget_placement: widget_placement
+ return Sequence;
- if (direction == 'next') and (@position >= @contents.length)
- window.location.href = @nextUrl
- else if (direction == 'previous') and (@position == 1)
- window.location.href = @prevUrl
- else
- # If the bottom nav is used, scroll to the top of the page on change.
- if is_bottom_nav
- $.scrollTo 0, 150
- offset =
- next: 1
- previous: -1
- new_position = @position + offset[direction]
- @render new_position
+ })();
- link_for: (position) ->
- @$("#sequence-list .nav-item[data-element=#{position}]")
-
- mark_visited: (position) ->
- # Don't overwrite class attribute to avoid changing Progress class
- element = @link_for(position)
- element.removeClass("inactive")
- .removeClass("active")
- .addClass("visited")
-
- mark_active: (position) ->
- # Don't overwrite class attribute to avoid changing Progress class
- element = @link_for(position)
- element.removeClass("inactive")
- .removeClass("visited")
- .addClass("active")
-
- addBookmarkIconToActiveNavItem: (event) =>
- event.preventDefault()
- @el.find('.nav-item.active .bookmark-icon').removeClass('is-hidden').addClass('bookmarked')
- @el.find('.nav-item.active .bookmark-icon-sr').text(gettext('Bookmarked'))
-
- removeBookmarkIconFromActiveNavItem: (event) =>
- event.preventDefault()
- @el.find('.nav-item.active .bookmark-icon').removeClass('bookmarked').addClass('is-hidden')
- @el.find('.nav-item.active .bookmark-icon-sr').text('')
+}).call(this);