diff --git a/.gitignore b/.gitignore index b24ec24e..7e7eb3e9 100644 --- a/.gitignore +++ b/.gitignore @@ -18,10 +18,12 @@ *.DS_Store **/.DS_Store /.idea -config/database.yml /.sass-cache /public/* /config/* public/* .env + +schema.rb +config/database.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..91881255 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: ruby +rvm: + - 2.2 +env: + - DB=sqlite +script: + - RAILS_ENV=development bundle exec rake db:create db:migrate db:seed --trace diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md new file mode 100644 index 00000000..fe5fcf9e --- /dev/null +++ b/CONTRIBUTION.md @@ -0,0 +1,35 @@ +###Tu veux contribuer ? +Tout le monde sans exception doit suivre ce processus de ce présent fichier. Les excuses du genre : “Je fais partie de la promo X” ne sont pas valables. + +Pour cela il te faut d’abord avoir [installé l’application](https://github.com/lpdw/lpdw2.0/blob/development/README.md). + +Avant de coder une nouvelle fonctionnalité de la mort qui tue, il y a quelques règles à suivre : + + - Avoir forké l’application et travailler directement dessus. + - Toujours travailler sur la branche “development”. + - Respecter les principes du + [MVC](https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur), [DRY](https://fr.wikipedia.org/wiki/Ne_vous_r%C3%A9p%C3%A9tez_pas), CoC et [REST](http://blog.nicolashachet.com/niveaux/confirme/larchitecture-rest-expliquee-en-5-regles/) au maximum. + - Utiliser des noms de commit suffisamment descriptifs mais courts pour que les administrateurs puissent comprendre directement la fonction du Commit. + +Une fois la fonctionnalité développée, commitée (avec un nom suffisant descriptif) et pushé sur l’application forkée, il te suffit de proposer une [Pull request](https://github.com/lpdw/lpdw2.0/pulls) et c’est expliqué juste après. + +**Tu veux soumettre Pull request ?** + +Si tu en es arrivé là, c’est que tu as déjà développé une fonctionnalité et que tu souhaites l’intégrer au dépôt central. Si tu n’as jamais fais de Pull request, c’est comme proposer d’ajouter un commit à un autre dépôt. +Pour cela, il y a un guide écrit par Github qui explique très simplement la procédure. +**La destination de la Pull request doit être la branche “development”.** + +Maintenant il suffit d’attendre qu’un administrateur vérifie ta Pull request, il peut y avoir 3 possibilités : + +**Accepté :** Votre fonctionnalité est parfaitement intègre et correspond au projet. Elle est directement incorporée à l’application, bravo ! + +**A revoir:** La fonctionnalité correspond au projet mais n’est pas correctement intégrée. Dommage ! Mais quelques conseils vous seront donnés afin d’améliorer votre code pour qu’il s'intègre parfaitement à l’application. + +**Refusé :** La fonctionnalité ne correspond pas au projet. + +---------- + + +Administrateurs (2015/2016) +Yassin AGHANI [@aghaniyassin](https://github.com/aghaniyassin) +Enguerran POULAIN [@theblackhole](https://github.com/theblackhole) diff --git a/Gemfile b/Gemfile index ca443448..dbd62ca1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,4 @@ + source 'https://rubygems.org' @@ -79,3 +80,9 @@ gem "simple_calendar", "~> 1.1.0" gem 'momentjs-rails', '>= 2.8.1' gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14' gem 'dotenv-rails' + +group :development, :test do + gem 'sqlite3' + gem 'mailcatcher' +end + diff --git a/Gemfile.lock b/Gemfile.lock index 15631f2a..c8b50d51 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,6 +46,7 @@ GEM coffee-script-source execjs coffee-script-source (1.9.1) + daemons (1.2.3) devise (3.4.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -58,6 +59,7 @@ GEM dotenv (= 2.0.2) railties (~> 4.0) erubis (2.7.0) + eventmachine (1.0.5) execjs (2.4.0) font-awesome-rails (4.2.0.0) railties (>= 3.2, < 5.0) @@ -80,6 +82,14 @@ GEM libv8 (3.16.14.7) mail (2.6.3) mime-types (>= 1.16, < 3) + mailcatcher (0.6.1) + activesupport (>= 4.0.0, < 5) + eventmachine (~> 1.0.0, <= 1.0.5) + mail (~> 2.3) + sinatra (~> 1.2) + skinny (~> 0.2.3) + sqlite3 (~> 1.3) + thin (~> 1.5.0) mime-types (2.4.3) mini_portile (0.6.2) minitest (5.5.1) @@ -100,6 +110,8 @@ GEM cocaine (~> 0.5.3) mime-types rack (1.5.2) + rack-protection (1.5.3) + rack rack-test (0.6.3) rack (>= 1.0) rails (4.1.6) @@ -141,6 +153,13 @@ GEM rdoc (~> 4.0) simple_calendar (1.1.10) rails (>= 3.0) + sinatra (1.4.6) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) + skinny (0.2.3) + eventmachine (~> 1.0.0) + thin (~> 1.5.0) spring (1.3.3) sprockets (2.12.3) hike (~> 1.2) @@ -151,9 +170,14 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) + sqlite3 (1.3.10) therubyracer (0.12.1) libv8 (~> 3.16.14.0) ref + thin (1.5.1) + daemons (>= 1.0.9) + eventmachine (>= 0.12.6) + rack (>= 1.0.0) thor (0.19.1) thread_safe (0.3.4) tilt (1.4.1) @@ -194,6 +218,7 @@ DEPENDENCIES jbuilder (~> 2.0) jquery-rails jquery-turbolinks + mailcatcher momentjs-rails (>= 2.8.1) mysql2 nested_form_fields @@ -206,6 +231,7 @@ DEPENDENCIES sdoc (~> 0.4.0) simple_calendar (~> 1.1.0) spring + sqlite3 therubyracer tinymce-rails tinymce-rails-imageupload (~> 4.0.0.beta) diff --git a/README.md b/README.md index 057766eb..9bf0e465 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,92 @@ -lpdw2.0 -======= +Site de la LP-DW [![Build Status](https://travis-ci.org/lpdw/lpdw2.0.svg)](https://travis-ci.org/lpdw/lpdw2.0) +================ -Refonte du site de la Licence Professionelle 2.0 +Le site de la LP-DW présente la formation “Licence Professionelle Developpeur Web”, il permet également de pouvoir candidater, de s’informer et de se tenir au courant des différentes actualités. +> **Changelog** + +> **[2.4](https://github.com/lpdw/lpdw2.0/releases/tag/v2.4)** : Nouvelles fonctionnalitées, refactoring et correctifs : +> - Annuaire d'entreprises avec offres d'emploi, stage... ([#28](https://github.com/lpdw/lpdw2.0/pull/28)) +> - Annuaire des étudiants ([#31](https://github.com/lpdw/lpdw2.0/pull/31)) +> - Section Bon Plans ([#32](https://github.com/lpdw/lpdw2.0/pull/32)) +> - Refactoring, fonctionnalités backoffice ([#6](https://github.com/lpdw/lpdw2.0/pull/6) [#18](https://github.com/lpdw/lpdw2.0/pull/18) [#19](https://github.com/lpdw/lpdw2.0/pull/19) [#29](https://github.com/lpdw/lpdw2.0/pull/29)) +> - Nombreux correctifs + +> **[2.0](https://github.com/lpdw/lpdw2.0/releases/tag/v2.0)** : workflow +> **1.0** : website + + +---------- + + +###Installation +L’installation de MySQL et HomeBrew sur Mac est indispensable. + +**1)** Il faut préalablement **[forker](https://help.github.com/articles/fork-a-repo/#fork-an-example-repository) le dépôt sur ton compte**. + +**2) Cloner ton dépôt** préalablement forké : + + git clone https://github.com/TON_PSEUDO/lpdw2.0.git + +**3) Ajouter un Remote “upstream”** afin de pouvoir synchroniser l’application avec le dépôt central : + + git remote add upstream https://github.com/lpdw/lpdw2.0 + +**4) Installer toutes les dépendances** : + + bundle install + + #Pour l'envoi de mail en local + gem install mailcatcher + +**5) Faire la migration** de la base de données : + + # Créer la base de données et faire les migrations : + rake db:create db:migrate + + #Peupler la base de données avec des exemples (fichier db/seeds.rb) + rake db:seed + + +---------- + + +###Démarrage de l’application + # Lancer le serveur + rails server +###Mettre à jour mon application + + # Se mettre sur la branche development + git checkout development + + # Synchronisation du code depuis le dépôt central + git fetch upstream + + # Rebase des commits + git rebase upstream/development + + # Push des mises à jour sur le fork + git push origin development + + +###Tu as découvert un bug ? + +**Tu as découvert un bug sur le site, dans le code ou une erreur dans la documentation ?** +Tu peux nous aider en [soumettant une Issue](https://github.com/lpdw/lpdw2.0/issues) sur le dépôt avec le tag “bug”. Ou encore mieux, tu peux soumettre une Pull request avec un correctif. + +**Tu veux une fonctionnalité et tu sais pas (encore) coder ?** +Tu peux proposer une nouvelle fonctionnalité en ajoutant une Issue sur le dépôt avec le tag “feature”. Et comme ton idée est super géniale, un développeur va vite s'empresser de la développer. + +**Tu veux contribuer ?** +Tout le monde sans exception doit suivre ce processus du fichier [CONTRIBUTION.md](https://github.com/lpdw/lpdw2.0/blob/development/CONTRIBUTION.md). Les excuses du genre : “Je fais partie de la promo X” ne sont pas valables. + + +---------- + + +Administrateurs (2015/2016) + +Yassin AGHANI [@aghaniyassin](https://github.com/aghaniyassin) + +Enguerran POULAIN [@theblackhole](https://github.com/theblackhole) -======= -Version 1.0 : website -Version 2.0 : workflow \ No newline at end of file diff --git a/app/assets/images/default_user.jpg b/app/assets/images/default_user.jpg new file mode 100644 index 00000000..39fcb2bb Binary files /dev/null and b/app/assets/images/default_user.jpg differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 00000000..06e684ea Binary files /dev/null and b/app/assets/images/favicon.ico differ diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index e9f70ad1..c8447747 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -71,5 +71,12 @@ $(document).ready(function() { overlay.remove(); }); - + $(document).ready( function () { + $('#myTable').dataTable( { + 'bAutoWidth': false, + "columnDefs": [ + { "orderable": false, "targets": 6 } + ] + }); + }); }); \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 75c210fe..7f04deae 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,26 +15,26 @@ //= require jquery_ujs //= require parsley.min.js //= require nested_form_fields -//= require_tree . //= require bootstrap-sprockets //= require jquery.nicescroll //= require moment //= require bootstrap-datetimepicker +//= require_tree . $(document).ready(function() { - topScroll(); + topScroll(); - $(window).scroll(function(){ - topScroll(); - }); + $(window).scroll(function(){ + topScroll(); + }); - function topScroll(){ - if($(window).scrollTop() == 0){ - $(".scroll-top").hide(); - } else{ - $(".scroll-top").show(); - } + function topScroll(){ + if($(window).scrollTop() == 0){ + $(".scroll-top").hide(); + } else{ + $(".scroll-top").show(); } + } $(".scroll-top").click(function(){ var body = $("html, body"); @@ -48,10 +48,10 @@ $(document).ready(function() { var body = $("html, body"); $(this).parent().slideUp(); return false; - }); + }); var tw_url = "https://cdn.syndication.twimg.com/widgets/followbutton/info.json?lang=fr&screen_names="; - var fb_url = "https://graph.facebook.com/"; + var fb_url = "http://api.facebook.com/restserver.php?format=json&method=links.getStats&urls=https://www.facebook.com/"; var fb_site = "https://facebook.com/"; var tw_site = "https://twitter.com/"; @@ -73,12 +73,12 @@ $(document).ready(function() { crossDomain: true, dataType: 'jsonp', success: function(data) { - $(".licence .fb-retour").html(''+data.likes); + $(".licence .fb-retour").html(''+data[0].like_count); $(".licence .fb-retour").attr("href", fb_site+"lpdwm"); } }); - $.ajax({ + $.ajax({ url: tw_url+"FacLabUcp", type: 'GET', crossDomain: true, @@ -95,20 +95,41 @@ $(document).ready(function() { crossDomain: true, dataType: 'jsonp', success: function(data) { - $(".faclab .fb-retour").html(''+data.likes); + $(".faclab .fb-retour").html(''+data[0].like_count); $(".faclab .fb-retour").attr("href", fb_site+"faclab"); } }); + $.ajax({ + url: tw_url+"UniversiteCergy", + type: 'GET', + crossDomain: true, + dataType: 'jsonp', + success: function(data) { + $(".universite .tw-retour").html(''+data[0].followers_count); + $(".universite .tw-retour").attr("href",tw_site+"UniversiteCergy"); + + } + }); + $.ajax({ + url: fb_url+"279510485409212/likes", + type: 'GET', + crossDomain: true, + dataType: 'jsonp', + success: function(data) { + $(".universite .fb-retour").html(''+data[0].like_count); + $(".universite .fb-retour").attr("href", fb_site+"UniversiteCergyPontoise"); + } + }); $(".navbar-toggle").on('click', function(e){ e.preventDefault(); - if($(".navbar-collapse").hasClass("in")){ + if($(".navbar-collapse").hasClass("in")){ document.documentElement.style.overflow = 'auto'; }else{ document.documentElement.style.overflow = 'hidden'; } - }); + }); $(".home-creations .article-creation_wrapper").each(function() { $(this).find("img").on('load',function() { @@ -121,4 +142,21 @@ $(document).ready(function() { }); + //Jquery menu color + if( $('#categ_currant').attr('value') ) { + + $('.bp nav.type a').each(function() { + if( $(this).attr('data-filter-type') == $('#categ_currant').attr('value') ) { + $(this).addClass('active'); + } + }); + + } else { + $('.bp nav.type a').each(function() { + if( $(this).attr('data-filter-type') == 'all') { + $(this).addClass('active'); + } + }); + }; + }); \ No newline at end of file diff --git a/app/assets/javascripts/apply.js b/app/assets/javascripts/apply.js index 2f71eebb..632677d5 100644 --- a/app/assets/javascripts/apply.js +++ b/app/assets/javascripts/apply.js @@ -1,4 +1,4 @@ -$(".first_apply .form_wrapper").hide(); +//$(".first_apply .form_wrapper").hide(); $(".first_apply .get_progression_form").hide(); $("#fill_form").on("click", function (e) { @@ -23,12 +23,12 @@ $("#get_progression").on("click",function(e){ }); -if ($(".modify_apply").length > 0) { - var step_position = $(".modify_apply").find(".step_position").data("step-position"); - $(".step"+step_position).show(); - $(".apply_step.active").removeClass("active"); - $(".apply_step.step_"+step_position).addClass("active"); -}; +// if ($(".modify_apply").length > 0) { +// //var step_position = $(".modify_apply").find(".step_position").data("step-position"); +// //$(".step1").show(); +// //$(".apply_step.active").removeClass("active"); +// //$(".apply_step.step_"+step_position).addClass("active"); +// }; $("input[name='applicant[has_connection]']").on("click", function() { if($("#entourage_true").is(':checked')) { @@ -74,4 +74,23 @@ function add_fields(link, association, content) { var new_id = new Date().getTime(); var regexp = new RegExp("new_" + association, "g"); $(link).parent().before(content.replace(regexp, new_id)); -} \ No newline at end of file +} + +$("#get_progression").on("click",function(e){ + e.preventDefault(); + $(".step").hide(); + $(".apply_steps").hide(); + $(".get_progression_form").show(); + $(".form_wrapper").show(); + +}); + +$('.file-upload').each(function(index,elem){ + var url = $(elem).attr('data-url'); + if(url != '/files/original/missing.png'){ + var parent = $(elem).parent(); + $(elem).addClass('hidden'); + window.papa = parent; + $(parent).find('.button-file').removeClass('hidden'); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/compagnies.js.coffee b/app/assets/javascripts/compagnies.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/compagnies.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/datatables.js b/app/assets/javascripts/datatables.js new file mode 100644 index 00000000..16446724 --- /dev/null +++ b/app/assets/javascripts/datatables.js @@ -0,0 +1,15353 @@ +/* + * This combined file was created by the DataTables downloader builder: + * https://datatables.net/download + * + * To rebuild or modify this file with the latest versions of the included + * software please visit: + * https://datatables.net/download/#bs/dt-1.10.9 + * + * Included libraries: + * DataTables 1.10.9 + */ + +/*! DataTables 1.10.9 + * ©2008-2015 SpryMedia Ltd - datatables.net/license + */ + +/** + * @summary DataTables + * @description Paginate, search and order HTML tables + * @version 1.10.9 + * @file jquery.dataTables.js + * @author SpryMedia Ltd (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * @copyright Copyright 2008-2015 SpryMedia Ltd. + * + * This source file is free software, available under the following license: + * MIT license - http://datatables.net/license + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ + +(/** @lends */function( window, document, undefined ) { + +(function( factory ) { + "use strict"; + + if ( typeof define === 'function' && define.amd ) { + // Define as an AMD module if possible + define( 'datatables', ['jquery'], factory ); + } + else if ( typeof exports === 'object' ) { + // Node/CommonJS + module.exports = factory( require( 'jquery' ) ); + } + else if ( jQuery && !jQuery.fn.dataTable ) { + // Define using browser globals otherwise + // Prevent multiple instantiations if the script is loaded twice + factory( jQuery ); + } +} +(/** @lends */function( $ ) { + "use strict"; + + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a highly + * flexible tool, based upon the foundations of progressive enhancement, + * which will add advanced interaction controls to any HTML table. For a + * full list of features please refer to + * [DataTables.net](href="http://datatables.net). + * + * Note that the `DataTable` object is not a global variable but is aliased + * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may + * be accessed. + * + * @class + * @param {object} [init={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.7+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "paginate": false, + * "sort": false + * } ); + * } ); + */ + var DataTable; + + + /* + * It is useful to have variables which are scoped locally so only the + * DataTables functions can access them and they don't leak into global space. + * At the same time these functions are often useful over multiple files in the + * core and API, so we list, or at least document, all variables which are used + * by DataTables as private variables here. This also ensures that there is no + * clashing of variable names and that they can easily referenced for reuse. + */ + + + // Defined else where + // _selector_run + // _selector_opts + // _selector_first + // _selector_row_indexes + + var _ext; // DataTable.ext + var _Api; // DataTable.Api + var _api_register; // DataTable.Api.register + var _api_registerPlural; // DataTable.Api.registerPlural + + var _re_dic = {}; + var _re_new_lines = /[\r\n]/g; + var _re_html = /<.*?>/g; + var _re_date_start = /^[\w\+\-]/; + var _re_date_end = /[\w\+\-]$/; + + // Escape regular expression special characters + var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); + + // http://en.wikipedia.org/wiki/Foreign_exchange_market + // - \u20BD - Russian ruble. + // - \u20a9 - South Korean Won + // - \u20BA - Turkish Lira + // - \u20B9 - Indian Rupee + // - R - Brazil (R$) and South Africa + // - fr - Swiss Franc + // - kr - Swedish krona, Norwegian krone and Danish krone + // - \u2009 is thin space and \u202F is narrow no-break space, both used in many + // standards as thousands separators. + var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; + + + var _empty = function ( d ) { + return !d || d === true || d === '-' ? true : false; + }; + + + var _intVal = function ( s ) { + var integer = parseInt( s, 10 ); + return !isNaN(integer) && isFinite(s) ? integer : null; + }; + + // Convert from a formatted number with characters other than `.` as the + // decimal place, to a Javascript number + var _numToDecimal = function ( num, decimalPoint ) { + // Cache created regular expressions for speed as this function is called often + if ( ! _re_dic[ decimalPoint ] ) { + _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); + } + return typeof num === 'string' && decimalPoint !== '.' ? + num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : + num; + }; + + + var _isNumber = function ( d, decimalPoint, formatted ) { + var strType = typeof d === 'string'; + + // If empty return immediately so there must be a number if it is a + // formatted string (this stops the string "k", or "kr", etc being detected + // as a formatted number for currency + if ( _empty( d ) ) { + return true; + } + + if ( decimalPoint && strType ) { + d = _numToDecimal( d, decimalPoint ); + } + + if ( formatted && strType ) { + d = d.replace( _re_formatted_numeric, '' ); + } + + return !isNaN( parseFloat(d) ) && isFinite( d ); + }; + + + // A string without HTML in it can be considered to be HTML still + var _isHtml = function ( d ) { + return _empty( d ) || typeof d === 'string'; + }; + + + var _htmlNumeric = function ( d, decimalPoint, formatted ) { + if ( _empty( d ) ) { + return true; + } + + var html = _isHtml( d ); + return ! html ? + null : + _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? + true : + null; + }; + + + var _pluck = function ( a, prop, prop2 ) { + var out = []; + var i=0, ien=a.length; + + // Could have the test in the loop for slightly smaller code, but speed + // is essential here + if ( prop2 !== undefined ) { + for ( ; i') + .css( { + position: 'fixed', + top: 0, + left: 0, + height: 1, + width: 1, + overflow: 'hidden' + } ) + .append( + $('
') + .css( { + position: 'absolute', + top: 1, + left: 1, + width: 100, + overflow: 'scroll' + } ) + .append( + $('
') + .css( { + width: '100%', + height: 10 + } ) + ) + ) + .appendTo( 'body' ); + + var outer = n.children(); + var inner = outer.children(); + + // Numbers below, in order, are: + // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth + // + // IE6 XP: 100 100 100 83 + // IE7 Vista: 100 100 100 83 + // IE 8+ Windows: 83 83 100 83 + // Evergreen Windows: 83 83 100 83 + // Evergreen Mac with scrollbars: 85 85 100 85 + // Evergreen Mac without scrollbars: 100 100 100 100 + + // Get scrollbar width + browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; + + // IE6/7 will oversize a width 100% element inside a scrolling element, to + // include the width of the scrollbar, while other browsers ensure the inner + // element is contained without forcing scrolling + //console.log( inner.offsetWidth ); + browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; + + // In rtl text layout, some browsers (most, but not all) will place the + // scrollbar on the left, rather than the right. + browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; + + // IE8- don't provide height and width for getBoundingClientRect + browser.bBounding = n[0].getBoundingClientRect().width ? true : false; + + n.remove(); + } + + $.extend( settings.oBrowser, DataTable.__browser ); + settings.oScroll.iBarWidth = DataTable.__browser.barWidth; + } + + + /** + * Array.prototype reduce[Right] method, used for browsers which don't support + * JS 1.6. Done this way to reduce code size, since we iterate either way + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnReduce ( that, fn, init, start, end, inc ) + { + var + i = start, + value, + isSet = false; + + if ( init !== undefined ) { + value = init; + isSet = true; + } + + while ( i !== end ) { + if ( ! that.hasOwnProperty(i) ) { + continue; + } + + value = isSet ? + fn( value, that[i], i, that ) : + that[i]; + + isSet = true; + i += inc; + } + + return value; + } + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + // Add column to aoColumns array + var oDefaults = DataTable.defaults.column; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.mData : iCol, + idx: iCol + } ); + oSettings.aoColumns.push( oCol ); + + // Add search object for column specific search. Note that the `searchCols[ iCol ]` + // passed into extend can be undefined. This allows the user to give a default + // with only some of the parameters defined, and also not give a default + var searchCols = oSettings.aoPreSearchCols; + searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); + + // Use the default column options function to initialise classes etc + _fnColumnOptions( oSettings, iCol, $(nTh).data() ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + var oClasses = oSettings.oClasses; + var th = $(oCol.nTh); + + // Try to get width information from the DOM. We can't get it from CSS + // as we'd need to parse the CSS stylesheet. `width` option can override + if ( ! oCol.sWidthOrig ) { + // Width attribute + oCol.sWidthOrig = th.attr('width') || null; + + // Style attribute + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); + if ( t ) { + oCol.sWidthOrig = t[1]; + } + } + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + // Backwards compatibility + _fnCompatCols( oOptions ); + + // Map camel case parameters to their Hungarian counterparts + _fnCamelToHungarian( DataTable.defaults.column, oOptions ); + + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp !== undefined && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType ) + { + oCol._sManualType = oOptions.sType; + } + + // `class` is a reserved word in Javascript, so we need to provide + // the ability to use a valid name for the camel case input + if ( oOptions.className && ! oOptions.sClass ) + { + oOptions.sClass = oOptions.className; + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mDataSrc = oCol.mData; + var mData = _fnGetObjectDataFn( mDataSrc ); + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + + var attrTest = function( src ) { + return typeof src === 'string' && src.indexOf('@') !== -1; + }; + oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( + attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) + ); + + oCol.fnGetData = function (rowData, type, meta) { + var innerData = mData( rowData, type, undefined, meta ); + + return mRender && type ? + mRender( innerData, type, rowData, meta ) : + innerData; + }; + oCol.fnSetData = function ( rowData, val, meta ) { + return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); + }; + + // Indicate if DataTables should read DOM data as an object or array + // Used in _fnGetRowElements + if ( typeof mDataSrc !== 'number' ) { + oSettings._rowReadObject = true; + } + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called + } + + /* Check that the class assignment is correct for sorting */ + var bAsc = $.inArray('asc', oCol.asSorting) !== -1; + var bDesc = $.inArray('desc', oCol.asSorting) !== -1; + if ( !oCol.bSortable || (!bAsc && !bDesc) ) + { + oCol.sSortingClass = oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( bAsc && !bDesc ) + { + oCol.sSortingClass = oClasses.sSortableAsc; + oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; + } + else if ( !bAsc && bDesc ) + { + oCol.sSortingClass = oClasses.sSortableDesc; + oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; + } + else + { + oCol.sSortingClass = oClasses.sSortable; + oCol.sSortingClassJUI = oClasses.sSortJUI; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( settings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( settings.oFeatures.bAutoWidth !== false ) + { + var columns = settings.aoColumns; + + _fnCalculateColumnWidths( settings ); + for ( var i=0 , iLen=columns.length ; i