diff --git a/.gitignore b/.gitignore
index 593dc3cf19e7..f50ad217f395 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,7 +20,6 @@ cms/envs/private.py
*.orig
/nbproject
.idea/
-.vscode/
.redcar/
codekit-config.json
.pycharm_helpers/
diff --git a/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js b/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js
index fdc7f9dede29..2f4865356cd3 100644
--- a/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js
+++ b/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js
@@ -1,15 +1,9 @@
/* JavaScript for Vertical Student View. */
-
-/* global markBlocksCompletedOnViewIfNeeded:false */
-
window.VerticalStudentView = function(runtime, element) {
'use strict';
-
- markBlocksCompletedOnViewIfNeeded(runtime, element);
-
if (typeof RequireJS === 'undefined') {
// eslint-disable-next-line no-console
- console.warn('Cannot initialize bookmarks for VerticalStudentView. RequireJS is not defined.');
+ console.log('Cannot initialize VerticalStudentView. RequireJS is not defined.');
return;
}
RequireJS.require(['js/bookmarks/views/bookmark_button'], function(BookmarkButton) {
diff --git a/common/lib/xmodule/xmodule/vertical_block.py b/common/lib/xmodule/xmodule/vertical_block.py
index 70fd2c04d5cb..d253a1f67e7c 100644
--- a/common/lib/xmodule/xmodule/vertical_block.py
+++ b/common/lib/xmodule/xmodule/vertical_block.py
@@ -2,10 +2,8 @@
VerticalBlock - an XBlock which renders its children in a column.
"""
import logging
-import os
from copy import copy
-from django.conf import settings
from lxml import etree
from xblock.core import XBlock
from xblock.fragment import Fragment
@@ -25,7 +23,6 @@
@XBlock.needs('user', 'bookmarks')
-@XBlock.wants('completion')
class VerticalBlock(SequenceFields, XModuleFields, StudioEditableBlock, XmlParserMixin, MakoTemplateBlockBase, XBlock):
"""
Layout XBlock for rendering subblocks vertically.
@@ -58,24 +55,14 @@ def student_view(self, context):
if 'username' not in child_context:
user_service = self.runtime.service(self, 'user')
child_context['username'] = user_service.get_current_user().opt_attrs['edx-platform.username']
- child_blocks = self.get_display_items()
- child_blocks_to_complete_on_view = set()
- completion_service = self.runtime.service(self, 'completion')
- if completion_service and completion_service.completion_tracking_enabled():
- child_blocks_to_complete_on_view = completion_service.blocks_to_mark_complete_on_view(child_blocks)
child_context['child_of_vertical'] = True
is_child_of_vertical = context.get('child_of_vertical', False)
# pylint: disable=no-member
- for child in child_blocks:
- child_block_context = copy(child_context)
- if child in child_blocks_to_complete_on_view:
- child_block_context['wrap_xblock_data'] = {
- 'mark-completed-on-view-after-delay': completion_service.get_complete_on_view_delay_ms()
- }
- rendered_child = child.render(STUDENT_VIEW, child_block_context)
+ for child in self.get_display_items():
+ rendered_child = child.render(STUDENT_VIEW, child_context)
fragment.add_frag_resources(rendered_child)
contents.append({
@@ -92,7 +79,6 @@ def student_view(self, context):
'bookmark_id': u"{},{}".format(child_context['username'], unicode(self.location))
}))
- fragment.add_javascript_url(self.runtime.STATIC_URL + 'bundles/CompletionOnViewService.js')
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/vertical_student_view.js'))
fragment.initialize_js('VerticalStudentView')
diff --git a/common/test/acceptance/pages/lms/completion.py b/common/test/acceptance/pages/lms/completion.py
deleted file mode 100644
index b535af7f51ff..000000000000
--- a/common/test/acceptance/pages/lms/completion.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""
-Mixins for completion.
-"""
-
-
-class CompletionOnViewMixin(object):
- """
- Methods for testing completion on view.
- """
-
- def xblock_components_mark_completed_on_view_value(self):
- """
- Return the xblock components data-mark-completed-on-view-after-delay value.
- """
- return self.q(css=self.xblock_component_selector).attrs(u'data-mark-completed-on-view-after-delay')
-
- def wait_for_xblock_component_to_be_marked_completed_on_view(self, index=0):
- """
- Wait for xblock component to be marked completed on view.
-
- Arguments
- index (int): index of block to wait on. (default is 0)
- """
- self.wait_for(lambda: (self.xblock_components_mark_completed_on_view_value()[index] == u'0'),
- u'Waiting for xblock to be marked completed on view.')
diff --git a/common/test/acceptance/pages/lms/courseware.py b/common/test/acceptance/pages/lms/courseware.py
index 6dabe9f2e555..2240808c6089 100644
--- a/common/test/acceptance/pages/lms/courseware.py
+++ b/common/test/acceptance/pages/lms/courseware.py
@@ -8,13 +8,11 @@
from bok_choy.promise import EmptyPromise
from selenium.webdriver.common.action_chains import ActionChains
-from common.test.acceptance.pages.lms import BASE_URL
from common.test.acceptance.pages.lms.bookmarks import BookmarksPage
-from common.test.acceptance.pages.lms.completion import CompletionOnViewMixin
from common.test.acceptance.pages.lms.course_page import CoursePage
-class CoursewarePage(CoursePage, CompletionOnViewMixin):
+class CoursewarePage(CoursePage):
"""
Course info.
"""
@@ -589,25 +587,3 @@ def visit_course_outline_page(self):
# reload the same page with the course_outline_page flag
self.browser.get(self.browser.current_url + "&course_experience.course_outline_page=1")
self.wait_for_page()
-
-
-class RenderXBlockPage(PageObject, CompletionOnViewMixin):
- """
- render_xblock page.
- """
-
- xblock_component_selector = '.xblock'
-
- def __init__(self, browser, block_id):
- super(RenderXBlockPage, self).__init__(browser)
- self.block_id = block_id
-
- @property
- def url(self):
- """
- Construct a URL to the page within the course.
- """
- return BASE_URL + "/xblock/" + self.block_id
-
- def is_browser_on_page(self):
- return self.q(css='.course-content').present
diff --git a/common/test/acceptance/tests/lms/test_lms_courseware.py b/common/test/acceptance/tests/lms/test_lms_courseware.py
index aa500a6d9b02..e86fd7e78dcf 100644
--- a/common/test/acceptance/tests/lms/test_lms_courseware.py
+++ b/common/test/acceptance/tests/lms/test_lms_courseware.py
@@ -14,7 +14,7 @@
from ...pages.common.auto_auth import AutoAuthPage
from ...pages.common.logout import LogoutPage
from ...pages.lms.course_home import CourseHomePage
-from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage, RenderXBlockPage
+from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage
from ...pages.lms.create_mode import ModeCreationPage
from ...pages.lms.dashboard import DashboardPage
from ...pages.lms.pay_and_verify import FakePaymentPage, FakeSoftwareSecureVerificationPage, PaymentAndVerificationFlow
@@ -947,129 +947,3 @@ def test_subsecton_hidden_after_due_date(self):
self.progress_page.visit()
self.assertEqual(self.progress_page.scores('Test Section 1', 'Test Subsection 1'), [(0, 1)])
-
-
-@attr(shard=9)
-class CompletionTestCase(UniqueCourseTest, EventsTestMixin):
- """
- Test the completion on view functionality.
- """
- USERNAME = "STUDENT_TESTER"
- EMAIL = "student101@example.com"
- COMPLETION_BY_VIEWING_DELAY_MS = '1000'
-
- def setUp(self):
- super(CompletionTestCase, self).setUp()
-
- self.studio_course_outline = StudioCourseOutlinePage(
- self.browser,
- self.course_info['org'],
- self.course_info['number'],
- self.course_info['run']
- )
-
- # Install a course with sections/problems, tabs, updates, and handouts
- course_fix = CourseFixture(
- self.course_info['org'], self.course_info['number'],
- self.course_info['run'], self.course_info['display_name']
- )
-
- self.html_1_block = XBlockFixtureDesc('html', 'html 1', data="html 1 dummy body")
- self.problem_1_block = XBlockFixtureDesc(
- 'problem', 'Test Problem 1', data='problem 1 dummy body'
- )
-
- course_fix.add_children(
- XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
- XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
- XBlockFixtureDesc('vertical', 'Test Unit 1,1,1').add_children(
- XBlockFixtureDesc('html', 'html 1', data="html 1 dummy body"),
- XBlockFixtureDesc(
- 'html', 'html 2',
- data=("html 2 dummy body" * 100) + "End",
- ),
- XBlockFixtureDesc('problem', 'Test Problem 1', data='problem 1 dummy body'),
- ),
- XBlockFixtureDesc('vertical', 'Test Unit 1,1,2').add_children(
- XBlockFixtureDesc('html', 'html 1', data="html 1 dummy body"),
- XBlockFixtureDesc('problem', 'Test Problem 1', data='problem 1 dummy body'),
- ),
- XBlockFixtureDesc('vertical', 'Test Unit 1,1,2').add_children(
- self.html_1_block,
- self.problem_1_block,
- ),
- ),
- ),
- ).install()
-
- # Auto-auth register for the course.
- AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
- course_id=self.course_id, staff=False).visit()
-
- def test_courseware_publish_completion_is_sent_on_view(self):
- """
- Test that when viewing courseware XBlocks are correctly marked as completed on view.
- """
- courseware_page = CoursewarePage(self.browser, self.course_id)
- courseware_page.visit()
- courseware_page.wait_for_page()
-
- # Initially, the first two blocks in the first vertical should be marked as needing to be completed on view.
- self.assertEqual(
- courseware_page.xblock_components_mark_completed_on_view_value(),
- [self.COMPLETION_BY_VIEWING_DELAY_MS, self.COMPLETION_BY_VIEWING_DELAY_MS, None],
- )
- # Wait and verify that the first block which is completely visible is marked as completed.
- courseware_page.wait_for_xblock_component_to_be_marked_completed_on_view(0)
- self.assertEqual(
- courseware_page.xblock_components_mark_completed_on_view_value(),
- ['0', self.COMPLETION_BY_VIEWING_DELAY_MS, None],
- )
-
- # Scroll to the bottom of the second block.
- courseware_page.scroll_to_element('#html2-end', 'Scroll to end of html 2 block')
- # Wait and verify that the second block is also now marked as completed.
- courseware_page.wait_for_xblock_component_to_be_marked_completed_on_view(1)
- self.assertEqual(courseware_page.xblock_components_mark_completed_on_view_value(), ['0', '0', None])
-
- # After page refresh, no blocks in the vertical should be marked as needing to be completed on view.
- self.browser.refresh()
- courseware_page.wait_for_page()
- self.assertEqual(courseware_page.xblock_components_mark_completed_on_view_value(), [None, None, None])
-
- courseware_page.go_to_sequential_position(2)
-
- # Initially, the first block in the second vertical should be marked as needing to be completed on view.
- self.assertEqual(
- courseware_page.xblock_components_mark_completed_on_view_value(),
- [self.COMPLETION_BY_VIEWING_DELAY_MS, None],
- )
- # Wait and verify that the first block which is completely visible is marked as completed.
- courseware_page.wait_for_xblock_component_to_be_marked_completed_on_view(0)
- self.assertEqual(courseware_page.xblock_components_mark_completed_on_view_value(), ['0', None])
-
- # After page refresh, no blocks in the vertical should be marked as needing to be completed on view.
- self.browser.refresh()
- courseware_page.wait_for_page()
- self.assertEqual(courseware_page.xblock_components_mark_completed_on_view_value(), [None, None])
-
- def test_render_xblock_publish_completion_is_sent_on_view(self):
- """
- Test that when viewing a XBlock in render_xblock, it is correctly marked as completed on view.
- """
- block_page = RenderXBlockPage(self.browser, self.html_1_block.locator)
- block_page.visit()
- block_page.wait_for_page()
-
- # Initially the block should be marked as needing to be completed on view.
- self.assertEqual(
- block_page.xblock_components_mark_completed_on_view_value(), [self.COMPLETION_BY_VIEWING_DELAY_MS]
- )
- # Wait and verify that the block is marked as completed on view.
- block_page.wait_for_xblock_component_to_be_marked_completed_on_view(0)
- self.assertEqual(block_page.xblock_components_mark_completed_on_view_value(), ['0'])
-
- # After page refresh, it should not be marked as needing to be completed on view.
- self.browser.refresh()
- block_page.wait_for_page()
- self.assertEqual(block_page.xblock_components_mark_completed_on_view_value(), [None])
diff --git a/common/test/db_fixtures/waffle_flags.json b/common/test/db_fixtures/waffle_flags.json
deleted file mode 100644
index 43de53b0a7ce..000000000000
--- a/common/test/db_fixtures/waffle_flags.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
- {
- "pk": 2,
- "fields": {
- "name": "completion.enable_completion_tracking",
- "active": true
- }
- }
-]
diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py
index 7748c4d2c636..e29be8df6b19 100644
--- a/lms/djangoapps/courseware/views/views.py
+++ b/lms/djangoapps/courseware/views/views.py
@@ -1458,15 +1458,6 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
student_view_context = request.GET.dict()
student_view_context['show_bookmark_button'] = False
- enable_completion_on_view_service = False
- completion_service = block.runtime.service(block, 'completion')
- if completion_service and completion_service.completion_tracking_enabled():
- if completion_service.blocks_to_mark_complete_on_view({block}):
- enable_completion_on_view_service = True
- student_view_context['wrap_xblock_data'] = {
- 'mark-completed-on-view-after-delay': completion_service.get_complete_on_view_delay_ms()
- }
-
context = {
'fragment': block.render('student_view', context=student_view_context),
'course': course,
@@ -1475,7 +1466,6 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
'disable_header': True,
'disable_footer': True,
'disable_window_wrap': True,
- 'enable_completion_on_view_service': enable_completion_on_view_service,
'staff_access': bool(has_access(request.user, 'staff', course)),
'xqa_server': settings.FEATURES.get('XQA_SERVER', 'http://your_xqa_server.com'),
}
diff --git a/lms/djangoapps/lms_xblock/mixin.py b/lms/djangoapps/lms_xblock/mixin.py
index 9b60ad14f45f..2e850088a60e 100644
--- a/lms/djangoapps/lms_xblock/mixin.py
+++ b/lms/djangoapps/lms_xblock/mixin.py
@@ -5,14 +5,12 @@
#from django.utils.translation import ugettext_noop as _
from lazy import lazy
from xblock.core import XBlock
-from xblock.exceptions import JsonHandlerError
from xblock.fields import Boolean, Dict, Scope, String, XBlockMixin
from xblock.validation import ValidationMessage
from xmodule.modulestore.inheritance import UserPartitionList
from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError
-
# Please do not remove, this is a workaround for Django 1.8.
# more information can be found here: https://openedx.atlassian.net/browse/PLAT-902
_ = lambda text: text
@@ -33,7 +31,6 @@ def to_json(self, access_dict):
@XBlock.needs('partitions')
-@XBlock.wants('completion')
class LmsBlockMixin(XBlockMixin):
"""
Mixin that defines fields common to all blocks used in the LMS
@@ -182,18 +179,3 @@ def validate(self):
)
)
return validation
-
- @XBlock.json_handler
- def publish_completion(self, data, suffix=''): # pylint: disable=unused-argument
- """
- Publish completion data from the front end.
- """
- completion_service = self.runtime.service(self, 'completion')
- if completion_service is None:
- raise JsonHandlerError(500, u"No completion service found")
- elif not completion_service.completion_tracking_enabled():
- raise JsonHandlerError(404, u"Completion tracking is not enabled and API calls are unexpected")
- if not completion_service.should_mark_block_completed_on_view(self):
- raise JsonHandlerError(400, u"Block not configured for completion on view.")
- self.runtime.publish(self, u"completion", data)
- return {u'result': u'ok'}
diff --git a/lms/djangoapps/lms_xblock/runtime.py b/lms/djangoapps/lms_xblock/runtime.py
index 9ce5fef9e49b..105afd46e157 100644
--- a/lms/djangoapps/lms_xblock/runtime.py
+++ b/lms/djangoapps/lms_xblock/runtime.py
@@ -1,9 +1,7 @@
"""
Module implementing `xblock.runtime.Runtime` functionality for the LMS
"""
-
import xblock.reference.plugins
-from completion.services import CompletionService
from django.conf import settings
from django.core.urlresolvers import reverse
@@ -180,7 +178,6 @@ class LmsModuleSystem(LmsCourse, LmsUser, ModuleSystem): # pylint: disable=abst
def __init__(self, **kwargs):
request_cache_dict = RequestCache.get_request_cache().data
services = kwargs.setdefault('services', {})
- services['completion'] = CompletionService(user=kwargs.get('user'), course_key=kwargs.get('course_id'))
services['fs'] = xblock.reference.plugins.FSService()
services['i18n'] = ModuleI18nService
services['library_tools'] = LibraryToolsService(modulestore())
diff --git a/lms/static/coffee/src/courseware.coffee b/lms/static/coffee/src/courseware.coffee
index ff44e7b6a20d..49e27c484b8c 100644
--- a/lms/static/coffee/src/courseware.coffee
+++ b/lms/static/coffee/src/courseware.coffee
@@ -10,13 +10,6 @@ class @Courseware
render: ->
XBlock.initializeBlocks($('.course-content'))
-
- courseContentElement = $('.course-content')[0]
- blocks = XBlock.initializeBlocks(courseContentElement)
-
- if (courseContentElement.dataset.enableCompletionOnViewService == 'true')
- markBlocksCompletedOnViewIfNeeded(blocks[0].runtime, courseContentElement)
-
$('.course-content .histogram').each ->
id = $(this).attr('id').replace(/histogram_/, '')
try
diff --git a/lms/static/completion/js/.eslintrc.js b/lms/static/completion/js/.eslintrc.js
deleted file mode 100644
index 12cb26eef91e..000000000000
--- a/lms/static/completion/js/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = {
- extends: 'eslint-config-edx',
- root: true,
- settings: {
- 'import/resolver': 'webpack',
- },
-};
diff --git a/lms/static/completion/js/CompletionOnViewService.js b/lms/static/completion/js/CompletionOnViewService.js
deleted file mode 100644
index 833610ca4c15..000000000000
--- a/lms/static/completion/js/CompletionOnViewService.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { ViewedEventTracker } from './ViewedEvent';
-
-const completedBlocksKeys = new Set();
-
-// eslint-disable-next-line import/prefer-default-export
-export function markBlocksCompletedOnViewIfNeeded(runtime, containerElement) {
- const blockElements = $(containerElement).find(
- '.xblock-student_view[data-mark-completed-on-view-after-delay]',
- ).get();
-
- if (blockElements.length > 0) {
- const tracker = new ViewedEventTracker();
-
- blockElements.forEach((blockElement) => {
- const markCompletedOnViewAfterDelay = parseInt(
- blockElement.dataset.markCompletedOnViewAfterDelay, 10,
- );
- if (markCompletedOnViewAfterDelay >= 0) {
- tracker.addElement(blockElement, markCompletedOnViewAfterDelay);
- }
- });
-
- tracker.addHandler((blockElement, event) => {
- const blockKey = blockElement.dataset.usageId;
- if (blockKey && !completedBlocksKeys.has(blockKey)) {
- if (event.elementHasBeenViewed) {
- $.ajax({
- type: 'POST',
- url: runtime.handlerUrl(blockElement, 'publish_completion'),
- data: JSON.stringify({
- completion: 1.0,
- }),
- }).then(
- () => {
- completedBlocksKeys.add(blockKey);
- // eslint-disable-next-line no-param-reassign
- blockElement.dataset.markCompletedOnViewAfterDelay = 0;
- },
- );
- }
- }
- });
- }
-}
diff --git a/lms/static/completion/js/ViewedEvent.js b/lms/static/completion/js/ViewedEvent.js
deleted file mode 100644
index fe2d8f3fead1..000000000000
--- a/lms/static/completion/js/ViewedEvent.js
+++ /dev/null
@@ -1,182 +0,0 @@
-/** Ensure that a function is only run once every `wait` milliseconds */
-function throttle(fn, wait) {
- let time = 0;
- function delay() {
- // Do not call the function until at least `wait` seconds after the
- // last time the function was called.
- const now = Date.now();
- if (time + wait < now) {
- time = now;
- fn();
- }
- }
- return delay;
-}
-
-
-export class ElementViewing {
- /**
- * A wrapper for an HTMLElement that tracks whether the element has been
- * viewed or not.
- */
- constructor(el, viewedAfterMs, callback) {
- this.el = el;
- this.viewedAfterMs = viewedAfterMs;
- this.callback = callback;
-
- this.topSeen = false;
- this.bottomSeen = false;
- this.seenForMs = 0;
- this.becameVisibleAt = undefined;
- this.hasBeenViewed = false;
- }
-
- getBoundingRect() {
- return this.el.getBoundingClientRect();
- }
-
- /** This element has become visible on screen.
- *
- * (may be called even when already on screen though)
- */
- handleVisible() {
- if (!this.becameVisibleAt) {
- this.becameVisibleAt = Date.now();
- // We're now visible; after viewedAfterMs, if the top and bottom have been
- // seen, this block will count as viewed.
- setTimeout(
- () => {
- this.checkIfViewed();
- },
- this.viewedAfterMs - this.seenForMs,
- );
- }
- }
-
- handleNotVisible() {
- if (this.becameVisibleAt) {
- this.seenForMs = Date.now() - this.becameVisibleAt;
- }
- this.becameVisibleAt = undefined;
- }
-
- markTopSeen() {
- // If this element has been seen for enough time, but the top wasn't visible, it may now be
- // considered viewed.
- this.topSeen = true;
- this.checkIfViewed();
- }
-
- markBottomSeen() {
- this.bottomSeen = true;
- this.checkIfViewed();
- }
-
- getTotalTimeSeen() {
- if (this.becameVisibleAt) {
- return this.seenForMs + (Date.now() - this.becameVisibleAt);
- }
- return this.seenForMs;
- }
-
- areViewedCriteriaMet() {
- return this.topSeen && this.bottomSeen && (this.getTotalTimeSeen() >= this.viewedAfterMs);
- }
-
- checkIfViewed() {
- // User can provide a "now" value for testing purposes.
- if (this.hasBeenViewed) {
- return;
- }
- if (this.areViewedCriteriaMet()) {
- this.hasBeenViewed = true;
- // Report to the tracker that we have been viewed
- this.callback(this.el, { elementHasBeenViewed: this.hasBeenViewed });
- }
- }
-}
-
-
-export class ViewedEventTracker {
- /**
- * When the top or bottom of an element is first viewed, and the entire
- * element is viewed for a specified amount of time, the callback is called,
- * passing the element that was viewed, and an event object having the
- * following field:
- *
- * * hasBeenViewed (bool): true if all the conditions for being
- * considered "viewed" have been met.
- */
- constructor() {
- this.elementViewings = new Set();
- this.handlers = [];
- this.registerDomHandlers();
- }
-
- /** Add an element to track. */
- addElement(element, viewedAfterMs) {
- this.elementViewings.add(
- new ElementViewing(
- element,
- viewedAfterMs,
- (el, event) => this.callHandlers(el, event),
- ),
- );
- this.updateVisible();
- }
-
- /** Register a new handler to be called when an element has been viewed. */
- addHandler(handler) {
- this.handlers.push(handler);
- }
-
- /** Mark which elements are currently visible.
- *
- * Also marks when an elements top or bottom has been seen.
- * */
- updateVisible() {
- this.elementViewings.forEach((elv) => {
- if (elv.hasBeenViewed) {
- return;
- }
-
- const now = Date.now(); // Use the same "now" for all calculations
- const rect = elv.getBoundingRect();
- let visible = false;
-
- if (rect.top > 0 && rect.top < window.innerHeight) {
- elv.markTopSeen(now);
- visible = true;
- }
- if (rect.bottom > 0 && rect.bottom < window.innerHeight) {
- elv.markBottomSeen(now);
- visible = true;
- }
- if (rect.top < 0 && rect.bottom > window.innerHeight) {
- visible = true;
- }
-
- if (visible) {
- elv.handleVisible(now);
- } else {
- elv.handleNotVisible(now);
- }
- });
- }
-
- registerDomHandlers() {
- window.onscroll = throttle(() => this.updateVisible(), 100);
- window.onresize = throttle(() => this.updateVisible(), 100);
- this.updateVisible();
- }
-
- /** Call the handlers for all newly-viewed elements and pause tracking
- * for recently disappeared elements.
- */
- callHandlers(el, event) {
- this.handlers.forEach((handler) => {
- handler(el, event);
- });
- }
-}
-
diff --git a/lms/static/completion/js/spec/ViewedEvent_spec.js b/lms/static/completion/js/spec/ViewedEvent_spec.js
deleted file mode 100644
index 62662317423c..000000000000
--- a/lms/static/completion/js/spec/ViewedEvent_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { ElementViewing, ViewedEventTracker } from '../ViewedEvent';
-
-
-describe('ViewedTracker', () => {
- let existingHTML;
- beforeEach(() => {
- existingHTML = document.body.innerHTML;
- });
-
- afterEach(() => {
- document.body.innerHTML = existingHTML;
- });
-
- it('calls the handlers when an element is viewed', () => {
- document.body.innerHTML = '
';
- const tracker = new ViewedEventTracker();
- for (const element of document.getElementsByTagName('div')) { // eslint-disable-line no-restricted-syntax
- tracker.addElement(element, 1000);
- }
- const handlerSpy = jasmine.createSpy('handlerSpy');
- tracker.addHandler(handlerSpy);
- const elvIter = tracker.elementViewings.values();
- // Pick two elements, and mock them so that one has met the criteria to be viewed,
- // and the other hasn't.
- const viewed = elvIter.next().value;
- spyOn(viewed, 'areViewedCriteriaMet').and.returnValue(true);
- viewed.checkIfViewed();
- expect(handlerSpy).toHaveBeenCalledWith(viewed.el, {
- elementHasBeenViewed: true,
- });
- const unviewed = elvIter.next().value;
- spyOn(unviewed, 'areViewedCriteriaMet').and.returnValue(false);
- unviewed.checkIfViewed();
- expect(handlerSpy).not.toHaveBeenCalledWith(unviewed.el, jasmine.anything());
- });
-});
-
-describe('ElementViewing', () => {
- beforeEach(() => {
- jasmine.clock().install();
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- it('calls checkIfViewed when enough time has elapsed', () => {
- const viewing = new ElementViewing({}, 500, () => {});
- spyOn(viewing, 'checkIfViewed').and.callThrough();
- viewing.seenForMs = 250;
- viewing.handleVisible();
- jasmine.clock().tick(249);
- expect(viewing.checkIfViewed).not.toHaveBeenCalled();
- jasmine.clock().tick(1);
- expect(viewing.checkIfViewed).toHaveBeenCalled();
- });
-
- it('has been viewed after the specified number of milliseconds', () => {
- const viewing = new ElementViewing({}, 500, () => {});
- viewing.seenForMs = 250;
- spyOn(Date, 'now').and.returnValue(750);
- viewing.handleVisible();
- viewing.markTopSeen();
- viewing.markBottomSeen();
- Date.now.and.returnValue(999);
- viewing.checkIfViewed();
- expect(viewing.hasBeenViewed).toBeFalsy();
- Date.now.and.returnValue(1000);
- jasmine.clock().tick(250);
- expect(viewing.hasBeenViewed).toBeTruthy();
- });
-
- it('has not been viewed if the bottom has not been seen', () => {
- const viewing = new ElementViewing(undefined, 500, () => {});
- viewing.markTopSeen();
- viewing.seenForMs = 500;
- expect(viewing.areViewedCriteriaMet()).toBeFalsy();
- viewing.checkIfViewed();
- expect(viewing.hasBeenViewed).toBeFalsy();
- });
-
- it('has not been viewed if the top has not been seen', () => {
- const viewing = new ElementViewing(undefined, 500, () => {});
- viewing.markBottomSeen();
- viewing.seenForMs = 500;
- expect(viewing.areViewedCriteriaMet()).toBeFalsy();
- viewing.checkIfViewed();
- expect(viewing.hasBeenViewed).toBeFalsy();
- });
-
- it('does not update time seen if lastSeen is undefined', () => {
- const viewing = new ElementViewing(undefined, 500, () => {});
- viewing.becameVisibleAt = undefined;
- expect(viewing.becameVisibleAt).toBeUndefined();
- viewing.handleVisible();
- expect(viewing.becameVisibleAt).not.toBeUndefined();
- });
-});
diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js
index 28440b25d926..4395917af681 100644
--- a/lms/static/lms/js/spec/main.js
+++ b/lms/static/lms/js/spec/main.js
@@ -673,7 +673,6 @@
});
testFiles = [
- 'completion/js/spec/ViewedEvent_spec.js',
'course_bookmarks/js/spec/bookmark_button_view_spec.js',
'course_bookmarks/js/spec/bookmarks_list_view_spec.js',
'course_bookmarks/js/spec/course_bookmarks_factory_spec.js',
diff --git a/lms/templates/courseware/courseware-chromeless.html b/lms/templates/courseware/courseware-chromeless.html
index 92cb8f694432..6ebabf686009 100644
--- a/lms/templates/courseware/courseware-chromeless.html
+++ b/lms/templates/courseware/courseware-chromeless.html
@@ -54,15 +54,11 @@
## codemirror
- % if enable_completion_on_view_service:
-
-
- % endif
<%static:js group='courseware'/>
<%include file="/mathjax_include.html" args="disable_fast_preview=True"/>
% if staff_access:
- <%include file="xqa_interface.html"/>
+ <%include file="xqa_interface.html"/>
% endif