Utilisateur:Gede/vector.js
Apparence
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;
Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.// <nowiki>
importScript('User:Alphos/historyselect.js');
//wgVectorEnabledModules.simplesearch = false;
jQuery(document).ready(function($){
$('table.sortable_new').each(function(){
var thead = $(this).find('tr:first').detach();
$(this).find('tbody:first').before('<thead />');
$(this).find('thead').prepend(thead);
if($(this).hasClass('pager_new')) {
$(this).ariaSorTable({rowsToShow: 10, pager: true,});
} else {
$(this).ariaSorTable();
}
});
});
jQuery(document).ready(function($){
$('#toc a').click(function(){
var cible = $(this).attr('href');
$(cible).parents('.acc_navbox collapsed').removeClass('acc_navbox collapsed');
});
});
jQuery(document).ready(function($){
$('[tabindex]').attr('tabindex',0);
});
jQuery(document).ready(function($){
$('#searchform').append($('<input />').attr({'type':'hidden','name':'advanced','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns4','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns5','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns8','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns9','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns10','value':1}));
$('#searchform').append($('<input />').attr({'type':'hidden','name':'ns12','value':1}));
});
jQuery(document).ready(function($){
$('#bodyContent > p:first b').wrapInner('<dfn />');
$('#bodyContent > p:first b dfn').unwrap();
});
jQuery(document).ready(function($){
$('#content div.acc_navbox:has(div.acc_navbox)').removeClass('acc_navbox').toggleClass('error').text('Désolé : pas de boîtes déroulantes dans des boîtes déroulantes');
var $navbox=$('#content div.acc_navbox p.acc_navbox_header');
$navbox.each(function(){
var $label = 'Ouvrir/fermer ' + $(this).find('span.acc_navbox_label').text();
$(this).append('<span class="acc_navbox_toggle acc_navbox_space"><a href="#" title="'+$label+'">Enrouler</a></span>');
var $parent = $(this).parent();
var $toggle = $(this).find('span.acc_navbox_toggle a');
if($parent.hasClass('collapsed')) {
$parent.find('ul.acc_navbox_content, div.acc_navbox_content').hide();
var $label = $toggle.text();
if($label == 'Enrouler') {
$toggle.text('Dérouler');
}
}
$parent.attr({'role':'navigation'})
});
$('div.acc_navbox > p.acc_navbox_header > span.acc_navbox_toggle a').click(function(){
var $parent = $(this).parents('div.acc_navbox');
$parent.toggleClass('collapsed');
$parent.find('ul.acc_navbox_content, div.acc_navbox_content').slideToggle('fast');
if($(this).text() == 'Enrouler' || $(this).text() == 'Dérouler') {
$(this).text(($(this).text() == 'Enrouler') ? 'Dérouler' : 'Enrouler');
}
return false;
});
});
importScript('Utilisateur:Lgd/typo.js');
/* test tableau amélioré */
jQuery(document).ready(function($){
$('#p-accessibility ul').append('<li><a title="Vérifier ..." id="acc_new_test" href="#">Complément tableaux</a></li>');
var state=$.cookie('acc_new_test');
if(state=='true' && (mw.config.get('wgAction')=='view')){
acc_new_test();
}
if(state!=null){
$.cookie('acc_new_test',state,{'expires':30,'path':'/'});
}
$('#acc_new_test').click(function(){
acc_new_test();
return false;
});
function acc_new_test(){
$('#acc_new_test').toggleClass('acc_on');
$.cookie('acc_new_test',$('#acc_new_test').is('.acc_on'),{'expires':30,'path':'/'});
if($('#acc_new_test').attr('class') == 'acc_on') {
/*
$('#content table:not(:has(table))').each(function() {
$(this).find('tr:first-child th:only-child').prepend('<span class="error acc_th_error">Vérifiez s\'il faut scinder le tableau en plusieurs tableaux simples<br>ou si cette cellule ne devrait pas être un titre de tableau</span>');
$(this).find('tr:last-child th:only-child').prepend('<span class="error acc_th_error">Vérifiez si cette cellule n\'est pas une note à placer après le tableau</span>');
$(this).find('tr:not(:last-child):not(:first-child) th:only-child').prepend('<span class="error acc_th_error">Vérifiez s\'il faut scinder le tableau en plusieurs tableaux simples</span>');
});
*/
$('#content table tr:first-child th:only-child:not(:has(span.acc_th_error))').prepend('<span class="error acc_th_error">Vérifiez s\'il faut scinder le tableau en plusieurs tableaux simples<br>ou si cette cellule ne devrait pas être un titre de tableau</span>');
$('#content table tr:last-child th:only-child:not(:has(span.acc_th_error))').prepend('<span class="error acc_th_error">Vérifiez si cette cellule n\'est pas une note à placer après le tableau</span>');
$('#content table tr:not(:last-child):not(:first-child) th:only-child:not(:has(span.acc_th_error))').prepend('<span class="error acc_th_error">Vérifiez s\'il faut scinder le tableau en plusieurs tableaux simples</span>');
$('#content table th:not([scope]):not(:has(span.acc_th_error))').prepend('<span class="error acc_th_error">Vérifiez s\'il faut ajouter un SCOPE ou transformer en TD (code wiki: |)</span>');
} else {
$('#content table span.acc_th_error').remove();
}
};
});
/* tests liens from dev corporate */
jQuery(document).ready(function($){
$('#p-accessibility ul').append('<li><a title="Vérifier l\'accessibilité des liens" id="acc_links" href="#">Liens</a></li>');
var state=$.cookie('acc_links');
if(state=='true' && (mw.config.get('wgAction')=='view')){
acc_links();
}
if(state!=null){
$.cookie('acc_links',state,{'expires':30,'path':'/'});
}
$('#acc_links').click(function(){
acc_links();
return false;
});
function acc_links(){
$('#acc_links').toggleClass('acc_on');
$.cookie('acc_links',$('#acc_links').is('.acc_on'),{'expires':30,'path':'/'});
if($('#acc_links').attr('class') == 'acc_on') {
var links = $('a:empty[href]');
if(links.length>0) {
links.addClass('acc_links').before('<span class="error acc_attr_show acc_links">Lien sans libellé (pseudo-contenu CSS)</span>');
}
var img = $('a img:only-child[alt=]').filter(function() {
var texte = $(this).parents('a').text();
return texte.length == 0;
});
if(img.length>0) {
img.before('<span class="error acc_attr_show acc_links">Lien sans libellé (alternative vide)</span>').parents('a').addClass('acc_links');
}
} else {
$('span.acc_links').remove();
$('a').removeClass('acc_links');
}
};
});
/* test titres amélioré */
jQuery(document).ready(function($){
$('#p-accessibility ul').append('<li><a title="Vérifier l\'accessibilité des titres" id="acc_header2" href="#">Titres amélioré</a></li>');
var state=$.cookie('acc_header2');
if(state=='true' && (mw.config.get('wgAction')=='view')){
acc_header2();
}
if(state!=null){
$.cookie('acc_header2',state,{'expires':30,'path':'/'});
}
$('#acc_header2').click(function(){
acc_header2();
return false;
});
function acc_header2(){
$('#acc_header2').toggleClass('acc_on');
$.cookie('acc_header2',$('#acc_header2').is('.acc_on'),{'expires':30,'path':'/'});
if($('#acc_header2').attr('class') == 'acc_on') {
var headers= $('#content :header');
headers.each(function(index) {
if(headers.get(index-1)) {
level = parseInt(headers.get(index).nodeName.substring(2,1));
levelbefore = parseInt(headers.get(index-1).nodeName.substring(2,1));
if(level - levelbefore > 1) {
$(this).addClass('acc_headers').before('<span class="error acc_attr_show acc_headers">Titrage de niveau incorrect</span>');
}
}
});
} else {
$('span.acc_headers').remove();
$('#content :header').removeClass('acc_headers');
}
};
});
/* tests justify from dev corporate */
jQuery(document).ready(function($){
$('#p-accessibility ul').append('<li><a title="Vérifier l\'absence de texte justifié" id="acc_justify" href="#">Justified</a></li>');
var state=$.cookie('acc_justify');
if(state=='true' && (mw.config.get('wgAction')=='view')){
acc_justify();
}
if(state!=null){
$.cookie('acc_justify',state,{'expires':30,'path':'/'});
}
$('#acc_justify').click(function(){
acc_justify();
return false;
});
function acc_justify(){
$('#acc_justify').toggleClass('acc_on');
$.cookie('acc_justify',$('#acc_justify').is('.acc_on'),{'expires':30,'path':'/'});
if($('#acc_justify').attr('class') == 'acc_on') {
var justify = $('#content').find('*').filter(function() {
return $(this).css('text-align') == 'justify';
});
if (justify.length > 0)
justify.each( function() {
$(this).before('<span class="error acc_attr_show acc_justify">Texte justifié</span>').addClass('acc_justify');
});
} else {
$('span.acc_justify').remove();
$('#content').find('*').removeClass('acc_justify');
}
};
});
/* test img amélioré */
jQuery(document).ready(function($){
$('#p-accessibility ul').append('<li><a title="..." id="acc_alt_test" href="#">alt amélioré</a></li>');
/* Alternatives */
var state=$.cookie('wp_acc_alt_test');
if(state=='true'){
acc_alt_test();
}
if(state!=null){
$.cookie('wp_acc_alt_test',state,{'expires':30,'path':'/'});
}
$('#acc_alt_test').click(function(){
acc_alt_test();
return false;
});
function acc_alt_test(){
$('#acc_alt_test').toggleClass('acc_on');
$.cookie('wp_acc_alt_test',$('#acc_alt_test').is('.acc_on'),{'expires':30,'path':'/'});
if($('#acc_alt_test').attr('class') == 'acc_on') {
$('#content img').each(function(){
var $alt = $(this).attr('alt');
var $parent = $(this).parent();
var $grandparent = $parent.parent();
if(!$grandparent.is('.magnify')) {
if($alt == '') {
if($parent.is('a')) {
$alt = '<span class="error">ALT MANQUANT</span>';
} else {
$alt = 'ALT VIDE';
}
} else {
if($alt.length > 120) {
$alt = $alt + '<br /><span class="error">Vérifiez si cette alternative de ' + $alt.length + ' caractères pourrait être plus concise (environ 120 caractères au plus) et si l\'alternative actuelle pourrait être transférée dans la section description de la page de l\'image.</span>';
}
}
if (!$(this).parents().is('.thumb')) {
if($(this).is('img[alt$=.png], img[alt$=.svg], img[alt$=.jpg], img[alt$=.gif], img[alt$=.PNG], img[alt$=.SVG], img[alt$=.JPG], img[alt$=.GIF]')) {
$alt = '<span class="error">ALT MANQUANT</span>';
}
if(($parent.is('a.image') || $parent.is('.mw-file-description')) && !$grandparent.is('.smiley')) {
if($grandparent.is('.flagicon')) {
if(!$(this).is('img[alt^=Drapeau], img[alt^=drapeau], img[alt^=Pavillon], img[alt^=pavillon]')) {
$alt = $alt + '<br /><span class="error">L\'alternative devrait commencer par « Drapeau... » ou « Pavillon... »</span>';
}
} else {
$alt = $alt + '<br /><span class="error">Vérifiez si le lien sur l\'image peut être désactivé (LINK vide)<br />(ou si l\'image peut être transformée en thumb)</span>';
}
}
}
if($parent.is('a')) {
$parent.before('<span class="acc_attr_show">'+$alt+'</span>');
} else {
$(this).before('<span class="acc_attr_show">'+$alt+'</span>');
}
}
});
$('#content table.gallery').before('<span class="acc_attr_show"><span class="error">Les alternatives des images ne peuvent pas être indiquées dans les galeries. (<a href="https://bugzilla.wikimedia.org/show_bug.cgi?id=18682" target="_blank" title="Demande de correction du bug des alternatives d\'images dans les galeries, sur Bugzilla, en anglais (nouvelle fenêtre)">Vous pouvez voter pour la résolution ce bug</a>).</span></span>');
$('#content img[usemap]').before('<span class="acc_attr_show"><span class="error">Les alternatives nécessaires aux images de <span lang="en">timelines</span> ne peuvent pas être indiquées en l\'état actuel de cette extension.</span></span>');
} else {
$('#content span.acc_attr_show').remove();
}
}
});
/*!
* jQuery UI Widget 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Widget
*/
(function($, undefined) {
// jQuery 1.4+
if ($.cleanData) {
var _cleanData = $.cleanData;
$.cleanData = function(elems) {
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
$(elem).triggerHandler("remove");
}
_cleanData(elems);
};
} else {
var _remove = $.fn.remove;
$.fn.remove = function(selector, keepData) {
return this.each(function() {
if (!keepData) {
if (!selector || $.filter(selector, [this]).length) {
$("*", this).add([this]).each(function() {
$(this).triggerHandler("remove");
});
}
}
return _remove.call($(this), selector, keepData);
});
};
}
$.widget = function(name, base, prototype) {
var namespace = name.split(".")[0],
fullName;
name = name.split(".")[1];
fullName = namespace + "-" + name;
if (!prototype) {
prototype = base;
base = $.Widget;
}
// create selector for plugin
$.expr[":"][fullName] = function(elem) {
return !! $.data(elem, name);
};
$[namespace] = $[namespace] || {};
$[namespace][name] = function(options, element) {
// allow instantiation without initializing for simple inheritance
if (arguments.length) {
this._createWidget(options, element);
}
};
var basePrototype = new base();
// we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
// $.each( basePrototype, function( key, val ) {
// if ( $.isPlainObject(val) ) {
// basePrototype[ key ] = $.extend( {}, val );
// }
// });
basePrototype.options = $.extend(true, {},
basePrototype.options);
$[namespace][name].prototype = $.extend(true, basePrototype, {
namespace: namespace,
widgetName: name,
widgetEventPrefix: $[namespace][name].prototype.widgetEventPrefix || name,
widgetBaseClass: fullName
},
prototype);
$.widget.bridge(name, $[namespace][name]);
};
$.widget.bridge = function(name, object) {
$.fn[name] = function(options) {
var isMethodCall = typeof options === "string",
args = Array.prototype.slice.call(arguments, 1),
returnValue = this;
// allow multiple hashes to be passed on init
options = !isMethodCall && args.length ? $.extend.apply(null, [true, options].concat(args)) : options;
// prevent calls to internal methods
if (isMethodCall && options.charAt(0) === "_") {
return returnValue;
}
if (isMethodCall) {
this.each(function() {
var instance = $.data(this, name),
methodValue = instance && $.isFunction(instance[options]) ? instance[options].apply(instance, args) : instance;
// TODO: add this back in 1.9 and use $.error() (see #5972)
// if ( !instance ) {
// throw "cannot call methods on " + name + " prior to initialization; " +
// "attempted to call method '" + options + "'";
// }
// if ( !$.isFunction( instance[options] ) ) {
// throw "no such method '" + options + "' for " + name + " widget instance";
// }
// var methodValue = instance[ options ].apply( instance, args );
if (methodValue !== instance && methodValue !== undefined) {
returnValue = methodValue;
return false;
}
});
} else {
this.each(function() {
var instance = $.data(this, name);
if (instance) {
instance.option(options || {})._init();
} else {
$.data(this, name, new object(options, this));
}
});
}
return returnValue;
};
};
$.Widget = function(options, element) {
// allow instantiation without initializing for simple inheritance
if (arguments.length) {
this._createWidget(options, element);
}
};
$.Widget.prototype = {
widgetName: "widget",
widgetEventPrefix: "",
options: {
disabled: false
},
_createWidget: function(options, element) {
// $.widget.bridge stores the plugin instance, but we do it anyway
// so that it's stored even before the _create function runs
$.data(element, this.widgetName, this);
this.element = $(element);
this.options = $.extend(true, {},
this.options, this._getCreateOptions(), options);
var self = this;
this.element.bind("remove." + this.widgetName,
function() {
self.destroy();
});
this._create();
this._trigger("create");
this._init();
},
_getCreateOptions: function() {
return $.metadata && $.metadata.get(this.element[0])[this.widgetName];
},
_create: function() {},
_init: function() {},
destroy: function() {
this.element.unbind("." + this.widgetName).removeData(this.widgetName);
this.widget().unbind("." + this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass + "-disabled " + "ui-state-disabled");
},
widget: function() {
return this.element;
},
option: function(key, value) {
var options = key;
if (arguments.length === 0) {
// don't return a reference to the internal hash
return $.extend({},
this.options);
}
if (typeof key === "string") {
if (value === undefined) {
return this.options[key];
}
options = {};
options[key] = value;
}
this._setOptions(options);
return this;
},
_setOptions: function(options) {
var self = this;
$.each(options,
function(key, value) {
self._setOption(key, value);
});
return this;
},
_setOption: function(key, value) {
this.options[key] = value;
if (key === "disabled") {
this.widget()[value ? "addClass": "removeClass"](this.widgetBaseClass + "-disabled" + " " + "ui-state-disabled").attr("aria-disabled", value);
}
return this;
},
enable: function() {
return this._setOption("disabled", false);
},
disable: function() {
return this._setOption("disabled", true);
},
_trigger: function(type, event, data) {
var callback = this.options[type];
event = $.Event(event);
event.type = (type === this.widgetEventPrefix ? type: this.widgetEventPrefix + type).toLowerCase();
data = data || {};
// copy original event properties over to the new event
// this would happen if we could call $.event.fix instead of $.Event
// but we don't have a way to force an event to be fixed multiple times
if (event.originalEvent) {
for (var i = $.event.props.length, prop; i;) {
prop = $.event.props[--i];
event[prop] = event.originalEvent[prop];
}
}
this.element.trigger(event, data);
return ! ($.isFunction(callback) && callback.call(this.element[0], event, data) === false || event.isDefaultPrevented());
}
};
})(jQuery);
/*!
* jQuery UI AriaSorTable (24.12.10)
* http://github.com/fnagel/jQuery-Accessible-RIA
*
* Copyright (c) 2009 Felix Nagel for Namics (Deustchland) GmbH
* Copyright (c) 2010-2011 Felix Nagel
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*
* Depends: jQuery UI
* Optional: jQuery Address Plugin
*/
/*
USAGE:::::::::::::
* Take a look in the html file or the (german) pdf file delivered with this example
* To set sorting method add css classes, default is text, alphabetically
* Sorting CSS classes (apply to th elements)
ui-table-text default: sorts text
ui-table-text-html sorts text with html tags
ui-table-number 123 or 123.456
ui-table-number-de 123,456
ui-table-date 07/28/2009
ui-table-date-de 28.07.2009
ui-table-date-iso 2009-07-28
ui-table-deactivate deactivates sorting for this col
ui-state-active class to set a col as pre sorted (server site)
* Options
rowToStart row to start, begins with 1
rowsToShow How many rows to show? If not set, widget will show all rows
colScopeRow Which col has scope? Could be the UID or a names, begins with 1
defaultSortBy first sorting action sould sort ascending or descending?
colsToHide array; set value true if col should be hidden, example: colsToHide[3] = true;
rowsToHide array; set value true if row should be hidden, example: rowsToHide[3] = true;
keyboard activate default keyboard control
pager add default pager control; (do use with rowsToShow < all rows in the original table)
textPager String pager
textAsc String for sorting ascending
textDesc String for sorting descending
disabled deactivate the widget
jqAddress You need to add the add the jQuery Address file, please see demo file!
enable enable browser history support
title
enable enable title change
split set delimiter string
* Callbacks
onInit
onUpdateData
onSetHTML
onRowSort
* public Methods
updateData
setHTML
rowSort
colSwitch
buildPager
setPager
disable
enable
disable
destroy
*/
(function($) {
// necassary global var for STRING.sort() function clauses
var sortIndex = 0;
$.widget("ui.ariaSorTable", {
version: '1.8',
options: {
rowToStart: 1,
rowsToShow: false,
colScopeRow: 1,
defaultSortBy: "asc",
colsToHide: false,
rowsToHide: false,
keyboard: true,
pager: false,
textPager: "Page:",
textAsc: "Sort ascending",
textDesc: "Sort descending",
// jQuery Address
jqAddress: {
enable: true,
title: {
enable: true,
split: ' | '
},
changeRow: true
}
},
_create: function() {
var options = this.options, self = this;
// init vars
options.tableData = [];
options.originalData = [];
options.selectedCol = 0;
options.activeCol = 0;
// ARIA | make UID if no ID is set by default
var elementID = self.element.attr("id");
if (elementID != "") {
options.uid = elementID;
} else {
options.uid = Math.random().toString(16).slice(2, 10);
self.element.attr("id", "ui-table-"+options.uid);
}
self.element.find("caption").attr("id", "ui-table-"+options.uid+"-caption");
self.element
.attr("role","grid")
.attr("aria-readonly","true")
.attr("aria-labelledby", "ui-table-"+options.uid+"-caption");
// save header elements
var theadTr = self.element.find("thead tr");
// bubbling event for th link elements
options.headers = theadTr.find("th");
theadTr.bind("click", function(e){
if (!options.disabled) {
// get the th element
th = $(e.target).closest("th", theadTr);
if (!th.hasClass("ui-table-deactivate")) {
// does not work in certain browsers
// self.rowSort(th.prevAll("th:visible").length);
self.rowSort(self._getVisible(th.prevAll("th")).length);
return false;
}
}
})
.attr("role", "row");
options.headers.each( function(index) {
// get single th element
var th = $(this);
// ARIA
th.attr("id","ui-table-" + options.uid + "-header-" + index)
.attr("role","columnheader")
.attr("scope","col");
// select title text ( next sorting action)
var text = (options.defaultSortBy == "asc") ? options.textAsc : options.textDesc;
var thA = th.find("a").length;
if (!th.hasClass("ui-table-deactivate")) {
// no link but JS sort function? Add link
if (!thA) {
th.html('<a title="'+text+'" href="#ui-table-dummy">'+th.html()+'</a>');
}
// set title attribute | add events
th.children("a")
.attr("title", text)
.bind("mouseenter", function(){ $(this).parent().addClass('ui-state-hover'); })
.bind("mouseleave", function(){ $(this).parent().removeClass('ui-state-hover'); });
//not activated th elements with no link are added to the tabindex by setting tabindex attribute
} else if (!thA) {
th.attr("tabindex", 0);
}
// save pre sorted (server site) ; aka active col | set attributes
if (th.hasClass("ui-state-active")) {
if (th.hasClass("ui-table-asc")) {
th.attr("aria-sort", "ascending").children("a").attr("title", options.textDesc);
} else if (th.hasClass("ui-table-desc")) {
th.attr("aria-sort", "descending").children("a").attr("title", options.textAsc);
}
options.activeCol = index;
}
});
// get all table data and save them
var rows = self.element.find("tbody tr");
// go trough every row
for (var x = 0; x < rows.length; x++) {
options.originalData[x] = [];
var cells = $(rows[x]).children("td");
for (var y = 0; y < cells.length; y++) {
options.originalData[x][y] = $(cells[y]).html();
}
}
// set var to table length if no custom value
if (!options.rowsToShow) options.rowsToShow = rows.length;
// update data to delete hided rows and cols
self.updateData();
// pager?
if (options.pager) self.buildPager();
// activate Keyboard accessibility
if (options.keyboard) self._setKeyboard();
// add jQuery Address stuff
if ($.address && options.jqAddress.enable && self._jqAddressHelper) {
// set inital state
var startRow = self._jqAddressHelper($.address.pathNames());
// check is address bar in browser is manually changed but fires setHTML only when necassary
$.address.externalChange(function(event) {
var changeRow = self._jqAddressHelper(event.pathNames);
if (changeRow) self.setHTML(changeRow, false, true);
});
}
startRow = (startRow) ? startRow : options.rowToStart;
// set new HTML (with ARIA)
self.setHTML(startRow, true); // true = initial
// Callback
self._trigger("onInit", 0);
},
// make another "cleaned" version of the data array | delete hidden rows and cols
updateData: function () {
var options = this.options, self = this;
options.tableData = [];
var xIndex = 0;
for (var x = 0; x < options.originalData.length; x++) {
if (!options.rowsToHide[x]) {
options.tableData[xIndex] = [];
for (var y = 0; y < options.headers.length; y++) {
if (!options.colsToHide[y]) options.tableData[xIndex].push(options.originalData[x][y]);
}
xIndex++;
}
}
// Callback
self._trigger("onUpdateData", 0);
},
// set new HTML with selected data
// init and forceFirst only necassary when using jqAddress
setHTML: function(newRowToStart, init, forceFirst) {
var options = this.options, self = this;
// var for diffrent row colors
var second = true;
var html = [];
// backfall
if (!newRowToStart) newRowToStart = option.rowToStart;
// set pager
if (options.pager) self.setPager(newRowToStart);
// make html
html.push( "<tbody class=\"ui-table-tbody-active\" aria-live=\"polite\" aria-relevant=\"text\">\n");
for (var x = newRowToStart - 1; x < newRowToStart - 1 + options.rowsToShow; x++) {
// check if row data exists
if (options.tableData[x]) {
// diffrent row css class
var rowClass = (second) ? "class=\"odd\"" : "";
second = (second) ? false : true;
html.push( "\t\t\t\t<tr role=\"row\""+rowClass+">\n");
// build table html (with ARIA and HTML table relation attributes)
for (var y = 0; y < options.tableData[x].length; y++) {
if (y+1 == options.colScopeRow) {
html.push("\t\t\t\t\t<td headers=\"ui-table-"+ options.uid +"-header-"+ y +"\" scope=\"row\" role=\"rowheader\">" + options.tableData[x][y] + "</td>\n");
} else {
html.push("\t\t\t\t\t<td headers=\"ui-table-"+ options.uid +"-header-"+ y +"\" role=\"gridcell\">" + options.tableData[x][y] + "</td>\n");
}
}
html.push( "\t\t\t\t</tr>\n");
}
}
html.push( "\t\t\t</tbody>");
var str = '';
str = html.join('');
// replace tbody or hide original and add new | dont remove but hide because of performance
var tbody = self.element.find("tbody.ui-table-tbody-active");
if (tbody.length) {
tbody.replaceWith(str);
} else {
self.element.find("tbody").hide();
self.element.append(str);
}
// show or hide header cols
if (options.colsToHide)
options.headers.each( function(index) {
if (!options.colsToHide[index]) {
$(this).show();
} else {
$(this).hide();
}
});
// ARIA
$(options.headers[0]).parent().parent()
.attr("aria-live", "polite")
.attr("aria-relevant","text");
// add jQuery Address stuff
if ($.address && options.jqAddress.enable) {
if (!init) {
if (options.jqAddress.title.enable) $.address.title($.address.title().split(options.jqAddress.title.split)[0] + options.jqAddress.title.split + self.element.find("caption").text() + " (" + newRowToStart + "-" + (newRowToStart - 1 + options.rowsToShow) + ")");
// save first page in browser history when user (!) starts to interact with the table
if (options.rowToStart == 1 && newRowToStart != 1 && !forceFirst) {
// if there is no anchor to keep, prevent double entry
if ($.address.value() == "") $.address.history(false);
$.address.value(options.uid + "/" + 1 + "/" + options.rowsToShow);
$.address.history(true);
}
$.address.value(options.uid + "/" + newRowToStart + "/" + (newRowToStart - 1 + options.rowsToShow));
}
}
// update virtual Buffer
self._updateVirtualBuffer();
// set new start point
options.rowToStart = newRowToStart;
// Callback
self._trigger("onSetHTML", 0);
},
// sort data, build and add the new html to the DOM
rowSort: function (index) {
var options = this.options, self = this;
// get all visible th elements
// var thArray = options.headers.filter(":visible");
var thArray = self._getVisible(options.headers);
// get new (clicked) th element
th = $(thArray[index]);
// set global index
sortIndex = index;
// check the css class and sort the array
if (th.hasClass("ui-table-number")) {
options.tableData.sort(self._sortNumber);
} else if (th.hasClass("ui-table-number-de")) {
options.tableData.sort(self._sortNumberDE);
} else if (th.hasClass("ui-table-date")) {
options.tableData.sort(self._sortDate);
} else if (th.hasClass("ui-table-date-de")) {
options.tableData.sort(self._sortDateDE);
} else if (th.hasClass("ui-table-date-iso")) {
options.tableData.sort(self._sortDateISO);
} else if (th.hasClass("ui-table-text-html")) {
options.tableData.sort(self._sortTextHTML);
} else {
// default is text
options.tableData.sort(self._sortText);
}
// set new sorted by
var asc = th.hasClass("ui-table-asc");
if (asc || th.hasClass("ui-table-desc")) {
var newSortBy = (asc) ? "desc" : "asc";
// no class found? set it by default
} else {
var newSortBy = options.defaultSortBy;
}
// reverse array if necassary
if (newSortBy == "desc") options.tableData.reverse();
// get active col
var thActiveCol = $(thArray[options.activeCol]);
// set class to remove of the active col
var sortedBy = (thActiveCol.hasClass("ui-table-asc")) ? "asc" : "desc";
// delete css class of the last sorted col
thActiveCol
.removeClass("ui-table-" + sortedBy)
.removeClass("ui-state-active")
// set ARIA-sort to none
.attr("aria-sort", "none");
// remove focus classs from selected col
$(thArray[options.selectedCol]).removeClass("ui-state-focus");
// set new title text
var newSortByText = (newSortBy == "asc") ? options.textDesc : options.textAsc;
var newSortByARIA = (newSortBy == "asc") ? "ascending" : "descending";
// add new css class, title and css state to the new active col
th.addClass("ui-state-active")
.addClass("ui-table-" + newSortBy)
.attr("aria-sort", newSortByARIA)
.children("a").attr("title", newSortByText);
// save new sorted and active col
options.activeCol = options.selectedCol = index;
// Callback
self._trigger("onRowSort", 0);
// update HTML
self.setHTML(options.rowToStart);
},
// sorting clauses function
_sortNumber: function (a, b) {
// 123.456
return (a[sortIndex] - b[sortIndex]);
},
_sortNumberDE: function (a, b) {
// 123,456
return (a[sortIndex].replace(",", ".") - b[sortIndex].replace(",", "."));
},
_sortDateDE: function (a, b) {
// 28.07.2009
var x = Date.parse(a[sortIndex].substr(3,2) + "/" + a[sortIndex].substr(0,2) + "/" + a[sortIndex].substr(6,4));
var y = Date.parse(b[sortIndex].substr(3,2) + "/" + b[sortIndex].substr(0,2) + "/" + b[sortIndex].substr(6,4));
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
_sortDate: function (a, b) {
// 07/28/2009
var x = Date.parse(a[sortIndex]);
var y = Date.parse(b[sortIndex]);
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
_sortDateISO: function (a, b) {
// 2009-07-28
var x = Date.parse(a[sortIndex].substr(5,2) + "/" + a[sortIndex].substr(8,2) + "/" + a[sortIndex].substr(0,4));
var y = Date.parse(b[sortIndex].substr(5,2) + "/" + b[sortIndex].substr(8,2) + "/" + b[sortIndex].substr(0,4));
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
_sortTextHTML: function (a, b) {
// Text with html
var x = $(a[sortIndex]).text().toLowerCase();
var y = $(b[sortIndex]).text().toLowerCase();
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
_sortText: function (a, b) {
// 20:00:13
// Text without (!) html
var x = a[sortIndex].toLowerCase();
var y = b[sortIndex].toLowerCase();
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
// jQuery :visible filter does not work with tables in certain browser (IE8, ?) so wee built our own function
// http://www.code-styling.de/deutsch/jquery-132-verursacht-probleme-im-ie-8
_getVisible: function (elements) {
var elReturn = [];
var i = 0;
elements.each(function(index){
if ($(this).css('display') != 'none') {
elReturn[i] = $(this);
i++;
}
});
return elReturn;
},
// set keyboard control
_setKeyboard: function () {
var options = this.options, self = this;
self.element
.keydown( function(e){
if (!options.disabled) {
switch (e.keyCode) {
// go to next page
case $.ui.keyCode.DOWN:
case $.ui.keyCode.PAGE_DOWN:
// check if new value is in range and if there are any pages to show
if (options.rowToStart < options.tableData.length-1 && options.rowsToShow != options.tableData.length) self.setHTML(options.rowToStart + options.rowsToShow);
break;
// go to previous page
case $.ui.keyCode.UP:
case $.ui.keyCode.PAGE_UP:
// check if new value is in range and if there are any pages to show
if (options.rowToStart > 0 + options.rowsToShow && options.rowsToShow != options.tableData.length) self.setHTML(options.rowToStart - options.rowsToShow);
break;
// go to first page
case $.ui.keyCode.HOME:
// check if there are any pages to show
if (options.rowsToShow != options.tableData.length) self.setHTML(1);
break;
// go to last page
case $.ui.keyCode.END:
// check if there are any pages to show
if (options.rowsToShow != options.tableData.length) self.setHTML(((Math.ceil(options.tableData.length / options.rowsToShow)) * options.rowsToShow) - options.rowsToShow + 1);
break;
// go to next or previous page
case $.ui.keyCode.TAB:
if (e.shiftKey) {
if (options.selectedCol > 0) { self.colSwitch(-1); } else { return true; }
} else {
if (options.selectedCol < self._getVisible(options.headers).length-1) { self.colSwitch(1); } else { return true; }
}
break;
// switch to left col
case $.ui.keyCode.LEFT:
if (options.selectedCol > 0) self.colSwitch(-1);
break;
// switch to right col
case $.ui.keyCode.RIGHT:
if (options.selectedCol < self._getVisible(options.headers).length-1) self.colSwitch(1);
break;
// start sorting
case $.ui.keyCode.SPACE:
var th = self._getVisible(options.headers);
$(th[options.selectedCol]).find("a").click();
break;
default:
return true;
break;
}
return false;
}
});
},
// switchh selected col
colSwitch: function (dir) {
var options = this.options, self = this;
// get visible headers
var thArray = self._getVisible(options.headers);
// remove old selected col css class
$(thArray[options.selectedCol]).removeClass("ui-state-focus");
// set new selected col
options.selectedCol = options.selectedCol + dir;
// get new selected col
el = $(thArray[options.selectedCol]);
// set new focus
el.addClass("ui-state-focus");
// set focus
if (el.find("a").length) { el.find("a").focus(); } else { el.focus(); }
},
// removes instance and attributes
destroy: function() {
this.element
.unbind(".ariaSorTable")
// remove data
.removeData('ariaSorTable')
// remove attributes
.removeAttr("role")
.removeAttr("aria-readonly")
.removeAttr("aria-labelledby")
// remove attributes of the caption
.find("caption").removeAttr("id")
// remove ARIA attributes from head element
.end().find("thead")
.removeAttr("aria-live")
.removeAttr("aria-relevant")
// remove event and role of the tr and show them all
.find("tr")
.removeAttr("role")
.unbind("click")
.end().end()
// remove injected HTML
.find("tbody.ui-table-tbody-active").remove().end()
// show hidden original html
.find("tbody").show();
// th's
$.each(this.options.headers, function() {
$(this)
.show()
.removeAttr("id")
.removeAttr("role")
.removeAttr("aria-sort")
.removeAttr("tabindex")
.removeAttr("scope");
// search for added links and delete them | remove event
var link = $(this).children("a");
if (link.length) {
link.unbind("mouseenter mouseleave").removeAttr("title");
if (link.attr("href") == "#ui-table-dummy") $(this).html(link.html());
}
});
// pager
if (this.options.pager) $("#ui-table-pager").remove();
// remove virtual buffer form
$("body>form #virtualBufferForm").parent().remove();
// call widget destroy function
$.widget.prototype.destroy.apply(this, arguments);
},
// updates virtual buffer | for older screenreader
_updateVirtualBuffer: function() {
var form = $("body>form #virtualBufferForm");
if(form.length) {
(form.val() == "1") ? form.val("0") : form.val("1");
} else {
var html = '<form><input id="virtualBufferForm" type="hidden" value="1" /></form>';
$("body").append(html);
}
}
});
$.fn.extend($.ui.ariaSorTable.prototype,{
// this code is only needed if you like to use the pager, otherwise: delete it
// build a pager
buildPager: function () {
var options = this.options, self = this;
// build html to inject
var site = 0;
var y = 0;
var html = '<div class="ui-table-pager" aria-valuemin="1" aria-controls="ui-table-'+options.uid+'">'+"\n";
html += '<span id="ui-table-'+options.uid+'-pager-title" class="ui-corner-all">'+options.textPager+'</span>'+"\n";
while (y < options.tableData.length){
site++;
html += ' <button title="'+options.textPager+' '+ site +'" type="button" class="ui-state-default ui-corner-all" aria-selected="false" aria-labelledby="ui-table-'+options.uid+'-pager-title">'+ site +'</button>'+"\n";
y = y + options.rowsToShow;
}
html += '</div>'+"\n";
options.pager = self.element.next(".ui-table-pager");
if (options.pager.length) options.pager.replaceWith(html);
else self.element.after(html);
// ARIA
options.pager = self.element.next(".ui-table-pager")
.attr("aria-valuemax", site);
// set events | change css classes and sort table
options.pagerButtons = options.pager.find("button")
.each( function(index) {
$(this)
.bind("click", function(){
// calculate new start position
var newRowToStart = (options.rowsToShow * index == 0) ? 1 : (options.rowsToShow * index)+1;
// set new html
self.setHTML(newRowToStart);
})
.bind("mouseenter", function(){ $(this).addClass('ui-state-hover'); })
.bind("mouseleave", function(){ $(this).removeClass('ui-state-hover'); })
.bind("focus", function(){ $(this).addClass('ui-state-focus'); })
.bind("blur", function(){ $(this).removeClass('ui-state-focus'); });
});
// set active button after set events
self.setPager(options.rowToStart);
},
// sets active page | call befor setting new options.rowToStart with new row as parameter
setPager: function (newRow) {
var options = this.options, self = this;
// calculate new start point and add or remove css classes and ARIA attributes
$(options.pagerButtons[Math.floor(options.rowToStart/options.rowsToShow)]).removeClass('ui-state-active').attr("aria-selected", false);
$(options.pagerButtons[Math.floor(newRow/options.rowsToShow)]).addClass('ui-state-active').attr("aria-selected", true);
options.pager.attr("aria-valuenow", Math.floor(newRow/options.rowsToShow)+1);
},
// this code is only needed if you like to use the jQuery Address support, otherwise: delete it
_jqAddressHelper: function (path) {
var options = this.options, self = this;
// check if anchor has valid values
if (path != "" && path[0] == options.uid) {
var start = parseInt(path[1]);
var end = parseInt(path[2]);
// make this anchor control more fault-tolerant
if (isNaN(start)) {
return false;
} // -> start is a number
if (start <= options.tableData.length) {
// is end a number?
// start shall not be bigger than end
if (isNaN(end) || start > end) {
return start;
} // else -> both are valid numbers
var range = end - (start - 1);
// no need to update if already choosen rows should be displayed
if (options.rowToStart == start && options.rowsToShow == range) return false;
if (options.jqAddress.changeRow) {
var temp_rowsToShow = options.rowsToShow;
options.rowsToShow = range;
// if we changed rows we need to rebuild pager
if (options.pager && temp_rowsToShow != options.rowsToShow) self.buildPager();
}
return start;
}
}
return false;
}
});
})(jQuery);
// </nowiki>