From 872030d71635b8004f4b9dae59cbb2a216a3bca5 Mon Sep 17 00:00:00 2001 From: Alex Osborne Date: Fri, 21 Oct 2016 06:46:43 +1100 Subject: [PATCH] Add a mouseovers behavior based on simpleclicks --- brozzler/behaviors.d/mouseovers.js.template | 136 ++++++++++++++++++++ brozzler/behaviors.yaml | 5 + 2 files changed, 141 insertions(+) create mode 100644 brozzler/behaviors.d/mouseovers.js.template diff --git a/brozzler/behaviors.d/mouseovers.js.template b/brozzler/behaviors.d/mouseovers.js.template new file mode 100644 index 0000000..f4d6173 --- /dev/null +++ b/brozzler/behaviors.d/mouseovers.js.template @@ -0,0 +1,136 @@ +/* + * brozzler/behaviors.d/mouseovers.js.in - mouseovers behavior template, + * mouseovers on elements matching templatized css selector + * + * Copyright (C) 2014-2016 Internet Archive + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var umbraBehavior = { + IDLE_TIMEOUT_SEC : 10, + idleSince : null, + alreadyMouseovered : {}, + + intervalFunc : function() { + var mouseoveredSomething = false; + var somethingLeftBelow = false; + var somethingLeftAbove = false; + var cssSelector = "${mouseover_css_selector}"; + var mouseoverUntilTimeout = "${mouseover_until_hard_timeout}"; + + //handle Python to JavaScript boolean conversion + mouseoverUntilTimeout == "True" ? mouseoverUntilTimeout = true : mouseoverUntilTimeout = false; + + var iframes = document.querySelectorAll("iframe"); + var documents = Array(iframes.length + 1); + documents[0] = document; + + for (var i = 0; i < iframes.length; i++) { + documents[i+1] = iframes[i].contentWindow.document; + } + + for (var j = 0; j < documents.length; j++) { + + var mouseoverTargets = documents[j].querySelectorAll(cssSelector); + + for ( var i = 0; i < mouseoverTargets.length; i++) { + if (mouseoverTargets[i].umbraMouseovered && !mouseoverUntilTimeout) { + continue; + } + + var where = this.aboveBelowOrOnScreen(mouseoverTargets[i]); + + if (where == 0) { + console.log("mouseovering on " + mouseoverTargets[i].outerHTML); + // do mouse over event on mouseover target + // since some urls are requsted only on + // this event - see + // https://webarchive.jira.com/browse/AITFIVE-451 + var mouseOverEvent = document.createEvent('Events'); + mouseOverEvent.initEvent("mouseover",true, false); + mouseoverTargets[i].dispatchEvent(mouseOverEvent); + mouseoveredSomething = true; + this.idleSince = null; + mouseoverTargets[i].umbraMouseovered = true; + + break; //break from mouseoverTargets loop, but not from iframe loop + } else if (where > 0) { + somethingLeftBelow = true; + } else if (where < 0) { + somethingLeftAbove = true; + } + } + } + + if (!mouseoveredSomething) { + if (somethingLeftAbove) { + // console.log("scrolling UP because everything on this screen has been mouseovered but we missed something above"); + window.scrollBy(0, -500); + this.idleSince = null; + } else if (somethingLeftBelow) { + // console.log("scrolling because everything on this screen has been mouseovered but there's more below document.body.clientHeight=" + // + document.body.clientHeight); + window.scrollBy(0, 200); + this.idleSince = null; + } else if (window.scrollY + window.innerHeight < document.documentElement.scrollHeight) { + // console.log("scrolling because we're not to the bottom yet document.body.clientHeight=" + // + document.body.clientHeight); + window.scrollBy(0, 200); + this.idleSince = null; + } else if (this.idleSince == null) { + this.idleSince = Date.now(); + } + } + + if (!this.idleSince) { + this.idleSince = Date.now(); + } + }, + + start : function() { + var that = this; + this.intervalId = setInterval(function() { + that.intervalFunc() + }, 250); + }, + + isFinished : function() { + if (this.idleSince != null) { + var idleTimeMs = Date.now() - this.idleSince; + if (idleTimeMs / 1000 > this.IDLE_TIMEOUT_SEC) { + clearInterval(this.intervalId); + return true; + } + } + return false; + }, + + aboveBelowOrOnScreen : function(e) { + var eTop = e.getBoundingClientRect().top; + if (eTop < window.scrollY) { + return -1; // above + } else if (eTop > window.scrollY + window.innerHeight) { + return 1; // below + } else { + return 0; // on screen + } + }, +}; + +// Called from outside of this script. +var umbraBehaviorFinished = function() { + return umbraBehavior.isFinished() +}; + +umbraBehavior.start(); diff --git a/brozzler/behaviors.yaml b/brozzler/behaviors.yaml index a44f7af..843a897 100644 --- a/brozzler/behaviors.yaml +++ b/brozzler/behaviors.yaml @@ -92,6 +92,11 @@ behaviors: url_regex: '^https?://(?:www\.)?fec.gov/data/.*$' behavior_js: fec_gov.js request_idle_timeout_sec: 10 + - url_regex: '^https?://(?:www\.)?news\.com\.au/.*$' + behavior_js_template: mouseovers.js.template + default_parameters: + mouseover_css_selector: .menu-item a + request_idle_timeout_sec: 10 - # default fallback behavior url_regex: '^.*$' request_idle_timeout_sec: 10