Commit d4e5d9e9 authored by Ghislain Loas's avatar Ghislain Loas
Browse files

Merge branch...

Merge branch 'dev#64923_contractuel_concarneau_personnaliser_le_fonds_de_la_carte_bib' into 'master'

Dev#64923 contractuel concarneau personnaliser le fonds de la carte bib

See merge request !2430
parents 3cdb7a8f c2f6bd1b
......@@ -3,7 +3,7 @@ RewriteEngine on
RewriteCond %{REQUEST_URI} !/(xhprof_html|ckeditor|exploit|\.well-known)
RewriteCond %{REQUEST_FILENAME} !^.*/robots\.txt$ [NC]
RewriteRule !(userfiles|public|tmp|temp|skins)/.*\.(js|ico|txt|gif|jpg|jpeg|png|css|xml|swf|mov|pdf|doc|docx|woff|woff2|eot|svg|ttf|xls|wsdl|mp3|m4v|ogg|ogv|epub|html|xhtml|asmx|zip|sql|bro|flv|mp4|webm|tgz|json)$ index.php [NC,NE]
RewriteRule !(userfiles|public|tmp|temp|skins)/.*\.(js|ico|txt|gif|jpg|jpeg|png|css|xml|swf|mov|pdf|doc|docx|woff|woff2|eot|svg|ttf|xls|wsdl|mp3|m4v|ogg|ogv|epub|html|xhtml|asmx|zip|sql|bro|flv|mp4|webm|tgz|json|geojson)$ index.php [NC,NE]
AddType application/x-javascript .js
AddType text/css .css
......
'64923' =>
['Label' => $this->_('Fond de carte personnalisable'),
'Desc' => $this->_('Le fond de carte de la boite bibliothèques est personnalisable.'),
'Image' => '',
'Video' => '',
'Category' => $this->_('Mise en page'),
'Right' => function($feature_description, $user) {return true;},
'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Bo%C3%AEte_Biblioth%C3%A8que#Affichage_de_la_carte',
'Test' => '',
'Date' => '2017-11-21'],
\ No newline at end of file
- ticket #64923 : Boite bibliothèques : le fond de la carte interractive est personnalisable.
\ No newline at end of file
<?php
echo $this->openBoite($this->titre);
echo $this->tag('div',
$this->librariesMap($this->libraries, '#osm_wrapper'),
['id' => 'osm_wrapper']);
echo $this->closeBoite();
?>
echo $this->openBoite($this->titre)
. $this->tag('div',
$this->librariesMap($this->libraries, '#osm_wrapper'),
['id' => 'osm_wrapper'])
. $this->closeBoite();
\ No newline at end of file
This diff is collapsed.
......@@ -394,7 +394,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
['value' => '500'])->bePrivate(),
'ALLOWED_FILES_EXTENSIONS_FOR_IMPORT' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des extensions de fichiers disponibles à l\'import.'),
['value' => 'css;pdf;mp3;mp4;ogg;m4v;ico;gif;svg;jpg;jpeg;png;epub'])
['value' => 'css;pdf;mp3;mp4;ogg;m4v;ico;gif;svg;jpg;jpeg;png;epub;geojson'])
->bePrivate(),
'RESIZABLE_DIMENSIONS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des dimensions disponibles pour retailler les images lors de l\'import.'),
......@@ -404,7 +404,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
['value' => 'jpg;jpeg;png;']),
'SELECTABLE_IMAGE_EXTENSIONS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des extensions d\'images susceptibles d\'être sélectionnées pour enrichir un contenu.'),
['value' => 'svg;gif;jpg;jpeg;png']),
['value' => 'svg;gif;jpg;jpeg;png;geojson']),
'IMAGICK_IMAGE_COMPRESSION_QUALITY' => Class_AdminVar_Meta::newDefault($this->_('Compression d\'image utilisée dans le redimensionnement et la compression des images.'),
['value' => '90'])->bePrivate(),
......
......@@ -175,6 +175,7 @@ class Class_ScriptLoader {
public function loadLeafletJS() {
return $this
->addAdminScript('leaflet-0.7.7/leaflet.js')
->addOPACPluginScript('leaflet-ajax-gh-pages/dist/leaflet.ajax.min.js')
->addStyleSheet(URL_ADMIN_JS . 'leaflet-0.7.7/leaflet.css');
}
......
......@@ -70,7 +70,9 @@ class Class_Systeme_ModulesAccueil_Library extends Class_Systeme_ModulesAccueil_
'filters_position' => self::POSITION_RIGHT,
'default_filters' => [],
'linked' => 0,
'osm_map' => 0];
'osm_map' => 0,
'osm_layer' => 1,
'geo_json' => ''];
}
......
......@@ -25,7 +25,9 @@ class ZendAfi_Form_Configuration_Widget_Libraries extends ZendAfi_Form_Configura
parent::init();
Class_ScriptLoader::getInstance()
->addJQueryReady('checkBoxToggleVisibilityForElement("#allow_link_on_title", $("#anchor").closest("tr"), true);');
->addJQueryReady('checkBoxToggleVisibilityForElement("#allow_link_on_title", $("#anchor").closest("tr"), true);'
. 'checkBoxToggleVisibilityForElement("#osm_map", $("#geo_json").closest("tr"), true);'
. 'checkBoxToggleVisibilityForElement("#osm_map", $("#osm_layer").closest("tr"), true);');
$module = (new Class_Systeme_ModulesAccueil())->getModuleByCode('LIBRARY');
......@@ -87,6 +89,15 @@ class ZendAfi_Form_Configuration_Widget_Libraries extends ZendAfi_Form_Configura
'osm_map',
['label' => $this->_('Afficher la carte interactive')])
->addElement('checkbox',
'osm_layer',
['label' => $this->_('Fond de carte OpenStreetMap')])
->addElement('userfile',
'geo_json',
['label' => $this->_('Fond de carte GeoJSON'),
'folder' => 'js'])
->addElement('url',
'anchor',
['label' => $this->_('Personnaliser le lien du titre'),
......@@ -103,6 +114,8 @@ class ZendAfi_Form_Configuration_Widget_Libraries extends ZendAfi_Form_Configura
->addToSelectionGroup(['libraries'])
->addToDisplaySettingsGroup(['osm_map',
'osm_layer',
'geo_json',
'order',
'nb_aff',
'fields',
......
......@@ -35,6 +35,7 @@ class ZendAfi_View_Helper_LibrariesMap extends ZendAfi_View_Helper_BaseHelper {
Class_ScriptLoader::getInstance()
->loadLeafletJS()
->addOPACScript('openStreetMap/openStreetMap.js')
->addOPACStyleSheet('../js/openStreetMap/openStreetMap.css')
->addJQueryReady('$("'. $container_selector . '").openStreetMap();');
$datas = [];
......@@ -45,9 +46,19 @@ class ZendAfi_View_Helper_LibrariesMap extends ZendAfi_View_Helper_BaseHelper {
'lon' => $library->getLongitude()
];
$geojson = json_encode(isset($preferences['geo_json'])
? $preferences['geo_json']
: '');
$osm_layer = json_encode(isset($preferences['osm_layer'])
? $preferences['osm_layer']
: '0');
return $this->_tag('div', '', ['id' => $container_id,
'class' => 'leaflet_osm',
'data-osm' => json_encode($datas),
'data-osm-geojson' => $geojson,
'data-osm-layer' => $osm_layer,
'data-osm-open-url-icon' => $this->_getUrlIcon('/map/open-marker-icon.png'),
'data-osm-close-url-icon' => $this->_getUrlIcon('/map/close-marker-icon.png'),
'data-osm-default-url-icon' => $this->_getUrlIcon('/map/marker-icon.png')]);
......
......@@ -36,10 +36,10 @@ class ZendAfi_View_Helper_RenderLibrary extends ZendAfi_View_Helper_BaseHelper {
$this->library = $library;
$this->preferences = $preferences;
$label = (!$this->preferences['linked'])
? $this->library->getLibelle()
: $this->view->tagAnchor($this->library->getUrl(),
$this->library->getLibelle());
$label = (isset($this->preferences['linked']) && $this->preferences['linked'])
? $this->view->tagAnchor($this->library->getUrl(),
$this->library->getLibelle())
: $this->library->getLibelle();
return $this->_tag('section',
$this->_tag('h2', $label . $this->view->tagEditLibrary($library)) .
......@@ -48,7 +48,7 @@ class ZendAfi_View_Helper_RenderLibrary extends ZendAfi_View_Helper_BaseHelper {
protected function renderFields() {
$fields = $this->preferences['fields']
$fields = (isset($this->preferences['fields']) && $this->preferences['fields'])
? explode(';', $this->preferences['fields'])
: [];
......
......@@ -201,9 +201,12 @@ function radioToggleVisibilityForElement(eventSourceSelector, objectToShowSelect
function checkBoxToggleVisibilityForElement(eventSourceSelector, objectToShowSelector, visibleWhenChecked) {
return toggleVisibilityForElement(eventSourceSelector,
objectToShowSelector,
function(element) {
return visibleWhenChecked == ($(element).attr('checked') == 'checked');
});
function(element) {
if(visibleWhenChecked)
return $(element).is(':checked');
return !$(element).is(':checked');
});
}
......
.c9revisions
*~
node_modules
\ No newline at end of file
leaflet-ajax
===========
[![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)
Allows you to call JSON via an Ajax call with a jsonp fallback.
```javascript
var geojsonLayer = new L.GeoJSON.AJAX("geojson.json");
```
for jsonp add the option "dataType" and set it to "jsonp"
``` javascript
var geojsonLayer = L.geoJson.ajax("http:webhost.fake/geojson.jsonp",{dataType:"jsonp"});
```
Note that data starts to download when the layer is created NOT when it’s added to the map in order to get a head start.
You may pass either a url string or an array of url strings if you want to download multiple things (handy
if your downloading data from an ESRI based thing which will have separate line, point, and poly features).
As you see you can also use lower case methods without creating new objects
For weirder jsonp you can set "callbackParam" for if you need to change the name of the callback parameter to something besides "callback", e.g. [Mapquest Nominative Open](http://open.mapquestapi.com/nominatim/) uses "json_callback" instead of "callback".
If you want to be able to load stuff from the file system (with appropriate custom flags set) set local to true.
If you want to set headers to the XMLHttpRequest set the 'headers' option equal to an object.
Gives off three events `data:loading`, `data:progress` and `data:loaded`.
- `data:loading` fires before we start downloading things, note if the constructor is given a url it won't wait to be added to the map
to start downloading the data, but it does do an async wait so you have time to add a listener to it (and so [leaflet.spin](https://github.com/makinacorpus/Leaflet.Spin) will work with it).
- `data:progress` is called each time a file is downloaded and passes the downloaded geojson as event data.
- `data:loaded` is called when all files have downloaded, this is mainly different from `data:progress` when you are downloading multiple things.
You can also add a middleware function which is called after you download the data but before you add it to leaflet:
```javascript
var geojsonLayer = L.geoJson.ajax("route/to/esri.json",{
middleware:function(data){
return esri2geoOrSomething(json);
}
});
```
addUrl does not clear the current layers but adds to the current one, e.g.:
```javascript
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.addUrl("data2.json");//we now have 2 layers
geojsonLayer.refresh();//redownload the most recent layer
geojsonLayer.refresh("new1.json");//add a new layer replacing whatever is there
```
last but now least we can refilter layers without re adding them
```javascript
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.refilter(function(feature){
return feature.properties.key === values;
});
```
Behind the scenes are two new classes L.Util.ajax = function (url) for same origin requests and L.Util.jsonp = function (url,options) cross origin ones. Both return promises, which have an additional abort method that will abort the ajax request.
```js
L.Util.ajax("url/same/origin.xml").then(function(data){
doStuff(data);
});
//or
L.Util.jsonp("http://www.dif.ori/gin").then(function(data){
doStuff(data);
});
```
In related news `L.Util.Promise` is now a constructor for a promise, it takes one argument, a resolver function.
Some of the jsonp code inspired by/taken from [this interesting looking plugin](https://github.com/stefanocudini/leaflet-search) that I have failed to make heads nor tails of (the plugin, not the jsonp code)
{
"name": "leaflet-ajax",
"version": "2.1.0",
"homepage": "https://github.com/calvinmetcalf/leaflet-ajax",
"authors": [
"Calvin Metcalf <calvin.metcalf@gmail.com>"
],
"description": "AJAX and JSONP in Leaflet",
"main": "dist/leaflet.ajax.js",
"keywords": [
"leaflet",
"ajax",
"jsonp"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var immediate = require('immediate');
/* istanbul ignore next */
function INTERNAL() {}
var handlers = {};
var REJECTED = ['REJECTED'];
var FULFILLED = ['FULFILLED'];
var PENDING = ['PENDING'];
module.exports = exports = Promise;
function Promise(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError('resolver must be a function');
}
this.state = PENDING;
this.queue = [];
this.outcome = void 0;
if (resolver !== INTERNAL) {
safelyResolveThenable(this, resolver);
}
}
Promise.prototype["catch"] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function (onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
typeof onRejected !== 'function' && this.state === REJECTED) {
return this;
}
var promise = new this.constructor(INTERNAL);
if (this.state !== PENDING) {
var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
unwrap(promise, resolver, this.outcome);
} else {
this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
}
return promise;
};
function QueueItem(promise, onFulfilled, onRejected) {
this.promise = promise;
if (typeof onFulfilled === 'function') {
this.onFulfilled = onFulfilled;
this.callFulfilled = this.otherCallFulfilled;
}
if (typeof onRejected === 'function') {
this.onRejected = onRejected;
this.callRejected = this.otherCallRejected;
}
}
QueueItem.prototype.callFulfilled = function (value) {
handlers.resolve(this.promise, value);
};
QueueItem.prototype.otherCallFulfilled = function (value) {
unwrap(this.promise, this.onFulfilled, value);
};
QueueItem.prototype.callRejected = function (value) {
handlers.reject(this.promise, value);
};
QueueItem.prototype.otherCallRejected = function (value) {
unwrap(this.promise, this.onRejected, value);
};
function unwrap(promise, func, value) {
immediate(function () {
var returnValue;
try {
returnValue = func(value);
} catch (e) {
return handlers.reject(promise, e);
}
if (returnValue === promise) {
handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
} else {
handlers.resolve(promise, returnValue);
}
});
}
handlers.resolve = function (self, value) {
var result = tryCatch(getThen, value);
if (result.status === 'error') {
return handlers.reject(self, result.value);
}
var thenable = result.value;
if (thenable) {
safelyResolveThenable(self, thenable);
} else {
self.state = FULFILLED;
self.outcome = value;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callFulfilled(value);
}
}
return self;
};
handlers.reject = function (self, error) {
self.state = REJECTED;
self.outcome = error;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callRejected(error);
}
return self;
};
function getThen(obj) {
// Make sure we only access the accessor once as required by the spec
var then = obj && obj.then;
if (obj && typeof obj === 'object' && typeof then === 'function') {
return function appyThen() {
then.apply(obj, arguments);
};
}
}
function safelyResolveThenable(self, thenable) {
// Either fulfill, reject or reject with error
var called = false;
function onError(value) {
if (called) {
return;
}
called = true;
handlers.reject(self, value);
}
function onSuccess(value) {
if (called) {
return;
}
called = true;
handlers.resolve(self, value);
}
function tryToUnwrap() {
thenable(onSuccess, onError);
}
var result = tryCatch(tryToUnwrap);
if (result.status === 'error') {
onError(result.value);
}
}
function tryCatch(func, value) {
var out = {};
try {
out.value = func(value);
out.status = 'success';
} catch (e) {
out.status = 'error';
out.value = e;
}
return out;
}
exports.resolve = resolve;
function resolve(value) {
if (value instanceof this) {
return value;
}
return handlers.resolve(new this(INTERNAL), value);
}
exports.reject = reject;
function reject(reason) {
var promise = new this(INTERNAL);
return handlers.reject(promise, reason);
}
exports.all = all;
function all(iterable) {
var self = this;
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return this.reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var values = new Array(len);
var resolved = 0;
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
allResolver(iterable[i], i);
}
return promise;
function allResolver(value, i) {
self.resolve(value).then(resolveFromAll, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
function resolveFromAll(outValue) {
values[i] = outValue;
if (++resolved === len && !called) {
called = true;
handlers.resolve(promise, values);
}
}
}
}
exports.race = race;
function race(iterable) {
var self = this;
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return this.reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
resolver(iterable[i]);
}
return promise;
function resolver(value) {
self.resolve(value).then(function (response) {
if (!called) {
called = true;
handlers.resolve(promise, response);
}
}, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
}
}
},{"immediate":2}],2:[function(require,module,exports){
(function (global){
'use strict';
var Mutation = global.MutationObserver || global.WebKitMutationObserver;
var scheduleDrain;
{
if (Mutation) {
var called = 0;
var observer = new Mutation(nextTick);
var element = global.document.createTextNode('');
observer.observe(element, {
characterData: true
});
scheduleDrain = function () {
element.data = (called = ++called % 2);
};
} else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
var channel = new global.MessageChannel();
channel.port1.onmessage = nextTick;
scheduleDrain = function () {
channel.port2.postMessage(0);
};
} else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
scheduleDrain = function () {
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {