diff --git a/CHANGELOG b/CHANGELOG
index de2e06806..19b2bdeba 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,7 +15,7 @@ Agenda:
Motions:
- New export dialog [#3185].
-- New feature: Personal notes for motions [#3190, #3267].
+- New feature: Personal notes for motions [#3190, #3267, #3404].
- Fixed issue when creating/deleting motion comment fields in the
settings [#3187].
- Fixed empty motion comment field in motion update form [#3194].
@@ -80,6 +80,8 @@ Core:
- Updated CKEditor to 4.7 [#3375].
- Reduced ckeditor toolbar for inline editing [#3368].
- Added custom translations in config [#3383].
+- Added dynamic webpage title [#3404].
+- Added 'go to top'-link [#3404].
Mediafiles:
- Fixed reloading of PDF on page change [#3274].
diff --git a/openslides/agenda/static/js/agenda/site.js b/openslides/agenda/static/js/agenda/site.js
index 1a2d7027a..ed8dd12e6 100644
--- a/openslides/agenda/static/js/agenda/site.js
+++ b/openslides/agenda/static/js/agenda/site.js
@@ -391,14 +391,19 @@ angular.module('OpenSlidesApp.agenda.site', [
'itemId',
'Projector',
'ProjectionDefault',
+ 'gettextCatalog',
+ 'WebpageTitle',
'ErrorMessage',
- function ($scope, $filter, Agenda, itemId, Projector, ProjectionDefault, ErrorMessage) {
+ function ($scope, $filter, Agenda, itemId, Projector, ProjectionDefault, gettextCatalog, WebpageTitle,
+ ErrorMessage) {
$scope.alert = {};
$scope.$watch(function () {
return Agenda.lastModified(itemId);
}, function () {
$scope.item = Agenda.get(itemId);
+ WebpageTitle.updateTitle(gettextCatalog.getString('List of speakers') + ' ' +
+ gettextCatalog.getString('of') + ' ' + $scope.item.getTitle());
// all speakers
$scope.speakers = $filter('orderBy')($scope.item.speakers, 'weight');
// next speakers
diff --git a/openslides/assignments/static/js/assignments/base.js b/openslides/assignments/static/js/assignments/base.js
index e43cae127..d9b4c3bc7 100644
--- a/openslides/assignments/static/js/assignments/base.js
+++ b/openslides/assignments/static/js/assignments/base.js
@@ -406,7 +406,10 @@ angular.module('OpenSlidesApp.assignments', [])
return isProjectedIds;
},
isRelatedProjected: function () {
- var listOfSpeakers = this.agenda_item.isListOfSpeakersProjected();
+ var listOfSpeakers = [];
+ if (this.agenda_item) {
+ listOfSpeakers = this.agenda_item.isListOfSpeakersProjected();
+ }
return listOfSpeakers.concat(this.isProjected(null, true));
},
},
diff --git a/openslides/assignments/static/js/assignments/site.js b/openslides/assignments/static/js/assignments/site.js
index 14d9f9b74..b13223ad9 100644
--- a/openslides/assignments/static/js/assignments/site.js
+++ b/openslides/assignments/static/js/assignments/site.js
@@ -418,10 +418,11 @@ angular.module('OpenSlidesApp.assignments.site', [
'gettextCatalog',
'AssignmentPhases',
'AssignmentPdfExport',
+ 'WebpageTitle',
'ErrorMessage',
function($scope, $http, $filter, $timeout, filterFilter, gettext, ngDialog, AssignmentForm, operator,
Assignment, User, assignmentId, Projector, ProjectionDefault, gettextCatalog, AssignmentPhases,
- AssignmentPdfExport, ErrorMessage) {
+ AssignmentPdfExport, WebpageTitle, ErrorMessage) {
User.bindAll({}, $scope, 'users');
var assignment = Assignment.get(assignmentId);
Assignment.loadRelations(assignment, 'agenda_item');
@@ -447,6 +448,7 @@ angular.module('OpenSlidesApp.assignments.site', [
$scope.activeTab = $scope.assignment.polls.length - 1;
updateBallotTabsFlag = false;
}
+ WebpageTitle.updateTitle(gettextCatalog.getString('Election') + ' ' + $scope.assignment.title);
});
$scope.candidateSelectBox = {};
$scope.phases = AssignmentPhases;
diff --git a/openslides/core/static/css/app.css b/openslides/core/static/css/app.css
index 15695ddae..b14789157 100644
--- a/openslides/core/static/css/app.css
+++ b/openslides/core/static/css/app.css
@@ -296,6 +296,24 @@ img {
color: #555;
}
+/** Goto top link **/
+#goto-top {
+ position: fixed;
+ bottom: 15px;
+ right: 30px;
+ padding: 10px 30px;
+ background: white;
+ opacity: 0.6;
+ transition: opacity 250ms ease-out;
+ z-index: 100;
+}
+#goto-top:hover {
+ opacity: 1;
+ transition: opacity 250ms ease-in;
+}
+#goto-top a:hover {
+ text-decoration: none;
+}
/** Content **/
diff --git a/openslides/core/static/js/core/pdf.js b/openslides/core/static/js/core/pdf.js
index 9382a6296..9789cf3ac 100644
--- a/openslides/core/static/js/core/pdf.js
+++ b/openslides/core/static/js/core/pdf.js
@@ -818,7 +818,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
// If this element is inside a list (happens if copied from word), do not set spaces
// and margins. Just leave the paragraph there..
if (!isInsideAList(element)) {
- currentParagraph.margin = [20, 0, 0, 0];
+ currentParagraph.margin = [0, 0, 0, 0];
if (classes.indexOf('os-split-before') === -1) {
currentParagraph.margin[1] = 8;
}
diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js
index 1c053357d..669a97aac 100644
--- a/openslides/core/static/js/core/site.js
+++ b/openslides/core/static/js/core/site.js
@@ -134,20 +134,30 @@ angular.module('OpenSlidesApp.core.site', [
}
])
-// Set up the activeAppTitle for the title from the webpage
+.factory('WebpageTitle', [
+ '$rootScope',
+ function ($rootScope) {
+ $rootScope.activeAppTitle = '';
+ return {
+ updateTitle: function (text) {
+ $rootScope.activeAppTitle = text || '';
+ },
+ };
+ }
+])
+
+// Watch for the basePerm on a stateChange and initialize the WebpageTitle factory
.run([
'$rootScope',
- 'gettextCatalog',
'operator',
- function ($rootScope, gettextCatalog, operator) {
- $rootScope.activeAppTitle = '';
+ 'WebpageTitle',
+ function ($rootScope, operator, WebpageTitle) {
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
+ WebpageTitle.updateTitle(toState.data ? toState.data.title : '');
if (toState.data) {
- $rootScope.activeAppTitle = toState.data.title || '';
$rootScope.baseViewPermissionsGranted = toState.data.basePerm ?
operator.hasPerms(toState.data.basePerm) : true;
} else {
- $rootScope.activeAppTitle = '';
$rootScope.baseViewPermissionsGranted = true;
}
});
@@ -987,6 +997,23 @@ angular.module('OpenSlidesApp.core.site', [
}
])
+.controller('GotoTopCtrl', [
+ '$scope',
+ '$window',
+ '$timeout',
+ function ($scope, $window, $timeout) {
+ $scope.show = false;
+ angular.element($window).bind('scroll', function () {
+ $timeout(function () {
+ $scope.show = ($window.pageYOffset >= 150);
+ });
+ });
+ $scope.gotoTop = function () {
+ $window.scrollTo(0, 0);
+ };
+ }
+])
+
// Projector Sidebar Controller
.controller('ProjectorSidebarCtrl', [
'$scope',
diff --git a/openslides/core/static/templates/index.html b/openslides/core/static/templates/index.html
index 70fd63a89..f2a2080c7 100644
--- a/openslides/core/static/templates/index.html
+++ b/openslides/core/static/templates/index.html
@@ -4,7 +4,7 @@