Merge branch '3.8'

Conflicts:
	bower.json
This commit is contained in:
Romain Neutron
2013-10-15 19:11:39 +02:00
21 changed files with 1341 additions and 1651 deletions

View File

@@ -18,7 +18,7 @@
"backbone-amd": "~1.0", "backbone-amd": "~1.0",
"underscore-amd": "~1.4", "underscore-amd": "~1.4",
"i18next": "~1.6", "i18next": "~1.6",
"bootstrap-multiselect": "https://github.com/davidstutz/bootstrap-multiselect.git", "bootstrap-multiselect": "https://github.com/davidstutz/bootstrap-multiselect.git#bootstrap-2-3",
"zxcvbn": "https://github.com/lowe/zxcvbn.git", "zxcvbn": "https://github.com/lowe/zxcvbn.git",
"geonames-server-jquery-plugin": "~0.2", "geonames-server-jquery-plugin": "~0.2",
"swfobject": "latest", "swfobject": "latest",

View File

@@ -972,7 +972,7 @@ class Databox implements ControllerProviderInterface
public function getReorder(Application $app, Request $request, $databox_id) public function getReorder(Application $app, Request $request, $databox_id)
{ {
return $app['twig']->render('admin/collection/reorder.html.twig', array( return $app['twig']->render('admin/collection/reorder.html.twig', array(
'databox' => $app['phraseanet.appbox']->get_databox($databox_id), 'collections' => $app['authentication']->getUser()->ACL()->get_granted_base(array(), array($databox_id)),
)); ));
} }
@@ -986,19 +986,14 @@ class Databox implements ControllerProviderInterface
*/ */
public function setReorder(Application $app, Request $request, $databox_id) public function setReorder(Application $app, Request $request, $databox_id)
{ {
$success = false;
try { try {
foreach ($request->request->get('order', array()) as $order => $data) { foreach ($request->request->get('order', array()) as $data) {
$baseId = $data['id']; $collection = \collection::get_from_base_id($app, $data['id']);
$collection = \collection::get_from_base_id($app, $baseId); $collection->set_ord($data['offset']);
$app['phraseanet.appbox']->set_collection_order($collection, $order);
unset($collection);
} }
$success = true; $success = true;
} catch (\Exception $e) { } catch (\Exception $e) {
$success = false;
} }
if ('json' === $app['request']->getRequestFormat()) { if ('json' === $app['request']->getRequestFormat()) {

View File

@@ -150,7 +150,7 @@ class Root implements ControllerProviderInterface
$currentPage = 1; $currentPage = 1;
} }
$result = $app['phraseanet.SE']->query($query, $currentPage, $perPage); $result = $app['phraseanet.SE']->query($query, ($currentPage - 1) * $perPage, $perPage);
$userQuery = new UserQuery(); $userQuery = new UserQuery();
$userQuery->setUsrId($app['authentication']->getUser()->get_id()); $userQuery->setUsrId($app['authentication']->getUser()->get_id());

View File

@@ -40,15 +40,14 @@ class Edit implements ControllerProviderInterface
$records = RecordsRequest::fromRequest($app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, array('canmodifrecord')); $records = RecordsRequest::fromRequest($app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, array('canmodifrecord'));
$thesaurus = $multipleDataboxes = false; $thesaurus = false;
$status = $ids = $elements = $suggValues = $status = $ids = $elements = $suggValues =
$fields = $JSFields = array(); $fields = $JSFields = array();
$databox = null; $databox = null;
$multipleDataboxes = count($records->databoxes()) > 1; $multipleDataboxes = count($records->databoxes()) > 1;
if (!$multipleDataboxes) { if (1 === count($records->databoxes())) {
$databoxes = $records->databoxes(); $databoxes = $records->databoxes();
$databox = array_pop($databoxes); $databox = array_pop($databoxes);

View File

@@ -85,6 +85,7 @@ class Language implements ControllerProviderInterface
$out['FeedBackName'] = _('Name'); $out['FeedBackName'] = _('Name');
$out['FeedBackMessage'] = _('Message'); $out['FeedBackMessage'] = _('Message');
$out['FeedBackDuration'] = _('Time for feedback (days)'); $out['FeedBackDuration'] = _('Time for feedback (days)');
$out['FeedBackNameMandatory'] = _('Please provide a name for this selection.');
$out['send'] = _('Send'); $out['send'] = _('Send');
$out['Recept'] = _('Accuse de reception'); $out['Recept'] = _('Accuse de reception');
$out['nFieldsChanged'] = _('%d fields have been updated'); $out['nFieldsChanged'] = _('%d fields have been updated');

View File

@@ -157,12 +157,7 @@ class Push implements ControllerProviderInterface
try { try {
$pusher = new RecordHelper\Push($app, $app['request']); $pusher = new RecordHelper\Push($app, $app['request']);
$push_name = $request->request->get('name'); $push_name = $request->request->get('name', sprintf(_('Push from %s'), $app['authentication']->getUser()->get_display_name()));
if (trim($push_name) === '') {
$push_name = sprintf(_('Push from %s'), $app['authentication']->getUser()->get_display_name());
}
$push_description = $request->request->get('push_description'); $push_description = $request->request->get('push_description');
$receivers = $request->request->get('participants'); $receivers = $request->request->get('participants');
@@ -281,12 +276,7 @@ class Push implements ControllerProviderInterface
$repository = $app['EM']->getRepository('\Entities\Basket'); $repository = $app['EM']->getRepository('\Entities\Basket');
$validation_name = $request->request->get('name'); $validation_name = $request->request->get('name', sprintf(_('Validation from %s'), $app['authentication']->getUser()->get_display_name()));
if (trim($validation_name) === '') {
$validation_name = sprintf(_('Validation from %s'), $app['authentication']->getUser()->get_display_name());
}
$validation_description = $request->request->get('validation_description'); $validation_description = $request->request->get('validation_description');
$participants = $request->request->get('participants'); $participants = $request->request->get('participants');

View File

@@ -33,7 +33,7 @@ class SearchEngineSuggestion
{ {
$this->query = $query; $this->query = $query;
$this->suggestion = $suggestion; $this->suggestion = $suggestion;
$this->hits = (int) $hits; $this->hits = null !== $hits ? (int) $hits : null;
} }
/** /**
@@ -66,4 +66,16 @@ class SearchEngineSuggestion
return $this->hits; return $this->hits;
} }
/**
* Returns the suggestion as an array representation.
*
* @return array
*/
public function toArray()
{
return array(
'query' => $this->getSuggestion(),
'hits' => $this->getHits(),
);
}
} }

View File

@@ -12,6 +12,7 @@
use Alchemy\Phrasea\Feed\Aggregate; use Alchemy\Phrasea\Feed\Aggregate;
use Alchemy\Phrasea\Feed\FeedInterface; use Alchemy\Phrasea\Feed\FeedInterface;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions; use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Border\File; use Alchemy\Phrasea\Border\File;
use Alchemy\Phrasea\Border\Attribute\Status; use Alchemy\Phrasea\Border\Attribute\Status;
@@ -896,7 +897,7 @@ class API_V1_adapter extends API_V1_Abstract
$offsetStart = (int) ($request->get('offset_start') ? : 0); $offsetStart = (int) ($request->get('offset_start') ? : 0);
$perPage = (int) $request->get('per_page') ? : 10; $perPage = (int) $request->get('per_page') ? : 10;
$query = (string) $request->request->get('query'); $query = (string) $request->get('query');
$this->app['phraseanet.SE']->setOptions($options); $this->app['phraseanet.SE']->setOptions($options);
$this->app['phraseanet.SE']->resetCache(); $this->app['phraseanet.SE']->resetCache();
@@ -929,7 +930,9 @@ class API_V1_adapter extends API_V1_Abstract
'warning' => $search_result->getWarning(), 'warning' => $search_result->getWarning(),
'query_time' => $search_result->getDuration(), 'query_time' => $search_result->getDuration(),
'search_indexes' => $search_result->getIndexes(), 'search_indexes' => $search_result->getIndexes(),
'suggestions' => $search_result->getSuggestions()->toArray(), 'suggestions' => array_map(function (SearchEngineSuggestion $suggestion) {
return $suggestion->toArray();
}, $search_result->getSuggestions()->toArray()),
'results' => array(), 'results' => array(),
'query' => $search_result->getQuery(), 'query' => $search_result->getQuery(),
); );

View File

@@ -36,6 +36,7 @@ class collection implements cache_cacheableInterface
protected $databox; protected $databox;
protected $is_active; protected $is_active;
protected $binary_logo; protected $binary_logo;
protected $ord;
protected $app; protected $app;
const PIC_LOGO = 'minilogos'; const PIC_LOGO = 'minilogos';
@@ -63,6 +64,7 @@ class collection implements cache_cacheableInterface
$this->available = $datas['available']; $this->available = $datas['available'];
$this->pub_wm = $datas['pub_wm']; $this->pub_wm = $datas['pub_wm'];
$this->name = $datas['name']; $this->name = $datas['name'];
$this->ord = $datas['ord'];
$this->prefs = $datas['prefs']; $this->prefs = $datas['prefs'];
$this->labels = $datas['labels']; $this->labels = $datas['labels'];
@@ -96,7 +98,7 @@ class collection implements cache_cacheableInterface
$conn = connection::getPDOConnection($this->app); $conn = connection::getPDOConnection($this->app);
$sql = 'SELECT server_coll_id, sbas_id, base_id, active FROM bas $sql = 'SELECT server_coll_id, sbas_id, base_id, active, ord FROM bas
WHERE server_coll_id = :coll_id AND sbas_id = :sbas_id'; WHERE server_coll_id = :coll_id AND sbas_id = :sbas_id';
$stmt = $conn->prepare($sql); $stmt = $conn->prepare($sql);
@@ -109,6 +111,7 @@ class collection implements cache_cacheableInterface
if ($row) { if ($row) {
$this->is_active = ! ! $row['active']; $this->is_active = ! ! $row['active'];
$this->base_id = (int) $row['base_id']; $this->base_id = (int) $row['base_id'];
$this->ord = (int) $row['ord'];
} }
$stmt->closeCursor(); $stmt->closeCursor();
@@ -119,6 +122,7 @@ class collection implements cache_cacheableInterface
, 'available' => $this->available , 'available' => $this->available
, 'pub_wm' => $this->pub_wm , 'pub_wm' => $this->pub_wm
, 'name' => $this->name , 'name' => $this->name
, 'ord' => $this->ord
, 'prefs' => $this->prefs , 'prefs' => $this->prefs
, 'labels' => $this->labels , 'labels' => $this->labels
); );
@@ -144,6 +148,20 @@ class collection implements cache_cacheableInterface
return $this; return $this;
} }
public function get_ord()
{
return $this->ord;
}
public function set_ord($ord)
{
$this->app['phraseanet.appbox']->set_collection_order($this, $ord);
$this->delete_data_from_cache();
$this->app['phraseanet.appbox']->delete_data_from_cache(appbox::CACHE_LIST_BASES);
return $this;
}
public function disable(appbox $appbox) public function disable(appbox $appbox)
{ {
$sql = 'UPDATE bas SET active=0 WHERE base_id = :base_id'; $sql = 'UPDATE bas SET active=0 WHERE base_id = :base_id';

View File

@@ -0,0 +1,90 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2012 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Alchemy\Phrasea\Application;
use Symfony\Component\Process\ExecutableFinder;
class patch_3819 implements patchInterface
{
/** @var string */
private $release = '3.8.1';
/** @var array */
private $concern = array(base::APPLICATION_BOX);
/**
* {@inheritdoc}
*/
public function get_release()
{
return $this->release;
}
/**
* {@inheritdoc}
*/
public function require_all_upgrades()
{
return false;
}
/**
* {@inheritdoc}
*/
public function concern()
{
return $this->concern;
}
/**
* {@inheritdoc}
*/
public function apply(base $appbox, Application $app)
{
$sql = 'SELECT base_id, ord, sbas_id
FROM `bas`
ORDER BY sbas_id, ord';
$stmt = $appbox->get_connection()->prepare($sql);
$stmt->execute();
$rs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor();
$sbasData = array();
$sbas_id = null;
$reorder = array();
foreach ($rs as $row) {
$sbasData[$row['sbas_id']][] = array('base_id' => $row['base_id']);
if ($sbas_id !== $row['sbas_id']) {
$orders = array();
}
$sbas_id = $row['sbas_id'];
if (in_array($row['ord'], $orders, true)) {
$reorder[] = $row['sbas_id'];
}
$orders[] = $row['ord'];
}
$reorder = array_unique($reorder);
if (count($reorder) > 0) {
$sql = 'UPDATE bas SET ord = :ord WHERE base_id = :base_id';
$stmt = $appbox->get_connection()->prepare($sql);
foreach ($reorder as $sbas_id) {
$i = 1;
foreach ($sbasData[$sbas_id] as $data) {
$stmt->execute(array('base_id' => $data['base_id'], 'ord' => $i++));
}
}
$stmt->closeCursor();
}
return true;
}
}

View File

@@ -57,7 +57,6 @@ $groups = array(
, '//include/jquery.tooltip.js' , '//include/jquery.tooltip.js'
, '//include/jslibs/jquery.contextmenu_scroll.js' , '//include/jslibs/jquery.contextmenu_scroll.js'
, '//include/jslibs/jquery.print.js' , '//include/jslibs/jquery.print.js'
, '//include/jslibs/jquery.multiselect.js'
, '//include/jslibs/jquery.cluetip.js' , '//include/jslibs/jquery.cluetip.js'
, '//include/jquery.nicoslider.js' , '//include/jquery.nicoslider.js'
, '//skins/report/report.js' , '//skins/report/report.js'

View File

@@ -6,7 +6,7 @@
<tr> <tr>
<td valign="center" align="center"> <td valign="center" align="center">
<select size=16 name="coll-order" id="coll-order" style="width:140px;"> <select size=16 name="coll-order" id="coll-order" style="width:140px;">
{% for collection in databox.get_collections() %} {% for collection in collections %}
<option value="{{ collection.get_base_id() }}"> {{ collection.get_name() }}</option> <option value="{{ collection.get_base_id() }}"> {{ collection.get_name() }}</option>
{% endfor %} {% endfor %}
</select> </select>
@@ -35,6 +35,11 @@
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function(){ $(document).ready(function(){
var offsets = [
{% for collection in collections %}
{% if not loop.first %},{% endif %} {{ collection.get_ord() }}
{% endfor %}
];
var select = $("#coll-order"); var select = $("#coll-order");
var upButton = $('#upbutton'); var upButton = $('#upbutton');
var downButton = $('#downbutton'); var downButton = $('#downbutton');
@@ -63,9 +68,11 @@
applyButton.bind('click', function() { applyButton.bind('click', function() {
var $this = $(this); var $this = $(this);
var order = []; var order = [];
// clone the array
var appliedoffsets = offsets.slice(0);
select.find('option').each(function(i, option){ select.find('option').each(function(i, option){
order[i] = {id: $(this).val(), name: $(this).text()}; order.push({id: $(this).val(), offset: appliedoffsets.shift()});
}); });
$.ajax({ $.ajax({

View File

@@ -15,25 +15,36 @@
</div> </div>
</div> </div>
</div> </div>
{% set all_coll = dashboard.getAllColl() %}
<div class="form2"> <div class="form2">
<div class="form_titre">{% trans "report:: 2 - Bases" %}</div> <div class="form_titre">{% trans "report:: 2 - Bases" %}</div>
<div id="select_one"> <div id="select_one">
{% block base_selector %} <ul class="multiselect" style="max-height: 150px; overflow-y: auto; overflow-x: hidden;">
{% set all_coll = dashboard.getAllColl() %} <li>
<select name="popbases[]" class="multiselect" multiple="multiple" id="popbases"> <a href="javascript:void(0);" class="select-all">
{% for the_base_coll in all_coll %} {% trans %}Select all{% endtrans %}
<optgroup label="{{ the_base_coll.name_sbas }}"> </a>
{% for a_coll in the_base_coll.sbas_collections %} <a href="javascript:void(0);" class="deselect-all">
<option value="{{ a_coll.sbas_id}}_{{ a_coll.coll_id }}">{{ a_coll.name }}</option> {% trans %}Deselect all{% endtrans %}
</a>
</li>
{% for the_base_coll in all_coll %}
<li><label data-group-id="{{ loop.index }}" class="multiselect-group"><b>{{ the_base_coll.name_sbas }}</b></label></li>
{% for a_coll in the_base_coll.sbas_collections %}
<li>
<a href="javascript:void(0);">
<label class="checkbox">
<input name="popbases[]" checked="checked" type="checkbox" class="coll-checkbox checkbox-{{ loop.parent.loop.index }}" value="{{ a_coll.sbas_id}}_{{ a_coll.coll_id }}">
{{ a_coll.name }}
</label>
</a>
</li>
{% endfor %}
{% endfor %} {% endfor %}
</optgroup> </ul>
{% endfor %}
</select>
{% endblock base_selector %}
</div> </div>
</div> </div>
{% endblock form_date_and_base %} {% endblock form_date_and_base %}

View File

@@ -924,6 +924,29 @@ abstract class ApiAbstract extends \PhraseanetWebTestCaseAbstract
} }
} }
/**
* @dataProvider provideAvailableSearchMethods
*/
public function testRecordsSearchRouteWithQuery($method)
{
$this->setToken(self::$token);
self::$DI['app']['phraseanet.SE'] = $this->getMock('Alchemy\Phrasea\SearchEngine\SearchEngineInterface');
self::$DI['app']['phraseanet.SE']->expects($this->once())
->method('query')
->with('koala', 0, 10)
->will($this->returnValue(
$this->getMockBuilder('Alchemy\Phrasea\SearchEngine\SearchEngineResult')
->disableOriginalConstructor()
->getMock()
));
$crawler = self::$DI['client']->request($method, '/api/v1/records/search/', $this->getParameters(array('query' => 'koala')), array(), array('HTTP_Accept' => $this->getAcceptMimeType()));
}
public function provideAvailableSearchMethods()
{
return array(array('POST'), array('GET'));
}
/** /**
* @covers \API_V1_adapter::caption_records * @covers \API_V1_adapter::caption_records
*/ */

View File

@@ -12,7 +12,7 @@ class SearchEngineSuggestionTest extends \PhraseanetPHPUnitAbstract
public function testSetUp() public function testSetUp()
{ {
$words = 'plutôt cela'; $words = 'plutôt cela';
$query = 'Katy Query'; $query = 'Batman';
$hits = 42; $hits = 42;
$suggestion = new SearchEngineSuggestion($query, $words, $hits); $suggestion = new SearchEngineSuggestion($query, $words, $hits);
@@ -20,4 +20,36 @@ class SearchEngineSuggestionTest extends \PhraseanetPHPUnitAbstract
$this->assertEquals($query, $suggestion->getQuery()); $this->assertEquals($query, $suggestion->getQuery());
$this->assertEquals($words, $suggestion->getSuggestion()); $this->assertEquals($words, $suggestion->getSuggestion());
} }
public function testNullHits()
{
$words = 'plutôt cela';
$query = 'Batman';
$hits = null;
$suggestion = new SearchEngineSuggestion($query, $words, $hits);
$this->assertNull($suggestion->getHits());
$this->assertEquals($query, $suggestion->getQuery());
$this->assertEquals($words, $suggestion->getSuggestion());
}
public function testToArray()
{
$words = 'plutôt cela';
$query = 'Batman';
$hits = 35;
$suggestion = new SearchEngineSuggestion($query, $words, $hits);
$this->assertEquals(array('query' => $words, 'hits' => 35), $suggestion->toArray());
}
public function testToArrayWithNullValue()
{
$words = 'plutôt cela';
$query = 'Batman';
$hits = null;
$suggestion = new SearchEngineSuggestion($query, $words, $hits);
$this->assertEquals(array('query' => $words, 'hits' => null), $suggestion->toArray());
}
} }

View File

@@ -6,32 +6,32 @@
color : '#F6F2F1', color : '#F6F2F1',
sliderHeight : false sliderHeight : false
}; };
var opts = $.extend({}, $.fn.nicoslider.defaults,defaults, options); var opts = $.extend({}, $.fn.nicoslider.defaults,defaults, options);
return this.each(function(){ return this.each(function(){
new nicoslide(this, opts); new nicoslide(this, opts);
}); });
}; };
var nicoslide = function(slider, o) var nicoslide = function(slider, o)
{ {
var $slider = $(slider); var $slider = $(slider);
$sliderWidth = $slider.parent().innerWidth(); $sliderWidth = $slider.parent().innerWidth();
$sliderCss = { $sliderCss = {
'width':$sliderWidth, 'width':$sliderWidth,
'background-color':o.color 'background-color':o.color
}; };
$slider.css($sliderCss); $slider.css($sliderCss);
var ul = $slider.find("ul"); var ul = $slider.find("ul");
var ulWidth = 0; var ulWidth = 0;
var liHeight = 0; var liHeight = 0;
$slider.find("li").each(function(){ $slider.find("li").each(function(){
ulWidth += $(this).width() + 5; ulWidth += $(this).width() + 5;
ulWidth += parseInt($(this).css("padding-left")); ulWidth += parseInt($(this).css("padding-left"));
@@ -47,116 +47,97 @@
{ {
$scrollWidth = 30; $scrollWidth = 30;
} }
var $wrapperWidth = Math.round(parseInt($sliderWidth) - ( 2 * $scrollWidth )); var $wrapperWidth = Math.round(parseInt($sliderWidth) - ( 2 * $scrollWidth ));
if(ulWidth > $wrapperWidth) if(ulWidth > $wrapperWidth)
{ {
ul.wrapAll("<div class='wrapper'></div>"); ul.wrapAll("<div class='wrapper'></div>");
$wrapper = $slider.find(".wrapper"); $wrapper = $slider.find(".wrapper");
$ulHeight = ul.height(); $ulHeight = ul.height();
$wrapper.width($wrapperWidth); $wrapper.width($wrapperWidth);
$wrapper.height($ulHeight);
$wrapperCss= { $wrapperCss= {
'overflow':'hidden', 'overflow':'hidden',
'float':'left', 'float':'left',
'position':'relative' 'position':'relative'
}; };
$wrapper.css($wrapperCss); $wrapper.css($wrapperCss);
ul.css('position', 'absolute');
ul.width(ulWidth); ul.width(ulWidth);
$slider.prepend("<div class='scrollleft'></div>"); $slider.prepend("<div class='scrollleft'></div>");
$slider.append("<div class='scrollright'></div>"); $slider.append("<div class='scrollright'></div>");
var rightScroll = $slider.find(".scrollright"); var rightScroll = $slider.find(".scrollright");
var leftScroll = $slider.find(".scrollleft"); var leftScroll = $slider.find(".scrollleft");
rightScroll.append("<div class='rb'>&gt;</div>"); rightScroll.append("<div class='rb'>&gt;</div>");
leftScroll.append("<div class='lb'>&lt;</div>"); leftScroll.append("<div class='lb'>&lt;</div>");
$("div.rb").css('float', 'right'); $("div.rb").css('float', 'right');
rightCss = { rightCss = {
'width' : $scrollWidth - ($wrapper.outerWidth(true) - $wrapper.innerWidth()), 'width' : $scrollWidth - ($wrapper.outerWidth(true) - $wrapper.innerWidth()),
'height' : liHeight, 'height' : liHeight + 5,
'float' : 'right', 'float' : 'right',
'background-color' : o.color 'background-color' : o.color,
'cursor': 'pointer',
' user-select': 'none'
}; };
leftCss = { leftCss = {
'width' : $scrollWidth - ($wrapper.outerWidth(true) - $wrapper.innerWidth()), 'width' : $scrollWidth - ($wrapper.outerWidth(true) - $wrapper.innerWidth()),
'height' : liHeight, 'height' : liHeight + 5,
'float' : 'left', 'float' : 'left',
'background-color' : o.color 'background-color' : o.color,
'cursor': 'pointer',
' user-select': 'none'
}; };
leftScroll.css(leftCss); leftScroll.css(leftCss);
rightScroll.css(rightCss); rightScroll.css(rightCss);
var rightScrollWidth = rightScroll.width(); var rightScrollWidth = rightScroll.width();
var leftScrollWidth = leftScroll.width(); var leftScrollWidth = leftScroll.width();
var scrollInterval = 100;
var scrollXpos = 0; var scrollXpos = 0;
var scrollStepSpeed = 20; var scrollStepSpeed = 40;
var speed = 8; var speed = 8;
var repeat = null;
var shift = o.start; var shift = o.start;
//calcul position zone droite
rightScroll.bind("mousemove", function(e){
var x = e.pageX - ($(this).offset().left);
scrollXpos = Math.round((x / rightScrollWidth) * scrollStepSpeed);
});
//calcul position zone gauche
leftScroll.bind("mousemove", function(e){
var x = $(this).innerWidth() - (e.pageX - $(this).offset().left);
scrollXpos = Math.round((x / leftScrollWidth) * scrollStepSpeed);
});
//scroll a droite //scroll a droite
rightScroll.bind("mouseenter", function(){ rightScroll.bind("click", function(e){
repeat = setInterval(function(){ var x = e.pageX - ($(this).offset().left);
scrollXpos = Math.round((x / rightScrollWidth) * scrollStepSpeed);
shift += (scrollXpos * speed); shift += (scrollXpos * speed);
if(shift > (ulWidth - $wrapperWidth) + 50) if(shift > (ulWidth - $wrapperWidth) + 50)
{ {
shift = (ulWidth - $wrapperWidth) + 50; shift = (ulWidth - $wrapperWidth) + 50;
} }
ul.animate({ ul.animate({
left: -shift left: -shift
}, 1); }, 1);
}, scrollInterval);
}); });
//scroll a gauche //scroll a gauche
leftScroll.bind("mouseenter", function(){ leftScroll.bind("click", function(e){
repeat = setInterval(function(){ var x = $(this).innerWidth() - (e.pageX - $(this).offset().left);
scrollXpos = Math.round((x / leftScrollWidth) * scrollStepSpeed);
shift -= (scrollXpos * speed); shift -= (scrollXpos * speed);
if(shift < 0) if(shift < 0)
{ {
shift = 0; shift = 0;
} }
ul.animate({ ul.animate({
left: -shift left: -shift
}, 1); }, 1);
}, scrollInterval);
});
//on stop a droite
rightScroll.bind("mouseout", function(){
clearInterval(repeat);
scrollXpos = 0;
});
//on stop a gauche
leftScroll.bind("mouseout", function(){
clearInterval(repeat);
scrollXpos = 0;
}); });
} }
}; };

View File

@@ -1,431 +0,0 @@
/*
* jQuery MultiSelect Plugin 0.6
* Copyright (c) 2010 Eric Hynds
*
* http://www.erichynds.com/jquery/jquery-multiselect-plugin-with-themeroller-support/
* Inspired by Cory S.N. LaViska's implementation, A Beautiful Site (http://abeautifulsite.net/) 2009
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){
$.fn.multiSelect = function(opts){
opts = $.extend({}, $.fn.multiSelect.defaults, opts);
return this.each(function(){
return new MultiSelect(this, opts);
});
};
// counter to dynamically generate label/option IDs if they don't exist
var multiselectID = 0;
var MultiSelect = function(select,o){
var $select = $original = $(select),
$options, $header, $labels,
html = [],
optgroups = [],
isDisabled = $select.is(':disabled'),
id = select.id || 'ui-multiselect-'+multiselectID++; // unique ID for the label & option tags
html.push('<a id="'+ id +'" class="ui-multiselect ui-widget ui-state-default ui-corner-all' + (isDisabled || o.disabled ? ' ui-state-disabled' : '') + '" style="margin-left: 10px;margin-right: 10px;height:20px;">');
html.push('<input readonly="readonly" type="text" class="" value="'+ o.allSelectedText +'" title="'+ select.title +'" /></a>');
html.push('<div class="ui-multiselect-options' + (o.shadow ? ' ui-multiselect-shadow' : '') + ' ui-widget ui-widget-content ui-corner-all" style="margin-left: 10px;margin-right: 10px;border:1px solid #212121;">');
if(o.showHeader){
html.push('<div class="ui-widget-header ui-helper-clearfix ui-corner-all ui-multiselect-header" >');
html.push('<ul class="ui-helper-reset">');
html.push('<li><a class="ui-multiselect-all" href="" style="color:#FF9000;"><span class="ui-icon ui-icon-check"></span>' + o.checkAllText + '</a></li>');
html.push('<li><a class="ui-multiselect-none" href="" style="color:#FF9000;"><span class="ui-icon ui-icon-closethick"></span>' + o.unCheckAllText + '</a></li>');
html.push('<li class="ui-multiselect-close"><a href="" class="ui-multiselect-close ui-icon ui-icon-circle-close"></a></li>');
html.push('</ul>');
html.push('</div>');
}
// build options
html.push('<ul class="ui-multiselect-checkboxes ui-helper-reset">');
/*
If this select is disabled, remove the actual disabled attribute and let themeroller's .ui-state-disabled class handle it.
This is a workaround for jQuery bug #6211 where options in webkit inherit the select's disabled property. This
won't achieve the same level of 'disabled' behavior (the checkboxes will still be present in form submission),
but it at least gives you a way to emulate the UI.
*/
if(isDisabled){
$select.removeAttr("disabled");
}
$select.find('option').each(function(i){
var $this = $(this),
title = $this.html(),
value = this.value,
inputID = this.id || "ui-multiselect-"+id+"-option-"+i,
$parent = $this.parent(),
hasOptGroup = $parent.is('optgroup'),
isDisabled = $this.is(':disabled'),
labelClasses = ['ui-corner-all'];
if(hasOptGroup){
var label = $parent.attr('label');
if($.inArray(label,optgroups) === -1){
html.push('<li class="ui-multiselect-optgroup-label"><a href="#" class="ui-multiselect-all" style="color:#FF9000;float:left;width:350px;">' + label + '</a><a href="#" style="float:right;" class="ui-multiselect-toggleclose ui-icon ui-icon-triangle-1-s"></a></li>');
optgroups.push(label);
}
}
if(value.length > 0){
if(isDisabled){
labelClasses.push('ui-state-disabled');
}
html.push('<li class="' + (isDisabled ? 'ui-multiselect-disabled' : '') +'">');
html.push('<label for="'+inputID+'" class="'+labelClasses.join(' ')+'"><input id="'+inputID+'" type="'+(o.multiple ? 'checkbox' : 'radio')+'" checked="checked" name="'+select.name+'" value="'+value+'" title="'+title+'"');
if($this.is(':selected')){
html.push(' checked="checked"');
}
if(isDisabled){
html.push(' disabled="disabled"');
}
html.push(' />'+title+'</label></li>');
}
});
html.push('</ul></div>');
// append the new control to the DOM; cache queries
$select = $select.after( html.join('') ).next('a.ui-multiselect');
$options = $select.next('div.ui-multiselect-options');
$header = $options.find('div.ui-multiselect-header');
$labels = $options.find('label').not('.ui-state-disabled');
//hide by default
$options.find('li.ui-multiselect-optgroup-label a.ui-multiselect-toggleclose').parent().nextUntil('li.ui-multiselect-optgroup-label').find('label').hide();
// calculate widths
var iconWidth = $select.find('span.ui-icon').outerWidth(), inputWidth = $original.outerWidth(), totalWidth = inputWidth+iconWidth;
if( /\d/.test(o.minWidth) && totalWidth < o.minWidth){
inputWidth = o.minWidth-iconWidth;
totalWidth = o.minWidth;
}
// set widths
$select.width(totalWidth).find('input').width(inputWidth - 6);
// build header links
if(o.showHeader){
$header.find('a').click(function(e){
var $this = $(this);
// close link
if($this.hasClass('ui-multiselect-close')){
$options.trigger('close');
// check all / uncheck all
} else {
var checkAll = $this.hasClass('ui-multiselect-all');
$options.trigger('toggleChecked', [(checkAll ? true : false)]);
checkAll ? $options.find('li.ui-multiselect-optgroup-label a.ui-multiselect-all').css("color", "#FF9000") : $options.find('li.ui-multiselect-optgroup-label a.ui-multiselect-all').css("color", "white") ;
o[ checkAll ? 'onCheckAll' : 'onUncheckAll']['call'](this);
}
e.preventDefault();
});
}
var updateSelected = function(){
var $inputs = $labels.find('input'),
$checked = $inputs.filter(':checked'),
$tot = $inputs.length,
value = '',
numChecked = $checked.length;
if(numChecked === 0){
value = o.noneSelectedText;
} else if($tot == numChecked ) {
value = o.allSelectedText;
}else {
if($.isFunction(o.selectedText)){
value = o.selectedText.call(this, numChecked, $inputs.length, $checked.get());
} else if( /\d/.test(o.selectedList) && o.selectedList > 0 && numChecked <= o.selectedList){
value = $checked.map(function(){ return this.title; }).get().join(', ');
} else {
value = o.selectedText.replace('#', numChecked).replace('#', $inputs.length);
}
}
$select.find('input').val(value);
return value;
};
// the select box events
$select.bind({
click: function(){
$options.trigger('toggle');
},
keypress: function(e){
switch(e.keyCode){
case 27: // esc
case 38: // up
$options.trigger('close');
break;
case 40: // down
case 0: // space
$options.trigger('toggle');
break;
}
},
/*mouseenter: function(){
if(!$select.hasClass('ui-state-disabled')){
$(this).addClass('ui-state-hover');
}
},
mouseleave: function(){
$(this).removeClass('ui-state-hover');
},*/
focus: function(){
if(!$select.hasClass('ui-state-disabled')){
$(this).addClass('ui-state-focus');
}
},
blur: function(){
$(this).removeClass('ui-state-focus');
}
});
// bind custom events to the options div
$options.bind({
'close': function(e, others){
others = others || false;
// hides all other options but the one clicked
if(others === true){
$('div.ui-multiselect-options')
.filter(':visible')
.fadeOut(o.fadeSpeed)
.prev('a.ui-multiselect')
.removeClass('ui-state-active')
.trigger('mouseout');
// hides the clicked options
} else {
$select.removeClass('ui-state-active').trigger('mouseout');
$options.fadeOut(o.fadeSpeed);
}
},
'open': function(e, closeOthers){
// bail if this widget is disabled
if($select.hasClass('ui-state-disabled')){
return;
}
// use position() if inside ui-widget-content, because offset() won't cut it.
var offset = $select.position(),
$container = $options.find('ul:last'),
top, width;
// calling select is active
$select.addClass('ui-state-active');
// hide all other options
if(closeOthers || typeof closeOthers === 'undefined'){
$options.trigger('close', [true]);
}
// calculate positioning
if(o.position === 'middle'){
top = ( offset.top+($select.height()/2)-($options.outerHeight()/2) );
} else if(o.position === 'top'){
top = (offset.top-$options.outerHeight());
} else {
top = (offset.top+$select.outerHeight());
}
// calculate the width of the options menu
width = $select.width()-parseInt($options.css('padding-left'),10)-parseInt($options.css('padding-right'),10);
// select the first option
$labels.filter('label:first').trigger('mouseenter').trigger('focus');
// show the options div + position it
$options.css({
position: 'absolute',
top: top+'px',
left: offset.left+'px',
width: width+'px'
}).show();
// set the scroll of the checkbox container
$container.scrollTop(0);
// set the height of the checkbox container
if(o.maxHeight){
$container.css('height', o.maxHeight);
}
o.onOpen.call($options[0]);
},
'toggle': function(){
$options.trigger( $(this).is(':hidden') ? 'open' : 'close' );
},
'traverse': function(e, start, keycode){
var $start = $(start),
moveToLast = (keycode === 38 || keycode === 37) ? true : false,
// select the first li that isn't an optgroup label / disabled
$next = $start.parent()[moveToLast ? 'prevAll' : 'nextAll']('li:not(.ui-multiselect-disabled, .ui-multiselect-optgroup-label)')[ moveToLast ? 'last' : 'first']();
// if at the first/last element
if(!$next.length){
var $container = $options.find("ul:last");
// move to the first/last
$options.find('label')[ moveToLast ? 'last' : 'first' ]().trigger('mouseover');
// set scroll position
$container.scrollTop( moveToLast ? $container.height() : 0 );
} else {
$next.find('label').trigger('mouseenter');
}
},
'toggleChecked': function(e, flag, group){
var $inputs = (group && group.length) ? group : $labels.find('input');
$inputs.not(':disabled').attr('checked', flag);
updateSelected();
}
})
.find('li.ui-multiselect-optgroup-label a.ui-multiselect-all')
.click(function(e){
// optgroup label toggle support
if(cssColorToHex($(this).css("color")) == "#ffffff")
{
$(this).css("color", "rgb(255,144,0)");
}
else
{
$(this).css("color", "rgb(255,255,255)");
}
var $checkboxes = $(this).parent().nextUntil('li.ui-multiselect-optgroup-label').find('input');
$options.trigger('toggleChecked', [ ($checkboxes.filter(':checked').length === $checkboxes.length) ? false : true, $checkboxes]);
o.onOptgroupToggle.call(this, $checkboxes.get());
e.preventDefault();
});
$options.find('li.ui-multiselect-optgroup-label a.ui-multiselect-toggleclose')
.click(function(e){
var $label = $(this).parent().nextUntil('li.ui-multiselect-optgroup-label').find('label');
// optgroup label toggle support
$label.toggle();
e.preventDefault();
});
/*************************************************************************/
function cssColorToHex(colorStr)
{
var hex = '#';
$.each(colorStr.substring(4).split(','), function(i, str){
var h = ($.trim(str.replace(')',''))*1).toString(16);
hex += (h.length == 1) ? "0" + h : h;
});
return hex;
};
/**************************************************************************/
// labels/checkbox events
$labels.bind({
/*mouseenter: function(){
$labels.removeClass('ui-state-hover');
$(this).addClass('ui-state-hover').find('input').focus();
},*/
keyup: function(e){
switch(e.keyCode){
case 27: // esc
$options.trigger('close');
break;
case 38: // up
case 40: // down
case 37: // left
case 39: // right
$options.trigger('traverse', [this, e.keyCode]);
break;
case 13: // enter
e.preventDefault();
$(this).click();
break;
}
}
})
.find('input')
.bind('click', function(e){
o.onCheck.call(this);
updateSelected();
});
// remove the original input element
$original.remove();
// apply bgiframe if available
if($.fn.bgiframe){
$options.bgiframe();
}
// open by default?
if(o.state === 'open'){
$options.trigger('open', [false]);
}
// update the number of selected elements when the page initially loads, and use that as the defaultValue. necessary for form resets when options are pre-selected.
$select.find('input')[0].defaultValue = updateSelected();
return $select;
};
// close each select when clicking on any other element/anywhere else on the page
$(document).bind('click', function(e){
var $target = $(e.target);
if(!$target.closest('div.ui-multiselect-options').length && !$target.parent().hasClass('ui-multiselect')){
$('div.ui-multiselect-options').trigger('close', [true]);
}
});
// default options
$.fn.multiSelect.defaults = {
showHeader: true,
maxHeight: 380, /* max height of the checkbox container (scroll) in pixels */
minWidth: 380, /* min width of the entire widget in pixels. setting to 'auto' will disable */
checkAllText: 'Cochez tout',
unCheckAllText: 'Décochez Tout',
noneSelectedText: 'Aucune base selectionnée',
selectedText: '# collections selectionnées',
allSelectedText : 'Toutes les bases',
selectedList: 0,
position: 'bottom', /* top|middle|bottom */
shadow: false,
fadeSpeed: 200,
disabled: false,
state: 'closed',
multiple: true,
onCheck: function(){}, /* when an individual checkbox is clicked */
onOpen: function(){}, /* when the select menu is opened */
onCheckAll: function(){}, /* when the check all link is clicked */
onUncheckAll: function(){}, /* when the uncheck all link is clicked */
onOptgroupToggle: function(){} /* when the optgroup heading is clicked */
};
})(jQuery);

View File

@@ -99,29 +99,6 @@ ul {
/** Button style */ /** Button style */
.btn {
@glow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 7px rgba(0, 0, 0, 1);
.glow(@glow);
.border-radius(@borderRadiusSmall);
text-shadow : 0 -1px 0 rgba(0, 0, 0, 0.5);
}
.btn-success {
.gradient (@btnSuccessBackground, 0.7);
}
.btn-info {
.gradient (@btnInfoBackground, 0.7);
}
.btn-success:hover {
.gradient (@btnSuccessBackgroundHighlight, 0.7);
}
.btn-info:hover {
.gradient (@btnInfoBackgroundHighlight, 0.7);
}
.btn-flat { .btn-flat {
filter:progid:DXImageTransform.Microsoft.Gradient(enabled='false'); filter:progid:DXImageTransform.Microsoft.Gradient(enabled='false');
-webkit-box-shadow: none; -webkit-box-shadow: none;
@@ -195,6 +172,14 @@ ul {
width: 100% !important; width: 100% !important;
} }
.footer a {
color: @footerLinkColor;
}
.footer a:hover {
color: @footerLinkColorHover;
}
/** Alert style */ /** Alert style */
.alert { .alert {
@@ -208,7 +193,7 @@ ul {
.alert .alert-block-close { .alert .alert-block-close {
width:45px; width:45px;
text-align: center; text-align: center;
font-size:36px font-size:36px;
} }
.alert table { .alert table {
@@ -233,6 +218,10 @@ ul {
border-left: 1px solid darken(@successBackground, 20%); border-left: 1px solid darken(@successBackground, 20%);
} }
.alert.alert-success .alert-block-close a {
color: @successText;
}
.alert.alert-error .alert-block-content { .alert.alert-error .alert-block-content {
border-right: 1px solid lighten(@errorBackground, 10%); border-right: 1px solid lighten(@errorBackground, 10%);
} }
@@ -241,6 +230,10 @@ ul {
border-left: 1px solid darken(@errorBackground, 20%); border-left: 1px solid darken(@errorBackground, 20%);
} }
.alert.alert-error .alert-block-close a {
color: @errorText;
}
.alert.alert-info .alert-block-content { .alert.alert-info .alert-block-content {
border-right: 1px solid lighten(@infoBackground, 10%); border-right: 1px solid lighten(@infoBackground, 10%);
} }
@@ -249,6 +242,10 @@ ul {
border-left: 1px solid darken(@infoBackground, 20%); border-left: 1px solid darken(@infoBackground, 20%);
} }
.alert.alert-info .alert-block-close a {
color: @infoText;
}
.alert.alert-warning .alert-block-content { .alert.alert-warning .alert-block-content {
border-right: 1px solid lighten(@warningBackground, 10%); border-right: 1px solid lighten(@warningBackground, 10%);
} }
@@ -257,6 +254,10 @@ ul {
border-left: 1px solid darken(@warningBackground, 20%); border-left: 1px solid darken(@warningBackground, 20%);
} }
.alert.alert-warning .alert-block-close a {
color: @warningText;
}
.alert .close { .alert .close {
position: static; position: static;
} }

View File

@@ -81,6 +81,8 @@
// ------------------------- // -------------------------
@linkColor: #fff; @linkColor: #fff;
@linkColorHover: darken(@linkColor, 15%); @linkColorHover: darken(@linkColor, 15%);
@footerLinkColor: @linkColor;
@footerLinkColorHover: @linkColorHover;
// Typography // Typography
@@ -132,11 +134,11 @@
@btnPrimaryBackground: @linkColor; @btnPrimaryBackground: @linkColor;
@btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 20%); @btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 20%);
@btnInfoBackground: #1c607f; @btnInfoBackground: #3d8fa8;
@btnInfoBackgroundHighlight: darken(@btnInfoBackground, 10%); @btnInfoBackgroundHighlight: #0d4461;
@btnSuccessBackground: #1ea062; @btnSuccessBackground: #2fac74;
@btnSuccessBackgroundHighlight: darken(@btnSuccessBackground, 10%); @btnSuccessBackgroundHighlight: #118749;
@btnWarningBackground: lighten(@orange, 15%); @btnWarningBackground: lighten(@orange, 15%);
@btnWarningBackgroundHighlight: @orange; @btnWarningBackgroundHighlight: @orange;

View File

@@ -155,6 +155,18 @@
var buttons = {}; var buttons = {};
buttons[language.send] = function(){ buttons[language.send] = function(){
if ($.trim($('input[name="name"]', $dialog.getDomElement()).val()) === '') {
options = {
size : 'Alert',
closeButton : true,
title : language.warning
},
$dialog = p4.Dialog.Create(options, 3);
$dialog.setContent(language.FeedBackNameMandatory);
return false;
}
$dialog.Close(); $dialog.Close();
$('input[name="name"]', $FeedBackForm).val($('input[name="name"]', $dialog.getDomElement()).val()); $('input[name="name"]', $FeedBackForm).val($('input[name="name"]', $dialog.getDomElement()).val());

File diff suppressed because it is too large Load Diff