openlp-dev team mailing list archive
-
openlp-dev team
-
Mailing list archive
-
Message #00064
[Merge] lp:~ic90/openlp/animated-alerts into lp:~openlp-dev/openlp/webengine-migrate
Nico Opiyo has proposed merging lp:~ic90/openlp/animated-alerts into lp:~openlp-dev/openlp/webengine-migrate.
Commit message:
Refactored the tests and optimized alert display code plus fixed spacing
Requested reviews:
Nico Opiyo (ic90)
Raoul Snyman (raoul-snyman)
For more details, see:
https://code.launchpad.net/~ic90/openlp/animated-alerts/+merge/363053
Refactored the tests and optimized alert display code plus fixed spacing
JS Test Output is as below:
PhantomJS 2.1.1 (Windows 8.0.0) Display.setTextSlides should correctly set outline width FAILED
TypeError: undefined is not an object (evaluating 'dom.wrapper.querySelectorAll') in openlp/core/display/html/reveal.js (line 2304)
slide@openlp/core/display/html/reveal.js:2304:37
goToSlide@openlp/core/display/html/display.js:712:19
setTextSlides@openlp/core/display/html/display.js:569:22
tests/js/test_display.js:365:26
PhantomJS 2.1.1 (Windows 8.0.0): Executed 68 of 68 (1 FAILED) (0 secs / 0.099 secs)
PhantomJS 2.1.1 (Windows 8.0.0): Executed 68 of 68 (1 FAILED) (0.127 secs / 0.099 secs)
TOTAL: 1 FAILED, 67 SUCCESS
--
Your team OpenLP Development is subscribed to branch lp:~openlp-dev/openlp/webengine-migrate.
=== modified file 'openlp/core/display/html/display.html'
--- openlp/core/display/html/display.html 2018-10-12 19:51:51 +0000
+++ openlp/core/display/html/display.html 2019-02-12 12:08:26 +0000
@@ -24,14 +24,89 @@
visibility: visible;
z-index: -1;
}
+
+ /* Animation key frames for horizontal scrolling of alert */
+ @keyframes alert-scrolling-text {
+ from { margin-left: 100%; }
+ to { margin-left: -300% }
+ }
+ /* Middle fade-in alert animation */
+ @keyframes middle-fade-in {
+ from { opacity: 0;}
+ to { opacity: 1;}
+ }
+
+ /* Middle fade-out alert animation */
+ @keyframes middle-fade-out {
+ from { opacity: 1;}
+ to { opacity: 0;}
+ }
+
+ /* Fade in when alert location is in the middle */
+ .middle-entrance-animation {
+ animation-duration: 2s;
+ animation-timing-function: linear;
+ animation-name: middle-fade-in;
+ }
+
+ /* Fade out when alert location is in the middle */
+ .middle-exit-animation {
+ animation-duration: 2s;
+ animation-timing-function: linear;
+ animation-name: middle-fade-out;
+ }
+
+ .horizontal-scroll-animation {
+ animation-duration: 10s;
+ animation-iteration-count: 1;
+ animation-timing-function: linear;
+ animation-name: alert-scrolling-text;
+ }
+
+ /* ALERT STYLING */
+ #alert-background {
+ position: absolute;
+ margin: 0;
+ padding: 0;
+ left: 0px;
+ right: 0px;
+ z-index: 10;
+ width: 100%;
+ height: 0%;
+ vertical-align: middle;
+ color: #ffffff;
+ background-color: #660000;
+ overflow: hidden;
+ visibility:hidden;
+ }
+
+ #alert {
+ position: relative;
+ top: 50%;
+ transform: translateY(-50%);
+ margin-top: 0%;
+ margin-right: 0%;
+ margin-left: 100%;
+ margin-bottom: 0%;
+ z-index: 11;
+ overflow: visible;
+ white-space: nowrap;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+ font-size: 100pt;
+ color: #ffffff;
+ visibility: hidden;
+ }
+
</style>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="reveal.js"></script>
<script type="text/javascript" src="display.js"></script>
</head>
+
<body>
<div class="reveal">
<div id="global-background" class="slide-background present" data-loaded="true"></div>
+ <div id="alert-background"><p id="alert">Testing alerts</p></div>
<div class="slides"></div>
<div class="footer"></div>
</div>
=== modified file 'openlp/core/display/html/display.js'
--- openlp/core/display/html/display.js 2019-02-05 21:26:30 +0000
+++ openlp/core/display/html/display.js 2019-02-12 12:08:26 +0000
@@ -53,6 +53,39 @@
};
/**
+ * Transition state enumeration
+ */
+
+var TransitionState = {
+ EntranceTransition: "entranceTransition",
+ NoTransition: "noTransition",
+ ExitTransition: "exitTransition"
+};
+
+/**
+ * Animation state enumeration
+ */
+var AnimationState = {
+ NoAnimation: "noAnimation",
+ ScrollingAnimation: "scrollingAnimation",
+ FadeInAnimation: "fadeInAnimation",
+ FadeOutAnimation: "fadeOutAnimation"
+};
+/**
+ * Alert location enumeration
+ */
+var AlertLocation = {
+ Top: "0",
+ Middle: "1",
+ Bottom: "2"
+};
+
+/**
+ *
+ * @param {Location} selector
+ */
+
+/**
* Return an array of elements based on the selector query
* @param {string} selector - The selector to find elements
* @returns {array} An array of matching elements
@@ -132,6 +165,10 @@
}
/**
+ *
+ */
+
+/**
* An audio player with a play list
*/
var AudioPlayer = function (audioElement) {
@@ -249,6 +286,8 @@
*/
var Display = {
_slides: {},
+ _transitionState: TransitionState.NoTransition,
+ _animationState: AnimationState.NoAnimation,
_revealConfig: {
margin: 0.0,
minScale: 1.0,
@@ -372,15 +411,121 @@
* @param {string} text - The alert text
* @param {int} location - The location of the text (top, middle or bottom)
*/
- alert: function (text, location) {
- console.debug(" alert text: " + text, ", location: " + location);
+ alert: function (text, location) {
+ console.debug(" alert text: " + text + ", location: " + location);
+
+ if (text == "") {
+ return null;
+ }
+
+ var alertBackground = $("#alert-background")[0];
+ var alertText = $("#alert")[0];
+
+ alertText.innerHTML = text;
+
+ /* Bring in the transition background */
+ Display._transitionState = Display.doEntranceTransition(location);
+
+ alertBackground.addEventListener('transitionend', function (e) {
+ e.stopPropagation();
+ if (Display._transitionState == TransitionState.EntranceTransition) {
+ alertText.style.visibility = "visible";
+ alertText.classList.add("horizontal-scroll-animation");
+ }
+ else if (Display._transitionState == TransitionState.ExitTransition) {
+ Display._transitionState = TransitionState.NoTransition;
+ alertBackground.style.visibility = "hidden";
+ alertText.style.visibility = "hidden";
+ alertBackground.style.top = "";
+ alertBackground.style.bottom = "";
+ alertBackground.style.height = "";
+ alertBackground.style.transition = "";
+ alertBackground.classList.remove("middle-exit-animation");
+ }
+ });
+
+ alertBackground.addEventListener('animationend', function () {
+
+ if (Display._animationState == AnimationState.FadeInAnimation) {
+ alertText.style.visibility = "visible";
+ alertText.classList.add("horizontal-scroll-animation");
+ alertText.classList.remove("middle-entrance-animation");
+ Display._animationState = AnimationState.ScrollingAnimation;
+ }
+ else if (Display._animationState == AnimationState.FadeOutAnimation) {
+ alertBackground.style.visibility = "hidden";
+ alertBackground.classList.remove("middle-exit-animation");
+ Display._animationState = AnimationState.NoAnimation;
+ }
+ else if (alertText.classList.contains("horizontal-scroll-animation")) {
+ alertText.classList.remove("horizontal-scroll-animation");
+ alertText.style.visibility = "hidden";
+ Display._animationState = AnimationState.NoAnimation;
+ Display._transitionState = Display.doExitTransition(location);
+ }
+
+ });
+
/*
* The implementation should show an alert.
* It should be able to handle receiving a new alert before a previous one is "finished", basically queueing it.
*/
- return;
-},
-
+ return location;
+ },
+
+ /**
+ * Start background entrance transition for display of alert
+ * @param {string} location - String showing the location of the alert on screen
+ */
+ doEntranceTransition: function (location) {
+ var alertBackground = $("#alert-background")[0];
+
+ switch (location) {
+ case AlertLocation.Top:
+ alertBackground.style.bottom = '';
+ alertBackground.style.top = '0px';
+ alertBackground.style.height = "25%";
+ alertBackground.style.transition = "2s linear";
+ break;
+ case AlertLocation.Middle:
+ alertBackground.style.top = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px';
+ alertBackground.style.height = "25%";
+ alertBackground.classList.add("middle-entrance-animation");
+ Display._animationState = AnimationState.FadeInAnimation;
+ break;
+ case AlertLocation.Bottom:
+ default:
+ alertBackground.style.top = '';
+ alertBackground.style.bottom = '0px';
+ alertBackground.style.height = "25%";
+ alertBackground.style.transition= "2s linear";
+ break;
+ }
+ alertBackground.style.visibility = "visible";
+ return TransitionState.EntranceTransition;
+
+ },
+
+ /**
+ * Start background exit transition once alert has been displayed
+ * @param {string} location - Integer showing the location of the alert on screen
+ */
+ doExitTransition: function (location) {
+
+ var alertBackground = $("#alert-background")[0];
+
+ if (location == AlertLocation.Top || location == AlertLocation.Bottom) {
+ alertBackground.style.height = "0%";
+ alertBackground.style.transition = '2s linear';
+ }
+ else if (location == AlertLocation.Middle) {
+ alertBackground.classList.add("middle-exit-animation");
+ alertBackground.style.height = "0%";
+ Display._animationState = AnimationState.FadeOutAnimation;
+ }
+
+ return TransitionState.ExitTransition;
+ },
/**
* Add a slides. If the slide exists but the HTML is different, update the slide.
* @param {string} verse - The verse number, e.g. "v1"
=== modified file 'openlp/core/display/window.py'
--- openlp/core/display/window.py 2018-12-06 20:26:35 +0000
+++ openlp/core/display/window.py 2019-02-12 12:08:26 +0000
@@ -401,4 +401,4 @@
"""
Set an alert
"""
- self.run_javascript('Display.alert({text}, {location});'.format(text=text, location=location))
+ self.run_javascript('Display.alert("{text}", "{location}");'.format(text=text, location=location))
=== modified file 'tests/js/test_display.js'
--- tests/js/test_display.js 2019-01-16 06:15:21 +0000
+++ tests/js/test_display.js 2019-02-12 12:08:26 +0000
@@ -18,6 +18,14 @@
it("AudioState should exist", function () {
expect(AudioState).toBeDefined();
});
+
+ it("TransitionState should exist", function(){
+ expect(TransitionState).toBeDefined();
+ });
+
+ it("AnimationState should exist", function(){
+ expect(AnimationState).toBeDefined();
+ });
});
describe("The function", function () {
@@ -138,7 +146,111 @@
Display.goToSlide("v1");
expect(Reveal.slide).toHaveBeenCalledWith(0);
});
-});
+
+ it("should have an alert() method", function () {
+ expect(Display.alert).toBeDefined();
+ });
+
+});
+
+describe("Display.alert", function () {
+ var alertBackground, alert;
+
+ beforeEach(function () {
+ document.body.innerHTML = "";
+ alertBackground = document.createElement("div");
+ alertBackground.setAttribute("id", "alert-background");
+ document.body.appendChild(alertBackground);
+ alert = document.createElement("p");
+ alert.setAttribute("id","alert");
+ alertBackground.appendChild(alert);
+ });
+
+ it("should return null if called without any text", function () {
+ expect(Display.alert("","2")).toBeNull();
+ });
+
+ it("should set correct alert text", function () {
+ Display.alert("OPEN-LP-3.0 Alert Test", "2");
+ expect(alert.innerHTML).toEqual("OPEN-LP-3.0 Alert Test");
+ });
+
+ it("should set the correct alert position", function () {
+ expect(Display.alert("Alert Location Test","2")).toEqual("2");
+ });
+});
+
+describe("The doEntranceTransition", function () {
+
+ var alertBackground;
+
+ beforeEach(function() {
+ document.body.innerHTML = "";
+ alertBackground = document.createElement("div");
+ alertBackground.setAttribute("id", "alert-background");
+ document.body.appendChild(alertBackground);
+ alertBackground.style.top = '0px';
+ alertBackground.style.height = "0%";
+ });
+
+ it("should set the correct styles for the alert when location is top of the page", function () {
+ Display.doEntranceTransition("0");
+ expect(alertBackground.style.bottom).toEqual('');
+ expect(alertBackground.style.top).toEqual('0px');
+ expect(alertBackground.style.transition).toEqual("2s linear");
+ expect(alertBackground.style.height).toEqual("25%");
+ expect(alertBackground.style.visibility).toEqual("visible");
+ });
+
+ it("should set the correct styles for the alert when location is middle of the page", function () {
+ Display.doEntranceTransition("1");
+ var middlePosition = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px';
+ expect(alertBackground.style.top).toEqual(middlePosition);
+ expect(alertBackground.classList.contains("middle-entrance-animation"));
+ expect(alertBackground.style.height).toEqual("25%");
+ expect(alertBackground.style.visibility).toEqual("visible");
+ });
+
+ it("should set the correct styles for the alert when location is bottom of the page", function () {
+ Display.doEntranceTransition("2");
+ expect(alertBackground.style.top).toEqual('');
+ expect(alertBackground.style.bottom).toEqual('0px');
+ expect(alertBackground.style.transition).toEqual("2s linear");
+ expect(alertBackground.style.height).toEqual("25%");
+ expect(alertBackground.style.visibility).toEqual("visible");
+ });
+});
+
+describe("The doExitTransition", function () {
+ var alertBackground;
+
+ beforeEach(function () {
+ document.body.innerHTML = "";
+ alertBackground = document.createElement("div");
+ alertBackground.setAttribute("id", "alert-background");
+ document.body.appendChild(alertBackground);
+ });
+
+ it("should remove the styles correctly when the location is the top of the page", function () {
+ Display.doExitTransition("0");
+ expect(alertBackground.style.height).toEqual('0%');
+ expect(alertBackground.style.transition).toEqual("2s linear");
+ });
+
+ it("should remove the styles correctly when the location is middle of the page", function () {
+ Display.doExitTransition("1");
+ expect(alertBackground.style.height).toEqual('0%');
+ expect(alertBackground.classList.contains("middle-exit-animation"));
+ });
+
+it("should remove the styles correctly when the location is the bottom of the page", function () {
+ Display.doExitTransition("2");
+ expect(alertBackground.style.height).toEqual('0%');
+ expect(alertBackground.style.transition).toEqual("2s linear");
+});
+
+});
+
describe("Display.addTextSlide", function () {
beforeEach(function() {
Follow ups