diff --git a/ChangeLog b/ChangeLog index 460e2dc73ae..803703caf9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ For users: configured. Show also total number of activated modules. - New: Can filter list of proposal, order or invoice on sales representative. - New: Add supplier ref on supplier orders. -- New: Can export supplier orders. +- New: Can export supplier orders and customers shipments. - New: First change to install external plugins from gui (experimental). - New: Monaco is like France for default vat calculation - New: Can list elements (invoices, orders or proposals) on a particular @@ -26,10 +26,11 @@ For users: - New: Can insert URL links into elements lines. Also reported into PDF. - New: When a member is validated, we can subscribe to mailing-lists according to its type. +- New: Add a tab into members statistics to count members by nature. - New: Add link to third party into sells and purchase journal. - New: Suggest a method to generate a backup file for user with no access to mysqldump binary. -- New: Can use extrafields on contacts/addresses. +- New: Can also use extrafields on contacts/addresses and users. - New: Support unique field for extrafields. - New: Extra fields supports more types (int, string, double, date, datetime). - New: Can correct stock of a warehouse from warehouse card. @@ -50,9 +51,10 @@ For users: - New: Allow to search product from barcodes directly from invoices, proposals... through AJAX. - New: Can make one invoice for several orders. - New: POS module can works with only one payment method (cach, chq, credit card). -- New: Add possibility to defined position/job of a user -- New: [ task #210 ] Can choose cash account during POS login -- New: [ task #104 ] Can create an invoice from several orders +- New: Add possibility to defined position/job of a user. +- New: Add hidden option to add slashes between lines into PDF. +- New: [ task #210 ] Can choose cash account during POS login. +- New: [ task #104 ] Can create an invoice from several orders. - New: Update libs/tools/logo for DoliWamp (now use PHP 5.3). - New: Added ODT Template tag {object_total_discount} - New: Add new import options: Third parties bank details, warehouses and stocks, categories and suppliers prices @@ -60,10 +62,12 @@ For users: - New: Can choose menu entry to show with external site module. - New: Add hidden option MAIN_PDF_MARGIN_LEFT, MAIN_PDF_MARGIN_RIGHT, MAIN_PDF_MARGIN_TOP, MAIN_PDF_MARGIN_BOTTOM to force margins of generated PDF. +- New: [ task #314 ] Can define if prof id are mandatory or not New experimental modules: - New: Add margin management module. - New: Add commissions management module. + - Fix: [ bug #499 ]: Supplier order input method not translated - Fix: No images into product description lines as PDF generation does not work with this. diff --git a/build/debian/apache.conf b/build/debian/apache.conf index 249c100245d..560a1c5193c 100644 --- a/build/debian/apache.conf +++ b/build/debian/apache.conf @@ -34,16 +34,6 @@ Alias /dolibarr /usr/share/dolibarr/htdocs - # OPTIMIZE: To use gzip compressed files (for Dolibarr already compressed files). - # Note that constant MAIN_OPTIMIZE_SPEED must have a value with bit 0 set. - #AddType text/javascript .jgz - #AddEncoding gzip .jgz - - # OPTIMIZE: To use gzip compression (on the fly). - # Note that you must also enable the module mod_deflate. - # You can also set this with constant MAIN_OPTIMIZE_SPEED and bit 2 set. - #TODO - # OPTIMIZE: To use cache on static pages (A259200 = 1 month). # Note that you must also enable the module mod_expires. #ExpiresActive On diff --git a/build/debian/conf.php.install b/build/debian/conf.php.install index 78195f27006..e439e80caef 100755 --- a/build/debian/conf.php.install +++ b/build/debian/conf.php.install @@ -161,12 +161,11 @@ $dolibarr_main_authentication='dolibarr'; # $dolibarr_main_auth_ldap_filter = ''; # If defined, two previous parameters are not used to find a user into LDAP. Ex: (uid=%1%) or &(uid=%1%)(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com). # $dolibarr_main_auth_ldap_admin_login=''; # Required only if anonymous bind disabled. Ex: cn=admin,dc=example,dc=com # $dolibarr_main_auth_ldap_admin_pass=''; # Required only if anonymous bind disabled. Ex: secret - # $dolibarr_main_auth_ldap_debug='false'; # dolibarr_main_demo -# Login and pass to use in a demo mode +# Login and pass to use in a demo mode. # Default value: '' # Examples: # $dolibarr_main_demo='autologin,autopass' diff --git a/build/debian/control.debianbin b/build/debian/control.debianbin deleted file mode 100755 index 39fe764e088..00000000000 --- a/build/debian/control.debianbin +++ /dev/null @@ -1,55 +0,0 @@ -Package: dolibarr -Version: __VERSION__ -Architecture: all -Maintainer: Laurent Destailleur -Installed-Size: 61200 -Depends: libapache2-mod-php5 | libapache2-mod-php5filter | php5-cgi | php5-fpm | php5, - php5-mysql | php5-mysqli, - php5-cli, php5-curl, php5-gd, php5-ldap, php-pear, php-mail-mime, php5-geoip, - libphp-adodb, - libnusoap-php, - libphp-pclzip, - libjs-jquery, libjs-jquery-ui, ckeditor, - ttf-dejavu-core, - xdg-utils, - mysql-server -Section: web -Priority: optional -Homepage: http://www.dolibarr.org -Description: Web based software to manage a small company or foundation - Dolibarr ERP & CRM is an easy to use open source/free software for small - and medium companies, foundations or freelances. It includes different - features for Enterprise Resource Planning (ERP) and Customer Relationship - Management (CRM) but also for different other activities. - It's a web software you can install as a standalone program or on any web - hosting provider to use it from anywhere with any web browser. - . - Dolibarr was designed to be easy to use. Only features you need are - visible, depending on which module were activated. - Most common used modules are: - . - Customers, Suppliers or Prospects directory, - Contacts directory, - Orders management, - Commercial proposals management, - Invoices management, - Products and services catalog, - Stock management, - Foundations members management, - Bank accounts management, - Point of Sale, - Payments management, - Commercial actions management, - Contracts management, - Standing orders management, - Shipping management, - Donations management, - Bookmarks management, - Mass Emailings, - Reports, - Wizards to export and import data, - LDAP connectivity, - PDF exports, - And a lot of more modules... - . - You can also add third parties external modules or develop yours. diff --git a/build/debian/install.forced.php.install b/build/debian/install.forced.php.install index c62d4760d23..3977caf8430 100755 --- a/build/debian/install.forced.php.install +++ b/build/debian/install.forced.php.install @@ -29,13 +29,14 @@ $force_install_lockinstall='444'; // If we enable/disable libraries declaration during install, we must also check they are // not removed from package (see in rules file), // declared into dependencies (see in control file) +$force_dolibarr_lib_TCPDF_PATH=''; +$force_dolibarr_lib_FPDF_PATH='/usr/share/php/fpdf'; +$force_dolibarr_lib_FPDI_PATH='/usr/share/php/fpdi'; $force_dolibarr_lib_ADODB_PATH='/usr/share/php/adodb'; -//$force_dolibarr_lib_FPDI_PATH='/usr/share/php/fpdi'; $force_dolibarr_lib_GEOIP_PATH=''; $force_dolibarr_lib_NUSOAP_PATH='/usr/share/php/nusoap'; $force_dolibarr_lib_ODTPHP_PATHTOPCLZIP='/usr/share/php/libphp-pclzip'; $force_dolibarr_lib_PHPEXCEL_PATH=''; -$force_dolibarr_lib_TCPDF_PATH=''; $force_dolibarr_js_CKEDITOR='/javascript/ckeditor'; $force_dolibarr_js_JQUERY='/javascript/jquery'; $force_dolibarr_js_JQUERY_UI='/javascript/jquery-ui'; diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index a18529821b6..eda983bbb88 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -337,6 +337,7 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/freefont-20100919`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/utils`; $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/LICENSE.TXT`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/savant`; } # Build package for each target diff --git a/dev/skeletons/modMyModule.class.php b/dev/skeletons/modMyModule.class.php index 6107560d656..9200524f259 100644 --- a/dev/skeletons/modMyModule.class.php +++ b/dev/skeletons/modMyModule.class.php @@ -111,9 +111,9 @@ class modMyModule extends DolibarrModules $this->const = array(); // Array to add new pages in new tabs - // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 - // 'objecttype:+tabname2:Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2 - // 'objecttype:-tabname'); // To remove an existing tab identified by code tabname + // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 + // 'objecttype:+tabname2:Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2 + // 'objecttype:-tabname':NU:conditiontoremove); // To remove an existing tab identified by code tabname // where objecttype can be // 'thirdparty' to add a tab in third party view // 'intervention' to add a tab in intervention view diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 1e8f6dadc18..4a0d966b6d2 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -33,8 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; /** - * \class Adherent - * \brief Class to manage members of a foundation + * Class to manage members of a foundation */ class Adherent extends CommonObject { @@ -705,7 +704,7 @@ class Adherent extends CommonObject $this->db->begin(); - // Suppression options + // Remove extrafields $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent_extrafields WHERE fk_object = ".$rowid; dol_syslog(get_class($this)."::delete sql=".$sql); diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index d6a0ed1ce91..2c05f71a5da 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -28,8 +28,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; /** - * \class AdherentType - * \brief Class to manage members type + * Class to manage members type */ class AdherentType extends CommonObject { diff --git a/htdocs/adherents/class/adherentstats.class.php b/htdocs/adherents/class/adherentstats.class.php index 52d73691cb8..c1a2537aa3a 100755 --- a/htdocs/adherents/class/adherentstats.class.php +++ b/htdocs/adherents/class/adherentstats.class.php @@ -28,8 +28,7 @@ include_once DOL_DOCUMENT_ROOT . '/adherents/class/cotisation.class.php'; /** - * \class AdherentStats - * \brief Classe permettant la gestion des stats des adherents + * Class to manage statistics of members */ class AdherentStats extends Stats { diff --git a/htdocs/adherents/class/cotisation.class.php b/htdocs/adherents/class/cotisation.class.php index f08b2257a7d..f333a6fbb98 100644 --- a/htdocs/adherents/class/cotisation.class.php +++ b/htdocs/adherents/class/cotisation.class.php @@ -26,8 +26,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; /** - * \class Cotisation - * \brief Class to manage subscriptions of foundation members + * Class to manage subscriptions of foundation members */ class Cotisation extends CommonObject { diff --git a/htdocs/adherents/stats/byproperties.php b/htdocs/adherents/stats/byproperties.php new file mode 100755 index 00000000000..dcc25501d84 --- /dev/null +++ b/htdocs/adherents/stats/byproperties.php @@ -0,0 +1,151 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/adherents/stats/byproperties.php + * \ingroup member + * \brief Page with statistics on members + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; + +$graphwidth = 700; +$mapratio = 0.5; +$graphheight = round($graphwidth * $mapratio); + +$mode=GETPOST('mode')?GETPOST('mode'):''; + + +// Security check +if ($user->societe_id > 0) +{ + $action = ''; + $socid = $user->societe_id; +} +if (! $user->rights->adherent->cotisation->lire) + accessforbidden(); + +$year = strftime("%Y", time()); +$startyear=$year-2; +$endyear=$year; + + + +/* + * View + */ + +$memberstatic=new Adherent($db); + +llxHeader('','','','',0,0,array('http://www.google.com/jsapi')); + +$title=$langs->trans("MembersStatisticsByProperties"); + +print_fiche_titre($title, $mesg); + +dol_mkdir($dir); + +$tab='byproperties'; + +$data = array(); +$sql.="SELECT COUNT(d.rowid) as nb, MAX(d.datevalid) as lastdate, d.morphy as code"; +$sql.=" FROM ".MAIN_DB_PREFIX."adherent as d"; +$sql.=" WHERE d.entity IN (".getEntity().")"; +$sql.=" AND d.statut = 1"; +$sql.=" GROUP BY d.morphy"; + +$foundphy=$foundmor=0; + +// Define $data array +dol_syslog("Count member sql=".$sql); +$resql=$db->query($sql); +if ($resql) +{ + $num=$db->num_rows($resql); + $i=0; + while ($i < $num) + { + $obj=$db->fetch_object($resql); + + if ($obj->code == 'phy') $foundphy++; + if ($obj->code == 'mor') $foundmor++; + + $data[]=array('label'=>$obj->code, 'nb'=>$obj->nb, 'lastdate'=>$db->jdate($obj->lastdate)); + + $i++; + } + $db->free($resql); +} +else +{ + dol_print_error($db); +} + + +$head = member_stats_prepare_head($adh); + +dol_fiche_head($head, 'statsbyproperties', $langs->trans("Statistics"), 0, 'user'); + + +// Print title +if (! count($data)) +{ + print $langs->trans("NoValidatedMemberYet").'
'; + print '
'; +} +else +{ + print_fiche_titre($langs->trans("MembersByNature"),'',''); +} + +// Print array +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +if (! $foundphy) $data[]=array('label'=>'phy','nb'=>'0','lastdate'=>''); +if (! $foundmor) $data[]=array('label'=>'mor','nb'=>'0','lastdate'=>''); + +$oldyear=0; +$var=true; +foreach ($data as $val) +{ + $year = $val['year']; + $var=!$var; + print ''; + print ''; + print ''; + print ''; + print ''; + $oldyear=$year; +} + +print '
'.$langs->trans("Nature").''.$langs->trans("NbOfMembers").''.$langs->trans("LastMemberDate").'
'.$memberstatic->getmorphylib($val['label']).''.$val['nb'].''.dol_print_date($val['lastdate'],'dayhour').'
'; + + +dol_fiche_end(); + + +llxFooter(); + +$db->close(); +?> diff --git a/htdocs/adherents/stats/geo.php b/htdocs/adherents/stats/geo.php index b97133c4606..cdc731ecdca 100755 --- a/htdocs/adherents/stats/geo.php +++ b/htdocs/adherents/stats/geo.php @@ -277,7 +277,8 @@ if ($mode) dol_fiche_end(); -$db->close(); llxFooter(); + +$db->close(); ?> diff --git a/htdocs/admin/agenda.php b/htdocs/admin/agenda.php index c0d9d389627..5af5b8a5787 100644 --- a/htdocs/admin/agenda.php +++ b/htdocs/admin/agenda.php @@ -94,6 +94,34 @@ if ($action == "save" && empty($cancel)) } } +if (preg_match('/set_(.*)/',$action,$reg)) +{ + $code=$reg[1]; + $value=(GETPOST($code) ? GETPOST($code) : 1); + if (dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity) > 0) + { + Header("Location: ".$_SERVER["PHP_SELF"]); + exit; + } + else + { + dol_print_error($db); + } +} + +if (preg_match('/del_(.*)/',$action,$reg)) +{ + $code=$reg[1]; + if (dolibarr_del_const($db, $code, $conf->entity) > 0) + { + Header("Location: ".$_SERVER["PHP_SELF"]); + exit; + } + else + { + dol_print_error($db); + } +} /** @@ -159,6 +187,46 @@ print "\n"; print ''; +/* + * Other options +*/ + +print_titre($langs->trans("OtherOptions")); + +$var=true; + +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; + +// Manual or automatic +$var=!$var; +print ''."\n"; +print ''."\n"; +print ''."\n"; + +print ''."\n"; + + print "
"; dol_htmloutput_mesg($mesg); diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index b1838928511..0bee6992ec1 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -547,7 +547,7 @@ if ($action == 'edit' || $action == 'updateedit') /* * Local Taxes */ - if ($mysoc->country_code=='ES') + if ($mysoc->hasLocalTax(1)) { // Local Tax 1 print '
'; @@ -563,7 +563,8 @@ if ($action == 'edit' || $action == 'updateedit') print '\n"; @@ -572,11 +573,14 @@ if ($action == 'edit' || $action == 'updateedit') print '\n"; print "
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("AGENDA_USE_EVENT_TYPE").' '."\n"; +if ($conf->use_javascript_ajax) +{ + print ajax_constantonoff('AGENDA_USE_EVENT_TYPE'); +} +else +{ + if($conf->global->AGENDA_USE_EVENT_TYPE == 0) + { + print ''.img_picto($langs->trans("Disabled"),'off').''; + } + else if($conf->global->BUSINESS_VISIBLE_TO_ALL_BY_DEFAULT == 1) + { + print ''.img_picto($langs->trans("Enabled"),'on').''; + } +} +print '
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code); + print ($example!="LocalTax1IsUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax1IsUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code)."
"; print "
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code); + print ($example!="LocalTax1IsNotUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax1IsNotUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code)."
"; print "
"; - + } + if ($mysoc->hasLocalTax(2)) + { // Local Tax 2 print '
'; print ''; @@ -591,7 +595,8 @@ if ($action == 'edit' || $action == 'updateedit') print '\n"; @@ -600,7 +605,8 @@ if ($action == 'edit' || $action == 'updateedit') print '\n"; print "
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code); + print ($example!="LocalTax2IsUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax2IsUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code)."
"; print "
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code); + print ($example!="LocalTax2IsNotUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax2IsNotUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code)."
"; print "
"; @@ -921,7 +927,7 @@ else /* * Local Taxes */ - if ($mysoc->country_code=='ES') + if ($mysoc->hasLocalTax(1)) { // Local Tax 1 print '
'; @@ -937,7 +943,8 @@ else print ''; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code); + print ($example!="LocalTax1IsUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax1IsUsedDesc",$mysoc->country_code)."
".$langs->trans("Example",$mysoc->country_code).': '.$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsUsedExample",$mysoc->country_code)."
"; print "\n"; @@ -946,12 +953,15 @@ else print ''; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code); + print ($example!="LocalTax1IsNotUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax1IsNotUsedDesc",$mysoc->country_code)."
".$langs->trans("Example",$mysoc->country_code).': '.$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax1IsNotUsedExample",$mysoc->country_code)."
"; print "\n"; print ""; - + } + if ($mysoc->hasLocalTax(2)) + { // Local Tax 2 print '
'; print ''; @@ -966,7 +976,8 @@ else print '\n"; @@ -975,7 +986,8 @@ else print '\n"; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 92111cd9a2c..e18420285c0 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -1066,7 +1066,6 @@ if ($id) } } - print '"; // Modify link diff --git a/htdocs/admin/mailing.php b/htdocs/admin/mailing.php index 0732dbeb31c..f43c9f8b244 100644 --- a/htdocs/admin/mailing.php +++ b/htdocs/admin/mailing.php @@ -40,7 +40,16 @@ $action = GETPOST('action','alpha'); * Actions */ -if ($action == 'setvalue' && $user->admin) +if ($action == 'setMAILING_EMAIL_UNSUBSCRIBE') +{ + $res=dolibarr_set_const($db, "MAILING_EMAIL_UNSUBSCRIBE",1,'chaine',0,'',$conf->entity); +} +if ($action == 'unsetMAILING_EMAIL_UNSUBSCRIBE') +{ + $res=dolibarr_del_const($db, "MAILING_EMAIL_UNSUBSCRIBE"); +} + +if ($action == 'setvalue') { $db->begin(); @@ -129,14 +138,14 @@ print ''; -print '
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code); + print ($example!="LocalTax2IsUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax2IsUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsUsedExample",$mysoc->country_code)."
"; print "
'; print ""; print ""; - print "\n"; + $example=$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code); + print ($example!="LocalTax2IsNotUsedExample"?"\n":""); print "
".$langs->transcountry("LocalTax2IsNotUsedDesc",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code)."
".$langs->trans("Example").': '.$langs->transcountry("LocalTax2IsNotUsedExample",$mysoc->country_code)."
"; print "
'; // Est-ce une entree du dictionnaire qui peut etre desactivee ? $iserasable=1; // Oui par defaut if (isset($obj->code) && ($obj->code == '0' || $obj->code == '' || preg_match('/unknown/i',$obj->code))) $iserasable=0; @@ -1074,8 +1073,14 @@ if ($id) if (isset($obj->code) && $obj->code == 'EF0') $iserasable=0; if (isset($obj->type) && in_array($obj->type, array('system', 'systemauto'))) $iserasable=0; + // Active + print ''; if ($iserasable) print ''.$actl[$obj->active].''; - else print $langs->trans("AlwaysActive"); + else + { + if (isset($obj->type) && in_array($obj->type, array('system', 'systemauto')) && empty($obj->active)) print $langs->trans("Deprecated"); + else print $langs->trans("AlwaysActive"); + } print "
'; print $langs->trans("ActivateCheckRead").''; if (!empty($conf->global->MAILING_EMAIL_UNSUBSCRIBE)) { - print ''; + print ''; print img_picto($langs->trans("Enabled"),'switch_on'); print ''; $readonly=''; } else { - print ''; + print ''; print img_picto($langs->trans("Disabled"),'switch_off'); print ''; $readonly='disabled="disabled"'; @@ -149,11 +158,13 @@ print $langs->trans("ActivateCheckReadKey").''; print ''; print '
'; +print ''; print '
'; print '
'; +print ''; + llxFooter(); $db->close(); diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 6d869ba7a78..eddb3b7c859 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -591,19 +591,19 @@ else print ''; - // Warning 1 if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') { print '
'; + /* + // Warning 1 if ($linuxlike) { $sendmailoption=ini_get('mail.force_extra_parameters'); - //print 'x'.$sendmailoption; if (empty($sendmailoption) || ! preg_match('/ba/',$sendmailoption)) { print info_admin($langs->trans("SendmailOptionNotComplete")); } - } + }*/ // Warning 2 print info_admin($langs->trans("SendmailOptionMayHurtBuggedMTA")); } @@ -657,11 +657,11 @@ else print '
'; } - // Affichage formulaire de TEST simple - if ($action == 'test') + // Show email send test form + if ($action == 'test' || $action == 'testhtml') { print '
'; - print_titre($langs->trans("DoTestSend")); + print_titre($action == 'testhtml'?$langs->trans("DoTestSendHTML"):$langs->trans("DoTestSend")); // Cree l'objet formulaire mail include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; @@ -678,62 +678,16 @@ else $formmail->withtopic=(isset($_POST['subject'])?$_POST['subject']:$langs->trans("Test")); $formmail->withtopicreadonly=0; $formmail->withfile=2; - $formmail->withbody=(isset($_POST['message'])?$_POST['message']:$langs->trans("PredefinedMailTest")); + $formmail->withbody=(isset($_POST['message'])?$_POST['message']:($action == 'testhtml'?$langs->trans("PredefinedMailTestHtml"):$langs->trans("PredefinedMailTest"))); $formmail->withbodyreadonly=0; $formmail->withcancel=1; $formmail->withdeliveryreceipt=1; - $formmail->withfckeditor=0; - // Tableau des substitutions - $formmail->substit=$substitutionarrayfortest; - // Tableau des parametres complementaires du post - $formmail->param["action"]="send"; - $formmail->param["models"]="body"; - $formmail->param["mailid"]=0; - $formmail->param["returnurl"]=$_SERVER["PHP_SELF"]; - - // Init list of files - if (GETPOST("mode")=='init') - { - $formmail->clear_attached_files(); - } - - $formmail->show_form('addfile','removefile'); - - print '
'; - } - - // Affichage formulaire de TEST HTML - if ($action == 'testhtml') - { - print '
'; - print_titre($langs->trans("DoTestSendHTML")); - - // Cree l'objet formulaire mail - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; - $formmail = new FormMail($db); - $formmail->fromname = (isset($_POST['fromname'])?$_POST['fromname']:$conf->global->MAIN_MAIL_EMAIL_FROM); - $formmail->frommail = (isset($_POST['frommail'])?$_POST['frommail']:$conf->global->MAIN_MAIL_EMAIL_FROM); - $formmail->withfromreadonly=0; - $formmail->withsubstit=0; - $formmail->withfrom=1; - $formmail->witherrorsto=1; - $formmail->withto=(! empty($_POST['sendto'])?$_POST['sendto']:($user->email?$user->email:1)); - $formmail->withtocc=(! empty($_POST['sendtocc'])?$_POST['sendtocc']:1); // ! empty to keep field if empty - $formmail->withtoccc=(! empty($_POST['sendtoccc'])?$_POST['sendtoccc']:1); // ! empty to keep field if empty - $formmail->withtopic=(isset($_POST['subject'])?$_POST['subject']:$langs->trans("Test")); - $formmail->withtopicreadonly=0; - $formmail->withfile=2; - $formmail->withbody=(isset($_POST['message'])?$_POST['message']:$langs->trans("PredefinedMailTestHtml")); - //$formmail->withbody='Test aaa __LOGIN__'; - $formmail->withbodyreadonly=0; - $formmail->withcancel=1; - $formmail->withdeliveryreceipt=1; - $formmail->withfckeditor=1; + $formmail->withfckeditor=($action == 'testhtml'?1:0); $formmail->ckeditortoolbar='dolibarr_mailings'; // Tableau des substitutions $formmail->substit=$substitutionarrayfortest; // Tableau des parametres complementaires du post - $formmail->param["action"]="sendhtml"; + $formmail->param["action"]=($action == 'testhtml'?"sendhtml":"send"); $formmail->param["models"]="body"; $formmail->param["mailid"]=0; $formmail->param["returnurl"]=$_SERVER["PHP_SELF"]; @@ -744,7 +698,7 @@ else $formmail->clear_attached_files(); } - $formmail->show_form('addfilehtml','removefilehtml'); + $formmail->show_form(($action == 'testhtml'?'addfilehtml':'addfile'),($action == 'testhtml'?'removefilehtml':'removefile')); print '
'; } diff --git a/htdocs/admin/user.php b/htdocs/admin/user.php index bf9bec788d4..2fd9e0d5a4a 100644 --- a/htdocs/admin/user.php +++ b/htdocs/admin/user.php @@ -27,7 +27,9 @@ */ require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $langs->load("admin"); $langs->load("members"); @@ -35,6 +37,9 @@ $langs->load("users"); if (! $user->admin) accessforbidden(); +$extrafields = new ExtraFields($db); + + /* * Action */ @@ -71,14 +76,17 @@ if (preg_match('/del_(.*)/',$action,$reg)) * View */ -llxHeader(); +$help_url='EN:Module_Users|FR:Module_Utilisateurs|ES:Módulo_Usuarios'; +llxHeader('',$langs->trans("UsersSetup"),$help_url); $linkback=''.$langs->trans("BackToModuleList").''; print_fiche_titre($langs->trans("UsersSetup"),$linkback,'setup'); -print "
"; -print_fiche_titre($langs->trans("MemberMainOptions"),'',''); +$head=user_admin_prepare_head(); + +dol_fiche_head($head,'card', $langs->trans("User"), 0, 'user'); + print ''; print ''; print ''; @@ -114,7 +122,8 @@ else print ''; print '
'.$langs->trans("Description").'
'; -print '

'; + +dol_fiche_end(); llxFooter(); $db->close(); diff --git a/htdocs/bookmarks/class/bookmark.class.php b/htdocs/bookmarks/class/bookmark.class.php index 088d4751d2e..277e6318590 100644 --- a/htdocs/bookmarks/class/bookmark.class.php +++ b/htdocs/bookmarks/class/bookmark.class.php @@ -23,8 +23,7 @@ /** - * \class Bookmark - * \brief Class to manage bookmarks + * Class to manage bookmarks */ class Bookmark { diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 760651a7f2b..a79650fa893 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -477,12 +477,14 @@ class ActionComm extends CommonObject * @param int $fk_element Id of element action is linked to * @param string $elementtype Type of element action is linked to * @param string $filter Other filter - * @return int <0 if KO, >0 if OK + * @return array <0 if KO, array with actions */ - function getActions($socid=0, $fk_element=0, $elementtype='', $filter='') + static function getActions($db, $socid=0, $fk_element=0, $elementtype='', $filter='') { global $conf, $langs; + $resarray=array(); + $sql = "SELECT a.id"; $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as a"; $sql.= " WHERE a.entity = ".$conf->entity; @@ -495,27 +497,27 @@ class ActionComm extends CommonObject if (! empty($filter)) $sql.= $filter; dol_syslog(get_class($this)."::getActions sql=".$sql); - $resql=$this->db->query($sql); + $resql=$db->query($sql); if ($resql) { - $num = $this->db->num_rows($resql); + $num = $db->num_rows($resql); if ($num) { for($i=0;$i<$num;$i++) { - $obj = $this->db->fetch_object($resql); - $actioncommstatic = new ActionComm($this->db); + $obj = $db->fetch_object($resql); + $actioncommstatic = new ActionComm($db); $actioncommstatic->fetch($obj->id); - $this->actions[$i] = $actioncommstatic; + $resarray[$i] = $actioncommstatic; } } - $this->db->free($resql); - return 1; + $db->free($resql); + return $resarray; } else { - $this->error=$this->db->lasterror(); + $this->error=$db->lasterror(); return -1; } } @@ -707,26 +709,34 @@ class ActionComm extends CommonObject if ($option=='birthday') $lien = ''; else $lien = ''; $lienfin=''; - //print $this->libelle; + $label=$this->label; + if (empty($label)) $label=$this->libelle; // Fro backward compatibility + //print 'rrr'.$this->libelle; + if ($withpicto == 2) { - $libelle=$langs->trans("Action".$this->type_code); + $libelle=$label; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) $libelle=$langs->trans("Action".$this->type_code); $libelleshort=''; } else if (empty($this->libelle)) { - $libelle=$langs->trans("Action".$this->type_code); - $libelleshort=$langs->trans("Action".$this->type_code,'','','','',$maxlength); + $libelle=$label; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) $libelle=$langs->trans("Action".$this->type_code); + $libelleshort=dol_trunc($label, $maxlength); } else - { - $libelle=$this->libelle; - $libelleshort=dol_trunc($this->libelle,$maxlength); + { + $libelle=$label; + $libelleshort=dol_trunc($label,$maxlength); } if ($withpicto) { - $libelle.=(($this->type_code && $libelle!=$langs->trans("Action".$this->type_code) && $langs->trans("Action".$this->type_code)!="Action".$this->type_code)?' ('.$langs->trans("Action".$this->type_code).')':''); + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + { + $libelle.=(($this->type_code && $libelle!=$langs->trans("Action".$this->type_code) && $langs->trans("Action".$this->type_code)!="Action".$this->type_code)?' ('.$langs->trans("Action".$this->type_code).')':''); + } $result.=$lien.img_object($langs->trans("ShowAction").': '.$libelle,($overwritepicto?$overwritepicto:'action')).$lienfin; } if ($withpicto==1) $result.=' '; diff --git a/htdocs/comm/action/class/cactioncomm.class.php b/htdocs/comm/action/class/cactioncomm.class.php index 50f9f077785..f1c8a4abbaf 100644 --- a/htdocs/comm/action/class/cactioncomm.class.php +++ b/htdocs/comm/action/class/cactioncomm.class.php @@ -100,9 +100,10 @@ class CActionComm * @param int $active 1 or 0 to filter on event state active or not ('' by default = no filter) * @param string $idorcode 'id' or 'code' * @param string $excludetype Type to exclude + * @param string $onlyautoornot Group list by auto events or not * @return array Array of all event types if OK, <0 if KO */ - function liste_array($active='',$idorcode='id',$excludetype='') + function liste_array($active='',$idorcode='id',$excludetype='',$onlyautoornot=0) { global $langs,$conf; $langs->load("commercial"); @@ -110,7 +111,7 @@ class CActionComm $repid = array(); $repcode = array(); - $sql = "SELECT id, code, libelle, module"; + $sql = "SELECT id, code, libelle, module, type"; $sql.= " FROM ".MAIN_DB_PREFIX."c_actioncomm"; if ($active != '') $sql.=" WHERE active=".$active; if (! empty($excludetype)) $sql.=($active != ''?" AND":" WHERE")." type <> '".$excludetype."'"; @@ -127,20 +128,31 @@ class CActionComm while ($i < $nump) { $obj = $this->db->fetch_object($resql); + $qualified=1; - if ($obj->module) + + // $obj->type can be system, systemauto, module, moduleauto, xxx, xxxauto + if ($qualified && $onlyautoornot && preg_match('/^system/',$obj->type) && ! preg_match('/^AC_OTH/',$obj->code)) $qualified=0; // We discard detailed system events. We keep only the 2 generic lines (AC_OTH and AC_OTHER) + + if ($qualified && $obj->module) { if ($obj->module == 'invoice' && ! $conf->facture->enabled) $qualified=0; if ($obj->module == 'order' && ! $conf->commande->enabled) $qualified=0; if ($obj->module == 'propal' && ! $conf->propal->enabled) $qualified=0; if ($obj->module == 'invoice_supplier' && ! $conf->fournisseur->enabled) $qualified=0; if ($obj->module == 'order_supplier' && ! $conf->fournisseur->enabled) $qualified=0; + if ($obj->module == 'shipping' && ! $conf->expedition->enabled) $qualified=0; } + if ($qualified) { - $transcode=$langs->trans("Action".$obj->code); - $repid[$obj->id] = ($transcode!="Action".$obj->code?$transcode:$langs->trans($obj->libelle)); - $repcode[$obj->code] = ($transcode!="Action".$obj->code?$transcode:$langs->trans($obj->libelle)); + $code=$obj->code; + if ($onlyautoornot && $code == 'AC_OTH') $code='AC_MANUAL'; + if ($onlyautoornot && $code == 'AC_OTH_AUTO') $code='AC_AUTO'; + $transcode=$langs->trans("Action".$code); + $repid[$obj->id] = ($transcode!="Action".$code?$transcode:$langs->trans($obj->libelle)); + $repcode[$obj->code] = ($transcode!="Action".$code?$transcode:$langs->trans($obj->libelle)); + if ($onlyautoornot && preg_match('/^module/',$obj->type) && $obj->module) $repcode[$obj->code].=' ('.$langs->trans("Module").': '.$obj->module.')'; } $i++; } diff --git a/htdocs/comm/action/contact.php b/htdocs/comm/action/contact.php new file mode 100644 index 00000000000..625dd854790 --- /dev/null +++ b/htdocs/comm/action/contact.php @@ -0,0 +1,429 @@ + + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2012 Philippe Grand + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/comm/action/contact.php + * \ingroup agenda + * \brief Page for multi-users event + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; +require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + +$langs->load("companies"); +$langs->load("commercial"); +$langs->load("other"); +$langs->load("bills"); + +$id = GETPOST('id','int'); +$action = GETPOST('action','alpha'); +$ref = GETPOST('ref'); +$confirm = GETPOST('confirm'); +$lineid = GETPOST('lineid','int'); + +// Security check +if ($user->societe_id > 0) +{ + unset($_GET["action"]); + $action=''; + $socid = $user->societe_id; +} + +$object = new ActionComm($db); + +/* + * Actions + */ + +/* + * Ajout d'un nouveau contact + */ + +if ($action == 'addcontact') +{ + $result = $object->fetch($id); + + if ($object->id > 0) + { + $contactid = (GETPOST('userid','int') ? GETPOST('userid','int') : GETPOST('contactid','int')); + $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]); + } + + if ($result >= 0) + { + header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); + exit; + } + else + { + if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') + { + $langs->load("errors"); + setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); + } + else + { + setEventMessage($object->error, 'errors'); + } + } +} + +// modification d'un contact. On enregistre le type +if ($action == 'updateline') +{ + if ($object->fetch($id)) + { + $contact = $object->detail_contact($_POST["line"]); + $type = $_POST["type"]; + $statut = $contact->statut; + + $result = $object->update_contact($_POST["line"], $statut, $type); + if ($result >= 0) + { + $db->commit(); + } else + { + dol_print_error($db, "result=$result"); + $db->rollback(); + } + } + else + { + setEventMessage($object->error, 'errors'); + } +} + +// Bascule du statut d'un contact +else if ($action == 'swapstatut') +{ + if ($object->id > 0) + { + $result=$object->swapContactStatus(GETPOST('ligne')); + } +} + +// Efface un contact +else if ($action == 'deletecontact') +{ + $result = $object->delete_contact($lineid); + + if ($result >= 0) + { + header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); + exit; + } + else + { + dol_print_error($db); + } +} + +/* + * View + */ + +$form = new Form($db); +$formcompany= new FormCompany($db); + +$contactstatic=new Contact($db); +$userstatic=new User($db); + +$help_url='EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; +llxHeader('',$langs->trans("Agenda"),$help_url); + + +if ($id > 0 || ! empty($ref)) +{ + dol_htmloutput_mesg($mesg,$mesgs); + + if ($object->fetch($id,$ref) > 0) + { + + $head=actions_prepare_head($object); + dol_fiche_head($head, 'contact', $langs->trans("Action"),0,'action'); + + // Affichage fiche action en mode visu + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + + // Type + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + { + print ''; + } + + // Title + print ''; + + // Full day event + print ''; + + // Date start + print ''; + print ''; + print ''; + + // Date end + print ''; + + // Location + print ''; + + + print '
'.$langs->trans("Ref").''; + print $form->showrefnav($object, 'id', $linkback, ($user->societe_id?0:1), 'id', 'ref', ''); + print '
'.$langs->trans("Type").''.$object->type.'
'.$langs->trans("Title").''.$object->label.'
'.$langs->trans("EventOnFullDay").''.yn($object->fulldayevent).'
'.$langs->trans("DateActionStart").''; + if (! $object->fulldayevent) print dol_print_date($object->datep,'dayhour'); + else print dol_print_date($object->datep,'day'); + if ($object->percentage == 0 && $object->datep && $object->datep < ($now - $delay_warning)) print img_warning($langs->trans("Late")); + print ''."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendar').' '; + print '
'."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendarweek').' '; + print '
'."\n"; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + //print ''; + print img_picto($langs->trans("ViewCal"),'object_calendarday').' '; + print '
'."\n"; + print '
'.$langs->trans("DateActionEnd").''; + if (! $object->fulldayevent) print dol_print_date($object->datef,'dayhour'); + else print dol_print_date($object->datef,'day'); + if ($object->percentage > 0 && $object->percentage < 100 && $object->datef && $object->datef < ($now- $delay_warning)) print img_warning($langs->trans("Late")); + print '
'.$langs->trans("Location").''.$object->location.'
'; + + print ''; + /* + * Lignes de contacts + */ + print '
'; + + /* + * Ajouter une ligne de contact + * Non affiche en mode modification de ligne + */ + if ($action != 'editline') + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + + $var = false; + + print ''; + print ''; + print ''; + print ''; + print ''; + + // Ligne ajout pour contact interne + print ""; + + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + + // Line to add external contact. Only if project is linked to a third party. + if ($object->socid) + { + $var=!$var; + print ""; + + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + } + + print ""; + + print ''; + } + + // Liste des contacts lies + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + + $companystatic = new Societe($db); + $var = true; + + foreach(array('internal','external') as $source) + { + $tab = $object->liste_contact(-1,$source); + $num=sizeof($tab); + + $i = 0; + while ($i < $num) + { + $var = !$var; + + print ''; + + // Source + print ''; + + // Societe + print ''; + + // Contact + print ''; + + // Type de contact + print ''; + + // Statut + print ''; + + // Icon update et delete + print ''; + + print "\n"; + + $i ++; + } + } + print "
'.$langs->trans("Source").''.$langs->trans("Company").''.$langs->trans("Contacts").''.$langs->trans("ContactType").' 
'; + print img_object('','user').' '.$langs->trans("Users"); + print ''; + print $conf->global->MAIN_INFO_SOCIETE_NOM; + print ''; + // On recupere les id des users deja selectionnes + $form->select_users($user->id,'contactid',0); + print ''; + $formcompany->selectTypeContact($object, '', 'type','internal','rowid'); + print '
'; + print img_object('','contact').' '.$langs->trans("ThirdPartyContacts"); + print ''; + $selectedCompany = isset($_GET["newcompany"])?$_GET["newcompany"]:$object->socid; + $selectedCompany = $formcompany->selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany'); + print ''; + $nbofcontacts=$form->select_contacts($selectedCompany,'','contactid'); + if ($nbofcontacts == 0) print $langs->trans("NoContactDefined"); + print ''; + $formcompany->selectTypeContact($object,'','type','external','rowid'); + print '
 
'.$langs->trans("Source").''.$langs->trans("Company").''.$langs->trans("Contacts").''.$langs->trans("ContactType").''.$langs->trans("Status").' 
'; + if ($tab[$i]['source']=='internal') print $langs->trans("User"); + if ($tab[$i]['source']=='external') print $langs->trans("ThirdPartyContact"); + print ''; + if ($tab[$i]['socid'] > 0) + { + $companystatic->fetch($tab[$i]['socid']); + print $companystatic->getNomUrl(1); + } + if ($tab[$i]['socid'] < 0) + { + print $conf->global->MAIN_INFO_SOCIETE_NOM; + } + if (! $tab[$i]['socid']) + { + print ' '; + } + print ''; + if ($tab[$i]['source']=='internal') + { + print ''; + print img_object($langs->trans("ShowUser"),"user").' '.$tab[$i]['nom'].''; + } + if ($tab[$i]['source']=='external') + { + print ''; + print img_object($langs->trans("ShowContact"),"contact").' '.$tab[$i]['nom'].''; + } + print ''.$tab[$i]['libelle'].''; + // Activation desativation du contact + if ($object->statut >= 0 ) print ''; + print $contactstatic->LibStatut($tab[$i]['status'],3); + if ($object->statut >= 0 ) print ''; + print ''; + /*if ($user->rights->business->write && $userAccess) + {*/ + print ' '; + print ''; + print img_delete(); + print ''; + //} + print '
"; + } + else + { + print "ErrorRecordNotFound"; + } +} + +llxFooter(); + +$db->close(); + +?> diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php index 7fa1a71c5f3..db2e459f551 100755 --- a/htdocs/comm/action/document.php +++ b/htdocs/comm/action/document.php @@ -127,7 +127,10 @@ if ($objectid > 0) print ''; // Type - print ''.$langs->trans("Type").''.$act->type.''; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + { + print ''.$langs->trans("Type").''.$act->type.''; + } // Title print ''.$langs->trans("Title").''.$act->label.''; diff --git a/htdocs/comm/action/fiche.php b/htdocs/comm/action/fiche.php index 53b0dae69ab..5b5ebee90ee 100644 --- a/htdocs/comm/action/fiche.php +++ b/htdocs/comm/action/fiche.php @@ -107,6 +107,13 @@ if ($action == 'add_action') $mesg='
'.$langs->trans("ErrorFieldRequired",$langs->trans("DateEnd")).'
'; } + if (empty($conf->global->AGENDA_USE_EVENT_TYPE) && ! GETPOST('label')) + { + $error++; + $action = 'create'; + $mesg='
'.$langs->trans("ErrorFieldRequired",$langs->trans("Title")).'
'; + } + // Initialisation objet cactioncomm if (! GETPOST('actioncode')) { @@ -122,13 +129,13 @@ if ($action == 'add_action') // Initialisation objet actioncomm $actioncomm->type_id = $cactioncomm->id; $actioncomm->type_code = $cactioncomm->code; - $actioncomm->priority = isset($_POST["priority"])?$_POST["priority"]:0; + $actioncomm->priority = GETPOST("priority")?GETPOST("priority"):0; $actioncomm->fulldayevent = (! empty($fulldayevent)?1:0); - $actioncomm->location = isset($_POST["location"])?$_POST["location"]:''; - $actioncomm->label = trim($_POST["label"]); - if (! $_POST["label"]) + $actioncomm->location = GETPOST("location"); + $actioncomm->label = trim(GETPOST('label')); + if (! GETPOST('label')) { - if ($_POST["actioncode"] == 'AC_RDV' && $contact->getFullName($langs)) + if (GETPOST('actioncode') == 'AC_RDV' && $contact->getFullName($langs)) { $actioncomm->label = $langs->transnoentitiesnoconv("TaskRDVWith",$contact->getFullName($langs)); } @@ -390,11 +397,13 @@ if ($action == 'create') $(".fulldaystartmin").removeAttr("disabled"); $(".fulldayendhour").removeAttr("disabled"); $(".fulldayendmin").removeAttr("disabled"); + $("#p2").removeAttr("disabled"); } else { $(".fulldaystarthour").attr("disabled","disabled").val("00"); $(".fulldaystartmin").attr("disabled","disabled").val("00"); $(".fulldayendhour").attr("disabled","disabled").val("23"); $(".fulldayendmin").attr("disabled","disabled").val("59"); + $("#p2").attr("disabled","disabled").val(""); } } setdatefields(); @@ -432,21 +441,25 @@ if ($action == 'create') print ''; // Type d'action actifs - print ''; } - else - { - $htmlactions->select_type_actions($actioncomm->type_code, "actioncode","systemauto"); - } - print ''; + else print ''; // Title - print ''; + print 'global->AGENDA_USE_EVENT_TYPE)?' class="fieldrequired"':'').'>'.$langs->trans("Title").''; // Full day print ''; @@ -678,10 +691,13 @@ if ($id) print ''; // Type - print ''; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + { + print ''; + } // Title - print ''; + print 'global->AGENDA_USE_EVENT_TYPE)?' class="fieldrequired"':'').'>'.$langs->trans("Title").''; // Full day event print ''; @@ -797,7 +813,10 @@ if ($id) print ''; // Type - print ''; + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) + { + print ''; + } // Title print ''; diff --git a/htdocs/comm/addpropal.php b/htdocs/comm/addpropal.php index 7d03960dd11..a3f7c8ef647 100644 --- a/htdocs/comm/addpropal.php +++ b/htdocs/comm/addpropal.php @@ -340,6 +340,7 @@ if ($action == 'create') $langs->load("bills"); print '
'; print ''; + print ' '; print '
'; print ""; diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index d290ec43a75..e928de437b9 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -78,8 +78,6 @@ if ($action == 'del_bookmark' && ! empty($bid)) * View */ -$now=dol_now(); - $form = new Form($db); $formfile = new FormFile($db); $companystatic=new Societe($db); diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index 2081bda8cbb..79a018546c5 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -136,7 +136,7 @@ if ($action == 'delete') $classname = "MailingTargets"; $obj = new $classname($db); $obj->update_nb($id); - + header("Location: ".$_SERVER['PHP_SELF']."?id=".$id); exit; } @@ -298,7 +298,7 @@ if ($object->fetch($id) >= 0) } print ''; diff --git a/htdocs/comm/mailing/fiche.php b/htdocs/comm/mailing/fiche.php index 8e3b5064a70..af408cef79d 100644 --- a/htdocs/comm/mailing/fiche.php +++ b/htdocs/comm/mailing/fiche.php @@ -337,16 +337,30 @@ if ($action == 'sendallconfirmed' && $confirm == 'yes') $i++; } } + else + { + setEventMessage($langs->transnoentitiesnoconv("NoMoreRecipientToSendTo")); + } // Loop finished, set global statut of mail if ($nbko > 0) { $statut=2; // Status 'sent partially' (because at least one error) + if ($nbok > 0) setEventMessage($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok)); + else setEventMessage($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok)); } else { - if ($nbok >= $num) $statut=3; // Send to everybody - else $statut=2; // Status 'sent partially' (because not send to everybody) + if ($nbok >= $num) + { + $statut=3; // Send to everybody + setEventMessage($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok)); + } + else + { + $statut=2; // Status 'sent partially' (because not send to everybody) + setEventMessage($langs->transnoentitiesnoconv("EMailSentToNRecipients",$nbok)); + } } $sql="UPDATE ".MAIN_DB_PREFIX."mailing SET statut=".$statut." WHERE rowid=".$object->id; @@ -388,8 +402,8 @@ if ($action == 'send' && empty($_POST["cancel"])) if (preg_match('/[\s\t]*/i',$object->body)) $msgishtml=1; // Pratique les substitutions sur le sujet et message - $object->sujet=make_substitutions($object->sujet,$object->substitutionarrayfortest); - $object->body=make_substitutions($object->body,$object->substitutionarrayfortest); + $tmpsujet=make_substitutions($object->sujet,$object->substitutionarrayfortest); + $tmpbody=make_substitutions($object->body,$object->substitutionarrayfortest); $arr_file = array(); $arr_mime = array(); @@ -412,7 +426,7 @@ if ($action == 'send' && empty($_POST["cancel"])) } } - $mailfile = new CMailFile($object->sujet,$object->sendto,$object->email_from,$object->body, $arr_file,$arr_mime,$arr_name,'', '', 0, $msgishtml,$object->email_errorsto,$arr_css); + $mailfile = new CMailFile($tmpsujet,$object->sendto,$object->email_from,$tmpbody, $arr_file,$arr_mime,$arr_name,'', '', 0, $msgishtml,$object->email_errorsto,$arr_css); $result=$mailfile->sendfile(); if ($result) @@ -1148,7 +1162,6 @@ else } } - llxFooter(); $db->close(); ?> diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index 0df445e2b28..36dae818cfa 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -1565,21 +1565,19 @@ print ''; print ''; // Amount Local Taxes -if ($mysoc->country_code=='ES') +if ($mysoc->localtax1_assuj=="1") //Localtax1 { - if ($mysoc->localtax1_assuj=="1") //Localtax1 RE - { - print ''; - print ''; - print ''; - } - if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF - { - print ''; - print ''; - print ''; - } + print ''; + print ''; + print ''; } +if ($mysoc->localtax2_assuj=="1") //Localtax2 +{ + print ''; + print ''; + print ''; +} + // Amount TTC print ''; diff --git a/htdocs/comm/propal/index.php b/htdocs/comm/propal/index.php index fb6fa29902e..895f922395d 100644 --- a/htdocs/comm/propal/index.php +++ b/htdocs/comm/propal/index.php @@ -43,7 +43,7 @@ $result = restrictedArea($user, 'propal'); /* * View */ - +$now=dol_now(); $propalstatic=new Propal($db); $companystatic=new Societe($db); $form = new Form($db); @@ -288,7 +288,7 @@ if (! empty($conf->propal->enabled) && $user->rights->propale->lire) $now=dol_now(); - $sql = "SELECT s.nom as socname, s.rowid as socid, s.canvas, s.client, p.rowid as propalid, p.total as total_ttc, p.total_ht, p.ref, p.fk_statut, p.datep as dp"; + $sql = "SELECT s.nom as socname, s.rowid as socid, s.canvas, s.client, p.rowid as propalid, p.total as total_ttc, p.total_ht, p.ref, p.fk_statut, p.datep as dp, p.fin_validite as dfv"; $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql.= ", ".MAIN_DB_PREFIX."propal as p"; if (!$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -328,7 +328,7 @@ if (! empty($conf->propal->enabled) && $user->rights->propale->lire) print $propalstatic->getNomUrl(1); print ''; print ''; print ''; print ''; print '"; - if ($mysoc->country_code=='ES') + if ($mysoc->localtax1_assuj=="1") //Localtax1 RE { - if ($mysoc->localtax1_assuj=="1") //Localtax1 RE - { - print '"; - } - - if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF - { - print '"; - } + print '"; } + + if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF + { + print '"; + } + print '"; } else @@ -1814,11 +1812,8 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G if (! empty($conf->projet->enabled)) $nbrow++; //Local taxes - if ($mysoc->country_code=='ES') - { - if($mysoc->localtax1_assuj=="1") $nbrow++; - if($mysoc->localtax2_assuj=="1") $nbrow++; - } + if($mysoc->localtax1_assuj=="1") $nbrow++; + if($mysoc->localtax2_assuj=="1") $nbrow++; print '
'.$langs->trans("Type").''; - if (GETPOST("actioncode")) + if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - print ''."\n"; - $cactioncomm->fetch(GETPOST("actioncode")); - print $cactioncomm->getNomUrl(); + print '
'.$langs->trans("Type").''; + if (GETPOST("actioncode")) + { + print ''."\n"; + $cactioncomm->fetch(GETPOST("actioncode")); + print $cactioncomm->getNomUrl(); + } + else + { + $htmlactions->select_type_actions($actioncomm->type_code, "actioncode","systemauto"); + } + print '
'.$langs->trans("Title").'
'.$langs->trans("EventOnFullDay").'
'.$langs->trans("Ref").''.$act->id.'
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Title").'
'.$langs->trans("EventOnFullDay").'fulldayevent?' checked="checked"':'').'>
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Type").''.$act->type.'
'.$langs->trans("Title").''.$act->label.'
'; - if (! $obj->picto) $obj->picto='generic'; + if (empty($obj->picto)) $obj->picto='generic'; print img_object($langs->trans("Module").': '.get_class($obj),$obj->picto).' '.$obj->getDesc(); print ''.price($object->total_tva).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
'.$langs->trans('AmountTTC').''; - if ($db->jdate($obj->dp) < ($now - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late")); + if ($db->jdate($obj->dfv) < ($now - $conf->propal->cloture->warning_delay)) print img_warning($langs->trans("Late")); print ''; $filename=dol_sanitizeFileName($obj->ref); diff --git a/htdocs/commande/fiche.php b/htdocs/commande/fiche.php index 3f77370edf5..e7533d0055d 100644 --- a/htdocs/commande/fiche.php +++ b/htdocs/commande/fiche.php @@ -1581,18 +1581,16 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G print '
'.$langs->trans($newclassname).''.$objectsrc->getNomUrl(1).'
'.$langs->trans('TotalHT').''.price($objectsrc->total_ht).'
'.$langs->trans('TotalVAT').''.price($objectsrc->total_tva)."
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($objectsrc->total_localtax1)."
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($objectsrc->total_localtax2)."
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($objectsrc->total_localtax1)."
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($objectsrc->total_localtax2)."
'.$langs->trans('TotalTTC').''.price($objectsrc->total_ttc)."
'; @@ -2075,20 +2070,17 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G print ''; // Amount Local Taxes - if ($mysoc->country_code=='ES') + if ($mysoc->localtax1_assuj=="1") //Localtax1 RE { - if ($mysoc->localtax1_assuj=="1") //Localtax1 RE - { - print ''; - print ''; - print ''; - } - if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF - { - print ''; - print ''; - print ''; - } + print ''; + print ''; + print ''; + } + if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF + { + print ''; + print ''; + print ''; } // Total TTC diff --git a/htdocs/commissions/lib/commissions.lib.php b/htdocs/commissions/lib/commissions.lib.php index 89fba20a60c..016339a72d5 100644 --- a/htdocs/commissions/lib/commissions.lib.php +++ b/htdocs/commissions/lib/commissions.lib.php @@ -41,8 +41,10 @@ function commissions_admin_prepare_head() // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab - complete_head_from_modules($conf,$langs,'',$head,$h,'commissionsadmin'); + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf,$langs,'',$head,$h,'commissionsadmin'); + + complete_head_from_modules($conf,$langs,'',$head,$h,'commissionsadmin','remove'); return $head; } diff --git a/htdocs/compta/ajaxpayment.php b/htdocs/compta/ajaxpayment.php index e9ceafdaf52..cf042bccc49 100644 --- a/htdocs/compta/ajaxpayment.php +++ b/htdocs/compta/ajaxpayment.php @@ -18,7 +18,6 @@ /** * \file htdocs/compta/ajaxpayment.php * \brief File to return Ajax response on payment breakdown process - * \version ajaxpayment.php,v 1.0 */ //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); @@ -33,8 +32,14 @@ if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't nee //if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; -$langs->Load('compta'); +$langs->load('compta'); + + +/* + * View + */ //init var $amountPayment = $_POST['amountPayment']; @@ -42,26 +47,31 @@ $amounts = $_POST['amounts']; // from text inputs : invoice amount payment (c $remains = $_POST['remains']; // from dolibarr's object (no need to check) $currentInvId = $_POST['imgClicked']; // from DOM elements : imgId (equals invoice id) - // Getting the posted keys=>values, sanitize the ones who are from text inputs // from text inputs : total amount -$amountPayment = $amountPayment!='' ? ( is_numeric(price2num($amountPayment)) ? price2num($amountPayment) - : '' - ) - : ''; // keep void if not a valid entry -// Checkamounts +$amountPayment = $amountPayment!='' ? ( is_numeric(price2num($amountPayment)) ? price2num($amountPayment) : '' ) : ''; // keep void if not a valid entry + +// Clean checkamounts foreach ($amounts as $key => $value) { $value = price2num($value); - if (!is_numeric($value)) unset($amounts[$key]); + $amounts[$key]=$value; + if (empty($value)) unset($amounts[$key]); +} +// Clean remains +foreach ($remains as $key => $value) +{ + $value = price2num($value); + $remains[$key]=$value; + if (empty($value)) unset($remains[$key]); } // Treatment -$result = $amountPayment != '' ? $amountPayment - array_sum($amounts) : $amountPayment + array_sum($amounts); // Remaining amountPayment +$result = $amountPayment != '' ? ($amountPayment - array_sum($amounts)) : ($amountPayment + array_sum($amounts)); // Remaining amountPayment $toJsonArray = array(); $totalRemaining = price2num(array_sum($remains)); -$toJsonArray['label'] = $amountPayment == '' ? $langs->transnoentities('AmountToBeCharged') : $langs->transnoentities('RemainingAmountPayment'); -if($currentInvId) // Here to breakdown +$toJsonArray['label'] = $amountPayment == '' ? '' : $langs->transnoentities('RemainingAmountPayment'); +if ($currentInvId) // Here to breakdown { // Get the current amount (from form) and the corresponding remainToPay (from invoice) $currentAmount = $amounts['amount_'.$currentInvId]; @@ -99,9 +109,11 @@ if($currentInvId) // Here to breakdown } $toJsonArray['amount_'.$currentInvId] = price2num($currentAmount).""; // Param will exist only if an img has been clicked } -// Encode to JSON to return -$toJsonArray['makeRed'] = $totalRemaining < price2num($result) || price2num($result) < 0 ? true : false; -$toJsonArray['result'] = price2num($result); -echo json_encode($toJsonArray); // Printing the call's result +$toJsonArray['makeRed'] = ($totalRemaining < price2num($result) || price2num($result) < 0) ? true : false; +$toJsonArray['result'] = price($result); // Return value to user format +$toJsonArray['resultnum'] = price2num($result); // Return value to numeric format + +// Encode to JSON to return +echo dol_json_encode($toJsonArray); // Printing the call's result ?> \ No newline at end of file diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 67194b610d5..a66f53f7458 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -757,6 +757,7 @@ else if ($action == 'add' && $user->rights->facture->creer) $object->amount = $_POST['amount']; $object->remise_absolue = $_POST['remise_absolue']; $object->remise_percent = $_POST['remise_percent']; + $object->fetch_thirdparty(); // If creation from another object of another module (Example: origin=propal, originid=1) if ($_POST['origin'] && $_POST['originid']) @@ -2078,17 +2079,14 @@ if ($action == 'create') print ''; print ''; print '"; - if ($mysoc->pays_code=='ES') + if ($mysoc->localtax1_assuj=="1") //Localtax1 RE { - if ($mysoc->localtax1_assuj=="1") //Localtax1 RE - { - print '"; - } + print '"; + } - if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF - { - print '"; - } + if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF + { + print '"; } print '"; } @@ -2654,11 +2652,8 @@ else if ($id > 0 || ! empty($ref)) if (! empty($conf->banque->enabled)) $nbcols++; //Local taxes - if ($mysoc->pays_code=='ES') - { - if($mysoc->localtax1_assuj=="1") $nbrows++; - if($mysoc->localtax2_assuj=="1") $nbrows++; - } + if($mysoc->localtax1_assuj=="1") $nbrows++; + if($mysoc->localtax2_assuj=="1") $nbrows++; print ''; print ''; - print ''; + print ''; print ''; print "\n"; } diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 11c575f701d..25153612f56 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -28,9 +28,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; -// FIXME don't include external module class -if (! empty($conf->esaeb->enabled)) - dol_include_once('/esaeb/class/esaeb19.class.php'); /** @@ -481,7 +478,6 @@ class BonPrelevement extends CommonObject /* * End of procedure - * */ if ($error == 0) { @@ -550,17 +546,12 @@ class BonPrelevement extends CommonObject // TODO Call trigger to create a notification using notification module } else - { + { dol_syslog(get_class($this)."::set_infotrans Erreur 1", LOG_ERR); dol_syslog($this->db->error()); $error++; } - /* - * End of procedure - * - */ - if ($error == 0) { $this->db->commit(); @@ -928,7 +919,7 @@ class BonPrelevement extends CommonObject } /* - * Creation process + * Create withdrawal receipt */ if (!$error) { @@ -1051,6 +1042,44 @@ class BonPrelevement extends CommonObject } + /** + * Get object and lines from database + * + * @return int >0 if OK, <0 if KO + */ + function delete() + { + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_facture WHERE fk_prelevement_lignes IN (SELECT rowid FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = '".$this->id."')"; + $resql1=$this->db->query($sql); + if (! $resql1) dol_print_error($this->db); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = '".$this->id."'"; + $resql2=$this->db->query($sql); + if (! $resql2) dol_print_error($this->db); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_bons WHERE rowid = '".$this->id."'"; + $resql3=$this->db->query($sql); + if (! $resql3) dol_print_error($this->db); + + $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_facture_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = '".$this->id."'"; + $resql4=$this->db->query($sql); + if (! $resql4) dol_print_error($this->db); + + if ($resql1 && $resql2 && $resql3) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } + } + + /** * Returns clickable name (with picto) * @@ -1181,12 +1210,15 @@ class BonPrelevement extends CommonObject $this->file = fopen($this->filename,"w"); + // TODO Move code for es and fr into an external module file with selection into setup of prelevement module + // Build file for Spain if ($mysoc->country_code=='ES') { - // TODO replace by a hook (external modules) if (! empty($conf->esaeb->enabled)) { + dol_include_once('/esaeb/class/esaeb19.class.php'); + //Head $esaeb19 = new AEB19DocWritter; $esaeb19->configuraPresentador($this->numero_national_emetteur,$conf->global->ESAEB_SUFIX_PRESENTADOR,$this->raison_sociale,$this->emetteur_code_banque,$this->emetteur_code_guichet); @@ -1239,7 +1271,7 @@ class BonPrelevement extends CommonObject fputs($this->file, $esaeb19->generaRemesa()); } else - { + { $this->total = 0; $sql = "SELECT pl.amount"; $sql.= " FROM"; @@ -1271,10 +1303,8 @@ class BonPrelevement extends CommonObject $langs->load('withdrawals'); fputs($this->file, $langs->trans('WithdrawalFileNotCapable')); } - } - - //Build file for France + // Build file for France elseif ($mysoc->country_code=='FR') { /* @@ -1316,7 +1346,7 @@ class BonPrelevement extends CommonObject } } else - { + { $result = -2; } @@ -1326,10 +1356,9 @@ class BonPrelevement extends CommonObject $this->EnregTotal($this->total); } - - //Build file for Other Countries with unknow format + // Build file for Other Countries with unknow format else - { + { $this->total = 0; $sql = "SELECT pl.amount"; $sql.= " FROM"; @@ -1599,20 +1628,20 @@ class BonPrelevement extends CommonObject { if ($statut==0) return img_picto($langs->trans($this->labelstatut[$statut]),'statut0').' '.$langs->trans($this->labelstatut[$statut]); if ($statut==1) return img_picto($langs->trans($this->labelstatut[$statut]),'statut1').' '.$langs->trans($this->labelstatut[$statut]); - if ($statut==2) return img_picto($langs->trans($this->labelstatut[$statut]),'statut4').' '.$langs->trans($this->labelstatut[$statut]); + if ($statut==2) return img_picto($langs->trans($this->labelstatut[$statut]),'statut6').' '.$langs->trans($this->labelstatut[$statut]); } if ($mode == 2) { if ($statut==0) return img_picto($langs->trans($this->labelstatut[$statut]),'statut0'); if ($statut==1) return img_picto($langs->trans($this->labelstatut[$statut]),'statut1'); - if ($statut==2) return img_picto($langs->trans($this->labelstatut[$statut]),'statut4'); + if ($statut==2) return img_picto($langs->trans($this->labelstatut[$statut]),'statut6'); } if ($mode == 3) { if ($statut==0) return $langs->trans($this->labelstatut[$statut]).' '.img_picto($langs->trans($this->labelstatut[$statut]),'statut0'); if ($statut==1) return $langs->trans($this->labelstatut[$statut]).' '.img_picto($langs->trans($this->labelstatut[$statut]),'statut1'); - if ($statut==2) return $langs->trans($this->labelstatut[$statut]).' '.img_picto($langs->trans($this->labelstatut[$statut]),'statut4'); + if ($statut==2) return $langs->trans($this->labelstatut[$statut]).' '.img_picto($langs->trans($this->labelstatut[$statut]),'statut6'); } } diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index aed9237e028..e30e3f05d82 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -55,27 +55,21 @@ if ($prev_id) dol_fiche_head($head, 'invoices', $langs->trans("WithdrawalReceipt"), '', 'payment'); print '
'.$langs->trans('Currency'.$conf->currency).'
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
'.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
'.$langs->trans($newclassname).''.$objectsrc->getNomUrl(1).'
'.$langs->trans('TotalHT').''.price($objectsrc->total_ht).'
'.$langs->trans('TotalVAT').''.price($objectsrc->total_tva)."
'.$langs->transcountry("AmountLT1",$mysoc->pays_code).''.price($objectsrc->total_localtax1)."
'.$langs->transcountry("AmountLT1",$mysoc->pays_code).''.price($objectsrc->total_localtax1)."
'.$langs->transcountry("AmountLT2",$mysoc->pays_code).''.price($objectsrc->total_localtax2)."
'.$langs->transcountry("AmountLT2",$mysoc->pays_code).''.price($objectsrc->total_localtax2)."
'.$langs->trans('TotalTTC').''.price($objectsrc->total_ttc)."
'; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index b1896db302a..04a4af7e09d 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -280,12 +280,9 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie $(\'.fieldrequireddyn\').removeClass(\'fieldrequired\'); $(\'#fieldchqemetteur\').val(\'\'); } - }'; - // For paiement auto-completion - if (! empty($conf->global->MAIN_JS_ON_PAYMENT)) - { - print "\n".' - function elemToJson(selector) + } + + function _elemToJson(selector) { var subJson = {}; $.map(selector.serializeArray(), function(n,i) @@ -300,14 +297,14 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie var form = $("#payment_form"); json["amountPayment"] = $("#amountpayment").attr("value"); - json["amounts"] = elemToJson(form.find("input[name*=\"amount_\"]")); - json["remains"] = elemToJson(form.find("input[name*=\"remain_\"]")); + json["amounts"] = _elemToJson(form.find("input[name*=\"amount_\"]")); + json["remains"] = _elemToJson(form.find("input[name*=\"remain_\"]")); if (imgId != null) { json["imgClicked"] = imgId; } - $.post("ajaxpayment.php", json, function(data) + $.post("'.DOL_URL_ROOT.'/compta/ajaxpayment.php", json, function(data) { json = $.parseJSON(data); @@ -317,9 +314,9 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie { if (key == "result") { if (json["makeRed"]) { - $("#"+key).css("color", "red"); + $("#"+key).addClass("error"); } else { - $("#"+key).removeAttr("style"); + $("#"+key).removeClass("error"); } json[key]=json["label"]+" "+json[key]; $("#"+key).text(json[key]); @@ -331,27 +328,27 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie } }); } - function callToBreakdown(imgSelector) { - var form = $("#payment_form"), imgId; - - imgId = imgSelector.attr("id"); - callForResult(imgId); - } - - $("#payment_form").find("img").click(function() { - callToBreakdown(jQuery(this)); - }); - $("#payment_form").find("input[name*=\"amount_\"]").change(function() { callForResult(); }); + $("#payment_form").find("input[name*=\"amount_\"]").keyup(function() { + callForResult(); + }); + '; + + if (! empty($conf->global->MAIN_JS_ON_PAYMENT)) + { + print ' $("#payment_form").find("img").click(function() { + callForResult(jQuery(this).attr("id")); + }); $("#amountpayment").change(function() { callForResult(); });'; } - print '}); - '."\n"; + + print ' });'."\n"; + print ' '."\n"; } print '
'; @@ -573,7 +570,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie if ($totalrecudeposits) print '+'.price($totalrecudeposits); print '
'.price(price2num($total_ttc - $totalrecu - $totalrecucreditnote - $totalrecudeposits,'MT')).' 
'; - print ''; + + print ''; print ''; print ''; - print ''; - + // Status print ''; print ''; print ''; - + if($bon->date_trans <> 0) { $muser = new User($db); $muser->fetch($bon->user_trans); - + print ''; @@ -89,10 +83,19 @@ if ($prev_id) print dol_print_date($bon->date_credit,'day'); print ''; } - - print '
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Date").''.dol_print_date($bon->datec,'day').'
'.$langs->trans("Amount").''.price($bon->amount).'
'.$langs->trans("File").''; - - $relativepath = 'receipts/'.$bon->ref; - - print ''.$relativepath.''; - - print '
'.$langs->trans('Status').''.$bon->getLibStatut(1).'
'.$langs->trans("TransData").''; print dol_print_date($bon->date_trans,'day'); print ' '.$langs->trans("By").' '.$muser->getFullName($langs).'
'; - - print ''; + + print ''; + + print '
'; + + print '
'; + print $langs->trans("WithdrawalFile").''; + $relativepath = 'receipts/'.$bon->ref; + print ''.$relativepath.''; + print '
'; + + dol_fiche_end(); + } else { diff --git a/htdocs/compta/prelevement/fiche-rejet.php b/htdocs/compta/prelevement/fiche-rejet.php index 2ca9479f441..5ff3d5544d9 100644 --- a/htdocs/compta/prelevement/fiche-rejet.php +++ b/htdocs/compta/prelevement/fiche-rejet.php @@ -54,27 +54,21 @@ if ($prev_id) dol_fiche_head($head, 'rejects', $langs->trans("WithdrawalReceipt"), '', 'payment'); print ''; - print ''; + + print ''; print ''; print ''; - print ''; - + // Status print ''; print ''; print ''; - + if($bon->date_trans <> 0) { $muser = new User($db); $muser->fetch($bon->user_trans); - + print ''; @@ -88,10 +82,19 @@ if ($prev_id) print dol_print_date($bon->date_credit,'day'); print ''; } - - print '
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Date").''.dol_print_date($bon->datec,'day').'
'.$langs->trans("Amount").''.price($bon->amount).'
'.$langs->trans("File").''; - - $relativepath = 'receipts/'.$bon->ref; - - print ''.$relativepath.''; - - print '
'.$langs->trans('Status').''.$bon->getLibStatut(1).'
'.$langs->trans("TransData").''; print dol_print_date($bon->date_trans,'day'); print ' '.$langs->trans("By").' '.$muser->getFullName($langs).'
'; - - print ''; + + print ''; + + print '
'; + + print '
'; + print $langs->trans("WithdrawalFile").''; + $relativepath = 'receipts/'.$bon->ref; + print ''.$relativepath.''; + print '
'; + + dol_fiche_end(); + } else { @@ -103,8 +106,6 @@ $rej = new RejetPrelevement($db, $user); /* * Liste des factures - * - * */ $sql = "SELECT pl.rowid, pl.amount, pl.statut"; $sql.= " , s.rowid as socid, s.nom"; @@ -141,10 +142,10 @@ if ($resql) { $obj = $db->fetch_object($resql); - print ""; - print ' '; - print ''; + print ""; + print ''; + print img_picto('', 'statut'.$obj->statut).' '; print substr('000000'.$obj->rowid, -6); print ''; print ''.stripslashes($obj->nom)."\n"; @@ -164,7 +165,7 @@ if ($resql) print ' '; print ''.$langs->trans("Total").''; print ''.price($total)."\n"; - print ' '; + print ' '; print "\n\n"; $db->free($resql); } diff --git a/htdocs/compta/prelevement/fiche-stat.php b/htdocs/compta/prelevement/fiche-stat.php index 5497b1acf2a..eab046c7d45 100644 --- a/htdocs/compta/prelevement/fiche-stat.php +++ b/htdocs/compta/prelevement/fiche-stat.php @@ -58,24 +58,17 @@ if ($prev_id) print ''.$langs->trans("Ref").''.$bon->getNomUrl(1).''; print ''.$langs->trans("Date").''.dol_print_date($bon->datec,'day').''; print ''.$langs->trans("Amount").''.price($bon->amount).''; - print ''.$langs->trans("File").''; - - $relativepath = 'receipts/'.$bon->ref; - - print ''.$relativepath.''; - - print ''; - + // Status print ''.$langs->trans('Status').''; print ''.$bon->getLibStatut(1).''; print ''; - + if($bon->date_trans <> 0) { $muser = new User($db); $muser->fetch($bon->user_trans); - + print ''.$langs->trans("TransData").''; print dol_print_date($bon->date_trans,'day'); print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; @@ -89,10 +82,19 @@ if ($prev_id) print dol_print_date($bon->date_credit,'day'); print ''; } - + print ''; - - print ''; + + print '
'; + + print '
'; + print $langs->trans("WithdrawalFile").''; + $relativepath = 'receipts/'.$bon->ref; + print ''.$relativepath.''; + print '
'; + + dol_fiche_end(); + } else { diff --git a/htdocs/compta/prelevement/fiche.php b/htdocs/compta/prelevement/fiche.php index cd99849de9c..73450228480 100644 --- a/htdocs/compta/prelevement/fiche.php +++ b/htdocs/compta/prelevement/fiche.php @@ -42,14 +42,28 @@ if ($user->societe_id > 0) accessforbidden(); $action = GETPOST('action','alpha'); $id = GETPOST('id','int'); + /* * Actions */ +if ( $action == 'confirm_delete' ) +{ + $bon = new BonPrelevement($db,""); + $bon->fetch($id); + + $res=$bon->delete(); + if ($res > 0) + { + header("Location: index.php"); + exit; + } +} if ( $action == 'confirm_credite' && GETPOST('confirm','alpha') == 'yes') { $bon = new BonPrelevement($db,""); - $bon->id = $id; + $bon->fetch($id); + $bon->set_credite(); header("Location: fiche.php?id=".$id); @@ -63,14 +77,15 @@ if ($action == 'infotrans' && $user->rights->prelevement->bons->send) $bon = new BonPrelevement($db,""); $bon->fetch($id); + $dt = dol_mktime(12,0,0,GETPOST('remonth','int'),GETPOST('reday','int'),GETPOST('reyear','int')); + + /* if ($_FILES['userfile']['name'] && basename($_FILES['userfile']['name'],".ps") == $bon->ref) { $dir = $conf->prelevement->dir_output.'/receipts'; if (dol_move_uploaded_file($_FILES['userfile']['tmp_name'], $dir . "/" . dol_unescapefile($_FILES['userfile']['name']),1) > 0) { - $dt = dol_mktime(12,0,0,GETPOST('remonth','int'),GETPOST('reday','int'),GETPOST('reyear','int')); - $bon->set_infotrans($user, $dt, GETPOST('methode','alpha')); } @@ -81,6 +96,14 @@ if ($action == 'infotrans' && $user->rights->prelevement->bons->send) { dol_syslog("Fichier invalide",LOG_WARNING); $mesg='BadFile'; + }*/ + + $error = $bon->set_infotrans($user, $dt, GETPOST('methode','alpha')); + + if ($error) + { + header("Location: fiche.php?id=".$id."&error=$error"); + exit; } } @@ -92,15 +115,11 @@ if ($action == 'infocredit' && $user->rights->prelevement->bons->credit) $error = $bon->set_infocredit($user, $dt); - if ($error == 0) - { - header("Location: fiche.php?id=".$id); - } - else + if ($error) { header("Location: fiche.php?id=".$id."&error=$error"); + exit; } - exit; } @@ -108,132 +127,139 @@ if ($action == 'infocredit' && $user->rights->prelevement->bons->credit) * View */ -llxHeader('',$langs->trans("WithdrawalReceipt")); - +$bon = new BonPrelevement($db,""); $form = new Form($db); -if ($id) +llxHeader('',$langs->trans("WithdrawalReceipt")); + + +if ($id > 0) { - $bon = new BonPrelevement($db,""); + $bon->fetch($id); - if ($bon->fetch($id) == 0) + $head = prelevement_prepare_head($bon); + dol_fiche_head($head, 'prelevement', $langs->trans("WithdrawalReceipt"), '', 'payment'); + + if (GETPOST('error','alpha')!='') { - $head = prelevement_prepare_head($bon); - dol_fiche_head($head, 'prelevement', $langs->trans("WithdrawalReceipt"), '', 'payment'); + print '
'.$bon->ReadError(GETPOST('error','alpha')).'
'; + } - if (GETPOST('error','alpha')!='') - { - print '
'.$bon->ReadError(GETPOST('error','alpha')).'
'; - } + /*if ($action == 'credite') + { + $ret=$form->form_confirm("fiche.php?id=".$bon->id,$langs->trans("ClassCredited"),$langs->trans("ClassCreditedConfirm"),"confirm_credite",'',1,1); + if ($ret == 'html') print '
'; + }*/ - if ($action == 'credite') - { - $ret=$form->form_confirm("fiche.php?id=".$bon->id,$langs->trans("ClassCredited"),$langs->trans("ClassCreditedConfirm"),"confirm_credite",'',1,1); - if ($ret == 'html') print '
'; - } + print ''; - print '
'; + print ''; + print ''; + print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; - $relativepath = 'receipts/'.$bon->ref; - - print ''.$relativepath.''; + if($bon->date_trans <> 0) + { + $muser = new User($db); + $muser->fetch($bon->user_trans); + print ''; + print ''; - - // Status - print ''; - print ''; - print ''; - - if($bon->date_trans <> 0) - { - $muser = new User($db); - $muser->fetch($bon->user_trans); - - print ''; - print ''; - } - if($bon->date_credit <> 0) - { - print ''; - } - - print '
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Date").''.dol_print_date($bon->datec,'day').'
'.$langs->trans("Amount").''.price($bon->amount).'
'.$langs->trans("Ref").''.$bon->getNomUrl(1).'
'.$langs->trans("Date").''.dol_print_date($bon->datec,'day').'
'.$langs->trans("Amount").''.price($bon->amount).'
'.$langs->trans("File").''; + // Status + print '
'.$langs->trans('Status').''.$bon->getLibStatut(1).'
'.$langs->trans("TransData").''; + print dol_print_date($bon->date_trans,'day'); + print ' '.$langs->trans("By").' '.$muser->getFullName($langs).'
'.$langs->trans("TransMetod").''; + print $bon->methodes_trans[$bon->method_trans]; print '
'.$langs->trans('Status').''.$bon->getLibStatut(1).'
'.$langs->trans("TransData").''; - print dol_print_date($bon->date_trans,'day'); - print ' '.$langs->trans("By").' '.$muser->getFullName($langs).'
'.$langs->trans("TransMetod").''; - print $bon->methodes_trans[$bon->method_trans]; - print '
'.$langs->trans('CreditDate').''; - print dol_print_date($bon->date_credit,'day'); - print '
'; - dol_fiche_end(); - - if($bon->date_trans == 0 && $user->rights->prelevement->bons->send) - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print '
'.$langs->trans("NotifyTransmision").'
'.$langs->trans("TransData").''; - print $form->select_date('','','','','',"userfile"); - print '
'.$langs->trans("TransMetod").''; - print $form->selectarray("methode",$bon->methodes_trans); - print '
'.$langs->trans("File").''; - print ''; - print '
'; - print '

'; - print '
'; - print ''; - } - - if($bon->date_trans <> 0 && $bon->date_credit == 0 && $user->rights->prelevement->bons->credit) - { - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print '
'.$langs->trans("NotifyCredit").'
'.$langs->trans('CreditDate').''; - print $form->select_date('','','','','',"infocredit"); - print '

'; - print '
'; - print ''; - } } - else + if($bon->date_credit <> 0) { - dol_print_error($db); + print ''.$langs->trans('CreditDate').''; + print dol_print_date($bon->date_credit,'day'); + print ''; + } + + print ''; + + print '
'; + + print '
'; + print $langs->trans("WithdrawalFile").''; + $relativepath = 'receipts/'.$bon->ref; + print ''.$relativepath.''; + print '
'; + + dol_fiche_end(); + + + + + if (empty($bon->date_trans) && $user->rights->prelevement->bons->send && $action=='settransmitted') + { + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; +/* print '';*/ + print '
'.$langs->trans("NotifyTransmision").'
'.$langs->trans("TransData").''; + print $form->select_date('','','','','',"userfile",1,1); + print '
'.$langs->trans("TransMetod").''; + print $form->selectarray("methode",$bon->methodes_trans); + print '
'.$langs->trans("File").''; + print ''; + print '
'; + print '

'; + print '
'; + print ''; + } + + if (! empty($bon->date_trans) && $bon->date_credit == 0 && $user->rights->prelevement->bons->credit && $action=='setcredited') + { + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'.$langs->trans("NotifyCredit").'
'.$langs->trans('CreditDate').''; + print $form->select_date('','','','','',"infocredit",1,1); + print '
'; + print '
'.$langs->trans("ThisWillAlsoAddPaymentOnInvoice"); + print '
'; + print ''; + } + + + // Actions + if ($action != 'settransmitted' && $action != 'setcredited') + { + print "\n
\n"; + + if (empty($bon->date_trans) && $user->rights->prelevement->bons->send) + { + print "id."\">".$langs->trans("SetToStatusSent").""; + } + + if (! empty($bon->date_trans) && $bon->date_credit == 0) + { + print "id."\">".$langs->trans("ClassCredited").""; + } + + print "id."\">".$langs->trans("Delete").""; + + print "
"; } } -/* ************************************************************************** */ -/* */ -/* Barre d'action */ -/* */ -/* ************************************************************************** */ - -/* -print "\n\n
\n"; - -if ($bon->statut == 0) -{ - print "id\">".$langs->trans("ClassCredited").""; -} -*/ -print "
"; - -$db->close(); llxFooter(); + +$db->close(); ?> diff --git a/htdocs/compta/prelevement/index.php b/htdocs/compta/prelevement/index.php index 8dba0b37cae..2f2dd82fcb7 100644 --- a/htdocs/compta/prelevement/index.php +++ b/htdocs/compta/prelevement/index.php @@ -1,6 +1,6 @@ - * Copyright (C) 2005-2011 Laurent Destailleur + * Copyright (C) 2005-2012 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2011 Juanjo Menent * @@ -93,10 +93,10 @@ print ''; * Withdraw receipts */ $limit=5; -$sql = "SELECT p.rowid, p.ref, p.amount, p.datec"; -$sql .= " ,p.statut "; -$sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; -$sql .= " ORDER BY datec DESC LIMIT ".$limit; +$sql = "SELECT p.rowid, p.ref, p.amount, p.datec, p.statut"; +$sql.= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; +$sql.= " ORDER BY datec DESC"; +$sql.= $db->plimit($limit); $result = $db->query($sql); if ($result) @@ -110,6 +110,7 @@ if ($result) print ''.$langs->trans("LastWithdrawalReceipt",$limit).''; print ''.$langs->trans("Date").''; print ''.$langs->trans("Amount").''; + print ''.$langs->trans("Status").''; print ''; while ($i < min($num,$limit)) @@ -117,15 +118,17 @@ if ($result) $obj = $db->fetch_object($result); $var=!$var; - print ""; - - print ' '; - - print ''.$obj->ref."\n"; + print ""; + print ""; + $bprev->id=$obj->rowid; + $bprev->ref=$obj->ref; + $bprev->statut=$obj->statut; + print $bprev->getNomUrl(1); + print "\n"; print ''.dol_print_date($db->jdate($obj->datec),"dayhour")."\n"; - print ''.price($obj->amount)."\n"; + print ''.$bprev->getLibStatut(3)."\n"; print "\n"; $i++; diff --git a/htdocs/compta/prelevement/lignes.php b/htdocs/compta/prelevement/lignes.php index 4e9636af6a4..6276e745d72 100644 --- a/htdocs/compta/prelevement/lignes.php +++ b/htdocs/compta/prelevement/lignes.php @@ -65,13 +65,6 @@ if ($prev_id) print ''.$langs->trans("Ref").''.$bon->getNomUrl(1).''; print ''.$langs->trans("Date").''.dol_print_date($bon->datec,'day').''; print ''.$langs->trans("Amount").''.price($bon->amount).''; - print ''.$langs->trans("File").''; - - $relativepath = 'receipts/'.$bon->ref; - - print ''.$relativepath.''; - - print ''; // Status print ''.$langs->trans('Status').''; @@ -99,7 +92,16 @@ if ($prev_id) print ''; - print ''; + print '
'; + + print '
'; + print $langs->trans("WithdrawalFile").''; + $relativepath = 'receipts/'.$bon->ref; + print ''.$relativepath.''; + print '
'; + + dol_fiche_end(); + } else { diff --git a/htdocs/compta/sociales/charges.php b/htdocs/compta/sociales/charges.php index 7e380204640..685a0eb05ca 100644 --- a/htdocs/compta/sociales/charges.php +++ b/htdocs/compta/sociales/charges.php @@ -214,11 +214,11 @@ if ($action == 'create') print ' '; // Label - print ''; + print ''; // Type print ''; - $formsocialcontrib->select_type_socialcontrib(isset($_POST["actioncode"])?$_POST["actioncode"]:'','actioncode',1); + $formsocialcontrib->select_type_socialcontrib(GETPOST("actioncode")?GETPOST("actioncode"):'','actioncode',1); print ''; // Date end period diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 0f9758cd427..4fb1e57c9e6 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -29,8 +29,7 @@ require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php'; /** - * \class Contact - * \brief Classe permettant la gestion des contacts + * Class to manage contact/addresses */ class Contact extends CommonObject { @@ -128,6 +127,7 @@ class Contact extends CommonObject $sql.= ", priv"; $sql.= ", canvas"; $sql.= ", entity"; + $sql.= ", import_key"; $sql.= ") VALUES ("; $sql.= "'".$this->db->idate($now)."',"; if ($this->socid > 0) $sql.= " ".$this->socid.","; @@ -136,8 +136,9 @@ class Contact extends CommonObject $sql.= "'".$this->db->escape($this->firstname)."',"; $sql.= " ".($user->id > 0 ? "'".$user->id."'":"null").","; $sql.= " ".$this->priv.","; - $sql.= " ".($this->canvas?"'".$this->canvas."'":"null").","; - $sql.= " ".$conf->entity; + $sql.= " ".(! empty($this->canvas)?"'".$this->canvas."'":"null").","; + $sql.= " ".$conf->entity.","; + $sql.= " ".(! empty($this->import_key)?"'".$this->import_key."'":"null"); $sql.= ")"; dol_syslog(get_class($this)."::create sql=".$sql); diff --git a/htdocs/contact/fiche.php b/htdocs/contact/fiche.php index 3027eb22026..2e28c7e2a5c 100644 --- a/htdocs/contact/fiche.php +++ b/htdocs/contact/fiche.php @@ -361,7 +361,7 @@ else $object->state_id = $_POST["state_id"]; // We set country_id, country_code and label for the selected country - $object->country_id=$_POST["country_id"]?$_POST["country_id"]:$mysoc->country_id; + $object->country_id=$_POST["country_id"]?$_POST["country_id"]:(empty($objsoc->country_id)?$mysoc->country_id:$objsoc->country_id); if ($object->country_id) { $tmparray=getCountry($object->country_id,'all'); @@ -434,7 +434,7 @@ else $colspan=3; if ($conf->use_javascript_ajax && $socid > 0) $colspan=2; - + // Address if (($objsoc->typent_code == 'TE_PRIVATE' || ! empty($conf->global->CONTACT_USE_COMPANY_ADDRESS)) && dol_strlen(trim($object->address)) == 0) $object->address = $objsoc->address; // Predefined with third party print ''.$langs->trans("Address"); @@ -442,9 +442,9 @@ else if ($conf->use_javascript_ajax && $socid > 0) { - $rowspan=3; + $rowspan=3; if (empty($conf->global->SOCIETE_DISABLE_STATE)) $rowspan++; - + print ''; print ''.$langs->trans('CopyAddressFromSoc').''; print ''; @@ -460,7 +460,6 @@ else print ''; // Country - if (dol_strlen(trim($object->fk_pays)) == 0) $object->fk_pays = $objsoc->country_id; // Predefined with third party print ''.$langs->trans("Country").''; print $form->select_country((isset($_POST["country_id"])?$_POST["country_id"]:$object->country_id),'country_id'); if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0cb132d23c6..eb1c4c9e435 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -221,14 +221,16 @@ abstract class CommonObject * @param int $rowid Id of line contact-element * @param int $statut New status of link * @param int $type_contact_id Id of contact type (not modified if 0) + * @param int $fk_socpeople Id of soc_people to update (not modified if 0) * @return int <0 if KO, >= 0 if OK */ - function update_contact($rowid, $statut, $type_contact_id=0) + function update_contact($rowid, $statut, $type_contact_id=0, $fk_socpeople=0) { // Insertion dans la base $sql = "UPDATE ".MAIN_DB_PREFIX."element_contact set"; $sql.= " statut = ".$statut; if ($type_contact_id) $sql.= ", fk_c_type_contact = '".$type_contact_id ."'"; + if ($fk_socpeople) $sql.= ", fk_socpeople = '".$fk_socpeople ."'"; $sql.= " where rowid = ".$rowid; $resql=$this->db->query($sql); if ($resql) @@ -1516,27 +1518,49 @@ abstract class CommonObject $this->total_localtax2 += $obj->total_localtax2; $this->total_ttc += $obj->total_ttc; - // Define vatrates with totals for each line and for all lines - // TODO $vatrates and $vatrates_alllines not used ? - if (! empty($this->vatrate)) + // Check if global invoice tax for this vat rate + if (! empty($obj->vatrate)) { - $vatrates[$this->vatrate][]=array( - 'total_ht' =>$obj->total_ht, - 'total_tva' =>$obj->total_tva, - 'total_ttc' =>$obj->total_ttc, - 'total_localtax1'=>$obj->total_localtax1, - 'total_localtax2'=>$obj->total_localtax2 - ); - if (! isset($vatrates_alllines[$this->vatrate]['total_ht'])) $vatrates_alllines[$this->vatrate]['total_ht']=0; - if (! isset($vatrates_alllines[$this->vatrate]['total_tva'])) $vatrates_alllines[$this->vatrate]['total_tva']=0; - if (! isset($vatrates_alllines[$this->vatrate]['total_localtax1'])) $vatrates_alllines[$this->vatrate]['total_localtax1']=0; - if (! isset($vatrates_alllines[$this->vatrate]['total_localtax2'])) $vatrates_alllines[$this->vatrate]['total_localtax2']=0; - if (! isset($vatrates_alllines[$this->vatrate]['total_ttc'])) $vatrates_alllines[$this->vatrate]['total_ttc']=0; - $vatrates_alllines[$this->vatrate]['total_ht'] +=$obj->total_ht; - $vatrates_alllines[$this->vatrate]['total_tva'] +=$obj->total_tva; - $vatrates_alllines[$this->vatrate]['total_localtax1']+=$obj->total_localtax1; - $vatrates_alllines[$this->vatrate]['total_localtax2']+=$obj->total_localtax2; - $vatrates_alllines[$this->vatrate]['total_ttc'] +=$obj->total_ttc; + if ($this->total_localtax1 == 0) + { + // Search local taxes + $sql = "SELECT t.localtax1, t.localtax1_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_pays as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$this->client->country_code."'"; + $sql .= " AND t.taux = ".$obj->vatrate." AND t.active = 1"; + + dol_syslog("get_localtax sql=".$sql); + $resqlt=$this->db->query($sql); + if ($resqlt) + { + $objt = $this->db->fetch_object($resqlt); + if ($objt->localtax1_type == '7') + { + $this->total_localtax1 += $objt->localtax1; + $this->total_ttc += $objt->localtax1; + } + } + } + if ($this->total_localtax2 == 0) + { + // Search local taxes + $sql = "SELECT t.localtax2, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_pays as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$this->client->country_code."'"; + $sql .= " AND t.taux = ".$obj->vatrate." AND t.active = 1"; + + dol_syslog("get_localtax sql=".$sql); + $resqlt=$this->db->query($sql); + if ($resqlt) + { + $objt = $this->db->fetch_object($resqlt); + if ($objt->localtax2_type == '7') + { + $this->total_localtax2 += $objt->localtax2; + $this->total_ttc += $objt->localtax2; + } + } + } } $i++; @@ -1544,21 +1568,6 @@ abstract class CommonObject $this->db->free($resql); - // TODO - if ($roundingadjust) - { - // For each vatrate, calculate if two method of calculation differs - - - // If it differs - if (1==2) - { - // Adjust a line and update it - - - } - } - // Now update global field total_ht, total_ttc and tva $fieldht='total_ht'; $fieldtva='tva'; diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index ae35425bf09..5c8954d6664 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -60,6 +60,7 @@ class Conf public $societe_modules = array(); var $logbuffer = array(); + var $loghandlers = array(); //! To store properties of multi-company public $multicompany; @@ -371,7 +372,7 @@ class Conf $this->css = "/theme/".$this->theme."/style.css.php"; // conf->email_from = email pour envoi par dolibarr des mails automatiques - $this->email_from = "dolibarr-robot@domain.com"; + $this->email_from = "robot@domain.com"; if (! empty($this->global->MAIN_MAIL_EMAIL_FROM)) $this->email_from = $this->global->MAIN_MAIL_EMAIL_FROM; // conf->notification->email_from = email pour envoi par Dolibarr des notifications @@ -456,6 +457,27 @@ class Conf { if (is_object($mc)) $mc->setValues($this); } + + // We init log handlers + if (defined('SYSLOG_HANDLERS')) $handlers = json_decode(constant('SYSLOG_HANDLERS')); + else $handlers = array(); + foreach ($handlers as $handler) + { + $file = DOL_DOCUMENT_ROOT.'/core/modules/syslog/'.$handler.'.php'; + if (!file_exists($file)) + { + throw new Exception('Missing log handler file '.$handler.'.php'); + } + + require_once $file; + $loghandlerinstance = new $handler(); + if (!$loghandlerinstance instanceof LogHandlerInterface) + { + throw new Exception('Log handler does not extend LogHandlerInterface'); + } + + $this->loghandlers[]=$loghandlerinstance; + } } } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 381a6f1b34d..a5668597db7 100755 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -42,7 +42,7 @@ class ExtraFields var $attribute_unique; // Array to store if attribute is required or not var $attribute_required; - + var $error; var $errno; @@ -439,6 +439,10 @@ class ExtraFields $array_name_label=array(); + // For avoid conflicts with external modules + if (! empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) + return $array_name_label; + $sql = "SELECT rowid,name,label,type,size,elementtype,fieldunique,fieldrequired"; $sql.= " FROM ".MAIN_DB_PREFIX."extrafields"; $sql.= " WHERE entity = ".$conf->entity; diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 136d034a0ec..671334982e9 100755 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -115,7 +115,8 @@ class HookManager * @param Object &$object Object to use hooks on * @param string &$action Action code on calling page ('create', 'edit', 'view', 'add', 'update', 'delete'...) * @return mixed For doActions,formObjectOptions: Return 0 if we want to keep standard actions, >0 if if want to stop standard actions, <0 means KO. - * For printSearchForm,printLeftBlock,printTopRightMenu,...: Return HTML string. + * For printSearchForm,printLeftBlock,printTopRightMenu,formAddObjectLine,...: Return HTML string. TODO Must always return an int and things to print into ->resprints. + * Can also return some values into an array ->results. * $this->error or this->errors are also defined by class called by this function if error. */ function executeHooks($method, $parameters=false, &$object='', &$action='') @@ -127,45 +128,58 @@ class HookManager // Loop on each hook to qualify modules that declared context $modulealreadyexecuted=array(); - $resaction=0; $resprint=''; + $resaction=0; $error=0; + $this->resPrint=''; $this->resArray=array(); foreach($this->hooks as $modules) // this->hooks is an array with context as key and value is an array of modules that handle this context { if (! empty($modules)) { foreach($modules as $module => $actionclassinstance) { - // test to avoid to run twice a hook, when a module implements several active contexts + // jump to next class if method does not exists + if (! method_exists($actionclassinstance,$method)) continue; + // test to avoid to run twice a hook, when a module implements several active contexts if (in_array($module,$modulealreadyexecuted)) continue; $modulealreadyexecuted[$module]=$module; // Hooks that return int - if (($method == 'doActions' || $method == 'formObjectOptions') && method_exists($actionclassinstance,$method)) + if (($method == 'doActions' || $method == 'formObjectOptions')) { - $resaction+=$actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example) - if ($resaction < 0 || ! empty($actionclassinstance->error) || (! empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) - { - $this->error=$actionclassinstance->error; $this->errors=array_merge($this->errors, (array) $actionclassinstance->errors); - if ($method == 'doActions') - { - if ($action=='add') $action='create'; // TODO this change must be inside the doActions - if ($action=='update') $action='edit'; // TODO this change must be inside the doActions - } - } + $resaction+=$actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example) + if ($resaction < 0 || ! empty($actionclassinstance->error) || (! empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) + { + $error++; + $this->error=$actionclassinstance->error; $this->errors=array_merge($this->errors, (array) $actionclassinstance->errors); + // TODO remove this. Change must be inside the method if required + if ($method == 'doActions') + { + if ($action=='add') $action='create'; + if ($action=='update') $action='edit'; + } + } } - // Generic hooks that return a string (printSearchForm, printLeftBlock, formBuilddocOptions, ...) - else if (method_exists($actionclassinstance,$method)) + // Generic hooks that return a string (printSearchForm, printLeftBlock, printTopRightMenu, formAddObjectLine, formBuilddocOptions, ...) + else { - if (is_array($parameters) && ! empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) continue; + // TODO. this should be done into the method by returning nothing + if (is_array($parameters) && ! empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) continue; + $result = $actionclassinstance->$method($parameters, $object, $action, $this); + + if (is_array($actionclassinstance->results)) $this->resArray =array_merge($this->resArray, $actionclassinstance->results); + if (! empty($actionclassinstance->resprints)) $this->resPrint.=$actionclassinstance->resprints; + + // TODO. remove this. array result must be set into $actionclassinstance->results if (is_array($result)) $this->resArray = array_merge($this->resArray, $result); - else $resprint.=$result; + // TODO. remove this. result must not be a string. we must use $actionclassinstance->resprint to return a string + if (! is_array($result) && ! is_numeric($result)) $this->resPrint.=$result; } } } } - if ($method == 'doActions' || $method == 'formObjectOptions') return $resaction; - return $resprint; + if ($method != 'doActions' && $method != 'formObjectOptions') return $this->resPrint; // TODO remove this. When there is something to print, ->resPrint is filled. + return ($error?-1:$resaction); } } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index dc25d81344d..f031750cb5b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -165,6 +165,10 @@ class Form { $ret.=$this->form_date($_SERVER['PHP_SELF'].'?id='.$object->id,$value,$htmlname); } + else if ($typeofdata == 'datehourpicker') + { + $ret.=$this->form_date($_SERVER['PHP_SELF'].'?id='.$object->id,$value,$htmlname,1,1); + } else if (preg_match('/^select;/',$typeofdata)) { $arraydata=explode(',',preg_replace('/^select;/','',$typeofdata)); @@ -183,7 +187,7 @@ class Form $ret.=$doleditor->Create(1); } $ret.=''; - if ($typeofdata != 'day' && $typeofdata != 'datepicker') $ret.=''; + if ($typeofdata != 'day' && $typeofdata != 'datepicker' && $typeofdata != 'datehourpicker') $ret.=''; $ret.=''."\n"; $ret.=''."\n"; } @@ -192,6 +196,7 @@ class Form if ($typeofdata == 'email') $ret.=dol_print_email($value,0,0,0,0,1); elseif (preg_match('/^text/',$typeofdata) || preg_match('/^note/',$typeofdata)) $ret.=dol_htmlentitiesbr($value); elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') $ret.=dol_print_date($value,'day'); + elseif ($typeofdata == 'datehourpicker') $ret.=dol_print_date($value,'dayhour'); else if (preg_match('/^select;/',$typeofdata)) { $arraydata=explode(',',preg_replace('/^select;/','',$typeofdata)); @@ -272,7 +277,7 @@ class Form if (! empty($tmp[1])) $inputOption=$tmp[1]; if (! empty($tmp[2])) $savemethod=$tmp[2]; } - else if (preg_match('/^datepicker/',$inputType)) + else if ((preg_match('/^datepicker/',$inputType)) || (preg_match('/^datehourpicker/',$inputType))) { $tmp=explode(':',$inputType); $inputType=$tmp[0]; @@ -1447,7 +1452,8 @@ class Form $num = $this->db->num_rows($result); - $outselect.=''; // remove select to have id same with combo and ajax + $outselect.=''; @@ -2601,9 +2618,11 @@ class Form * @param string $page Page * @param string $selected Date preselected * @param string $htmlname Name of input html field + * @param int $displayhour Display hour selector + * @param int $displaymin Display minutes selector * @return void */ - function form_date($page, $selected, $htmlname) + function form_date($page, $selected, $htmlname,$displayhour=0,$displaymin=0) { global $langs; @@ -2614,7 +2633,7 @@ class Form print ''; print ''; print ''; print ''; print '
'; - print $this->select_date($selected,$htmlname,0,0,1,'form'.$htmlname); + print $this->select_date($selected,$htmlname,$displayhour,$displaymin,1,'form'.$htmlname); print '
'; diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index 09213bdd0b9..5916159bd6e 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -144,10 +144,10 @@ class FormActions require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; - $actioncomm = new ActionComm($this->db); - $actioncomm->getActions($socid, $object->id, $typeelement); + $listofactions=ActionComm::getActions($this->db, $socid, $object->id, $typeelement); + if (is_numeric($listofactions) && $listofactions < 0) dol_print_error($this->db,'FailedToGetActions'); - $num = count($actioncomm->actions); + $num = count($listofactions); if ($num) { if ($typeelement == 'invoice') $title=$langs->trans('ActionsOnBill'); @@ -164,17 +164,29 @@ class FormActions $total = 0; $var=true; print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; print "\n"; - foreach($actioncomm->actions as $action) + $userstatic = new User($this->db); + + foreach($listofactions as $action) { + $savlabel=$action->label; + $action->label=$action->ref; + $ref=$action->getNomUrl(1); + $action->label=$savlabel; + $label=$action->getNomUrl(0,38); + $var=!$var; print ''; - print ''; + print ''; + print ''; print ''; - print ''; - $userstatic = new User($this->db); $userstatic->id = $action->author->id; $userstatic->firstname = $action->author->firstname; $userstatic->lastname = $action->author->lastname; @@ -194,9 +206,10 @@ class FormActions * @param string $selected Type pre-selectionne * @param string $htmlname Nom champ formulaire * @param string $excludetype Type to exclude + * @param string $onlyautoornot Group list by auto events or not * @return void */ - function select_type_actions($selected='',$htmlname='actioncode',$excludetype='') + function select_type_actions($selected='',$htmlname='actioncode',$excludetype='',$onlyautoornot=0) { global $langs,$user; @@ -205,12 +218,13 @@ class FormActions $caction=new CActionComm($this->db); $form=new Form($this->db); - $arraylist=$caction->liste_array(1, 'code', $excludetype); - array_unshift($arraylist,' '); // Add empty line at start - //asort($arraylist); + // Suggest a list with manual event or all auto events + $arraylist=$caction->liste_array(1, 'code', $excludetype, $onlyautoornot); + array_unshift($arraylist,' '); // Add empty line at start + //asort($arraylist); print $form->selectarray($htmlname, $arraylist, $selected); - if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); + if ($user->admin && empty($onlyautoornot)) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); } } diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index d454cc3d005..ae43f9f34e7 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -143,6 +143,9 @@ class Translate * If data for file already loaded, do nothing. * All data in translation array are stored in UTF-8 format. * tab_loaded is completed with $domain key. + * Warning: MAIN_USE_CUSTOM_TRANSLATION is an old deprecated feature. Do not use it. It will revert + * rule "we keep first entry found with we keep last entry found" so it is probably not what you want to do. + * * Value for hash are: 1:Loaded from disk, 2:Not found, 3:Loaded from cache * * @param string $domain File name to load (.lang file). Must be "file" or "file@module" for module language files: @@ -198,13 +201,14 @@ class Translate // Directory of translation files $file_lang = $searchdir.($modulename?'/'.$modulename:'')."/langs/".$langofdir."/".$newdomain.".lang"; $file_lang_osencoded=dol_osencode($file_lang); + $filelangexists=is_file($file_lang_osencoded); //dol_syslog('Translate::Load Try to read for alt='.$alt.' langofdir='.$langofdir.' file_lang='.$file_lang." => filelangexists=".$filelangexists); if ($filelangexists) { - // TODO Move cache read out of loop on dirs + // TODO Move cache read out of loop on dirs or at least filelangexists $found=false; // Enable caching of lang file in memory (not by default) diff --git a/htdocs/core/db/mysql.class.php b/htdocs/core/db/mysql.class.php index 9fd6058bedd..c9040982fa5 100644 --- a/htdocs/core/db/mysql.class.php +++ b/htdocs/core/db/mysql.class.php @@ -26,8 +26,7 @@ /** - * \class DoliDBMysql - * \brief Class to manage Dolibarr database access for a Mysql database + * Class to manage Dolibarr database access for a Mysql database */ class DoliDBMysql { @@ -291,12 +290,14 @@ class DoliDBMysql { $this->transaction_opened++; dol_syslog("BEGIN Transaction",LOG_DEBUG); + dol_syslog('',0,1); } return $ret; } else { $this->transaction_opened++; + dol_syslog('',0,1); return 1; } } @@ -309,6 +310,7 @@ class DoliDBMysql */ function commit($log='') { + dol_syslog('',0,-1); if ($this->transaction_opened<=1) { $ret=$this->query("COMMIT"); @@ -334,6 +336,7 @@ class DoliDBMysql */ function rollback($log='') { + dol_syslog('',0,-1); if ($this->transaction_opened<=1) { $ret=$this->query("ROLLBACK"); diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index c0a99589388..c647c12e607 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -26,8 +26,7 @@ /** - * \class DoliDBMysqli - * \brief Class to manage Dolibarr database access for a Mysql database + * Class to manage Dolibarr database access for a Mysql database */ class DoliDBMysqli { @@ -286,12 +285,14 @@ class DoliDBMysqli { $this->transaction_opened++; dol_syslog("BEGIN Transaction",LOG_DEBUG); + dol_syslog('',0,1); } return $ret; } else { $this->transaction_opened++; + dol_syslog('',0,1); return 1; } } @@ -304,7 +305,8 @@ class DoliDBMysqli */ function commit($log='') { - if ($this->transaction_opened<=1) + dol_syslog('',0,-1); + if ($this->transaction_opened<=1) { $ret=$this->query("COMMIT"); if ($ret) @@ -329,7 +331,8 @@ class DoliDBMysqli */ function rollback($log='') { - if ($this->transaction_opened<=1) + dol_syslog('',0,-1); + if ($this->transaction_opened<=1) { $ret=$this->query("ROLLBACK"); $this->transaction_opened=0; diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index ac44643192b..475bb42c6db 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -474,12 +474,14 @@ class DoliDBPgsql { $this->transaction_opened++; dol_syslog("BEGIN Transaction",LOG_DEBUG); + dol_syslog('',0,1); } return $ret; } else { $this->transaction_opened++; + dol_syslog('',0,1); return 1; } } @@ -492,6 +494,7 @@ class DoliDBPgsql */ function commit($log='') { + dol_syslog('',0,-1); if ($this->transaction_opened<=1) { $ret=$this->query("COMMIT;"); @@ -516,6 +519,7 @@ class DoliDBPgsql */ function rollback() { + dol_syslog('',0,-1); if ($this->transaction_opened<=1) { $ret=$this->query("ROLLBACK;"); diff --git a/htdocs/core/db/sqlite.class.php b/htdocs/core/db/sqlite.class.php index 180f11ef5ba..34955d6d5df 100644 --- a/htdocs/core/db/sqlite.class.php +++ b/htdocs/core/db/sqlite.class.php @@ -416,12 +416,14 @@ class DoliDBSqlite { $this->transaction_opened++; dol_syslog("BEGIN Transaction",LOG_DEBUG); + dol_syslog('',0,1); } return $ret; } else { $this->transaction_opened++; + dol_syslog('',0,1); return 1; } } @@ -434,7 +436,8 @@ class DoliDBSqlite */ function commit($log='') { - if ($this->transaction_opened<=1) + dol_syslog('',0,-1); + if ($this->transaction_opened<=1) { $ret=$this->query("COMMIT"); if ($ret) @@ -445,8 +448,8 @@ class DoliDBSqlite return $ret; } else - { - $this->transaction_opened--; + { + $this->transaction_opened--; return 1; } } @@ -459,7 +462,8 @@ class DoliDBSqlite */ function rollback($log='') { - if ($this->transaction_opened<=1) + dol_syslog('',0,-1); + if ($this->transaction_opened<=1) { $ret=$this->query("ROLLBACK"); $this->transaction_opened=0; diff --git a/htdocs/core/js/lib_head.js b/htdocs/core/js/lib_head.js index d9088ba83ba..d03baa648c4 100644 --- a/htdocs/core/js/lib_head.js +++ b/htdocs/core/js/lib_head.js @@ -729,6 +729,7 @@ function confirmConstantAction(action, url, code, input, box, entity, yesButton, modal: true, buttons: [ { + id : 'yesButton_' + code, text : yesButton, click : function() { if (action == "set") { @@ -748,6 +749,7 @@ function confirmConstantAction(action, url, code, input, box, entity, yesButton, } }, { + id : 'noButton_' + code, text : noButton, click : function() { $(this).dialog("close"); @@ -755,6 +757,10 @@ function confirmConstantAction(action, url, code, input, box, entity, yesButton, } ] }); + // For information dialog box only, hide the noButton + if (boxConfirm.info) { + $("#noButton_" + code).button().hide(); + } } /* diff --git a/htdocs/core/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index dba22075612..1c92cdf504e 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -93,7 +93,10 @@ function print_actions_filter($form,$canedit,$status,$year,$month,$day,$showbirt print ''; } @@ -403,6 +406,14 @@ function actions_prepare_head($object) $head[$h][2] = 'card'; $h++; + if (! empty($conf->global->AGENDA_USE_SEVERAL_CONTACTS)) + { + $head[$h][0] = DOL_URL_ROOT.'/comm/action/contact.php?id='.$object->id; + $head[$h][1] = $langs->trans("Contacts"); + $head[$h][2] = 'contact'; + $h++; + } + $head[$h][0] = DOL_URL_ROOT.'/comm/action/document.php?id='.$object->id; $head[$h][1] = $langs->trans('Documents'); $head[$h][2] = 'documents'; @@ -440,9 +451,11 @@ function calendars_prepare_head($param) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'agenda'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'agenda','remove'); + return $head; } diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 82a6dadcfb8..ba9511d8d66 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -48,8 +48,14 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt var options = '.json_encode($ajaxoptions).'; // Remove product id before select another product + // use keyup instead change to avoid loosing the product id + $("input#search_'.$htmlname.'").keydown(function() { + //console.log(\'purge_id_after_keydown\'); + $("#'.$htmlname.'").val(""); + }); $("input#search_'.$htmlname.'").change(function() { - $("#'.$htmlname.'").val("").trigger("change"); + //console.log(\'keyup\'); + $("#'.$htmlname.'").trigger("change"); }); // Check when keyup $("input#search_'.$htmlname.'").onDelayedKeyup({ handler: function() { @@ -115,6 +121,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt dataType: "json", minLength: '.$minLength.', select: function( event, ui ) { + //console.log(\'set value of id with \'+ui.item.id); $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Disable an element if (options.option_disabled) { @@ -163,7 +170,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLengt }).data( "autocomplete" )._renderItem = function( ul, item ) { return $( "
  • " ) .data( "item.autocomplete", item ) - .append( \'\' + item.label + "" ) + .append( \'\' + item.label + "" ) .appendTo(ul); }; });'; @@ -368,6 +375,11 @@ function ajax_constantonoff($code, $input=array(), $entity=false) // Set constant $("#set_" + code).click(function() { if (input.alert && input.alert.set) { + // Posibility to force label of buttons + if (input.alert.set.yesButton) + yesButton = input.alert.set.yesButton; + if (input.alert.set.noButton) + noButton = input.alert.set.noButton; confirmConstantAction("set", url, code, input, input.alert.set, entity, yesButton, noButton); } else { setConstant(url, code, input, entity); @@ -377,6 +389,11 @@ function ajax_constantonoff($code, $input=array(), $entity=false) // Del constant $("#del_" + code).click(function() { if (input.alert && input.alert.del) { + // Posibility to force label of buttons + if (input.alert.del.yesButton) + yesButton = input.alert.del.yesButton; + if (input.alert.del.noButton) + noButton = input.alert.del.noButton; confirmConstantAction("del", url, code, input, input.alert.del, entity, yesButton, noButton); } else { delConstant(url, code, input, entity); diff --git a/htdocs/core/lib/categories.lib.php b/htdocs/core/lib/categories.lib.php index ba3f0de1145..06ee257dcdf 100644 --- a/htdocs/core/lib/categories.lib.php +++ b/htdocs/core/lib/categories.lib.php @@ -51,9 +51,11 @@ function categories_prepare_head($object,$type) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'categories_'.$type); + complete_head_from_modules($conf,$langs,$object,$head,$h,'categories_'.$type,'remove'); + return $head; } diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index a5fe3c5d1f2..8ddf40e2abf 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -777,7 +777,7 @@ function show_actions_todo($conf,$langs,$db,$object,$objcon='',$noprint=0) if (get_class($object) == 'Adherent') $sql.= ", ".MAIN_DB_PREFIX."adherent as m"; if (get_class($object) == 'Societe') $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON a.fk_contact = sp.rowid"; $sql.= " WHERE u.rowid = a.fk_user_author"; - $sql.= " AND a.entity IN (".getEntity('actioncomm').")"; + $sql.= " AND a.entity IN (".getEntity('agenda', 1).")"; if (get_class($object) == 'Adherent') { $sql.= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; if (! empty($object->id)) @@ -916,7 +916,7 @@ function show_actions_done($conf,$langs,$db,$object,$objcon='',$noprint=0) if (get_class($object) == 'Adherent') $sql.= ", ".MAIN_DB_PREFIX."adherent as m"; if (get_class($object) == 'Societe') $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON a.fk_contact = sp.rowid"; $sql.= " WHERE u.rowid = a.fk_user_author"; - $sql.= " AND a.entity IN (".getEntity('actioncomm').")"; + $sql.= " AND a.entity IN (".getEntity('agenda', 1).")"; if (get_class($object) == 'Adherent') $sql.= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; if (get_class($object) == 'Adherent' && $object->id) $sql.= " AND a.fk_element = ".$object->id; if (get_class($object) == 'Societe' && $object->id) $sql.= " AND a.fk_soc = ".$object->id; diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index 8009ba6e31d..af31f52d166 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -63,7 +63,7 @@ function contact_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'contact'); $head[$h][0] = DOL_URL_ROOT.'/contact/info.php?id='.$object->id; @@ -71,7 +71,7 @@ function contact_prepare_head($object) $head[$h][2] = 'info'; $h++; - + complete_head_from_modules($conf,$langs,$object,$head,$h,'contact','remove'); return $head; } diff --git a/htdocs/core/lib/contract.lib.php b/htdocs/core/lib/contract.lib.php index 90a15cf958e..238bfb2a7b3 100644 --- a/htdocs/core/lib/contract.lib.php +++ b/htdocs/core/lib/contract.lib.php @@ -38,7 +38,7 @@ function contract_prepare_head($object) $head[$h][1] = $langs->trans("ContractCard"); $head[$h][2] = 'card'; $h++; - + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/contrat/contact.php?id='.$object->id; @@ -50,9 +50,9 @@ function contract_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'contract'); - + if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/contrat/note.php?id='.$object->id; @@ -71,6 +71,8 @@ function contract_prepare_head($object) $head[$h][2] = 'info'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'contract','remove'); + return $head; } diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index b0d2c997d05..88c6ee49f09 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -759,25 +759,30 @@ function num_between_day($timestampStart, $timestampEnd, $lastday=0) } /** - * Fonction retournant le nombre de jour entre deux dates sans les jours feries (jours ouvres) + * Function to return number of working days (and text of units) between two dates (jours ouvres) * - * @param timestamp $timestampStart Timestamp de debut - * @param timestamp $timestampEnd Timestamp de fin - * @param int $inhour 0: sort le nombre de jour , 1: sort le nombre d'heure (72 max) - * @param int $lastday We include last day, 0: non, 1:oui - * @return int Nombre de jours ou d'heures + * @param timestamp $timestampStart Timestamp for start date + * @param timestamp $timestampEnd Timestamp for end date + * @param int $inhour 0: return number of days, 1: return number of hours (72 max) + * @param int $lastday We include last day, 0: no, 1:yes + * @return int Number of days or hours */ function num_open_day($timestampStart, $timestampEnd,$inhour=0,$lastday=0) { global $langs; dol_syslog('num_open_day timestampStart='.$timestampStart.' timestampEnd='.$timestampEnd.' bit='.$lastday); + + // Check parameters + if (! is_int($timestampStart) && ! is_float($timestampStart)) return 'ErrorBadParameter_num_open_day'; + if (! is_int($timestampEnd) && ! is_float($timestampEnd)) return 'ErrorBadParameter_num_open_day'; + //print 'num_open_day timestampStart='.$timestampStart.' timestampEnd='.$timestampEnd.' bit='.$lastday; if ($timestampStart < $timestampEnd) { //print num_between_day($timestampStart, $timestampEnd, $lastday).' - '.num_public_holiday($timestampStart, $timestampEnd); $nbOpenDay = num_between_day($timestampStart, $timestampEnd, $lastday) - num_public_holiday($timestampStart, $timestampEnd, $lastday); - $nbOpenDay.= " ".$langs->trans("Days"); + $nbOpenDay.= " " . $langs->trans("Days"); if ($inhour == 1 && $nbOpenDay <= 3) $nbOpenDay = $nbOpenDay*24 . $langs->trans("HourShort"); return $nbOpenDay; } @@ -785,7 +790,7 @@ function num_open_day($timestampStart, $timestampEnd,$inhour=0,$lastday=0) { $nbOpenDay=$lastday; if ($inhour == 1) $nbOpenDay = $nbOpenDay*24 . $langs->trans("HourShort"); - return $nbOpenDay=1; + return $nbOpenDay; } else { diff --git a/htdocs/core/lib/fichinter.lib.php b/htdocs/core/lib/fichinter.lib.php index 08732c271af..463375baca0 100644 --- a/htdocs/core/lib/fichinter.lib.php +++ b/htdocs/core/lib/fichinter.lib.php @@ -42,7 +42,7 @@ function fichinter_prepare_head($object) $head[$h][1] = $langs->trans("Card"); $head[$h][2] = 'card'; $h++; - + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/fichinter/contact.php?id='.$object->id; @@ -62,9 +62,9 @@ function fichinter_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'intervention'); - + if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/fichinter/note.php?id='.$object->id; @@ -83,7 +83,9 @@ function fichinter_prepare_head($object) $head[$h][2] = 'info'; $h++; - return $head; + complete_head_from_modules($conf,$langs,$object,$head,$h,'intervention','remove'); + + return $head; } ?> diff --git a/htdocs/core/lib/fourn.lib.php b/htdocs/core/lib/fourn.lib.php index 887cae3115d..21db6d63fb8 100644 --- a/htdocs/core/lib/fourn.lib.php +++ b/htdocs/core/lib/fourn.lib.php @@ -52,7 +52,7 @@ function facturefourn_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'supplier_invoice'); if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) @@ -77,7 +77,9 @@ function facturefourn_prepare_head($object) $head[$h][2] = 'info'; $h++; - return $head; + complete_head_from_modules($conf,$langs,$object,$head,$h,'supplier_invoice','remove'); + + return $head; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 86fb33f545c..78d9b653b87 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -232,10 +232,11 @@ function dol_getprefix() function dol_include_once($relpath, $classname='') { global $conf,$langs,$user,$mysoc; // Other global var must be retreived with $GLOBALS['var'] + if (! empty($classname) && ! class_exists($classname)) { - return @include dol_buildpath($relpath); + return @include dol_buildpath($relpath); // Remove @ to find error into php log file if you have problems } else { - return @include_once dol_buildpath($relpath); + return @include_once dol_buildpath($relpath); // Remove @ to find error into php log file if you have problems } } @@ -483,90 +484,73 @@ function dol_strtoupper($utf8_string) * * @param string $message Line to log. Ne doit pas etre traduit si level = LOG_ERR * @param int $level Log level + * 0=Show nothing * On Windows LOG_ERR=4, LOG_WARNING=5, LOG_NOTICE=LOG_INFO=6, LOG_DEBUG=6 si define_syslog_variables ou PHP 5.3+, 7 si dolibarr * On Linux LOG_ERR=3, LOG_WARNING=4, LOG_INFO=6, LOG_DEBUG=7 + * @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1 * @return void */ -function dol_syslog($message, $level = LOG_INFO) +function dol_syslog($message, $level = LOG_INFO, $ident = 0) { - global $conf, $user, $langs; + global $conf, $user; // If syslog module enabled if (empty($conf->syslog->enabled)) return false; - if (!defined('SYSLOG_HANDLERS') || !constant('SYSLOG_HANDLERS')) return false; - - $logLevels = array( - LOG_EMERG, - LOG_ALERT, - LOG_CRIT, - LOG_ERR, - LOG_WARNING, - LOG_NOTICE, - LOG_INFO, - LOG_DEBUG - ); - - if (!in_array($level, $logLevels)) + if (! empty($level)) { - throw new Exception('Incorrect log level'); - } - - if ($level > $conf->global->SYSLOG_LEVEL) return false; - - // If adding log inside HTML page is required - if (! empty($_REQUEST['logtohtml']) && ! empty($conf->global->MAIN_LOGTOHTML)) - { - $conf->logbuffer[] = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".$message; - } - - // If enable html log tag enabled and url parameter log defined, we show output log on HTML comments - if (! empty($conf->global->MAIN_ENABLE_LOG_HTML) && ! empty($_GET["log"])) - { - print "\n\n\n"; - } - - $data = array( - 'message' => $message, - 'script' => (isset($_SERVER['PHP_SELF'])? basename($_SERVER['PHP_SELF'],'.php') : false), - 'level' => $level, - 'user' => ((is_object($user) && $user->id) ? $user->login : false), - 'ip' => false - ); - - if (! empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; - // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) - else if (! empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR']; - // This is when PHP session is ran outside a web server, like from Windows command line (Not always defined, but useful if OS defined it). - else if (! empty($_SERVER['COMPUTERNAME'])) $data['ip'] = $_SERVER['COMPUTERNAME'].(empty($_SERVER['USERNAME'])?'':'@'.$_SERVER['USERNAME']); - // This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it). - else if (! empty($_SERVER['LOGNAME'])) $data['ip'] = '???@'.$_SERVER['LOGNAME']; - - //We load SYSLOG handlers - if (defined('SYSLOG_HANDLERS')) $handlers = json_decode(SYSLOG_HANDLERS); - else $handlers = array(); - - foreach ($handlers as $handler) - { - $file = DOL_DOCUMENT_ROOT.'/core/modules/syslog/'.$handler.'.php'; - - if (!file_exists($file)) + // Test log level + $logLevels = array( LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG); + if (!in_array($level, $logLevels)) { - throw new Exception('Missing log handler'); + throw new Exception('Incorrect log level'); + } + if ($level > $conf->global->SYSLOG_LEVEL) return false; + + // If adding log inside HTML page is required + if (! empty($_REQUEST['logtohtml']) && ! empty($conf->global->MAIN_LOGTOHTML)) + { + $conf->logbuffer[] = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".$message; } - require_once $file; - - $class = new $handler(); - - if (!$class instanceof LogHandlerInterface) + // If enable html log tag enabled and url parameter log defined, we show output log on HTML comments + if (! empty($conf->global->MAIN_ENABLE_LOG_HTML) && ! empty($_GET["log"])) { - throw new Exception('Log handler does not extend LogHandlerInterface'); + print "\n\n\n"; } - $class->export($data); + $data = array( + 'message' => $message, + 'script' => (isset($_SERVER['PHP_SELF'])? basename($_SERVER['PHP_SELF'],'.php') : false), + 'level' => $level, + 'user' => ((is_object($user) && $user->id) ? $user->login : false), + 'ip' => false + ); + + if (! empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; + // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) + else if (! empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR']; + // This is when PHP session is ran outside a web server, like from Windows command line (Not always defined, but useful if OS defined it). + else if (! empty($_SERVER['COMPUTERNAME'])) $data['ip'] = $_SERVER['COMPUTERNAME'].(empty($_SERVER['USERNAME'])?'':'@'.$_SERVER['USERNAME']); + // This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it). + else if (! empty($_SERVER['LOGNAME'])) $data['ip'] = '???@'.$_SERVER['LOGNAME']; + + // Loop on each log handler and send output + foreach ($conf->loghandlers as $loghandlerinstance) + { + $loghandlerinstance->export($data); + } + unset($data); + } + + if (! empty($ident)) + { + foreach ($conf->loghandlers as $loghandlerinstance) + { + $loghandlerinstance->setIdent($ident); + } } } @@ -2190,17 +2174,18 @@ function dol_print_error($db='',$error='') } /** - * Show email to contact if technical error + * Show a public email and error code to contact if technical error * + * @param string $prefixcode Prefix of public error code * @return void */ -function dol_print_error_email() +function dol_print_error_email($prefixcode) { global $langs,$conf; $langs->load("errors"); $now=dol_now(); - print '
    '.$langs->trans("ErrorContactEMail",$conf->global->MAIN_INFO_SOCIETE_MAIL,'ERRORNEWPAYMENT'.dol_print_date($now,'%Y%m%d')).'
    '; + print '
    '.$langs->trans("ErrorContactEMail", $conf->global->MAIN_INFO_SOCIETE_MAIL, $prefixcode.dol_print_date($now,'%Y%m%d')).'
    '; } /** @@ -2700,8 +2685,16 @@ function get_localtax($tva, $local, $thirdparty_buyer="", $thirdparty_seller="") dol_syslog("get_localtax tva=".$tva." local=".$local." thirdparty_buyer=".(is_object($thirdparty_buyer)?$thirdparty_buyer->id:'')." thirdparty_seller=".$thirdparty_seller->id); // Some test to guess with no need to make database access - if ($local == 1 && ! $thirdparty_seller->localtax1_assuj) return 0; - if ($local == 2 && ! $thirdparty_seller->localtax2_assuj) return 0; + if ($mysoc->country_code == 'ES') // For spain, localtaxes are qualified if both supplier and seller use local taxe + { + if ($local == 1 && ! $thirdparty_buyer->localtax1_assuj) return 0; + if ($local == 2 && ! $thirdparty_seller->localtax2_assuj) return 0; + } + else + { + if ($local == 1 && ! $thirdparty_seller->localtax1_assuj) return 0; + if ($local == 2 && ! $thirdparty_seller->localtax2_assuj) return 0; + } //if ($local == 0 && ! $thirdparty_seller->localtax1_assuj && ! $thirdparty_seller->localtax2_assuj) return array('localtax1'=>0,'localtax2'=>0); $code_country=$thirdparty_seller->country_code; @@ -2712,7 +2705,7 @@ function get_localtax($tva, $local, $thirdparty_buyer="", $thirdparty_seller="") } // Search local taxes - $sql = "SELECT t.localtax1, t.localtax2"; + $sql = "SELECT t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_pays as p"; $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$code_country."'"; $sql .= " AND t.taux = ".$tva." AND t.active = 1"; @@ -2722,9 +2715,8 @@ function get_localtax($tva, $local, $thirdparty_buyer="", $thirdparty_seller="") if ($resql) { $obj = $db->fetch_object($resql); - if ($local==1) return $obj->localtax1; - elseif ($local==2) return $obj->localtax2; - //else return array($obj->localtax1,$obj->localtax2); + if ($local==1 && $obj->localtax1_type != '7') return $obj->localtax1; + elseif ($local==2 && $obj->localtax2_type != '7') return $obj->localtax2; } return 0; @@ -2985,18 +2977,27 @@ function get_default_npr($thirdparty_seller, $thirdparty_buyer, $idprod) */ function get_default_localtax($thirdparty_seller, $thirdparty_buyer, $local, $idprod=0) { + global $mysoc; + if (!is_object($thirdparty_seller)) return -1; if (!is_object($thirdparty_buyer)) return -1; - if ($local==1) //RE + if ($local==1) // Localtax 1 { - // Si vendeur non assujeti a RE, localtax1 par default=0 - if (is_numeric($thirdparty_seller->localtax1_assuj) && ! $thirdparty_seller->localtax1_assuj) return 0; - if (! is_numeric($thirdparty_seller->localtax1_assuj) && $thirdparty_seller->localtax1_assuj=='localtax1off') return 0; + if ($mysoc->country_code == 'ES') + { + if (is_numeric($thirdparty_buyer->localtax1_assuj) && ! $thirdparty_buyer->localtax1_assuj) return 0; + } + else + { + // Si vendeur non assujeti a Localtax1, localtax1 par default=0 + if (is_numeric($thirdparty_seller->localtax1_assuj) && ! $thirdparty_seller->localtax1_assuj) return 0; + if (! is_numeric($thirdparty_seller->localtax1_assuj) && $thirdparty_seller->localtax1_assuj=='localtax1off') return 0; + } } - elseif ($local==2) //IRPF + elseif ($local==2) //I Localtax 2 { - // Si vendeur non assujeti a IRPF, localtax2 par default=0 + // Si vendeur non assujeti a Localtax2, localtax2 par default=0 if (is_numeric($thirdparty_seller->localtax2_assuj) && ! $thirdparty_seller->localtax2_assuj) return 0; if (! is_numeric($thirdparty_seller->localtax2_assuj) && $thirdparty_seller->localtax2_assuj=='localtax2off') return 0; } @@ -3565,7 +3566,7 @@ function get_date_range($date_start,$date_end,$format = '',$outputlangs='') */ function setEventMessage($mesgs, $style='mesgs') { - if (! in_array($style,array('mesgs','warnings','errors'))) dol_print_error('','Bad parameter for setEventMessage'); + if (! in_array((string) $style, array('mesgs','warnings','errors'))) dol_print_error('','Bad parameter for setEventMessage'); if (! is_array($mesgs)) // If mesgs is a string { if ($mesgs) $_SESSION['dol_events'][$style][] = $mesgs; @@ -4199,6 +4200,35 @@ function getCurrencySymbol($currency_code) return $currency_sign; } +/** + * Get type of one localtax + * + * @param int $vatrate VAT Rate + * @param int $number Number of localtax (1 / 2) + * @param int $thirdparty company object + * @return array array(Type of local tax (1 to 7 / 0 if not found), rate or amount of localtax) + */ + +function getTypeOfLocalTaxFromRate($vatrate, $number, $thirdparty) +{ + global $db; + + // Search local taxes + $sql = "SELECT t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_pays as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$thirdparty->country_code."'"; + $sql .= " AND t.taux = ".$vatrate." AND t.active = 1"; + + $resql=$db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + if ($number == 1) return array($obj->localtax1_type, $obj->localtax1); + elseif ($number == 2) return array($obj->localtax2_type, $obj->localtax2); + } + + return 0; +} if (! function_exists('getmypid')) { diff --git a/htdocs/core/lib/holiday.lib.php b/htdocs/core/lib/holiday.lib.php new file mode 100644 index 00000000000..6d96d2bd1f3 --- /dev/null +++ b/htdocs/core/lib/holiday.lib.php @@ -0,0 +1,53 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/lib/holiday.lib.php + * \brief Ensemble de fonctions de base pour les adherents + */ + +/** + * Return array head with list of tabs to view object informations + * + * @param Object $object Holiday + * @return array head + */ +function holiday_prepare_head($object) +{ + global $langs, $conf, $user; + + $h = 0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT . '/holiday/fiche.php?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf,$langs,$object,$head,$h,'holiday'); + + complete_head_from_modules($conf,$langs,$object,$head,$h,'holiday','remove'); + + return $head; +} + +?> diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php index 8d3990942c1..10e4e91ce56 100644 --- a/htdocs/core/lib/invoice.lib.php +++ b/htdocs/core/lib/invoice.lib.php @@ -39,7 +39,7 @@ function facture_prepare_head($object) $head[$h][1] = $langs->trans('CardBill'); $head[$h][2] = 'compta'; $h++; - + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/compta/facture/contact.php?facid='.$object->id; @@ -68,9 +68,9 @@ function facture_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'invoice'); - + if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/compta/facture/note.php?facid='.$object->id; @@ -93,6 +93,8 @@ function facture_prepare_head($object) $head[$h][2] = 'info'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'invoice','remove'); + return $head; } diff --git a/htdocs/core/lib/member.lib.php b/htdocs/core/lib/member.lib.php index a4357147732..835708295c3 100644 --- a/htdocs/core/lib/member.lib.php +++ b/htdocs/core/lib/member.lib.php @@ -96,7 +96,7 @@ function member_prepare_head($object) $head[$h][2] = 'info'; $h++; - + complete_head_from_modules($conf,$langs,$object,$head,$h,'member','remove'); return $head; @@ -175,12 +175,19 @@ function member_stats_prepare_head($object) $head[$h][2] = 'statstown'; $h++; + $head[$h][0] = DOL_URL_ROOT.'/adherents/stats/byproperties.php'; + $head[$h][1] = $langs->trans('ByProperties'); + $head[$h][2] = 'statsbyproperties'; + $h++; + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'member_stats'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'member_stats','remove'); + return $head; } ?> diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index 3fc1bc73f04..f5c8b41f0ec 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -67,7 +67,7 @@ function commande_prepare_head($object) $head[$h][2] = 'preview'; $h++; } - + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/commande/contact.php?id='.$object->id; @@ -79,7 +79,7 @@ function commande_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'order'); $head[$h][0] = DOL_URL_ROOT.'/commande/document.php?id='.$object->id; @@ -90,7 +90,7 @@ function commande_prepare_head($object) $head[$h][1] = $langs->trans('Documents'); $head[$h][2] = 'documents'; $h++; - + if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/commande/note.php?id='.$object->id; @@ -104,7 +104,9 @@ function commande_prepare_head($object) $head[$h][2] = 'info'; $h++; - return $head; + complete_head_from_modules($conf,$langs,$object,$head,$h,'order','remove'); + + return $head; } ?> diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 219602f761e..764eb97c3c3 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -80,8 +80,10 @@ function pdf_getInstance($format='',$metric='mm',$pagetype='P') if (! empty($conf->global->MAIN_USE_FPDF) && ! empty($conf->global->MAIN_DISABLE_FPDI)) return "Error MAIN_USE_FPDF and MAIN_DISABLE_FPDI can't be set together"; - // We use by default TCPDF + // We use by default TCPDF else FPDF if (empty($conf->global->MAIN_USE_FPDF)) require_once TCPDF_PATH.'tcpdf.php'; + else require_once FPDF_PATH.'fpdf.php'; + // We need to instantiate fpdi object (instead of tcpdf) to use merging features. But we can disable it. if (empty($conf->global->MAIN_DISABLE_FPDI)) require_once FPDI_PATH.'fpdi.php'; @@ -90,7 +92,7 @@ function pdf_getInstance($format='',$metric='mm',$pagetype='P') //$metric=$arrayformat['unit']; // Protection et encryption du pdf - if (! empty($conf->global->PDF_SECURITY_ENCRYPTION)) + if (empty($conf->global->MAIN_USE_FPDF) && ! empty($conf->global->PDF_SECURITY_ENCRYPTION)) { /* Permission supported by TCPDF - print : Print the document; @@ -103,20 +105,11 @@ function pdf_getInstance($format='',$metric='mm',$pagetype='P') - print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality. - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions. */ - if (! empty($conf->global->MAIN_USE_FPDF)) - { - require_once FPDI_PATH.'fpdi_protection.php'; - $pdf = new FPDI_Protection($pagetype,$metric,$format); - // For FPDF, we specify permission we want to open - $pdfrights = array('print'); - } - else - { - if (class_exists('FPDI')) $pdf = new FPDI($pagetype,$metric,$format); - else $pdf = new TCPDF($pagetype,$metric,$format); - // For TCPDF, we specify permission we want to block - $pdfrights = array('modify','copy'); - } + if (class_exists('FPDI')) $pdf = new FPDI($pagetype,$metric,$format); + else $pdf = new TCPDF($pagetype,$metric,$format); + // For TCPDF, we specify permission we want to block + $pdfrights = array('modify','copy'); + $pdfuserpass = ''; // Mot de passe pour l'utilisateur final $pdfownerpass = NULL; // Mot de passe du proprietaire, cree aleatoirement si pas defini $pdf->SetProtection($pdfrights,$pdfuserpass,$pdfownerpass); @@ -126,9 +119,43 @@ function pdf_getInstance($format='',$metric='mm',$pagetype='P') if (class_exists('FPDI')) $pdf = new FPDI($pagetype,$metric,$format); else $pdf = new TCPDF($pagetype,$metric,$format); } + + // If we use FPDF class, we may need to add method writeHTMLCell + if (! empty($conf->global->MAIN_USE_FPDF) && ! method_exists($pdf, 'writeHTMLCell')) + { + // Declare here a class to overwrite FPDFI to add method writeHTMLCell + /** + * This class if a enhanced FPDI class that support method writeHTMLCell + */ + class FPDI_DolExtended extends FPDI + { + public function __call($method, $args) + { + if (isset($this->$method)) { + $func = $this->$method; + $func($args); + } + } + + public function writeHTMLCell($w, $h, $x, $y, $html = '', $border = 0, $ln = 0, $fill = false, $reseth = true, $align = '', $autopadding = true) + { + $this->SetXY($x,$y); + $val=str_replace('
    ',"\n",$html); + $val=dol_string_nohtmltag($val,false,'ISO-8859-1'); + //print 'eee'.$val;exit; + $this->MultiCell($w,$h,$val,$border,$align,$fill); + } + } + + $pdf2=new FPDI_DolExtended($pagetype,$metric,$format); + unset($pdf); + $pdf=$pdf2; + } + return $pdf; } + /** * Return font name to use for PDF generation * @@ -691,7 +718,7 @@ function pdf_pagefoot(&$pdf,$outputlangs,$paramfreetext,$fromcompany,$marge_bass { $pdf->SetFont('','B',7); $pdf->SetXY($dims['lm'],-$posy); - $pdf->MultiCell(200, 2, $line1, 0, 'C', 0); + $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line1, 0, 'C', 0); $posy-=3; $pdf->SetFont('','',7); } @@ -700,7 +727,7 @@ function pdf_pagefoot(&$pdf,$outputlangs,$paramfreetext,$fromcompany,$marge_bass { $pdf->SetFont('','B',7); $pdf->SetXY($dims['lm'],-$posy); - $pdf->MultiCell(200, 2, $line2, 0, 'C', 0); + $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line2, 0, 'C', 0); $posy-=3; $pdf->SetFont('','',7); } @@ -708,22 +735,23 @@ function pdf_pagefoot(&$pdf,$outputlangs,$paramfreetext,$fromcompany,$marge_bass if (! empty($line3)) { $pdf->SetXY($dims['lm'],-$posy); - $pdf->MultiCell(200, 2, $line3, 0, 'C', 0); + $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line3, 0, 'C', 0); } if (! empty($line4)) { $posy-=3; $pdf->SetXY($dims['lm'],-$posy); - $pdf->MultiCell(200, 2, $line4, 0, 'C', 0); + $pdf->MultiCell($dims['wk']-$dims['rm'], 2, $line4, 0, 'C', 0); } // Show page nb only on iso languages (so default Helvetica font) if (pdf_getPDFFont($outputlangs) == 'Helvetica') { $pdf->SetXY(-20,-$posy); - $pdf->MultiCell(11, 2, $pdf->PageNo().'/'.$pdf->getAliasNbPages(), 0, 'R', 0); - //print 'xxx'.$pdf->getAliasNbPages().'-'.$pdf->getAliasNumPage();exit; + //print 'xxx'.$pdf->PageNo().'-'.$pdf->getAliasNbPages().'-'.$pdf->getAliasNumPage();exit; + if (empty($conf->global->MAIN_USE_FPDF)) $pdf->MultiCell(11, 2, $pdf->PageNo().'/'.$pdf->getAliasNbPages(), 0, 'R', 0); + else $pdf->MultiCell(11, 2, $pdf->PageNo().'/{nb}', 0, 'R', 0); } return $marginwithfooter; diff --git a/htdocs/core/lib/prelevement.lib.php b/htdocs/core/lib/prelevement.lib.php index c370172430a..2b4f6264068 100644 --- a/htdocs/core/lib/prelevement.lib.php +++ b/htdocs/core/lib/prelevement.lib.php @@ -75,9 +75,11 @@ function prelevement_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'prelevement'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'prelevement','remove'); + return $head; } diff --git a/htdocs/core/lib/price.lib.php b/htdocs/core/lib/price.lib.php index dfca755bcac..ef1e43b17df 100644 --- a/htdocs/core/lib/price.lib.php +++ b/htdocs/core/lib/price.lib.php @@ -27,11 +27,11 @@ /** * Calculate totals (net, vat, ...) of a line. * Value for localtaxX_type are '0' : local tax not applied - * '1' : local tax apply on products and services without vat (vat is not applied on local tax) + * '1' : local tax apply on products and services without vat (vat is not applied for local tax calculation) * '2' : local tax apply on products and services before vat (vat is calculated on amount + localtax) - * '3' : local tax apply on products without vat (vat is not applied on local tax) + * '3' : local tax apply on products without vat (vat is not applied for local tax calculation) * '4' : local tax apply on products before vat (vat is calculated on amount + localtax) - * '5' : local tax apply on services without vat (vat is not applied on local tax) + * '5' : local tax apply on services without vat (vat is not applied for local tax calculation) * '6' : local tax apply on services before vat (vat is calculated on amount + localtax) * '7' : local tax is a fix amount applied on global invoice * @@ -46,7 +46,22 @@ * @param int $info_bits Miscellanous informations on line * @param int $type 0/1=Product/service * @param string $seller Thirdparty seller (we need $seller->country_code property). Provided only if seller is the supplier. - * @return result[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount, ...) + * @return result[ 0=total_ht, + * 1=total_vat, + * 2=total_ttc, + * 3=pu_ht, + * 4=pu_tva, + * 5=pu_ttc, + * 6=total_ht_without_discount, + * 7=total_vat_without_discount, + * 8=total_ttc_without_discount, + * 9=amount tax1 for total_ht, + * 10=amount tax2 for total_ht, + * 11=amount tax1 for pu_ht, + * 12=amount tax2 for pu_ht, + * 13=not used???, + * 14=amount tax1 for total_ht_without_discount, + * 15=amount tax1 for total_ht_without_discount] */ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '') { @@ -177,16 +192,17 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt } // if there's some localtax without vat, we calculate localtaxes (we will add them at end) - $apply_tax = false; - + //If price is 'TTC' we need to have the totals without VAT for a correct calculation if ($price_base_type=='TTC') { $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)),'MU'); $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)),'MU'); + $pu = price2num($pu / (1 + ($txtva / 100)),'MU'); } - switch($localtax1_type) { + $apply_tax = false; + switch($localtax1_type) { case '1': // localtax on product or service $apply_tax = true; break; diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index cb345399733..ee547ca49d7 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -113,7 +113,7 @@ function product_prepare_head($object, $user) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'product'); $head[$h][0] = DOL_URL_ROOT.'/product/document.php?id='.$object->id; @@ -158,8 +158,8 @@ function product_admin_prepare_head($object=null) // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'product_admin'); $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_extrafields.php'; diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index e5dddb11ea5..6265ecdb52b 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -61,7 +61,7 @@ function project_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'project'); $head[$h][0] = DOL_URL_ROOT.'/projet/document.php?id='.$object->id; @@ -96,7 +96,9 @@ function project_prepare_head($object) $head[$h][2] = 'gantt'; $h++; - return $head; + complete_head_from_modules($conf,$langs,$object,$head,$h,'project','remove'); + + return $head; } @@ -130,7 +132,7 @@ function task_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'task'); $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject')?'&withproject=1':'');; @@ -147,6 +149,8 @@ function task_prepare_head($object) $head[$h][2] = 'task_notes'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'task','remove'); + return $head; } @@ -208,7 +212,7 @@ function select_projects($socid=-1, $selected='', $htmlname='projectid', $maxlen //else $labeltoshow.=' ('.$langs->trans("Private").')'; if (!empty($selected) && $selected == $obj->rowid && $obj->fk_statut > 0) { - print ''; + print ''; } else { diff --git a/htdocs/core/lib/propal.lib.php b/htdocs/core/lib/propal.lib.php index a0922fc4c4c..8d5d668d667 100644 --- a/htdocs/core/lib/propal.lib.php +++ b/htdocs/core/lib/propal.lib.php @@ -73,7 +73,7 @@ function propal_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'propal'); if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) @@ -98,6 +98,8 @@ function propal_prepare_head($object) $head[$h][2] = 'info'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'propal','remove'); + return $head; } diff --git a/htdocs/core/lib/sendings.lib.php b/htdocs/core/lib/sendings.lib.php index d031bdd167c..5ba774d1b3e 100644 --- a/htdocs/core/lib/sendings.lib.php +++ b/htdocs/core/lib/sendings.lib.php @@ -66,10 +66,12 @@ function shipping_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'delivery'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'delivery','remove'); + return $head; } @@ -105,10 +107,12 @@ function delivery_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'delivery'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'delivery','remove'); + return $head; } diff --git a/htdocs/core/lib/stock.lib.php b/htdocs/core/lib/stock.lib.php index 7fb81297cb3..22694c39217 100644 --- a/htdocs/core/lib/stock.lib.php +++ b/htdocs/core/lib/stock.lib.php @@ -66,7 +66,7 @@ function stock_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'stock'); $head[$h][0] = DOL_URL_ROOT.'/product/stock/info.php?id='.$object->id; @@ -74,7 +74,9 @@ function stock_prepare_head($object) $head[$h][2] = 'info'; $h++; - return $head; + complete_head_from_modules($conf,$langs,$object,$head,$h,'stock','remove'); + + return $head; } ?> \ No newline at end of file diff --git a/htdocs/core/lib/tax.lib.php b/htdocs/core/lib/tax.lib.php index eab91d27d4b..96ae34899fb 100644 --- a/htdocs/core/lib/tax.lib.php +++ b/htdocs/core/lib/tax.lib.php @@ -45,7 +45,7 @@ function tax_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'tax'); $head[$h][0] = DOL_URL_ROOT.'/compta/sociales/document.php?id='.$object->id; @@ -58,6 +58,8 @@ function tax_prepare_head($object) $head[$h][2] = 'info'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'tax','remove'); + return $head; } diff --git a/htdocs/core/lib/trip.lib.php b/htdocs/core/lib/trip.lib.php index d2c150cf7da..e0380e6ef55 100644 --- a/htdocs/core/lib/trip.lib.php +++ b/htdocs/core/lib/trip.lib.php @@ -33,23 +33,25 @@ function trip_prepare_head($object) $h = 0; $head = array(); - + $head[$h][0] = DOL_URL_ROOT . '/compta/deplacement/fiche.php?id=' . $object->id; $head[$h][1] = $langs->trans("Card"); $head[$h][2] = 'card'; $h++; - + // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'trip'); - + $head[$h][0] = DOL_URL_ROOT . '/compta/deplacement/info.php?id=' . $object->id; $head[$h][1] = $langs->trans("Info"); $head[$h][2] = 'info'; $h++; + complete_head_from_modules($conf,$langs,$object,$head,$h,'trip','remove'); + return $head; } diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index e0dea4a81cd..61276982e1a 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -81,8 +81,8 @@ function user_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:conditiontoshow:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:conditiontoshow:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'user'); if (! empty($user->societe_id)) @@ -98,6 +98,8 @@ function user_prepare_head($object) $h++; } + complete_head_from_modules($conf,$langs,$object,$head,$h,'user','remove'); + return $head; } @@ -140,12 +142,51 @@ function group_prepare_head($object) // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'group'); + complete_head_from_modules($conf,$langs,$object,$head,$h,'group','remove'); + return $head; } + + +/** + * Prepare array with list of tabs + * + * @return array Array of tabs to shoc + */ +function user_admin_prepare_head() +{ + global $langs, $conf, $user; + + $langs->load("users"); + $h=0; + + $head[$h][0] = DOL_URL_ROOT.'/admin/user.php'; + $head[$h][1] = $langs->trans("Parameters"); + $head[$h][2] = 'card'; + $h++; + + $head[$h][0] = DOL_URL_ROOT.'/user/admin/user_extrafields.php'; + $head[$h][1] = $langs->trans("ExtraFields"); + $head[$h][2] = 'attributes'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf,$langs,$object,$head,$h,'useradmin'); + + complete_head_from_modules($conf,$langs,$object,$head,$h,'useradmin','remove'); + + return $head; +} + + + /** * Prepare array with list of tabs * diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index fc3f02d3250..2b5d0b7a60c 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -415,6 +415,9 @@ abstract class DolibarrModules global $db,$conf; $error=0; + $dirfound=0; + + if (empty($reldir)) return 1; include_once DOL_DOCUMENT_ROOT .'/core/lib/admin.lib.php'; @@ -426,11 +429,13 @@ abstract class DolibarrModules $dir = $dirroot.$reldir; $ok = 0; - // Run llx_mytable.sql files $handle=@opendir($dir); // Dir may not exists if (is_resource($handle)) { - while (($file = readdir($handle))!==false) + $dirfound++; + + // Run llx_mytable.sql files + while (($file = readdir($handle))!==false) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data') { @@ -438,14 +443,11 @@ abstract class DolibarrModules if ($result <= 0) $error++; } } - closedir($handle); - } + + rewinddir($handle); - // Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) - $handle=@opendir($dir); // Dir may not exist - if (is_resource($handle)) - { - while (($file = readdir($handle))!==false) + // Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) + while (($file = readdir($handle))!==false) { if (preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data') { @@ -453,14 +455,11 @@ abstract class DolibarrModules if ($result <= 0) $error++; } } - closedir($handle); - } - // Run data_xxx.sql files (Must be done after llx_mytable.key.sql) - $handle=@opendir($dir); // Dir may not exist - if (is_resource($handle)) - { - while (($file = readdir($handle))!==false) + rewinddir($handle); + + // Run data_xxx.sql files (Must be done after llx_mytable.key.sql) + while (($file = readdir($handle))!==false) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'data') { @@ -468,14 +467,11 @@ abstract class DolibarrModules if ($result <= 0) $error++; } } - closedir($handle); - } - - // Run update_xxx.sql files - $handle=@opendir($dir); // Dir may not exist - if (is_resource($handle)) - { - while (($file = readdir($handle))!==false) + + rewinddir($handle); + + // Run update_xxx.sql files + while (($file = readdir($handle))!==false) { if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,6) == 'update') { @@ -483,6 +479,7 @@ abstract class DolibarrModules if ($result <= 0) $error++; } } + closedir($handle); } @@ -493,6 +490,7 @@ abstract class DolibarrModules } } + if (! $dirfound) dol_syslog("A module ask to load sql files into ".$reldir." but this directory was not found.", LOG_WARNING); return $ok; } diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 1d56eb79635..0e179e4fb3c 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -3,6 +3,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2008 Raphael Bertrand * Copyright (C) 2010-2012 Juanjo Menent + * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -117,8 +118,6 @@ class pdf_einstein extends ModelePDFCommandes } $this->tva=array(); - $this->localtax1=array(); - $this->localtax2=array(); $this->atleastoneratenotnull=0; $this->atleastonediscount=0; } @@ -137,7 +136,7 @@ class pdf_einstein extends ModelePDFCommandes */ function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0,$hookmanager=false) { - global $user,$langs,$conf; + global $user,$langs,$conf,$mysoc,$db; if (! is_object($outputlangs)) $outputlangs=$langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO @@ -150,8 +149,6 @@ class pdf_einstein extends ModelePDFCommandes $outputlangs->load("products"); $outputlangs->load("orders"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->commande->dir_output) { $object->fetch_thirdparty(); @@ -186,7 +183,8 @@ class pdf_einstein extends ModelePDFCommandes // Create pdf instance $pdf=pdf_getInstance($this->format); - $heightforinfotot = 50; // Height reserved to output the info and total part + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance + $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) $pdf->SetAutoPageBreak(1,0); @@ -364,22 +362,49 @@ class pdf_einstein extends ModelePDFCommandes $localtax1ligne=$object->lines[$i]->total_localtax1; $localtax2ligne=$object->lines[$i]->total_localtax2; + $localtax1_rate=$object->lines[$i]->localtax1_tx; + $localtax2_rate=$object->lines[$i]->localtax2_tx; + $localtax1_type=$object->lines[$i]->localtax1_type; + $localtax2_type=$object->lines[$i]->localtax2_type; if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax1ligne-=($localtax1ligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax2ligne-=($localtax2ligne*$object->remise_percent)/100; $vatrate=(string) $object->lines[$i]->tva_tx; - $localtax1rate=(string) $object->lines[$i]->localtax1_tx; - $localtax2rate=(string) $object->lines[$i]->localtax2_tx; + + // TODO : store local taxes types into object lines and remove this + $localtax1_array=getTypeOfLocalTaxFromRate($vatrate,1,$mysoc); + $localtax2_array=getTypeOfLocalTaxFromRate($vatrate,2,$mysoc); + if (empty($localtax1_type)) + $localtax1_type = $localtax1_array[0]; + if (empty($localtax2_type)) + $localtax2_type = $localtax2_array[0]; + //end TODO + + // retrieve global local tax + if ($localtax1_type == '7') + $localtax1_rate = $localtax1_array[1]; + if ($localtax2_type == '7') + $localtax2_rate = $localtax2_array[1]; + + if ($localtax1ligne != 0 || $localtax1_type == '7') + $this->localtax1[$localtax1_type][$localtax1_rate]+=$localtax1ligne; + if ($localtax2ligne != 0 || $localtax2_type == '7') + $this->localtax2[$localtax2_type][$localtax2_rate]+=$localtax2ligne; if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate.='*'; if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=''; - if (! isset($this->localtax1[$localtax1rate])) $this->localtax1[$localtax1rate]=''; - if (! isset($this->localtax2[$localtax2rate])) $this->localtax2[$localtax2rate]=''; $this->tva[$vatrate] += $tvaligne; - $this->localtax1[$localtax1rate]+=$localtax1ligne; - $this->localtax2[$localtax2rate]+=$localtax2ligne; + + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } $nexY+=2; // Passe espace entre les lignes @@ -692,6 +717,84 @@ class pdf_einstein extends ModelePDFCommandes } else { + //Local tax 1 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') + { + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } + } + } + } + //Local tax 2 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + + } + } + } + } + // VAT foreach($this->tva as $tvakey => $tvaval) { if ($tvakey > 0) // On affiche pas taux 0 @@ -715,48 +818,26 @@ class pdf_einstein extends ModelePDFCommandes $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); } } - if (! $this->atleastoneratenotnull) // If no vat at all + + //Local tax 1 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1); - - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', 1); - - // Total LocalTax1 - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on' && $object->total_localtax1>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT1".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', 1); - } - - // Total LocalTax2 - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on' && $object->total_localtax2>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT2".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', 1); - } - } - else - { - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') - { - //Local tax 1 - foreach($this->localtax1 as $tvakey => $tvaval) + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -764,27 +845,43 @@ class pdf_einstein extends ModelePDFCommandes $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat =$outputlangs->transnoentities("TotalLT1".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } - - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') - { - //Local tax 2 - foreach($this->localtax2 as $tvakey => $tvaval) + } + //Local tax 2 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -792,12 +889,21 @@ class pdf_einstein extends ModelePDFCommandes $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat =$outputlangs->transnoentities("TotalLT2".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } diff --git a/htdocs/core/modules/expedition/doc/pdf_expedition_merou.modules.php b/htdocs/core/modules/expedition/doc/pdf_expedition_merou.modules.php index e65d09453e8..a15f13a5cda 100644 --- a/htdocs/core/modules/expedition/doc/pdf_expedition_merou.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_expedition_merou.modules.php @@ -84,7 +84,6 @@ class pdf_expedition_merou extends ModelePdfExpedition function write_file(&$object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0,$hookmanager=false) { global $user,$conf,$langs,$mysoc; - $default_font_size = pdf_getPDFFontSize($outputlangs); $object->fetch_thirdparty(); @@ -147,6 +146,7 @@ class pdf_expedition_merou extends ModelePdfExpedition $nblignes = count($object->lines); $pdf=pdf_getInstance($this->format,'mm','l'); + $default_font_size = pdf_getPDFFontSize($outputlangs); $heightforinfotot = 0; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -243,6 +243,15 @@ class pdf_expedition_merou extends ModelePdfExpedition $pdf->SetXY(170, $curY); $pdf->MultiCell(30, 3, $object->lines[$i]->qty_shipped, 0, 'C', 0); + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/expedition/doc/pdf_expedition_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_expedition_rouget.modules.php index 37f3ffc6538..d84905a53a8 100644 --- a/htdocs/core/modules/expedition/doc/pdf_expedition_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_expedition_rouget.modules.php @@ -87,7 +87,6 @@ class pdf_expedition_rouget extends ModelePdfExpedition function write_file(&$object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0,$hookmanager=false) { global $user,$conf,$langs; - $default_font_size = pdf_getPDFFontSize($outputlangs); $object->fetch_thirdparty(); @@ -133,7 +132,8 @@ class pdf_expedition_rouget extends ModelePdfExpedition $nblignes = count($object->lines); $pdf=pdf_getInstance($this->format); - $heightforinfotot = 0; // Height reserved to output the info and total part + $default_font_size = pdf_getPDFFontSize($outputlangs); + $heightforinfotot = 0; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) $pdf->SetAutoPageBreak(1,0); @@ -262,6 +262,15 @@ class pdf_expedition_rouget extends ModelePdfExpedition $pdf->SetXY($this->posxqtytoship, $curY); $pdf->MultiCell(($this->page_largeur - $this->marge_droite - $this->posxqtytoship), 3, $object->lines[$i]->qty_shipped,'','C'); + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 77d09e85691..eb4199649b4 100755 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -3,6 +3,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2008 Raphael Bertrand * Copyright (C) 2010-2012 Juanjo Menent + * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -138,7 +139,7 @@ class pdf_crabe extends ModelePDFFactures */ function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0,$hookmanager=false) { - global $user,$langs,$conf; + global $user,$langs,$conf,$mysoc,$db; if (! is_object($outputlangs)) $outputlangs=$langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO @@ -150,8 +151,6 @@ class pdf_crabe extends ModelePDFFactures $outputlangs->load("bills"); $outputlangs->load("products"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->facture->dir_output) { $object->fetch_thirdparty(); @@ -186,6 +185,7 @@ class pdf_crabe extends ModelePDFFactures $nblignes = count($object->lines); $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -197,6 +197,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->setPrintFooter(false); } $pdf->SetFont(pdf_getPDFFont($outputlangs)); + // Set path to the background PDF File if (empty($conf->global->MAIN_DISABLE_FPDI) && ! empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) { @@ -365,22 +366,49 @@ class pdf_crabe extends ModelePDFFactures $tvaligne=$object->lines[$i]->total_tva; $localtax1ligne=$object->lines[$i]->total_localtax1; $localtax2ligne=$object->lines[$i]->total_localtax2; + $localtax1_rate=$object->lines[$i]->localtax1_tx; + $localtax2_rate=$object->lines[$i]->localtax2_tx; + $localtax1_type=$object->lines[$i]->localtax1_type; + $localtax2_type=$object->lines[$i]->localtax2_type; if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax1ligne-=($localtax1ligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax2ligne-=($localtax2ligne*$object->remise_percent)/100; $vatrate=(string) $object->lines[$i]->tva_tx; - $localtax1rate=(string) $object->lines[$i]->localtax1_tx; - $localtax2rate=(string) $object->lines[$i]->localtax2_tx; + + // TODO : store local taxes types into object lines and remove this + $localtax1_array=getTypeOfLocalTaxFromRate($vatrate,1,$mysoc); + $localtax2_array=getTypeOfLocalTaxFromRate($vatrate,2,$mysoc); + if (empty($localtax1_type)) + $localtax1_type = $localtax1_array[0]; + if (empty($localtax2_type)) + $localtax2_type = $localtax2_array[0]; + //end TODO + + // retrieve global local tax + if ($localtax1_type == '7') + $localtax1_rate = $localtax1_array[1]; + if ($localtax2_type == '7') + $localtax2_rate = $localtax2_array[1]; + + if ($localtax1ligne != 0 || $localtax1_type == '7') + $this->localtax1[$localtax1_type][$localtax1_rate]+=$localtax1ligne; + if ($localtax2ligne != 0 || $localtax2_type == '7') + $this->localtax2[$localtax2_type][$localtax2_rate]+=$localtax2ligne; if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate.='*'; if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=''; - if (! isset($this->localtax1[$localtax1rate])) $this->localtax1[$localtax1rate]=''; - if (! isset($this->localtax2[$localtax2rate])) $this->localtax2[$localtax2rate]=''; $this->tva[$vatrate] += $tvaligne; - $this->localtax1[$localtax1rate]+=$localtax1ligne; - $this->localtax2[$localtax2rate]+=$localtax2ligne; + + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } $nexY+=2; // Passe espace entre les lignes @@ -813,6 +841,84 @@ class pdf_crabe extends ModelePDFFactures } else { + //Local tax 1 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') + { + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } + } + } + } + //Local tax 2 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + + } + } + } + } + // VAT foreach($this->tva as $tvakey => $tvaval) { if ($tvakey > 0) // On affiche pas taux 0 @@ -821,6 +927,7 @@ class pdf_crabe extends ModelePDFFactures $index++; $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $tvacompl=''; if (preg_match('/\*/',$tvakey)) { @@ -830,52 +937,31 @@ class pdf_crabe extends ModelePDFFactures $totalvat =$outputlangs->transnoentities("TotalVAT").' '; $totalvat.=vatrate($tvakey,1).$tvacompl; $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $tvaval), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); } } - if (! $this->atleastoneratenotnull) // If no vat at all + //Local tax 1 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_tva), 0, 'R', 1); - - // Total LocalTax1 - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on' && $object->total_localtax1>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT1".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_localtax1), $useborder, 'R', 1); - } - - // Total LocalTax2 - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on' && $object->total_localtax2>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT2".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_localtax2), $useborder, 'R', 1); - } - } - else - { - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') - { - //Local tax 1 - foreach($this->localtax1 as $tvakey => $tvaval) + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -883,27 +969,44 @@ class pdf_crabe extends ModelePDFFactures $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat =$outputlangs->transnoentities("TotalLT1".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $tvaval), 0, 'R', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } - - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') - { - //Local tax 2 - foreach($this->localtax2 as $tvakey => $tvaval) + } + //Local tax 2 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + // retrieve global local tax + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -911,12 +1014,21 @@ class pdf_crabe extends ModelePDFFactures $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat =$outputlangs->transnoentities("TotalLT2".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $tvaval), 0, 'R', 1); + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } @@ -927,11 +1039,10 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); $pdf->SetTextColor(0,0,60); $pdf->SetFillColor(224,224,224); - $text=$outputlangs->transnoentities("TotalTTC"); - if ($object->type == 2) $text=$outputlangs->transnoentities("TotalTTCToYourCredit"); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $text, $useborder, 'L', 1); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalTTC"), $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $object->total_ttc), $useborder, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc), $useborder, 'R', 1); } } diff --git a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php index 5d3246297bf..130f4409386 100644 --- a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php +++ b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php @@ -117,8 +117,6 @@ class pdf_soleil extends ModelePDFFicheinter $outputlangs->load("companies"); $outputlangs->load("interventions"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->ficheinter->dir_output) { $object->fetch_thirdparty(); @@ -140,6 +138,7 @@ class pdf_soleil extends ModelePDFFicheinter if (file_exists($dir)) { $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) diff --git a/htdocs/core/modules/livraison/pdf/pdf_typhon.modules.php b/htdocs/core/modules/livraison/pdf/pdf_typhon.modules.php index 420fce5653c..3a1ed05dffa 100644 --- a/htdocs/core/modules/livraison/pdf/pdf_typhon.modules.php +++ b/htdocs/core/modules/livraison/pdf/pdf_typhon.modules.php @@ -113,7 +113,6 @@ class pdf_typhon extends ModelePDFDeliveryOrder function write_file($object,$outputlangs) { global $user,$langs,$conf; - $default_font_size = pdf_getPDFFontSize($outputlangs); if (! is_object($outputlangs)) $outputlangs=$langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO @@ -150,6 +149,7 @@ class pdf_typhon extends ModelePDFDeliveryOrder if (file_exists($dir)) { $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -305,6 +305,16 @@ class pdf_typhon extends ModelePDFDeliveryOrder if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100; $this->tva[ (string) $object->lines[$i]->tva_tx ] += $tvaligne; */ + + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/mailings/framboise.modules.php b/htdocs/core/modules/mailings/framboise.modules.php index 76da4b23714..3d222b98eb7 100644 --- a/htdocs/core/modules/mailings/framboise.modules.php +++ b/htdocs/core/modules/mailings/framboise.modules.php @@ -61,9 +61,8 @@ class mailing_framboise extends MailingTargets $cibles = array(); - // CHANGE THIS // Select the members from category - $sql = "SELECT a.rowid as id, a.email as email, a.nom as name, null as fk_contact, null as firstname,"; + $sql = "SELECT a.rowid as id, a.email as email, a.nom as name, null as fk_contact, a.prenom as firstname,"; if ($_POST['filter']) $sql.= " c.label"; else $sql.=" null as label"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a"; diff --git a/htdocs/core/modules/modExpedition.class.php b/htdocs/core/modules/modExpedition.class.php index 5fa44181566..76396dfee7e 100644 --- a/htdocs/core/modules/modExpedition.class.php +++ b/htdocs/core/modules/modExpedition.class.php @@ -42,6 +42,8 @@ class modExpedition extends DolibarrModules */ function __construct($db) { + global $conf; + $this->db = $db; $this->numero = 80; @@ -71,6 +73,8 @@ class modExpedition extends DolibarrModules // Dependances $this->depends = array("modCommande"); $this->requiredby = array(); + $this->conflictwith = array(); + $this->langfiles = array('deliveries','sendings'); // Constantes $this->const = array(); @@ -141,6 +145,14 @@ class modExpedition extends DolibarrModules $this->rights[$r][4] = 'shipping_advance'; $this->rights[$r][5] = 'send'; + $r++; + $this->rights[$r][0] = 106; + $this->rights[$r][1] = 'Exporter les expeditions'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'shipment'; + $this->rights[$r][5] = 'export'; + $r++; $this->rights[$r][0] = 109; $this->rights[$r][1] = 'Supprimer les expeditions'; @@ -180,6 +192,25 @@ class modExpedition extends DolibarrModules $this->rights[$r][4] = 'livraison'; $this->rights[$r][5] = 'supprimer'; + // Exports + //-------- + $r=0; + + $r++; + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='Shipments'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_permission[$r]=array(array("expedition","shipment","export")); + $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.cp'=>'Zip','s.ville'=>'Town','s.fk_pays'=>'Country','s.tel'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.idprof5'=>'ProfId5','s.idprof6'=>'ProfId6','c.rowid'=>"Id",'c.ref'=>"Ref",'c.ref_customer'=>"RefCustomer",'c.fk_soc'=>"IdCompany",'c.date_creation'=>"DateCreation",'c.date_delivery'=>"DateSending",'c.tracking_number'=>"TrackingNumber",'c.height'=>"Height",'c.width'=>"Width",'c.size'=>"Depth",'c.size_units'=>'SizeUnits','c.weight'=>"Weight",'c.weight_units'=>"WeightUnits",'c.fk_statut'=>'Status','c.note'=>"Note",'ed.rowid'=>'LineId','cd.description'=>'Description','ed.qty'=>"Qty",'p.rowid'=>'ProductId','p.ref'=>'ProductRef','p.label'=>'ProductLabel'); + //$this->export_TypeFields_array[$r]=array('s.rowid'=>"List:societe:nom",'s.nom'=>'Text','s.address'=>'Text','s.cp'=>'Text','s.ville'=>'Text','s.libelle'=>'List:c_pays:libelle:rowid','s.tel'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','c.ref'=>"Text",'c.ref_client'=>"Text",'c.date_creation'=>"Date",'c.date_commande'=>"Date",'c.amount_ht'=>"Number",'c.remise_percent'=>"Number",'c.total_ht'=>"Number",'c.total_ttc'=>"Number",'c.facture'=>"Boolean",'c.fk_statut'=>'Status','c.note'=>"Text",'c.date_livraison'=>'Date','ed.qty'=>"Text"); + $this->export_TypeFields_array[$r]=array('s.nom'=>'Text','s.address'=>'Text','s.cp'=>'Text','s.ville'=>'Text','s.libelle'=>'List:c_pays:libelle:rowid','s.tel'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','c.ref'=>"Text",'c.ref_customer'=>"Text",'c.date_creation'=>"Date",'c.date_delivery'=>"Date",'c.tracking_number'=>"Number",'c.height'=>"Number",'c.width'=>"Number",'c.weight'=>"Number",'c.fk_statut'=>'Status','c.note'=>"Text",'ed.qty'=>"Number"); + $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.cp'=>'company','s.ville'=>'company','s.fk_pays'=>'company','s.tel'=>'company','s.siren'=>'company','s.ape'=>'company','s.siret'=>'company','s.idprof4'=>'company','s.idprof5'=>'company','s.idprof6'=>'company','c.rowid'=>"shipment",'c.ref'=>"shipment",'c.ref_customer'=>"shipment",'c.fk_soc'=>"shipment",'c.date_creation'=>"shipment",'c.date_delivery'=>"shipment",'c.tracking_number'=>'shipment','c.height'=>"shipment",'c.width'=>"shipment",'c.size'=>'shipment','c.size_units'=>'shipment','c.weight'=>"shipment",'c.weight_units'=>'shipment','c.fk_statut'=>"shipment",'c.note'=>"shipment",'ed.rowid'=>'shipment_line','cd.description'=>'shipment_line','ed.qty'=>"shipment_line",'p.rowid'=>'product','p.ref'=>'product','p.label'=>'product'); + $this->export_dependencies_array[$r]=array('shipment_line'=>'ed.rowid','product'=>'ed.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them + + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'expedition as c, '.MAIN_DB_PREFIX.'societe as s, '.MAIN_DB_PREFIX.'expeditiondet as ed, '.MAIN_DB_PREFIX.'commandedet as cd)'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (cd.fk_product = p.rowid)'; + $this->export_sql_end[$r] .=' WHERE c.fk_soc = s.rowid AND c.rowid = ed.fk_expedition AND ed.fk_origin_line = cd.rowid'; + $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; } diff --git a/htdocs/core/modules/modGravatar.class.php b/htdocs/core/modules/modGravatar.class.php index 7379b817396..c41c196e2ed 100644 --- a/htdocs/core/modules/modGravatar.class.php +++ b/htdocs/core/modules/modGravatar.class.php @@ -220,7 +220,7 @@ class modGravatar extends DolibarrModules */ function load_tables() { - return $this->_load_tables('/mymodule/sql/'); + return $this->_load_tables(''); } } diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index e4c4fb03952..7624436b34e 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -65,6 +65,8 @@ class modProjet extends DolibarrModules // Dependancies $this->depends = array(); $this->requiredby = array(); + $this->conflictwith = array(); + $this->langfiles = array('projects'); // Constants $this->const = array(); diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 853ad62ed0e..535971517e2 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004-2012 Laurent Destailleur * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2005-2012 Regis Houssin @@ -250,7 +250,7 @@ class modSociete extends DolibarrModules $this->export_fields_array[$r]=array('s.rowid'=>"Id",'s.nom'=>"Name",'s.status'=>"Status",'s.client'=>"Customer",'s.fournisseur'=>"Supplier",'s.datec'=>"DateCreation",'s.tms'=>"DateLastModification",'s.code_client'=>"CustomerCode",'s.code_fournisseur'=>"SupplierCode",'s.address'=>"Address",'s.cp'=>"Zip",'s.ville'=>"Town",'p.libelle'=>"Country",'p.code'=>"CountryCode",'s.tel'=>"Phone",'s.fax'=>"Fax",'s.url'=>"Url",'s.email'=>"Email",'s.default_lang'=>"DefaultLang",'s.siren'=>"ProfId1",'s.siret'=>"ProfId2",'s.ape'=>"ProfId3",'s.idprof4'=>"ProfId4",'s.idprof5'=>"ProfId5",'s.idprof6'=>"ProfId6",'s.tva_intra'=>"VATIntraShort",'s.capital'=>"Capital",'s.note'=>"Note",'t.libelle'=>"ThirdPartyType",'ce.code'=>"Staff","cfj.libelle"=>"JuridicalStatus",'s.fk_prospectlevel'=>'ProspectLevel','s.fk_stcomm'=>'ProspectStatus','d.nom'=>'State'); if (! empty($conf->global->SOCIETE_USEPREFIX)) $this->export_fields_array[$r]['s.prefix']='Prefix'; //$this->export_TypeFields_array[$r]=array('s.rowid'=>"List:societe:nom",'s.nom'=>"Text",'s.status'=>"Text",'s.client'=>"Boolean",'s.fournisseur'=>"Boolean",'s.datec'=>"Date",'s.tms'=>"Date",'s.code_client'=>"Text",'s.code_fournisseur'=>"Text",'s.address'=>"Text",'s.cp'=>"Text",'s.ville'=>"Text",'p.libelle'=>"List:c_pays:libelle:rowid",'p.code'=>"Text",'s.tel'=>"Text",'s.fax'=>"Text",'s.url'=>"Text",'s.email'=>"Text",'s.default_lang'=>"Text",'s.siret'=>"Text",'s.siren'=>"Text",'s.ape'=>"Text",'s.idprof4'=>"Text",'s.idprof5'=>"Text",'s.idprof6'=>"Text",'s.tva_intra'=>"Text",'s.capital'=>"Number",'s.note'=>"Text",'t.libelle'=>"Text",'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code','s.fk_stcomm'=>'List:c_stcomm:libelle:code','d.nom'=>'List:c_departements:nom:rowid'); - $this->export_TypeFields_array[$r]=array('s.nom'=>"Text",'s.status'=>"Text",'s.client'=>"Boolean",'s.fournisseur'=>"Boolean",'s.datec'=>"Date",'s.tms'=>"Date",'s.code_client'=>"Text",'s.code_fournisseur'=>"Text",'s.address'=>"Text",'s.cp'=>"Text",'s.ville'=>"Text",'p.libelle'=>"List:c_pays:libelle:rowid",'p.code'=>"Text",'s.tel'=>"Text",'s.fax'=>"Text",'s.url'=>"Text",'s.email'=>"Text",'s.default_lang'=>"Text",'s.siret'=>"Text",'s.siren'=>"Text",'s.ape'=>"Text",'s.idprof4'=>"Text",'s.idprof5'=>"Text",'s.idprof6'=>"Text",'s.tva_intra'=>"Text",'s.capital'=>"Number",'s.note'=>"Text",'t.libelle'=>"Text",'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code','s.fk_stcomm'=>'List:c_stcomm:libelle:code','d.nom'=>'List:c_departements:nom:rowid'); + $this->export_TypeFields_array[$r]=array('s.nom'=>"Text",'s.status'=>"Text",'s.client'=>"Boolean",'s.fournisseur'=>"Boolean",'s.datec'=>"Date",'s.tms'=>"Date",'s.code_client'=>"Text",'s.code_fournisseur'=>"Text",'s.address'=>"Text",'s.cp'=>"Text",'s.ville'=>"Text",'p.libelle'=>"List:c_pays:libelle:rowid",'p.code'=>"Text",'s.tel'=>"Text",'s.fax'=>"Text",'s.url'=>"Text",'s.email'=>"Text",'s.default_lang'=>"Text",'s.siret'=>"Text",'s.siren'=>"Text",'s.ape'=>"Text",'s.idprof4'=>"Text",'s.idprof5'=>"Text",'s.idprof6'=>"Text",'s.tva_intra'=>"Text",'s.capital'=>"Number",'s.note'=>"Text",'t.libelle'=>"Text",'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code','s.fk_stcomm'=>'List:c_stcomm:libelle:code','d.nom'=>'Text'); $this->export_entities_array[$r]=array(); // We define here only fields that use another picto // Add extra fields $sql="SELECT name, label FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'company'"; diff --git a/htdocs/core/modules/modWorkflow.class.php b/htdocs/core/modules/modWorkflow.class.php index 9ba4bf27d67..967e4178fb7 100644 --- a/htdocs/core/modules/modWorkflow.class.php +++ b/htdocs/core/modules/modWorkflow.class.php @@ -173,7 +173,7 @@ class modWorkflow extends DolibarrModules */ function load_tables() { - return $this->_load_tables('/workflow/sql/'); + return $this->_load_tables(''); } } ?> diff --git a/htdocs/core/modules/project/pdf/pdf_baleine.modules.php b/htdocs/core/modules/project/pdf/pdf_baleine.modules.php index 2a9048804c3..888dadc62d6 100644 --- a/htdocs/core/modules/project/pdf/pdf_baleine.modules.php +++ b/htdocs/core/modules/project/pdf/pdf_baleine.modules.php @@ -108,8 +108,6 @@ class pdf_baleine extends ModelePDFProjects { $nblignes = count($object->lines); - $default_font_size = pdf_getPDFFontsize($outputlangs); - $objectref = dol_sanitizeFileName($object->ref); $dir = $conf->projet->dir_output; if (! preg_match('/specimen/i',$objectref)) $dir.= "/" . $objectref; @@ -127,6 +125,7 @@ class pdf_baleine extends ModelePDFProjects if (file_exists($dir)) { $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -226,6 +225,15 @@ class pdf_baleine extends ModelePDFProjects $pdf->SetFont('','', $default_font_size - 1); // On repositionne la police par defaut $nexY = $pdf->GetY(); + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 77d9d849d2a..3459b045b62 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -3,6 +3,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2008 Raphael Bertrand * Copyright (C) 2010-2012 Juanjo Menent + * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -116,8 +117,6 @@ class pdf_azur extends ModelePDFPropales } $this->tva=array(); - $this->localtax1=array(); - $this->localtax2=array(); $this->atleastoneratenotnull=0; $this->atleastonediscount=0; } @@ -136,7 +135,7 @@ class pdf_azur extends ModelePDFPropales */ function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0,$hookmanager=false) { - global $user,$langs,$conf; + global $user,$langs,$conf,$mysoc,$db; if (! is_object($outputlangs)) $outputlangs=$langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO @@ -149,8 +148,6 @@ class pdf_azur extends ModelePDFPropales $outputlangs->load("propal"); $outputlangs->load("products"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->propal->dir_output) { $object->fetch_thirdparty(); @@ -185,6 +182,7 @@ class pdf_azur extends ModelePDFPropales // Create pdf instance $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -362,22 +360,48 @@ class pdf_azur extends ModelePDFPropales $tvaligne=$object->lines[$i]->total_tva; $localtax1ligne=$object->lines[$i]->total_localtax1; $localtax2ligne=$object->lines[$i]->total_localtax2; + $localtax1_rate=$object->lines[$i]->localtax1_tx; + $localtax2_rate=$object->lines[$i]->localtax2_tx; + $localtax1_type=$object->lines[$i]->localtax1_type; + $localtax2_type=$object->lines[$i]->localtax2_type; if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax1ligne-=($localtax1ligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax2ligne-=($localtax2ligne*$object->remise_percent)/100; $vatrate=(string) $object->lines[$i]->tva_tx; - $localtax1rate=(string) $object->lines[$i]->localtax1_tx; - $localtax2rate=(string) $object->lines[$i]->localtax2_tx; + // TODO : store local taxes types into object lines and remove this + $localtax1_array=getTypeOfLocalTaxFromRate($vatrate,1,$mysoc); + $localtax2_array=getTypeOfLocalTaxFromRate($vatrate,2,$mysoc); + if (empty($localtax1_type)) + $localtax1_type = $localtax1_array[0]; + if (empty($localtax2_type)) + $localtax2_type = $localtax2_array[0]; + //end TODO + + // retrieve global local tax + if ($localtax1_type == '7') + $localtax1_rate = $localtax1_array[1]; + if ($localtax2_type == '7') + $localtax2_rate = $localtax2_array[1]; + + if ($localtax1ligne != 0 || $localtax1_type == '7') + $this->localtax1[$localtax1_type][$localtax1_rate]+=$localtax1ligne; + if ($localtax2ligne != 0 || $localtax2_type == '7') + $this->localtax2[$localtax2_type][$localtax2_rate]+=$localtax2ligne; if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate.='*'; if (! isset($this->tva[$vatrate])) $this->tva[$vatrate]=''; - if (! isset($this->localtax1[$localtax1rate])) $this->localtax1[$localtax1rate]=''; - if (! isset($this->localtax2[$localtax2rate])) $this->localtax2[$localtax2rate]=''; $this->tva[$vatrate] += $tvaligne; - $this->localtax1[$localtax1rate]+=$localtax1ligne; - $this->localtax2[$localtax2rate]+=$localtax2ligne; + + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } $nexY+=2; // Passe espace entre les lignes @@ -726,6 +750,84 @@ class pdf_azur extends ModelePDFPropales } else { + //Local tax 1 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') + { + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } + } + } + } + //Local tax 2 before VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '1': + case '3': + case '5': + case '7': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) + { + if ($tvakey>0) // On affiche pas taux 0 + { + //$this->atleastoneratenotnull++; + + + + $index++; + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); + + $tvacompl=''; + if (preg_match('/\*/',$tvakey)) + { + $tvakey=str_replace('*','',$tvakey); + $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; + } + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + + } + } + } + } + // VAT foreach($this->tva as $tvakey => $tvaval) { if ($tvakey > 0) // On affiche pas taux 0 @@ -750,48 +852,25 @@ class pdf_azur extends ModelePDFPropales } } - if (! $this->atleastoneratenotnull) // If no vat at all + //Local tax 1 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalVAT"), 0, 'L', 1); - - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_tva), 0, 'R', 1); - - // Total LocalTax1 - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on' && $object->total_localtax1>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT1".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax1), $useborder, 'R', 1); - } - - // Total LocalTax2 - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on' && $object->total_localtax2>0) - { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalLT2".$mysoc->country_code), $useborder, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_localtax2), $useborder, 'R', 1); - } - } - else - { - if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') - { - //Local tax 1 - foreach($this->localtax1 as $tvakey => $tvaval) + foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -799,27 +878,43 @@ class pdf_azur extends ModelePDFPropales $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT1".$mysoc->pays_code).' '; + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } - - if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') - { - //Local tax 2 - foreach($this->localtax2 as $tvakey => $tvaval) + } + //Local tax 2 after VAT + if (! empty($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION=='localtax2on') + { + foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { + switch ($localtax_type) { + case '2': + case '4': + case '6': + continue 2; + break; + } + foreach( $localtax_rate as $tvakey => $tvaval ) { - if ($tvakey!=0) // On affiche pas taux 0 + if ($tvakey>0) // On affiche pas taux 0 { //$this->atleastoneratenotnull++; $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY ($col1x, $tab2_top + $tab2_hl * $index); $tvacompl=''; if (preg_match('/\*/',$tvakey)) @@ -827,13 +922,21 @@ class pdf_azur extends ModelePDFPropales $tvakey=str_replace('*','',$tvakey); $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")"; } - $totalvat =$outputlangs->transnoentities("TotalLT2".$mysoc->country_code).' '; - $totalvat.=vatrate($tvakey,1).$tvacompl; - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $totalvat = $outputlangs->transnoentities("TotalLT2".$mysoc->pays_code).' '; - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + if ($localtax_type == '7') { // amount on order + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvakey), 0, 'R', 1); + } + else + { + $totalvat.=vatrate($tvakey,1).$tvacompl; + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $pdf->SetXY ($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval), 0, 'R', 1); + } } } } diff --git a/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php b/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php index b0a2b33e2e7..0a723add648 100755 --- a/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php +++ b/htdocs/core/modules/supplier_invoice/pdf/pdf_canelle.modules.php @@ -146,8 +146,6 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $outputlangs->load("bills"); $outputlangs->load("products"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->fournisseur->dir_output.'/facture') { $object->fetch_thirdparty(); @@ -184,6 +182,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $nblignes = count($object->lines); $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -337,6 +336,15 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $this->localtax1[$localtax1rate]+=$localtax1ligne; $this->localtax2[$localtax2rate]+=$localtax2ligne; + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php index fdc97727658..69dcbaf2903 100644 --- a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php @@ -156,8 +156,6 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $outputlangs->load("products"); $outputlangs->load("orders"); - $default_font_size = pdf_getPDFFontSize($outputlangs); - if ($conf->fournisseur->dir_output.'/commande') { $object->fetch_thirdparty(); @@ -196,6 +194,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $nblignes = count($object->lines); $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) @@ -354,6 +353,15 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $this->localtax1[$localtax1rate]+=$localtax1ligne; $this->localtax2[$localtax2rate]+=$localtax2ligne; + // Add line + if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1)) + { + $pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(210,210,210))); + //$pdf->SetDrawColor(190,190,200); + $pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1); + $pdf->SetLineStyle(array('dash'=>0)); + } + $nexY+=2; // Passe espace entre les lignes // Detect if some page were added automatically and output _tableau for past pages diff --git a/htdocs/core/modules/syslog/logHandler.php b/htdocs/core/modules/syslog/logHandler.php index ff889934278..8bce8a0d2a1 100644 --- a/htdocs/core/modules/syslog/logHandler.php +++ b/htdocs/core/modules/syslog/logHandler.php @@ -7,6 +7,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandlerInterface.php'; */ class LogHandler { + protected $ident=0; + + /** * Content of the info tooltip. * @@ -58,4 +61,15 @@ class LogHandler { return array(); } + + /** + * Set current ident. + * + * @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1 + * @return void + */ + public function setIdent($ident) + { + $this->ident+=$ident; + } } \ No newline at end of file diff --git a/htdocs/core/modules/syslog/mod_syslog_file.php b/htdocs/core/modules/syslog/mod_syslog_file.php index 2fce762a848..ab5a1eea74c 100644 --- a/htdocs/core/modules/syslog/mod_syslog_file.php +++ b/htdocs/core/modules/syslog/mod_syslog_file.php @@ -7,6 +7,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/syslog/logHandler.php'; */ class mod_syslog_file extends LogHandler implements LogHandlerInterface { + /** * Return name of logger * @@ -106,6 +107,7 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface * Export the message * * @param array $content Array containing the info about the message + * @param int $ident 1=Increase ident of 1, -1=Decrease ident of 1 * @return void */ public function export($content) @@ -133,7 +135,7 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface LOG_DEBUG => 'DEBUG' ); - $message = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".sprintf("%-5s", $logLevels[$content['level']])." ".sprintf("%-15s", $content['ip'])." ".$content['message']; + $message = dol_print_date(time(),"%Y-%m-%d %H:%M:%S")." ".sprintf("%-5s", $logLevels[$content['level']])." ".sprintf("%-15s", $content['ip'])." ".($this->ident>0?str_pad('',$this->ident,' '):'').$content['message']; fwrite($filefd, $message."\n"); fclose($filefd); diff --git a/htdocs/core/tpl/freeproductline_create.tpl.php b/htdocs/core/tpl/freeproductline_create.tpl.php index 17da725a80d..5b611768119 100644 --- a/htdocs/core/tpl/freeproductline_create.tpl.php +++ b/htdocs/core/tpl/freeproductline_create.tpl.php @@ -1,7 +1,7 @@ - * Copyright (C) 2010-2011 Laurent Destailleur - * Copyright (C) 2012 Christophe Battarel +/* Copyright (C) 2010-2012 Regis Houssin + * Copyright (C) 2010-2011 Laurent Destailleur + * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,13 +50,10 @@
    -" /> +" /> + +> global->MAIN_VIEW_LINE_NUMBER) ? ' colspan="2"' : ''); ?>> @@ -77,8 +74,9 @@ // Editor wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $nbrows=ROWS_2; + $enabled=(! empty($conf->global->FCKEDITOR_ENABLE_DETAILS)?$conf->global->FCKEDITOR_ENABLE_DETAILS:0); if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; - $doleditor=new DolEditor('dp_desc',$_POST["dp_desc"],'',100,'dolibarr_details','',false,true,$conf->global->FCKEDITOR_ENABLE_DETAILS,$nbrows,70); + $doleditor=new DolEditor('dp_desc',GETPOST('dp_desc'),'',100,'dolibarr_details','',false,true,$enabled,$nbrows,70); $doleditor->Create(); ?> diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index fe1525eb6fe..81d446281ae 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -54,7 +54,6 @@ if (isset($conf->modules_parts['css'])) } // JQuery. Must be before other includes $ext='.js'; -if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) $ext='.jgz'; print ''."\n"; if (constant('JS_JQUERY')) print ''."\n"; else print ''."\n"; diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index 5234949629c..460637fedee 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -53,7 +53,6 @@ if (isset($conf->modules_parts['css'])) } // JQuery. Must be before other includes $ext='.js'; -if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) $ext='.jgz'; print ''."\n"; if (constant('JS_JQUERY')) print ''."\n"; else print ''."\n"; diff --git a/htdocs/core/tpl/predefinedproductline_create.tpl.php b/htdocs/core/tpl/predefinedproductline_create.tpl.php index a3dc4f412dc..6897a523b56 100644 --- a/htdocs/core/tpl/predefinedproductline_create.tpl.php +++ b/htdocs/core/tpl/predefinedproductline_create.tpl.php @@ -1,6 +1,6 @@ - * Copyright (C) 2010-2011 Laurent Destailleur + * Copyright (C) 2010-2012 Laurent Destailleur * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify @@ -42,15 +42,14 @@ margin->enabled)) { +if (! empty($conf->margin->enabled)) +{ + if (! empty($conf->global->DISPLAY_MARGIN_RATES)) $colspan++; + if (! empty($conf->global->DISPLAY_MARK_RATES)) $colspan++; ?> -global->DISPLAY_MARGIN_RATES)) - $colspan++; - if (! empty($conf->global->DISPLAY_MARK_RATES)) - $colspan++; -} + @@ -63,7 +62,7 @@ if (! empty($conf->margin->enabled)) { @@ -78,7 +77,7 @@ jQuery(document).ready(function() { if (is_object($hookmanager)) { - $parameters=array('fk_parent_line'=>$_POST["fk_parent_line"]); + $parameters=array('fk_parent_line'=>GETPOST('fk_parent_line','int')); $reshook=$hookmanager->executeHooks('formCreateProductOptions',$parameters,$object,$action); } @@ -87,8 +86,9 @@ jQuery(document).ready(function() { // Editor wysiwyg require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $nbrows=ROWS_2; + $enabled=(! empty($conf->global->FCKEDITOR_ENABLE_DETAILS)?$conf->global->FCKEDITOR_ENABLE_DETAILS:0); if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; - $doleditor=new DolEditor('np_desc',$_POST["np_desc"],'',100,'dolibarr_details','',false,true,$conf->global->FCKEDITOR_ENABLE_DETAILS,$nbrows,70); + $doleditor=new DolEditor('np_desc',GETPOST('np_desc"'),'',100,'dolibarr_details','',false,true,$enabled,$nbrows,70); $doleditor->Create(); ?> @@ -96,34 +96,34 @@ jQuery(document).ready(function() { margin->enabled)) { +if (! empty($conf->margin->enabled)) +{ + if (! empty($conf->global->DISPLAY_MARGIN_RATES)) $colspan++; + if (! empty($conf->global->DISPLAY_MARK_RATES)) $colspan++; ?> + + "> + global->DISPLAY_MARGIN_RATES)) - $colspan++; - if (! empty($conf->global->DISPLAY_MARK_RATES)) - $colspan++; } ?> - + -service->enabled) && $dateSelector) { -if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) - $colspan = 10; -else - $colspan = 9; -if (! empty($conf->margin->enabled)) { - $colspan++; // For the buying price - if (! empty($conf->global->DISPLAY_MARGIN_RATES)) - $colspan++; - if (! empty($conf->global->DISPLAY_MARK_RATES)) - $colspan++; -} +service->enabled) && $dateSelector) +{ + if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) $colspan = 10; + else $colspan = 9; + if (! empty($conf->margin->enabled)) + { + $colspan++; // For the buying price + if (! empty($conf->global->DISPLAY_MARGIN_RATES)) $colspan++; + if (! empty($conf->global->DISPLAY_MARK_RATES)) $colspan++; + } ?> > - + + margin->enabled)) { +if (! empty($conf->margin->enabled)) +{ ?> - + diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index b3e2633fe9d..e3bf26df606 100755 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -127,7 +127,7 @@ class InterfaceActionsAuto $langs->load("other"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("NewCompanyToDolibarr",$object->nom); $object->actionmsg=$langs->transnoentities("NewCompanyToDolibarr",$object->nom); if ($object->prefix) $object->actionmsg.=" (".$object->prefix.")"; @@ -146,7 +146,7 @@ class InterfaceActionsAuto $langs->load("contracts"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("ContractValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("ContractValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -160,7 +160,7 @@ class InterfaceActionsAuto $langs->load("propal"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("PropalValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("PropalValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -174,7 +174,7 @@ class InterfaceActionsAuto $langs->load("propal"); $langs->load("agenda"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("ProposalSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -192,7 +192,7 @@ class InterfaceActionsAuto $langs->load("propal"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("PropalClosedSignedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("PropalClosedSignedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -206,7 +206,7 @@ class InterfaceActionsAuto $langs->load("propal"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("PropalClosedRefusedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("PropalClosedRefusedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -220,7 +220,7 @@ class InterfaceActionsAuto $langs->load("orders"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("OrderValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("OrderValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -234,7 +234,7 @@ class InterfaceActionsAuto $langs->load("orders"); $langs->load("agenda"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("OrderSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -253,7 +253,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoiceValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoiceValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -268,7 +268,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoiceSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -288,7 +288,7 @@ class InterfaceActionsAuto $langs->load("agenda"); // Values for this action can't be defined by caller. - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; $object->actionmsg2=$langs->transnoentities("InvoicePaidInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoicePaidInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -303,7 +303,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoiceCanceledInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoiceCanceledInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -318,7 +318,7 @@ class InterfaceActionsAuto $langs->load("interventions"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InterventionValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InterventionValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -335,7 +335,7 @@ class InterfaceActionsAuto $langs->load("interventions"); $langs->load("agenda"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InterventionSentByEMail",$object->ref); $object->actionmsg=$langs->transnoentities("InterventionSentByEMail",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -351,7 +351,7 @@ class InterfaceActionsAuto $langs->load("sendings"); $langs->load("agenda"); - $object->actiontypecode='AC_SHIP'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("ShippingSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -369,7 +369,7 @@ class InterfaceActionsAuto $langs->load("orders"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("OrderValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("OrderValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -385,7 +385,7 @@ class InterfaceActionsAuto $langs->load("agenda"); $langs->load("orders"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("SupplierOrderSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -404,7 +404,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoiceValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoiceValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -420,7 +420,7 @@ class InterfaceActionsAuto $langs->load("agenda"); $langs->load("orders"); - $object->actiontypecode='AC_EMAIL'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("SupplierInvoiceSentByEMail",$object->ref); if (empty($object->actionmsg)) { @@ -439,7 +439,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoicePaidInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoicePaidInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -454,7 +454,7 @@ class InterfaceActionsAuto $langs->load("bills"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("InvoiceCanceledInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("InvoiceCanceledInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login; @@ -471,7 +471,7 @@ class InterfaceActionsAuto $langs->load("members"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberValidatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("MemberValidatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); @@ -488,7 +488,7 @@ class InterfaceActionsAuto $langs->load("members"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); @@ -511,7 +511,7 @@ class InterfaceActionsAuto $langs->load("members"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberResiliatedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("MemberResiliatedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); @@ -528,7 +528,7 @@ class InterfaceActionsAuto $langs->load("members"); $langs->load("agenda"); - $object->actiontypecode='AC_OTH'; + $object->actiontypecode='AC_OTH_AUTO'; if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberDeletedInDolibarr",$object->ref); $object->actionmsg=$langs->transnoentities("MemberDeletedInDolibarr",$object->ref); $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 1aeede8b5ba..0b36281c825 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -709,12 +709,12 @@ class Expedition extends CommonObject $sql.= " fk_expedition_methode=".((isset($this->expedition_method_id) && $this->expedition_method_id > 0)?$this->expedition_method_id:"null").","; $sql.= " tracking_number=".(isset($this->tracking_number)?"'".$this->db->escape($this->tracking_number)."'":"null").","; $sql.= " fk_statut=".(isset($this->statut)?$this->statut:"null").","; - $sql.= " height=".(isset($this->trueHeight)?$this->trueHeight:"null").","; - $sql.= " width=".(isset($this->trueWidth)?$this->trueWidth:"null").","; + $sql.= " height=".(($this->trueHeight != '')?$this->trueHeight:"null").","; + $sql.= " width=".(($this->trueWidth != '')?$this->trueWidth:"null").","; $sql.= " size_units=".(isset($this->size_units)?$this->size_units:"null").","; - $sql.= " size=".(isset($this->trueDepth)?$this->trueDepth:"null").","; + $sql.= " size=".(($this->trueDepth != '')?$this->trueDepth:"null").","; $sql.= " weight_units=".(isset($this->weight_units)?$this->weight_units:"null").","; - $sql.= " weight=".(isset($this->trueWeight)?$this->trueWeight:"null").","; + $sql.= " weight=".(($this->trueWeight != '')?$this->trueWeight:"null").","; $sql.= " note=".(isset($this->note)?"'".$this->db->escape($this->note)."'":"null").","; $sql.= " model_pdf=".(isset($this->model_pdf)?"'".$this->db->escape($this->model_pdf)."'":"null").","; $sql.= " entity=".$conf->entity; @@ -858,7 +858,8 @@ class Expedition extends CommonObject $sql.= ", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva"; $sql.= ", cd.tva_tx, cd.localtax1_tx, cd.localtax2_tx, cd.price, cd.subprice"; $sql.= ", ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot"; - $sql.= ", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.weight, p.weight_units, p.volume, p.volume_units"; + $sql.= ", p.ref as product_ref, p.label as product_label, p.fk_product_type"; + $sql.= ", p.weight, p.weight_units, p.length, p.length_units, p.surface, p.surface_units, p.volume, p.volume_units"; $sql.= " FROM (".MAIN_DB_PREFIX."expeditiondet as ed,"; $sql.= " ".MAIN_DB_PREFIX."commandedet as cd)"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = cd.fk_product"; @@ -900,6 +901,10 @@ class Expedition extends CommonObject $line->qty_shipped = $obj->qty_shipped; $line->weight = $obj->weight; $line->weight_units = $obj->weight_units; + $line->length = $obj->length; + $line->length_units = $obj->length_units; + $line->surface = $obj->surface; + $line->surface_units = $obj->surface_units; $line->volume = $obj->volume; $line->volume_units = $obj->volume_units; diff --git a/htdocs/expedition/fiche.php b/htdocs/expedition/fiche.php index 363ec801e3a..d3cd793891d 100644 --- a/htdocs/expedition/fiche.php +++ b/htdocs/expedition/fiche.php @@ -285,10 +285,9 @@ else if ($action == 'settrackingnumber' || $action == 'settrackingurl' header("Location: fiche.php?id=".$shipping->id); exit; } - $mesg=$shipping->error; + setEventMessage($shipping->error,'errors'); } - $mesg='
    '.$mesg.'
    '; $action=""; } @@ -537,7 +536,7 @@ else if ($action == 'classifybilled') /* * View -*/ + */ llxHeader('',$langs->trans('Sending'),'Expedition'); @@ -662,6 +661,7 @@ if ($action == 'create') print '\n"; // Tracking number @@ -904,7 +904,7 @@ else /* * Confirmation de la suppression - */ + */ if ($action == 'delete') { $ret=$form->form_confirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$object->ref),'confirm_delete','',0,1); @@ -913,7 +913,7 @@ else /* * Confirmation de la validation - */ + */ if ($action == 'valid') { $objectref = substr($object->ref, 1, 4); @@ -930,15 +930,15 @@ else } /* * Confirmation de l'annulation - */ + */ if ($action == 'annuler') { $ret=$form->form_confirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('CancelSending'),$langs->trans("ConfirmCancelSending",$object->ref),'confirm_cancel','',0,1); if ($ret == 'html') print '
    '; } - // Calculate ture totalVeight and totalVolume for all products - // by adding weight and volume of each line. + // Calculate true totalWeight and totalVolume for all products + // by adding weight and volume of each product line. $totalWeight = ''; $totalVolume = ''; $weightUnit=0; @@ -949,6 +949,7 @@ else $volumeUnit=0; if (! empty($lines[$i]->weight_units)) $weightUnit = $lines[$i]->weight_units; if (! empty($lines[$i]->volume_units)) $volumeUnit = $lines[$i]->volume_units; + // TODO Use a function addvalueunits(val1,unit1,val2,unit2)=>(val,unit) if ($lines[$i]->weight_units < 50) { @@ -973,8 +974,6 @@ else $totalVolume += $lines[$i]->volume*$lines[$i]->qty_shipped; } } - $totalVolume=$totalVolume; - //print "totalVolume=".$totalVolume." volumeUnit=".$volumeUnit; print '
    '.$langs->trans('Ref').''.$langs->trans('Date').''.$langs->trans('Action').''.$langs->trans('By').'
    '.$langs->trans('Ref').''.$langs->trans('Action').''.$langs->trans('Date').''.$langs->trans('By').'
    '.$action->getNomUrl(1).''.$ref.''.$label.''.dol_print_date($action->datep,'day').''.dol_trunc($action->label,32).''; print $langs->trans("Type"); print '  '; - print $formactions->select_type_actions(GETPOST('actioncode'), "actioncode"); + + // print $formactions->select_type_actions(GETPOST('actioncode'), "actioncode"); + print $formactions->select_type_actions(GETPOST('actioncode')?GETPOST('actioncode'):'manual', "actioncode", '', (empty($conf->global->AGENDA_USE_EVENT_TYPE)?1:0)); + print '
     
    trans('ReductionShort'); ?> trans('BuyingPrice'); ?>  
    % - - "> - " name="addline"> + " name="addline"> +
    @@ -135,11 +135,15 @@ if (! empty($conf->margin->enabled)) { ?>
    '; $expe->fetch_delivery_methods(); print $form->selectarray("expedition_method_id",$expe->meths,GETPOST('expedition_method_id','int'),1,0,0,"",1); + if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); print "
    '; @@ -1053,49 +1052,50 @@ else // Weight print ''; - // Volume Total - print ''; - print '\n"; - print ''; - // Width print ''; // Height print ''; // Depth print ''; + // Volume + print ''; + print '\n"; + print ''; + // Status print ''; print '\n"; @@ -1117,6 +1117,7 @@ else print ''; $object->fetch_delivery_methods(); print $form->selectarray("expedition_method_id",$object->meths,$object->expedition_method_id,1,0,0,"",1); + if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); print ''; print ''; } diff --git a/htdocs/exports/class/export.class.php b/htdocs/exports/class/export.class.php index c3098c38a87..721a0c94e52 100644 --- a/htdocs/exports/class/export.class.php +++ b/htdocs/exports/class/export.class.php @@ -202,10 +202,9 @@ class Export * @param int $indice Indice of export * @param array $array_selected Filter on array of fields to export * @param array $array_filterValue Filter on array of fields to export - * @param array $array_filtered Array with filters values * @return string SQL String. Example "select s.rowid as r_rowid, s.status as s_status from ..." */ - function build_sql($indice, $array_selected, $array_filterValue, $array_filtered) + function build_sql($indice, $array_selected, $array_filterValue) { // Build the sql request $sql=$this->array_export_sql_start[$indice]; @@ -225,16 +224,13 @@ class Export $sql.=$this->array_export_sql_end[$indice]; //construction du filtrage si le parametrage existe - if (is_array($array_filtered)) + if (is_array($array_filterValue)) { $sqlWhere=''; // pour ne pas a gerer le nombre de condition - foreach ($array_filtered as $key => $value) + foreach ($array_filterValue as $key => $value) { - if ($array_filterValue[$key]) - { - $sqlWhere.=" and ".$this->build_filterQuery($this->array_export_TypeFields[0][$key], $key, $array_filterValue[$key]); - } + $sqlWhere.=" and ".$this->build_filterQuery($this->array_export_TypeFields[0][$key], $key, $array_filterValue[$key]); } $sql.=$sqlWhere; } @@ -257,18 +253,18 @@ class Export // build the input field on depend of the type of file switch ($InfoFieldList[0]) { case 'Text': - if (strpos($ValueField, "%") > 0) - $szFilterQuery=" ".$NameField." like '".$ValueField."'"; + if (! (strpos($ValueField, '%') === false)) + $szFilterQuery.=" ".$NameField." LIKE '".$ValueField."'"; else - $szFilterQuery=" ".$NameField."='".$ValueField."'"; + $szFilterQuery.=" ".$NameField."='".$ValueField."'"; break; case 'Date': if (strpos($ValueField, "+") > 0) { // mode plage $ValueArray = explode("+", $ValueField); - $szFilterQuery= $this->conditionDate($NameField,$ValueArray[0],">="); - $szFilterQuery.=" and ".$this->conditionDate($NameField,$ValueArray[1],"<="); + $szFilterQuery ="(".$this->conditionDate($NameField,$ValueArray[0],">="); + $szFilterQuery.=" AND ".$this->conditionDate($NameField,$ValueArray[1],"<=").")"; } else { @@ -286,8 +282,8 @@ class Export { // mode plage $ValueArray = explode("+", $ValueField); - $szFilterQuery=$NameField.">=".$ValueArray[0]; - $szFilterQuery.=" and ".$NameField."<=".$ValueArray[1]; + $szFilterQuery ="(".$NameField.">=".$ValueArray[0]; + $szFilterQuery.=" AND ".$NameField."<=".$ValueArray[1].")"; } else { @@ -297,8 +293,10 @@ class Export $szFilterQuery=" ".$NameField.substr($ValueField,0,1).substr($ValueField,1); } break; - case 'Status': case 'Boolean': + $szFilterQuery=" ".$NameField."=".(is_numeric($ValueField) ? $ValueField : ($ValueField =='yes' ? 1: 0) ); + break; + case 'Status': case 'List': if (is_numeric($ValueField)) $szFilterQuery=" ".$NameField."=".$ValueField; @@ -339,8 +337,10 @@ class Export { $szFilterField=''; $InfoFieldList = explode(":", $TypeField); + // build the input field on depend of the type of file - switch ($InfoFieldList[0]) { + switch ($InfoFieldList[0]) + { case 'Text': case 'Date': case 'Duree': @@ -348,18 +348,18 @@ class Export $szFilterField='"; break; case 'Boolean': - $szFilterField="'; $szFilterField.=''; $szFilterField.=''; $szFilterField.=""; break; case 'List': @@ -387,6 +387,13 @@ class Export while ($i < $num) { $obj = $this->db->fetch_object($resql); + if ($obj->$InfoFieldList[2] == '-') + { + // Discard entry '-' + $i++; + continue; + } + $labeltoshow=dol_trunc($obj->$InfoFieldList[2],18); if (!empty($ValueField) && $ValueField == $obj->rowid) { @@ -401,7 +408,7 @@ class Export } $szFilterField.=""; - $this->db->close(); + $this->db->free(); } break; } @@ -457,11 +464,10 @@ class Export * @param string $datatoexport Name of dataset to export * @param array $array_selected Filter on array of fields to export * @param array $array_filterValue Filter on array of fields with a filter - * @param array $array_filtered Values of filters * @param string $sqlquery If set, transmit a sql query instead of building it from arrays * @return int <0 if KO, >0 if OK */ - function build_file($user, $model, $datatoexport, $array_selected, $array_filterValue, $array_filtered, $sqlquery = '') + function build_file($user, $model, $datatoexport, $array_selected, $array_filterValue, $sqlquery = '') { global $conf,$langs; @@ -485,7 +491,7 @@ class Export $objmodel = new $classname($this->db); if (! empty($sqlquery)) $sql = $sqlquery; - else $sql=$this->build_sql($indice, $array_selected, $array_filterValue, $array_filtered); + else $sql=$this->build_sql($indice, $array_selected, $array_filterValue); // Run the sql $this->sqlusedforexport=$sql; diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index 386be209cb3..6ffcc39e1c8 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -58,6 +58,8 @@ $entitytoicon = array( 'product' => 'product', 'warehouse' => 'stock', 'category' => 'category', + 'shipment' => 'sending', + 'shipment_line'=> 'sending' ); // Translation code @@ -86,11 +88,12 @@ $entitytolang = array( 'warehouse' => 'Warehouse', 'category' => 'Category', 'other' => 'Other', - 'trip' => 'TripsAndExpenses' + 'trip' => 'TripsAndExpenses', + 'shipment' => 'Shipments', + 'shipment_line'=> 'ShipmentLine' ); $array_selected=isset($_SESSION["export_selected_fields"])?$_SESSION["export_selected_fields"]:array(); -$array_filtered=isset($_SESSION["export_filtered_fields"])?$_SESSION["export_filtered_fields"]:array(); $array_filtervalue=isset($_SESSION["export_FilterValue_fields"])?$_SESSION["export_FilterValue_fields"]:array(); $datatoexport=GETPOST("datatoexport"); $action=GETPOST('action', 'alpha'); @@ -112,8 +115,8 @@ $sqlusedforexport=''; $upload_dir = $conf->export->dir_temp.'/'.$user->id; -$usefilters=($conf->global->MAIN_FEATURES_LEVEL > 1); -//$usefilters=1; +//$usefilters=($conf->global->MAIN_FEATURES_LEVEL > 1); +$usefilters=1; /* @@ -185,53 +188,6 @@ if ($action=='unselectfield') } } -/* -if ($action=='selectFilterfield') -{ - if ($_GET["field"]=='all') - { - $fieldsarray=$objexport->array_export_TypeFields[0]; - foreach($fieldsarray as $key=>$val) - { - if (! empty($array_filtered[$key])) continue; // If already selected, select next - $array_filtered[$key]=count($array_filtered)+1; - //print_r($array_selected); - $_SESSION["export_filtered_fields"]=$array_filtered; - } - } - else - { - $array_filtered[$_GET["field"]]=count($array_filtered)+1; - //print_r($array_selected); - $_SESSION["export_filtered_fields"]=$array_filtered; - } -} - -if ($action=='unselectFilterfield') -{ - if ($_GET["field"]=='all') - { - $array_filtered=array(); - $_SESSION["export_filtered_fields"]=$array_filtered; - } - else - { - unset($array_filtered[$_GET["field"]]); - // Renumber fields of array_selected (from 1 to nb_elements) - asort($array_filtered); - $i=0; - $array_filterted_save=$array_filtered; - foreach($array_filtered as $code=>$value) - { - $i++; - $array_filtered[$code]=$i; - //print "x $code x $i y
    "; - } - $_SESSION["export_filtered_fields"]=$array_filtered; - } -} -*/ - if ($action=='downfield' || $action=='upfield') { $pos=$array_selected[$_GET["field"]]; @@ -259,24 +215,23 @@ if ($action=='downfield' || $action=='upfield') if ($step == 1 || $action == 'cleanselect') { $_SESSION["export_selected_fields"]=array(); - $_SESSION["export_FilterValue_fields"]=array(); + //$_SESSION["export_FilterValue_fields"]=array(); $_SESSION["export_filtered_fields"]=array(); $array_selected=array(); $array_filtervalue=array(); - $array_filtered=array(); } if ($action == 'builddoc') { // Build export file - $result=$objexport->build_file($user, $_POST['model'], $datatoexport, $array_selected, $array_filtervalue, $array_filtered); + $result=$objexport->build_file($user, $_POST['model'], $datatoexport, $array_selected, $array_filtervalue); if ($result < 0) { - $mesg='
    '.$objexport->error.'
    '; + setEventMessage($objexport->error, 'errors'); } else { - $mesg='
    '.$langs->trans("FileSuccessfullyBuilt").'
    '; + setEventMessage($langs->trans("FileSuccessfullyBuilt")); $sqlusedforexport=$objexport->sqlusedforexport; } } @@ -302,6 +257,7 @@ if ($action == 'deleteprof') } } +// TODO The export for filter is not yet implemented (old code created conflicts with step 2). We must use same way of working and same combo list of predefined export than step 2. if ($action == 'add_export_model') { if ($export_name) @@ -316,51 +272,44 @@ if ($action == 'add_export_model') $hexa.=$key; } - $hexafilter=''; $hexafiltervalue=''; - foreach($array_filtered as $key=>$val) + foreach($array_filtervalue as $key=>$val) { - if ($hexafilter) $hexafilter.=','; if ($hexafilter) $hexafiltervalue.=','; - $hexafilter.=$key; - $hexafiltervalue.=$array_filtervalue[$key]; + $hexafiltervalue.=$key.'='.$val; } $objexport->model_name = $export_name; $objexport->datatoexport = $datatoexport; $objexport->hexa = $hexa; - $objexport->hexafilter = $hexafilter; $objexport->hexafiltervalue = $hexafiltervalue; $result = $objexport->create($user); if ($result >= 0) { - $mesg='
    '.$langs->trans("ExportModelSaved",$objexport->model_name).'
    '; + setEventMessage($langs->trans("ExportModelSaved",$objexport->model_name)); } else { $langs->load("errors"); if ($objexport->errno == 'DB_ERROR_RECORD_ALREADY_EXISTS') - { - $mesg='
    '.$langs->trans("ErrorExportDuplicateProfil").'
    '; - } - else $mesg='
    '.$objexport->error.'
    '; + setEventMessage($langs->trans("ErrorExportDuplicateProfil"), 'errors'); + else + setEventMessage($objexport->error, 'errors'); } } else { - $mesg='
    '.$langs->trans("ErrorFieldRequired",$langs->transnoentities("ExportModelName")).'
    '; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("ExportModelName")), 'errors'); } } if ($step == 2 && $action == 'select_model') { $_SESSION["export_selected_fields"]=array(); - $_SESSION["export_filtered_fields"]=array(); $_SESSION["export_FilterValue_fields"]=array(); $array_selected=array(); - $array_filtered=array(); $array_filtervalue=array(); $result = $objexport->fetch($exportmodelid); @@ -380,29 +329,37 @@ if ($step == 2 && $action == 'select_model') $i=1; foreach($fieldsarray as $val) { - $array_filtered[$val]=$i; - $array_filtervalue[$val]=$fieldsarrayvalue[$i-1]; + $tmp=explode('=',$val); + $array_filtervalue[$tmp[0]]=$tmp[1]; $i++; } - $_SESSION["export_filtered_fields"]=$array_filtered; $_SESSION["export_FilterValue_fields"]=$array_filtervalue; } } -// recuperation du filtrage issu du formulaire +// Get form with filters if ($step == 4 && $action == 'submitFormField') { // on boucle sur les champs selectionne pour recuperer la valeur if (is_array($objexport->array_export_TypeFields[0])) { $_SESSION["export_FilterValue_fields"]=array(); - foreach($array_filtered as $code=>$value) + //var_dump($_POST); + foreach($objexport->array_export_TypeFields[0] as $code => $type) // $code: s.fieldname $value: Text|Boolean|List:ccc { - //print $code."=".$_POST[$objexport->array_export_fields[0][$code]]; - $objexport->array_export_FilterValue[0][$code] = (isset($objexport->array_export_fields[0][$code])?$_POST[$objexport->array_export_fields[0][$code]]:''); + $newcode=(string) preg_replace('/\./','_',$code); + //print 'xxx'.$code."=".$newcode."=".$type."=".$_POST[$newcode]."\n
    "; + $filterqualified=1; + if (! isset($_POST[$newcode]) || $_POST[$newcode] == '') $filterqualified=0; + elseif (preg_match('/^List/',$type) && (is_numeric($_POST[$newcode]) && $_POST[$newcode] <= 0)) $filterqualified=0; + if ($filterqualified) + { + //print 'Filter on '.$newcode.' type='.$type.' value='.$_POST[$newcode]."\n"; + $objexport->array_export_FilterValue[0][$code] = $_POST[$newcode]; + } } - $_SESSION["export_FilterValue_fields"]=(! empty($objexport->array_export_FilterValue[0])?$objexport->array_export_FilterValue[0]:''); $array_filtervalue=(! empty($objexport->array_export_FilterValue[0])?$objexport->array_export_FilterValue[0]:''); + $_SESSION["export_FilterValue_fields"]=$array_filtervalue; } } @@ -411,7 +368,6 @@ if ($step == 4 && $action == 'submitFormField') * View */ - if ($step == 1 || ! $datatoexport) { llxHeader('',$langs->trans("NewExport"),'EN:Module_Exports_En|FR:Module_Exports|ES:Módulo_Exportaciones'); @@ -482,9 +438,6 @@ if ($step == 1 || ! $datatoexport) print '
    '.$form->editfieldkey("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer).''; print $form->editfieldval("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer); - print $object->weight_units?measuring_units_string($object->weight_units,"weight"):''; + print ($object->trueWeight && $object->weight_units!='')?' '.measuring_units_string($object->weight_units,"weight"):''; print '
    '.$langs->trans("Volume").''; - if (! empty($object->trueVolume)) // FIXME trueVolume not exist - { - // If sending volume defined - print $object->trueVolume.' '.measuring_units_string($object->volumeUnit,"volume"); - } - else - { - // If sending volume not defined we use sum of products - if ($totalVolume > 0) - { - print $totalVolume.' '; - if ($volumeUnit < 50) print measuring_units_string(0,"volume"); - else print measuring_units_string($volumeUnit,"volume"); - } - else print ' '; - } - print "
    '.$form->editfieldkey("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer).''; print $form->editfieldval("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer); - print $object->trueWidth?measuring_units_string($object->width_units,"size"):''; + print ($object->trueWidth && $object->width_units!='')?' '.measuring_units_string($object->width_units,"size"):''; print '
    '.$form->editfieldkey("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer).''; print $form->editfieldval("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer); - print $object->trueHeight?measuring_units_string($object->height_units,"size"):''; + print ($object->trueHeight && $object->height_units!='')?' '.measuring_units_string($object->height_units,"size"):''; print '
    '.$form->editfieldkey("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer).''; print $form->editfieldval("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer); - print $object->trueDepth?measuring_units_string($object->depth_units,"size"):''; + print ($object->trueDepth && $object->depth_units!='')?' '.measuring_units_string($object->depth_units,"size"):''; print '
    '; + print $langs->trans("Volume"); + print ''; + $calculatedVolume=0; + if ($object->trueWidth && $object->trueHeight && $object->trueDepth) $calculatedVolume=($object->trueWidth * $object->trueHeight * $object->trueDepth); + // If sending volume not defined we use sum of products + if ($calculatedVolume > 0) + { + print $calculatedVolume.' '; + if ($volumeUnit < 50) print measuring_units_string(0,"volume"); + else print measuring_units_string($volumeUnit,"volume"); + } + if ($totalVolume > 0) + { + if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': '; + print $totalVolume; + if ($calculatedVolume) print ')'; + } + print "
    '.$langs->trans("Status").''.$object->getLibStatut(4)."
    '; print ''; - - if ($mesg) print $mesg; - } if ($step == 2 && $datatoexport) @@ -562,7 +515,7 @@ if ($step == 2 && $datatoexport) // Champs exportables $fieldsarray=$objexport->array_export_fields[0]; // Select request if all fields are selected - $sqlmaxforexport=$objexport->build_sql(0, array(), array(), array()); + $sqlmaxforexport=$objexport->build_sql(0, array(), array()); // $this->array_export_module[0]=$module; // $this->array_export_code[0]=$module->export_code[$r]; @@ -630,8 +583,6 @@ if ($step == 2 && $datatoexport) print ''; - if ($mesg) print $mesg; - /* * Barre d'action * @@ -737,7 +688,7 @@ if ($step == 3 && $datatoexport) // valeur des filtres $ValueFiltersarray=(! empty($objexport->array_export_FilterValue[0])?$objexport->array_export_FilterValue[0]:''); // Select request if all fields are selected - $sqlmaxforexport=$objexport->build_sql(0, array(), array(), array()); + $sqlmaxforexport=$objexport->build_sql(0, array(), array()); $var=true; $i = 0; @@ -763,6 +714,7 @@ if ($step == 3 && $datatoexport) print img_object('',$entityicon).' '.$langs->trans($entitylang); print ''; + // Field name $labelName=(! empty($fieldsarray[$code])?$fieldsarray[$code]:''); $ValueFilter=(! empty($array_filtervalue[$code])?$array_filtervalue[$code]:''); $text=$langs->trans($labelName); @@ -773,11 +725,13 @@ if ($step == 3 && $datatoexport) print ''; print $form->textwithpicto($text,$htmltext); print ''; + + // Filter value print ''; if (! empty($Typefieldsarray[$code])) { $szInfoFiltre=$objexport->genDocFilter($Typefieldsarray[$code]); - if ($szInfoFiltre) + if ($szInfoFiltre) // Is there an info help for this filter ? { $tmp=$objexport->build_filterField($Typefieldsarray[$code], $code, $ValueFilter); print $form->textwithpicto($tmp, $szInfoFiltre); @@ -796,12 +750,9 @@ if ($step == 3 && $datatoexport) print ''; - if ($mesg) print $mesg; - /* * Barre d'action - * - */ + */ print '
    '; // il n'est pas obligatoire de filtrer les champs print ''.$langs->trans("NextStep").''; @@ -861,7 +812,7 @@ if ($step == 4 && $datatoexport) print $objexport->array_export_label[0]; print ''; - // Nbre champs exportes + // List of exported fields print ''.$langs->trans("ExportedFields").''; $list=''; foreach($array_selected as $code=>$value) @@ -869,28 +820,31 @@ if ($step == 4 && $datatoexport) $list.=($list?', ':''); $list.=$langs->trans($objexport->array_export_fields[0][$code]); } - print ''.$list.''; + print ''.$list.''; + print ''; - // Number of filtered fields + // List of filtered fiels if (isset($objexport->array_export_TypeFields[0]) && is_array($objexport->array_export_TypeFields[0])) { print ''.$langs->trans("FilteredFields").''; $list=''; - foreach($array_filtered as $code=>$value) + foreach($array_filtervalue as $code=>$value) { - if (isset($objexport->array_export_fields[0][$code])) { + if (isset($objexport->array_export_fields[0][$code])) + { $list.=($list?', ':''); - $list.="[".$langs->trans($objexport->array_export_fields[0][$code])."]='".(isset($array_filtervalue[$code])?$array_filtervalue[$code]:'')."'"; + $list.=$langs->trans($objexport->array_export_fields[0][$code])."='".(isset($array_filtervalue[$code])?$array_filtervalue[$code]:'')."'"; } } - print ''.$list.''; + print ''.($list?$list:$langs->trans("None")).''; + print ''; } print ''; print '
    '; // Select request if all fields are selected - $sqlmaxforexport=$objexport->build_sql(0, array(), array(), array()); + $sqlmaxforexport=$objexport->build_sql(0, array(), array()); print $langs->trans("ChooseFieldsOrdersAndTitle").'
    '; @@ -948,11 +902,8 @@ if ($step == 4 && $datatoexport) print ''; - print '
    '; - if ($mesg) print $mesg; - /* * Barre d'action * @@ -1023,7 +974,6 @@ if ($step == 4 && $datatoexport) print ''; print ''; } - } if ($step == 5 && $datatoexport) @@ -1091,7 +1041,7 @@ if ($step == 5 && $datatoexport) print $objexport->array_export_label[0]; print ''; - // Nbre champs exportes + // List of exported fields print ''.$langs->trans("ExportedFields").''; $list=''; foreach($array_selected as $code=>$label) @@ -1101,19 +1051,21 @@ if ($step == 5 && $datatoexport) } print ''.$list.''; - // Nbre champs filtres - if (is_array($objexport->array_export_TypeFields[0])) + // List of filtered fiels + if (isset($objexport->array_export_TypeFields[0]) && is_array($objexport->array_export_TypeFields[0])) { print ''.$langs->trans("FilteredFields").''; $list=''; - foreach($array_filtered as $code=>$value) + foreach($array_filtervalue as $code=>$value) { - if (isset($objexport->array_export_fields[0][$code])) { + if (isset($objexport->array_export_fields[0][$code])) + { $list.=($list?', ':''); - $list.="[".$langs->trans($objexport->array_export_fields[0][$code])."]='".(isset($array_filtervalue[$code])?$array_filtervalue[$code]:'')."'"; + $list.=$langs->trans($objexport->array_export_fields[0][$code])."='".(isset($array_filtervalue[$code])?$array_filtervalue[$code]:'')."'"; } } - print ''.$list.''; + print ''.($list?$list:$langs->trans("None")).''; + print ''; } print ''; @@ -1145,12 +1097,7 @@ if ($step == 5 && $datatoexport) print ''; print ''; - if ($mesg) - { - print ''; - } + if ($sqlusedforexport && $user->admin) { print '
    '; - print $mesg; - print '
    '; @@ -1171,14 +1118,12 @@ if ($step == 5 && $datatoexport) print '
    '; } - print '
    '; +llxFooter(); $db->close(); -llxFooter(); - /** * Return table name of an alias. For this, we look for the "tablename as alias" in sql string. diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 62eec4ebaaf..ba260ea4f19 100755 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -207,6 +207,7 @@ define('MAIN_DB_PREFIX',$dolibarr_main_db_prefix); // Path to root libraries if (! defined('ADODB_PATH')) { define('ADODB_PATH', (!isset($dolibarr_lib_ADODB_PATH))?DOL_DOCUMENT_ROOT.'/includes/adodbtime/':(empty($dolibarr_lib_ADODB_PATH)?'':$dolibarr_lib_ADODB_PATH.'/')); } if (! defined('TCPDF_PATH')) { define('TCPDF_PATH', (!isset($dolibarr_lib_TCPDF_PATH))?DOL_DOCUMENT_ROOT.'/includes/tcpdf/':(empty($dolibarr_lib_TCPDF_PATH)?'':$dolibarr_lib_TCPDF_PATH.'/')); } +if (! defined('FPDF_PATH')) { define('FPDF_PATH', (!isset($dolibarr_lib_FPDF_PATH))?DOL_DOCUMENT_ROOT.'/includes/fpdf/':(empty($dolibarr_lib_FPDF_PATH)?'':$dolibarr_lib_FPDF_PATH.'/')); } // Used only for package that can't include tcpdf if (! defined('FPDI_PATH')) { define('FPDI_PATH', (!isset($dolibarr_lib_FPDI_PATH))?DOL_DOCUMENT_ROOT.'/includes/fpdfi/':(empty($dolibarr_lib_FPDI_PATH)?'':$dolibarr_lib_FPDI_PATH.'/')); } if (! defined('NUSOAP_PATH')) { define('NUSOAP_PATH', (!isset($dolibarr_lib_NUSOAP_PATH))?DOL_DOCUMENT_ROOT.'/includes/nusoap/lib/':(empty($dolibarr_lib_NUSOAP_PATH)?'':$dolibarr_lib_NUSOAP_PATH.'/')); } if (! defined('PHPEXCEL_PATH')) { define('PHPEXCEL_PATH', (!isset($dolibarr_lib_PHPEXCEL_PATH))?DOL_DOCUMENT_ROOT.'/includes/phpexcel/':(empty($dolibarr_lib_PHPEXCEL_PATH)?'':$dolibarr_lib_PHPEXCEL_PATH.'/')); } diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index d8eaef777ad..079149dd240 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -889,7 +889,7 @@ class CommandeFournisseur extends CommonOrder dol_syslog(get_class($this)."::commande sql=".$sql, LOG_DEBUG); if ($this->db->query($sql)) { - $result = 0; + $result = 1; $this->log($user, 3, $date, $comment); } else @@ -954,34 +954,67 @@ class CommandeFournisseur extends CommonOrder { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."commande_fournisseur"); - $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur"; - $sql.= " SET ref='(PROV".$this->id.")'"; - $sql.= " WHERE rowid=".$this->id; - dol_syslog(get_class($this)."::create sql=".$sql); - if ($this->db->query($sql)) - { - // On logue creation pour historique - $this->log($user, 0, time()); + if ($this->id) { + $num=count($this->lines); - if (! $notrigger) - { - // Appel des triggers - include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; - $interface=new Interfaces($this->db); - $result=$interface->run_triggers('ORDER_SUPPLIER_CREATE',$this,$user,$langs,$conf); - if ($result < 0) { $error++; $this->errors=$interface->errors; } - // Fin appel triggers - } + /* + * Insertion du detail des produits dans la base + */ + for ($i=0;$i<$num;$i++) + { + $result = $this->addline( + $this->lines[$i]->desc, + $this->lines[$i]->subprice, + $this->lines[$i]->qty, + $this->lines[$i]->tva_tx, + $this->lines[$i]->localtax1_tx, + $this->lines[$i]->localtax2_tx, + $this->lines[$i]->fk_product, + 0, + $this->lines[$i]->ref_fourn, + $this->lines[$i]->remise_percent, + 'HT', + 0, + $this->lines[$i]->info_bits + ); + if ($result < 0) + { + $this->error=$this->db->lasterror(); + dol_print_error($this->db); + $this->db->rollback(); + return -1; + } + } - $this->db->commit(); - return $this->id; - } - else - { - $this->error=$this->db->error(); - dol_syslog(get_class($this)."::create: Failed -2 - ".$this->error, LOG_ERR); - $this->db->rollback(); - return -2; + $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur"; + $sql.= " SET ref='(PROV".$this->id.")'"; + $sql.= " WHERE rowid=".$this->id; + dol_syslog(get_class($this)."::create sql=".$sql); + if ($this->db->query($sql)) + { + // On logue creation pour historique + $this->log($user, 0, time()); + + if (! $notrigger) + { + // Appel des triggers + include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + $interface=new Interfaces($this->db); + $result=$interface->run_triggers('ORDER_SUPPLIER_CREATE',$this,$user,$langs,$conf); + if ($result < 0) { $error++; $this->errors=$interface->errors; } + // Fin appel triggers + } + + $this->db->commit(); + return $this->id; + } + else + { + $this->error=$this->db->error(); + dol_syslog(get_class($this)."::create: Failed -2 - ".$this->error, LOG_ERR); + $this->db->rollback(); + return -2; + } } } else @@ -993,6 +1026,69 @@ class CommandeFournisseur extends CommonOrder } } + /** + * Load an object from its id and create a new one in database + * + * @param HookManager $hookmanager Hook manager instance + * @return int New id of clone + */ + function createFromClone($hookmanager=false) + { + global $conf,$user,$langs; + + $error=0; + + $this->db->begin(); + + // Load source object + $objFrom = dol_clone($this); + + $this->id=0; + $this->statut=0; + + // Clear fields + $this->user_author_id = $user->id; + $this->user_valid = ''; + $this->date_creation = ''; + $this->date_validation = ''; + $this->ref_supplier = ''; + + // Create clone + $result=$this->create($user); + if ($result < 0) $error++; + + if (! $error) + { + // Hook of thirdparty module + if (is_object($hookmanager)) + { + $parameters=array('objFrom'=>$objFrom); + $action=''; + $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) $error++; + } + + // Appel des triggers + include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + $interface=new Interfaces($this->db); + $result=$interface->run_triggers('ORDER_SUPPLIER_CLONE',$this,$user,$langs,$conf); + if ($result < 0) { $error++; $this->errors=$interface->errors; } + // Fin appel triggers + } + + // End + if (! $error) + { + $this->db->commit(); + return $this->id; + } + else + { + $this->db->rollback(); + return -1; + } + } + /** * Add order line * @@ -1026,6 +1122,7 @@ class CommandeFournisseur extends CommonOrder if (empty($txtva)) $txtva=0; if (empty($txlocaltax1)) $txlocaltax1=0; if (empty($txlocaltax2)) $txlocaltax2=0; + if (empty($remise_percent)) $remise_percent=0; $remise_percent=price2num($remise_percent); $qty=price2num($qty); @@ -1044,7 +1141,6 @@ class CommandeFournisseur extends CommonOrder } $desc=trim($desc); - // Check parameters if ($qty < 1 && ! $fk_product) { @@ -1053,7 +1149,6 @@ class CommandeFournisseur extends CommonOrder } if ($type < 0) return -1; - if ($this->statut == 0) { $this->db->begin(); @@ -1111,7 +1206,7 @@ class CommandeFournisseur extends CommonOrder $subprice = price2num($pu,'MU'); $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseurdet"; - $sql.= " (fk_commande,label, description,"; + $sql.= " (fk_commande, label, description,"; $sql.= " fk_product, product_type,"; $sql.= " qty, tva_tx, localtax1_tx, localtax2_tx, remise_percent, subprice, ref,"; $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc"; @@ -1712,24 +1807,19 @@ class CommandeFournisseur extends CommonOrder $now=dol_now(); - // Charge tableau des produits prodids - $prodids = array(); - + // Find first product + $prodid=0; + $product=new ProductFournisseur($db); $sql = "SELECT rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."product"; $sql.= " WHERE entity IN (".getEntity('product', 1).")"; - + $sql.=$this->db->order("rowid","ASC"); + $sql.=$this->db->plimit(1); $resql = $this->db->query($sql); if ($resql) { - $num_prods = $this->db->num_rows($resql); - $i = 0; - while ($i < $num_prods) - { - $i++; - $row = $this->db->fetch_row($resql); - $prodids[$i] = $row[0]; - } + $obj = $this->db->fetch_object($resql); + $prodid = $obj->rowid; } // Initialise parametres @@ -1771,9 +1861,7 @@ class CommandeFournisseur extends CommonOrder $line->total_tva=19.6; $line->remise_percent=00; } - $line->ref_fourn='SUPPLIER_REF_'.$xnbp; - $prodid = rand(1, $num_prods); - $line->fk_product=$prodids[$prodid]; + $line->fk_product=$prodid; $this->lines[$xnbp]=$line; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 0ac846810a9..c01815816c4 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -30,8 +30,7 @@ include_once DOL_DOCUMENT_ROOT.'/core/class/commoninvoice.class.php'; /** - * \class FactureFournisseur - * \brief Class to manage suppliers invoices + * Class to manage suppliers invoices */ class FactureFournisseur extends CommonInvoice { @@ -618,6 +617,8 @@ class FactureFournisseur extends CommonInvoice // We remove directory if ($conf->fournisseur->facture->dir_output) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $ref = dol_sanitizeFileName($this->ref); $dir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2).$ref; $file = $dir . "/" . $ref . ".pdf"; @@ -632,6 +633,7 @@ class FactureFournisseur extends CommonInvoice if (file_exists($dir)) { $res=@dol_delete_dir_recursive($dir); + if (! $res) { $this->error='ErrorFailToDeleteDir'; diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 3c238369924..5a06857e201 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -30,8 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; /** - * \class ProductFournisseur - * \brief Class to manage predefined suppliers products + * Class to manage predefined suppliers products */ class ProductFournisseur extends Product { @@ -146,7 +145,7 @@ class ProductFournisseur extends Product * @param string $charges costs affering to product * @param float $remise_percent Discount regarding qty (percent) * @param float $remise Discount regarding qty (amount) - * @return int >0 if KO, >0 if OK + * @return int <0 if KO, >=0 if OK */ function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0) { diff --git a/htdocs/fourn/commande/fiche.php b/htdocs/fourn/commande/fiche.php index c57d9e12bfc..e7e4c1d6161 100644 --- a/htdocs/fourn/commande/fiche.php +++ b/htdocs/fourn/commande/fiche.php @@ -73,18 +73,31 @@ include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager=new HookManager($db); $hookmanager->initHooks(array('ordersuppliercard')); -$mesg=''; -$errors=array(); - $object = new CommandeFournisseur($db); +// Load object +if ($id > 0 || ! empty($ref)) +{ + $ret = $object->fetch($id, $ref); + if ($ret < 0) dol_print_error($db,$object->error); + $ret = $object->fetch_thirdparty(); + if ($ret < 0) dol_print_error($db,$object->error); +} +else if (! empty($socid)) +{ + $fourn = new Fournisseur($db); + $ret=$fourn->fetch($socid); + if ($ret < 0) dol_print_error($db,$object->error); + $object->socid = $fourn->id; + $ret = $object->fetch_thirdparty(); + if ($ret < 0) dol_print_error($db,$object->error); +} /* * Actions */ if ($action == 'setref_supplier' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result=$object->setValueFrom('ref_supplier',GETPOST('ref_supplier','alpha')); if ($result < 0) dol_print_error($db, $object->error); } @@ -92,14 +105,12 @@ if ($action == 'setref_supplier' && $user->rights->fournisseur->commande->creer) // conditions de reglement if ($action == 'setconditions' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result=$object->setPaymentTerms(GETPOST('cond_reglement_id','int')); } // mode de reglement else if ($action == 'setmode' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result = $object->setPaymentMethods(GETPOST('mode_reglement_id','int')); } @@ -108,44 +119,38 @@ if ($action == 'setdate_livraison' && $user->rights->fournisseur->commande->cree { $datelivraison=dol_mktime(0, 0, 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int')); - $object->fetch($id); $result=$object->set_date_livraison($user,$datelivraison); if ($result < 0) { - $mesg='
    '.$object->error.'
    '; + setEventMessage($object->error, 'errors'); } } // Set project else if ($action == 'classin' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $object->setProject($projectid); } else if ($action == 'setremisepercent' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result = $object->set_remise($user, $_POST['remise_percent']); } else if ($action == 'setnote_public' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result=$object->update_note_public(dol_html_entity_decode(GETPOST('note_public'), ENT_QUOTES)); if ($result < 0) dol_print_error($db,$object->error); } else if ($action == 'setnote' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result=$object->update_note(dol_html_entity_decode(GETPOST('note'), ENT_QUOTES)); if ($result < 0) dol_print_error($db,$object->error); } else if ($action == 'reopen' && $user->rights->fournisseur->commande->approuver) { - $result = $object->fetch($id); if (in_array($object->statut, array(1, 5, 6, 7, 9))) { if ($object->statut == 1) $newstatus=0; // Validated->Draft @@ -173,46 +178,43 @@ else if ($action == 'reopen' && $user->rights->fournisseur->commande->approuver) else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) { $langs->load('errors'); - $error = false; + $error = 0; - if ($_POST['pu'] < 0 && $_POST['qty'] < 0) + if (GETPOST('pu') < 0 && GETPOST('qty') < 0) { setEventMessage($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPrice'), $langs->transnoentitiesnoconv('Qty')), 'errors'); - $error = true; + $error++; } - if (empty($_POST['idprodfournprice']) && $_POST['type'] < 0) + if (! GETPOST('idprodfournprice') && GETPOST('type') < 0) { setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), 'errors'); - $error = true; + $error++; } - if (empty($_POST['idprodfournprice']) && (! isset($_POST['pu']) || $_POST['pu']=='')) // Unit price can be 0 but not '' + if (! GETPOST('idprodfournprice') && (! GETPOST('pu') || GETPOST('pu')=='')) // Unit price can be 0 but not '' { setEventMessage($langs->trans($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('UnitPrice'))), 'errors'); - $error = true; + $error++; } - if (empty($_POST['idprodfournprice']) && empty($_POST['np_desc']) && empty($_POST['dp_desc'])) + if (! GETPOST('idprodfournprice') && ! GETPOST('np_desc') && ! GETPOST('dp_desc')) { setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), 'errors'); - $error = true; + $error++; } - if (empty($_POST['idprodfournprice']) && (! isset($_POST['qty']) || $_POST['qty'] == '') - || ! empty($_POST['idprodfournprice']) && (! isset($_POST['pqty']) || $_POST['pqty'] == '')) + if (! GETPOST('idprodfournprice') && (! GETPOST('qty') || GETPOST('qty') == '') + || GETPOST('idprodfournprice') && (! GETPOST('pqty') || GETPOST('pqty') == '')) { setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), 'errors'); - $error = true; + $error++; } - if (! $error && (($_POST['qty'] || $_POST['pqty']) && (($_POST['pu'] && ($_POST['np_desc'] || $_POST['dp_desc'])) || $_POST['idprodfournprice']))) + if (! $error && ((GETPOST('qty') || GETPOST('pqty')) && ((GETPOST('pu') && (GETPOST('np_desc') || GETPOST('dp_desc'))) || GETPOST('idprodfournprice')))) { - if ($object->fetch($id) < 0) dol_print_error($db,$object->error); - if ($object->fetch_thirdparty() < 0) dol_print_error($db,$object->error); - // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit // Ecrase $txtva par celui du produit - if ($_POST["idprodfournprice"]) // >0 or -1 + if (GETPOST('idprodfournprice')) // >0 or -1 { - $qty = $_POST['qty'] ? $_POST['qty'] : $_POST['pqty']; + $qty = GETPOST('qty') ? GETPOST('qty') : GETPOST('pqty'); $productsupplier = new ProductFournisseur($db); $idprod=$productsupplier->get_buyprice($_POST['idprodfournprice'], $qty); // Just to see if a price exists for the quantity. Not used to found vat @@ -229,9 +231,9 @@ else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) $desc.= $productsupplier->description && $_POST['np_desc'] ? "\n" : ""; $desc.= $_POST['np_desc']; - $remise_percent = $_POST["remise_percent"] ? $_POST["remise_percent"] : $_POST["p_remise_percent"]; + $remise_percent = GETPOST('remise_percent') ? GETPOST('remise_percent') : GETPOST('p_remise_percent'); - $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, $_POST['idprodfournprice']); + $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice')); $type = $productsupplier->type; // Local Taxes @@ -240,13 +242,13 @@ else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) $result=$object->addline( $desc, - $pu, + $pu, // FIXME $pu is not defined $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $productsupplier->id, - $_POST['idprodfournprice'], + GETPOST('idprodfournprice'), $productsupplier->fourn_ref, $remise_percent, 'HT', @@ -256,7 +258,7 @@ else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) if ($idprod == -1) { // Quantity too low - $mesg='
    '.$langs->trans("ErrorQtyTooLowForThisSupplier").'
    '; + setEventMessage($langs->trans("ErrorQtyTooLowForThisSupplier"), 'errors'); } } else @@ -271,7 +273,7 @@ else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) if (! $_POST['dp_desc']) { - $mesg='
    '.$langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")).'
    '; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")), 'errors'); } else { @@ -306,7 +308,7 @@ else if ($action == 'addline' && $user->rights->fournisseur->commande->creer) $outputlangs->setDefaultLang($newlang); } - $ret=$object->fetch($id); // Reload to get new records + $ret=$object->fetch($object->id); // Reload to get new records supplier_order_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); } unset($_POST['qty']); @@ -338,9 +340,6 @@ else if ($action == 'updateligne' && $user->rights->fournisseur->commande->creer if ($product->fetch($_POST["elrowid"]) < 0) dol_print_error($db); } - if ($object->fetch($id) < 0) dol_print_error($db,$object->error); - if ($object->fetch_thirdparty() < 0) dol_print_error($db,$object->error); - $localtax1_tx=get_localtax($_POST['tva_tx'],1,$object->thirdparty); $localtax2_tx=get_localtax($_POST['tva_tx'],2,$object->thirdparty); @@ -361,14 +360,14 @@ else if ($action == 'updateligne' && $user->rights->fournisseur->commande->creer if ($result >= 0) { $outputlangs = $langs; - if (! empty($_REQUEST['lang_id'])) + if (GETPOST('lang_id')) { $outputlangs = new Translate("",$conf); - $outputlangs->setDefaultLang($_REQUEST['lang_id']); + $outputlangs->setDefaultLang(GETPOST('lang_id')); } if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { - $ret=$object->fetch($id); // Reload to get new records + $ret=$object->fetch($object->id); // Reload to get new records supplier_order_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); } } @@ -381,60 +380,56 @@ else if ($action == 'updateligne' && $user->rights->fournisseur->commande->creer else if ($action == 'confirm_deleteproductline' && $confirm == 'yes' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $result = $object->deleteline(GETPOST('lineid')); if ($result >= 0) { $outputlangs = $langs; - if (! empty($_REQUEST['lang_id'])) + if (GETPOST('lang_id')) { $outputlangs = new Translate("",$conf); - $outputlangs->setDefaultLang($_REQUEST['lang_id']); + $outputlangs->setDefaultLang(GETPOST('lang_id')); } if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { - $ret=$object->fetch($id); // Reload to get new records + $ret=$object->fetch($object->id); // Reload to get new records supplier_order_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); } } else { $error++; - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } if (! $error) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } } else if ($action == 'confirm_valid' && $confirm == 'yes' && $user->rights->fournisseur->commande->valider) { - $object->fetch($id); - $object->fetch_thirdparty(); - $object->date_commande=dol_now(); $result = $object->valid($user); if ($result >= 0) { $outputlangs = $langs; - if (! empty($_REQUEST['lang_id'])) + if (GETPOST('lang_id')) { $outputlangs = new Translate("",$conf); - $outputlangs->setDefaultLang($_REQUEST['lang_id']); + $outputlangs->setDefaultLang(GETPOST('lang_id')); } if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { - $ret=$object->fetch($id); // Reload to get new records + $ret=$object->fetch($object->id); // Reload to get new records supplier_order_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); } } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } // If we have permission, and if we don't need to provide th idwarehouse, we go directly on approved step @@ -448,16 +443,13 @@ else if ($action == 'confirm_approve' && $confirm == 'yes' && $user->rights->fou { $idwarehouse=GETPOST('idwarehouse', 'int'); - $object->fetch($id); - $object->fetch_thirdparty(); - // Check parameters if (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) && $object->hasProductsOrServices(1)) { if (! $idwarehouse || $idwarehouse == -1) { $error++; - $errors[]=$langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")); + setEventMessage($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), 'errors'); $action=''; } } @@ -467,51 +459,47 @@ else if ($action == 'confirm_approve' && $confirm == 'yes' && $user->rights->fou $result = $object->approve($user, $idwarehouse); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } } } else if ($action == 'confirm_refuse' && $confirm == 'yes' && $user->rights->fournisseur->commande->approuver) { - $object->fetch($id); $result = $object->refuse($user); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } } else if ($action == 'confirm_commande' && $confirm == 'yes' && $user->rights->fournisseur->commande->commander) { - $object->fetch($id); $result = $object->commande($user, $_REQUEST["datecommande"], $_REQUEST["methode"], $_REQUEST['comment']); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } } else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->fournisseur->commande->supprimer) { - $object->fetch($id); - $object->fetch_thirdparty(); $result=$object->delete($user); if ($result > 0) { @@ -520,14 +508,39 @@ else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->four } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } } +// Action clone object +else if ($action == 'confirm_clone' && $confirm == 'yes' && $user->rights->fournisseur->commande->creer) +{ + if (1==0 && ! GETPOST('clone_content') && ! GETPOST('clone_receivers')) + { + setEventMessage($langs->trans("NoCloneOptionsSpecified"), 'errors'); + } + else + { + if ($object->id > 0) + { + $result=$object->createFromClone($hookmanager); + if ($result > 0) + { + header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); + exit; + } + else + { + setEventMessage($object->error, 'errors'); + $action=''; + } + } + } +} + // Receive else if ($action == 'livraison' && $user->rights->fournisseur->commande->receptionner) { - $object->fetch($id); if ($_POST["type"]) { @@ -536,12 +549,12 @@ else if ($action == 'livraison' && $user->rights->fournisseur->commande->recepti $result = $object->Livraison($user, $date_liv, $_POST["type"], $_POST["comment"]); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } else if($result == -3) { - $mesg='
    '.$langs->trans("NotAuthorized").'
    '; + setEventMessage($langs->trans("NotAuthorized"), 'errors'); } else { @@ -557,23 +570,21 @@ else if ($action == 'livraison' && $user->rights->fournisseur->commande->recepti else if ($action == 'confirm_cancel' && $confirm == 'yes' && $user->rights->fournisseur->commande->commander) { - $object->fetch($id); $result = $object->cancel($user); if ($result > 0) { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object->id); exit; } else { - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } } // Line ordering else if ($action == 'up' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $object->line_up($_GET['rowid']); $outputlangs = $langs; @@ -583,12 +594,11 @@ else if ($action == 'up' && $user->rights->fournisseur->commande->creer) $outputlangs->setDefaultLang($_REQUEST['lang_id']); } if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) supplier_order_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id.(empty($conf->global->MAIN_JUMP_TAG)?'':'#'.$_GET['rowid'])); + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.(empty($conf->global->MAIN_JUMP_TAG)?'':'#'.$_GET['rowid'])); exit; } else if ($action == 'down' && $user->rights->fournisseur->commande->creer) { - $object->fetch($id); $object->line_down($_GET['rowid']); $outputlangs = $langs; @@ -607,19 +617,17 @@ else if ($action == 'builddoc' && $user->rights->fournisseur->commande->creer) / // Build document // Sauvegarde le dernier module choisi pour generer un document - $object->fetch($id); - $object->fetch_thirdparty(); - if ($_REQUEST['model']) + if (GETPOST('model')) { - $object->setDocModel($user, $_REQUEST['model']); + $object->setDocModel($user, GETPOST('model')); } $outputlangs = $langs; - if (! empty($_REQUEST['lang_id'])) + if (GETPOST('lang_id')) { $outputlangs = new Translate("",$conf); - $outputlangs->setDefaultLang($_REQUEST['lang_id']); + $outputlangs->setDefaultLang(GETPOST('lang_id')); } $result=supplier_order_pdf_create($db, $object,$object->modelpdf,$outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); if ($result <= 0) @@ -635,52 +643,41 @@ else if ($action == 'builddoc' && $user->rights->fournisseur->commande->creer) / } // Delete file in doc form -else if ($action == 'remove_file' && $user->rights->fournisseur->commande->creer) +else if ($action == 'remove_file' && $object->id > 0 && $user->rights->fournisseur->commande->creer) { require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - - if ($object->fetch($id)) - { - $object->fetch_thirdparty(); - - $langs->load("other"); - $upload_dir = $conf->fournisseur->commande->dir_output; - $file = $upload_dir . '/' . GETPOST('file'); - $ret=dol_delete_file($file,0,0,0,$object); - if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); - else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); - } + $langs->load("other"); + $upload_dir = $conf->fournisseur->commande->dir_output; + $file = $upload_dir . '/' . GETPOST('file'); + $ret=dol_delete_file($file,0,0,0,$object); + if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); + else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); } /* * Create an order */ -else if ($action == 'create' && $user->rights->fournisseur->commande->creer) +else if ($action == 'create' && ! empty($object->socid) && $user->rights->fournisseur->commande->creer) { $error=0; - $fourn = new Fournisseur($db); - $result=$fourn->fetch($socid); - - $object->socid = $fourn->id; - $db->begin(); - $orderid=$object->create($user); - if (! $orderid > 0) + $id=$object->create($user); + if (! $id > 0) { $error++; - $mesg=$object->error; + setEventMessage($object->error, 'errors'); } if (! $error) { if ($comclientid != '') { - $object->updateFromCommandeClient($user, $orderid, $comclientid); + $object->updateFromCommandeClient($user, $id, $comclientid); } - $id=$orderid; + $ret=$object->fetch($id); // Reload to get new records $db->commit(); } @@ -728,10 +725,7 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G { $langs->load('mails'); - $result=$object->fetch($_POST['orderid']); - $result=$object->fetch_thirdparty(); - - if ($result > 0) + if ($object->id > 0) { // $ref = dol_sanitizeFileName($object->ref); // $file = $conf->fournisseur->commande->dir_output . '/' . $ref . '/' . $ref . '.pdf'; @@ -798,14 +792,15 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G $mailfile = new CMailFile($subject,$sendto,$from,$message,$filepath,$mimetype,$filename,$sendtocc,'',$deliveryreceipt); if ($mailfile->error) { - $mesg='
    '.$mailfile->error.'
    '; + setEventMessage($mailfile->error, 'errors'); } else { $result=$mailfile->sendfile(); if ($result) { - $mesg=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2)); // Must not contain " + $mesg=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($from,2),$mailfile->getValidAddress($sendto,2)); // Must not contain " + setEventMessage($mesg); $error=0; @@ -839,17 +834,17 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G else { $langs->load("other"); - $mesg='
    '; if ($mailfile->error) { - $mesg.=$langs->trans('ErrorFailedToSendMail',$from,$sendto); - $mesg.='
    '.$mailfile->error; + $mesg = $langs->trans('ErrorFailedToSendMail',$from,$sendto); + $mesg.= '
    '.$mailfile->error; } else { - $mesg.='No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS'; + $mesg = 'No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS'; } - $mesg.='
    '; + + setEventMessage($mesg, 'errors'); } } /* } @@ -864,14 +859,14 @@ if ($action == 'send' && ! GETPOST('addfile') && ! GETPOST('removedfile') && ! G else { $langs->load("errors"); - $mesg='
    '.$langs->trans('ErrorCantReadFile',$file).'
    '; + setEventMessage($langs->trans('ErrorCantReadFile',$file), 'errors'); dol_syslog('Failed to read file: '.$file); } } else { $langs->load("other"); - $mesg='
    '.$langs->trans('ErrorFailedToReadEntity',$langs->trans("Invoice")).'
    '; + setEventMessage($langs->trans('ErrorFailedToReadEntity',$langs->trans("Invoice")), 'errors'); dol_syslog('Impossible de lire les donnees de la facture. Le fichier facture n\'a peut-etre pas ete genere.'); } } @@ -880,12 +875,10 @@ if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->fourniss { if ($action == 'addcontact') { - $result = $object->fetch($id); - - if ($result > 0 && $id > 0) + if ($object->id > 0) { $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid')); - $result = $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]); + $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]); } if ($result >= 0) @@ -898,32 +891,24 @@ if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->fourniss if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - $mesg = '
    '.$langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType").'
    '; + setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); } else { - $mesg = '
    '.$object->error.'
    '; + setEventMessage($object->error, 'errors'); } } } // bascule du statut d'un contact - else if ($action == 'swapstatut') + else if ($action == 'swapstatut' && $object->id > 0) { - if ($object->fetch($id)) - { - $result=$object->swapContactStatus(GETPOST('ligne')); - } - else - { - dol_print_error($db); - } + $result=$object->swapContactStatus(GETPOST('ligne')); } // Efface un contact - else if ($action == 'deletecontact') + else if ($action == 'deletecontact' && $object->id > 0) { - $object->fetch($id); $result = $object->delete_contact($_GET["lineid"]); if ($result >= 0) @@ -958,891 +943,899 @@ $productstatic = new Product($db); $now=dol_now(); -if ($id > 0 || ! empty($ref)) +if (! empty($object->id)) { - //if ($mesg) print $mesg.'
    '; - - $result=$object->fetch($id,$ref); - if ($result >= 0) - { - $soc = new Societe($db); - $soc->fetch($object->socid); - - $author = new User($db); - $author->fetch($object->user_author_id); - - $head = ordersupplier_prepare_head($object); - - $title=$langs->trans("SupplierOrder"); - dol_fiche_head($head, 'card', $title, 0, 'order'); - - /* - * Confirmation de la suppression de la commande - */ - if ($action == 'delete') - { - $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 2); - if ($ret == 'html') print '
    '; - } - - /* - * Confirmation de la validation - */ - if ($action == 'valid') - { - $object->date_commande=dol_now(); - - // We check if number is temporary number - if (preg_match('/^[\(]?PROV/i',$object->ref)) $newref = $object->getNextNumRef($soc); - else $newref = $object->ref; - - $text=$langs->trans('ConfirmValidateOrder',$newref); - if (! empty($conf->notification->enabled)) - { - require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php'; - $notify=new Notify($db); - $text.='
    '; - $text.=$notify->confirmMessage(3,$object->socid); - } - - $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$id, $langs->trans('ValidateOrder'), $text, 'confirm_valid', '', 0, 1); - if ($ret == 'html') print '
    '; - } - /* - * Confirmation de l'approbation - */ - if ($action == 'approve') - { - $formquestion=array(); - if (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) && $object->hasProductsOrServices(1)) - { - $langs->load("stocks"); - require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; - $formproduct=new FormProduct($db); - $formquestion=array( - //'text' => $langs->trans("ConfirmClone"), - //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), - //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), - array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'),'idwarehouse','',1))); - } - - $ret=$form->form_confirm("fiche.php?id=".$object->id,$langs->trans("ApproveThisOrder"),$langs->trans("ConfirmApproveThisOrder",$object->ref),"confirm_approve", $formquestion, 1, 1, 240); - if ($ret == 'html') print '
    '; - } - /* - * Confirmation de la desapprobation - */ - if ($action == 'refuse') - { - $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("DenyingThisOrder"),$langs->trans("ConfirmDenyingThisOrder",$object->ref),"confirm_refuse", '', 0, 1); - if ($ret == 'html') print '
    '; - } - /* - * Confirmation de l'annulation - */ - if ($action == 'cancel') - { - $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("Cancel"),$langs->trans("ConfirmCancelThisOrder",$object->ref),"confirm_cancel", '', 0, 1); - if ($ret == 'html') print '
    '; - } - - /* - * Confirmation de l'envoi de la commande - */ - if ($action == 'commande') - { - $date_com = dol_mktime(0,0,0,$_POST["remonth"],$_POST["reday"],$_POST["reyear"]); - $ret=$form->form_confirm("fiche.php?id=".$object->id."&datecommande=".$date_com."&methode=".$_POST["methodecommande"]."&comment=".urlencode($_POST["comment"]), $langs->trans("MakeOrder"),$langs->trans("ConfirmMakeOrder",dol_print_date($date_com,'day')),"confirm_commande",'',0,2); - if ($ret == 'html') print '
    '; - } - - /* - * Confirmation de la suppression d'une ligne produit - */ - if ($action == 'delete_product_line') - { - $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$_GET["lineid"], $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteproductline','',0,2); - if ($ret == 'html') print '
    '; - } - - /* - * Commande - */ - $nbrow=8; - if (! empty($conf->projet->enabled)) $nbrow++; - - //Local taxes - if ($mysoc->country_code=='ES') - { - if($mysoc->localtax1_assuj=="1") $nbrow++; - if($mysoc->localtax2_assuj=="1") $nbrow++; - } - - print ''; - - $linkback = ''.$langs->trans("BackToList").''; - - // Ref - print ''; - print ''; - print ''; - - // Ref supplier - print ''; - - // Fournisseur - print '"; - print ''; - print ''; - - // Statut - print ''; - print ''; - print '"; - - // Date - if ($object->methode_commande_id > 0) - { - print '"; - - if ($object->methode_commande) - { - print ''; - } - } - - // Author - print ''; - print ''; - print ''; - - // Conditions de reglement par defaut - $langs->load('bills'); - $form = new Form($db); - print '"; - print ''; - - // Mode of payment - $langs->load('bills'); - $form = new Form($db); - print ''; - - // Delivery date planed - print ''; - - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load('projects'); - print ''; - print ''; - } - - // Other attributes - $parameters=array('socid'=>$socid, 'colspan' => ' colspan="3"'); - $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook - - // Ligne de 3 colonnes - print ''; - print ''; - print ''; - - print ''; - print ''; - - // Amount Local Taxes - if ($mysoc->country_code=='ES') - { - if ($mysoc->localtax1_assuj=="1") //Localtax1 RE - { - print ''; - print ''; - print ''; - } - if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF - { - print ''; - print ''; - print ''; - } - } - print ''; - print ''; - - print "
    '.$langs->trans("Ref").''; - print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref'); - print '
    '; - print $form->editfieldkey("RefSupplier",'ref_supplier',$langs->trans($object->ref_supplier),$object,$user->rights->fournisseur->commande->creer); - print ''; - print $form->editfieldval("RefSupplier",'ref_supplier',$langs->trans($object->ref_supplier),$object,$user->rights->fournisseur->commande->creer); - print '
    '.$langs->trans("Supplier")."'.$soc->getNomUrl(1,'supplier').'
    '.$langs->trans("Status").''; - print $object->getLibStatut(4); - print "
    '.$langs->trans("Date").''; - if ($object->date_commande) - { - print dol_print_date($object->date_commande,"dayhourtext")."\n"; - } - print "
    '.$langs->trans("Method").''.$object->getInputMethod().'
    '.$langs->trans("AuthorRequest").''.$author->getNomUrl(1).'
    '; - print ''; - print '
    '; - print $langs->trans('PaymentConditions'); - print ''; - if ($action != 'editconditions') print 'id.'">'.img_edit($langs->trans('SetConditions'),1).'
    '; - print '
    '; - if ($action == 'editconditions') - { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id,'cond_reglement_id'); - } - else - { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id,'none'); - } - print "
    '; - print ''; - if ($action != 'editmode') print ''; - print '
    '; - print $langs->trans('PaymentMode'); - print 'id.'">'.img_edit($langs->trans('SetMode'),1).'
    '; - print '
    '; - if ($action == 'editmode') - { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'mode_reglement_id'); - } - else - { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'none'); - } - print '
    '; - print ''; - - if ($action != 'editdate_livraison') print ''; - print '
    '; - print $langs->trans('DateDeliveryPlanned'); - print 'id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'
    '; - print '
    '; - if ($action == 'editdate_livraison') - { - print '
    '; - print ''; - print ''; - $form->select_date($object->date_livraison?$object->date_livraison:-1,'liv_','','','',"setdate_livraison"); - print ''; - print '
    '; - } - else - { - print $object->date_livraison ? dol_print_date($object->date_livraison,'daytext') : ' '; - } - print '
    '; - print ''; - if ($action != 'classify') print ''; - print '
    '; - print $langs->trans('Project'); - print ''.img_edit($langs->trans('SetProject')).'
    '; - print '
    '; - //print "$object->id, $object->socid, $object->fk_project"; - if ($action == 'classify') - { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:'-1', $object->fk_project, 'projectid'); - } - else - { - $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none'); - } - print '
    '.$langs->trans("AmountHT").''.price($object->total_ht).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->trans("AmountVAT").''.price($object->total_tva).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->trans("AmountTTC").''.price($object->total_ttc).''.$langs->trans("Currency".$conf->currency).'

    "; - - if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) - { - $blocname = 'contacts'; - $title = $langs->trans('ContactsAddresses'); - include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php'; - } - - if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) - { - $blocname = 'notes'; - $title = $langs->trans('Notes'); - include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php'; - } - - dol_htmloutput_mesg($mesg); - dol_htmloutput_errors('',$errors); - - /* - * Lines - */ - print ''; - - $num = count($object->lines); - $i = 0; $total = 0; - - if ($num) - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - } - $var=true; - while ($i < $num) - { - $line = $object->lines[$i]; - $var=!$var; - - // Show product and description - $type=(! empty($line->product_type)?$line->product_type:(! empty($line->fk_product_type)?$line->fk_product_type:0)); - // Try to enhance type detection using date_start and date_end for free lines where type - // was not saved. - $date_start=''; - $date_end=''; - if (! empty($line->date_start)) - { - $date_start=$line->date_start; - $type=1; - } - if (! empty($line->date_end)) - { - $date_end=$line->date_end; - $type=1; - } - - // Ligne en mode visu - if ($action != 'editline' || $_GET['rowid'] != $line->id) - { - print ''; - - // Show product and description - print ''; - - print ''; - - print '\n"; - - print ''; - - if ($line->remise_percent > 0) - { - print '\n"; - } - else - { - print ''; - } - - print ''; - if ($object->statut == 0 && $user->rights->fournisseur->commande->creer) - { - print ''; - - $actiondelete='delete_product_line'; - print ''; - } - else - { - print ''; - } - print ""; - } - - // Ligne en mode update - if ($action == 'editline' && $user->rights->fournisseur->commande->creer && ($_GET["rowid"] == $line->id)) - { - print "\n"; - print 'id.'" method="post">'; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print '' . "\n"; - print "\n"; - } - $i++; - } - - /* - * Form to add new line - */ - if ($object->statut == 0 && $user->rights->fournisseur->commande->creer && $action <> 'editline') - { - //WYSIWYG Editor - require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - - // Add free products/services form - print ''; - print ''; - print ''; - print ''; - - $var=true; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - - print ''; - - // Ajout de produits/services predefinis - if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - - print ''; - print ''; - print ''; - print ''; - - $var=!$var; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + // Cancel + if ($object->statut == 2) + { + if ($user->rights->fournisseur->commande->commander) + { + print ''.$langs->trans("CancelOrder").''; + } + } - print ''; - } - } - print '
    '.$langs->trans('Label').''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('Qty').''.$langs->trans('ReductionShort').''.$langs->trans('TotalHTShort').' 
    '; - if ($line->fk_product > 0) - { - print ''; // ancre pour retourner sur la ligne - - $product_static=new ProductFournisseur($db); - $product_static->fetch($line->fk_product); - $text=$product_static->getNomUrl(1,'supplier'); - $text.= ' - '.$product_static->libelle; - $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->description)); - print $form->textwithtooltip($text,$description,3,'','',$i); - - // Show range - print_date_range($date_start,$date_end); - - // Add description in form - if (! empty($conf->global->PRODUIT_DESC_IN_FORM)) print ($line->description && $line->description!=$product_static->libelle)?'
    '.dol_htmlentitiesbr($line->description):''; - } - - // Description - Editor wysiwyg - if (! $line->fk_product) - { - if ($type==1) $text = img_object($langs->trans('Service'),'service'); - else $text = img_object($langs->trans('Product'),'product'); - print $text.' '.nl2br($line->description); - - // Show range - print_date_range($date_start,$date_end); - } - - print '
    '.vatrate($line->tva_tx).'%'.price($line->subprice)."'.$line->qty.''.dol_print_reduction($line->remise_percent,$langs)." '.price($line->total_ht).'id.'#'.$line->id.'">'; - print img_edit(); - print ''; - print img_delete(); - print '  
    '; - print ''; // ancre pour retourner sur la ligne - if ((! empty($conf->product->enabled) || ! empty($conf->service->enabled)) && $line->fk_product > 0) - { - $product_static=new ProductFournisseur($db); - $product_static->fetch($line->fk_product); - $text=$product_static->getNomUrl(1,'supplier'); - $text.= ' - '.$product_static->libelle; - $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->description)); - print $form->textwithtooltip($text,$description,3,'','',$i); - - // Show range - print_date_range($date_start,$date_end); - print '
    '; - } - else - { - print $form->select_type_of_lines($line->product_type,'type',1); - if (! empty($conf->product->enabled) && ! empty($conf->service->enabled)) print '
    '; - } - - if (is_object($hookmanager)) - { - $parameters=array('fk_parent_line'=>$line->fk_parent_line, 'line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i); - $reshook=$hookmanager->executeHooks('formEditProductOptions',$parameters,$object,$action); - } - - // Description - Editor wysiwyg - require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $nbrows=ROWS_2; - if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; - $doleditor=new DolEditor('eldesc',$line->description,'',200,'dolibarr_details','',false,true,$conf->global->FCKEDITOR_ENABLE_DETAILS,$nbrows,70); - $doleditor->Create(); - - print '
    '; - print $form->load_tva('tva_tx',$line->tva_tx,$soc,$mysoc); - print '%'; - print '
    '; - print ''; // ancre - print $langs->trans('AddNewLine').' - '.$langs->trans("FreeZone").''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('Qty').''.$langs->trans('ReductionShort').' 
    '; - - $forceall=1; - print $form->select_type_of_lines(isset($_POST["type"])?$_POST["type"]:-1,'type',1,0,$forceall); - if ($forceall || (! empty($conf->product->enabled) && ! empty($conf->service->enabled)) - || (empty($conf->product->enabled) && empty($conf->service->enabled))) print '
    '; - - if (is_object($hookmanager)) - { - $parameters=array(); - $reshook=$hookmanager->executeHooks('formCreateProductOptions',$parameters,$object,$action); - } - - $nbrows=ROWS_2; - if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; - $doleditor = new DolEditor('dp_desc', GETPOST('dp_desc'), '', 100, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_DETAILS, $nbrows, 70); - $doleditor->Create(); - - print '
    '; - print $form->load_tva('tva_tx',(GETPOST('tva_tx')?GETPOST('tva_tx'):-1),$soc,$mysoc); - print '%
    '; - print $langs->trans("AddNewLine").' - '; - if (! empty($conf->service->enabled)) - { - print $langs->trans('RecordedProductsAndServices'); - } - else - { - print $langs->trans('RecordedProducts'); - } - print ''.$langs->trans('Qty').''.$langs->trans('ReductionShort').' 
    '; - - $ajaxoptions=array( - 'update' => array('pqty' => 'qty', 'p_remise_percent' => 'discount'), - 'option_disabled' => 'addPredefinedProductButton', - 'error' => $langs->trans("NoPriceDefinedForThisSupplier") - ); - $form->select_produits_fournisseurs($object->fourn_id, '', 'idprodfournprice', '', '', $ajaxoptions); - - if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) print '
    '; - - if (is_object($hookmanager)) + $author = new User($db); + $author->fetch($object->user_author_id); + + $head = ordersupplier_prepare_head($object); + + $title=$langs->trans("SupplierOrder"); + dol_fiche_head($head, 'card', $title, 0, 'order'); + + /* + * Confirmation de la suppression de la commande + */ + if ($action == 'delete') + { + $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 2); + if ($ret == 'html') print '
    '; + } + + // Clone confirmation + if ($action == 'clone') + { + // Create an array for form + $formquestion=array( + //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1) + ); + // Paiement incomplet. On demande si motif = escompte ou autre + $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('CloneOrder'),$langs->trans('ConfirmCloneOrder',$object->ref),'confirm_clone',$formquestion,'yes',1); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de la validation + */ + if ($action == 'valid') + { + $object->date_commande=dol_now(); + + // We check if number is temporary number + if (preg_match('/^[\(]?PROV/i',$object->ref)) $newref = $object->getNextNumRef($object->thirdparty); + else $newref = $object->ref; + + $text=$langs->trans('ConfirmValidateOrder',$newref); + if (! empty($conf->notification->enabled)) + { + require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php'; + $notify=new Notify($db); + $text.='
    '; + $text.=$notify->confirmMessage(3,$object->socid); + } + + $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateOrder'), $text, 'confirm_valid', '', 0, 1); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de l'approbation + */ + if ($action == 'approve') + { + $formquestion=array(); + if (! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) && $object->hasProductsOrServices(1)) + { + $langs->load("stocks"); + require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + $formproduct=new FormProduct($db); + $formquestion=array( + //'text' => $langs->trans("ConfirmClone"), + //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'),'idwarehouse','',1)) + ); + } + + $ret=$form->form_confirm($_SERVER['PHP_SELF']."?id=".$object->id,$langs->trans("ApproveThisOrder"),$langs->trans("ConfirmApproveThisOrder",$object->ref),"confirm_approve", $formquestion, 1, 1, 240); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de la desapprobation + */ + if ($action == 'refuse') + { + $ret=$form->form_confirm($_SERVER['PHP_SELF']."?id=$object->id",$langs->trans("DenyingThisOrder"),$langs->trans("ConfirmDenyingThisOrder",$object->ref),"confirm_refuse", '', 0, 1); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de l'annulation + */ + if ($action == 'cancel') + { + $ret=$form->form_confirm($_SERVER['PHP_SELF']."?id=$object->id",$langs->trans("Cancel"),$langs->trans("ConfirmCancelThisOrder",$object->ref),"confirm_cancel", '', 0, 1); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de l'envoi de la commande + */ + if ($action == 'commande') + { + $date_com = dol_mktime(0,0,0,$_POST["remonth"],$_POST["reday"],$_POST["reyear"]); + $ret=$form->form_confirm($_SERVER['PHP_SELF']."?id=".$object->id."&datecommande=".$date_com."&methode=".$_POST["methodecommande"]."&comment=".urlencode($_POST["comment"]), $langs->trans("MakeOrder"),$langs->trans("ConfirmMakeOrder",dol_print_date($date_com,'day')),"confirm_commande",'',0,2); + if ($ret == 'html') print '
    '; + } + + /* + * Confirmation de la suppression d'une ligne produit + */ + if ($action == 'delete_product_line') + { + $ret=$form->form_confirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$_GET["lineid"], $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteproductline','',0,2); + if ($ret == 'html') print '
    '; + } + + /* + * Commande + */ + $nbrow=8; + if (! empty($conf->projet->enabled)) $nbrow++; + + //Local taxes + if ($mysoc->country_code=='ES') + { + if($mysoc->localtax1_assuj=="1") $nbrow++; + if($mysoc->localtax2_assuj=="1") $nbrow++; + } + + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + print ''; + print ''; + + // Ref supplier + print ''; + + // Fournisseur + print '"; + print ''; + print ''; + + // Statut + print ''; + print ''; + print '"; + + // Date + if ($object->methode_commande_id > 0) + { + print '"; + + if ($object->methode_commande) + { + print ''; + } + } + + // Author + print ''; + print ''; + print ''; + + // Conditions de reglement par defaut + $langs->load('bills'); + $form = new Form($db); + print '"; + print ''; + + // Mode of payment + $langs->load('bills'); + $form = new Form($db); + print ''; + + // Delivery date planed + print ''; + + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load('projects'); + print ''; + print ''; + } + + // Other attributes + $parameters=array('socid'=>$socid, 'colspan' => ' colspan="3"'); + $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + + // Ligne de 3 colonnes + print ''; + print ''; + print ''; + + print ''; + print ''; + + // Amount Local Taxes + if ($mysoc->country_code=='ES') + { + if ($mysoc->localtax1_assuj=="1") //Localtax1 RE + { + print ''; + print ''; + print ''; + } + if ($mysoc->localtax2_assuj=="1") //Localtax2 IRPF + { + print ''; + print ''; + print ''; + } + } + print ''; + print ''; + + print "
    '.$langs->trans("Ref").''; + print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref'); + print '
    '; + print $form->editfieldkey("RefSupplier",'ref_supplier',$langs->trans($object->ref_supplier),$object,$user->rights->fournisseur->commande->creer); + print ''; + print $form->editfieldval("RefSupplier",'ref_supplier',$langs->trans($object->ref_supplier),$object,$user->rights->fournisseur->commande->creer); + print '
    '.$langs->trans("Supplier")."'.$object->thirdparty->getNomUrl(1,'supplier').'
    '.$langs->trans("Status").''; + print $object->getLibStatut(4); + print "
    '.$langs->trans("Date").''; + if ($object->date_commande) + { + print dol_print_date($object->date_commande,"dayhourtext")."\n"; + } + print "
    '.$langs->trans("Method").''.$object->getInputMethod().'
    '.$langs->trans("AuthorRequest").''.$author->getNomUrl(1).'
    '; + print ''; + print '
    '; + print $langs->trans('PaymentConditions'); + print ''; + if ($action != 'editconditions') print 'id.'">'.img_edit($langs->trans('SetConditions'),1).'
    '; + print '
    '; + if ($action == 'editconditions') + { + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id,'cond_reglement_id'); + } + else + { + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id,'none'); + } + print "
    '; + print ''; + if ($action != 'editmode') print ''; + print '
    '; + print $langs->trans('PaymentMode'); + print 'id.'">'.img_edit($langs->trans('SetMode'),1).'
    '; + print '
    '; + if ($action == 'editmode') + { + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'mode_reglement_id'); + } + else + { + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id,$object->mode_reglement_id,'none'); + } + print '
    '; + print ''; + + if ($action != 'editdate_livraison') print ''; + print '
    '; + print $langs->trans('DateDeliveryPlanned'); + print 'id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'
    '; + print '
    '; + if ($action == 'editdate_livraison') + { + print ''; + print ''; + print ''; + $form->select_date($object->date_livraison?$object->date_livraison:-1,'liv_','','','',"setdate_livraison"); + print ''; + print ''; + } + else + { + print $object->date_livraison ? dol_print_date($object->date_livraison,'daytext') : ' '; + } + print '
    '; + print ''; + if ($action != 'classify') print ''; + print '
    '; + print $langs->trans('Project'); + print ''.img_edit($langs->trans('SetProject')).'
    '; + print '
    '; + //print "$object->id, $object->socid, $object->fk_project"; + if ($action == 'classify') + { + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$object->socid:'-1', $object->fk_project, 'projectid'); + } + else + { + $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none'); + } + print '
    '.$langs->trans("AmountHT").''.price($object->total_ht).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->trans("AmountVAT").''.price($object->total_tva).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->transcountry("AmountLT1",$mysoc->country_code).''.price($object->total_localtax1).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->transcountry("AmountLT2",$mysoc->country_code).''.price($object->total_localtax2).''.$langs->trans("Currency".$conf->currency).'
    '.$langs->trans("AmountTTC").''.price($object->total_ttc).''.$langs->trans("Currency".$conf->currency).'

    "; + + if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) + { + $blocname = 'contacts'; + $title = $langs->trans('ContactsAddresses'); + include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php'; + } + + if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) + { + $blocname = 'notes'; + $title = $langs->trans('Notes'); + include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php'; + } + + /* + * Lines + */ + print ''; + + $num = count($object->lines); + $i = 0; $total = 0; + + if ($num) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + } + $var=true; + while ($i < $num) + { + $line = $object->lines[$i]; + $var=!$var; + + // Show product and description + $type=(! empty($line->product_type)?$line->product_type:(! empty($line->fk_product_type)?$line->fk_product_type:0)); + // Try to enhance type detection using date_start and date_end for free lines where type + // was not saved. + $date_start=''; + $date_end=''; + if (! empty($line->date_start)) + { + $date_start=$line->date_start; + $type=1; + } + if (! empty($line->date_end)) + { + $date_end=$line->date_end; + $type=1; + } + + // Ligne en mode visu + if ($action != 'editline' || $_GET['rowid'] != $line->id) + { + print ''; + + // Show product and description + print ''; + + print ''; + + print '\n"; + + print ''; + + if ($line->remise_percent > 0) + { + print '\n"; + } + else + { + print ''; + } + + print ''; + if ($object->statut == 0 && $user->rights->fournisseur->commande->creer) + { + print ''; + + $actiondelete='delete_product_line'; + print ''; + } + else + { + print ''; + } + print ""; + } + + // Ligne en mode update + if ($action == 'editline' && $user->rights->fournisseur->commande->creer && ($_GET["rowid"] == $line->id)) + { + print "\n"; + print 'id.'" method="post">'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '' . "\n"; + print "\n"; + } + $i++; + } + + /* + * Form to add new line + */ + if ($object->statut == 0 && $user->rights->fournisseur->commande->creer && $action <> 'editline') + { + //WYSIWYG Editor + require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + // TODO Use the predefinedproductline_create.tpl.php file + + // Add free products/services form + print ''; + print ''; + print ''; + print ''; + + print ''; + + $var=true; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + + // Ajout de produits/services predefinis + if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; + + $var=!$var; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + } + } + print '
    '.$langs->trans('Label').''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('Qty').''.$langs->trans('ReductionShort').''.$langs->trans('TotalHTShort').' 
    '; + if ($line->fk_product > 0) + { + print ''; // ancre pour retourner sur la ligne + + $product_static=new ProductFournisseur($db); + $product_static->fetch($line->fk_product); + $text=$product_static->getNomUrl(1,'supplier'); + $text.= ' - '.$product_static->libelle; + $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->description)); + print $form->textwithtooltip($text,$description,3,'','',$i); + + // Show range + print_date_range($date_start,$date_end); + + // Add description in form + if (! empty($conf->global->PRODUIT_DESC_IN_FORM)) print ($line->description && $line->description!=$product_static->libelle)?'
    '.dol_htmlentitiesbr($line->description):''; + } + + // Description - Editor wysiwyg + if (! $line->fk_product) + { + if ($type==1) $text = img_object($langs->trans('Service'),'service'); + else $text = img_object($langs->trans('Product'),'product'); + print $text.' '.nl2br($line->description); + + // Show range + print_date_range($date_start,$date_end); + } + + print '
    '.vatrate($line->tva_tx).'%'.price($line->subprice)."'.$line->qty.''.dol_print_reduction($line->remise_percent,$langs)." '.price($line->total_ht).'id.'#'.$line->id.'">'; + print img_edit(); + print ''; + print img_delete(); + print '  
    '; + print ''; // ancre pour retourner sur la ligne + if ((! empty($conf->product->enabled) || ! empty($conf->service->enabled)) && $line->fk_product > 0) + { + $product_static=new ProductFournisseur($db); + $product_static->fetch($line->fk_product); + $text=$product_static->getNomUrl(1,'supplier'); + $text.= ' - '.$product_static->libelle; + $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->description)); + print $form->textwithtooltip($text,$description,3,'','',$i); + + // Show range + print_date_range($date_start,$date_end); + print '
    '; + } + else + { + print $form->select_type_of_lines($line->product_type,'type',1); + if (! empty($conf->product->enabled) && ! empty($conf->service->enabled)) print '
    '; + } + + if (is_object($hookmanager)) + { + $parameters=array('fk_parent_line'=>$line->fk_parent_line, 'line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i); + $reshook=$hookmanager->executeHooks('formEditProductOptions',$parameters,$object,$action); + } + + // Description - Editor wysiwyg + require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; + $nbrows=ROWS_2; + if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; + $doleditor=new DolEditor('eldesc',$line->description,'',200,'dolibarr_details','',false,true,$conf->global->FCKEDITOR_ENABLE_DETAILS,$nbrows,70); + $doleditor->Create(); + + print '
    '; + print $form->load_tva('tva_tx',$line->tva_tx,$object->thirdparty,$mysoc); + print '%'; + print '
    '; + print ''; // ancre + print $langs->trans('AddNewLine').' - '.$langs->trans("FreeZone").''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('Qty').''.$langs->trans('ReductionShort').' 
    '; + + $forceall=1; + print $form->select_type_of_lines(isset($_POST["type"])?$_POST["type"]:-1,'type',1,0,$forceall); + if ($forceall || (! empty($conf->product->enabled) && ! empty($conf->service->enabled)) + || (empty($conf->product->enabled) && empty($conf->service->enabled))) print '
    '; + + if (is_object($hookmanager)) + { + $parameters=array(); + $reshook=$hookmanager->executeHooks('formCreateProductOptions',$parameters,$object,$action); + } + + $nbrows=ROWS_2; + if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; + $doleditor = new DolEditor('dp_desc', GETPOST('dp_desc'), '', 100, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_DETAILS, $nbrows, 70); + $doleditor->Create(); + + print '
    '; + print $form->load_tva('tva_tx',(GETPOST('tva_tx')?GETPOST('tva_tx'):-1),$object->thirdparty,$mysoc); + print '%
    '; + print $langs->trans("AddNewLine").' - '; + if (! empty($conf->service->enabled)) + { + print $langs->trans('RecordedProductsAndServices'); + } + else + { + print $langs->trans('RecordedProducts'); + } + print ''.$langs->trans('Qty').''.$langs->trans('ReductionShort').' 
    '; + + $ajaxoptions=array( + 'update' => array('pqty' => 'qty', 'p_remise_percent' => 'discount'), + 'option_disabled' => 'addPredefinedProductButton', + 'error' => $langs->trans("NoPriceDefinedForThisSupplier") + ); + $form->select_produits_fournisseurs($object->fourn_id, '', 'idprodfournprice', '', '', $ajaxoptions); + + if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) print '
    '; + + if (is_object($hookmanager)) + { + $parameters=array('htmlname'=>'idprodfournprice'); + $reshook=$hookmanager->executeHooks('formCreateProductSupplierOptions',$parameters,$object,$action); + } + + $nbrows=ROWS_2; + if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; + $doleditor = new DolEditor('np_desc', GETPOST('np_desc'), '', 100, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_DETAILS, $nbrows, 70); + $doleditor->Create(); + + print '
    %
    '; + print ''; + + + if ($action != 'presend') + { + /** + * Boutons actions + */ + if ($user->societe_id == 0 && $action != 'editline' && $action != 'delete') + { + print '
    '; + + // Validate + if ($object->statut == 0 && $num > 0) + { + if ($user->rights->fournisseur->commande->valider) { - $parameters=array('htmlname'=>'idprodfournprice'); - $reshook=$hookmanager->executeHooks('formCreateProductSupplierOptions',$parameters,$object,$action); + print ''.$langs->trans('Validate').''; + } + } + + // Modify + if ($object->statut == 1) + { + if ($user->rights->fournisseur->commande->commander) + { + print ''.$langs->trans("Modify").''; + } + } + + // Approve + if ($object->statut == 1) + { + if ($user->rights->fournisseur->commande->approuver) + { + print ''.$langs->trans("ApproveOrder").''; + print ''.$langs->trans("RefuseOrder").''; + } + else + { + print ''.$langs->trans("ApproveOrder").''; + print ''.$langs->trans("RefuseOrder").''; + } + } + + // Send + if (in_array($object->statut, array(2, 3, 4, 5))) + { + if ($user->rights->fournisseur->commande->commander) + { + print ''.$langs->trans('SendByMail').''; + } + } + + // Reopen + if (in_array($object->statut, array(5, 6, 7, 9))) + { + if ($user->rights->fournisseur->commande->commander) + { + print ''.$langs->trans("ReOpen").''; + } + } + + // Create bill + if (! empty($conf->fournisseur->enabled) && $object->statut >= 2) // 2 means accepted + { + if ($user->rights->fournisseur->facture->creer) + { + print ''.$langs->trans("CreateBill").''; } - $nbrows=ROWS_2; - if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; - $doleditor = new DolEditor('np_desc', GETPOST('np_desc'), '', 100, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_DETAILS, $nbrows, 70); - $doleditor->Create(); + //if ($user->rights->fournisseur->commande->creer && $object->statut > 2) + //{ + // print ''.$langs->trans("ClassifyBilled").''; + //} + } - print '
    %
    '; - print ''; + // Clone + if ($user->rights->fournisseur->commande->creer) + { + print ''.$langs->trans("ToClone").''; + } + // Delete + if ($user->rights->fournisseur->commande->supprimer) + { + print ''.$langs->trans("Delete").''; + } - if ($action != 'presend') - { + print ""; + } - /** - * Boutons actions - */ - if ($user->societe_id == 0 && $action != 'editline' && $action != 'delete') - { - print '
    '; + print '
    '; + print ''; // ancre - // Validate - if ($object->statut == 0 && $num > 0) - { - if ($user->rights->fournisseur->commande->valider) - { - print ''.$langs->trans('Validate').''; - } - } + /* + * Documents generes + */ + $comfournref = dol_sanitizeFileName($object->ref); + $file = $conf->fournisseur->dir_output . '/commande/' . $comfournref . '/' . $comfournref . '.pdf'; + $relativepath = $comfournref.'/'.$comfournref.'.pdf'; + $filedir = $conf->fournisseur->dir_output . '/commande/' . $comfournref; + $urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id; + $genallowed=$user->rights->fournisseur->commande->creer; + $delallowed=$user->rights->fournisseur->commande->supprimer; - // Modify - if ($object->statut == 1) - { - if ($user->rights->fournisseur->commande->commander) - { - print ''.$langs->trans("Modify").''; - } - } + print $formfile->showdocuments('commande_fournisseur',$comfournref,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf,1,0,0,0,0,'','','',$object->thirdparty->default_lang); + $somethingshown=$formfile->numoffiles; - // Approve - if ($object->statut == 1) - { - if ($user->rights->fournisseur->commande->approuver) - { - print ''.$langs->trans("ApproveOrder").''; - print ''.$langs->trans("RefuseOrder").''; - } - else - { - print ''.$langs->trans("ApproveOrder").''; - print ''.$langs->trans("RefuseOrder").''; - } - } + $object=$object; - // Send - if (in_array($object->statut, array(2, 3, 4, 5))) - { - if ($user->rights->fournisseur->commande->commander) - { - print ''.$langs->trans('SendByMail').''; - } - } + /* + * Linked object block + */ + $somethingshown=$object->showLinkedObjectBlock(); - // Reopen - if (in_array($object->statut, array(5, 6, 7, 9))) - { - if ($user->rights->fournisseur->commande->commander) - { - print ''.$langs->trans("ReOpen").''; - } - } + print ''; - // Create bill - if (! empty($conf->fournisseur->enabled) && $object->statut >= 2) // 2 means accepted - { - if ($user->rights->fournisseur->facture->creer) - { - print ''.$langs->trans("CreateBill").''; - } + if ($user->rights->fournisseur->commande->commander && $object->statut == 2) + { + /* + * Commander (action=commande) + */ + print '
    '; + print '
    '; + print ''; + print ''; + print ''; + print ''; + print ''; - //if ($user->rights->fournisseur->commande->creer && $object->statut > 2) - //{ - // print ''.$langs->trans("ClassifyBilled").''; - //} - } + print ''; - // Cancel - if ($object->statut == 2) - { - if ($user->rights->fournisseur->commande->commander) - { - print ''.$langs->trans("CancelOrder").''; - } - } + print ''; + print ''; + print '
    '.$langs->trans("ToOrder").'
    '.$langs->trans("OrderDate").''; + $date_com = dol_mktime(0, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); + print $form->select_date($date_com,'','','','',"commande"); + print '
    '.$langs->trans("OrderMode").''; + $formorder->select_methodes_commande(GETPOST('methodecommande'), "methodecommande", 1); + print '
    '.$langs->trans("Comment").'
    '; + print '
    '; + } - // Delete - if ($user->rights->fournisseur->commande->supprimer) - { - print ''.$langs->trans("Delete").''; - } + if ($user->rights->fournisseur->commande->receptionner && ($object->statut == 3 || $object->statut == 4)) + { + /* + * Receptionner (action=livraison) + */ + print '
    '; + print '
    '; + print ''; + print ''; + print ''; + print ''; + print '\n"; + print "'; + print ''; + print ''; + print "
    '.$langs->trans("Receive").'
    '.$langs->trans("DeliveryDate").''; + print $form->select_date('','','','','',"commande"); + print "
    ".$langs->trans("Delivery")."\n"; + $liv = array(); + $liv[''] = ' '; + $liv['tot'] = $langs->trans("TotalWoman"); + $liv['par'] = $langs->trans("PartialWoman"); + $liv['nev'] = $langs->trans("NeverReceived"); + $liv['can'] = $langs->trans("Canceled"); - print ""; - } + print $form->selectarray("type",$liv); + print '
    '.$langs->trans("Comment").'
    \n"; + print "
    \n"; + } - print '
    '; - print ''; // ancre + // List of actions on element + /* Hidden because" available into "Log" tab + print '
    '; + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; + $formactions=new FormActions($db); + $somethingshown=$formactions->showactions($object,'order_supplier',$socid); + */ - /* - * Documents generes - */ - $comfournref = dol_sanitizeFileName($object->ref); - $file = $conf->fournisseur->dir_output . '/commande/' . $comfournref . '/' . $comfournref . '.pdf'; - $relativepath = $comfournref.'/'.$comfournref.'.pdf'; - $filedir = $conf->fournisseur->dir_output . '/commande/' . $comfournref; - $urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed=$user->rights->fournisseur->commande->creer; - $delallowed=$user->rights->fournisseur->commande->supprimer; + print '
    '; + } - print $formfile->showdocuments('commande_fournisseur',$comfournref,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf,1,0,0,0,0,'','','',$soc->default_lang); - $somethingshown=$formfile->numoffiles; + /* + * Action presend + */ + if ($action == 'presend') + { + $ref = dol_sanitizeFileName($object->ref); + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $fileparams = dol_most_recent_file($conf->fournisseur->commande->dir_output . '/' . $ref); + $file=$fileparams['fullname']; - $object=$object; + // Build document if it not exists + if (! $file || ! is_readable($file)) + { + // Define output language + $outputlangs = $langs; + $newlang=''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id']; + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->client->default_lang; + if (! empty($newlang)) + { + $outputlangs = new Translate("",$conf); + $outputlangs->setDefaultLang($newlang); + } - /* - * Linked object block - */ - $somethingshown=$object->showLinkedObjectBlock(); + $result=supplier_order_pdf_create($db, $object, GETPOST('model')?GETPOST('model'):$object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); + if ($result <= 0) + { + dol_print_error($db,$result); + exit; + } + $fileparams = dol_most_recent_file($conf->fournisseur->commande->dir_output . '/' . $ref); + $file=$fileparams['fullname']; + } + print '
    '; - print '
    '; + print_titre($langs->trans('SendOrderByMail')); - if ($user->rights->fournisseur->commande->commander && $object->statut == 2) - { - /** - * Commander (action=commande) - */ - print '
    '; - print '
    '; - print ''; - print ''; - print ''; - print ''; - print ''; + // Cree l'objet formulaire mail + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + $formmail->fromtype = 'user'; + $formmail->fromid = $user->id; + $formmail->fromname = $user->getFullName($langs); + $formmail->frommail = $user->email; + $formmail->withfrom=1; + $formmail->withto=empty($_POST["sendto"])?1:$_POST["sendto"]; + $formmail->withtosocid=$object->thirdparty->id; + $formmail->withtocc=1; + $formmail->withtoccsocid=0; + $formmail->withtoccc=(! empty($conf->global->MAIN_EMAIL_USECCC)?$conf->global->MAIN_EMAIL_USECCC:false); + $formmail->withtocccsocid=0; + $formmail->withtopic=$langs->trans('SendOrderRef','__ORDERREF__'); + $formmail->withfile=2; + $formmail->withbody=1; + $formmail->withdeliveryreceipt=1; + $formmail->withcancel=1; + // Tableau des substitutions + $formmail->substit['__ORDERREF__']=$object->ref; + $formmail->substit['__SIGNATURE__']=$user->signature; + $formmail->substit['__PERSONALIZED__']=''; + // Tableau des parametres complementaires + $formmail->param['action']='send'; + $formmail->param['models']='order_supplier_send'; + $formmail->param['orderid']=$object->id; + $formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id; - print ''; + // Init list of files + if (GETPOST("mode")=='init') + { + $formmail->clear_attached_files(); + $formmail->add_attached_files($file,basename($file),dol_mimetype($file)); + } - print ''; - print ''; - print '
    '.$langs->trans("ToOrder").'
    '.$langs->trans("OrderDate").''; - $date_com = dol_mktime(0, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); - print $form->select_date($date_com,'','','','',"commande"); - print '
    '.$langs->trans("OrderMode").''; - $formorder->select_methodes_commande(GETPOST('methodecommande'), "methodecommande", 1); - print '
    '.$langs->trans("Comment").'
    '; - print '
    '; - } + // Show form + $formmail->show_form(); - if ($user->rights->fournisseur->commande->receptionner && ($object->statut == 3 || $object->statut == 4)) - { - /** - * Receptionner (action=livraison) - */ - print '
    '; - print '
    '; - print ''; - print ''; - print ''; - print ''; - print '\n"; + print '
    '; + } - print "'; - print ''; - print ''; - print "
    '.$langs->trans("Receive").'
    '.$langs->trans("DeliveryDate").''; - print $form->select_date('','','','','',"commande"); - print "
    ".$langs->trans("Delivery")."\n"; - $liv = array(); - $liv[''] = ' '; - $liv['tot'] = $langs->trans("TotalWoman"); - $liv['par'] = $langs->trans("PartialWoman"); - $liv['nev'] = $langs->trans("NeverReceived"); - $liv['can'] = $langs->trans("Canceled"); - - print $form->selectarray("type",$liv); - - print '
    '.$langs->trans("Comment").'
    \n"; - print "
    \n"; - } - - // List of actions on element - /* Hidden because" available into "Log" tab - print '
    '; - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; - $formactions=new FormActions($db); - $somethingshown=$formactions->showactions($object,'order_supplier',$socid); - */ - - print '
    '; - } - - - - /* - * Action presend - * - */ - if ($action == 'presend') - { - $ref = dol_sanitizeFileName($object->ref); - include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - $fileparams = dol_most_recent_file($conf->fournisseur->commande->dir_output . '/' . $ref); - $file=$fileparams['fullname']; - - // Build document if it not exists - if (! $file || ! is_readable($file)) - { - // Define output language - $outputlangs = $langs; - $newlang=''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id']; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->client->default_lang; - if (! empty($newlang)) - { - $outputlangs = new Translate("",$conf); - $outputlangs->setDefaultLang($newlang); - } - - $result=supplier_order_pdf_create($db, $object, GETPOST('model')?GETPOST('model'):$object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref, $hookmanager); - if ($result <= 0) - { - dol_print_error($db,$result); - exit; - } - $fileparams = dol_most_recent_file($conf->fournisseur->commande->dir_output . '/' . $ref); - $file=$fileparams['fullname']; - } - - print '
    '; - print_titre($langs->trans('SendOrderByMail')); - - // Cree l'objet formulaire mail - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; - $formmail = new FormMail($db); - $formmail->fromtype = 'user'; - $formmail->fromid = $user->id; - $formmail->fromname = $user->getFullName($langs); - $formmail->frommail = $user->email; - $formmail->withfrom=1; - $formmail->withto=empty($_POST["sendto"])?1:$_POST["sendto"]; - $formmail->withtosocid=$soc->id; - $formmail->withtocc=1; - $formmail->withtoccsocid=0; - $formmail->withtoccc=(! empty($conf->global->MAIN_EMAIL_USECCC)?$conf->global->MAIN_EMAIL_USECCC:false); - $formmail->withtocccsocid=0; - $formmail->withtopic=$langs->trans('SendOrderRef','__ORDERREF__'); - $formmail->withfile=2; - $formmail->withbody=1; - $formmail->withdeliveryreceipt=1; - $formmail->withcancel=1; - // Tableau des substitutions - $formmail->substit['__ORDERREF__']=$object->ref; - $formmail->substit['__SIGNATURE__']=$user->signature; - $formmail->substit['__PERSONALIZED__']=''; - // Tableau des parametres complementaires - $formmail->param['action']='send'; - $formmail->param['models']='order_supplier_send'; - $formmail->param['orderid']=$object->id; - $formmail->param['returnurl']=$_SERVER["PHP_SELF"].'?id='.$object->id; - - // Init list of files - if (GETPOST("mode")=='init') - { - $formmail->clear_attached_files(); - $formmail->add_attached_files($file,basename($file),dol_mimetype($file)); - } - - // Show form - $formmail->show_form(); - - print '
    '; - } - - print ''; - - } - else - { - // Commande non trouvee - dol_print_error($db); - } + print ''; } // End of page diff --git a/htdocs/fourn/commande/liste.php b/htdocs/fourn/commande/liste.php index 5bfbf4cff62..f5cd59ba8d5 100644 --- a/htdocs/fourn/commande/liste.php +++ b/htdocs/fourn/commande/liste.php @@ -122,7 +122,7 @@ if ($resql) print_barre_liste($title, $page, "liste.php", "", $sortfield, $sortorder, '', $num); print '
    '; - print ''; + print '
    '; print ''; print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"cf.ref","","",'',$sortfield,$sortorder); print_liste_field_titre($langs->trans("Company"),$_SERVER["PHP_SELF"],"s.nom","","",'',$sortfield,$sortorder); diff --git a/htdocs/fourn/facture/fiche.php b/htdocs/fourn/facture/fiche.php index 4e3d60848f6..6986b743dfd 100644 --- a/htdocs/fourn/facture/fiche.php +++ b/htdocs/fourn/facture/fiche.php @@ -82,7 +82,7 @@ if ($action == 'confirm_clone' && $confirm == 'yes') $result=$object->createFromClone($id); if ($result > 0) { - header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); + header("Location: ".$_SERVER['PHP_SELF'].'?action=editfacnumber&id='.$result); exit; } else @@ -466,10 +466,19 @@ elseif ($action == 'addline') } $ret=$object->fetch_thirdparty(); - if ($_POST['idprodfournprice']) // > 0 or -1 + if (GETPOST('search_idprodfournprice') || GETPOST('idprodfournprice')) // With combolist idprodfournprice is > 0 or -1, with autocomplete, idprodfournprice is > 0 or '' { - $product=new Product($db); - $idprod=$product->get_buyprice($_POST['idprodfournprice'], $_POST['qty']); // Just to see if a price exists for the quantity. Not used to found vat + $idprod=0; + $product=new Product($db); + + if (GETPOST('idprodfournprice') == '') + { + $idprod=-1; + } + if (GETPOST('idprodfournprice') > 0) + { + $idprod=$product->get_buyprice(GETPOST('idprodfournprice'), $_POST['qty']); // Just to see if a price exists for the quantity. Not used to found vat + } if ($idprod > 0) { @@ -1805,10 +1814,20 @@ else print ''; print ''; + // TODO Use the predefinedproductline_create.tpl.php file print ''; print ''; print ''; print ''; + + print ''; + $var=! $var; print ''; print ''; print ''; @@ -690,10 +685,10 @@ if (empty($id) || $action == 'add' || $action == 'request') print ''; print ''; @@ -706,7 +701,7 @@ if (empty($id) || $action == 'add' || $action == 'request') $valideurarray = $validator->listUsersForGroup(); print ''; print ''; print ''; @@ -758,35 +753,36 @@ else //print_fiche_titre($langs->trans('TitreRequestCP')); // Si il y a une erreur - if (GETPOST('error')) { - - switch(GETPOST('error')) { + if (GETPOST('error')) + { + switch(GETPOST('error')) + { case 'datefin' : - $errors[] = $langs->trans('ErrorEndDateCP'); + $errors[] = $langs->transnoentitiesnoconv('ErrorEndDateCP'); break; case 'SQL_Create' : - $errors[] = $langs->trans('ErrorSQLCreateCP').' '.htmlentities($_GET['msg']).''; + $errors[] = $langs->transnoentitiesnoconv('ErrorSQLCreateCP').' '.$_GET['msg']; break; case 'CantCreate' : - $errors[] = $langs->trans('CantCreateCP'); + $errors[] = $langs->transnoentitiesnoconv('CantCreateCP'); break; case 'Valideur' : - $errors[] = $langs->trans('InvalidValidatorCP'); + $errors[] = $langs->transnoentitiesnoconv('InvalidValidatorCP'); break; case 'nodatedebut' : - $errors[] = $langs->trans('NoDateDebut'); + $errors[] = $langs->transnoentitiesnoconv('NoDateDebut'); break; case 'nodatedebut' : - $errors[] = $langs->trans('NoDateFin'); + $errors[] = $langs->transnoentitiesnoconv('NoDateFin'); break; case 'DureeHoliday' : - $errors[] = $langs->trans('ErrorDureeCP'); + $errors[] = $langs->transnoentitiesnoconv('ErrorDureeCP'); break; case 'NoMotifRefuse' : - $errors[] = $langs->trans('NoMotifRefuseCP'); + $errors[] = $langs->transnoentitiesnoconv('NoMotifRefuseCP'); break; case 'mail' : - $errors[] = $langs->trans('ErrorMailNotSend').'
    '.$_GET['error_content'].''; + $errors[] = $langs->transnoentitiesnoconv('ErrorMailNotSend')."\n".$_GET['error_content']; break; } @@ -798,49 +794,45 @@ else { if ($action == 'delete' && $cp->statut == 1) { - if($user->rights->holiday->delete) { - $html = new Form($db); - - $ret=$html->form_confirm("fiche.php?id=".$_GET['id'],$langs->trans("TitleDeleteCP"),$langs->trans("ConfirmDeleteCP"),"confirm_delete", '', 0, 1); + if($user->rights->holiday->delete) + { + $ret=$form->form_confirm("fiche.php?id=".$id,$langs->trans("TitleDeleteCP"),$langs->trans("ConfirmDeleteCP"),"confirm_delete", '', 0, 1); if ($ret == 'html') print '
    '; } } // Si envoi en validation - if ($action == 'sendToValidate' && $cp->statut == 1 && $userID == $cp->fk_user) { - $html = new Form($db); - - $ret=$html->form_confirm("fiche.php?id=".$_GET['id'],$langs->trans("TitleToValidCP"),$langs->trans("ConfirmToValidCP"),"confirm_send", '', 0, 1); + if ($action == 'sendToValidate' && $cp->statut == 1 && $userID == $cp->fk_user) + { + $ret=$form->form_confirm("fiche.php?id=".$id,$langs->trans("TitleToValidCP"),$langs->trans("ConfirmToValidCP"),"confirm_send", '', 1, 1); if ($ret == 'html') print '
    '; } // Si validation de la demande - if ($action == 'valid' && $cp->statut == 2 && $userID == $cp->fk_validator) { - $html = new Form($db); - - $ret=$html->form_confirm("fiche.php?id=".$_GET['id'],$langs->trans("TitleValidCP"),$langs->trans("ConfirmValidCP"),"confirm_valid", '', 0, 1); + if ($action == 'valid' && $cp->statut == 2 && $userID == $cp->fk_validator) + { + $ret=$form->form_confirm("fiche.php?id=".$id,$langs->trans("TitleValidCP"),$langs->trans("ConfirmValidCP"),"confirm_valid", '', 1, 1); if ($ret == 'html') print '
    '; } // Si refus de la demande - if ($action == 'refuse' && $cp->statut == 2 && $userID == $cp->fk_validator) { - $html = new Form($db); - + if ($action == 'refuse' && $cp->statut == 2 && $userID == $cp->fk_validator) + { $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif de refus :",'name'=>"detail_refuse",'size'=>"50",'value'=>"")); - $ret=$html->form_confirm("fiche.php?id=".$_GET['id']."&action=confirm_refuse",$langs->trans("TitleRefuseCP"),"","confirm_refuse",$array_input,"",0); + $ret=$form->form_confirm("fiche.php?id=".$id."&action=confirm_refuse",$langs->trans("TitleRefuseCP"),"","confirm_refuse", $array_input, 1 ,0); if ($ret == 'html') print '
    '; } // Si annulation de la demande - if ($action == 'cancel' && $cp->statut == 2 && $userID == $cp->fk_validator) { - $html = new Form($db); - - $ret=$html->form_confirm("fiche.php?id=".$_GET['id'],$langs->trans("TitleCancelCP"),$langs->trans("ConfirmCancelCP"),"confirm_cancel", '', 0, 1); + if ($action == 'cancel' && $cp->statut == 2 && $userID == $cp->fk_validator) + { + $ret=$form->form_confirm("fiche.php?id=".$id,$langs->trans("TitleCancelCP"),$langs->trans("ConfirmCancelCP"),"confirm_cancel", '', 1, 1); if ($ret == 'html') print '
    '; } + $head=holiday_prepare_head($cp); - dol_fiche_head(array(),'card',$langs->trans("CPTitreMenu"),0,'holiday'); + dol_fiche_head($head,'card',$langs->trans("CPTitreMenu"),0,'holiday'); if ($action == 'edit' && $user->id == $cp->fk_user && $cp->statut == 1) @@ -849,8 +841,6 @@ else print ''."\n"; print ''."\n"; print ''."\n"; - - $html = new Form($db); } print '
     
    '; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index e16cbc29229..be90f452158 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -89,6 +89,12 @@ class Holiday extends CommonObject global $conf, $langs; $error=0; + $now=dol_now(); + + // Check parameters + if (empty($this->fk_user) || ! is_numeric($this->fk_user) || $this->fk_user < 0) { $this->error="ErrorBadParameter"; return -1; } + if (empty($this->fk_validator) || ! is_numeric($this->fk_validator) || $this->fk_validator < 0) { $this->error="ErrorBadParameter"; return -1; } + // Insert request $sql = "INSERT INTO ".MAIN_DB_PREFIX."holiday("; @@ -103,22 +109,13 @@ class Holiday extends CommonObject $sql.= ") VALUES ("; // User - if(!empty($this->fk_user)) { - $sql.= "'".$this->fk_user."',"; - } else { - $error++; - } - $sql.= " NOW(),"; + $sql.= "'".$this->fk_user."',"; + $sql.= " '".$this->db->idate($now)."',"; $sql.= " '".addslashes($this->description)."',"; $sql.= " '".$this->db->idate($this->date_debut)."',"; $sql.= " '".$this->db->idate($this->date_fin)."',"; $sql.= " '1',"; - if(is_numeric($this->fk_validator)) { - $sql.= " '".$this->fk_validator."'"; - } - else { - $error++; - } + $sql.= " '".$this->fk_validator."'"; $sql.= ")"; @@ -183,7 +180,6 @@ class Holiday extends CommonObject $sql.= " cp.fk_user_cancel,"; $sql.= " cp.detail_refuse"; - $sql.= " FROM ".MAIN_DB_PREFIX."holiday as cp"; $sql.= " WHERE cp.rowid = ".$id; @@ -195,7 +191,8 @@ class Holiday extends CommonObject { $obj = $this->db->fetch_object($resql); - $this->rowid = $obj->rowid; + $this->id = $obj->rowid; + $this->rowid = $obj->rowid; // deprecated $this->fk_user = $obj->fk_user; $this->date_create = $this->db->jdate($obj->date_create); $this->description = $obj->description; @@ -210,8 +207,6 @@ class Holiday extends CommonObject $this->date_cancel = $this->db->jdate($obj->date_cancel); $this->fk_user_cancel = $obj->fk_user_cancel; $this->detail_refuse = $obj->detail_refuse; - - } $this->db->free($resql); @@ -226,12 +221,12 @@ class Holiday extends CommonObject } /** - * Liste les congés payés pour un utilisateur + * List holidays for a particular user * - * @param int $user_id ID de l'utilisateur à lister - * @param string $order Filtrage par ordre - * @param string $filter Filtre de séléction - * @return int -1 si erreur, 1 si OK et 2 si pas de résultat + * @param int $user_id ID of user to list + * @param string $order Sort order + * @param string $filter SQL Filter + * @return int -1 if KO, 1 if OK, 2 if no result */ function fetchByUser($user_id,$order='',$filter='') { @@ -321,11 +316,11 @@ class Holiday extends CommonObject } /** - * Liste les congés payés de tout les utilisateurs + * List all holidays of all users * - * @param string $order Filtrage par ordre - * @param string $filter Filtre de séléction - * @return int -1 si erreur, 1 si OK et 2 si pas de résultat + * @param string $order Sort order + * @param string $filter SQL Filter + * @return int -1 if KO, 1 if OK, 2 if no result */ function fetchAll($order,$filter) { @@ -384,13 +379,13 @@ class Holiday extends CommonObject $tab_result[$i]['rowid'] = $obj->rowid; $tab_result[$i]['fk_user'] = $obj->fk_user; - $tab_result[$i]['date_create'] = $obj->date_create; + $tab_result[$i]['date_create'] = $this->db->jdate($obj->date_create); $tab_result[$i]['description'] = $obj->description; - $tab_result[$i]['date_debut'] = $obj->date_debut; - $tab_result[$i]['date_fin'] = $obj->date_fin; + $tab_result[$i]['date_debut'] = $this->db->jdate($obj->date_debut); + $tab_result[$i]['date_fin'] = $this->db->jdate($obj->date_fin); $tab_result[$i]['statut'] = $obj->statut; $tab_result[$i]['fk_validator'] = $obj->fk_validator; - $tab_result[$i]['date_valid'] = $obj->date_valid; + $tab_result[$i]['date_valid'] = $this->db->jdate($obj->date_valid); $tab_result[$i]['fk_user_valid'] = $obj->fk_user_valid; $tab_result[$i]['date_refuse'] = $obj->date_refuse; $tab_result[$i]['fk_user_refuse'] = $obj->fk_user_refuse; @@ -1595,5 +1590,27 @@ class Holiday extends CommonObject } } + /** + * Initialise an instance with random values. + * Used to build previews or test instances. + * id must be 0 if object instance is a specimen. + * + * @return void + */ + function initAsSpecimen() + { + global $user,$langs; + + // Initialise parameters + $this->id=0; + $this->specimen=1; + + $this->fk_user=1; + $this->description='SPECIMEN description'; + $this->date_debut=dol_now(); + $this->date_fin=dol_now()+(24*3600); + $this->fk_validator=1; + } + } ?> diff --git a/htdocs/holiday/fiche.php b/htdocs/holiday/fiche.php index 38911ca13da..18af62b7feb 100644 --- a/htdocs/holiday/fiche.php +++ b/htdocs/holiday/fiche.php @@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/holiday.lib.php'; require_once DOL_DOCUMENT_ROOT.'/holiday/common.inc.php'; // Get parameters @@ -262,29 +263,27 @@ if ($action == 'confirm_send') $verif = $cp->update($user->id); // Si pas d'erreur SQL on redirige vers la fiche de la demande - if($verif > 0) { - - // A + if ($verif > 0) + { + // To $destinataire = new User($db); $destinataire->fetch($cp->fk_validator); $emailTo = $destinataire->email; - // De + // From $expediteur = new User($db); $expediteur->fetch($cp->fk_user); $emailFrom = $expediteur->email; - // Sujet - if($conf->global->MAIN_APPLICATION_TITLE != NULL) { - $societeName = addslashes($conf->global->MAIN_APPLICATION_TITLE); - } else { - $societeName = addslashes($conf->global->MAIN_INFO_SOCIETE_NOM); - } + // Subject + $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; + if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; - $subject = stripslashes($societeName)." - Demande de congés payés à valider"; + $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysToValidate"); - // Contenu - $message = "Bonjour {$destinataire->prenom},\n\n"; + // Content + $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->prenom.",\n"; + $message.= "\n"; $message.= "Veuillez trouver ci-dessous une demande de congés payés à valider.\n"; $delayForRequest = $cp->getConfCP('delayForRequest'); @@ -293,16 +292,18 @@ if ($action == 'confirm_send') $nextMonth = dol_time_plus_duree($now, $delayForRequest, 'd'); // Si l'option pour avertir le valideur en cas de délai trop court - if($cp->getConfCP('AlertValidatorDelay')) { - if($cp->date_debut < $nextMonth) { + if($cp->getConfCP('AlertValidatorDelay')) + { + if($cp->date_debut < $nextMonth) + { $message.= "\n"; - $message.= "Cette demande de congés payés à été effectué dans un"; - $message.= " délai de moins de ".$cp->getConfCP('delayForRequest')." jours avant ceux-ci.\n"; + $message.= "Cette demande de congés payés à été effectué dans un délai de moins de ".$cp->getConfCP('delayForRequest')." jours avant ceux-ci.\n"; } } // Si l'option pour avertir le valideur en cas de solde inférieur à la demande - if($cp->getConfCP('AlertValidatorSolde')) { + if($cp->getConfCP('AlertValidatorSolde')) + { $nbopenedday=num_open_day($cp->date_debut,$cp->date_fin,0,1); if ($nbopenedday > $cp->getCPforUser($cp->fk_user)) { @@ -312,24 +313,26 @@ if ($action == 'confirm_send') } $message.= "\n"; - $message.= "- Demandeur : {$expediteur->prenom} {$expediteur->nom}\n"; - $message.= "- Période : du ".date('d/m/Y',strtotime($cp->date_debut))." au ".date('d/m/Y',strtotime($cp->date_fin))."\n"; - $message.= "- Lien : {$dolibarr_main_url_root}/holiday/fiche.php?id={$cp->rowid}\n\n"; - $message.= "Bien cordialement,\n".$societeName; + $message.= "- ".$langs->transnoentitiesnoconv("Name")." : ".$expediteur->prenom." ".$expediteur->nom."\n"; + $message.= "- ".$langs->transnoentitiesnoconv("Period")." : ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')."\n"; + $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n"; + $message.= "\n"; $mail = new CMailFile($subject,$emailTo,$emailFrom,$message); // Envoi du mail $result=$mail->sendfile(); - if(!$result) { + if (!$result) + { header('Location: fiche.php?id='.$_GET['id'].'&error=mail&error_content='.$mail->error); exit; } - header('Location: fiche.php?id='.$_GET['id']); exit; - } else { + } + else + { // Sinon on affiche le formulaire de demande avec le message d'erreur SQL header('Location: fiche.php?id='.$_GET['id'].'&error=SQL_Create&msg='.$cp->error); exit; @@ -366,37 +369,34 @@ if($action == 'confirm_valid') $newSolde = $soldeActuel - ($nbJour*$cp->getConfCP('nbHolidayDeducted')); // On ajoute la modification dans le LOG - $cp->addLogCP($userID,$cp->fk_user,'Event : Prise de congés payés',$newSolde); + $cp->addLogCP($userID,$cp->fk_user,'Event : '.$langs->transnoentitiesnoconv("Holiday"),$newSolde); // Mise à jour du solde $cp->updateSoldeCP($cp->fk_user,$newSolde); - // A + // To $destinataire = new User($db); $destinataire->fetch($cp->fk_user); $emailTo = $destinataire->email; - // De + // From $expediteur = new User($db); $expediteur->fetch($cp->fk_validator); $emailFrom = $expediteur->email; - // Sujet - if($conf->global->MAIN_APPLICATION_TITLE != NULL) { - $societeName = addslashes($conf->global->MAIN_APPLICATION_TITLE); - } else { - $societeName = addslashes($conf->global->MAIN_INFO_SOCIETE_NOM); - } + // Subject + $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; + if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; - $subject = stripslashes($societeName)." - Demande de congés payés validée"; - - // Contenu - $message = "Bonjour {$destinataire->prenom},\n\n"; - $message.= "Votre demande de congés payés du ".$cp->date_debut." au ".$cp->date_fin." vient d'être validée!\n"; - $message.= "- Valideur : {$expediteur->prenom} {$expediteur->nom}\n"; - $message.= "- Lien : {$dolibarr_main_url_root}/holiday/fiche.php?id={$cp->rowid}\n\n"; - $message.= "Bien cordialement,\n".$societeName; + $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysValidated"); + // Content + $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->prenom.",\n"; + $message.= "\n"; + $message.= "Votre demande de congés payés du ".dol_print_date($cp->date_debut,'day')." au ".dol_print_date($cp->date_fin,'day')." vient d'être validée!\n"; + $message.= "- ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".$expediteur->prenom." ".$expediteur->nom."\n"; + $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n"; + $message.= "\n"; $mail = new CMailFile($subject,$emailTo,$emailFrom,$message); @@ -442,33 +442,30 @@ if ($action == 'confirm_refuse') // Si pas d'erreur SQL on redirige vers la fiche de la demande if($verif > 0) { - // A + // To $destinataire = new User($db); $destinataire->fetch($cp->fk_user); $emailTo = $destinataire->email; - // De + // From $expediteur = new User($db); $expediteur->fetch($cp->fk_validator); $emailFrom = $expediteur->email; - // Sujet - if($conf->global->MAIN_APPLICATION_TITLE != NULL) { - $societeName = addslashes($conf->global->MAIN_APPLICATION_TITLE); - } else { - $societeName = addslashes($conf->global->MAIN_INFO_SOCIETE_NOM); - } + // Subject + $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; + if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; - $subject = stripslashes($societeName)." - Demande de congés payés refusée"; + $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysRefused"); - // Contenu - $message = "Bonjour {$destinataire->prenom},\n\n"; - $message.= "Votre demande de congés payés ".$cp->date_debut." au ".$cp->date_fin." vient d'être refusée pour le motif suivant :\n"; + // Content + $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->prenom.",\n"; + $message.= "\n"; + $message.= "Votre demande de congés payés ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')." vient d'être refusée pour le motif suivant :\n"; $message.= $_POST['detail_refuse']."\n\n"; - $message.= "- Valideur : {$expediteur->prenom} {$expediteur->nom}\n"; - $message.= "- Lien : {$dolibarr_main_url_root}/holiday/fiche.php?id={$cp->rowid}\n\n"; - $message.= "Bien cordialement,\n".$societeName; - + $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".$expediteur->prenom." ".$expediteur->nom."\n"; + $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n"; + $message.= "\n"; $mail = new CMailFile($subject,$emailTo,$emailFrom,$message); @@ -516,32 +513,29 @@ if ($action == 'confirm_cancel' && $_GET['confirm'] == 'yes') // Si pas d'erreur SQL on redirige vers la fiche de la demande if($verif > 0) { - // A + // To $destinataire = new User($db); $destinataire->fetch($cp->fk_user); $emailTo = $destinataire->email; - // De + // From $expediteur = new User($db); $expediteur->fetch($cp->fk_validator); $emailFrom = $expediteur->email; - // Sujet - if($conf->global->MAIN_APPLICATION_TITLE != NULL) { - $societeName = addslashes($conf->global->MAIN_APPLICATION_TITLE); - } else { - $societeName = addslashes($conf->global->MAIN_INFO_SOCIETE_NOM); - } + // Subject + $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; + if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; - $subject = stripslashes($societeName)."- Demande de congés payés annulée"; - - // Contenu - $message = "Bonjour {$destinataire->prenom},\n\n"; - $message.= "Votre demande de congés payés ".$cp->date_debut." au ".$cp->date_fin." vient d'être annulée !\n"; - $message.= "- Valideur : {$expediteur->prenom} {$expediteur->nom}\n"; - $message.= "- Lien : {$dolibarr_main_url_root}/holiday/fiche.php?id={$cp->rowid}\n\n"; - $message.= "Bien cordialement,\n".$societeName; + $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysCanceled"); + // Content + $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->prenom.",\n"; + $message.= "\n"; + $message.= "Votre demande de congés ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')." va été annulée.\n"; + $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".$expediteur->prenom." ".$expediteur->nom."\n"; + $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n"; + $message.= "\n"; $mail = new CMailFile($subject,$emailTo,$emailFrom,$message); @@ -570,9 +564,11 @@ if ($action == 'confirm_cancel' && $_GET['confirm'] == 'yes') -/*************************************************** +/* * View -****************************************************/ + */ + +$form = new Form($db); llxHeader(array(),$langs->trans('CPTitreMenu')); @@ -621,7 +617,6 @@ if (empty($id) || $action == 'add' || $action == 'request') dol_htmloutput_mesg('',$errors,'error'); } - $html = new Form($db); $cp = new Holiday($db); $delayForRequest = $cp->getConfCP('delayForRequest'); @@ -678,10 +673,10 @@ if (empty($id) || $action == 'add' || $action == 'request') print ''; // Si la demande ne vient pas de l'agenda if(!isset($_GET['datep'])) { - $html->select_date(-1,'date_debut_'); + $form->select_date(-1,'date_debut_'); } else { $tmpdate = dol_mktime(0, 0, 0, GETPOST('datepmonth'), GETPOST('datepday'), GETPOST('datepyear')); - $html->select_date($tmpdate,'date_debut_'); + $form->select_date($tmpdate,'date_debut_'); } print '
    '; // Si la demande ne vient pas de l'agenda if(!isset($_GET['datep'])) { - $html->select_date(-1,'date_fin_'); + $form->select_date(-1,'date_fin_'); } else { $tmpdate = dol_mktime(0, 0, 0, GETPOST('datefmonth'), GETPOST('datefday'), GETPOST('datefyear')); - $html->select_date($tmpdate,'date_fin_'); + $form->select_date($tmpdate,'date_fin_'); } print '
    '; - print $html->select_dolusers($validator->id, "valideur", 1, "", 0, $valideurarray); + print $form->select_dolusers($validator->id, "valideur", 1, "", 0, $valideurarray); print '
    '; @@ -873,7 +863,7 @@ else print ''; print ''; print ''; print ''; } @@ -887,7 +877,7 @@ else print ''; print ''; print ''; print ''; } @@ -952,7 +942,7 @@ else $valideur = $validator->listUsersForGroup(); print ''; print ''; } @@ -982,44 +972,44 @@ else print ''; print '
    '.$langs->trans('DateDebCP').''; - $html->select_date($cp->date_debut,'date_debut_'); + $form->select_date($cp->date_debut,'date_debut_'); print '
    '.$langs->trans('DateFinCP').''; - $html->select_date($cp->date_fin,'date_fin_'); + $form->select_date($cp->date_fin,'date_fin_'); print '
    '; - $html->select_users($cp->fk_validator,"valideur",1,"",0,$valideur,''); + $form->select_users($cp->fk_validator,"valideur",1,"",0,$valideur,''); print '
    '; - dol_fiche_end(); - - print '
    '."\n"; - - if ($edit) + if ($edit && $user->id == $cp->fk_user && $cp->statut == 1) { - print '
    '; + print '
    '; if($user->rights->holiday->write && $_GET['action'] == 'edit' && $cp->statut == 1) { print ''; } - print '
    '; + print '
    '; print ''; } + dol_fiche_end(); + if (! $edit) { - print '
    '; - print '
    '."\n"; + print '
    '; // Boutons d'actions - - if($user->rights->holiday->write && $_GET['action'] != 'edit' && $cp->statut == 1) { - print ''.$langs->trans("EditCP").''; + if($user->rights->holiday->write && $_GET['action'] != 'edit' && $cp->statut == 1) + { + print ''.$langs->trans("EditCP").''; } - if($user->rights->holiday->delete && $cp->statut == 1) { - print ''.$langs->trans("DeleteCP").''; + if($user->rights->holiday->delete && $cp->statut == 1) + { + print ''.$langs->trans("DeleteCP").''; } - if($user->id == $cp->fk_user && $cp->statut == 1) { - print ''.$langs->trans("SendToValidationCP").''; + if($user->id == $cp->fk_user && $cp->statut == 1) + { + print ''.$langs->trans("SendToValidationCP").''; } // Si le statut est en attente de validation et que le valideur est connecté - if($userID == $cp->fk_validator && $cp->statut == 2) { - print ''.$langs->trans("ActionValidCP").''; - print ''.$langs->trans("ActionRefuseCP").''; - print ''.$langs->trans("ActionCancelCP").''; + if($userID == $cp->fk_validator && $cp->statut == 2) + { + print ''.$langs->trans("ActionValidCP").''; + print ''.$langs->trans("ActionRefuseCP").''; + print ''.$langs->trans("ActionCancelCP").''; } print '
    '; diff --git a/htdocs/holiday/index.php b/htdocs/holiday/index.php index 1c27e2978bf..12e0c0fb493 100644 --- a/htdocs/holiday/index.php +++ b/htdocs/holiday/index.php @@ -26,6 +26,7 @@ require('../main.inc.php'); require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; require_once DOL_DOCUMENT_ROOT.'/holiday/common.inc.php'; @@ -56,6 +57,7 @@ $search_employe = GETPOST('search_employe'); $search_valideur = GETPOST('search_valideur'); $search_statut = GETPOST('select_statut'); +$holiday = new Holiday($db); /* * Actions @@ -78,8 +80,9 @@ llxHeader(array(),$langs->trans('CPTitreMenu')); $order = $db->order($sortfield,$sortorder).$db->plimit($conf->liste_limit + 1, $offset); // WHERE -if(!empty($search_ref)){ - $filter.= " AND cp.rowid LIKE '%$search_ref%'\n"; +if(!empty($search_ref)) +{ + $filter.= " AND cp.rowid LIKE '%".$db->escape($search_ref)."%'\n"; } // DATE START @@ -123,17 +126,17 @@ if($year_create > 0) { // EMPLOYE if(!empty($search_employe) && $search_employe != -1) { - $filter.= " AND cp.fk_user = '$search_employe'\n"; + $filter.= " AND cp.fk_user = '".$db->escape($search_employe)."'\n"; } // VALIDEUR if(!empty($search_valideur) && $search_valideur != -1) { - $filter.= " AND cp.fk_validator = '$search_valideur'\n"; + $filter.= " AND cp.fk_validator = '".$db->escape($search_valideur)."'\n"; } // STATUT if(!empty($search_statut) && $search_statut != -1) { - $filter.= " AND cp.statut = '$search_statut'\n"; + $filter.= " AND cp.statut = '".$db->escape($search_statut)."'\n"; } /************************************* @@ -144,19 +147,17 @@ if(!empty($search_statut) && $search_statut != -1) { $user_id = $user->id; // Récupération des congés payés de l'utilisateur ou de tous les users -if(!$user->rights->holiday->lire_tous) +if (!$user->rights->holiday->lire_tous) { - $holiday = new Holiday($db); $holiday_payes = $holiday->fetchByUser($user_id,$order,$filter); } else { - $holiday = new Holiday($db); $holiday_payes = $holiday->fetchAll($order,$filter); } // Si pas de congés payés -if($holiday_payes == 0) +if ($holiday_payes == 0) { print_fiche_titre($langs->trans('CPTitreMenu')); @@ -168,7 +169,7 @@ if($holiday_payes == 0) } // Si erreur SQL -if($holiday_payes == '-1') +if ($holiday_payes == '-1') { print_fiche_titre($langs->trans('CPTitreMenu')); @@ -281,21 +282,20 @@ if (! empty($holiday->holiday)) $validator = new User($db); $validator->fetch($infos_CP['fk_validator']); - $date = date_create($infos_CP['date_create']); - $date = date_format($date,'Y-m-d'); + $date = $infos_CP['date_create']; $statut = $holiday->getStatutCP($infos_CP['statut']); print ''; print 'CP '.$infos_CP['rowid'].''; - print ''.$date.''; + print ''.dol_print_date($date,'day').''; print ''.$user->getNomUrl('1').''; print ''.$validator->getNomUrl('1').''; - print ''.$infos_CP['date_debut'].''; - print ''.$infos_CP['date_fin'].''; + print ''.dol_print_date($infos_CP['date_debut'],'day').''; + print ''.dol_print_date($infos_CP['date_fin'],'day').''; print ''; $nbopenedday=num_open_day($infos_CP['date_debut'],$infos_CP['date_fin'],0,1); - print $nbopenedday.' '.$langs->trans('Jours'); + print $nbopenedday; print ''.$statut.''; print ''."\n"; @@ -318,7 +318,7 @@ print '
    '; print ''.$langs->trans('AddCP').''; print '
    '; -// Fin de page -$db->close(); llxFooter(); + +$db->close(); ?> diff --git a/htdocs/holiday/month_report.php b/htdocs/holiday/month_report.php index f581375463b..b581a3b5bfd 100644 --- a/htdocs/holiday/month_report.php +++ b/htdocs/holiday/month_report.php @@ -26,6 +26,7 @@ require('../main.inc.php'); require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/holiday/common.inc.php'; // Protection if external user diff --git a/htdocs/holiday/view_log.php b/htdocs/holiday/view_log.php index 4731b29d956..5c212a87ea6 100644 --- a/htdocs/holiday/view_log.php +++ b/htdocs/holiday/view_log.php @@ -87,7 +87,7 @@ foreach($cp->logs as $logs_CP) if($log_holiday == '2') { print ''; - print ''.$langs->trans('NoResult').''; + print ''.$langs->trans('NoResults').''; print ''; } diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index c942bd23efe..8b90a1178c6 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -1498,7 +1498,7 @@ if ($step == 6 && $datatoimport) // Source file format print ''.$langs->trans("SourceFileFormat").''; print ''; - $text=$objmodelimport->getDriverDesc($format); + $text=$objmodelimport->getDriverDescForKey($format); print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format),$text); print ''; diff --git a/htdocs/includes/jquery/js/jquery-latest.min.jgz b/htdocs/includes/jquery/js/jquery-latest.min.jgz deleted file mode 100644 index 7d052bcf861..00000000000 Binary files a/htdocs/includes/jquery/js/jquery-latest.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/js/jquery-ui-latest.custom.min.jgz b/htdocs/includes/jquery/js/jquery-ui-latest.custom.min.jgz deleted file mode 100644 index 8bfca3a3e04..00000000000 Binary files a/htdocs/includes/jquery/js/jquery-ui-latest.custom.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/datatables/extras/Bootstrap/js/DT_bootstrap.jgz b/htdocs/includes/jquery/plugins/datatables/extras/Bootstrap/js/DT_bootstrap.jgz deleted file mode 100644 index 17b30bd297b..00000000000 Binary files a/htdocs/includes/jquery/plugins/datatables/extras/Bootstrap/js/DT_bootstrap.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/datatables/extras/ColReorder/js/ColReorder.min.jgz b/htdocs/includes/jquery/plugins/datatables/extras/ColReorder/js/ColReorder.min.jgz deleted file mode 100644 index 5790b3785af..00000000000 Binary files a/htdocs/includes/jquery/plugins/datatables/extras/ColReorder/js/ColReorder.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/datatables/extras/ColVis/js/ColVis.min.jgz b/htdocs/includes/jquery/plugins/datatables/extras/ColVis/js/ColVis.min.jgz deleted file mode 100644 index 517c50c5592..00000000000 Binary files a/htdocs/includes/jquery/plugins/datatables/extras/ColVis/js/ColVis.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/datatables/extras/TableTools/js/TableTools.min.jgz b/htdocs/includes/jquery/plugins/datatables/extras/TableTools/js/TableTools.min.jgz deleted file mode 100644 index a467a5f2008..00000000000 Binary files a/htdocs/includes/jquery/plugins/datatables/extras/TableTools/js/TableTools.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/datatables/js/jquery.dataTables.min.jgz b/htdocs/includes/jquery/plugins/datatables/js/jquery.dataTables.min.jgz deleted file mode 100644 index e7a91f87f75..00000000000 Binary files a/htdocs/includes/jquery/plugins/datatables/js/jquery.dataTables.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/jeditable/jquery.jeditable.min.jgz b/htdocs/includes/jquery/plugins/jeditable/jquery.jeditable.min.jgz deleted file mode 100644 index c6f41e14005..00000000000 Binary files a/htdocs/includes/jquery/plugins/jeditable/jquery.jeditable.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/jstree/jquery.jstree.min.jgz b/htdocs/includes/jquery/plugins/jstree/jquery.jstree.min.jgz deleted file mode 100644 index 8ba61f32afc..00000000000 Binary files a/htdocs/includes/jquery/plugins/jstree/jquery.jstree.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.jgz b/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.jgz deleted file mode 100644 index a3c068acb0e..00000000000 Binary files a/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.js b/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.js index a25c9eb872c..270ddb1d08e 100644 --- a/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.js +++ b/htdocs/includes/jquery/plugins/layout/jquery.layout-latest.js @@ -1,4353 +1,5919 @@ -/** - * @preserve jquery.layout 1.3.0 - Release Candidate 29.15 - * $Date: 2011/07/06 11:40:21 $ - * $Rev: 302915 $ - * - * Copyright (c) 2010 - * Fabrizio Balliano (http://www.fabrizioballiano.net) - * Kevin Dalman (http://allpro.net) - * - * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) - * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. - * - * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc29.15 - * - * Docs: http://layout.jquery-dev.net/documentation.html - * Tips: http://layout.jquery-dev.net/tips.html - * Help: http://groups.google.com/group/jquery-ui-layout - */ - -// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars - -;(function ($) { - -/* - * GENERIC $.layout METHODS - used by all layouts - */ -$.layout = { - - version: "1.3.rc29.15" -, revision: 0.032915 // 1.3.0 final = 1.0300 - major(n+).minor(nn)+patch(nn+) - - // LANGUAGE CUSTOMIZATION -, language: { - // Tips and messages for resizers, togglers, custom buttons, etc. - Open: "Open" // eg: "Open Pane" - , Close: "Close" - , Resize: "Resize" - , Slide: "Slide Open" - , Pin: "Pin" - , Unpin: "Un-Pin" - , noRoomToOpenTip: "Not enough room to show this pane." - // Developer error messages - , pane: "pane" // description of "layout pane element" - , selector: "selector" // description of "jQuery-selector" - , errButton: "Error Adding Button \n\nInvalid " - , errContainerMissing: "UI Layout Initialization Error\n\nThe specified layout-container does not exist." - , errCenterPaneMissing: "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element." - , errContainerHeight: "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!" - } - - // can update code here if $.browser is phased out -, browser: { - mozilla: !!$.browser.mozilla - , webkit: !!$.browser.webkit || !!$.browser.safari // webkit = jQ 1.4 - , msie: !!$.browser.msie - , isIE6: !!$.browser.msie && $.browser.version == 6 - , boxModel: false // page must load first, so will be updated set by _create - //, version: $.browser.version - not used - } - - /* - * GENERIC UTILITY METHODS - */ - - // calculate and return the scrollbar width, as an integer -, scrollbarWidth: function () { return window.scrollbarWidth || $.layout.getScrollbarSize('width'); } -, scrollbarHeight: function () { return window.scrollbarHeight || $.layout.getScrollbarSize('height'); } -, getScrollbarSize: function (dim) { - var $c = $('
    ').appendTo("body"); - var d = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight }; - $c.remove(); - window.scrollbarWidth = d.width; - window.scrollbarHeight = d.height; - return dim.match(/^(width|height)$/i) ? d[dim] : d; - } - - - /** - * Returns hash container 'display' and 'visibility' - * - * @see $.swap() - swaps CSS, runs callback, resets CSS - */ -, showInvisibly: function ($E, force) { - if (!$E) return {}; - if (!$E.jquery) $E = $($E); - var CSS = { - display: $E.css('display') - , visibility: $E.css('visibility') - }; - if (force || CSS.display == "none") { // only if not *already hidden* - $E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so can be measured - return CSS; - } - else return {}; - } - - /** - * Returns data for setting size of an element (container or a pane). - * - * @see _create(), onWindowResize() for container, plus others for pane - * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc - */ -, getElementDimensions: function ($E) { - var - d = {} // dimensions hash - , x = d.css = {} // CSS hash - , i = {} // TEMP insets - , b, p // TEMP border, padding - , N = $.layout.cssNum - , off = $E.offset() - ; - d.offsetLeft = off.left; - d.offsetTop = off.top; - - $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge - b = x["border" + e] = $.layout.borderWidth($E, e); - p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e); - i[e] = b + p; // total offset of content from outer side - d["inset"+ e] = p; - }); - - d.offsetWidth = $E.innerWidth(); - d.offsetHeight = $E.innerHeight(); - d.outerWidth = $E.outerWidth(); - d.outerHeight = $E.outerHeight(); - d.innerWidth = Math.max(0, d.outerWidth - i.Left - i.Right); - d.innerHeight = Math.max(0, d.outerHeight - i.Top - i.Bottom); - - x.width = $E.width(); - x.height = $E.height(); - x.top = N($E,"top",true); - x.bottom = N($E,"bottom",true); - x.left = N($E,"left",true); - x.right = N($E,"right",true); - - //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0; - - return d; - } - -, getElementCSS: function ($E, list) { - var - CSS = {} - , style = $E[0].style - , props = list.split(",") - , sides = "Top,Bottom,Left,Right".split(",") - , attrs = "Color,Style,Width".split(",") - , p, s, a, i, j, k - ; - for (i=0; i < props.length; i++) { - p = props[i]; - if (p.match(/(border|padding|margin)$/)) - for (j=0; j < 4; j++) { - s = sides[j]; - if (p == "border") - for (k=0; k < 3; k++) { - a = attrs[k]; - CSS[p+s+a] = style[p+s+a]; - } - else - CSS[p+s] = style[p+s]; - } - else - CSS[p] = style[p]; - }; - return CSS - } - - /** - * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype - * - * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() - * @param {Array.} $E Must pass a jQuery object - first element is processed - * @param {number=} outerWidth/outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerWidth/Height of the elem by subtracting padding and borders - */ -, cssWidth: function ($E, outerWidth) { - var - b = $.layout.borderWidth - , n = $.layout.cssNum - ; - // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed - if (outerWidth <= 0) return 0; - - if (!$.layout.browser.boxModel) return outerWidth; - - // strip border and padding from outerWidth to get CSS Width - var W = outerWidth - - b($E, "Left") - - b($E, "Right") - - n($E, "paddingLeft") - - n($E, "paddingRight") - ; - - return Math.max(0,W); - } - -, cssHeight: function ($E, outerHeight) { - var - b = $.layout.borderWidth - , n = $.layout.cssNum - ; - // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed - if (outerHeight <= 0) return 0; - - if (!$.layout.browser.boxModel) return outerHeight; - - // strip border and padding from outerHeight to get CSS Height - var H = outerHeight - - b($E, "Top") - - b($E, "Bottom") - - n($E, "paddingTop") - - n($E, "paddingBottom") - ; - - return Math.max(0,H); - } - - /** - * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist - * - * @see Called by many methods - * @param {Array.} $E Must pass a jQuery object - first element is processed - * @param {string} prop The name of the CSS property, eg: top, width, etc. - * @param {boolean=} allowAuto true = return 'auto' if that is value; false = return 0 - * @return {(string|number)} Usually used to get an integer value for position (top, left) or size (height, width) - */ -, cssNum: function ($E, prop, allowAuto) { - if (!$E.jquery) $E = $($E); - var CSS = $.layout.showInvisibly($E) - , p = $.curCSS($E[0], prop, true) - , v = allowAuto && p=="auto" ? p : (parseInt(p, 10) || 0); - $E.css( CSS ); // RESET - return v; - } - -, borderWidth: function (el, side) { - if (el.jquery) el = el[0]; - var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left - return $.curCSS(el, b+"Style", true) == "none" ? 0 : (parseInt($.curCSS(el, b+"Width", true), 10) || 0); - } - - - /** - * UTLITY for mouse tracking - FUTURE REFERENCE - * - * init: if (!window.mouse) { - * window.mouse = { x: 0, y: 0 }; - * $(document).mousemove( $.layout.trackMouse ); - * } - * - * @param {Object} evt - * -, trackMouse: function (evt) { - window.mouse = { x: evt.clientX, y: evt.clientY }; - } - */ - - /** - * SUBROUTINE for preventPrematureSlideClose option - * - * @param {Object} evt - * @param {Object=} el - */ -, isMouseOverElem: function (evt, el) { - var - $E = $(el || this) - , d = $E.offset() - , T = d.top - , L = d.left - , R = L + $E.outerWidth() - , B = T + $E.outerHeight() - , x = evt.pageX // evt.clientX ? - , y = evt.pageY // evt.clientY ? - ; - // if X & Y are < 0, probably means is over an open SELECT - return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B)); - } - -}; - -$.fn.layout = function (opts) { - -/* - * ########################### - * WIDGET CONFIG & OPTIONS - * ########################### - */ - var - - // LANGUAGE - for tips & messages - lang = $.layout.language // internal alias - - // DEFAULT OPTIONS - CHANGE IF DESIRED -, options = { - name: "" // Not required, but useful for buttons and used for the state-cookie - , containerClass: "ui-layout-container" // layout-container element - , scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark) - , resizeWithWindow: true // bind thisLayout.resizeAll() to the window.resize event - , resizeWithWindowDelay: 200 // delay calling resizeAll because makes window resizing very jerky - , resizeWithWindowMaxDelay: 0 // 0 = none - force resize every XX ms while window is being resized - , onresizeall_start: null // CALLBACK when resizeAll() STARTS - NOT pane-specific - , onresizeall_end: null // CALLBACK when resizeAll() ENDS - NOT pane-specific - , onload_start: null // CALLBACK when Layout inits - after options initialized, but before elements - , onload_end: null // CALLBACK when Layout inits - after EVERYTHING has been initialized - , onunload_start: null // CALLBACK when Layout is destroyed OR onWindowUnload - , onunload_end: null // CALLBACK when Layout is destroyed OR onWindowUnload - , autoBindCustomButtons: false // search for buttons with ui-layout-button class and auto-bind them - , zIndex: null // the PANE zIndex - resizers and masks will be +1 - , initPanes: true // false = DO NOT initialize the panes onLoad - will init later - , showErrorMessages: true // enables fatal error messages to warn developers of common errors - // PANE SETTINGS - , defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings' - applyDemoStyles: false // NOTE: renamed from applyDefaultStyles for clarity - , closable: true // pane can open & close - , resizable: true // when open, pane can be resized - , slidable: true // when closed, pane can 'slide open' over other panes - closes on mouse-out - , initClosed: false // true = init pane as 'closed' - , initHidden: false // true = init pane as 'hidden' - no resizer-bar/spacing - // SELECTORS - //, paneSelector: "" // MUST be pane-specific - jQuery selector for pane - , contentSelector: ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane! - , contentIgnoreSelector: ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content' - , findNestedContent: false // true = $P.find(contentSelector), false = $P.children(contentSelector) - // GENERIC ROOT-CLASSES - for auto-generated classNames - , paneClass: "ui-layout-pane" // border-Pane - default: 'ui-layout-pane' - , resizerClass: "ui-layout-resizer" // Resizer Bar - default: 'ui-layout-resizer' - , togglerClass: "ui-layout-toggler" // Toggler Button - default: 'ui-layout-toggler' - , buttonClass: "ui-layout-button" // CUSTOM Buttons - default: 'ui-layout-button-toggle/-open/-close/-pin' - // ELEMENT SIZE & SPACING - //, size: 100 // MUST be pane-specific -initial size of pane - , minSize: 0 // when manually resizing a pane - , maxSize: 0 // ditto, 0 = no limit - , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open' - , spacing_closed: 6 // ditto - when pane is 'closed' - , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides - , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden' - , togglerAlign_open: "center" // top/left, bottom/right, center, OR... - , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right - , togglerTip_open: lang.Close // Toggler tool-tip (title) - , togglerTip_closed: lang.Open // ditto - , togglerContent_open: "" // text or HTML to put INSIDE the toggler - , togglerContent_closed: "" // ditto - // RESIZING OPTIONS - , resizerDblClickToggle: true // - , autoResize: true // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes - , autoReopen: true // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed - , resizerDragOpacity: 1 // option for ui.draggable - //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar - , maskIframesOnResize: true // true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging - , resizeNestedLayout: true // true = trigger nested.resizeAll() when a 'pane' of this layout is the 'container' for another - , resizeWhileDragging: false // true = LIVE Resizing as resizer is dragged - , resizeContentWhileDragging: false // true = re-measure header/footer heights as resizer is dragged - // TIPS & MESSAGES - also see lang object - , noRoomToOpenTip: lang.noRoomToOpenTip - , resizerTip: lang.Resize // Resizer tool-tip (title) - , sliderTip: lang.Slide // resizer-bar triggers 'sliding' when pane is closed - , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding' - , slideTrigger_open: "click" // click, dblclick, mouseenter - , slideTrigger_close: "mouseleave"// click, mouseleave - , slideDelay_open: 300 // applies only for mouseenter event - 0 = instant open - , slideDelay_close: 300 // applies only for mouseleave event (300ms is the minimum!) - , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show? - , preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening - , preventPrematureSlideClose: false - // HOT-KEYS & MISC - , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver - , enableCursorHotkey: true // enabled 'cursor' hotkeys - //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character - , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT' - // PANE ANIMATION - // NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed - , fxName: "slide" // ('none' or blank), slide, drop, scale - , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration - , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 } - , fxOpacityFix: true // tries to fix opacity in IE to restore anti-aliasing after animation - // CALLBACKS - , triggerEventsOnLoad: false // true = trigger onopen OR onclose callbacks when layout initializes - , triggerEventsWhileDragging: true // true = trigger onresize callback REPEATEDLY if resizeWhileDragging==true - , onshow_start: null // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start - , onshow_end: null // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end - , onhide_start: null // CALLBACK when pane STARTS to Close - BEFORE onclose_start - , onhide_end: null // CALLBACK when pane ENDS being Closed - AFTER onclose_end - , onopen_start: null // CALLBACK when pane STARTS to Open - , onopen_end: null // CALLBACK when pane ENDS being Opened - , onclose_start: null // CALLBACK when pane STARTS to Close - , onclose_end: null // CALLBACK when pane ENDS being Closed - , onresize_start: null // CALLBACK when pane STARTS being Resized ***FOR ANY REASON*** - , onresize_end: null // CALLBACK when pane ENDS being Resized ***FOR ANY REASON*** - , onsizecontent_start: null // CALLBACK when sizing of content-element STARTS - , onsizecontent_end: null // CALLBACK when sizing of content-element ENDS - , onswap_start: null // CALLBACK when pane STARTS to Swap - , onswap_end: null // CALLBACK when pane ENDS being Swapped - , ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized - , ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized - } - , north: { - paneSelector: ".ui-layout-north" - , size: "auto" // eg: "auto", "30%", 200 - , resizerCursor: "n-resize" // custom = url(myCursor.cur) - , customHotkey: "" // EITHER a charCode OR a character - } - , south: { - paneSelector: ".ui-layout-south" - , size: "auto" - , resizerCursor: "s-resize" - , customHotkey: "" - } - , east: { - paneSelector: ".ui-layout-east" - , size: 200 - , resizerCursor: "e-resize" - , customHotkey: "" - } - , west: { - paneSelector: ".ui-layout-west" - , size: 200 - , resizerCursor: "w-resize" - , customHotkey: "" - } - , center: { - paneSelector: ".ui-layout-center" - , minWidth: 0 - , minHeight: 0 - } - - // STATE MANAGMENT - , useStateCookie: false // Enable cookie-based state-management - can fine-tune with cookie.autoLoad/autoSave - , cookie: { - name: "" // If not specified, will use Layout.name, else just "Layout" - , autoSave: true // Save a state cookie when page exits? - , autoLoad: true // Load the state cookie when Layout inits? - // Cookie Options - , domain: "" - , path: "" - , expires: "" // 'days' to keep cookie - leave blank for 'session cookie' - , secure: false - // List of options to save in the cookie - must be pane-specific - , keys: "north.size,south.size,east.size,west.size,"+ - "north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+ - "north.isHidden,south.isHidden,east.isHidden,west.isHidden" - } - } - - - // PREDEFINED EFFECTS / DEFAULTS -, effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings - slide: { - all: { duration: "fast" } // eg: duration: 1000, easing: "easeOutBounce" - , north: { direction: "up" } - , south: { direction: "down" } - , east: { direction: "right"} - , west: { direction: "left" } - } - , drop: { - all: { duration: "slow" } // eg: duration: 1000, easing: "easeOutQuint" - , north: { direction: "up" } - , south: { direction: "down" } - , east: { direction: "right"} - , west: { direction: "left" } - } - , scale: { - all: { duration: "fast" } - } - } - - - // DYNAMIC DATA - IS READ-ONLY EXTERNALLY! -, state = { - // generate unique ID to use for event.namespace so can unbind only events added by 'this layout' - id: "layout"+ new Date().getTime() // code uses alias: sID - , initialized: false - , container: {} // init all keys - , north: {} - , south: {} - , east: {} - , west: {} - , center: {} - , cookie: {} // State Managment data storage - } - - - // INTERNAL CONFIG DATA - DO NOT CHANGE THIS! -, _c = { - allPanes: "north,south,west,east,center" - , borderPanes: "north,south,west,east" - , altSide: { - north: "south" - , south: "north" - , east: "west" - , west: "east" - } - // CSS used in multiple places - , hidden: { visibility: "hidden" } - , visible: { visibility: "visible" } - // layout element settings - , zIndex: { // set z-index values here - pane_normal: 1 // normal z-index for panes - , resizer_normal: 2 // normal z-index for resizer-bars - , iframe_mask: 2 // overlay div used to mask pane(s) during resizing - , pane_sliding: 100 // applied to *BOTH* the pane and its resizer when a pane is 'slid open' - , pane_animate: 1000 // applied to the pane when being animated - not applied to the resizer - , resizer_drag: 10000 // applied to the CLONED resizer-bar when being 'dragged' - } - , resizers: { - cssReq: { - position: "absolute" - , padding: 0 - , margin: 0 - , fontSize: "1px" - , textAlign: "left" // to counter-act "center" alignment! - , overflow: "hidden" // prevent toggler-button from overflowing - // SEE c.zIndex.resizer_normal - } - , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true - background: "#DDD" - , border: "none" - } - } - , togglers: { - cssReq: { - position: "absolute" - , display: "block" - , padding: 0 - , margin: 0 - , overflow: "hidden" - , textAlign: "center" - , fontSize: "1px" - , cursor: "pointer" - , zIndex: 1 - } - , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true - background: "#AAA" - } - } - , content: { - cssReq: { - position: "relative" /* contain floated or positioned elements */ - } - , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true - overflow: "auto" - , padding: "10px" - } - , cssDemoPane: { // DEMO CSS - REMOVE scrolling from 'pane' when it has a content-div - overflow: "hidden" - , padding: 0 - } - } - , panes: { // defaults for ALL panes - overridden by 'per-pane settings' below - cssReq: { - position: "absolute" - , margin: 0 - // SEE c.zIndex.pane_normal - } - , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true - padding: "10px" - , background: "#FFF" - , border: "1px solid #BBB" - , overflow: "auto" - } - } - , north: { - side: "Top" - , sizeType: "Height" - , dir: "horz" - , cssReq: { - top: 0 - , bottom: "auto" - , left: 0 - , right: 0 - , width: "auto" - // height: DYNAMIC - } - , pins: [] // array of 'pin buttons' to be auto-updated on open/close (classNames) - } - , south: { - side: "Bottom" - , sizeType: "Height" - , dir: "horz" - , cssReq: { - top: "auto" - , bottom: 0 - , left: 0 - , right: 0 - , width: "auto" - // height: DYNAMIC - } - , pins: [] - } - , east: { - side: "Right" - , sizeType: "Width" - , dir: "vert" - , cssReq: { - left: "auto" - , right: 0 - , top: "auto" // DYNAMIC - , bottom: "auto" // DYNAMIC - , height: "auto" - // width: DYNAMIC - } - , pins: [] - } - , west: { - side: "Left" - , sizeType: "Width" - , dir: "vert" - , cssReq: { - left: 0 - , right: "auto" - , top: "auto" // DYNAMIC - , bottom: "auto" // DYNAMIC - , height: "auto" - // width: DYNAMIC - } - , pins: [] - } - , center: { - dir: "center" - , cssReq: { - left: "auto" // DYNAMIC - , right: "auto" // DYNAMIC - , top: "auto" // DYNAMIC - , bottom: "auto" // DYNAMIC - , height: "auto" - , width: "auto" - } - } - } - - -/* - * ########################### - * INTERNAL HELPER FUNCTIONS - * ########################### - */ - - /** - * Manages all internal timers - */ -, timer = { - data: {} - , set: function (s, fn, ms) { timer.clear(s); timer.data[s] = setTimeout(fn, ms); } - , clear: function (s) { var t=timer.data; if (t[s]) {clearTimeout(t[s]); delete t[s];} } - } - - /** - * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false - */ -, isStr = function (o) { - try { return typeof o == "string" - || (typeof o == "object" && o.constructor.toString().match(/string/i) !== null); } - catch (e) { return false; } - } - - /** - * Returns a simple string if passed EITHER a simple string OR a 'string object', - * else returns the original object - */ -, str = function (o) { // trim converts 'String object' to a simple string - return isStr(o) ? $.trim(o) : o == undefined || o == null ? "" : o; - } - - /** - * min / max - * - * Aliases for Math methods to simplify coding - */ -, min = function (x,y) { return Math.min(x,y); } -, max = function (x,y) { return Math.max(x,y); } - - /** - * Processes the options passed in and transforms them into the format used by layout() - * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys) - * In flat-format, pane-specific-settings are prefixed like: north__optName (2-underscores) - * To update effects, options MUST use nested-keys format, with an effects key ??? - * - * @see initOptions() - * @param {Object} d Data/options passed by user - may be a single level or nested levels - * @return {Object} Creates a data struture that perfectly matches 'options', ready to be imported - */ -, _transformData = function (d) { - var a, json = { cookie:{}, defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} }; - d = d || {}; - if (d.effects || d.cookie || d.defaults || d.north || d.south || d.west || d.east || d.center) - json = $.extend( true, json, d ); // already in json format - add to base keys - else - // convert 'flat' to 'nest-keys' format - also handles 'empty' user-options - $.each( d, function (key,val) { - a = key.split("__"); - if (!a[1] || json[a[0]]) // check for invalid keys - json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val; - }); - return json; - } - - /** - * Set an INTERNAL callback to avoid simultaneous animation - * Runs only if needed and only if all callbacks are not 'already set' - * Called by open() and close() when isLayoutBusy=true - * - * @param {string} action Either 'open' or 'close' - * @param {string} pane A valid border-pane name, eg 'west' - * @param {boolean=} param Extra param for callback (optional) - */ -, _queue = function (action, pane, param) { - var tried = []; - - // if isLayoutBusy, then some pane must be 'moving' - $.each(_c.borderPanes.split(","), function (i, p) { - if (_c[p].isMoving) { - bindCallback(p); // TRY to bind a callback - return false; // BREAK - } - }); - - // if pane does NOT have a callback, then add one, else follow the callback chain... - function bindCallback (p) { - var c = _c[p]; - if (!c.doCallback) { - c.doCallback = true; - c.callback = action +","+ pane +","+ (param ? 1 : 0); - } - else { // try to 'chain' this callback - tried.push(p); - var cbPane = c.callback.split(",")[1]; // 2nd param of callback is 'pane' - // ensure callback target NOT 'itself' and NOT 'target pane' and NOT already tried (avoid loop) - if (cbPane != pane && !$.inArray(cbPane, tried) >= 0) - bindCallback(cbPane); // RECURSE - } - } - } - - /** - * RUN the INTERNAL callback for this pane - if one exists - * - * @param {string} pane A valid border-pane name, eg 'west' - */ -, _dequeue = function (pane) { - var c = _c[pane]; - - // RESET flow-control flags - _c.isLayoutBusy = false; - delete c.isMoving; - if (!c.doCallback || !c.callback) return; - - c.doCallback = false; // RESET logic flag - - // EXECUTE the callback - var - cb = c.callback.split(",") - , param = (cb[2] > 0 ? true : false) - ; - if (cb[0] == "open") - open( cb[1], param ); - else if (cb[0] == "close") - close( cb[1], param ); - - if (!c.doCallback) c.callback = null; // RESET - unless callback above enabled it again! - } - - /** - * Executes a Callback function after a trigger event, like resize, open or close - * - * @param {?string} pane This is passed only so we can pass the 'pane object' to the callback - * @param {(string|function())} v_fn Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument - */ -, _execCallback = function (pane, v_fn) { - if (!v_fn) return; - var fn; - try { - if (typeof v_fn == "function") - fn = v_fn; - else if (!isStr(v_fn)) - return; - else if (v_fn.match(/,/)) { - // function name cannot contain a comma, so must be a function name AND a 'name' parameter - var args = v_fn.split(","); - fn = eval(args[0]); - if (typeof fn=="function" && args.length > 1) - return fn(args[1]); // pass the argument parsed from 'list' - } - else // just the name of an external function? - fn = eval(v_fn); - - if (typeof fn=="function") { - if (pane && $Ps[pane]) - // pass data: pane-name, pane-element, pane-state, pane-options, and layout-name - return fn( pane, $Ps[pane], state[pane], options[pane], options.name ); - else // must be a layout/container callback - pass suitable info - return fn( Instance, state, options, options.name ); - } - } - catch (ex) {} - } - - /** - * cure iframe display issues in IE & other browsers - */ -, _fixIframe = function (pane) { - if ($.layout.browser.mozilla) return; // skip FireFox - it auto-refreshes iframes onShow - var $P = $Ps[pane]; - // if the 'pane' is an iframe, do it - if (state[pane].tagName == "IFRAME") - $P.css(_c.hidden).css(_c.visible); - else // ditto for any iframes INSIDE the pane - $P.find('IFRAME').css(_c.hidden).css(_c.visible); - } - - /** - * cssW / cssH / cssSize / cssMinDims - * - * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype - * - * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() - * @param {(string|!Object)} el Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object - * @param {number=} outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerWidth of el by subtracting padding and borders - */ -, cssW = function (el, outerWidth) { - var str = isStr(el) - , $E = str ? $Ps[el] : $(el) - ; - if (!$E.length) return 0; - if (isNaN(outerWidth)) // not specified - outerWidth = str ? getPaneSize(el) : $E.outerWidth(); - return $.layout.cssWidth($E, outerWidth); - } - - /** - * @param {(string|!Object)} el Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object - * @param {number=} outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerHeight el by subtracting padding and borders - */ -, cssH = function (el, outerHeight) { - var str = isStr(el) - , $E = str ? $Ps[el] : $(el) - ; - if (!$E.length) return 0; - if (isNaN(outerHeight)) // not specified - outerHeight = str ? getPaneSize(el) : $E.outerHeight(); - return $.layout.cssHeight($E, outerHeight); - } - - /** - * @param {string} pane Can accept ONLY a 'pane' (east, west, etc) - * @param {number=} outerSize (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerHeight/Width of el by subtracting padding and borders - */ -, cssSize = function (pane, outerSize) { - if (_c[pane].dir=="horz") // pane = north or south - return cssH(pane, outerSize); - else // pane = east or west - return cssW(pane, outerSize); - } - - /** - * @param {string} pane Can accept ONLY a 'pane' (east, west, etc) - * @return {Object} Returns hash of minWidth & minHeight - */ -, cssMinDims = function (pane) { - // minWidth/Height means CSS width/height = 1px - var - dir = _c[pane].dir - , d = { - minWidth: 1001 - cssW(pane, 1000) - , minHeight: 1001 - cssH(pane, 1000) - } - ; - if (dir == "horz") d.minSize = d.minHeight; - if (dir == "vert") d.minSize = d.minWidth; - return d; - } - - // TODO: see if these methods can be made more useful... - // TODO: *maybe* return cssW/H from these so caller can use this info - - /** - * @param {(string|!Object)} el - * @param {number=} outerWidth - * @param {boolean=} autoHide - */ -, setOuterWidth = function (el, outerWidth, autoHide) { - var $E = el, w; - if (isStr(el)) $E = $Ps[el]; // west - else if (!el.jquery) $E = $(el); - w = cssW($E, outerWidth); - $E.css({ width: w }); - if (w > 0) { - if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) { - $E.show().data('autoHidden', false); - if (!$.layout.browser.mozilla) // FireFox refreshes iframes - IE does not - // make hidden, then visible to 'refresh' display after animation - $E.css(_c.hidden).css(_c.visible); - } - } - else if (autoHide && !$E.data('autoHidden')) - $E.hide().data('autoHidden', true); - } - - /** - * @param {(string|!Object)} el - * @param {number=} outerHeight - * @param {boolean=} autoHide - */ -, setOuterHeight = function (el, outerHeight, autoHide) { - var $E = el, h; - if (isStr(el)) $E = $Ps[el]; // west - else if (!el.jquery) $E = $(el); - h = cssH($E, outerHeight); - $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent - if (h > 0 && $E.innerWidth() > 0) { - if (autoHide && $E.data('autoHidden')) { - $E.show().data('autoHidden', false); - if (!$.layout.browser.mozilla) // FireFox refreshes iframes - IE does not - $E.css(_c.hidden).css(_c.visible); - } - } - else if (autoHide && !$E.data('autoHidden')) - $E.hide().data('autoHidden', true); - } - - /** - * @param {(string|!Object)} el - * @param {number=} outerSize - * @param {boolean=} autoHide - */ -, setOuterSize = function (el, outerSize, autoHide) { - if (_c[pane].dir=="horz") // pane = north or south - setOuterHeight(el, outerSize, autoHide); - else // pane = east or west - setOuterWidth(el, outerSize, autoHide); - } - - - /** - * Converts any 'size' params to a pixel/integer size, if not already - * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated - * - /** - * @param {string} pane - * @param {(string|number)=} size - * @param {string=} dir - * @return {number} - */ -, _parseSize = function (pane, size, dir) { - if (!dir) dir = _c[pane].dir; - - if (isStr(size) && size.match(/%/)) - size = parseInt(size, 10) / 100; // convert % to decimal - - if (size === 0) - return 0; - else if (size >= 1) - return parseInt(size, 10); - else if (size > 0) { // percentage, eg: .25 - var o = options, avail; - if (dir=="horz") // north or south or center.minHeight - avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0); - else if (dir=="vert") // east or west or center.minWidth - avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0); - return Math.floor(avail * size); - } - else if (pane=="center") - return 0; - else { // size < 0 || size=='auto' || size==Missing || size==Invalid - // auto-size the pane - var - $P = $Ps[pane] - , dim = (dir == "horz" ? "height" : "width") - , vis = $.layout.showInvisibly($P) // show pane invisibly if hidden - , s = $P.css(dim); // SAVE current size - ; - $P.css(dim, "auto"); - size = (dim == "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE - $P.css(dim, s).css(vis); // RESET size & visibility - return size; - } - } - - /** - * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added - * - * @param {(string|!Object)} pane - * @param {boolean=} inclSpace - * @return {number} Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser - */ -, getPaneSize = function (pane, inclSpace) { - var - $P = $Ps[pane] - , o = options[pane] - , s = state[pane] - , oSp = (inclSpace ? o.spacing_open : 0) - , cSp = (inclSpace ? o.spacing_closed : 0) - ; - if (!$P || s.isHidden) - return 0; - else if (s.isClosed || (s.isSliding && inclSpace)) - return cSp; - else if (_c[pane].dir == "horz") - return $P.outerHeight() + oSp; - else // dir == "vert" - return $P.outerWidth() + oSp; - } - - /** - * Calculate min/max pane dimensions and limits for resizing - * - * @param {string} pane - * @param {boolean=} slide - */ -, setSizeLimits = function (pane, slide) { - if (!isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , dir = c.dir - , side = c.side.toLowerCase() - , type = c.sizeType.toLowerCase() - , isSliding = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param - , $P = $Ps[pane] - , paneSpacing = o.spacing_open - // measure the pane on the *opposite side* from this pane - , altPane = _c.altSide[pane] - , altS = state[altPane] - , $altP = $Ps[altPane] - , altPaneSize = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth())) - , altPaneSpacing = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0) - // limitSize prevents this pane from 'overlapping' opposite pane - , containerSize = (dir=="horz" ? sC.innerHeight : sC.innerWidth) - , minCenterDims = cssMinDims("center") - , minCenterSize = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth) - // if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them - , limitSize = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing))) - , minSize = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize ) - , maxSize = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize ) - , r = s.resizerPosition = {} // used to set resizing limits - , top = sC.insetTop - , left = sC.insetLeft - , W = sC.innerWidth - , H = sC.innerHeight - , rW = o.spacing_open // subtract resizer-width to get top/left position for south/east - ; - switch (pane) { - case "north": r.min = top + minSize; - r.max = top + maxSize; - break; - case "west": r.min = left + minSize; - r.max = left + maxSize; - break; - case "south": r.min = top + H - maxSize - rW; - r.max = top + H - minSize - rW; - break; - case "east": r.min = left + W - maxSize - rW; - r.max = left + W - minSize - rW; - break; - }; - } - - /** - * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes - * - * @return JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height - */ -, calcNewCenterPaneDims = function () { - var d = { - top: getPaneSize("north", true) // true = include 'spacing' value for pane - , bottom: getPaneSize("south", true) - , left: getPaneSize("west", true) - , right: getPaneSize("east", true) - , width: 0 - , height: 0 - }; - - // NOTE: sC = state.container - // calc center-pane outer dimensions - d.width = sC.innerWidth - d.left - d.right; // outerWidth - d.height = sC.innerHeight - d.bottom - d.top; // outerHeight - // add the 'container border/padding' to get final positions relative to the container - d.top += sC.insetTop; - d.bottom += sC.insetBottom; - d.left += sC.insetLeft; - d.right += sC.insetRight; - - return d; - } - - - /** - * Returns data for setting size of an element (container or a pane). - * - * @see _create(), onWindowResize() for container, plus others for pane - * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc - */ -, elDims = function ($E) { return $.layout.getElementDimensions($E); } - -, elCSS = function ($E, list) { return $.layout.getElementCSS($E, list); } - - - /** - * @param {!Object} el - * @param {boolean=} allStates - */ -, getHoverClasses = function (el, allStates) { - var - $El = $(el) - , type = $El.data("layoutRole") - , pane = $El.data("layoutEdge") - , o = options[pane] - , root = o[type +"Class"] - , _pane = "-"+ pane // eg: "-west" - , _open = "-open" - , _closed = "-closed" - , _slide = "-sliding" - , _hover = "-hover " // NOTE the trailing space - , _state = $El.hasClass(root+_closed) ? _closed : _open - , _alt = _state == _closed ? _open : _closed - , classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover) - ; - if (allStates) // when 'removing' classes, also remove alternate-state classes - classes += (root+_alt+_hover) + (root+_pane+_alt+_hover); - - if (type=="resizer" && $El.hasClass(root+_slide)) - classes += (root+_slide+_hover) + (root+_pane+_slide+_hover); - - return $.trim(classes); - } -, addHover = function (evt, el) { - var $E = $(el || this); - if (evt && $E.data("layoutRole") == "toggler") - evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar - $E.addClass( getHoverClasses($E) ); - } -, removeHover = function (evt, el) { - var $E = $(el || this); - $E.removeClass( getHoverClasses($E, true) ); - } - -, onResizerEnter = function (evt) { - $('body').disableSelection(); - addHover(evt, this); - } -, onResizerLeave = function (evt, el) { - var - e = el || this // el is only passed when called by the timer - , pane = $(e).data("layoutEdge") - , name = pane +"ResizerLeave" - ; - timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set - timer.clear(name); // cancel enableSelection timer - may re/set below - if (!el) { // 1st call - mouseleave event - removeHover(evt, this); // do this on initial call - // this method calls itself on a timer because it needs to allow - // enough time for dragging to kick-in and set the isResizing flag - // dragging has a 100ms delay set, so this delay must be higher - timer.set(name, function(){ onResizerLeave(evt, e); }, 200); - } - // if user is resizing, then dragStop will enableSelection() when done - else if (!state[pane].isResizing) // 2nd call - by timer - $('body').enableSelection(); - } - -/* - * ########################### - * INITIALIZATION METHODS - * ########################### - */ - - /** - * Initialize the layout - called automatically whenever an instance of layout is created - * - * @see none - triggered onInit - * @return mixed true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort - */ -, _create = function () { - // initialize config/options - initOptions(); - var o = options; - - $.layout.browser.boxModel = $.support.boxModel; - - // update options with saved state, if option enabled - if (o.useStateCookie && o.cookie.autoLoad) - loadCookie(); // Update options from state-cookie - - // TEMP state so isInitialized returns true during init process - state.creatingLayout = true; - - // options & state have been initialized, so now run beforeLoad callback - // onload will CANCEL layout creation if it returns false - if (false === _execCallback(null, o.onload_start)) - return 'cancel'; - - // initialize the container element - _initContainer(); - - // bind hotkey function - keyDown - if required - initHotkeys(); - - // search for and bind custom-buttons - if (o.autoBindCustomButtons) initButtons(); - - // bind window.onunload - $(window).bind("unload."+ sID, unload); - - // if layout elements are hidden, then layout WILL NOT complete initialization! - // initLayoutElements will set initialized=true and run the onload callback IF successful - if (o.initPanes) _initLayoutElements(); - - delete state.creatingLayout; - - return state.initialized; - } - - /** - * Initialize the layout IF not already - * - * @see All methods in Instance run this test - * @return boolean true = layoutElements have been initialized | false = panes are not initialized (yet) - */ -, isInitialized = function () { - if (state.initialized || state.creatingLayout) return true; // already initialized - else return _initLayoutElements(); // try to init panes NOW - } - - /** - * Initialize the layout - called automatically whenever an instance of layout is created - * - * @see _create() & isInitialized - * @return An object pointer to the instance created - */ -, _initLayoutElements = function () { - // initialize config/options - var o = options; - - // CANNOT init panes inside a hidden container! - if (!$N.is(":visible")) - return false; - // a center pane is required, so make sure it exists - if (!getPane('center').length) { - if (o.showErrorMessages) alert( lang.errCenterPaneMissing ); - return false; - } - - // TEMP state so isInitialized returns true during init process - state.creatingLayout = true; - - // update Container dims - $.extend(sC, elDims( $N )); - - // initialize all layout elements - initPanes(); // size & position panes - calls initHandles() - which calls initResizable() - sizeContent(); // AFTER panes & handles have been initialized, size 'content' divs - - if (o.scrollToBookmarkOnLoad) { - var l = self.location; - if (l.hash) l.replace( l.hash ); // scrollTo Bookmark - } - - // bind resizeAll() for 'this layout instance' to window.resize event - if (o.resizeWithWindow && !$N.data("layoutRole")) // skip if 'nested' inside a pane - $(window).bind("resize."+ sID, windowResize); - - delete state.creatingLayout; - state.initialized = true; - - _execCallback(null, o.onload_end || o.onload); - - return true; // elements initialized successfully - } - - -, windowResize = function () { - var delay = Number(options.resizeWithWindowDelay); - if (delay < 10) delay = 100; // MUST have a delay! - // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway - timer.clear("winResize"); // if already running - timer.set("winResize", function(){ - timer.clear("winResize"); - timer.clear("winResizeRepeater"); - var dims = elDims( $N ); - // only trigger resizeAll() if container has changed size - if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight) - resizeAll(); - }, delay); - // ALSO set fixed-delay timer, if not already running - if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater(); - } - -, setWindowResizeRepeater = function () { - var delay = Number(options.resizeWithWindowMaxDelay); - if (delay > 0) - timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay); - } - -, unload = function () { - var o = options; - state.cookie = getState(); // save state in case onunload has custom state-management - _execCallback(null, o.onunload_start); - if (o.useStateCookie && o.cookie.autoSave) saveCookie(); - _execCallback(null, o.onunload_end || o.onunload); - } - - /** - * Validate and initialize container CSS and events - * - * @see _create() - */ -, _initContainer = function () { - var - tag = sC.tagName = $N[0].tagName - , o = options - , fullPage= (tag == "BODY") - , props = "overflow,position,margin,padding,border" - , CSS = {} - , hid = "hidden" // used A LOT! - , isVis = $N.is(":visible") - ; - // sC -> state.container - sC.selector = $N.selector.split(".slice")[0]; - sC.ref = tag +"/"+ sC.selector; // used in messages - - $N .data("layout", Instance) - .data("layoutContainer", sID) // unique identifier for internal use - .addClass(o.containerClass) - ; - - // SAVE original container CSS for use in destroy() - if (!$N.data("layoutCSS")) { - // handle props like overflow different for BODY & HTML - has 'system default' values - if (fullPage) { - CSS = $.extend( elCSS($N, props), { - height: $N.css("height") - , overflow: $N.css("overflow") - , overflowX: $N.css("overflowX") - , overflowY: $N.css("overflowY") - }); - // ALSO SAVE CSS - var $H = $("html"); - $H.data("layoutCSS", { - height: "auto" // FF would return a fixed px-size! - , overflow: $H.css("overflow") - , overflowX: $H.css("overflowX") - , overflowY: $H.css("overflowY") - }); - } - else // handle props normally for non-body elements - CSS = elCSS($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY"); - - $N.data("layoutCSS", CSS); - } - - try { // format html/body if this is a full page layout - if (fullPage) { - $("html").css({ - height: "100%" - , overflow: hid - , overflowX: hid - , overflowY: hid - }); - $("body").css({ - position: "relative" - , height: "100%" - , overflow: hid - , overflowX: hid - , overflowY: hid - , margin: 0 - , padding: 0 // TODO: test whether body-padding could be handled? - , border: "none" // a body-border creates problems because it cannot be measured! - }); - - // set current layout-container dimensions - $.extend(sC, elDims( $N )); - } - else { // set required CSS for overflow and position - // ENSURE container will not 'scroll' - CSS = { overflow: hid, overflowX: hid, overflowY: hid } - var - p = $N.css("position") - , h = $N.css("height") - ; - // if this is a NESTED layout, then container/outer-pane ALREADY has position and height - if (!$N.data("layoutRole")) { - if (!p || !p.match(/fixed|absolute|relative/)) - CSS.position = "relative"; // container MUST have a 'position' - /* - if (!h || h=="auto") - CSS.height = "100%"; // container MUST have a 'height' - */ - } - $N.css( CSS ); - - // set current layout-container dimensions - if (isVis) { - $.extend(sC, elDims( $N )); - if (o.showErrorMessages && sC.innerHeight < 2) - alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) ); - } - } - } catch (ex) {} - } - - /** - * Bind layout hotkeys - if options enabled - * - * @see _create() and addPane() - * @param {string=} panes The edge(s) to process, blank = all - */ -, initHotkeys = function (panes) { - if (!panes || panes == "all") panes = _c.borderPanes; - // bind keyDown to capture hotkeys, if option enabled for ANY pane - $.each(panes.split(","), function (i, pane) { - var o = options[pane]; - if (o.enableCursorHotkey || o.customHotkey) { - $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE - return false; // BREAK - binding was done - } - }); - } - - /** - * Build final OPTIONS data - * - * @see _create() - */ -, initOptions = function () { - // simplify logic by making sure passed 'opts' var has basic keys - opts = _transformData( opts ); - - // TODO: create a compatibility add-on for new UI widget that will transform old option syntax - var newOpts = { - applyDefaultStyles: "applyDemoStyles" - }; - renameOpts(opts.defaults); - $.each(_c.allPanes.split(","), function (i, pane) { - renameOpts(opts[pane]); - }); - - // update default effects, if case user passed key - if (opts.effects) { - $.extend( effects, opts.effects ); - delete opts.effects; - } - $.extend( options.cookie, opts.cookie ); - - // see if any 'global options' were specified - var globals = "name,containerClass,zIndex,scrollToBookmarkOnLoad,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,"+ - "onresizeall,onresizeall_start,onresizeall_end,onload,onload_start,onload_end,onunload,onunload_start,onunload_end,autoBindCustomButtons,useStateCookie"; - $.each(globals.split(","), function (i, key) { - if (opts[key] !== undefined) - options[key] = opts[key]; - else if (opts.defaults[key] !== undefined) { - options[key] = opts.defaults[key]; - delete opts.defaults[key]; - } - }); - - // remove any 'defaults' that MUST be set 'per-pane' - $.each("paneSelector,resizerCursor,customHotkey".split(","), - function (i, key) { delete opts.defaults[key]; } // is OK if key does not exist - ); - - // now update options.defaults - $.extend( true, options.defaults, opts.defaults ); - - // merge config for 'center-pane' - border-panes handled in the loop below - _c.center = $.extend( true, {}, _c.panes, _c.center ); - // update config.zIndex values if zIndex option specified - var z = options.zIndex; - if (z === 0 || z > 0) { - _c.zIndex.pane_normal = z; - _c.zIndex.resizer_normal = z+1; - _c.zIndex.iframe_mask = z+1; - } - - // merge options for 'center-pane' - border-panes handled in the loop below - $.extend( options.center, opts.center ); - // Most 'default options' do not apply to 'center', so add only those that DO - var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data - var optionsCenter = ("paneClass,contentSelector,applyDemoStyles,triggerEventsOnLoad,showOverflowOnHover," - + "onresize,onresize_start,onresize_end,resizeNestedLayout,resizeContentWhileDragging," - + "onsizecontent,onsizecontent_start,onsizecontent_end").split(","); - $.each(optionsCenter, - function (i, key) { options.center[key] = o_Center[key]; } - ); - - var o, defs = options.defaults; - - // create a COMPLETE set of options for EACH border-pane - $.each(_c.borderPanes.split(","), function (i, pane) { - - // apply 'pane-defaults' to CONFIG.[PANE] - _c[pane] = $.extend( true, {}, _c.panes, _c[pane] ); - - // apply 'pane-defaults' + user-options to OPTIONS.PANE - o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] ); - - // make sure we have base-classes - if (!o.paneClass) o.paneClass = "ui-layout-pane"; - if (!o.resizerClass) o.resizerClass = "ui-layout-resizer"; - if (!o.togglerClass) o.togglerClass = "ui-layout-toggler"; - - // create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close] - $.each(["_open","_close",""], function (i,n) { - var - sName = "fxName"+n - , sSpeed = "fxSpeed"+n - , sSettings = "fxSettings"+n - ; - // recalculate fxName according to specificity rules - o[sName] = - opts[pane][sName] // opts.west.fxName_open - || opts[pane].fxName // opts.west.fxName - || opts.defaults[sName] // opts.defaults.fxName_open - || opts.defaults.fxName // opts.defaults.fxName - || o[sName] // options.west.fxName_open - || o.fxName // options.west.fxName - || defs[sName] // options.defaults.fxName_open - || defs.fxName // options.defaults.fxName - || "none" - ; - // validate fxName to be sure is a valid effect - var fxName = o[sName]; - if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings)) - fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed - // set vars for effects subkeys to simplify logic - var - fx = effects[fxName] || {} // effects.slide - , fx_all = fx.all || {} // effects.slide.all - , fx_pane = fx[pane] || {} // effects.slide.west - ; - // RECREATE the fxSettings[_open|_close] keys using specificity rules - o[sSettings] = $.extend( - {} - , fx_all // effects.slide.all - , fx_pane // effects.slide.west - , defs.fxSettings || {} // options.defaults.fxSettings - , defs[sSettings] || {} // options.defaults.fxSettings_open - , o.fxSettings // options.west.fxSettings - , o[sSettings] // options.west.fxSettings_open - , opts.defaults.fxSettings // opts.defaults.fxSettings - , opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open - , opts[pane].fxSettings // opts.west.fxSettings - , opts[pane][sSettings] || {} // opts.west.fxSettings_open - ); - // recalculate fxSpeed according to specificity rules - o[sSpeed] = - opts[pane][sSpeed] // opts.west.fxSpeed_open - || opts[pane].fxSpeed // opts.west.fxSpeed (pane-default) - || opts.defaults[sSpeed] // opts.defaults.fxSpeed_open - || opts.defaults.fxSpeed // opts.defaults.fxSpeed - || o[sSpeed] // options.west.fxSpeed_open - || o[sSettings].duration // options.west.fxSettings_open.duration - || o.fxSpeed // options.west.fxSpeed - || o.fxSettings.duration // options.west.fxSettings.duration - || defs.fxSpeed // options.defaults.fxSpeed - || defs.fxSettings.duration// options.defaults.fxSettings.duration - || fx_pane.duration // effects.slide.west.duration - || fx_all.duration // effects.slide.all.duration - || "normal" // DEFAULT - ; - }); - - }); - - function renameOpts (O) { - for (var key in newOpts) { - if (O[key] != undefined) { - O[newOpts[key]] = O[key]; - delete O[key]; - } - } - } - } - - /** - * Initialize module objects, styling, size and position for all panes - * - * @see _create() - * @param {string} pane The pane to process - */ -, getPane = function (pane) { - var sel = options[pane].paneSelector - if (sel.substr(0,1)==="#") // ID selector - // NOTE: elements selected 'by ID' DO NOT have to be 'children' - return $N.find(sel).eq(0); - else { // class or other selector - var $P = $N.children(sel).eq(0); - // look for the pane nested inside a 'form' element - return $P.length ? $P : $N.children("form:first").children(sel).eq(0); - } - } -, initPanes = function () { - // NOTE: do north & south FIRST so we can measure their height - do center LAST - $.each(_c.allPanes.split(","), function (idx, pane) { - addPane( pane, true ); - }); - - // init the pane-handles NOW in case we have to hide or close the pane below - initHandles(); - - // now that all panes have been initialized and initially-sized, - // make sure there is really enough space available for each pane - $.each(_c.borderPanes.split(","), function (i, pane) { - if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN - setSizeLimits(pane); - makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit() - } - }); - // size center-pane AGAIN in case we 'closed' a border-pane in loop above - sizeMidPanes("center"); - - // Chrome fires callback BEFORE it completes resizing, so add a delay before handling children - setTimeout(function(){ - $.each(_c.allPanes.split(","), function (i, pane) { - var o = options[pane]; - if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN - // trigger onResize callbacks for all panes with triggerEventsOnLoad = true - if (o.triggerEventsOnLoad) - _execCallback(pane, o.onresize_end || o.onresize); - resizeNestedLayout(pane); - } - }); - }, 50 ); // 50ms delay is enough - - if (options.showErrorMessages && $N.innerHeight() < 2) - alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) ); - } - - /** - * Remove a pane from the layout - subroutine of destroy() - * - * @see initPanes() - * @param {string} pane The pane to process - */ -, addPane = function (pane, force) { - if (!force && !isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , fx = s.fx - , dir = c.dir - , spacing = o.spacing_open || 0 - , isCenter = (pane == "center") - , CSS = {} - , $P = $Ps[pane] - , size, minSize, maxSize - ; - - // if pane-pointer already exists, remove the old one first - if ($P) - removePane( pane ); - else - $Cs[pane] = false; // init - - $P = $Ps[pane] = getPane(pane); - if (!$P.length) { - $Ps[pane] = false; // logic - return; - } - - // SAVE original Pane CSS - if (!$P.data("layoutCSS")) { - var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border"; - $P.data("layoutCSS", elCSS($P, props)); - } - - // add basic classes & attributes - $P - .data("parentLayout", Instance) - .data("layoutRole", "pane") - .data("layoutEdge", pane) - .css(c.cssReq).css("zIndex", _c.zIndex.pane_normal) - .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles - .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector' - .bind("mouseenter."+ sID, addHover ) - .bind("mouseleave."+ sID, removeHover ) - ; - - // see if this pane has a 'scrolling-content element' - initContent(pane, false); // false = do NOT sizeContent() - called later - - if (!isCenter) { - // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden) - // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size' - size = s.size = _parseSize(pane, o.size); - minSize = _parseSize(pane,o.minSize) || 1; - maxSize = _parseSize(pane,o.maxSize) || 100000; - if (size > 0) size = max(min(size, maxSize), minSize); - - // state for border-panes - s.isClosed = false; // true = pane is closed - s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes - s.isResizing= false; // true = pane is in process of being resized - s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible! - } - // state common to ALL panes - s.tagName = $P[0].tagName; - s.edge = pane // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going) - s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically - s.isVisible = true; // false = pane is invisible - closed OR hidden - simplify logic - - // set css-position to account for container borders & padding - switch (pane) { - case "north": CSS.top = sC.insetTop; - CSS.left = sC.insetLeft; - CSS.right = sC.insetRight; - break; - case "south": CSS.bottom = sC.insetBottom; - CSS.left = sC.insetLeft; - CSS.right = sC.insetRight; - break; - case "west": CSS.left = sC.insetLeft; // top, bottom & height set by sizeMidPanes() - break; - case "east": CSS.right = sC.insetRight; // ditto - break; - case "center": // top, left, width & height set by sizeMidPanes() - } - - if (dir == "horz") // north or south pane - CSS.height = max(1, cssH(pane, size)); - else if (dir == "vert") // east or west pane - CSS.width = max(1, cssW(pane, size)); - //else if (isCenter) {} - - $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes - if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback - - // close or hide the pane if specified in settings - if (o.initClosed && o.closable && !o.initHidden) - close(pane, true, true); // true, true = force, noAnimation - else if (o.initHidden || o.initClosed) - hide(pane); // will be completely invisible - no resizer or spacing - else if (!s.noRoom) - // make the pane visible - in case was initially hidden - $P.css("display","block"); - // ELSE setAsOpen() - called later by initHandles() - - // RESET visibility now - pane will appear IF display:block - $P.css("visibility","visible"); - - // check option for auto-handling of pop-ups & drop-downs - if (o.showOverflowOnHover) - $P.hover( allowOverflow, resetOverflow ); - - // if adding a pane AFTER initialization, then... - if (state.initialized) { - initHandles( pane ); - initHotkeys( pane ); - resizeAll(); // will sizeContent if pane is visible - if (s.isVisible) { // pane is OPEN - if (o.triggerEventsOnLoad) - _execCallback(pane, o.onresize_end || o.onresize); - resizeNestedLayout(pane); - } - } - } - - /** - * Initialize module objects, styling, size and position for all resize bars and toggler buttons - * - * @see _create() - * @param {string=} panes The edge(s) to process, blank = all - */ -, initHandles = function (panes) { - if (!panes || panes == "all") panes = _c.borderPanes; - - // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV - $.each(panes.split(","), function (i, pane) { - var $P = $Ps[pane]; - $Rs[pane] = false; // INIT - $Ts[pane] = false; - if (!$P) return; // pane does not exist - skip - - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , rClass = o.resizerClass - , tClass = o.togglerClass - , side = c.side.toLowerCase() - , spacing = (s.isVisible ? o.spacing_open : o.spacing_closed) - , _pane = "-"+ pane // used for classNames - , _state = (s.isVisible ? "-open" : "-closed") // used for classNames - // INIT RESIZER BAR - , $R = $Rs[pane] = $("
    ") - // INIT TOGGLER BUTTON - , $T = (o.closable ? $Ts[pane] = $("
    ") : false) - ; - - //if (s.isVisible && o.resizable) ... handled by initResizable - if (!s.isVisible && o.slidable) - $R.attr("title", o.sliderTip).css("cursor", o.sliderCursor); - - $R - // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer" - .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : "")) - .data("parentLayout", Instance) - .data("layoutRole", "resizer") - .data("layoutEdge", pane) - .css(_c.resizers.cssReq).css("zIndex", _c.zIndex.resizer_normal) - .css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles - .addClass(rClass +" "+ rClass+_pane) - .appendTo($N) // append DIV to container - ; - - if ($T) { - $T - // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler" - .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : "")) - .data("parentLayout", Instance) - .data("layoutRole", "toggler") - .data("layoutEdge", pane) - .css(_c.togglers.cssReq) // add base/required styles - .css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles - .addClass(tClass +" "+ tClass+_pane) - .appendTo($R) // append SPAN to resizer DIV - ; - // ADD INNER-SPANS TO TOGGLER - if (o.togglerContent_open) // ui-layout-open - $(""+ o.togglerContent_open +"") - .data("layoutRole", "togglerContent") - .data("layoutEdge", pane) - .addClass("content content-open") - .css("display","none") - .appendTo( $T ) - //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead! - ; - if (o.togglerContent_closed) // ui-layout-closed - $(""+ o.togglerContent_closed +"") - .data("layoutRole", "togglerContent") - .data("layoutEdge", pane) - .addClass("content content-closed") - .css("display","none") - .appendTo( $T ) - //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead! - ; - // ADD TOGGLER.click/.hover - enableClosable(pane); - } - - // add Draggable events - initResizable(pane); - - // ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open" - if (s.isVisible) - setAsOpen(pane); // onOpen will be called, but NOT onResize - else { - setAsClosed(pane); // onClose will be called - bindStartSlidingEvent(pane, true); // will enable events IF option is set - } - - }); - - // SET ALL HANDLE DIMENSIONS - sizeHandles("all"); - } - - - /** - * Initialize scrolling ui-layout-content div - if exists - * - * @see initPane() - or externally after an Ajax injection - * @param {string} pane The pane to process - * @param {boolean=} resize Size content after init, default = true - */ -, initContent = function (pane, resize) { - if (!isInitialized()) return; - var - o = options[pane] - , sel = o.contentSelector - , $P = $Ps[pane] - , $C - ; - if (sel) $C = $Cs[pane] = (o.findNestedContent) - ? $P.find(sel).eq(0) // match 1-element only - : $P.children(sel).eq(0) - ; - if ($C && $C.length) { - // SAVE original Pane CSS - if (!$C.data("layoutCSS")) - $C.data("layoutCSS", elCSS($C, "height")); - $C.css( _c.content.cssReq ); - if (o.applyDemoStyles) { - $C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div - $P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane - } - state[pane].content = {}; // init content state - if (resize !== false) sizeContent(pane); - // sizeContent() is called AFTER init of all elements - } - else - $Cs[pane] = false; - } - - - /** - * Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons - * - * @see _create() - */ -, initButtons = function () { - var pre = "ui-layout-button-", name; - $.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) { - $.each(_c.borderPanes.split(","), function (ii, pane) { - $("."+pre+action+"-"+pane).each(function(){ - // if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name' - name = $(this).data("layoutName") || $(this).attr("layoutName"); - if (name == undefined || name == options.name) - bindButton(this, action, pane); - }); - }); - }); - } - - /** - * Add resize-bars to all panes that specify it in options - * -dependancy: $.fn.resizable - will skip if not found - * - * @see _create() - * @param {string=} panes The edge(s) to process, blank = all - */ -, initResizable = function (panes) { - var - draggingAvailable = (typeof $.fn.draggable == "function") - , $Frames, side // set in start() - ; - if (!panes || panes == "all") panes = _c.borderPanes; - - $.each(panes.split(","), function (idx, pane) { - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , side = (c.dir=="horz" ? "top" : "left") - , r, live // set in start because may change - ; - if (!draggingAvailable || !$Ps[pane] || !o.resizable) { - o.resizable = false; - return true; // skip to next - } - - var - $P = $Ps[pane] - , $R = $Rs[pane] - , base = o.resizerClass - // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process - , resizerClass = base+"-drag" // resizer-drag - , resizerPaneClass = base+"-"+pane+"-drag" // resizer-north-drag - // 'helper' class is applied to the CLONED resizer-bar while it is being dragged - , helperClass = base+"-dragging" // resizer-dragging - , helperPaneClass = base+"-"+pane+"-dragging" // resizer-north-dragging - , helperLimitClass = base+"-dragging-limit" // resizer-drag - , helperPaneLimitClass = base+"-"+pane+"-dragging-limit" // resizer-north-drag - , helperClassesSet = false // logic var - ; - - if (!s.isClosed) - $R - .attr("title", o.resizerTip) - .css("cursor", o.resizerCursor) // n-resize, s-resize, etc - ; - - $R.bind("mouseenter."+ sID, onResizerEnter) - .bind("mouseleave."+ sID, onResizerLeave); - - $R.draggable({ - containment: $N[0] // limit resizing to layout container - , axis: (c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis - , delay: 0 - , distance: 1 - // basic format for helper - style it using class: .ui-draggable-dragging - , helper: "clone" - , opacity: o.resizerDragOpacity - , addClasses: false // avoid ui-state-disabled class when disabled - //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed - , zIndex: _c.zIndex.resizer_drag - - , start: function (e, ui) { - // REFRESH options & state pointers in case we used swapPanes - o = options[pane]; - s = state[pane]; - // re-read options - live = o.resizeWhileDragging; - - // ondrag_start callback - will CANCEL hide if returns false - // TODO: dragging CANNOT be cancelled like this, so see if there is a way? - if (false === _execCallback(pane, o.ondrag_start)) return false; - - _c.isLayoutBusy = true; // used by sizePane() logic during a liveResize - s.isResizing = true; // prevent pane from closing while resizing - timer.clear(pane+"_closeSlider"); // just in case already triggered - - // SET RESIZER LIMITS - used in drag() - setSizeLimits(pane); // update pane/resizer state - r = s.resizerPosition; - - $R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes - helperClassesSet = false; // reset logic var - see drag() - - // MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS - $Frames = $(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).filter(":visible"); - var id, i=0; // ID incrementer - used when 'resizing' masks during dynamic resizing - $Frames.each(function() { - id = "ui-layout-mask-"+ (++i); - $(this).data("layoutMaskID", id); // tag iframe with corresponding maskID - $('
    ') - .css({ - background: "#fff" - , opacity: "0.001" - , zIndex: _c.zIndex.iframe_mask - , position: "absolute" - , width: this.offsetWidth+"px" - , height: this.offsetHeight+"px" - }) - .css($(this).position()) // top & left -- changed from offset() - .appendTo(this.parentNode) // put mask-div INSIDE pane to avoid zIndex issues - ; - }); - - // DISABLE TEXT SELECTION (probably already done by resizer.mouseOver) - $('body').disableSelection(); - } - - , drag: function (e, ui) { - if (!helperClassesSet) { // can only add classes after clone has been added to the DOM - //$(".ui-draggable-dragging") - ui.helper - .addClass( helperClass +" "+ helperPaneClass ) // add helper classes - .css({ right: "auto", bottom: "auto" }) // fix dir="rtl" issue - .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar - ; - helperClassesSet = true; - // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! - if (s.isSliding) $Ps[pane].css("zIndex", _c.zIndex.pane_sliding); - } - // CONTAIN RESIZER-BAR TO RESIZING LIMITS - var limit = 0; - if (ui.position[side] < r.min) { - ui.position[side] = r.min; - limit = -1; - } - else if (ui.position[side] > r.max) { - ui.position[side] = r.max; - limit = 1; - } - // ADD/REMOVE dragging-limit CLASS - if (limit) { - ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit - window.defaultStatus = "Panel has reached its " + - ((limit>0 && pane.match(/north|west/)) || (limit<0 && pane.match(/south|east/)) ? "maximum" : "minimum") +" size"; - } - else { - ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit - window.defaultStatus = ""; - } - // DYNAMICALLY RESIZE PANES IF OPTION ENABLED - if (live) resizePanes(e, ui, pane); - } - - , stop: function (e, ui) { - $('body').enableSelection(); // RE-ENABLE TEXT SELECTION - window.defaultStatus = ""; // clear 'resizing limit' message from statusbar - $R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer - s.isResizing = false; - _c.isLayoutBusy = false; // set BEFORE resizePanes so other logic can pick it up - resizePanes(e, ui, pane, true); // true = resizingDone - } - - }); - - /** - * resizePanes - * - * Sub-routine called from stop() and optionally drag() - * - * @param {!Object} evt - * @param {!Object} ui - * @param {string} pane - * @param {boolean=} resizingDone - */ - var resizePanes = function (evt, ui, pane, resizingDone) { - var - dragPos = ui.position - , c = _c[pane] - , resizerPos, newSize - , i = 0 // ID incrementer - ; - switch (pane) { - case "north": resizerPos = dragPos.top; break; - case "west": resizerPos = dragPos.left; break; - case "south": resizerPos = sC.offsetHeight - dragPos.top - o.spacing_open; break; - case "east": resizerPos = sC.offsetWidth - dragPos.left - o.spacing_open; break; - }; - - if (resizingDone) { - // Remove OR Resize MASK(S) created in drag.start - $("div.ui-layout-mask").each(function() { this.parentNode.removeChild(this); }); - //$("div.ui-layout-mask").remove(); // TODO: Is this less efficient? - - // ondrag_start callback - will CANCEL hide if returns false - if (false === _execCallback(pane, o.ondrag_end || o.ondrag)) return false; - } - else - $Frames.each(function() { - $("#"+ $(this).data("layoutMaskID")) // get corresponding mask by ID - .css($(this).position()) // update top & left - .css({ // update width & height - width: this.offsetWidth +"px" - , height: this.offsetHeight+"px" - }) - ; - }); - - // remove container margin from resizer position to get the pane size - newSize = resizerPos - sC["inset"+ c.side]; - manualSizePane(pane, newSize); - } - }); - } - - - /** - * Destroy this layout and reset all elements - */ -, destroy = function () { - // UNBIND layout events and remove global object - $(window).unbind("."+ sID); - $(document).unbind("."+ sID); - - // loop all panes to remove layout classes, attributes and bindings - $.each(_c.allPanes.split(","), function (i, pane) { - removePane( pane, false, true ); // true = skipResize - }); - - // reset layout-container - $N .removeData("layout") - .removeData("layoutContainer") - .removeClass(options.containerClass) - ; - - // do NOT reset container CSS if is a 'pane' in an outer-layout - ie, THIS layout is 'nested' - if (!$N.data("layoutEdge") && $N.data("layoutCSS")) // RESET CSS - $N.css( $N.data("layoutCSS") ).removeData("layoutCSS"); - - // for full-page layouts, also reset the CSS - if (sC.tagName == "BODY" && ($N = $("html")).data("layoutCSS")) // RESET CSS - $N.css( $N.data("layoutCSS") ).removeData("layoutCSS"); - - // trigger state-management and onunload callback - unload(); - } - - /** - * Remove a pane from the layout - subroutine of destroy() - * - * @see destroy() - * @param {string} pane The pane to process - * @param {boolean=} remove Remove the DOM element? default = false - * @param {boolean=} skipResize Skip calling resizeAll()? default = false - */ -, removePane = function (pane, remove, skipResize) { - if (!isInitialized()) return; - if (!$Ps[pane]) return; // NO SUCH PANE - var - $P = $Ps[pane] - , $C = $Cs[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - // create list of ALL pane-classes that need to be removed - , _open = "-open" - , _sliding= "-sliding" - , _closed = "-closed" - , root = options[pane].paneClass // default="ui-layout-pane" - , pRoot = root +"-"+ pane // eg: "ui-layout-pane-west" - , classes = [ root, root+_open, root+_closed, root+_sliding, // generic classes - pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ] // pane-specific classes - ; - $.merge(classes, getHoverClasses($P, true)); // ADD hover-classes - - if (!$P || !$P.length) { - } // pane has already been deleted! - else if (remove && !$P.data("layoutContainer") && (!$C || !$C.length || !$C.data("layoutContainer"))) - $P.remove(); - else { - $P .removeClass( classes.join(" ") ) // remove ALL pane-classes - .removeData("layoutParent") - .removeData("layoutRole") - .removeData("layoutEdge") - .removeData("autoHidden") // in case set - .unbind("."+ sID) // remove ALL Layout events - // TODO: remove these extra unbind commands when jQuery is fixed - //.unbind("mouseenter"+ sID) - //.unbind("mouseleave"+ sID) - ; - // do NOT reset CSS if this pane is STILL the container of a nested layout! - // the nested layout will reset its 'container' when/if it is destroyed - if (!$P.data("layoutContainer")) - $P.css( $P.data("layoutCSS") ).removeData("layoutCSS"); - // DITTO for the Content elem - if ($C && $C.length && !$C.data("layoutContainer")) - $C.css( $C.data("layoutCSS") ).removeData("layoutCSS"); - } - - // REMOVE pane resizer and toggler elements - if ($T && $T.length) $T.remove(); - if ($R && $R.length) $R.remove(); - - // CLEAR all pointers and data - $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = false; - - // skip resize & state-clear when called from destroy() - if (!skipResize) { - resizeAll(); - state[pane] = {}; - } - } - - -/* - * ########################### - * ACTION METHODS - * ########################### - */ - - /** - * Completely 'hides' a pane, including its spacing - as if it does not exist - * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it - * - * @param {string} pane The pane being hidden, ie: north, south, east, or west - * @param {boolean=} noAnimation - */ -, hide = function (pane, noAnimation) { - if (!isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - if (!$P || s.isHidden) return; // pane does not exist OR is already hidden - - // onhide_start callback - will CANCEL hide if returns false - if (state.initialized && false === _execCallback(pane, o.onhide_start)) return; - - s.isSliding = false; // just in case - - // now hide the elements - if ($R) $R.hide(); // hide resizer-bar - if (!state.initialized || s.isClosed) { - s.isClosed = true; // to trigger open-animation on show() - s.isHidden = true; - s.isVisible = false; - $P.hide(); // no animation when loading page - sizeMidPanes(_c[pane].dir == "horz" ? "all" : "center"); - if (state.initialized || o.triggerEventsOnLoad) - _execCallback(pane, o.onhide_end || o.onhide); - } - else { - s.isHiding = true; // used by onclose - close(pane, false, noAnimation); // adjust all panes to fit - } - } - - /** - * Show a hidden pane - show as 'closed' by default unless openPane = true - * - * @param {string} pane The pane being opened, ie: north, south, east, or west - * @param {boolean=} openPane - * @param {boolean=} noAnimation - * @param {boolean=} noAlert - */ -, show = function (pane, openPane, noAnimation, noAlert) { - if (!isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden - - // onshow_start callback - will CANCEL show if returns false - if (false === _execCallback(pane, o.onshow_start)) return; - - s.isSliding = false; // just in case - s.isShowing = true; // used by onopen/onclose - //s.isHidden = false; - will be set by open/close - if not cancelled - - // now show the elements - //if ($R) $R.show(); - will be shown by open/close - if (openPane === false) - close(pane, true); // true = force - else - open(pane, false, noAnimation, noAlert); // adjust all panes to fit - } - - - /** - * Toggles a pane open/closed by calling either open or close - * - * @param {string} pane The pane being toggled, ie: north, south, east, or west - * @param {boolean=} slide - */ -, toggle = function (pane, slide) { - if (!isInitialized()) return; - if (!isStr(pane)) { - pane.stopImmediatePropagation(); // pane = event - pane = $(this).data("layoutEdge"); // bound to $R.dblclick - } - var s = state[str(pane)]; - if (s.isHidden) - show(pane); // will call 'open' after unhiding it - else if (s.isClosed) - open(pane, !!slide); - else - close(pane); - } - - - /** - * Utility method used during init or other auto-processes - * - * @param {string} pane The pane being closed - * @param {boolean=} setHandles - */ -, _closePane = function (pane, setHandles) { - var - $P = $Ps[pane] - , s = state[pane] - ; - $P.hide(); - s.isClosed = true; - s.isVisible = false; - // UNUSED: if (setHandles) setAsClosed(pane, true); // true = force - } - - /** - * Close the specified pane (animation optional), and resize all other panes as needed - * - * @param {string} pane The pane being closed, ie: north, south, east, or west - * @param {boolean=} force - * @param {boolean=} noAnimation - * @param {boolean=} skipCallback - */ -, close = function (pane, force, noAnimation, skipCallback) { - if (!state.initialized && $Ps[pane]) { - _closePane(pane); // INIT pane as closed - return; - } - if (!isInitialized()) return; - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none") - // transfer logic vars to temp vars - , isShowing = s.isShowing - , isHiding = s.isHiding - , wasSliding = s.isSliding - ; - // now clear the logic vars - delete s.isShowing; - delete s.isHiding; - - if (!$P || (!o.closable && !isShowing && !isHiding)) return; // invalid request // (!o.resizable && !o.closable) ??? - else if (!force && s.isClosed && !isShowing) return; // already closed - - if (_c.isLayoutBusy) { // layout is 'busy' - probably with an animation - _queue("close", pane, force); // set a callback for this action, if possible - return; // ABORT - } - - // onclose_start callback - will CANCEL hide if returns false - // SKIP if just 'showing' a hidden pane as 'closed' - if (!isShowing && false === _execCallback(pane, o.onclose_start)) return; - - // SET flow-control flags - _c[pane].isMoving = true; - _c.isLayoutBusy = true; - - s.isClosed = true; - s.isVisible = false; - // update isHidden BEFORE sizing panes - if (isHiding) s.isHidden = true; - else if (isShowing) s.isHidden = false; - - if (s.isSliding) // pane is being closed, so UNBIND trigger events - bindStopSlidingEvents(pane, false); // will set isSliding=false - else // resize panes adjacent to this one - sizeMidPanes(_c[pane].dir == "horz" ? "all" : "center", false); // false = NOT skipCallback - - // if this pane has a resizer bar, move it NOW - before animation - setAsClosed(pane); - - // CLOSE THE PANE - if (doFX) { // animate the close - lockPaneForFX(pane, true); // need to set left/top so animation will work - $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () { - lockPaneForFX(pane, false); // undo - close_2(); - }); - } - else { // hide the pane without animation - $P.hide(); - close_2(); - }; - - // SUBROUTINE - function close_2 () { - if (s.isClosed) { // make sure pane was not 'reopened' before animation finished! - - bindStartSlidingEvent(pane, true); // will enable if o.slidable = true - - // if opposite-pane was autoClosed, see if it can be autoOpened now - var altPane = _c.altSide[pane]; - if (state[ altPane ].noRoom) { - setSizeLimits( altPane ); - makePaneFit( altPane ); - } - - if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) { - // onclose callback - UNLESS just 'showing' a hidden pane as 'closed' - if (!isShowing) _execCallback(pane, o.onclose_end || o.onclose); - // onhide OR onshow callback - if (isShowing) _execCallback(pane, o.onshow_end || o.onshow); - if (isHiding) _execCallback(pane, o.onhide_end || o.onhide); - } - } - // execute internal flow-control callback - _dequeue(pane); - } - } - - /** - * @param {string} pane The pane just closed, ie: north, south, east, or west - */ -, setAsClosed = function (pane) { - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , side = _c[pane].side.toLowerCase() - , inset = "inset"+ _c[pane].side - , rClass = o.resizerClass - , tClass = o.togglerClass - , _pane = "-"+ pane // used for classNames - , _open = "-open" - , _sliding= "-sliding" - , _closed = "-closed" - ; - $R - .css(side, sC[inset]) // move the resizer - .removeClass( rClass+_open +" "+ rClass+_pane+_open ) - .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - .addClass( rClass+_closed +" "+ rClass+_pane+_closed ) - .unbind("dblclick."+ sID) - ; - // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent? - if (o.resizable && typeof $.fn.draggable == "function") - $R - .draggable("disable") - .removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here - .css("cursor", "default") - .attr("title","") - ; - - // if pane has a toggler button, adjust that too - if ($T) { - $T - .removeClass( tClass+_open +" "+ tClass+_pane+_open ) - .addClass( tClass+_closed +" "+ tClass+_pane+_closed ) - .attr("title", o.togglerTip_closed) // may be blank - ; - // toggler-content - if exists - $T.children(".content-open").hide(); - $T.children(".content-closed").css("display","block"); - } - - // sync any 'pin buttons' - syncPinBtns(pane, false); - - if (state.initialized) { - // resize 'length' and position togglers for adjacent panes - sizeHandles("all"); - } - } - - /** - * Open the specified pane (animation optional), and resize all other panes as needed - * - * @param {string} pane The pane being opened, ie: north, south, east, or west - * @param {boolean=} slide - * @param {boolean=} noAnimation - * @param {boolean=} noAlert - */ -, open = function (pane, slide, noAnimation, noAlert) { - if (!isInitialized()) return; - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , doFX = !noAnimation && s.isClosed && (o.fxName_open != "none") - // transfer logic var to temp var - , isShowing = s.isShowing - ; - // now clear the logic var - delete s.isShowing; - - if (!$P || (!o.resizable && !o.closable && !isShowing)) return; // invalid request - else if (s.isVisible && !s.isSliding) return; // already open - - // pane can ALSO be unhidden by just calling show(), so handle this scenario - if (s.isHidden && !isShowing) { - show(pane, true); - return; - } - - if (_c.isLayoutBusy) { // layout is 'busy' - probably with an animation - _queue("open", pane, slide); // set a callback for this action, if possible - return; // ABORT - } - - setSizeLimits(pane, slide); // update pane-state - - // onopen_start callback - will CANCEL hide if returns false - if (false === _execCallback(pane, o.onopen_start)) return; - - // make sure there is enough space available to open the pane - setSizeLimits(pane, slide); // update pane-state - if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN! - syncPinBtns(pane, false); // make sure pin-buttons are reset - if (!noAlert && o.noRoomToOpenTip) - alert(o.noRoomToOpenTip); - return; // ABORT - } - - // SET flow-control flags - _c[pane].isMoving = true; - _c.isLayoutBusy = true; - - if (slide) // START Sliding - will set isSliding=true - bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane - else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead - bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false - else if (o.slidable) - bindStartSlidingEvent(pane, false); // UNBIND trigger events - - s.noRoom = false; // will be reset by makePaneFit if 'noRoom' - makePaneFit(pane); - - s.isVisible = true; - s.isClosed = false; - // update isHidden BEFORE sizing panes - WHY??? Old? - if (isShowing) s.isHidden = false; - - if (doFX) { // ANIMATE - lockPaneForFX(pane, true); // need to set left/top so animation will work - $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() { - lockPaneForFX(pane, false); // undo - open_2(); // continue - }); - } - else {// no animation - $P.show(); // just show pane and... - open_2(); // continue - }; - - // SUBROUTINE - function open_2 () { - if (s.isVisible) { // make sure pane was not closed or hidden before animation finished! - - // cure iframe display issues - _fixIframe(pane); - - // NOTE: if isSliding, then other panes are NOT 'resized' - if (!s.isSliding) // resize all panes adjacent to this one - sizeMidPanes(_c[pane].dir=="vert" ? "center" : "all", false); // false = NOT skipCallback - - // set classes, position handles and execute callbacks... - setAsOpen(pane); - } - - // internal flow-control callback - _dequeue(pane); - }; - - } - - /** - * @param {string} pane The pane just opened, ie: north, south, east, or west - * @param {boolean=} skipCallback - */ -, setAsOpen = function (pane, skipCallback) { - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , side = _c[pane].side.toLowerCase() - , inset = "inset"+ _c[pane].side - , rClass = o.resizerClass - , tClass = o.togglerClass - , _pane = "-"+ pane // used for classNames - , _open = "-open" - , _closed = "-closed" - , _sliding= "-sliding" - ; - $R - .css(side, sC[inset] + getPaneSize(pane)) // move the resizer - .removeClass( rClass+_closed +" "+ rClass+_pane+_closed ) - .addClass( rClass+_open +" "+ rClass+_pane+_open ) - ; - if (s.isSliding) - $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - else // in case 'was sliding' - $R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - - if (o.resizerDblClickToggle) - $R.bind("dblclick", toggle ); - removeHover( 0, $R ); // remove hover classes - if (o.resizable && typeof $.fn.draggable == "function") - $R - .draggable("enable") - .css("cursor", o.resizerCursor) - .attr("title", o.resizerTip) - ; - else if (!s.isSliding) - $R.css("cursor", "default"); // n-resize, s-resize, etc - - // if pane also has a toggler button, adjust that too - if ($T) { - $T - .removeClass( tClass+_closed +" "+ tClass+_pane+_closed ) - .addClass( tClass+_open +" "+ tClass+_pane+_open ) - .attr("title", o.togglerTip_open) // may be blank - ; - removeHover( 0, $T ); // remove hover classes - // toggler-content - if exists - $T.children(".content-closed").hide(); - $T.children(".content-open").css("display","block"); - } - - // sync any 'pin buttons' - syncPinBtns(pane, !s.isSliding); - - // update pane-state dimensions - BEFORE resizing content - $.extend(s, elDims($P)); - - if (state.initialized) { - // resize resizer & toggler sizes for all panes - sizeHandles("all"); - // resize content every time pane opens - to be sure - sizeContent(pane, true); // true = remeasure headers/footers, even if 'isLayoutBusy' - } - - if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) { - // onopen callback - _execCallback(pane, o.onopen_end || o.onopen); - // onshow callback - TODO: should this be here? - if (s.isShowing) _execCallback(pane, o.onshow_end || o.onshow); - // ALSO call onresize because layout-size *may* have changed while pane was closed - if (state.initialized) { - _execCallback(pane, o.onresize_end || o.onresize); - resizeNestedLayout(pane); - } - } - } - - - /** - * slideOpen / slideClose / slideToggle - * - * Pass-though methods for sliding - */ -, slideOpen = function (evt_or_pane) { - if (!isInitialized()) return; - var - evt = isStr(evt_or_pane) ? null : evt_or_pane - , pane = evt ? $(this).data("layoutEdge") : evt_or_pane - , s = state[pane] - , delay = options[pane].slideDelay_open - ; - // prevent event from triggering on NEW resizer binding created below - if (evt) evt.stopImmediatePropagation(); - - if (s.isClosed && evt && evt.type == "mouseenter" && delay > 0) - // trigger = mouseenter - use a delay - timer.set(pane+"_openSlider", open_NOW, delay); - else - open_NOW(); // will unbind events if is already open - - /** - * SUBROUTINE for timed open - */ - function open_NOW (evt) { - if (!s.isClosed) // skip if no longer closed! - bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane - else if (!_c[pane].isMoving) - open(pane, true); // true = slide - open() will handle binding - }; - } - -, slideClose = function (evt_or_pane) { - if (!isInitialized()) return; - var - evt = isStr(evt_or_pane) ? null : evt_or_pane - , pane = evt ? $(this).data("layoutEdge") : evt_or_pane - , o = options[pane] - , s = state[pane] - , delay = _c[pane].isMoving ? 1000 : 300 // MINIMUM delay - option may override - ; - - if (s.isClosed || s.isResizing) - return; // skip if already closed OR in process of resizing - else if (o.slideTrigger_close == "click") - close_NOW(); // close immediately onClick - else if (o.preventQuickSlideClose && _c.isLayoutBusy) - return; // handle Chrome quick-close on slide-open - else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane])) - return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE - else if (evt) // trigger = mouseleave - use a delay - // 1 sec delay if 'opening', else .3 sec - timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay)); - else // called programically - close_NOW(); - - /** - * SUBROUTINE for timed close - */ - function close_NOW () { - if (s.isClosed) // skip 'close' if already closed! - bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here? - else if (!_c[pane].isMoving) - close(pane); // close will handle unbinding - }; - } - -, slideToggle = function (pane) { toggle(pane, true); } - - - /** - * Must set left/top on East/South panes so animation will work properly - * - * @param {string} pane The pane to lock, 'east' or 'south' - any other is ignored! - * @param {boolean} doLock true = set left/top, false = remove - */ -, lockPaneForFX = function (pane, doLock) { - var $P = $Ps[pane]; - if (doLock) { - $P.css({ zIndex: _c.zIndex.pane_animate }); // overlay all elements during animation - if (pane=="south") - $P.css({ top: sC.insetTop + sC.innerHeight - $P.outerHeight() }); - else if (pane=="east") - $P.css({ left: sC.insetLeft + sC.innerWidth - $P.outerWidth() }); - } - else { // animation DONE - RESET CSS - // TODO: see if this can be deleted. It causes a quick-close when sliding in Chrome - $P.css({ zIndex: (state[pane].isSliding ? _c.zIndex.pane_sliding : _c.zIndex.pane_normal) }); - if (pane=="south") - $P.css({ top: "auto" }); - else if (pane=="east") - $P.css({ left: "auto" }); - // fix anti-aliasing in IE - only needed for animations that change opacity - var o = options[pane]; - if ($.layout.browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1) - $P[0].style.removeAttribute('filter'); - } - } - - - /** - * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger - * - * @see open(), close() - * @param {string} pane The pane to enable/disable, 'north', 'south', etc. - * @param {boolean} enable Enable or Disable sliding? - */ -, bindStartSlidingEvent = function (pane, enable) { - var - o = options[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , trigger = o.slideTrigger_open.toLowerCase() - ; - if (!$R || (enable && !o.slidable)) return; - - // make sure we have a valid event - if (trigger.match(/mouseover/)) - trigger = o.slideTrigger_open = "mouseenter"; - else if (!trigger.match(/click|dblclick|mouseenter/)) - trigger = o.slideTrigger_open = "click"; - - $R - // add or remove trigger event - [enable ? "bind" : "unbind"](trigger +'.'+ sID, slideOpen) - // set the appropriate cursor & title/tip - .css("cursor", enable ? o.sliderCursor : "default") - .attr("title", enable ? o.sliderTip : "") - ; - } - - /** - * Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed - * Also increases zIndex when pane is sliding open - * See bindStartSlidingEvent for code to control 'slide open' - * - * @see slideOpen(), slideClose() - * @param {string} pane The pane to process, 'north', 'south', etc. - * @param {boolean} enable Enable or Disable events? - */ -, bindStopSlidingEvents = function (pane, enable) { - var - o = options[pane] - , s = state[pane] - , z = _c.zIndex - , trigger = o.slideTrigger_close.toLowerCase() - , action = (enable ? "bind" : "unbind") - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - s.isSliding = enable; // logic - timer.clear(pane+"_closeSlider"); // just in case - - // remove 'slideOpen' trigger event from resizer - // ALSO will raise the zIndex of the pane & resizer - if (enable) bindStartSlidingEvent(pane, false); - - // RE/SET zIndex - increases when pane is sliding-open, resets to normal when not - $P.css("zIndex", enable ? z.pane_sliding : z.pane_normal); - $R.css("zIndex", enable ? z.pane_sliding : z.resizer_normal); - - // make sure we have a valid event - if (!trigger.match(/click|mouseleave/)) - trigger = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout' - - // add/remove slide triggers - $R[action](trigger, slideClose); // base event on resize - // need extra events for mouseleave - if (trigger == "mouseleave") { - // also close on pane.mouseleave - $P[action]("mouseleave."+ sID, slideClose); - // cancel timer when mouse moves between 'pane' and 'resizer' - $R[action]("mouseenter."+ sID, cancelMouseOut); - $P[action]("mouseenter."+ sID, cancelMouseOut); - } - - if (!enable) - timer.clear(pane+"_closeSlider"); - else if (trigger == "click" && !o.resizable) { - // IF pane is not resizable (which already has a cursor and tip) - // then set the a cursor & title/tip on resizer when sliding - $R.css("cursor", enable ? o.sliderCursor : "default"); - $R.attr("title", enable ? o.togglerTip_open : ""); // use Toggler-tip, eg: "Close Pane" - } - - // SUBROUTINE for mouseleave timer clearing - function cancelMouseOut (evt) { - timer.clear(pane+"_closeSlider"); - evt.stopPropagation(); - } - } - - - /** - * Hides/closes a pane if there is insufficient room - reverses this when there is room again - * MUST have already called setSizeLimits() before calling this method - * - * @param {string} pane The pane being resized - * @param {boolean=} isOpening Called from onOpen? - * @param {boolean=} skipCallback Should the onresize callback be run? - * @param {boolean=} force - */ -, makePaneFit = function (pane, isOpening, skipCallback, force) { - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , isSidePane = c.dir=="vert" - , hasRoom = false - ; - - // special handling for center & east/west panes - if (pane == "center" || (isSidePane && s.noVerticalRoom)) { - // see if there is enough room to display the pane - // ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth); - hasRoom = (s.maxHeight > 0); - if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now - $P.show(); - if ($R) $R.show(); - s.isVisible = true; - s.noRoom = false; - if (isSidePane) s.noVerticalRoom = false; - _fixIframe(pane); - } - else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now - $P.hide(); - if ($R) $R.hide(); - s.isVisible = false; - s.noRoom = true; - } - } - - // see if there is enough room to fit the border-pane - if (pane == "center") { - // ignore center in this block - } - else if (s.minSize <= s.maxSize) { // pane CAN fit - hasRoom = true; - if (s.size > s.maxSize) // pane is too big - shrink it - sizePane(pane, s.maxSize, skipCallback, force); - else if (s.size < s.minSize) // pane is too small - enlarge it - sizePane(pane, s.minSize, skipCallback, force); - else if ($R && $P.is(":visible")) { - // make sure resizer-bar is positioned correctly - // handles situation where nested layout was 'hidden' when initialized - var - side = c.side.toLowerCase() - , pos = s.size + sC["inset"+ c.side] - ; - if ($.layout.cssNum($R, side) != pos) $R.css( side, pos ); - } - - // if was previously hidden due to noRoom, then RESET because NOW there is room - if (s.noRoom) { - // s.noRoom state will be set by open or show - if (s.wasOpen && o.closable) { - if (o.autoReopen) - open(pane, false, true, true); // true = noAnimation, true = noAlert - else // leave the pane closed, so just update state - s.noRoom = false; - } - else - show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert - } - } - else { // !hasRoom - pane CANNOT fit - if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now... - s.noRoom = true; // update state - s.wasOpen = !s.isClosed && !s.isSliding; - if (s.isClosed){} // SKIP - else if (o.closable) // 'close' if possible - close(pane, true, true); // true = force, true = noAnimation - else // 'hide' pane if cannot just be closed - hide(pane, true); // true = noAnimation - } - } - } - - - /** - * sizePane / manualSizePane - * sizePane is called only by internal methods whenever a pane needs to be resized - * manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized' - * - * @param {string} pane The pane being resized - * @param {number} size The *desired* new size for this pane - will be validated - * @param {boolean=} skipCallback Should the onresize callback be run? - */ -, manualSizePane = function (pane, size, skipCallback) { - if (!isInitialized()) return; - // ANY call to sizePane will disabled autoResize - var - o = options[pane] - // if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete... - , forceResize = o.resizeWhileDragging && !_c.isLayoutBusy // && !o.triggerEventsWhileDragging - ; - o.autoResize = false; - // flow-through... - sizePane(pane, size, skipCallback, forceResize); - } - - /** - * @param {string} pane The pane being resized - * @param {number} size The *desired* new size for this pane - will be validated - * @param {boolean=} skipCallback Should the onresize callback be run? - * @param {boolean=} force Force resizing even if does not seem necessary - */ -, sizePane = function (pane, size, skipCallback, force) { - if (!isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , side = _c[pane].side.toLowerCase() - , dimName = _c[pane].sizeType.toLowerCase() - , inset = "inset"+ _c[pane].side - , skipResizeWhileDragging = _c.isLayoutBusy && !o.triggerEventsWhileDragging - , oldSize - ; - // calculate 'current' min/max sizes - setSizeLimits(pane); // update pane-state - oldSize = s.size; - - size = _parseSize(pane, size); // handle percentages & auto - size = max(size, _parseSize(pane, o.minSize)); - size = min(size, s.maxSize); - if (size < s.minSize) { // not enough room for pane! - makePaneFit(pane, false, skipCallback); // will hide or close pane - return; - } - - // IF newSize is same as oldSize, then nothing to do - abort - if (!force && size == oldSize) return; - - // onresize_start callback CANNOT cancel resizing because this would break the layout! - if (!skipCallback && state.initialized && s.isVisible) - _execCallback(pane, o.onresize_start); - - // resize the pane, and make sure its visible - $P.css( dimName, max(1, cssSize(pane, size)) ); - -/* -var - edge = _c[pane].sizeType.toLowerCase() -, test = [{ - target: size - , attempt: size - , actual: edge=='width' ? $P.outerWidth() : $P.outerHeight() - }] -, lastTest = test[0] -, thisTest = {} -; -while (lastTest.actual != size) { - test.push( {} ); - thisTest = test[ test.length - 1 ]; - - if (lastTest.actual > size) - thisTest.attempt = Math.max(1, lastTest.attempt - (lastTest.actual - size)); - else // lastTest.actual < size - thisTest.attempt = Math.max(1, lastTest.attempt + (size - lastTest.actual)); - - $P.css( edge, cssSize(pane, thisTest.attempt) ); - - thisTest.actual = edge=='width' ? $P.outerWidth() : $P.outerHeight() - - // after 3 tries, is as close as its gonna get! - if (test.length == 3) break; - else lastTest = thisTest; -} -debugData( test, pane ); -*/ - - // update pane-state dimensions - s.size = size; - $.extend(s, elDims($P)); - - // reposition the resizer-bar - if ($R && $P.is(":visible")) $R.css( side, size + sC[inset] ); - - sizeContent(pane); - - if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible) { - _execCallback(pane, o.onresize_end || o.onresize); - resizeNestedLayout(pane); - } - - // resize all the adjacent panes, and adjust their toggler buttons - // when skipCallback passed, it means the controlling method will handle 'other panes' - if (!skipCallback) { - // also no callback if live-resize is in progress and NOT triggerEventsWhileDragging - if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "all" : "center", skipResizeWhileDragging, force); - sizeHandles("all"); - } - - // if opposite-pane was autoClosed, see if it can be autoOpened now - var altPane = _c.altSide[pane]; - if (size < oldSize && state[ altPane ].noRoom) { - setSizeLimits( altPane ); - makePaneFit( altPane, false, skipCallback ); - } - } - - /** - * @see initPanes(), sizePane(), resizeAll(), open(), close(), hide() - * @param {string} panes The pane(s) being resized, comma-delmited string - * @param {boolean=} skipCallback Should the onresize callback be run? - * @param {boolean=} force - */ -, sizeMidPanes = function (panes, skipCallback, force) { - if (!panes || panes == "all") panes = "east,west,center"; - - $.each(panes.split(","), function (i, pane) { - if (!$Ps[pane]) return; // NO PANE - skip - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , isCenter= (pane=="center") - , hasRoom = true - , CSS = {} - , newCenter = calcNewCenterPaneDims() - ; - // update pane-state dimensions - $.extend(s, elDims($P)); - - if (pane == "center") { - if (!force && s.isVisible && newCenter.width == s.outerWidth && newCenter.height == s.outerHeight) - return true; // SKIP - pane already the correct size - // set state for makePaneFit() logic - $.extend(s, cssMinDims(pane), { - maxWidth: newCenter.width - , maxHeight: newCenter.height - }); - CSS = newCenter; - // convert OUTER width/height to CSS width/height - CSS.width = cssW(pane, CSS.width); - CSS.height = cssH(pane, CSS.height); - hasRoom = CSS.width > 0 && CSS.height > 0; - // during layout init, try to shrink east/west panes to make room for center - if (!hasRoom && !state.initialized && o.minWidth > 0) { - var - reqPx = o.minWidth - s.outerWidth - , minE = options.east.minSize || 0 - , minW = options.west.minSize || 0 - , sizeE = state.east.size - , sizeW = state.west.size - , newE = sizeE - , newW = sizeW - ; - if (reqPx > 0 && state.east.isVisible && sizeE > minE) { - newE = max( sizeE-minE, sizeE-reqPx ); - reqPx -= sizeE-newE; - } - if (reqPx > 0 && state.west.isVisible && sizeW > minW) { - newW = max( sizeW-minW, sizeW-reqPx ); - reqPx -= sizeW-newW; - } - // IF we found enough extra space, then resize the border panes as calculated - if (reqPx == 0) { - if (sizeE != minE) - sizePane('east', newE, true); // true = skipCallback - initPanes will handle when done - if (sizeW != minW) - sizePane('west', newW, true); - // now start over! - sizeMidPanes('center', skipCallback, force); - return; // abort this loop - } - } - } - else { // for east and west, set only the height, which is same as center height - // set state.min/maxWidth/Height for makePaneFit() logic - if (s.isVisible && !s.noVerticalRoom) - $.extend(s, elDims($P), cssMinDims(pane)) - if (!force && !s.noVerticalRoom && newCenter.height == s.outerHeight) - return true; // SKIP - pane already the correct size - // east/west have same top, bottom & height as center - CSS.top = newCenter.top; - CSS.bottom = newCenter.bottom; - CSS.height = cssH(pane, newCenter.height); - s.maxHeight = max(0, CSS.height); - hasRoom = (s.maxHeight > 0); - if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic - } - - if (hasRoom) { - // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized - if (!skipCallback && state.initialized) - _execCallback(pane, o.onresize_start); - - $P.css(CSS); // apply the CSS to pane - if (s.noRoom && !s.isClosed && !s.isHidden) - makePaneFit(pane); // will re-open/show auto-closed/hidden pane - if (s.isVisible) { - $.extend(s, elDims($P)); // update pane dimensions - if (state.initialized) sizeContent(pane); // also resize the contents, if exists - } - } - else if (!s.noRoom && s.isVisible) // no room for pane - makePaneFit(pane); // will hide or close pane - - if (!s.isVisible) - return true; // DONE - next pane - - /* - * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes - * Normally these panes have only 'left' & 'right' positions so pane auto-sizes - * ALSO required when pane is an IFRAME because will NOT default to 'full width' - */ - if (pane == "center") { // finished processing midPanes - var b = $.layout.browser; - var fix = b.isIE6 || (b.msie && !b.boxModel); - if ($Ps.north && (fix || state.north.tagName=="IFRAME")) - $Ps.north.css("width", cssW($Ps.north, sC.innerWidth)); - if ($Ps.south && (fix || state.south.tagName=="IFRAME")) - $Ps.south.css("width", cssW($Ps.south, sC.innerWidth)); - } - - // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized - if (!skipCallback && state.initialized) { - _execCallback(pane, o.onresize_end || o.onresize); - resizeNestedLayout(pane); - } - }); - } - - - /** - * @see window.onresize(), callbacks or custom code - */ -, resizeAll = function () { - if (!state.initialized) { - _initLayoutElements(); - return; // no need to resize since we just initialized! - } - var oldW = sC.innerWidth - , oldH = sC.innerHeight - ; - // cannot size layout when 'container' is hidden or collapsed - if (!$N.is(":visible:") ) return; - $.extend( state.container, elDims( $N ) ); // UPDATE container dimensions - if (!sC.outerHeight) return; - - // onresizeall_start will CANCEL resizing if returns false - // state.container has already been set, so user can access this info for calcuations - if (false === _execCallback(null, options.onresizeall_start)) return false; - - var // see if container is now 'smaller' than before - shrunkH = (sC.innerHeight < oldH) - , shrunkW = (sC.innerWidth < oldW) - , $P, o, s, dir - ; - // NOTE special order for sizing: S-N-E-W - $.each(["south","north","east","west"], function (i, pane) { - if (!$Ps[pane]) return; // no pane - SKIP - s = state[pane]; - o = options[pane]; - dir = _c[pane].dir; - - if (o.autoResize && s.size != o.size) // resize pane to original size set in options - sizePane(pane, o.size, true, true); // true=skipCallback, true=forceResize - else { - setSizeLimits(pane); - makePaneFit(pane, false, true, true); // true=skipCallback, true=forceResize - } - }); - - sizeMidPanes("all", true, true); // true=skipCallback, true=forceResize - sizeHandles("all"); // reposition the toggler elements - - // trigger all individual pane callbacks AFTER layout has finished resizing - o = options; // reuse alias - $.each(_c.allPanes.split(","), function (i, pane) { - $P = $Ps[pane]; - if (!$P) return; // SKIP - if (state[pane].isVisible) { // undefined for non-existent panes - _execCallback(pane, o[pane].onresize_end || o[pane].onresize); // callback - if exists - resizeNestedLayout(pane); - } - }); - - _execCallback(null, o.onresizeall_end || o.onresizeall); // onresizeall callback, if exists - } - - - /** - * Whenever a pane resizes or opens that has a nested layout, trigger resizeAll - * - * @param {string} pane The pane just resized or opened - */ -, resizeNestedLayout = function (pane) { - var - $P = $Ps[pane] - , $C = $Cs[pane] - , d = "layoutContainer" - ; - if (options[pane].resizeNestedLayout) { - if ($P.data( d )) - $P.layout().resizeAll(); - else if ($C && $C.data( d )) - $C.layout().resizeAll(); - } - } - - - /** - * IF pane has a content-div, then resize all elements inside pane to fit pane-height - * - * @param {string=} panes The pane(s) being resized - * @param {boolean=} remeasure Should the content (header/footer) be remeasured? - */ -, sizeContent = function (panes, remeasure) { - if (!isInitialized()) return; - if (!panes || panes == "all") panes = _c.allPanes; - $.each(panes.split(","), function (idx, pane) { - var - $P = $Ps[pane] - , $C = $Cs[pane] - , o = options[pane] - , s = state[pane] - , m = s.content // m = measurements - ; - if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip - - // onsizecontent_start will CANCEL resizing if returns false - if (false === _execCallback(null, o.onsizecontent_start)) return; - - // skip re-measuring offsets if live-resizing - if (!_c.isLayoutBusy || m.top == undefined || remeasure || o.resizeContentWhileDragging) { - _measure(); - // if any footers are below pane-bottom, they may not measure correctly, - // so allow pane overflow and re-measure - if (m.hiddenFooters > 0 && $P.css("overflow") == "hidden") { - $P.css("overflow", "visible"); - _measure(); // remeasure while overflowing - $P.css("overflow", "hidden"); - } - } - // NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders - var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom); - if (!$C.is(":visible") || m.height != newH) { - // size the Content element to fit new pane-size - will autoHide if not enough room - setOuterHeight($C, newH, true); // true=autoHide - m.height = newH; // save new height - }; - - if (state.initialized) { - _execCallback(pane, o.onsizecontent_end || o.onsizecontent); - resizeNestedLayout(pane); - } - - - function _below ($E) { - return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0)); - }; - - function _measure () { - var - ignore = options[pane].contentIgnoreSelector - , $Fs = $C.nextAll().not(ignore || ':lt(0)') // not :lt(0) = ALL - , $Fs_vis = $Fs.filter(':visible') - , $F = $Fs_vis.filter(':last') - ; - m = { - top: $C[0].offsetTop - , height: $C.outerHeight() - , numFooters: $Fs.length - , hiddenFooters: $Fs.length - $Fs_vis.length - , spaceBelow: 0 // correct if no content footer ($E) - } - m.spaceAbove = m.top; // just for state - not used in calc - m.bottom = m.top + m.height; - if ($F.length) - //spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom) - m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F); - else // no footer - check marginBottom on Content element itself - m.spaceBelow = _below($C); - }; - }); - } - - - /** - * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary - * - * @see initHandles(), open(), close(), resizeAll() - * @param {string=} panes The pane(s) being resized - */ -, sizeHandles = function (panes) { - if (!panes || panes == "all") panes = _c.borderPanes; - - $.each(panes.split(","), function (i, pane) { - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , $TC - ; - if (!$P || !$R) return; - - var - dir = _c[pane].dir - , _state = (s.isClosed ? "_closed" : "_open") - , spacing = o["spacing"+ _state] - , togAlign = o["togglerAlign"+ _state] - , togLen = o["togglerLength"+ _state] - , paneLen - , offset - , CSS = {} - ; - - if (spacing == 0) { - $R.hide(); - return; - } - else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason - $R.show(); // in case was previously hidden - - // Resizer Bar is ALWAYS same width/height of pane it is attached to - if (dir == "horz") { // north/south - paneLen = $P.outerWidth(); // s.outerWidth || - s.resizerLength = paneLen; - $R.css({ - width: max(1, cssW($R, paneLen)) // account for borders & padding - , height: max(0, cssH($R, spacing)) // ditto - , left: $.layout.cssNum($P, "left") - }); - } - else { // east/west - paneLen = $P.outerHeight(); // s.outerHeight || - s.resizerLength = paneLen; - $R.css({ - height: max(1, cssH($R, paneLen)) // account for borders & padding - , width: max(0, cssW($R, spacing)) // ditto - , top: sC.insetTop + getPaneSize("north", true) // TODO: what if no North pane? - //, top: $.layout.cssNum($Ps["center"], "top") - }); - } - - // remove hover classes - removeHover( o, $R ); - - if ($T) { - if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) { - $T.hide(); // always HIDE the toggler when 'sliding' - return; - } - else - $T.show(); // in case was previously hidden - - if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) { - togLen = paneLen; - offset = 0; - } - else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed - if (isStr(togAlign)) { - switch (togAlign) { - case "top": - case "left": offset = 0; - break; - case "bottom": - case "right": offset = paneLen - togLen; - break; - case "middle": - case "center": - default: offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos - } - } - else { // togAlign = number - var x = parseInt(togAlign, 10); // - if (togAlign >= 0) offset = x; - else offset = paneLen - togLen + x; // NOTE: x is negative! - } - } - - if (dir == "horz") { // north/south - var width = cssW($T, togLen); - $T.css({ - width: max(0, width) // account for borders & padding - , height: max(1, cssH($T, spacing)) // ditto - , left: offset // TODO: VERIFY that toggler positions correctly for ALL values - , top: 0 - }); - // CENTER the toggler content SPAN - $T.children(".content").each(function(){ - $TC = $(this); - $TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative - }); - } - else { // east/west - var height = cssH($T, togLen); - $T.css({ - height: max(0, height) // account for borders & padding - , width: max(1, cssW($T, spacing)) // ditto - , top: offset // POSITION the toggler - , left: 0 - }); - // CENTER the toggler content SPAN - $T.children(".content").each(function(){ - $TC = $(this); - $TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative - }); - } - - // remove ALL hover classes - removeHover( 0, $T ); - } - - // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now - if (!state.initialized && (o.initHidden || s.noRoom)) { - $R.hide(); - if ($T) $T.hide(); - } - }); - } - - -, enableClosable = function (pane) { - if (!isInitialized()) return; - var $T = $Ts[pane], o = options[pane]; - if (!$T) return; - o.closable = true; - $T .bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); }) - .bind("mouseenter."+ sID, addHover) - .bind("mouseleave."+ sID, removeHover) - .css("visibility", "visible") - .css("cursor", "pointer") - .attr("title", state[pane].isClosed ? o.togglerTip_closed : o.togglerTip_open) // may be blank - .show() - ; - } - -, disableClosable = function (pane, hide) { - if (!isInitialized()) return; - var $T = $Ts[pane]; - if (!$T) return; - options[pane].closable = false; - // is closable is disable, then pane MUST be open! - if (state[pane].isClosed) open(pane, false, true); - $T .unbind("."+ sID) - .css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues - .css("cursor", "default") - .attr("title", "") - ; - } - - -, enableSlidable = function (pane) { - if (!isInitialized()) return; - var $R = $Rs[pane], o = options[pane]; - if (!$R || !$R.data('draggable')) return; - options[pane].slidable = true; - if (s.isClosed) - bindStartSlidingEvent(pane, true); - } - -, disableSlidable = function (pane) { - if (!isInitialized()) return; - var $R = $Rs[pane]; - if (!$R) return; - options[pane].slidable = false; - if (state[pane].isSliding) - close(pane, false, true); - else { - bindStartSlidingEvent(pane, false); - $R .css("cursor", "default") - .attr("title", "") - ; - removeHover(null, $R[0]); // in case currently hovered - } - } - - -, enableResizable = function (pane) { - if (!isInitialized()) return; - var $R = $Rs[pane], o = options[pane]; - if (!$R || !$R.data('draggable')) return; - o.resizable = true; - $R .draggable("enable") - .bind("mouseenter."+ sID, onResizerEnter) - .bind("mouseleave."+ sID, onResizerLeave) - ; - if (!state[pane].isClosed) - $R .css("cursor", o.resizerCursor) - .attr("title", o.resizerTip) - ; - } - -, disableResizable = function (pane) { - if (!isInitialized()) return; - var $R = $Rs[pane]; - if (!$R || !$R.data('draggable')) return; - options[pane].resizable = false; - $R .draggable("disable") - .unbind("."+ sID) - .css("cursor", "default") - .attr("title", "") - ; - removeHover(null, $R[0]); // in case currently hovered - } - - - /** - * Move a pane from source-side (eg, west) to target-side (eg, east) - * If pane exists on target-side, move that to source-side, ie, 'swap' the panes - * - * @param {string} pane1 The pane/edge being swapped - * @param {string} pane2 ditto - */ -, swapPanes = function (pane1, pane2) { - if (!isInitialized()) return; - // change state.edge NOW so callbacks can know where pane is headed... - state[pane1].edge = pane2; - state[pane2].edge = pane1; - // run these even if NOT state.initialized - var cancelled = false; - if (false === _execCallback(pane1, options[pane1].onswap_start)) cancelled = true; - if (!cancelled && false === _execCallback(pane2, options[pane2].onswap_start)) cancelled = true; - if (cancelled) { - state[pane1].edge = pane1; // reset - state[pane2].edge = pane2; - return; - } - - var - oPane1 = copy( pane1 ) - , oPane2 = copy( pane2 ) - , sizes = {} - ; - sizes[pane1] = oPane1 ? oPane1.state.size : 0; - sizes[pane2] = oPane2 ? oPane2.state.size : 0; - - // clear pointers & state - $Ps[pane1] = false; - $Ps[pane2] = false; - state[pane1] = {}; - state[pane2] = {}; - - // ALWAYS remove the resizer & toggler elements - if ($Ts[pane1]) $Ts[pane1].remove(); - if ($Ts[pane2]) $Ts[pane2].remove(); - if ($Rs[pane1]) $Rs[pane1].remove(); - if ($Rs[pane2]) $Rs[pane2].remove(); - $Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false; - - // transfer element pointers and data to NEW Layout keys - move( oPane1, pane2 ); - move( oPane2, pane1 ); - - // cleanup objects - oPane1 = oPane2 = sizes = null; - - // make panes 'visible' again - if ($Ps[pane1]) $Ps[pane1].css(_c.visible); - if ($Ps[pane2]) $Ps[pane2].css(_c.visible); - - // fix any size discrepancies caused by swap - resizeAll(); - - // run these even if NOT state.initialized - _execCallback(pane1, options[pane1].onswap_end || options[pane1].onswap); - _execCallback(pane2, options[pane2].onswap_end || options[pane2].onswap); - - return; - - function copy (n) { // n = pane - var - $P = $Ps[n] - , $C = $Cs[n] - ; - return !$P ? false : { - pane: n - , P: $P ? $P[0] : false - , C: $C ? $C[0] : false - , state: $.extend({}, state[n]) - , options: $.extend({}, options[n]) - } - }; - - function move (oPane, pane) { - if (!oPane) return; - var - P = oPane.P - , C = oPane.C - , oldPane = oPane.pane - , c = _c[pane] - , side = c.side.toLowerCase() - , inset = "inset"+ c.side - // save pane-options that should be retained - , s = $.extend({}, state[pane]) - , o = options[pane] - // RETAIN side-specific FX Settings - more below - , fx = { resizerCursor: o.resizerCursor } - , re, size, pos - ; - $.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) { - fx[k] = o[k]; - fx[k +"_open"] = o[k +"_open"]; - fx[k +"_close"] = o[k +"_close"]; - }); - - // update object pointers and attributes - $Ps[pane] = $(P) - .data("layoutEdge", pane) - .css(_c.hidden) - .css(c.cssReq) - ; - $Cs[pane] = C ? $(C) : false; - - // set options and state - options[pane] = $.extend({}, oPane.options, fx); - state[pane] = $.extend({}, oPane.state); - - // change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west - re = new RegExp(o.paneClass +"-"+ oldPane, "g"); - P.className = P.className.replace(re, o.paneClass +"-"+ pane); - - // ALWAYS regenerate the resizer & toggler elements - initHandles(pane); // create the required resizer & toggler - - // if moving to different orientation, then keep 'target' pane size - if (c.dir != _c[oldPane].dir) { - size = sizes[pane] || 0; - setSizeLimits(pane); // update pane-state - size = max(size, state[pane].minSize); - // use manualSizePane to disable autoResize - not useful after panes are swapped - manualSizePane(pane, size, true); // true = skipCallback - } - else // move the resizer here - $Rs[pane].css(side, sC[inset] + (state[pane].isVisible ? getPaneSize(pane) : 0)); - - - // ADD CLASSNAMES & SLIDE-BINDINGS - if (oPane.state.isVisible && !s.isVisible) - setAsOpen(pane, true); // true = skipCallback - else { - setAsClosed(pane); - bindStartSlidingEvent(pane, true); // will enable events IF option is set - } - - // DESTROY the object - oPane = null; - }; - } - - -; // END var DECLARATIONS - - /** - * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed - * - * @see document.keydown() - */ - function keyDown (evt) { - if (!evt) return true; - var code = evt.keyCode; - if (code < 33) return true; // ignore special keys: ENTER, TAB, etc - - var - PANE = { - 38: "north" // Up Cursor - $.ui.keyCode.UP - , 40: "south" // Down Cursor - $.ui.keyCode.DOWN - , 37: "west" // Left Cursor - $.ui.keyCode.LEFT - , 39: "east" // Right Cursor - $.ui.keyCode.RIGHT - } - , ALT = evt.altKey // no worky! - , SHIFT = evt.shiftKey - , CTRL = evt.ctrlKey - , CURSOR = (CTRL && code >= 37 && code <= 40) - , o, k, m, pane - ; - - if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey - pane = PANE[code]; - else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey - $.each(_c.borderPanes.split(","), function (i, p) { // loop each pane to check its hotkey - o = options[p]; - k = o.customHotkey; - m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT" - if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches - if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches - pane = p; - return false; // BREAK - } - } - }); - - // validate pane - if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden) - return true; - - toggle(pane); - - evt.stopPropagation(); - evt.returnValue = false; // CANCEL key - return false; - }; - - -/* - * ###################################### - * UTILITY METHODS - * called externally or by initButtons - * ###################################### - */ - - /** - * Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work - * - * @param {Object=} el (optional) Can also be 'bound' to a click, mouseOver, or other event - */ - function allowOverflow (el) { - if (!isInitialized()) return; - if (this && this.tagName) el = this; // BOUND to element - var $P; - if (isStr(el)) - $P = $Ps[el]; - else if ($(el).data("layoutRole")) - $P = $(el); - else - $(el).parents().each(function(){ - if ($(this).data("layoutRole")) { - $P = $(this); - return false; // BREAK - } - }); - if (!$P || !$P.length) return; // INVALID - - var - pane = $P.data("layoutEdge") - , s = state[pane] - ; - - // if pane is already raised, then reset it before doing it again! - // this would happen if allowOverflow is attached to BOTH the pane and an element - if (s.cssSaved) - resetOverflow(pane); // reset previous CSS before continuing - - // if pane is raised by sliding or resizing, or its closed, then abort - if (s.isSliding || s.isResizing || s.isClosed) { - s.cssSaved = false; - return; - } - - var - newCSS = { zIndex: (_c.zIndex.pane_normal + 2) } - , curCSS = {} - , of = $P.css("overflow") - , ofX = $P.css("overflowX") - , ofY = $P.css("overflowY") - ; - // determine which, if any, overflow settings need to be changed - if (of != "visible") { - curCSS.overflow = of; - newCSS.overflow = "visible"; - } - if (ofX && !ofX.match(/visible|auto/)) { - curCSS.overflowX = ofX; - newCSS.overflowX = "visible"; - } - if (ofY && !ofY.match(/visible|auto/)) { - curCSS.overflowY = ofX; - newCSS.overflowY = "visible"; - } - - // save the current overflow settings - even if blank! - s.cssSaved = curCSS; - - // apply new CSS to raise zIndex and, if necessary, make overflow 'visible' - $P.css( newCSS ); - - // make sure the zIndex of all other panes is normal - $.each(_c.allPanes.split(","), function(i, p) { - if (p != pane) resetOverflow(p); - }); - - }; - - function resetOverflow (el) { - if (!isInitialized()) return; - if (this && this.tagName) el = this; // BOUND to element - var $P; - if (isStr(el)) - $P = $Ps[el]; - else if ($(el).data("layoutRole")) - $P = $(el); - else - $(el).parents().each(function(){ - if ($(this).data("layoutRole")) { - $P = $(this); - return false; // BREAK - } - }); - if (!$P || !$P.length) return; // INVALID - - var - pane = $P.data("layoutEdge") - , s = state[pane] - , CSS = s.cssSaved || {} - ; - // reset the zIndex - if (!s.isSliding && !s.isResizing) - $P.css("zIndex", _c.zIndex.pane_normal); - - // reset Overflow - if necessary - $P.css( CSS ); - - // clear var - s.cssSaved = false; - }; - - - /** - * Helper function to validate params received by addButton utilities - * - * Two classes are added to the element, based on the buttonClass... - * The type of button is appended to create the 2nd className: - * - ui-layout-button-pin - * - ui-layout-pane-button-toggle - * - ui-layout-pane-button-open - * - ui-layout-pane-button-close - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * @return {Array.} If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null - */ - function getBtn (selector, pane, action) { - var $E = $(selector) - , err = options.showErrorMessages; - if (!$E.length) { // element not found - if (err) alert(lang.errButton + lang.selector +": "+ selector); - } - else if (_c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified - if (err) alert(lang.errButton + lang.pane +": "+ pane); - else { // VALID - var btn = options[pane].buttonClass +"-"+ action; - $E - .addClass( btn +" "+ btn +"-"+ pane ) - .data("layoutName", options.name) // add layout identifier - even if blank! - ; - return $E; - } - return null; // INVALID - }; - - - /** - * NEW syntax for binding layout-buttons - will eventually replace addToggleBtn, addOpenBtn, etc. - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} action - * @param {string} pane - */ - function bindButton (selector, action, pane) { - switch (action.toLowerCase()) { - case "toggle": addToggleBtn(selector, pane); break; - case "open": addOpenBtn(selector, pane); break; - case "close": addCloseBtn(selector, pane); break; - case "pin": addPinBtn(selector, pane); break; - case "toggle-slide": addToggleBtn(selector, pane, true); break; - case "open-slide": addOpenBtn(selector, pane, true); break; - } - }; - - /** - * Add a custom Toggler button for a pane - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * @param {boolean=} slide true = slide-open, false = pin-open - */ - function addToggleBtn (selector, pane, slide) { - var $E = getBtn(selector, pane, "toggle"); - if ($E) - $E.click(function (evt) { - toggle(pane, !!slide); - evt.stopPropagation(); - }); - }; - - /** - * Add a custom Open button for a pane - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * @param {boolean=} slide true = slide-open, false = pin-open - */ - function addOpenBtn (selector, pane, slide) { - var $E = getBtn(selector, pane, "open"); - if ($E) - $E - .attr("title", lang.Open) - .click(function (evt) { - open(pane, !!slide); - evt.stopPropagation(); - }) - ; - }; - - /** - * Add a custom Close button for a pane - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - */ - function addCloseBtn (selector, pane) { - var $E = getBtn(selector, pane, "close"); - if ($E) - $E - .attr("title", lang.Close) - .click(function (evt) { - close(pane); - evt.stopPropagation(); - }) - ; - }; - - /** - * addPinBtn - * - * Add a custom Pin button for a pane - * - * Four classes are added to the element, based on the paneClass for the associated pane... - * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin: - * - ui-layout-pane-pin - * - ui-layout-pane-west-pin - * - ui-layout-pane-pin-up - * - ui-layout-pane-west-pin-up - * - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the pin is for: 'north', 'south', etc. - */ - function addPinBtn (selector, pane) { - var $E = getBtn(selector, pane, "pin"); - if ($E) { - var s = state[pane]; - $E.click(function (evt) { - setPinState($(this), pane, (s.isSliding || s.isClosed)); - if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open - else close( pane ); // slide-closed - evt.stopPropagation(); - }); - // add up/down pin attributes and classes - setPinState($E, pane, (!s.isClosed && !s.isSliding)); - // add this pin to the pane data so we can 'sync it' automatically - // PANE.pins key is an array so we can store multiple pins for each pane - _c[pane].pins.push( selector ); // just save the selector string - } - }; - - /** - * INTERNAL function to sync 'pin buttons' when pane is opened or closed - * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes - * - * @see open(), close() - * @param {string} pane These are the params returned to callbacks by layout() - * @param {boolean} doPin True means set the pin 'down', False means 'up' - */ - function syncPinBtns (pane, doPin) { - $.each(_c[pane].pins, function (i, selector) { - setPinState($(selector), pane, doPin); - }); - }; - - /** - * Change the class of the pin button to make it look 'up' or 'down' - * - * @see addPinBtn(), syncPinBtns() - * @param {Array.} $Pin The pin-span element in a jQuery wrapper - * @param {string} pane These are the params returned to callbacks by layout() - * @param {boolean} doPin true = set the pin 'down', false = set it 'up' - */ - function setPinState ($Pin, pane, doPin) { - var updown = $Pin.attr("pin"); - if (updown && doPin == (updown=="down")) return; // already in correct state - var - pin = options[pane].buttonClass +"-pin" - , side = pin +"-"+ pane - , UP = pin +"-up "+ side +"-up" - , DN = pin +"-down "+side +"-down" - ; - $Pin - .attr("pin", doPin ? "down" : "up") // logic - .attr("title", doPin ? lang.Unpin : lang.Pin) - .removeClass( doPin ? UP : DN ) - .addClass( doPin ? DN : UP ) - ; - }; - - - /* - * LAYOUT STATE MANAGEMENT - * - * @example .layout({ cookie: { name: "myLayout", keys: "west.isClosed,east.isClosed" } }) - * @example .layout({ cookie__name: "myLayout", cookie__keys: "west.isClosed,east.isClosed" }) - * @example myLayout.getState( "west.isClosed,north.size,south.isHidden" ); - * @example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} ); - * @example myLayout.deleteCookie(); - * @example myLayout.loadCookie(); - * @example var hSaved = myLayout.state.cookie; - */ - - function isCookiesEnabled () { - // TODO: is the cookieEnabled property common enough to be useful??? - return (navigator.cookieEnabled != 0); - }; - - /** - * Read & return data from the cookie - as JSON - * - * @param {Object=} opts - */ - function getCookie (opts) { - var - o = $.extend( {}, options.cookie, opts || {} ) - , name = o.name || options.name || "Layout" - , c = document.cookie - , cs = c ? c.split(';') : [] - , pair // loop var - ; - for (var i=0, n=cs.length; i < n; i++) { - pair = $.trim(cs[i]).split('='); // name=value pair - if (pair[0] == name) // found the layout cookie - // convert cookie string back to a hash - return decodeJSON( decodeURIComponent(pair[1]) ); - } - return ""; - }; - - /** - * Get the current layout state and save it to a cookie - * - * @param {(string|Array)=} keys - * @param {Object=} opts - */ - function saveCookie (keys, opts) { - var - o = $.extend( {}, options.cookie, opts || {} ) - , name = o.name || options.name || "Layout" - , params = '' - , date = '' - , clear = false - ; - if (o.expires.toUTCString) - date = o.expires; - else if (typeof o.expires == 'number') { - date = new Date(); - if (o.expires > 0) - date.setDate(date.getDate() + o.expires); - else { - date.setYear(1970); - clear = true; - } - } - if (date) params += ';expires='+ date.toUTCString(); - if (o.path) params += ';path='+ o.path; - if (o.domain) params += ';domain='+ o.domain; - if (o.secure) params += ';secure'; - - if (clear) { - state.cookie = {}; // clear data - document.cookie = name +'='+ params; // expire the cookie - } - else { - state.cookie = getState(keys || o.keys); // read current panes-state - document.cookie = name +'='+ encodeURIComponent( encodeJSON(state.cookie) ) + params; // write cookie - } - - return $.extend({}, state.cookie); // return COPY of state.cookie - }; - - /** - * Remove the state cookie - */ - function deleteCookie () { - saveCookie('', { expires: -1 }); - }; - - /** - * Get data from the cookie and USE IT to loadState - * - * @param {Object=} opts - */ - function loadCookie (opts) { - var o = getCookie(opts); // READ the cookie - if (o) { - state.cookie = $.extend({}, o); // SET state.cookie - loadState(o); // LOAD the retrieved state - } - return o; - }; - - /** - * Update layout options from the cookie, if one exists - * - * @param {Object=} opts - * @param {boolean=} animate - */ - function loadState (opts, animate) { - opts = _transformData(opts); - $.extend( true, options, opts ); // update layout options - // if layout has already been initialized, then UPDATE layout state - if (state.initialized) { - var pane, o, s, h, c, a = !animate; - $.each(_c.allPanes.split(","), function (idx, pane) { - o = opts[ pane ]; - if (typeof o != 'object') return; // no key, continue - s = o.size; - c = o.initClosed; - h = o.initHidden; - if (s > 0 || s=="auto") sizePane(pane, s); - if (h === true) hide(pane, a); - else if (c === false) open(pane, false, a ); - else if (c === true) close(pane, false, a); - else if (h === false) show(pane, false, a); - }); - } - }; - - /** - * Get the *current layout state* and return it as a hash - * - * @param {(string|Array)=} keys - */ - function getState (keys) { - var - data = {} - , alt = { isClosed: 'initClosed', isHidden: 'initHidden' } - , pair, pane, key, val - ; - if (!keys) keys = options.cookie.keys; // if called by user - if ($.isArray(keys)) keys = keys.join(","); - // convert keys to an array and change delimiters from '__' to '.' - keys = keys.replace(/__/g, ".").split(','); - // loop keys and create a data hash - for (var i=0,n=keys.length; i < n; i++) { - pair = keys[i].split("."); - pane = pair[0]; - key = pair[1]; - if (_c.allPanes.indexOf(pane) < 0) continue; // bad pane! - val = state[ pane ][ key ]; - if (val == undefined) continue; - if (key=="isClosed" && state[pane]["isSliding"]) - val = true; // if sliding, then *really* isClosed - ( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val; - } - return data; - }; - - /** - * Stringify a JSON hash so can save in a cookie or db-field - */ - function encodeJSON (JSON) { - return parse( JSON ); - function parse (h) { - var D=[], i=0, k, v, t; // k = key, v = value - for (k in h) { - v = h[k]; - t = typeof v; - if (t == 'string') // STRING - add quotes - v = '"'+ v +'"'; - else if (t == 'object') // SUB-KEY - recurse into it - v = parse(v); - D[i++] = '"'+ k +'":'+ v; - } - return "{"+ D.join(",") +"}"; - }; - }; - - /** - * Convert stringified JSON back to a hash object - */ - function decodeJSON (str) { - try { return window["eval"]("("+ str +")") || {}; } - catch (e) { return {}; } - }; - - -/* - * ##################### - * CREATE/RETURN LAYOUT - * ##################### - */ - - // validate that container exists - var $N = $(this).eq(0); // FIRST matching Container element - if (!$N.length) { - if (options.showErrorMessages) - alert( lang.errContainerMissing ); - return null; - }; - - // Users retreive Instance of a layout with: $N.layout() OR $N.data("layout") - // return the Instance-pointer if layout has already been initialized - if ($N.data("layoutContainer") && $N.data("layout")) - return $N.data("layout"); // cached pointer - - // init global vars - var - $Ps = {} // Panes x5 - set in initPanes() - , $Cs = {} // Content x5 - set in initPanes() - , $Rs = {} // Resizers x4 - set in initHandles() - , $Ts = {} // Togglers x4 - set in initHandles() - // aliases for code brevity - , sC = state.container // alias for easy access to 'container dimensions' - , sID = state.id // alias for unique layout ID/namespace - eg: "layout435" - ; - - // create Instance object to expose data & option Properties, and primary action Methods - var Instance = { - options: options // property - options hash - , state: state // property - dimensions hash - , container: $N // property - object pointers for layout container - , panes: $Ps // property - object pointers for ALL Panes: panes.north, panes.center - , contents: $Cs // property - object pointers for ALL Content: content.north, content.center - , resizers: $Rs // property - object pointers for ALL Resizers, eg: resizers.north - , togglers: $Ts // property - object pointers for ALL Togglers, eg: togglers.north - , toggle: toggle // method - pass a 'pane' ("north", "west", etc) - , hide: hide // method - ditto - , show: show // method - ditto - , open: open // method - ditto - , close: close // method - ditto - , slideOpen: slideOpen // method - ditto - , slideClose: slideClose // method - ditto - , slideToggle: slideToggle // method - ditto - , initContent: initContent // method - ditto - , sizeContent: sizeContent // method - ditto - , sizePane: manualSizePane // method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto' - , swapPanes: swapPanes // method - pass TWO 'panes' - will swap them - , resizeAll: resizeAll // method - no parameters - , initPanes: isInitialized // method - no parameters - , destroy: destroy // method - no parameters - , addPane: addPane // method - pass a 'pane' - , removePane: removePane // method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem - , setSizeLimits: setSizeLimits // method - pass a 'pane' - update state min/max data - , bindButton: bindButton // utility - pass element selector, 'action' and 'pane' (E, "toggle", "west") - , addToggleBtn: addToggleBtn // utility - pass element selector and 'pane' (E, "west") - , addOpenBtn: addOpenBtn // utility - ditto - , addCloseBtn: addCloseBtn // utility - ditto - , addPinBtn: addPinBtn // utility - ditto - , allowOverflow: allowOverflow // utility - pass calling element (this) - , resetOverflow: resetOverflow // utility - ditto - , encodeJSON: encodeJSON // method - pass a JSON object - , decodeJSON: decodeJSON // method - pass a string of encoded JSON - , getState: getState // method - returns hash of current layout-state - , getCookie: getCookie // method - update options from cookie - returns hash of cookie data - , saveCookie: saveCookie // method - optionally pass keys-list and cookie-options (hash) - , deleteCookie: deleteCookie // method - , loadCookie: loadCookie // method - update options from cookie - returns hash of cookie data - , loadState: loadState // method - pass a hash of state to use to update options - , cssWidth: cssW // utility - pass element and target outerWidth - , cssHeight: cssH // utility - ditto - , enableClosable: enableClosable - , disableClosable: disableClosable - , enableSlidable: enableSlidable - , disableSlidable: disableSlidable - , enableResizable: enableResizable - , disableResizable: disableResizable - }; - - // create the border layout NOW - if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation - return null; - else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later - return Instance; // return the Instance object - -} +/** + * @preserve + * jquery.layout 1.3.0 - Release Candidate 30.74 + * $Date: 2012-10-28 08:00:00 (Sun, 28 Oct 2012) $ + * $Rev: 303007 $ + * + * Copyright (c) 2012 + * Fabrizio Balliano (http://www.fabrizioballiano.net) + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.74 + * + * Docs: http://layout.jquery-dev.net/documentation.html + * Tips: http://layout.jquery-dev.net/tips.html + * Help: http://groups.google.com/group/jquery-ui-layout + */ + +/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html + * {!Object} non-nullable type (never NULL) + * {?string} nullable type (sometimes NULL) - default for {Object} + * {number=} optional parameter + * {*} ALL types + */ + +// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars + +;(function ($) { + +// alias Math methods - used a lot! +var min = Math.min +, max = Math.max +, round = Math.floor + +, isStr = function (v) { return $.type(v) === "string"; } + + /** + * @param {!Object} Instance + * @param {Array.} a_fn + */ +, runPluginCallbacks = function (Instance, a_fn) { + if ($.isArray(a_fn)) + for (var i=0, c=a_fn.length; i').appendTo("body"); + var d = { width: $c.css("width") - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight }; + $c.remove(); + window.scrollbarWidth = d.width; + window.scrollbarHeight = d.height; + return dim.match(/^(width|height)$/) ? d[dim] : d; + } + + + /** + * Returns hash container 'display' and 'visibility' + * + * @see $.swap() - swaps CSS, runs callback, resets CSS + * @param {!Object} $E jQuery element + * @param {boolean=} [force=false] Run even if display != none + * @return {!Object} Returns current style props, if applicable + */ +, showInvisibly: function ($E, force) { + if ($E && $E.length && (force || $E.css("display") === "none")) { // only if not *already hidden* + var s = $E[0].style + // save ONLY the 'style' props because that is what we must restore + , CSS = { display: s.display || '', visibility: s.visibility || '' }; + // show element 'invisibly' so can be measured + $E.css({ display: "block", visibility: "hidden" }); + return CSS; + } + return {}; + } + + /** + * Returns data for setting size of an element (container or a pane). + * + * @see _create(), onWindowResize() for container, plus others for pane + * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc + */ +, getElementDimensions: function ($E, inset) { + var + // dimensions hash - start with current data IF passed + d = { css: {}, inset: {} } + , x = d.css // CSS hash + , i = { bottom: 0 } // TEMP insets (bottom = complier hack) + , N = $.layout.cssNum + , off = $E.offset() + , b, p, ei // TEMP border, padding + ; + d.offsetLeft = off.left; + d.offsetTop = off.top; + + if (!inset) inset = {}; // simplify logic below + + $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge + b = x["border" + e] = $.layout.borderWidth($E, e); + p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e); + ei = e.toLowerCase(); + d.inset[ei] = inset[ei] >= 0 ? inset[ei] : p; // any missing insetX value = paddingX + i[ei] = d.inset[ei] + b; // total offset of content from outer side + }); + + x.width = $E.css("width"); + x.height = $E.height(); + x.top = N($E,"top",true); + x.bottom = N($E,"bottom",true); + x.left = N($E,"left",true); + x.right = N($E,"right",true); + + d.outerWidth = $E.outerWidth(); + d.outerHeight = $E.outerHeight(); + // calc the TRUE inner-dimensions, even in quirks-mode! + d.innerWidth = max(0, d.outerWidth - i.left - i.right); + d.innerHeight = max(0, d.outerHeight - i.top - i.bottom); + // layoutWidth/Height is used in calcs for manual resizing + // layoutW/H only differs from innerW/H when in quirks-mode - then is like outerW/H + d.layoutWidth = $E.innerWidth(); + d.layoutHeight = $E.innerHeight(); + + //if ($E.prop('tagName') === 'BODY') { debugData( d, $E.prop('tagName') ); } // DEBUG + + //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0; + + return d; + } + +, getElementStyles: function ($E, list) { + var + CSS = {} + , style = $E[0].style + , props = list.split(",") + , sides = "Top,Bottom,Left,Right".split(",") + , attrs = "Color,Style,Width".split(",") + , p, s, a, i, j, k + ; + for (i=0; i < props.length; i++) { + p = props[i]; + if (p.match(/(border|padding|margin)$/)) + for (j=0; j < 4; j++) { + s = sides[j]; + if (p === "border") + for (k=0; k < 3; k++) { + a = attrs[k]; + CSS[p+s+a] = style[p+s+a]; + } + else + CSS[p+s] = style[p+s]; + } + else + CSS[p] = style[p]; + }; + return CSS + } + + /** + * Return the innerWidth for the current browser/doctype + * + * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {number=} outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized + * @return {number} Returns the innerWidth of the elem by subtracting padding and borders + */ +, cssWidth: function ($E, outerWidth) { + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed + if (outerWidth <= 0) return 0; + + if (!$.layout.browser.boxModel) return outerWidth; + + // strip border and padding from outerWidth to get CSS Width + var b = $.layout.borderWidth + , n = $.layout.cssNum + , W = outerWidth + - b($E, "Left") + - b($E, "Right") + - n($E, "paddingLeft") + - n($E, "paddingRight"); + + return max(0,W); + } + + /** + * Return the innerHeight for the current browser/doctype + * + * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {number=} outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized + * @return {number} Returns the innerHeight of the elem by subtracting padding and borders + */ +, cssHeight: function ($E, outerHeight) { + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed + if (outerHeight <= 0) return 0; + + if (!$.layout.browser.boxModel) return outerHeight; + + // strip border and padding from outerHeight to get CSS Height + var b = $.layout.borderWidth + , n = $.layout.cssNum + , H = outerHeight + - b($E, "Top") + - b($E, "Bottom") + - n($E, "paddingTop") + - n($E, "paddingBottom"); + + return max(0,H); + } + + /** + * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist + * + * @see Called by many methods + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {string} prop The name of the CSS property, eg: top, width, etc. + * @param {boolean=} [allowAuto=false] true = return 'auto' if that is value; false = return 0 + * @return {(string|number)} Usually used to get an integer value for position (top, left) or size (height, width) + */ +, cssNum: function ($E, prop, allowAuto) { + if (!$E.jquery) $E = $($E); + var CSS = $.layout.showInvisibly($E) + , p = $.css($E[0], prop, true) + , v = allowAuto && p=="auto" ? p : Math.round(parseFloat(p) || 0); + $E.css( CSS ); // RESET + return v; + } + +, borderWidth: function (el, side) { + if (el.jquery) el = el[0]; + var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left + return $.css(el, b+"Style", true) === "none" ? 0 : Math.round(parseFloat($.css(el, b+"Width", true)) || 0); + } + + /** + * Mouse-tracking utility - FUTURE REFERENCE + * + * init: if (!window.mouse) { + * window.mouse = { x: 0, y: 0 }; + * $(document).mousemove( $.layout.trackMouse ); + * } + * + * @param {Object} evt + * +, trackMouse: function (evt) { + window.mouse = { x: evt.clientX, y: evt.clientY }; + } + */ + + /** + * SUBROUTINE for preventPrematureSlideClose option + * + * @param {Object} evt + * @param {Object=} el + */ +, isMouseOverElem: function (evt, el) { + var + $E = $(el || this) + , d = $E.offset() + , T = d.top + , L = d.left + , R = L + $E.outerWidth() + , B = T + $E.outerHeight() + , x = evt.pageX // evt.clientX ? + , y = evt.pageY // evt.clientY ? + ; + // if X & Y are < 0, probably means is over an open SELECT + return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B)); + } + + /** + * Message/Logging Utility + * + * @example $.layout.msg("My message"); // log text + * @example $.layout.msg("My message", true); // alert text + * @example $.layout.msg({ foo: "bar" }, "Title"); // log hash-data, with custom title + * @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR- + * @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data + * + * @param {(Object|string)} info String message OR Hash/Array + * @param {(Boolean|string|Object)=} [popup=false] True means alert-box - can be skipped + * @param {(Object|string)=} [debugTitle=""] Title for Hash data - can be skipped + * @param {Object=} [debugOpts] Extra options for debug output + */ +, msg: function (info, popup, debugTitle, debugOpts) { + if ($.isPlainObject(info) && window.debugData) { + if (typeof popup === "string") { + debugOpts = debugTitle; + debugTitle = popup; + } + else if (typeof debugTitle === "object") { + debugOpts = debugTitle; + debugTitle = null; + } + var t = debugTitle || "log( )" + , o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts); + if (popup === true || o.display) + debugData( info, t, o ); + else if (window.console) + console.log(debugData( info, t, o )); + } + else if (popup) + alert(info); + else if (window.console) + console.log(info); + else { + var id = "#layoutLogger" + , $l = $(id); + if (!$l.length) + $l = createLog(); + $l.children("ul").append('
  • '+ info.replace(/\/g,">") +'
  • '); + } + + function createLog () { + var pos = $.support.fixedPosition ? 'fixed' : 'absolute' + , $e = $('
    ' + + '
    ' + + 'XLayout console.log
    ' + + '
      ' + + '
      ' + ).appendTo("body"); + $e.css('left', $(window).width() - $e.outerWidth() - 5) + if ($.ui.draggable) $e.draggable({ handle: ':first-child' }); + return $e; + }; + } + +}; + +// DEFAULT OPTIONS +$.layout.defaults = { +/* + * LAYOUT & LAYOUT-CONTAINER OPTIONS + * - none of these options are applicable to individual panes + */ + name: "" // Not required, but useful for buttons and used for the state-cookie +, containerClass: "ui-layout-container" // layout-container element +, inset: null // custom container-inset values (override padding) +, scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark) +, resizeWithWindow: true // bind thisLayout.resizeAll() to the window.resize event +, resizeWithWindowDelay: 200 // delay calling resizeAll because makes window resizing very jerky +, resizeWithWindowMaxDelay: 0 // 0 = none - force resize every XX ms while window is being resized +, maskPanesEarly: false // true = create pane-masks on resizer.mouseDown instead of waiting for resizer.dragstart +, onresizeall_start: null // CALLBACK when resizeAll() STARTS - NOT pane-specific +, onresizeall_end: null // CALLBACK when resizeAll() ENDS - NOT pane-specific +, onload_start: null // CALLBACK when Layout inits - after options initialized, but before elements +, onload_end: null // CALLBACK when Layout inits - after EVERYTHING has been initialized +, onunload_start: null // CALLBACK when Layout is destroyed OR onWindowUnload +, onunload_end: null // CALLBACK when Layout is destroyed OR onWindowUnload +, initPanes: true // false = DO NOT initialize the panes onLoad - will init later +, showErrorMessages: true // enables fatal error messages to warn developers of common errors +, showDebugMessages: false // display console-and-alert debug msgs - IF this Layout version _has_ debugging code! +// Changing this zIndex value will cause other zIndex values to automatically change +, zIndex: null // the PANE zIndex - resizers and masks will be +1 +// DO NOT CHANGE the zIndex values below unless you clearly understand their relationships +, zIndexes: { // set _default_ z-index values here... + pane_normal: 0 // normal z-index for panes + , content_mask: 1 // applied to overlays used to mask content INSIDE panes during resizing + , resizer_normal: 2 // normal z-index for resizer-bars + , pane_sliding: 100 // applied to *BOTH* the pane and its resizer when a pane is 'slid open' + , pane_animate: 1000 // applied to the pane when being animated - not applied to the resizer + , resizer_drag: 10000 // applied to the CLONED resizer-bar when being 'dragged' + } +, errors: { + pane: "pane" // description of "layout pane element" - used only in error messages + , selector: "selector" // description of "jQuery-selector" - used only in error messages + , addButtonError: "Error Adding Button \n\nInvalid " + , containerMissing: "UI Layout Initialization Error\n\nThe specified layout-container does not exist." + , centerPaneMissing: "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element." + , noContainerHeight: "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!" + , callbackError: "UI Layout Callback Error\n\nThe EVENT callback is not a valid function." + } +/* + * PANE DEFAULT SETTINGS + * - settings under the 'panes' key become the default settings for *all panes* + * - ALL pane-options can also be set specifically for each panes, which will override these 'default values' + */ +, panes: { // default options for 'all panes' - will be overridden by 'per-pane settings' + applyDemoStyles: false // NOTE: renamed from applyDefaultStyles for clarity + , closable: true // pane can open & close + , resizable: true // when open, pane can be resized + , slidable: true // when closed, pane can 'slide open' over other panes - closes on mouse-out + , initClosed: false // true = init pane as 'closed' + , initHidden: false // true = init pane as 'hidden' - no resizer-bar/spacing + // SELECTORS + //, paneSelector: "" // MUST be pane-specific - jQuery selector for pane + , contentSelector: ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane! + , contentIgnoreSelector: ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content' + , findNestedContent: false // true = $P.find(contentSelector), false = $P.children(contentSelector) + // GENERIC ROOT-CLASSES - for auto-generated classNames + , paneClass: "ui-layout-pane" // Layout Pane + , resizerClass: "ui-layout-resizer" // Resizer Bar + , togglerClass: "ui-layout-toggler" // Toggler Button + , buttonClass: "ui-layout-button" // CUSTOM Buttons - eg: '[ui-layout-button]-toggle/-open/-close/-pin' + // ELEMENT SIZE & SPACING + //, size: 100 // MUST be pane-specific -initial size of pane + , minSize: 0 // when manually resizing a pane + , maxSize: 0 // ditto, 0 = no limit + , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open' + , spacing_closed: 6 // ditto - when pane is 'closed' + , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides + , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden' + , togglerAlign_open: "center" // top/left, bottom/right, center, OR... + , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right + , togglerContent_open: "" // text or HTML to put INSIDE the toggler + , togglerContent_closed: "" // ditto + // RESIZING OPTIONS + , resizerDblClickToggle: true // + , autoResize: true // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes + , autoReopen: true // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed + , resizerDragOpacity: 1 // option for ui.draggable + //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar + , maskContents: false // true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES + , maskObjects: false // true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask + , maskZindex: null // will override zIndexes.content_mask if specified - not applicable to iframe-panes + , resizingGrid: false // grid size that the resizers will snap-to during resizing, eg: [20,20] + , livePaneResizing: false // true = LIVE Resizing as resizer is dragged + , liveContentResizing: false // true = re-measure header/footer heights as resizer is dragged + , liveResizingTolerance: 1 // how many px change before pane resizes, to control performance + // SLIDING OPTIONS + , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding' + , slideTrigger_open: "click" // click, dblclick, mouseenter + , slideTrigger_close: "mouseleave"// click, mouseleave + , slideDelay_open: 300 // applies only for mouseenter event - 0 = instant open + , slideDelay_close: 300 // applies only for mouseleave event (300ms is the minimum!) + , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show? + , preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening + , preventPrematureSlideClose: false // handle incorrect mouseleave trigger, like when over a SELECT-list in IE + // PANE-SPECIFIC TIPS & MESSAGES + , tips: { + Open: "Open" // eg: "Open Pane" + , Close: "Close" + , Resize: "Resize" + , Slide: "Slide Open" + , Pin: "Pin" + , Unpin: "Un-Pin" + , noRoomToOpen: "Not enough room to show this panel." // alert if user tries to open a pane that cannot + , minSizeWarning: "Panel has reached its minimum size" // displays in browser statusbar + , maxSizeWarning: "Panel has reached its maximum size" // ditto + } + // HOT-KEYS & MISC + , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver + , enableCursorHotkey: true // enabled 'cursor' hotkeys + //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character + , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT' + // PANE ANIMATION + // NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed + , fxName: "slide" // ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size' + , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration + , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 } + , fxOpacityFix: true // tries to fix opacity in IE to restore anti-aliasing after animation + , animatePaneSizing: false // true = animate resizing after dragging resizer-bar OR sizePane() is called + /* NOTE: Action-specific FX options are auto-generated from the options above if not specifically set: + fxName_open: "slide" // 'Open' pane animation + fnName_close: "slide" // 'Close' pane animation + fxName_size: "slide" // 'Size' pane animation - when animatePaneSizing = true + fxSpeed_open: null + fxSpeed_close: null + fxSpeed_size: null + fxSettings_open: {} + fxSettings_close: {} + fxSettings_size: {} + */ + // CHILD/NESTED LAYOUTS + , children: null // Layout-options for nested/child layout - even {} is valid as options + , containerSelector: '' // if child is NOT 'directly nested', a selector to find it/them (can have more than one child layout!) + , initChildren: true // true = child layout will be created as soon as _this_ layout completes initialization + , destroyChildren: true // true = destroy child-layout if this pane is destroyed + , resizeChildren: true // true = trigger child-layout.resizeAll() when this pane is resized + // EVENT TRIGGERING + , triggerEventsOnLoad: false // true = trigger onopen OR onclose callbacks when layout initializes + , triggerEventsDuringLiveResize: true // true = trigger onresize callback REPEATEDLY if livePaneResizing==true + // PANE CALLBACKS + , onshow_start: null // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start + , onshow_end: null // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end + , onhide_start: null // CALLBACK when pane STARTS to Close - BEFORE onclose_start + , onhide_end: null // CALLBACK when pane ENDS being Closed - AFTER onclose_end + , onopen_start: null // CALLBACK when pane STARTS to Open + , onopen_end: null // CALLBACK when pane ENDS being Opened + , onclose_start: null // CALLBACK when pane STARTS to Close + , onclose_end: null // CALLBACK when pane ENDS being Closed + , onresize_start: null // CALLBACK when pane STARTS being Resized ***FOR ANY REASON*** + , onresize_end: null // CALLBACK when pane ENDS being Resized ***FOR ANY REASON*** + , onsizecontent_start: null // CALLBACK when sizing of content-element STARTS + , onsizecontent_end: null // CALLBACK when sizing of content-element ENDS + , onswap_start: null // CALLBACK when pane STARTS to Swap + , onswap_end: null // CALLBACK when pane ENDS being Swapped + , ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized + , ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized + } +/* + * PANE-SPECIFIC SETTINGS + * - options listed below MUST be specified per-pane - they CANNOT be set under 'panes' + * - all options under the 'panes' key can also be set specifically for any pane + * - most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane + */ +, north: { + paneSelector: ".ui-layout-north" + , size: "auto" // eg: "auto", "30%", .30, 200 + , resizerCursor: "n-resize" // custom = url(myCursor.cur) + , customHotkey: "" // EITHER a charCode (43) OR a character ("o") + } +, south: { + paneSelector: ".ui-layout-south" + , size: "auto" + , resizerCursor: "s-resize" + , customHotkey: "" + } +, east: { + paneSelector: ".ui-layout-east" + , size: 200 + , resizerCursor: "e-resize" + , customHotkey: "" + } +, west: { + paneSelector: ".ui-layout-west" + , size: 200 + , resizerCursor: "w-resize" + , customHotkey: "" + } +, center: { + paneSelector: ".ui-layout-center" + , minWidth: 0 + , minHeight: 0 + } +}; + +$.layout.optionsMap = { + // layout/global options - NOT pane-options + layout: ("name,instanceKey,stateManagement,effects,inset,zIndexes,errors," + + "zIndex,scrollToBookmarkOnLoad,showErrorMessages,maskPanesEarly," + + "outset,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay," + + "onresizeall,onresizeall_start,onresizeall_end,onload,onunload").split(",") +// borderPanes: [ ALL options that are NOT specified as 'layout' ] + // default.panes options that apply to the center-pane (most options apply _only_ to border-panes) +, center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad," + + "showOverflowOnHover,maskContents,maskObjects,liveContentResizing," + + "containerSelector,children,initChildren,resizeChildren,destroyChildren," + + "onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",") + // options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key +, noDefault: ("paneSelector,resizerCursor,customHotkey").split(",") +}; + +/** + * Processes options passed in converts flat-format data into subkey (JSON) format + * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName + * Plugins may also call this method so they can transform their own data + * + * @param {!Object} hash Data/options passed by user - may be a single level or nested levels + * @param {boolean=} [addKeys=false] Should the primary layout.options keys be added if they do not exist? + * @return {Object} Returns hash of minWidth & minHeight + */ +$.layout.transformData = function (hash, addKeys) { + var json = addKeys ? { panes: {}, center: {} } : {} // init return object + , branch, optKey, keys, key, val, i, c; + + if (typeof hash !== "object") return json; // no options passed + + // convert all 'flat-keys' to 'sub-key' format + for (optKey in hash) { + branch = json; + val = hash[ optKey ]; + keys = optKey.split("__"); // eg: west__size or north__fxSettings__duration + c = keys.length - 1; + // convert underscore-delimited to subkeys + for (i=0; i <= c; i++) { + key = keys[i]; + if (i === c) { // last key = value + if ($.isPlainObject( val )) + branch[key] = $.layout.transformData( val ); // RECURSE + else + branch[key] = val; + } + else { + if (!branch[key]) + branch[key] = {}; // create the subkey + // recurse to sub-key for next loop - if not done + branch = branch[key]; + } + } + } + return json; +}; + +// INTERNAL CONFIG DATA - DO NOT CHANGE THIS! +$.layout.backwardCompatibility = { + // data used by renameOldOptions() + map: { + // OLD Option Name: NEW Option Name + applyDefaultStyles: "applyDemoStyles" + // CHILD/NESTED LAYOUTS + , childOptions: "children" + , initChildLayout: "initChildren" + , destroyChildLayout: "destroyChildren" + , resizeChildLayout: "resizeChildren" + , resizeNestedLayout: "resizeChildren" + // MISC Options + , resizeWhileDragging: "livePaneResizing" + , resizeContentWhileDragging: "liveContentResizing" + , triggerEventsWhileDragging: "triggerEventsDuringLiveResize" + , maskIframesOnResize: "maskContents" + // STATE MANAGEMENT + , useStateCookie: "stateManagement.enabled" + , "cookie.autoLoad": "stateManagement.autoLoad" + , "cookie.autoSave": "stateManagement.autoSave" + , "cookie.keys": "stateManagement.stateKeys" + , "cookie.name": "stateManagement.cookie.name" + , "cookie.domain": "stateManagement.cookie.domain" + , "cookie.path": "stateManagement.cookie.path" + , "cookie.expires": "stateManagement.cookie.expires" + , "cookie.secure": "stateManagement.cookie.secure" + // OLD Language options + , noRoomToOpenTip: "tips.noRoomToOpen" + , togglerTip_open: "tips.Close" // open = Close + , togglerTip_closed: "tips.Open" // closed = Open + , resizerTip: "tips.Resize" + , sliderTip: "tips.Slide" + } + +/** +* @param {Object} opts +*/ +, renameOptions: function (opts) { + var map = $.layout.backwardCompatibility.map + , oldData, newData, value + ; + for (var itemPath in map) { + oldData = getBranch( itemPath ); + value = oldData.branch[ oldData.key ]; + if (value !== undefined) { + newData = getBranch( map[itemPath], true ); + newData.branch[ newData.key ] = value; + delete oldData.branch[ oldData.key ]; + } + } + + /** + * @param {string} path + * @param {boolean=} [create=false] Create path if does not exist + */ + function getBranch (path, create) { + var a = path.split(".") // split keys into array + , c = a.length - 1 + , D = { branch: opts, key: a[c] } // init branch at top & set key (last item) + , i = 0, k, undef; + for (; i 0) { + if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) { + $E.show().data('autoHidden', false); + if (!browser.mozilla) // FireFox refreshes iframes - IE does not + // make hidden, then visible to 'refresh' display after animation + $E.css(_c.hidden).css(_c.visible); + } + } + else if (autoHide && !$E.data('autoHidden')) + $E.hide().data('autoHidden', true); + } + + /** + * @param {(string|!Object)} el + * @param {number=} outerHeight + * @param {boolean=} [autoHide=false] + */ +, setOuterHeight = function (el, outerHeight, autoHide) { + var $E = el, h; + if (isStr(el)) $E = $Ps[el]; // west + else if (!el.jquery) $E = $(el); + h = cssH($E, outerHeight); + $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent + if (h > 0 && $E.innerWidth() > 0) { + if (autoHide && $E.data('autoHidden')) { + $E.show().data('autoHidden', false); + if (!browser.mozilla) // FireFox refreshes iframes - IE does not + $E.css(_c.hidden).css(_c.visible); + } + } + else if (autoHide && !$E.data('autoHidden')) + $E.hide().data('autoHidden', true); + } + + + /** + * Converts any 'size' params to a pixel/integer size, if not already + * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated + * + /** + * @param {string} pane + * @param {(string|number)=} size + * @param {string=} [dir] + * @return {number} + */ +, _parseSize = function (pane, size, dir) { + if (!dir) dir = _c[pane].dir; + + if (isStr(size) && size.match(/%/)) + size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal + + if (size === 0) + return 0; + else if (size >= 1) + return parseInt(size, 10); + + var o = options, avail = 0; + if (dir=="horz") // north or south or center.minHeight + avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0); + else if (dir=="vert") // east or west or center.minWidth + avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0); + + if (size === -1) // -1 == 100% + return avail; + else if (size > 0) // percentage, eg: .25 + return round(avail * size); + else if (pane=="center") + return 0; + else { // size < 0 || size=='auto' || size==Missing || size==Invalid + // auto-size the pane + var dim = (dir === "horz" ? "height" : "width") + , $P = $Ps[pane] + , $C = dim === 'height' ? $Cs[pane] : false + , vis = $.layout.showInvisibly($P) // show pane invisibly if hidden + , szP = $P.css(dim) // SAVE current pane size + , szC = $C ? $C.css(dim) : 0 // SAVE current content size + ; + $P.css(dim, "auto"); + if ($C) $C.css(dim, "auto"); + size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE + $P.css(dim, szP).css(vis); // RESET size & visibility + if ($C) $C.css(dim, szC); + return size; + } + } + + /** + * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added + * + * @param {(string|!Object)} pane + * @param {boolean=} [inclSpace=false] + * @return {number} Returns EITHER Width for east/west panes OR Height for north/south panes + */ +, getPaneSize = function (pane, inclSpace) { + var + $P = $Ps[pane] + , o = options[pane] + , s = state[pane] + , oSp = (inclSpace ? o.spacing_open : 0) + , cSp = (inclSpace ? o.spacing_closed : 0) + ; + if (!$P || s.isHidden) + return 0; + else if (s.isClosed || (s.isSliding && inclSpace)) + return cSp; + else if (_c[pane].dir === "horz") + return $P.outerHeight() + oSp; + else // dir === "vert" + return $P.outerWidth() + oSp; + } + + /** + * Calculate min/max pane dimensions and limits for resizing + * + * @param {string} pane + * @param {boolean=} [slide=false] + */ +, setSizeLimits = function (pane, slide) { + if (!isInitialized()) return; + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , dir = c.dir + , type = c.sizeType.toLowerCase() + , isSliding = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param + , $P = $Ps[pane] + , paneSpacing = o.spacing_open + // measure the pane on the *opposite side* from this pane + , altPane = _c.oppositeEdge[pane] + , altS = state[altPane] + , $altP = $Ps[altPane] + , altPaneSize = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth())) + , altPaneSpacing = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0) + // limitSize prevents this pane from 'overlapping' opposite pane + , containerSize = (dir=="horz" ? sC.innerHeight : sC.innerWidth) + , minCenterDims = cssMinDims("center") + , minCenterSize = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth) + // if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them + , limitSize = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing))) + , minSize = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize ) + , maxSize = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize ) + , r = s.resizerPosition = {} // used to set resizing limits + , top = sC.inset.top + , left = sC.inset.left + , W = sC.innerWidth + , H = sC.innerHeight + , rW = o.spacing_open // subtract resizer-width to get top/left position for south/east + ; + switch (pane) { + case "north": r.min = top + minSize; + r.max = top + maxSize; + break; + case "west": r.min = left + minSize; + r.max = left + maxSize; + break; + case "south": r.min = top + H - maxSize - rW; + r.max = top + H - minSize - rW; + break; + case "east": r.min = left + W - maxSize - rW; + r.max = left + W - minSize - rW; + break; + }; + } + + /** + * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes + * + * @return JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height + */ +, calcNewCenterPaneDims = function () { + var d = { + top: getPaneSize("north", true) // true = include 'spacing' value for pane + , bottom: getPaneSize("south", true) + , left: getPaneSize("west", true) + , right: getPaneSize("east", true) + , width: 0 + , height: 0 + }; + + // NOTE: sC = state.container + // calc center-pane outer dimensions + d.width = sC.innerWidth - d.left - d.right; // outerWidth + d.height = sC.innerHeight - d.bottom - d.top; // outerHeight + // add the 'container border/padding' to get final positions relative to the container + d.top += sC.inset.top; + d.bottom += sC.inset.bottom; + d.left += sC.inset.left; + d.right += sC.inset.right; + + return d; + } + + + /** + * @param {!Object} el + * @param {boolean=} [allStates=false] + */ +, getHoverClasses = function (el, allStates) { + var + $El = $(el) + , type = $El.data("layoutRole") + , pane = $El.data("layoutEdge") + , o = options[pane] + , root = o[type +"Class"] + , _pane = "-"+ pane // eg: "-west" + , _open = "-open" + , _closed = "-closed" + , _slide = "-sliding" + , _hover = "-hover " // NOTE the trailing space + , _state = $El.hasClass(root+_closed) ? _closed : _open + , _alt = _state === _closed ? _open : _closed + , classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover) + ; + if (allStates) // when 'removing' classes, also remove alternate-state classes + classes += (root+_alt+_hover) + (root+_pane+_alt+_hover); + + if (type=="resizer" && $El.hasClass(root+_slide)) + classes += (root+_slide+_hover) + (root+_pane+_slide+_hover); + + return $.trim(classes); + } +, addHover = function (evt, el) { + var $E = $(el || this); + if (evt && $E.data("layoutRole") === "toggler") + evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar + $E.addClass( getHoverClasses($E) ); + } +, removeHover = function (evt, el) { + var $E = $(el || this); + $E.removeClass( getHoverClasses($E, true) ); + } + +, onResizerEnter = function (evt) { // ALSO called by toggler.mouseenter + var pane = $(this).data("layoutEdge") + , s = state[pane] + ; + // ignore closed-panes and mouse moving back & forth over resizer! + // also ignore if ANY pane is currently resizing + if ( s.isClosed || s.isResizing || state.paneResizing ) return; + + if ($.fn.disableSelection) + $("body").disableSelection(); + if (options.maskPanesEarly) + showMasks( pane, { resizing: true }); + } +, onResizerLeave = function (evt, el) { + var e = el || this // el is only passed when called by the timer + , pane = $(e).data("layoutEdge") + , name = pane +"ResizerLeave" + ; + timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set + timer.clear(name); // cancel enableSelection timer - may re/set below + // this method calls itself on a timer because it needs to allow + // enough time for dragging to kick-in and set the isResizing flag + // dragging has a 100ms delay set, so this delay must be >100 + if (!el) // 1st call - mouseleave event + timer.set(name, function(){ onResizerLeave(evt, e); }, 200); + // if user is resizing, then dragStop will enableSelection(), so can skip it here + else if ( !state.paneResizing ) { // 2nd call - by timer + if ($.fn.enableSelection) + $("body").enableSelection(); + if (options.maskPanesEarly) + hideMasks(); + } + } + +/* + * ########################### + * INITIALIZATION METHODS + * ########################### + */ + + /** + * Initialize the layout - called automatically whenever an instance of layout is created + * + * @see none - triggered onInit + * @return mixed true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort + */ +, _create = function () { + // initialize config/options + initOptions(); + var o = options + , s = state; + + // TEMP state so isInitialized returns true during init process + s.creatingLayout = true; + + // init plugins for this layout, if there are any (eg: stateManagement) + runPluginCallbacks( Instance, $.layout.onCreate ); + + // options & state have been initialized, so now run beforeLoad callback + // onload will CANCEL layout creation if it returns false + if (false === _runCallbacks("onload_start")) + return 'cancel'; + + // initialize the container element + _initContainer(); + + // bind hotkey function - keyDown - if required + initHotkeys(); + + // bind window.onunload + $(window).bind("unload."+ sID, unload); + + // init plugins for this layout, if there are any (eg: customButtons) + runPluginCallbacks( Instance, $.layout.onLoad ); + + // if layout elements are hidden, then layout WILL NOT complete initialization! + // initLayoutElements will set initialized=true and run the onload callback IF successful + if (o.initPanes) _initLayoutElements(); + + delete s.creatingLayout; + + return state.initialized; + } + + /** + * Initialize the layout IF not already + * + * @see All methods in Instance run this test + * @return boolean true = layoutElements have been initialized | false = panes are not initialized (yet) + */ +, isInitialized = function () { + if (state.initialized || state.creatingLayout) return true; // already initialized + else return _initLayoutElements(); // try to init panes NOW + } + + /** + * Initialize the layout - called automatically whenever an instance of layout is created + * + * @see _create() & isInitialized + * @param {boolean=} [retry=false] // indicates this is a 2nd try + * @return An object pointer to the instance created + */ +, _initLayoutElements = function (retry) { + // initialize config/options + var o = options; + // CANNOT init panes inside a hidden container! + if (!$N.is(":visible")) { + // handle Chrome bug where popup window 'has no height' + // if layout is BODY element, try again in 50ms + // SEE: http://layout.jquery-dev.net/samples/test_popup_window.html + if ( !retry && browser.webkit && $N[0].tagName === "BODY" ) + setTimeout(function(){ _initLayoutElements(true); }, 50); + return false; + } + + // a center pane is required, so make sure it exists + if (!getPane("center").length) { + return _log( o.errors.centerPaneMissing ); + } + + // TEMP state so isInitialized returns true during init process + state.creatingLayout = true; + + // update Container dims + $.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values + + // initialize all layout elements + initPanes(); // size & position panes - calls initHandles() - which calls initResizable() + + if (o.scrollToBookmarkOnLoad) { + var l = self.location; + if (l.hash) l.replace( l.hash ); // scrollTo Bookmark + } + + // check to see if this layout 'nested' inside a pane + if (Instance.hasParentLayout) + o.resizeWithWindow = false; + // bind resizeAll() for 'this layout instance' to window.resize event + else if (o.resizeWithWindow) + $(window).bind("resize."+ sID, windowResize); + + delete state.creatingLayout; + state.initialized = true; + + // init plugins for this layout, if there are any + runPluginCallbacks( Instance, $.layout.onReady ); + + // now run the onload callback, if exists + _runCallbacks("onload_end"); + + return true; // elements initialized successfully + } + + /** + * Initialize nested layouts for a specific pane - can optionally pass layout-options + * + * @param {(string|Object)} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {Object=} [opts] Layout-options - if passed, will OVERRRIDE options[pane].children + * @return An object pointer to the layout instance created - or null + */ +, createChildren = function (evt_or_pane, opts) { + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + ; + if (!$P) return; + var $C = $Cs[pane] + , s = state[pane] + , o = options[pane] + , sm = options.stateManagement || {} + , cos = opts ? (o.children = opts) : o.children + ; + if ( $.isPlainObject( cos ) ) + cos = [ cos ]; // convert a hash to a 1-elem array + else if (!cos || !$.isArray( cos )) + return; + + $.each( cos, function (idx, co) { + if ( !$.isPlainObject( co ) ) return; + + // determine which element is supposed to be the 'child container' + // if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane + var $containers = co.containerSelector ? $P.find( co.containerSelector ) : ($C || $P); + + $containers.each(function(){ + var $cont = $(this) + , child = $cont.data("layout") // see if a child-layout ALREADY exists on this element + ; + // if no layout exists, but children are set, try to create the layout now + if (!child) { + // TODO: see about moving this to the stateManagement plugin, as a method + // set a unique child-instance key for this layout, if not already set + setInstanceKey({ container: $cont, options: co }, s ); + // If THIS layout has a hash in stateManagement.autoLoad, + // then see if it also contains state-data for this child-layout + // If so, copy the stateData to child.options.stateManagement.autoLoad + if ( sm.includeChildren && state.stateData[pane] ) { + // THIS layout's state was cached when its state was loaded + var paneChildren = state.stateData[pane].children || {} + , childState = paneChildren[ co.instanceKey ] + , co_sm = co.stateManagement || (co.stateManagement = { autoLoad: true }) + ; + // COPY the stateData into the autoLoad key + if ( co_sm.autoLoad === true && childState ) { + co_sm.autoSave = false; // disable autoSave because saving handled by parent-layout + co_sm.includeChildren = true; // cascade option - FOR NOW + co_sm.autoLoad = $.extend(true, {}, childState); // COPY the state-hash + } + } + + // create the layout + child = $cont.layout( co ); + + // if successful, update data + if (child) { + // add the child and update all layout-pointers + // MAY have already been done by child-layout calling parent.refreshChildren() + refreshChildren( pane, child ); + } + } + }); + }); + } + +, setInstanceKey = function (child, parentPaneState) { + // create a named key for use in state and instance branches + var $c = child.container + , o = child.options + , sm = o.stateManagement + , key = o.instanceKey || $c.data("layoutInstanceKey") + ; + if (!key) key = (sm && sm.cookie ? sm.cookie.name : '') || o.name; // look for a name/key + if (!key) key = "layout"+ (++parentPaneState.childIdx); // if no name/key found, generate one + else key = key.replace(/[^\w-]/gi, '_').replace(/_{2,}/g, '_'); // ensure is valid as a hash key + o.instanceKey = key; + $c.data("layoutInstanceKey", key); // useful if layout is destroyed and then recreated + return key; + } + + /** + * @param {string} pane The pane being opened, ie: north, south, east, or west + * @param {Object=} newChild New child-layout Instance to add to this pane + */ +, refreshChildren = function (pane, newChild) { + var $P = $Ps[pane] + , pC = children[pane] + , s = state[pane] + , o + ; + // check for destroy()ed layouts and update the child pointers & arrays + if ($.isPlainObject( pC )) { + $.each( pC, function (key, child) { + if (child.destroyed) delete pC[key] + }); + // if no more children, remove the children hash + if ($.isEmptyObject( pC )) + pC = children[pane] = null; // clear children hash + } + + // see if there is a directly-nested layout inside this pane + // if there is, then there can be only ONE child-layout, so check that... + if (!newChild && !pC) { + newChild = $P.data("layout"); + } + + // if a newChild instance was passed, add it to children[pane] + if (newChild) { + // update child.state + newChild.hasParentLayout = true; // set parent-flag in child + // instanceKey is a key-name used in both state and children + o = newChild.options; + // set a unique child-instance key for this layout, if not already set + setInstanceKey( newChild, s ); + // add pointer to pane.children hash + if (!pC) pC = children[pane] = {}; // create an empty children hash + pC[ o.instanceKey ] = newChild.container.data("layout"); // add childLayout instance + } + + // ALWAYS refresh the pane.children alias, even if null + Instance[pane].children = children[pane]; + + // if newChild was NOT passed - see if there is a child layout NOW + if (!newChild) { + createChildren(pane); // MAY create a child and re-call this method + } + } + +, windowResize = function () { + var o = options + , delay = Number(o.resizeWithWindowDelay); + if (delay < 10) delay = 100; // MUST have a delay! + // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway + timer.clear("winResize"); // if already running + timer.set("winResize", function(){ + timer.clear("winResize"); + timer.clear("winResizeRepeater"); + var dims = elDims( $N, o.inset ); + // only trigger resizeAll() if container has changed size + if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight) + resizeAll(); + }, delay); + // ALSO set fixed-delay timer, if not already running + if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater(); + } + +, setWindowResizeRepeater = function () { + var delay = Number(options.resizeWithWindowMaxDelay); + if (delay > 0) + timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay); + } + +, unload = function () { + var o = options; + + _runCallbacks("onunload_start"); + + // trigger plugin callabacks for this layout (eg: stateManagement) + runPluginCallbacks( Instance, $.layout.onUnload ); + + _runCallbacks("onunload_end"); + } + + /** + * Validate and initialize container CSS and events + * + * @see _create() + */ +, _initContainer = function () { + var + N = $N[0] + , $H = $("html") + , tag = sC.tagName = N.tagName + , id = sC.id = N.id + , cls = sC.className = N.className + , o = options + , name = o.name + , props = "position,margin,padding,border" + , css = "layoutCSS" + , CSS = {} + , hid = "hidden" // used A LOT! + // see if this container is a 'pane' inside an outer-layout + , parent = $N.data("parentLayout") // parent-layout Instance + , pane = $N.data("layoutEdge") // pane-name in parent-layout + , isChild = parent && pane + , num = $.layout.cssNum + , $parent, n + ; + // sC = state.container + sC.selector = $N.selector.split(".slice")[0]; + sC.ref = (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages + sC.isBody = (tag === "BODY"); + + // try to find a parent-layout + if (!isChild && !sC.isBody) { + $parent = $N.closest("."+ $.layout.defaults.panes.paneClass); + parent = $parent.data("parentLayout"); + pane = $parent.data("layoutEdge"); + isChild = parent && pane; + } + + $N .data({ + layout: Instance + , layoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID + }) + .addClass(o.containerClass) + ; + var layoutMethods = { + destroy: '' + , initPanes: '' + , resizeAll: 'resizeAll' + , resize: 'resizeAll' + }; + // loop hash and bind all methods - include layoutID namespacing + for (name in layoutMethods) { + $N.bind("layout"+ name.toLowerCase() +"."+ sID, Instance[ layoutMethods[name] || name ]); + } + + // if this container is another layout's 'pane', then set child/parent pointers + if (isChild) { + // update parent flag + Instance.hasParentLayout = true; + // set pointers to THIS child-layout (Instance) in parent-layout + parent.refreshChildren( pane, Instance ); + } + + // SAVE original container CSS for use in destroy() + if (!$N.data(css)) { + // handle props like overflow different for BODY & HTML - has 'system default' values + if (sC.isBody) { + // SAVE CSS + $N.data(css, $.extend( styles($N, props), { + height: $N.css("height") + , overflow: $N.css("overflow") + , overflowX: $N.css("overflowX") + , overflowY: $N.css("overflowY") + })); + // ALSO SAVE CSS + $H.data(css, $.extend( styles($H, 'padding'), { + height: "auto" // FF would return a fixed px-size! + , overflow: $H.css("overflow") + , overflowX: $H.css("overflowX") + , overflowY: $H.css("overflowY") + })); + } + else // handle props normally for non-body elements + $N.data(css, styles($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY") ); + } + + try { + // common container CSS + CSS = { + overflow: hid + , overflowX: hid + , overflowY: hid + }; + $N.css( CSS ); + + if (o.inset && !$.isPlainObject(o.inset)) { + // can specify a single number for equal outset all-around + n = parseInt(o.inset, 10) || 0 + o.inset = { + top: n + , bottom: n + , left: n + , right: n + }; + } + + // format html & body if this is a full page layout + if (sC.isBody) { + // if HTML has padding, use this as an outer-spacing around BODY + if (!o.outset) { + // use padding from parent-elem (HTML) as outset + o.outset = { + top: num($H, "paddingTop") + , bottom: num($H, "paddingBottom") + , left: num($H, "paddingLeft") + , right: num($H, "paddingRight") + }; + } + else if (!$.isPlainObject(o.outset)) { + // can specify a single number for equal outset all-around + n = parseInt(o.outset, 10) || 0 + o.outset = { + top: n + , bottom: n + , left: n + , right: n + }; + } + // HTML + $H.css( CSS ).css({ + height: "100%" + , border: "none" // no border or padding allowed when using height = 100% + , padding: 0 // ditto + , margin: 0 + }); + // BODY + if (browser.isIE6) { + // IE6 CANNOT use the trick of setting absolute positioning on all 4 sides - must have 'height' + $N.css({ + width: "100%" + , height: "100%" + , border: "none" // no border or padding allowed when using height = 100% + , padding: 0 // ditto + , margin: 0 + , position: "relative" + }); + // convert body padding to an inset option - the border cannot be measured in IE6! + if (!o.inset) o.inset = elDims( $N ).inset; + } + else { // use absolute positioning for BODY to allow borders & padding without overflow + $N.css({ + width: "auto" + , height: "auto" + , margin: 0 + , position: "absolute" // allows for border and padding on BODY + }); + // apply edge-positioning created above + $N.css( o.outset ); + } + // set current layout-container dimensions + $.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values + } + else { + // container MUST have 'position' + var p = $N.css("position"); + if (!p || !p.match(/(fixed|absolute|relative)/)) + $N.css("position","relative"); + + // set current layout-container dimensions + if ( $N.is(":visible") ) { + $.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT change insetX (padding) values + if (sC.innerHeight < 1) // container has no 'height' - warn developer + _log( o.errors.noContainerHeight.replace(/CONTAINER/, sC.ref) ); + } + } + + // if container has min-width/height, then enable scrollbar(s) + if ( num($N, "minWidth") ) $N.parent().css("overflowX","auto"); + if ( num($N, "minHeight") ) $N.parent().css("overflowY","auto"); + + } catch (ex) {} + } + + /** + * Bind layout hotkeys - if options enabled + * + * @see _create() and addPane() + * @param {string=} [panes=""] The edge(s) to process + */ +, initHotkeys = function (panes) { + panes = panes ? panes.split(",") : _c.borderPanes; + // bind keyDown to capture hotkeys, if option enabled for ANY pane + $.each(panes, function (i, pane) { + var o = options[pane]; + if (o.enableCursorHotkey || o.customHotkey) { + $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE + return false; // BREAK - binding was done + } + }); + } + + /** + * Build final OPTIONS data + * + * @see _create() + */ +, initOptions = function () { + var data, d, pane, key, val, i, c, o; + + // reprocess user's layout-options to have correct options sub-key structure + opts = $.layout.transformData( opts, true ); // panes = default subkey + + // auto-rename old options for backward compatibility + opts = $.layout.backwardCompatibility.renameAllOptions( opts ); + + // if user-options has 'panes' key (pane-defaults), clean it... + if (!$.isEmptyObject(opts.panes)) { + // REMOVE any pane-defaults that MUST be set per-pane + data = $.layout.optionsMap.noDefault; + for (i=0, c=data.length; i 0) { + z.pane_normal = zo; + z.content_mask = max(zo+1, z.content_mask); // MIN = +1 + z.resizer_normal = max(zo+2, z.resizer_normal); // MIN = +2 + } + + // DELETE 'panes' key now that we are done - values were copied to EACH pane + delete options.panes; + + + function createFxOptions ( pane ) { + var o = options[pane] + , d = options.panes; + // ensure fxSettings key to avoid errors + if (!o.fxSettings) o.fxSettings = {}; + if (!d.fxSettings) d.fxSettings = {}; + + $.each(["_open","_close","_size"], function (i,n) { + var + sName = "fxName"+ n + , sSpeed = "fxSpeed"+ n + , sSettings = "fxSettings"+ n + // recalculate fxName according to specificity rules + , fxName = o[sName] = + o[sName] // options.west.fxName_open + || d[sName] // options.panes.fxName_open + || o.fxName // options.west.fxName + || d.fxName // options.panes.fxName + || "none" // MEANS $.layout.defaults.panes.fxName == "" || false || null || 0 + , fxExists = $.effects && ($.effects[fxName] || ($.effects.effect && $.effects.effect[fxName])) + ; + // validate fxName to ensure is valid effect - MUST have effect-config data in options.effects + if (fxName === "none" || !options.effects[fxName] || !fxExists) + fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName + + // set vars for effects subkeys to simplify logic + var fx = options.effects[fxName] || {} // effects.slide + , fx_all = fx.all || null // effects.slide.all + , fx_pane = fx[pane] || null // effects.slide.west + ; + // create fxSpeed[_open|_close|_size] + o[sSpeed] = + o[sSpeed] // options.west.fxSpeed_open + || d[sSpeed] // options.west.fxSpeed_open + || o.fxSpeed // options.west.fxSpeed + || d.fxSpeed // options.panes.fxSpeed + || null // DEFAULT - let fxSetting.duration control speed + ; + // create fxSettings[_open|_close|_size] + o[sSettings] = $.extend( + true + , {} + , fx_all // effects.slide.all + , fx_pane // effects.slide.west + , d.fxSettings // options.panes.fxSettings + , o.fxSettings // options.west.fxSettings + , d[sSettings] // options.panes.fxSettings_open + , o[sSettings] // options.west.fxSettings_open + ); + }); + + // DONE creating action-specific-settings for this pane, + // so DELETE generic options - are no longer meaningful + delete o.fxName; + delete o.fxSpeed; + delete o.fxSettings; + } + } + + /** + * Initialize module objects, styling, size and position for all panes + * + * @see _initElements() + * @param {string} pane The pane to process + */ +, getPane = function (pane) { + var sel = options[pane].paneSelector + if (sel.substr(0,1)==="#") // ID selector + // NOTE: elements selected 'by ID' DO NOT have to be 'children' + return $N.find(sel).eq(0); + else { // class or other selector + var $P = $N.children(sel).eq(0); + // look for the pane nested inside a 'form' element + return $P.length ? $P : $N.children("form:first").children(sel).eq(0); + } + } + + /** + * @param {Object=} evt + */ +, initPanes = function (evt) { + // stopPropagation if called by trigger("layoutinitpanes") - use evtPane utility + evtPane(evt); + + // NOTE: do north & south FIRST so we can measure their height - do center LAST + $.each(_c.allPanes, function (idx, pane) { + addPane( pane, true ); + }); + + // init the pane-handles NOW in case we have to hide or close the pane below + initHandles(); + + // now that all panes have been initialized and initially-sized, + // make sure there is really enough space available for each pane + $.each(_c.borderPanes, function (i, pane) { + if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN + setSizeLimits(pane); + makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit() + } + }); + // size center-pane AGAIN in case we 'closed' a border-pane in loop above + sizeMidPanes("center"); + + // Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing! + // Before RC30.3, there was a 10ms delay here, but that caused layout + // to load asynchrously, which is BAD, so try skipping delay for now + + // process pane contents and callbacks, and init/resize child-layout if exists + $.each(_c.allPanes, function (idx, pane) { + afterInitPane(pane); + }); + } + + /** + * Add a pane to the layout - subroutine of initPanes() + * + * @see initPanes() + * @param {string} pane The pane to process + * @param {boolean=} [force=false] Size content after init + */ +, addPane = function (pane, force) { + if (!force && !isInitialized()) return; + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , dir = c.dir + , fx = s.fx + , spacing = o.spacing_open || 0 + , isCenter = (pane === "center") + , CSS = {} + , $P = $Ps[pane] + , size, minSize, maxSize, child + ; + // if pane-pointer already exists, remove the old one first + if ($P) + removePane( pane, false, true, false ); + else + $Cs[pane] = false; // init + + $P = $Ps[pane] = getPane(pane); + if (!$P.length) { + $Ps[pane] = false; // logic + return; + } + + // SAVE original Pane CSS + if (!$P.data("layoutCSS")) { + var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border"; + $P.data("layoutCSS", styles($P, props)); + } + + // create alias for pane data in Instance - initHandles will add more + Instance[pane] = { + name: pane + , pane: $Ps[pane] + , content: $Cs[pane] + , options: options[pane] + , state: state[pane] + , children: children[pane] + }; + + // add classes, attributes & events + $P .data({ + parentLayout: Instance // pointer to Layout Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "pane" + }) + .css(c.cssReq).css("zIndex", options.zIndexes.pane_normal) + .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles + .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector' + .bind("mouseenter."+ sID, addHover ) + .bind("mouseleave."+ sID, removeHover ) + ; + var paneMethods = { + hide: '' + , show: '' + , toggle: '' + , close: '' + , open: '' + , slideOpen: '' + , slideClose: '' + , slideToggle: '' + , size: 'sizePane' + , sizePane: 'sizePane' + , sizeContent: '' + , sizeHandles: '' + , enableClosable: '' + , disableClosable: '' + , enableSlideable: '' + , disableSlideable: '' + , enableResizable: '' + , disableResizable: '' + , swapPanes: 'swapPanes' + , swap: 'swapPanes' + , move: 'swapPanes' + , removePane: 'removePane' + , remove: 'removePane' + , createChildren: '' + , resizeChildren: '' + , resizeAll: 'resizeAll' + , resizeLayout: 'resizeAll' + } + , name; + // loop hash and bind all methods - include layoutID namespacing + for (name in paneMethods) { + $P.bind("layoutpane"+ name.toLowerCase() +"."+ sID, Instance[ paneMethods[name] || name ]); + } + + // see if this pane has a 'scrolling-content element' + initContent(pane, false); // false = do NOT sizeContent() - called later + + if (!isCenter) { + // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden) + // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size' + size = s.size = _parseSize(pane, o.size); + minSize = _parseSize(pane,o.minSize) || 1; + maxSize = _parseSize(pane,o.maxSize) || 100000; + if (size > 0) size = max(min(size, maxSize), minSize); + s.autoResize = o.autoResize; // used with percentage sizes + + // state for border-panes + s.isClosed = false; // true = pane is closed + s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes + s.isResizing= false; // true = pane is in process of being resized + s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible! + + // array for 'pin buttons' whose classNames are auto-updated on pane-open/-close + if (!s.pins) s.pins = []; + } + // states common to ALL panes + s.tagName = $P[0].tagName; + s.edge = pane; // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going) + s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically + s.isVisible = true; // false = pane is invisible - closed OR hidden - simplify logic + + // init pane positioning + setPanePosition( pane ); + + // if pane is not visible, + if (dir === "horz") // north or south pane + CSS.height = cssH($P, size); + else if (dir === "vert") // east or west pane + CSS.width = cssW($P, size); + //else if (isCenter) {} + + $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes + if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback + + // if manually adding a pane AFTER layout initialization, then... + if (state.initialized) { + initHandles( pane ); + initHotkeys( pane ); + } + + // close or hide the pane if specified in settings + if (o.initClosed && o.closable && !o.initHidden) + close(pane, true, true); // true, true = force, noAnimation + else if (o.initHidden || o.initClosed) + hide(pane); // will be completely invisible - no resizer or spacing + else if (!s.noRoom) + // make the pane visible - in case was initially hidden + $P.css("display","block"); + // ELSE setAsOpen() - called later by initHandles() + + // RESET visibility now - pane will appear IF display:block + $P.css("visibility","visible"); + + // check option for auto-handling of pop-ups & drop-downs + if (o.showOverflowOnHover) + $P.hover( allowOverflow, resetOverflow ); + + // if manually adding a pane AFTER layout initialization, then... + if (state.initialized) { + afterInitPane( pane ); + } + } + +, afterInitPane = function (pane) { + var $P = $Ps[pane] + , s = state[pane] + , o = options[pane] + ; + if (!$P) return; + + // see if there is a directly-nested layout inside this pane + if ($P.data("layout")) + refreshChildren( pane, $P.data("layout") ); + + // process pane contents and callbacks, and init/resize child-layout if exists + if (s.isVisible) { // pane is OPEN + if (state.initialized) // this pane was added AFTER layout was created + resizeAll(); // will also sizeContent + else + sizeContent(pane); + + if (o.triggerEventsOnLoad) + _runCallbacks("onresize_end", pane); + else // automatic if onresize called, otherwise call it specifically + // resize child - IF inner-layout already exists (created before this layout) + resizeChildren(pane, true); // a previously existing childLayout + } + + // init childLayouts - even if pane is not visible + if (o.initChildren && o.children) + createChildren(pane); + } + + /** + * @param {string=} panes The pane(s) to process + */ +, setPanePosition = function (panes) { + panes = panes ? panes.split(",") : _c.borderPanes; + + // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV + $.each(panes, function (i, pane) { + var $P = $Ps[pane] + , $R = $Rs[pane] + , o = options[pane] + , s = state[pane] + , side = _c[pane].side + , CSS = {} + ; + if (!$P) return; // pane does not exist - skip + + // set css-position to account for container borders & padding + switch (pane) { + case "north": CSS.top = sC.inset.top; + CSS.left = sC.inset.left; + CSS.right = sC.inset.right; + break; + case "south": CSS.bottom = sC.inset.bottom; + CSS.left = sC.inset.left; + CSS.right = sC.inset.right; + break; + case "west": CSS.left = sC.inset.left; // top, bottom & height set by sizeMidPanes() + break; + case "east": CSS.right = sC.inset.right; // ditto + break; + case "center": // top, left, width & height set by sizeMidPanes() + } + // apply position + $P.css(CSS); + + // update resizer position + if ($R && s.isClosed) + $R.css(side, sC.inset[side]); + else if ($R && !s.isHidden) + $R.css(side, sC.inset[side] + getPaneSize(pane)); + }); + } + + /** + * Initialize module objects, styling, size and position for all resize bars and toggler buttons + * + * @see _create() + * @param {string=} [panes=""] The edge(s) to process + */ +, initHandles = function (panes) { + panes = panes ? panes.split(",") : _c.borderPanes; + + // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV + $.each(panes, function (i, pane) { + var $P = $Ps[pane]; + $Rs[pane] = false; // INIT + $Ts[pane] = false; + if (!$P) return; // pane does not exist - skip + + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , paneId = o.paneSelector.substr(0,1) === "#" ? o.paneSelector.substr(1) : "" + , rClass = o.resizerClass + , tClass = o.togglerClass + , spacing = (s.isVisible ? o.spacing_open : o.spacing_closed) + , _pane = "-"+ pane // used for classNames + , _state = (s.isVisible ? "-open" : "-closed") // used for classNames + , I = Instance[pane] + // INIT RESIZER BAR + , $R = I.resizer = $Rs[pane] = $("
      ") + // INIT TOGGLER BUTTON + , $T = I.toggler = (o.closable ? $Ts[pane] = $("
      ") : false) + ; + + //if (s.isVisible && o.resizable) ... handled by initResizable + if (!s.isVisible && o.slidable) + $R.attr("title", o.tips.Slide).css("cursor", o.sliderCursor); + + $R // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer" + .attr("id", paneId ? paneId +"-resizer" : "" ) + .data({ + parentLayout: Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "resizer" + }) + .css(_c.resizers.cssReq).css("zIndex", options.zIndexes.resizer_normal) + .css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles + .addClass(rClass +" "+ rClass+_pane) + .hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead + .hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter + .appendTo($N) // append DIV to container + ; + if (o.resizerDblClickToggle) + $R.bind("dblclick."+ sID, toggle ); + + if ($T) { + $T // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler" + .attr("id", paneId ? paneId +"-toggler" : "" ) + .data({ + parentLayout: Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "toggler" + }) + .css(_c.togglers.cssReq) // add base/required styles + .css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles + .addClass(tClass +" "+ tClass+_pane) + .hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead + .bind("mouseenter", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer + .appendTo($R) // append SPAN to resizer DIV + ; + // ADD INNER-SPANS TO TOGGLER + if (o.togglerContent_open) // ui-layout-open + $(""+ o.togglerContent_open +"") + .data({ + layoutEdge: pane + , layoutRole: "togglerContent" + }) + .data("layoutRole", "togglerContent") + .data("layoutEdge", pane) + .addClass("content content-open") + .css("display","none") + .appendTo( $T ) + //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead! + ; + if (o.togglerContent_closed) // ui-layout-closed + $(""+ o.togglerContent_closed +"") + .data({ + layoutEdge: pane + , layoutRole: "togglerContent" + }) + .addClass("content content-closed") + .css("display","none") + .appendTo( $T ) + //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead! + ; + // ADD TOGGLER.click/.hover + enableClosable(pane); + } + + // add Draggable events + initResizable(pane); + + // ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open" + if (s.isVisible) + setAsOpen(pane); // onOpen will be called, but NOT onResize + else { + setAsClosed(pane); // onClose will be called + bindStartSlidingEvents(pane, true); // will enable events IF option is set + } + + }); + + // SET ALL HANDLE DIMENSIONS + sizeHandles(); + } + + + /** + * Initialize scrolling ui-layout-content div - if exists + * + * @see initPane() - or externally after an Ajax injection + * @param {string} pane The pane to process + * @param {boolean=} [resize=true] Size content after init + */ +, initContent = function (pane, resize) { + if (!isInitialized()) return; + var + o = options[pane] + , sel = o.contentSelector + , I = Instance[pane] + , $P = $Ps[pane] + , $C + ; + if (sel) $C = I.content = $Cs[pane] = (o.findNestedContent) + ? $P.find(sel).eq(0) // match 1-element only + : $P.children(sel).eq(0) + ; + if ($C && $C.length) { + $C.data("layoutRole", "content"); + // SAVE original Content CSS + if (!$C.data("layoutCSS")) + $C.data("layoutCSS", styles($C, "height")); + $C.css( _c.content.cssReq ); + if (o.applyDemoStyles) { + $C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div + $P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane + } + // ensure no vertical scrollbar on pane - will mess up measurements + if ($P.css("overflowX").match(/(scroll|auto)/)) { + $P.css("overflow", "hidden"); + } + state[pane].content = {}; // init content state + if (resize !== false) sizeContent(pane); + // sizeContent() is called AFTER init of all elements + } + else + I.content = $Cs[pane] = false; + } + + + /** + * Add resize-bars to all panes that specify it in options + * -dependancy: $.fn.resizable - will skip if not found + * + * @see _create() + * @param {string=} [panes=""] The edge(s) to process + */ +, initResizable = function (panes) { + var draggingAvailable = $.layout.plugins.draggable + , side // set in start() + ; + panes = panes ? panes.split(",") : _c.borderPanes; + + $.each(panes, function (idx, pane) { + var o = options[pane]; + if (!draggingAvailable || !$Ps[pane] || !o.resizable) { + o.resizable = false; + return true; // skip to next + } + + var s = state[pane] + , z = options.zIndexes + , c = _c[pane] + , side = c.dir=="horz" ? "top" : "left" + , $P = $Ps[pane] + , $R = $Rs[pane] + , base = o.resizerClass + , lastPos = 0 // used when live-resizing + , r, live // set in start because may change + // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process + , resizerClass = base+"-drag" // resizer-drag + , resizerPaneClass = base+"-"+pane+"-drag" // resizer-north-drag + // 'helper' class is applied to the CLONED resizer-bar while it is being dragged + , helperClass = base+"-dragging" // resizer-dragging + , helperPaneClass = base+"-"+pane+"-dragging" // resizer-north-dragging + , helperLimitClass = base+"-dragging-limit" // resizer-drag + , helperPaneLimitClass = base+"-"+pane+"-dragging-limit" // resizer-north-drag + , helperClassesSet = false // logic var + ; + + if (!s.isClosed) + $R.attr("title", o.tips.Resize) + .css("cursor", o.resizerCursor); // n-resize, s-resize, etc + + $R.draggable({ + containment: $N[0] // limit resizing to layout container + , axis: (c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis + , delay: 0 + , distance: 1 + , grid: o.resizingGrid + // basic format for helper - style it using class: .ui-draggable-dragging + , helper: "clone" + , opacity: o.resizerDragOpacity + , addClasses: false // avoid ui-state-disabled class when disabled + //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed + , zIndex: z.resizer_drag + + , start: function (e, ui) { + // REFRESH options & state pointers in case we used swapPanes + o = options[pane]; + s = state[pane]; + // re-read options + live = o.livePaneResizing; + + // ondrag_start callback - will CANCEL hide if returns false + // TODO: dragging CANNOT be cancelled like this, so see if there is a way? + if (false === _runCallbacks("ondrag_start", pane)) return false; + + s.isResizing = true; // prevent pane from closing while resizing + state.paneResizing = pane; // easy to see if ANY pane is resizing + timer.clear(pane+"_closeSlider"); // just in case already triggered + + // SET RESIZER LIMITS - used in drag() + setSizeLimits(pane); // update pane/resizer state + r = s.resizerPosition; + lastPos = ui.position[ side ] + + $R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes + helperClassesSet = false; // reset logic var - see drag() + + // DISABLE TEXT SELECTION (probably already done by resizer.mouseOver) + $('body').disableSelection(); + + // MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS + showMasks( pane, { resizing: true }); + } + + , drag: function (e, ui) { + if (!helperClassesSet) { // can only add classes after clone has been added to the DOM + //$(".ui-draggable-dragging") + ui.helper + .addClass( helperClass +" "+ helperPaneClass ) // add helper classes + .css({ right: "auto", bottom: "auto" }) // fix dir="rtl" issue + .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar + ; + helperClassesSet = true; + // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! + if (s.isSliding) $Ps[pane].css("zIndex", z.pane_sliding); + } + // CONTAIN RESIZER-BAR TO RESIZING LIMITS + var limit = 0; + if (ui.position[side] < r.min) { + ui.position[side] = r.min; + limit = -1; + } + else if (ui.position[side] > r.max) { + ui.position[side] = r.max; + limit = 1; + } + // ADD/REMOVE dragging-limit CLASS + if (limit) { + ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit + window.defaultStatus = (limit>0 && pane.match(/(north|west)/)) || (limit<0 && pane.match(/(south|east)/)) ? o.tips.maxSizeWarning : o.tips.minSizeWarning; + } + else { + ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit + window.defaultStatus = ""; + } + // DYNAMICALLY RESIZE PANES IF OPTION ENABLED + // won't trigger unless resizer has actually moved! + if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) { + lastPos = ui.position[side]; + resizePanes(e, ui, pane) + } + } + + , stop: function (e, ui) { + $('body').enableSelection(); // RE-ENABLE TEXT SELECTION + window.defaultStatus = ""; // clear 'resizing limit' message from statusbar + $R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer + s.isResizing = false; + state.paneResizing = false; // easy to see if ANY pane is resizing + resizePanes(e, ui, pane, true); // true = resizingDone + } + + }); + }); + + /** + * resizePanes + * + * Sub-routine called from stop() - and drag() if livePaneResizing + * + * @param {!Object} evt + * @param {!Object} ui + * @param {string} pane + * @param {boolean=} [resizingDone=false] + */ + var resizePanes = function (evt, ui, pane, resizingDone) { + var dragPos = ui.position + , c = _c[pane] + , o = options[pane] + , s = state[pane] + , resizerPos + ; + switch (pane) { + case "north": resizerPos = dragPos.top; break; + case "west": resizerPos = dragPos.left; break; + case "south": resizerPos = sC.layoutHeight - dragPos.top - o.spacing_open; break; + case "east": resizerPos = sC.layoutWidth - dragPos.left - o.spacing_open; break; + }; + // remove container margin from resizer position to get the pane size + var newSize = resizerPos - sC.inset[c.side]; + + // Disable OR Resize Mask(s) created in drag.start + if (!resizingDone) { + // ensure we meet liveResizingTolerance criteria + if (Math.abs(newSize - s.size) < o.liveResizingTolerance) + return; // SKIP resize this time + // resize the pane + manualSizePane(pane, newSize, false, true); // true = noAnimation + sizeMasks(); // resize all visible masks + } + else { // resizingDone + // ondrag_end callback + if (false !== _runCallbacks("ondrag_end", pane)) + manualSizePane(pane, newSize, false, true); // true = noAnimation + hideMasks(true); // true = force hiding all masks even if one is 'sliding' + if (s.isSliding) // RE-SHOW 'object-masks' so objects won't show through sliding pane + showMasks( pane, { resizing: true }); + } + }; + } + + /** + * sizeMask + * + * Needed to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane + * Called when mask created, and during livePaneResizing + */ +, sizeMask = function () { + var $M = $(this) + , pane = $M.data("layoutMask") // eg: "west" + , s = state[pane] + ; + // only masks over an IFRAME-pane need manual resizing + if (s.tagName == "IFRAME" && s.isVisible) // no need to mask closed/hidden panes + $M.css({ + top: s.offsetTop + , left: s.offsetLeft + , width: s.outerWidth + , height: s.outerHeight + }); + /* ALT Method... + var $P = $Ps[pane]; + $M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight }); + */ + } +, sizeMasks = function () { + $Ms.each( sizeMask ); // resize all 'visible' masks + } + + /** + * @param {string} pane The pane being resized, animated or isSliding + * @param {Object=} [args] (optional) Options: which masks to apply, and to which panes + */ +, showMasks = function (pane, args) { + var c = _c[pane] + , panes = ["center"] + , z = options.zIndexes + , a = $.extend({ + objectsOnly: false + , animation: false + , resizing: true + , sliding: state[pane].isSliding + }, args ) + , o, s + ; + if (a.resizing) + panes.push( pane ); + if (a.sliding) + panes.push( _c.oppositeEdge[pane] ); // ADD the oppositeEdge-pane + + if (c.dir === "horz") { + panes.push("west"); + panes.push("east"); + } + + $.each(panes, function(i,p){ + s = state[p]; + o = options[p]; + if (s.isVisible && ( o.maskObjects || (!a.objectsOnly && o.maskContents) )) { + getMasks(p).each(function(){ + sizeMask.call(this); + this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1 + this.style.display = "block"; + }); + } + }); + } + + /** + * @param {boolean=} force Hide masks even if a pane is sliding + */ +, hideMasks = function (force) { + // ensure no pane is resizing - could be a timing issue + if (force || !state.paneResizing) { + $Ms.hide(); // hide ALL masks + } + // if ANY pane is sliding, then DO NOT remove masks from panes with maskObjects enabled + else if (!force && !$.isEmptyObject( state.panesSliding )) { + var i = $Ms.length - 1 + , p, $M; + for (; i >= 0; i--) { + $M = $Ms.eq(i); + p = $M.data("layoutMask"); + if (!options[p].maskObjects) { + $M.hide(); + } + } + } + } + + /** + * @param {string} pane + */ +, getMasks = function (pane) { + var $Masks = $([]) + , $M, i = 0, c = $Ms.length + ; + for (; i CSS + if (sC.tagName === "BODY" && ($N = $("html")).data(css)) // RESET CSS + $N.css( $N.data(css) ).removeData(css); + + // trigger plugins for this layout, if there are any + runPluginCallbacks( Instance, $.layout.onDestroy ); + + // trigger state-management and onunload callback + unload(); + + // clear the Instance of everything except for container & options (so could recreate) + // RE-CREATE: myLayout = myLayout.container.layout( myLayout.options ); + for (var n in Instance) + if (!n.match(/^(container|options)$/)) delete Instance[ n ]; + // add a 'destroyed' flag to make it easy to check + Instance.destroyed = true; + + // if this is a child layout, CLEAR the child-pointer in the parent + /* for now the pointer REMAINS, but with only container, options and destroyed keys + if (parentPane) { + var layout = parentPane.pane.data("parentLayout") + , key = layout.options.instanceKey || 'error'; + // THIS SYNTAX MAY BE WRONG! + parentPane.children[key] = layout.children[ parentPane.name ].children[key] = null; + } + */ + + return Instance; // for coding convenience + } + + /** + * Remove a pane from the layout - subroutine of destroy() + * + * @see destroy() + * @param {(string|Object)} evt_or_pane The pane to process + * @param {boolean=} [remove=false] Remove the DOM element? + * @param {boolean=} [skipResize=false] Skip calling resizeAll()? + * @param {boolean=} [destroyChild=true] Destroy Child-layouts? If not passed, obeys options setting + */ +, removePane = function (evt_or_pane, remove, skipResize, destroyChild) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + , $C = $Cs[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + ; + // NOTE: elements can still exist even after remove() + // so check for missing data(), which is cleared by removed() + if ($P && $.isEmptyObject( $P.data() )) $P = false; + if ($C && $.isEmptyObject( $C.data() )) $C = false; + if ($R && $.isEmptyObject( $R.data() )) $R = false; + if ($T && $.isEmptyObject( $T.data() )) $T = false; + + if ($P) $P.stop(true, true); + + var o = options[pane] + , s = state[pane] + , d = "layout" + , css = "layoutCSS" + , pC = children[pane] + , hasChildren = $.isPlainObject( pC ) && !$.isEmptyObject( pC ) + , destroy = destroyChild !== undefined ? destroyChild : o.destroyChildren + ; + // FIRST destroy the child-layout(s) + if (hasChildren && destroy) { + $.each( pC, function (key, child) { + if (!child.destroyed) + child.destroy(true);// tell child-layout to destroy ALL its child-layouts too + if (child.destroyed) // destroy was successful + delete pC[key]; + }); + // if no more children, remove the children hash + if ($.isEmptyObject( pC )) { + pC = children[pane] = null; // clear children hash + hasChildren = false; + } + } + + // Note: can't 'remove' a pane element with non-destroyed children + if ($P && remove && !hasChildren) + $P.remove(); // remove the pane-element and everything inside it + else if ($P && $P[0]) { + // create list of ALL pane-classes that need to be removed + var root = o.paneClass // default="ui-layout-pane" + , pRoot = root +"-"+ pane // eg: "ui-layout-pane-west" + , _open = "-open" + , _sliding= "-sliding" + , _closed = "-closed" + , classes = [ root, root+_open, root+_closed, root+_sliding, // generic classes + pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ] // pane-specific classes + ; + $.merge(classes, getHoverClasses($P, true)); // ADD hover-classes + // remove all Layout classes from pane-element + $P .removeClass( classes.join(" ") ) // remove ALL pane-classes + .removeData("parentLayout") + .removeData("layoutPane") + .removeData("layoutRole") + .removeData("layoutEdge") + .removeData("autoHidden") // in case set + .unbind("."+ sID) // remove ALL Layout events + // TODO: remove these extra unbind commands when jQuery is fixed + //.unbind("mouseenter"+ sID) + //.unbind("mouseleave"+ sID) + ; + // do NOT reset CSS if this pane/content is STILL the container of a nested layout! + // the nested layout will reset its 'container' CSS when/if it is destroyed + if (hasChildren && $C) { + // a content-div may not have a specific width, so give it one to contain the Layout + $C.width( $C.width() ); + $.each( pC, function (key, child) { + child.resizeAll(); // resize the Layout + }); + } + else if ($C) + $C.css( $C.data(css) ).removeData(css).removeData("layoutRole"); + // remove pane AFTER content in case there was a nested layout + if (!$P.data(d)) + $P.css( $P.data(css) ).removeData(css); + } + + // REMOVE pane resizer and toggler elements + if ($T) $T.remove(); + if ($R) $R.remove(); + + // CLEAR all pointers and state data + Instance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = false; + s = { removed: true }; + + if (!skipResize) + resizeAll(); + } + + +/* + * ########################### + * ACTION METHODS + * ########################### + */ + + /** + * @param {string} pane + */ +, _hidePane = function (pane) { + var $P = $Ps[pane] + , o = options[pane] + , s = $P[0].style + ; + if (o.useOffscreenClose) { + if (!$P.data(_c.offscreenReset)) + $P.data(_c.offscreenReset, { left: s.left, right: s.right }); + $P.css( _c.offscreenCSS ); + } + else + $P.hide().removeData(_c.offscreenReset); + } + + /** + * @param {string} pane + */ +, _showPane = function (pane) { + var $P = $Ps[pane] + , o = options[pane] + , off = _c.offscreenCSS + , old = $P.data(_c.offscreenReset) + , s = $P[0].style + ; + $P .show() // ALWAYS show, just in case + .removeData(_c.offscreenReset); + if (o.useOffscreenClose && old) { + if (s.left == off.left) + s.left = old.left; + if (s.right == off.right) + s.right = old.right; + } + } + + + /** + * Completely 'hides' a pane, including its spacing - as if it does not exist + * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it + * + * @param {(string|Object)} evt_or_pane The pane being hidden, ie: north, south, east, or west + * @param {boolean=} [noAnimation=false] + */ +, hide = function (evt_or_pane, noAnimation) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + if (!$P || s.isHidden) return; // pane does not exist OR is already hidden + + // onhide_start callback - will CANCEL hide if returns false + if (state.initialized && false === _runCallbacks("onhide_start", pane)) return; + + s.isSliding = false; // just in case + delete state.panesSliding[pane]; + + // now hide the elements + if ($R) $R.hide(); // hide resizer-bar + if (!state.initialized || s.isClosed) { + s.isClosed = true; // to trigger open-animation on show() + s.isHidden = true; + s.isVisible = false; + if (!state.initialized) + _hidePane(pane); // no animation when loading page + sizeMidPanes(_c[pane].dir === "horz" ? "" : "center"); + if (state.initialized || o.triggerEventsOnLoad) + _runCallbacks("onhide_end", pane); + } + else { + s.isHiding = true; // used by onclose + close(pane, false, noAnimation); // adjust all panes to fit + } + } + + /** + * Show a hidden pane - show as 'closed' by default unless openPane = true + * + * @param {(string|Object)} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {boolean=} [openPane=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [noAlert=false] + */ +, show = function (evt_or_pane, openPane, noAnimation, noAlert) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden + + // onshow_start callback - will CANCEL show if returns false + if (false === _runCallbacks("onshow_start", pane)) return; + + s.isShowing = true; // used by onopen/onclose + //s.isHidden = false; - will be set by open/close - if not cancelled + s.isSliding = false; // just in case + delete state.panesSliding[pane]; + + // now show the elements + //if ($R) $R.show(); - will be shown by open/close + if (openPane === false) + close(pane, true); // true = force + else + open(pane, false, noAnimation, noAlert); // adjust all panes to fit + } + + + /** + * Toggles a pane open/closed by calling either open or close + * + * @param {(string|Object)} evt_or_pane The pane being toggled, ie: north, south, east, or west + * @param {boolean=} [slide=false] + */ +, toggle = function (evt_or_pane, slide) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , s = state[pane] + ; + if (evt) // called from to $R.dblclick OR triggerPaneEvent + evt.stopImmediatePropagation(); + if (s.isHidden) + show(pane); // will call 'open' after unhiding it + else if (s.isClosed) + open(pane, !!slide); + else + close(pane); + } + + + /** + * Utility method used during init or other auto-processes + * + * @param {string} pane The pane being closed + * @param {boolean=} [setHandles=false] + */ +, _closePane = function (pane, setHandles) { + var + $P = $Ps[pane] + , s = state[pane] + ; + _hidePane(pane); + s.isClosed = true; + s.isVisible = false; + // UNUSED: if (setHandles) setAsClosed(pane, true); // true = force + } + + /** + * Close the specified pane (animation optional), and resize all other panes as needed + * + * @param {(string|Object)} evt_or_pane The pane being closed, ie: north, south, east, or west + * @param {boolean=} [force=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [skipCallback=false] + */ +, close = function (evt_or_pane, force, noAnimation, skipCallback) { + var pane = evtPane.call(this, evt_or_pane); + // if pane has been initialized, but NOT the complete layout, close pane instantly + if (!state.initialized && $Ps[pane]) { + _closePane(pane); // INIT pane as closed + return; + } + if (!isInitialized()) return; + + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , c = _c[pane] + , doFX, isShowing, isHiding, wasSliding; + + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + + if ( !$P + || (!o.closable && !s.isShowing && !s.isHiding) // invalid request // (!o.resizable && !o.closable) ??? + || (!force && s.isClosed && !s.isShowing) // already closed + ) return queueNext(); + + // onclose_start callback - will CANCEL hide if returns false + // SKIP if just 'showing' a hidden pane as 'closed' + var abort = !s.isShowing && false === _runCallbacks("onclose_start", pane); + + // transfer logic vars to temp vars + isShowing = s.isShowing; + isHiding = s.isHiding; + wasSliding = s.isSliding; + // now clear the logic vars (REQUIRED before aborting) + delete s.isShowing; + delete s.isHiding; + + if (abort) return queueNext(); + + doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none"); + s.isMoving = true; + s.isClosed = true; + s.isVisible = false; + // update isHidden BEFORE sizing panes + if (isHiding) s.isHidden = true; + else if (isShowing) s.isHidden = false; + + if (s.isSliding) // pane is being closed, so UNBIND trigger events + bindStopSlidingEvents(pane, false); // will set isSliding=false + else // resize panes adjacent to this one + sizeMidPanes(_c[pane].dir === "horz" ? "" : "center", false); // false = NOT skipCallback + + // if this pane has a resizer bar, move it NOW - before animation + setAsClosed(pane); + + // CLOSE THE PANE + if (doFX) { // animate the close + lockPaneForFX(pane, true); // need to set left/top so animation will work + $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () { + lockPaneForFX(pane, false); // undo + if (s.isClosed) close_2(); + queueNext(); + }); + } + else { // hide the pane without animation + _hidePane(pane); + close_2(); + queueNext(); + }; + }); + + // SUBROUTINE + function close_2 () { + s.isMoving = false; + bindStartSlidingEvents(pane, true); // will enable if o.slidable = true + + // if opposite-pane was autoClosed, see if it can be autoOpened now + var altPane = _c.oppositeEdge[pane]; + if (state[ altPane ].noRoom) { + setSizeLimits( altPane ); + makePaneFit( altPane ); + } + + if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) { + // onclose callback - UNLESS just 'showing' a hidden pane as 'closed' + if (!isShowing) _runCallbacks("onclose_end", pane); + // onhide OR onshow callback + if (isShowing) _runCallbacks("onshow_end", pane); + if (isHiding) _runCallbacks("onhide_end", pane); + } + } + } + + /** + * @param {string} pane The pane just closed, ie: north, south, east, or west + */ +, setAsClosed = function (pane) { + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , side = _c[pane].side + , rClass = o.resizerClass + , tClass = o.togglerClass + , _pane = "-"+ pane // used for classNames + , _open = "-open" + , _sliding= "-sliding" + , _closed = "-closed" + ; + $R + .css(side, sC.inset[side]) // move the resizer + .removeClass( rClass+_open +" "+ rClass+_pane+_open ) + .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + .addClass( rClass+_closed +" "+ rClass+_pane+_closed ) + ; + // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvents? + if (o.resizable && $.layout.plugins.draggable) + $R + .draggable("disable") + .removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here + .css("cursor", "default") + .attr("title","") + ; + + // if pane has a toggler button, adjust that too + if ($T) { + $T + .removeClass( tClass+_open +" "+ tClass+_pane+_open ) + .addClass( tClass+_closed +" "+ tClass+_pane+_closed ) + .attr("title", o.tips.Open) // may be blank + ; + // toggler-content - if exists + $T.children(".content-open").hide(); + $T.children(".content-closed").css("display","block"); + } + + // sync any 'pin buttons' + syncPinBtns(pane, false); + + if (state.initialized) { + // resize 'length' and position togglers for adjacent panes + sizeHandles(); + } + } + + /** + * Open the specified pane (animation optional), and resize all other panes as needed + * + * @param {(string|Object)} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {boolean=} [slide=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [noAlert=false] + */ +, open = function (evt_or_pane, slide, noAnimation, noAlert) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , c = _c[pane] + , doFX, isShowing + ; + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + + if ( !$P + || (!o.resizable && !o.closable && !s.isShowing) // invalid request + || (s.isVisible && !s.isSliding) // already open + ) return queueNext(); + + // pane can ALSO be unhidden by just calling show(), so handle this scenario + if (s.isHidden && !s.isShowing) { + queueNext(); // call before show() because it needs the queue free + show(pane, true); + return; + } + + if (s.autoResize && s.size != o.size) // resize pane to original size set in options + sizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize + else + // make sure there is enough space available to open the pane + setSizeLimits(pane, slide); + + // onopen_start callback - will CANCEL open if returns false + var cbReturn = _runCallbacks("onopen_start", pane); + + if (cbReturn === "abort") + return queueNext(); + + // update pane-state again in case options were changed in onopen_start + if (cbReturn !== "NC") // NC = "No Callback" + setSizeLimits(pane, slide); + + if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN! + syncPinBtns(pane, false); // make sure pin-buttons are reset + if (!noAlert && o.tips.noRoomToOpen) + alert(o.tips.noRoomToOpen); + return queueNext(); // ABORT + } + + if (slide) // START Sliding - will set isSliding=true + bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane + else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead + bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false + else if (o.slidable) + bindStartSlidingEvents(pane, false); // UNBIND trigger events + + s.noRoom = false; // will be reset by makePaneFit if 'noRoom' + makePaneFit(pane); + + // transfer logic var to temp var + isShowing = s.isShowing; + // now clear the logic var + delete s.isShowing; + + doFX = !noAnimation && s.isClosed && (o.fxName_open != "none"); + s.isMoving = true; + s.isVisible = true; + s.isClosed = false; + // update isHidden BEFORE sizing panes - WHY??? Old? + if (isShowing) s.isHidden = false; + + if (doFX) { // ANIMATE + // mask adjacent panes with objects + lockPaneForFX(pane, true); // need to set left/top so animation will work + $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() { + lockPaneForFX(pane, false); // undo + if (s.isVisible) open_2(); // continue + queueNext(); + }); + } + else { // no animation + _showPane(pane);// just show pane and... + open_2(); // continue + queueNext(); + }; + }); + + // SUBROUTINE + function open_2 () { + s.isMoving = false; + + // cure iframe display issues + _fixIframe(pane); + + // NOTE: if isSliding, then other panes are NOT 'resized' + if (!s.isSliding) { // resize all panes adjacent to this one + sizeMidPanes(_c[pane].dir=="vert" ? "center" : "", false); // false = NOT skipCallback + } + + // set classes, position handles and execute callbacks... + setAsOpen(pane); + }; + + } + + /** + * @param {string} pane The pane just opened, ie: north, south, east, or west + * @param {boolean=} [skipCallback=false] + */ +, setAsOpen = function (pane, skipCallback) { + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , side = _c[pane].side + , rClass = o.resizerClass + , tClass = o.togglerClass + , _pane = "-"+ pane // used for classNames + , _open = "-open" + , _closed = "-closed" + , _sliding= "-sliding" + ; + $R + .css(side, sC.inset[side] + getPaneSize(pane)) // move the resizer + .removeClass( rClass+_closed +" "+ rClass+_pane+_closed ) + .addClass( rClass+_open +" "+ rClass+_pane+_open ) + ; + if (s.isSliding) + $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + else // in case 'was sliding' + $R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + + removeHover( 0, $R ); // remove hover classes + if (o.resizable && $.layout.plugins.draggable) + $R .draggable("enable") + .css("cursor", o.resizerCursor) + .attr("title", o.tips.Resize); + else if (!s.isSliding) + $R.css("cursor", "default"); // n-resize, s-resize, etc + + // if pane also has a toggler button, adjust that too + if ($T) { + $T .removeClass( tClass+_closed +" "+ tClass+_pane+_closed ) + .addClass( tClass+_open +" "+ tClass+_pane+_open ) + .attr("title", o.tips.Close); // may be blank + removeHover( 0, $T ); // remove hover classes + // toggler-content - if exists + $T.children(".content-closed").hide(); + $T.children(".content-open").css("display","block"); + } + + // sync any 'pin buttons' + syncPinBtns(pane, !s.isSliding); + + // update pane-state dimensions - BEFORE resizing content + $.extend(s, elDims($P)); + + if (state.initialized) { + // resize resizer & toggler sizes for all panes + sizeHandles(); + // resize content every time pane opens - to be sure + sizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving' + } + + if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) { + // onopen callback + _runCallbacks("onopen_end", pane); + // onshow callback - TODO: should this be here? + if (s.isShowing) _runCallbacks("onshow_end", pane); + + // ALSO call onresize because layout-size *may* have changed while pane was closed + if (state.initialized) + _runCallbacks("onresize_end", pane); + } + + // TODO: Somehow sizePane("north") is being called after this point??? + } + + + /** + * slideOpen / slideClose / slideToggle + * + * Pass-though methods for sliding + */ +, slideOpen = function (evt_or_pane) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , s = state[pane] + , delay = options[pane].slideDelay_open + ; + // prevent event from triggering on NEW resizer binding created below + if (evt) evt.stopImmediatePropagation(); + + if (s.isClosed && evt && evt.type === "mouseenter" && delay > 0) + // trigger = mouseenter - use a delay + timer.set(pane+"_openSlider", open_NOW, delay); + else + open_NOW(); // will unbind events if is already open + + /** + * SUBROUTINE for timed open + */ + function open_NOW () { + if (!s.isClosed) // skip if no longer closed! + bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane + else if (!s.isMoving) + open(pane, true); // true = slide - open() will handle binding + }; + } + +, slideClose = function (evt_or_pane) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , delay = s.isMoving ? 1000 : 300 // MINIMUM delay - option may override + ; + if (s.isClosed || s.isResizing) + return; // skip if already closed OR in process of resizing + else if (o.slideTrigger_close === "click") + close_NOW(); // close immediately onClick + else if (o.preventQuickSlideClose && s.isMoving) + return; // handle Chrome quick-close on slide-open + else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane])) + return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE + else if (evt) // trigger = mouseleave - use a delay + // 1 sec delay if 'opening', else .3 sec + timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay)); + else // called programically + close_NOW(); + + /** + * SUBROUTINE for timed close + */ + function close_NOW () { + if (s.isClosed) // skip 'close' if already closed! + bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here? + else if (!s.isMoving) + close(pane); // close will handle unbinding + }; + } + + /** + * @param {(string|Object)} evt_or_pane The pane being opened, ie: north, south, east, or west + */ +, slideToggle = function (evt_or_pane) { + var pane = evtPane.call(this, evt_or_pane); + toggle(pane, true); + } + + + /** + * Must set left/top on East/South panes so animation will work properly + * + * @param {string} pane The pane to lock, 'east' or 'south' - any other is ignored! + * @param {boolean} doLock true = set left/top, false = remove + */ +, lockPaneForFX = function (pane, doLock) { + var $P = $Ps[pane] + , s = state[pane] + , o = options[pane] + , z = options.zIndexes + ; + if (doLock) { + showMasks( pane, { animation: true, objectsOnly: true }); + $P.css({ zIndex: z.pane_animate }); // overlay all elements during animation + if (pane=="south") + $P.css({ top: sC.inset.top + sC.innerHeight - $P.outerHeight() }); + else if (pane=="east") + $P.css({ left: sC.inset.left + sC.innerWidth - $P.outerWidth() }); + } + else { // animation DONE - RESET CSS + hideMasks(); + $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); + if (pane=="south") + $P.css({ top: "auto" }); + // if pane is positioned 'off-screen', then DO NOT screw with it! + else if (pane=="east" && !$P.css("left").match(/\-99999/)) + $P.css({ left: "auto" }); + // fix anti-aliasing in IE - only needed for animations that change opacity + if (browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1) + $P[0].style.removeAttribute('filter'); + } + } + + + /** + * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger + * + * @see open(), close() + * @param {string} pane The pane to enable/disable, 'north', 'south', etc. + * @param {boolean} enable Enable or Disable sliding? + */ +, bindStartSlidingEvents = function (pane, enable) { + var o = options[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , evtName = o.slideTrigger_open.toLowerCase() + ; + if (!$R || (enable && !o.slidable)) return; + + // make sure we have a valid event + if (evtName.match(/mouseover/)) + evtName = o.slideTrigger_open = "mouseenter"; + else if (!evtName.match(/(click|dblclick|mouseenter)/)) + evtName = o.slideTrigger_open = "click"; + + // must remove double-click-toggle when using dblclick-slide + if (o.resizerDblClickToggle && evtName.match(/click/)) { + $R[enable ? "unbind" : "bind"]('dblclick.'+ sID, toggle) + } + + $R + // add or remove event + [enable ? "bind" : "unbind"](evtName +'.'+ sID, slideOpen) + // set the appropriate cursor & title/tip + .css("cursor", enable ? o.sliderCursor : "default") + .attr("title", enable ? o.tips.Slide : "") + ; + } + + /** + * Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed + * Also increases zIndex when pane is sliding open + * See bindStartSlidingEvents for code to control 'slide open' + * + * @see slideOpen(), slideClose() + * @param {string} pane The pane to process, 'north', 'south', etc. + * @param {boolean} enable Enable or Disable events? + */ +, bindStopSlidingEvents = function (pane, enable) { + var o = options[pane] + , s = state[pane] + , c = _c[pane] + , z = options.zIndexes + , evtName = o.slideTrigger_close.toLowerCase() + , action = (enable ? "bind" : "unbind") + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + timer.clear(pane+"_closeSlider"); // just in case + + if (enable) { + s.isSliding = true; + state.panesSliding[pane] = true; + // remove 'slideOpen' event from resizer + // ALSO will raise the zIndex of the pane & resizer + bindStartSlidingEvents(pane, false); + } + else { + s.isSliding = false; + delete state.panesSliding[pane]; + } + + // RE/SET zIndex - increases when pane is sliding-open, resets to normal when not + $P.css("zIndex", enable ? z.pane_sliding : z.pane_normal); + $R.css("zIndex", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1 + + // make sure we have a valid event + if (!evtName.match(/(click|mouseleave)/)) + evtName = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout' + + // add/remove slide triggers + $R[action](evtName, slideClose); // base event on resize + // need extra events for mouseleave + if (evtName === "mouseleave") { + // also close on pane.mouseleave + $P[action]("mouseleave."+ sID, slideClose); + // cancel timer when mouse moves between 'pane' and 'resizer' + $R[action]("mouseenter."+ sID, cancelMouseOut); + $P[action]("mouseenter."+ sID, cancelMouseOut); + } + + if (!enable) + timer.clear(pane+"_closeSlider"); + else if (evtName === "click" && !o.resizable) { + // IF pane is not resizable (which already has a cursor and tip) + // then set the a cursor & title/tip on resizer when sliding + $R.css("cursor", enable ? o.sliderCursor : "default"); + $R.attr("title", enable ? o.tips.Close : ""); // use Toggler-tip, eg: "Close Pane" + } + + // SUBROUTINE for mouseleave timer clearing + function cancelMouseOut (evt) { + timer.clear(pane+"_closeSlider"); + evt.stopPropagation(); + } + } + + + /** + * Hides/closes a pane if there is insufficient room - reverses this when there is room again + * MUST have already called setSizeLimits() before calling this method + * + * @param {string} pane The pane being resized + * @param {boolean=} [isOpening=false] Called from onOpen? + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [force=false] + */ +, makePaneFit = function (pane, isOpening, skipCallback, force) { + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , isSidePane = c.dir==="vert" + , hasRoom = false + ; + // special handling for center & east/west panes + if (pane === "center" || (isSidePane && s.noVerticalRoom)) { + // see if there is enough room to display the pane + // ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth); + hasRoom = (s.maxHeight >= 0); + if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now + _showPane(pane); + if ($R) $R.show(); + s.isVisible = true; + s.noRoom = false; + if (isSidePane) s.noVerticalRoom = false; + _fixIframe(pane); + } + else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now + _hidePane(pane); + if ($R) $R.hide(); + s.isVisible = false; + s.noRoom = true; + } + } + + // see if there is enough room to fit the border-pane + if (pane === "center") { + // ignore center in this block + } + else if (s.minSize <= s.maxSize) { // pane CAN fit + hasRoom = true; + if (s.size > s.maxSize) // pane is too big - shrink it + sizePane(pane, s.maxSize, skipCallback, true, force); // true = noAnimation + else if (s.size < s.minSize) // pane is too small - enlarge it + sizePane(pane, s.minSize, skipCallback, true, force); // true = noAnimation + // need s.isVisible because new pseudoClose method keeps pane visible, but off-screen + else if ($R && s.isVisible && $P.is(":visible")) { + // make sure resizer-bar is positioned correctly + // handles situation where nested layout was 'hidden' when initialized + var pos = s.size + sC.inset[c.side]; + if ($.layout.cssNum( $R, c.side ) != pos) $R.css( c.side, pos ); + } + + // if was previously hidden due to noRoom, then RESET because NOW there is room + if (s.noRoom) { + // s.noRoom state will be set by open or show + if (s.wasOpen && o.closable) { + if (o.autoReopen) + open(pane, false, true, true); // true = noAnimation, true = noAlert + else // leave the pane closed, so just update state + s.noRoom = false; + } + else + show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert + } + } + else { // !hasRoom - pane CANNOT fit + if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now... + s.noRoom = true; // update state + s.wasOpen = !s.isClosed && !s.isSliding; + if (s.isClosed){} // SKIP + else if (o.closable) // 'close' if possible + close(pane, true, true); // true = force, true = noAnimation + else // 'hide' pane if cannot just be closed + hide(pane, true); // true = noAnimation + } + } + } + + + /** + * sizePane / manualSizePane + * sizePane is called only by internal methods whenever a pane needs to be resized + * manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized' + * + * @param {(string|Object)} evt_or_pane The pane being resized + * @param {number} size The *desired* new size for this pane - will be validated + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [force=false] Force resizing even if does not seem necessary + */ +, manualSizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + // if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete... + , forceResize = force || (o.livePaneResizing && !s.isResizing) + ; + // ANY call to manualSizePane disables autoResize - ie, percentage sizing + s.autoResize = false; + // flow-through... + sizePane(pane, size, skipCallback, noAnimation, forceResize); // will animate resize if option enabled + } + + /** + * @param {(string|Object)} evt_or_pane The pane being resized + * @param {number} size The *desired* new size for this pane - will be validated + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [force=false] Force resizing even if does not seem necessary + */ +, sizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) // probably NEVER called from event? + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , side = _c[pane].side + , dimName = _c[pane].sizeType.toLowerCase() + , skipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize + , doFX = noAnimation !== true && o.animatePaneSizing + , oldSize, newSize + ; + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + // calculate 'current' min/max sizes + setSizeLimits(pane); // update pane-state + oldSize = s.size; + size = _parseSize(pane, size); // handle percentages & auto + size = max(size, _parseSize(pane, o.minSize)); + size = min(size, s.maxSize); + if (size < s.minSize) { // not enough room for pane! + queueNext(); // call before makePaneFit() because it needs the queue free + makePaneFit(pane, false, skipCallback); // will hide or close pane + return; + } + + // IF newSize is same as oldSize, then nothing to do - abort + if (!force && size === oldSize) + return queueNext(); + + s.newSize = size; + + // onresize_start callback CANNOT cancel resizing because this would break the layout! + if (!skipCallback && state.initialized && s.isVisible) + _runCallbacks("onresize_start", pane); + + // resize the pane, and make sure its visible + newSize = cssSize(pane, size); + + if (doFX && $P.is(":visible")) { // ANIMATE + var fx = $.layout.effects.size[pane] || $.layout.effects.size.all + , easing = o.fxSettings_size.easing || fx.easing + , z = options.zIndexes + , props = {}; + props[ dimName ] = newSize +'px'; + s.isMoving = true; + // overlay all elements during animation + $P.css({ zIndex: z.pane_animate }) + .show().animate( props, o.fxSpeed_size, easing, function(){ + // reset zIndex after animation + $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); + s.isMoving = false; + delete s.newSize; + sizePane_2(); // continue + queueNext(); + }); + } + else { // no animation + $P.css( dimName, newSize ); // resize pane + delete s.newSize; + // if pane is visible, then + if ($P.is(":visible")) + sizePane_2(); // continue + else { + // pane is NOT VISIBLE, so just update state data... + // when pane is *next opened*, it will have the new size + s.size = size; // update state.size + $.extend(s, elDims($P)); // update state dimensions + } + queueNext(); + }; + + }); + + // SUBROUTINE + function sizePane_2 () { + /* Panes are sometimes not sized precisely in some browsers!? + * This code will resize the pane up to 3 times to nudge the pane to the correct size + */ + var actual = dimName==='width' ? $P.outerWidth() : $P.outerHeight() + , tries = [{ + pane: pane + , count: 1 + , target: size + , actual: actual + , correct: (size === actual) + , attempt: size + , cssSize: newSize + }] + , lastTry = tries[0] + , thisTry = {} + , msg = 'Inaccurate size after resizing the '+ pane +'-pane.' + ; + while ( !lastTry.correct ) { + thisTry = { pane: pane, count: lastTry.count+1, target: size }; + + if (lastTry.actual > size) + thisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size)); + else // lastTry.actual < size + thisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual)); + + thisTry.cssSize = cssSize(pane, thisTry.attempt); + $P.css( dimName, thisTry.cssSize ); + + thisTry.actual = dimName=='width' ? $P.outerWidth() : $P.outerHeight(); + thisTry.correct = (size === thisTry.actual); + + // log attempts and alert the user of this *non-fatal error* (if showDebugMessages) + if ( tries.length === 1) { + _log(msg, false, true); + _log(lastTry, false, true); + } + _log(thisTry, false, true); + // after 4 tries, is as close as its gonna get! + if (tries.length > 3) break; + + tries.push( thisTry ); + lastTry = tries[ tries.length - 1 ]; + } + // END TESTING CODE + + // update pane-state dimensions + s.size = size; + $.extend(s, elDims($P)); + + if (s.isVisible && $P.is(":visible")) { + // reposition the resizer-bar + if ($R) $R.css( side, size + sC.inset[side] ); + // resize the content-div + sizeContent(pane); + } + + if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible) + _runCallbacks("onresize_end", pane); + + // resize all the adjacent panes, and adjust their toggler buttons + // when skipCallback passed, it means the controlling method will handle 'other panes' + if (!skipCallback) { + // also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize + if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "" : "center", skipResizeWhileDragging, force); + sizeHandles(); + } + + // if opposite-pane was autoClosed, see if it can be autoOpened now + var altPane = _c.oppositeEdge[pane]; + if (size < oldSize && state[ altPane ].noRoom) { + setSizeLimits( altPane ); + makePaneFit( altPane, false, skipCallback ); + } + + // DEBUG - ALERT user/developer so they know there was a sizing problem + if (tries.length > 1) + _log(msg +'\nSee the Error Console for details.', true, true); + } + } + + /** + * @see initPanes(), sizePane(), resizeAll(), open(), close(), hide() + * @param {(Array.|string)} panes The pane(s) being resized, comma-delmited string + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [force=false] + */ +, sizeMidPanes = function (panes, skipCallback, force) { + panes = (panes ? panes : "east,west,center").split(","); + + $.each(panes, function (i, pane) { + if (!$Ps[pane]) return; // NO PANE - skip + var + o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , isCenter= (pane=="center") + , hasRoom = true + , CSS = {} + // if pane is not visible, show it invisibly NOW rather than for *each call* in this script + , visCSS = $.layout.showInvisibly($P) + + , newCenter = calcNewCenterPaneDims() + ; + + // update pane-state dimensions + $.extend(s, elDims($P)); + + if (pane === "center") { + if (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight) { + $P.css(visCSS); + return true; // SKIP - pane already the correct size + } + // set state for makePaneFit() logic + $.extend(s, cssMinDims(pane), { + maxWidth: newCenter.width + , maxHeight: newCenter.height + }); + CSS = newCenter; + s.newWidth = CSS.width; + s.newHeight = CSS.height; + // convert OUTER width/height to CSS width/height + CSS.width = cssW($P, CSS.width); + // NEW - allow pane to extend 'below' visible area rather than hide it + CSS.height = cssH($P, CSS.height); + hasRoom = CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW + + // during layout init, try to shrink east/west panes to make room for center + if (!state.initialized && o.minWidth > newCenter.width) { + var + reqPx = o.minWidth - s.outerWidth + , minE = options.east.minSize || 0 + , minW = options.west.minSize || 0 + , sizeE = state.east.size + , sizeW = state.west.size + , newE = sizeE + , newW = sizeW + ; + if (reqPx > 0 && state.east.isVisible && sizeE > minE) { + newE = max( sizeE-minE, sizeE-reqPx ); + reqPx -= sizeE-newE; + } + if (reqPx > 0 && state.west.isVisible && sizeW > minW) { + newW = max( sizeW-minW, sizeW-reqPx ); + reqPx -= sizeW-newW; + } + // IF we found enough extra space, then resize the border panes as calculated + if (reqPx === 0) { + if (sizeE && sizeE != minE) + sizePane('east', newE, true, true, force); // true = skipCallback/noAnimation - initPanes will handle when done + if (sizeW && sizeW != minW) + sizePane('west', newW, true, true, force); // true = skipCallback/noAnimation + // now start over! + sizeMidPanes('center', skipCallback, force); + $P.css(visCSS); + return; // abort this loop + } + } + } + else { // for east and west, set only the height, which is same as center height + // set state.min/maxWidth/Height for makePaneFit() logic + if (s.isVisible && !s.noVerticalRoom) + $.extend(s, elDims($P), cssMinDims(pane)) + if (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight) { + $P.css(visCSS); + return true; // SKIP - pane already the correct size + } + // east/west have same top, bottom & height as center + CSS.top = newCenter.top; + CSS.bottom = newCenter.bottom; + s.newSize = newCenter.height + // NEW - allow pane to extend 'below' visible area rather than hide it + CSS.height = cssH($P, newCenter.height); + s.maxHeight = CSS.height; + hasRoom = (s.maxHeight >= 0); // ALWAYS TRUE NOW + if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic + } + + if (hasRoom) { + // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized + if (!skipCallback && state.initialized) + _runCallbacks("onresize_start", pane); + + $P.css(CSS); // apply the CSS to pane + if (pane !== "center") + sizeHandles(pane); // also update resizer length + if (s.noRoom && !s.isClosed && !s.isHidden) + makePaneFit(pane); // will re-open/show auto-closed/hidden pane + if (s.isVisible) { + $.extend(s, elDims($P)); // update pane dimensions + if (state.initialized) sizeContent(pane); // also resize the contents, if exists + } + } + else if (!s.noRoom && s.isVisible) // no room for pane + makePaneFit(pane); // will hide or close pane + + // reset visibility, if necessary + $P.css(visCSS); + + delete s.newSize; + delete s.newWidth; + delete s.newHeight; + + if (!s.isVisible) + return true; // DONE - next pane + + /* + * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes + * Normally these panes have only 'left' & 'right' positions so pane auto-sizes + * ALSO required when pane is an IFRAME because will NOT default to 'full width' + * TODO: Can I use width:100% for a north/south iframe? + * TODO: Sounds like a job for $P.outerWidth( sC.innerWidth ) SETTER METHOD + */ + if (pane === "center") { // finished processing midPanes + var fix = browser.isIE6 || !browser.boxModel; + if ($Ps.north && (fix || state.north.tagName=="IFRAME")) + $Ps.north.css("width", cssW($Ps.north, sC.innerWidth)); + if ($Ps.south && (fix || state.south.tagName=="IFRAME")) + $Ps.south.css("width", cssW($Ps.south, sC.innerWidth)); + } + + // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized + if (!skipCallback && state.initialized) + _runCallbacks("onresize_end", pane); + }); + } + + + /** + * @see window.onresize(), callbacks or custom code + * @param {(Object|boolean)=} evt_or_refresh If 'true', then also reset pane-positioning + */ +, resizeAll = function (evt_or_refresh) { + var oldW = sC.innerWidth + , oldH = sC.innerHeight + ; + // stopPropagation if called by trigger("layoutdestroy") - use evtPane utility + evtPane(evt_or_refresh); + + // cannot size layout when 'container' is hidden or collapsed + if (!$N.is(":visible")) return; + + if (!state.initialized) { + _initLayoutElements(); + return; // no need to resize since we just initialized! + } + + if (evt_or_refresh === true && $.isPlainObject(options.outset)) { + // update container CSS in case outset option has changed + $N.css( options.outset ); + } + // UPDATE container dimensions + $.extend(sC, elDims( $N, options.inset )); + if (!sC.outerHeight) return; + + // if 'true' passed, refresh pane & handle positioning too + if (evt_or_refresh === true) { + setPanePosition(); + } + + // onresizeall_start will CANCEL resizing if returns false + // state.container has already been set, so user can access this info for calcuations + if (false === _runCallbacks("onresizeall_start")) return false; + + var // see if container is now 'smaller' than before + shrunkH = (sC.innerHeight < oldH) + , shrunkW = (sC.innerWidth < oldW) + , $P, o, s + ; + // NOTE special order for sizing: S-N-E-W + $.each(["south","north","east","west"], function (i, pane) { + if (!$Ps[pane]) return; // no pane - SKIP + o = options[pane]; + s = state[pane]; + if (s.autoResize && s.size != o.size) // resize pane to original size set in options + sizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize + else { + setSizeLimits(pane); + makePaneFit(pane, false, true, true); // true=skipCallback/forceResize + } + }); + + sizeMidPanes("", true, true); // true=skipCallback/forceResize + sizeHandles(); // reposition the toggler elements + + // trigger all individual pane callbacks AFTER layout has finished resizing + $.each(_c.allPanes, function (i, pane) { + $P = $Ps[pane]; + if (!$P) return; // SKIP + if (state[pane].isVisible) // undefined for non-existent panes + _runCallbacks("onresize_end", pane); // callback - if exists + }); + + _runCallbacks("onresizeall_end"); + //_triggerLayoutEvent(pane, 'resizeall'); + } + + /** + * Whenever a pane resizes or opens that has a nested layout, trigger resizeAll + * + * @param {(string|Object)} evt_or_pane The pane just resized or opened + */ +, resizeChildren = function (evt_or_pane, skipRefresh) { + var pane = evtPane.call(this, evt_or_pane); + + if (!options[pane].resizeChildren) return; + + // ensure the pane-children are up-to-date + if (!skipRefresh) refreshChildren( pane ); + var pC = children[pane]; + if ($.isPlainObject( pC )) { + // resize one or more children + $.each( pC, function (key, child) { + child.resizeAll(); + }); + } + } + + /** + * IF pane has a content-div, then resize all elements inside pane to fit pane-height + * + * @param {(string|Object)} evt_or_panes The pane(s) being resized + * @param {boolean=} [remeasure=false] Should the content (header/footer) be remeasured? + */ +, sizeContent = function (evt_or_panes, remeasure) { + if (!isInitialized()) return; + + var panes = evtPane.call(this, evt_or_panes); + panes = panes ? panes.split(",") : _c.allPanes; + + $.each(panes, function (idx, pane) { + var + $P = $Ps[pane] + , $C = $Cs[pane] + , o = options[pane] + , s = state[pane] + , m = s.content // m = measurements + ; + if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip + + // if content-element was REMOVED, update OR remove the pointer + if (!$C.length) { + initContent(pane, false); // false = do NOT sizeContent() - already there! + if (!$C) return; // no replacement element found - pointer have been removed + } + + // onsizecontent_start will CANCEL resizing if returns false + if (false === _runCallbacks("onsizecontent_start", pane)) return; + + // skip re-measuring offsets if live-resizing + if ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) { + _measure(); + // if any footers are below pane-bottom, they may not measure correctly, + // so allow pane overflow and re-measure + if (m.hiddenFooters > 0 && $P.css("overflow") === "hidden") { + $P.css("overflow", "visible"); + _measure(); // remeasure while overflowing + $P.css("overflow", "hidden"); + } + } + // NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders + var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom); + + if (!$C.is(":visible") || m.height != newH) { + // size the Content element to fit new pane-size - will autoHide if not enough room + setOuterHeight($C, newH, true); // true=autoHide + m.height = newH; // save new height + }; + + if (state.initialized) + _runCallbacks("onsizecontent_end", pane); + + function _below ($E) { + return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0)); + }; + + function _measure () { + var + ignore = options[pane].contentIgnoreSelector + , $Fs = $C.nextAll().not(".ui-layout-mask").not(ignore || ":lt(0)") // not :lt(0) = ALL + , $Fs_vis = $Fs.filter(':visible') + , $F = $Fs_vis.filter(':last') + ; + m = { + top: $C[0].offsetTop + , height: $C.outerHeight() + , numFooters: $Fs.length + , hiddenFooters: $Fs.length - $Fs_vis.length + , spaceBelow: 0 // correct if no content footer ($E) + } + m.spaceAbove = m.top; // just for state - not used in calc + m.bottom = m.top + m.height; + if ($F.length) + //spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom) + m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F); + else // no footer - check marginBottom on Content element itself + m.spaceBelow = _below($C); + }; + }); + } + + + /** + * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary + * + * @see initHandles(), open(), close(), resizeAll() + * @param {(string|Object)=} evt_or_panes The pane(s) being resized + */ +, sizeHandles = function (evt_or_panes) { + var panes = evtPane.call(this, evt_or_panes) + panes = panes ? panes.split(",") : _c.borderPanes; + + $.each(panes, function (i, pane) { + var + o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , $TC + ; + if (!$P || !$R) return; + + var + dir = _c[pane].dir + , _state = (s.isClosed ? "_closed" : "_open") + , spacing = o["spacing"+ _state] + , togAlign = o["togglerAlign"+ _state] + , togLen = o["togglerLength"+ _state] + , paneLen + , left + , offset + , CSS = {} + ; + + if (spacing === 0) { + $R.hide(); + return; + } + else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason + $R.show(); // in case was previously hidden + + // Resizer Bar is ALWAYS same width/height of pane it is attached to + if (dir === "horz") { // north/south + //paneLen = $P.outerWidth(); // s.outerWidth || + paneLen = sC.innerWidth; // handle offscreen-panes + s.resizerLength = paneLen; + left = $.layout.cssNum($P, "left") + $R.css({ + width: cssW($R, paneLen) // account for borders & padding + , height: cssH($R, spacing) // ditto + , left: left > -9999 ? left : sC.inset.left // handle offscreen-panes + }); + } + else { // east/west + paneLen = $P.outerHeight(); // s.outerHeight || + s.resizerLength = paneLen; + $R.css({ + height: cssH($R, paneLen) // account for borders & padding + , width: cssW($R, spacing) // ditto + , top: sC.inset.top + getPaneSize("north", true) // TODO: what if no North pane? + //, top: $.layout.cssNum($Ps["center"], "top") + }); + } + + // remove hover classes + removeHover( o, $R ); + + if ($T) { + if (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) { + $T.hide(); // always HIDE the toggler when 'sliding' + return; + } + else + $T.show(); // in case was previously hidden + + if (!(togLen > 0) || togLen === "100%" || togLen > paneLen) { + togLen = paneLen; + offset = 0; + } + else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed + if (isStr(togAlign)) { + switch (togAlign) { + case "top": + case "left": offset = 0; + break; + case "bottom": + case "right": offset = paneLen - togLen; + break; + case "middle": + case "center": + default: offset = round((paneLen - togLen) / 2); // 'default' catches typos + } + } + else { // togAlign = number + var x = parseInt(togAlign, 10); // + if (togAlign >= 0) offset = x; + else offset = paneLen - togLen + x; // NOTE: x is negative! + } + } + + if (dir === "horz") { // north/south + var width = cssW($T, togLen); + $T.css({ + width: width // account for borders & padding + , height: cssH($T, spacing) // ditto + , left: offset // TODO: VERIFY that toggler positions correctly for ALL values + , top: 0 + }); + // CENTER the toggler content SPAN + $T.children(".content").each(function(){ + $TC = $(this); + $TC.css("marginLeft", round((width-$TC.outerWidth())/2)); // could be negative + }); + } + else { // east/west + var height = cssH($T, togLen); + $T.css({ + height: height // account for borders & padding + , width: cssW($T, spacing) // ditto + , top: offset // POSITION the toggler + , left: 0 + }); + // CENTER the toggler content SPAN + $T.children(".content").each(function(){ + $TC = $(this); + $TC.css("marginTop", round((height-$TC.outerHeight())/2)); // could be negative + }); + } + + // remove ALL hover classes + removeHover( 0, $T ); + } + + // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now + if (!state.initialized && (o.initHidden || s.noRoom)) { + $R.hide(); + if ($T) $T.hide(); + } + }); + } + + + /** + * @param {(string|Object)} evt_or_pane + */ +, enableClosable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $T = $Ts[pane] + , o = options[pane] + ; + if (!$T) return; + o.closable = true; + $T .bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); }) + .css("visibility", "visible") + .css("cursor", "pointer") + .attr("title", state[pane].isClosed ? o.tips.Open : o.tips.Close) // may be blank + .show(); + } + /** + * @param {(string|Object)} evt_or_pane + * @param {boolean=} [hide=false] + */ +, disableClosable = function (evt_or_pane, hide) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $T = $Ts[pane] + ; + if (!$T) return; + options[pane].closable = false; + // is closable is disable, then pane MUST be open! + if (state[pane].isClosed) open(pane, false, true); + $T .unbind("."+ sID) + .css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues + .css("cursor", "default") + .attr("title", ""); + } + + + /** + * @param {(string|Object)} evt_or_pane + */ +, enableSlidable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R || !$R.data('draggable')) return; + options[pane].slidable = true; + if (state[pane].isClosed) + bindStartSlidingEvents(pane, true); + } + /** + * @param {(string|Object)} evt_or_pane + */ +, disableSlidable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R) return; + options[pane].slidable = false; + if (state[pane].isSliding) + close(pane, false, true); + else { + bindStartSlidingEvents(pane, false); + $R .css("cursor", "default") + .attr("title", ""); + removeHover(null, $R[0]); // in case currently hovered + } + } + + + /** + * @param {(string|Object)} evt_or_pane + */ +, enableResizable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + , o = options[pane] + ; + if (!$R || !$R.data('draggable')) return; + o.resizable = true; + $R.draggable("enable"); + if (!state[pane].isClosed) + $R .css("cursor", o.resizerCursor) + .attr("title", o.tips.Resize); + } + /** + * @param {(string|Object)} evt_or_pane + */ +, disableResizable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R || !$R.data('draggable')) return; + options[pane].resizable = false; + $R .draggable("disable") + .css("cursor", "default") + .attr("title", ""); + removeHover(null, $R[0]); // in case currently hovered + } + + + /** + * Move a pane from source-side (eg, west) to target-side (eg, east) + * If pane exists on target-side, move that to source-side, ie, 'swap' the panes + * + * @param {(string|Object)} evt_or_pane1 The pane/edge being swapped + * @param {string} pane2 ditto + */ +, swapPanes = function (evt_or_pane1, pane2) { + if (!isInitialized()) return; + var pane1 = evtPane.call(this, evt_or_pane1); + // change state.edge NOW so callbacks can know where pane is headed... + state[pane1].edge = pane2; + state[pane2].edge = pane1; + // run these even if NOT state.initialized + if (false === _runCallbacks("onswap_start", pane1) + || false === _runCallbacks("onswap_start", pane2) + ) { + state[pane1].edge = pane1; // reset + state[pane2].edge = pane2; + return; + } + + var + oPane1 = copy( pane1 ) + , oPane2 = copy( pane2 ) + , sizes = {} + ; + sizes[pane1] = oPane1 ? oPane1.state.size : 0; + sizes[pane2] = oPane2 ? oPane2.state.size : 0; + + // clear pointers & state + $Ps[pane1] = false; + $Ps[pane2] = false; + state[pane1] = {}; + state[pane2] = {}; + + // ALWAYS remove the resizer & toggler elements + if ($Ts[pane1]) $Ts[pane1].remove(); + if ($Ts[pane2]) $Ts[pane2].remove(); + if ($Rs[pane1]) $Rs[pane1].remove(); + if ($Rs[pane2]) $Rs[pane2].remove(); + $Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false; + + // transfer element pointers and data to NEW Layout keys + move( oPane1, pane2 ); + move( oPane2, pane1 ); + + // cleanup objects + oPane1 = oPane2 = sizes = null; + + // make panes 'visible' again + if ($Ps[pane1]) $Ps[pane1].css(_c.visible); + if ($Ps[pane2]) $Ps[pane2].css(_c.visible); + + // fix any size discrepancies caused by swap + resizeAll(); + + // run these even if NOT state.initialized + _runCallbacks("onswap_end", pane1); + _runCallbacks("onswap_end", pane2); + + return; + + function copy (n) { // n = pane + var + $P = $Ps[n] + , $C = $Cs[n] + ; + return !$P ? false : { + pane: n + , P: $P ? $P[0] : false + , C: $C ? $C[0] : false + , state: $.extend(true, {}, state[n]) + , options: $.extend(true, {}, options[n]) + } + }; + + function move (oPane, pane) { + if (!oPane) return; + var + P = oPane.P + , C = oPane.C + , oldPane = oPane.pane + , c = _c[pane] + // save pane-options that should be retained + , s = $.extend(true, {}, state[pane]) + , o = options[pane] + // RETAIN side-specific FX Settings - more below + , fx = { resizerCursor: o.resizerCursor } + , re, size, pos + ; + $.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) { + fx[k +"_open"] = o[k +"_open"]; + fx[k +"_close"] = o[k +"_close"]; + fx[k +"_size"] = o[k +"_size"]; + }); + + // update object pointers and attributes + $Ps[pane] = $(P) + .data({ + layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + }) + .css(_c.hidden) + .css(c.cssReq) + ; + $Cs[pane] = C ? $(C) : false; + + // set options and state + options[pane] = $.extend(true, {}, oPane.options, fx); + state[pane] = $.extend(true, {}, oPane.state); + + // change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west + re = new RegExp(o.paneClass +"-"+ oldPane, "g"); + P.className = P.className.replace(re, o.paneClass +"-"+ pane); + + // ALWAYS regenerate the resizer & toggler elements + initHandles(pane); // create the required resizer & toggler + + // if moving to different orientation, then keep 'target' pane size + if (c.dir != _c[oldPane].dir) { + size = sizes[pane] || 0; + setSizeLimits(pane); // update pane-state + size = max(size, state[pane].minSize); + // use manualSizePane to disable autoResize - not useful after panes are swapped + manualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation + } + else // move the resizer here + $Rs[pane].css(c.side, sC.inset[c.side] + (state[pane].isVisible ? getPaneSize(pane) : 0)); + + + // ADD CLASSNAMES & SLIDE-BINDINGS + if (oPane.state.isVisible && !s.isVisible) + setAsOpen(pane, true); // true = skipCallback + else { + setAsClosed(pane); + bindStartSlidingEvents(pane, true); // will enable events IF option is set + } + + // DESTROY the object + oPane = null; + }; + } + + + /** + * INTERNAL method to sync pin-buttons when pane is opened or closed + * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes + * + * @see open(), setAsOpen(), setAsClosed() + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin True means set the pin 'down', False means 'up' + */ +, syncPinBtns = function (pane, doPin) { + if ($.layout.plugins.buttons) + $.each(state[pane].pins, function (i, selector) { + $.layout.buttons.setPinState(Instance, $(selector), pane, doPin); + }); + } + +; // END var DECLARATIONS + + /** + * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed + * + * @see document.keydown() + */ + function keyDown (evt) { + if (!evt) return true; + var code = evt.keyCode; + if (code < 33) return true; // ignore special keys: ENTER, TAB, etc + + var + PANE = { + 38: "north" // Up Cursor - $.ui.keyCode.UP + , 40: "south" // Down Cursor - $.ui.keyCode.DOWN + , 37: "west" // Left Cursor - $.ui.keyCode.LEFT + , 39: "east" // Right Cursor - $.ui.keyCode.RIGHT + } + , ALT = evt.altKey // no worky! + , SHIFT = evt.shiftKey + , CTRL = evt.ctrlKey + , CURSOR = (CTRL && code >= 37 && code <= 40) + , o, k, m, pane + ; + + if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey + pane = PANE[code]; + else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey + $.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey + o = options[p]; + k = o.customHotkey; + m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT" + if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches + if (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches + pane = p; + return false; // BREAK + } + } + }); + + // validate pane + if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden) + return true; + + toggle(pane); + + evt.stopPropagation(); + evt.returnValue = false; // CANCEL key + return false; + }; + + +/* + * ###################################### + * UTILITY METHODS + * called externally or by initButtons + * ###################################### + */ + + /** + * Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work + * + * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event + */ + function allowOverflow (el) { + if (!isInitialized()) return; + if (this && this.tagName) el = this; // BOUND to element + var $P; + if (isStr(el)) + $P = $Ps[el]; + else if ($(el).data("layoutRole")) + $P = $(el); + else + $(el).parents().each(function(){ + if ($(this).data("layoutRole")) { + $P = $(this); + return false; // BREAK + } + }); + if (!$P || !$P.length) return; // INVALID + + var + pane = $P.data("layoutEdge") + , s = state[pane] + ; + + // if pane is already raised, then reset it before doing it again! + // this would happen if allowOverflow is attached to BOTH the pane and an element + if (s.cssSaved) + resetOverflow(pane); // reset previous CSS before continuing + + // if pane is raised by sliding or resizing, or its closed, then abort + if (s.isSliding || s.isResizing || s.isClosed) { + s.cssSaved = false; + return; + } + + var + newCSS = { zIndex: (options.zIndexes.resizer_normal + 1) } + , curCSS = {} + , of = $P.css("overflow") + , ofX = $P.css("overflowX") + , ofY = $P.css("overflowY") + ; + // determine which, if any, overflow settings need to be changed + if (of != "visible") { + curCSS.overflow = of; + newCSS.overflow = "visible"; + } + if (ofX && !ofX.match(/(visible|auto)/)) { + curCSS.overflowX = ofX; + newCSS.overflowX = "visible"; + } + if (ofY && !ofY.match(/(visible|auto)/)) { + curCSS.overflowY = ofX; + newCSS.overflowY = "visible"; + } + + // save the current overflow settings - even if blank! + s.cssSaved = curCSS; + + // apply new CSS to raise zIndex and, if necessary, make overflow 'visible' + $P.css( newCSS ); + + // make sure the zIndex of all other panes is normal + $.each(_c.allPanes, function(i, p) { + if (p != pane) resetOverflow(p); + }); + + }; + /** + * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event + */ + function resetOverflow (el) { + if (!isInitialized()) return; + if (this && this.tagName) el = this; // BOUND to element + var $P; + if (isStr(el)) + $P = $Ps[el]; + else if ($(el).data("layoutRole")) + $P = $(el); + else + $(el).parents().each(function(){ + if ($(this).data("layoutRole")) { + $P = $(this); + return false; // BREAK + } + }); + if (!$P || !$P.length) return; // INVALID + + var + pane = $P.data("layoutEdge") + , s = state[pane] + , CSS = s.cssSaved || {} + ; + // reset the zIndex + if (!s.isSliding && !s.isResizing) + $P.css("zIndex", options.zIndexes.pane_normal); + + // reset Overflow - if necessary + $P.css( CSS ); + + // clear var + s.cssSaved = false; + }; + +/* + * ##################### + * CREATE/RETURN LAYOUT + * ##################### + */ + + // validate that container exists + var $N = $(this).eq(0); // FIRST matching Container element + if (!$N.length) { + return _log( options.errors.containerMissing ); + }; + + // Users retrieve Instance of a layout with: $N.layout() OR $N.data("layout") + // return the Instance-pointer if layout has already been initialized + if ($N.data("layoutContainer") && $N.data("layout")) + return $N.data("layout"); // cached pointer + + // init global vars + var + $Ps = {} // Panes x5 - set in initPanes() + , $Cs = {} // Content x5 - set in initPanes() + , $Rs = {} // Resizers x4 - set in initHandles() + , $Ts = {} // Togglers x4 - set in initHandles() + , $Ms = $([]) // Masks - up to 2 masks per pane (IFRAME + DIV) + // aliases for code brevity + , sC = state.container // alias for easy access to 'container dimensions' + , sID = state.id // alias for unique layout ID/namespace - eg: "layout435" + ; + + // create Instance object to expose data & option Properties, and primary action Methods + var Instance = { + // layout data + options: options // property - options hash + , state: state // property - dimensions hash + // object pointers + , container: $N // property - object pointers for layout container + , panes: $Ps // property - object pointers for ALL Panes: panes.north, panes.center + , contents: $Cs // property - object pointers for ALL Content: contents.north, contents.center + , resizers: $Rs // property - object pointers for ALL Resizers, eg: resizers.north + , togglers: $Ts // property - object pointers for ALL Togglers, eg: togglers.north + // border-pane open/close + , hide: hide // method - ditto + , show: show // method - ditto + , toggle: toggle // method - pass a 'pane' ("north", "west", etc) + , open: open // method - ditto + , close: close // method - ditto + , slideOpen: slideOpen // method - ditto + , slideClose: slideClose // method - ditto + , slideToggle: slideToggle // method - ditto + // pane actions + , setSizeLimits: setSizeLimits // method - pass a 'pane' - update state min/max data + , _sizePane: sizePane // method -intended for user by plugins only! + , sizePane: manualSizePane // method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto' + , sizeContent: sizeContent // method - pass a 'pane' + , swapPanes: swapPanes // method - pass TWO 'panes' - will swap them + , showMasks: showMasks // method - pass a 'pane' OR list of panes - default = all panes with mask option set + , hideMasks: hideMasks // method - ditto' + // pane element methods + , initContent: initContent // method - ditto + , addPane: addPane // method - pass a 'pane' + , removePane: removePane // method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem + , createChildren: createChildren // method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].children + , refreshChildren: refreshChildren // method - pass a 'pane' and a layout-instance + // special pane option setting + , enableClosable: enableClosable // method - pass a 'pane' + , disableClosable: disableClosable // method - ditto + , enableSlidable: enableSlidable // method - ditto + , disableSlidable: disableSlidable // method - ditto + , enableResizable: enableResizable // method - ditto + , disableResizable: disableResizable// method - ditto + // utility methods for panes + , allowOverflow: allowOverflow // utility - pass calling element (this) + , resetOverflow: resetOverflow // utility - ditto + // layout control + , destroy: destroy // method - no parameters + , initPanes: isInitialized // method - no parameters + , resizeAll: resizeAll // method - no parameters + // callback triggering + , runCallbacks: _runCallbacks // method - pass evtName & pane (if a pane-event), eg: trigger("onopen", "west") + // alias collections of options, state and children - created in addPane and extended elsewhere + , hasParentLayout: false // set by initContainer() + , children: children // pointers to child-layouts, eg: Instance.children.west.layoutName + , north: false // alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], children: children[pane] } + , south: false // ditto + , west: false // ditto + , east: false // ditto + , center: false // ditto + }; + + // create the border layout NOW + if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation + return null; + else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later + return Instance; // return the Instance object + +} + + +/* OLD versions of jQuery only set $.support.boxModel after page is loaded + * so if this is IE, use support.boxModel to test for quirks-mode (ONLY IE changes boxModel). + */ +$(function(){ + var b = $.layout.browser; + if (b.msie) b.boxModel = $.support.boxModel; +}); + + +})( jQuery ); +// END Layout - keep internal vars internal! + + + +// START Plugins - shared wrapper, no global vars +(function ($) { + + +/** + * jquery.layout.state 1.0 + * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ + * + * Copyright (c) 2012 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @requires: UI Layout 1.3.0.rc30.1 or higher + * @requires: $.ui.cookie (above) + * + * @see: http://groups.google.com/group/jquery-ui-layout + */ +/* + * State-management options stored in options.stateManagement, which includes a .cookie hash + * Default options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden + * + * // STATE/COOKIE OPTIONS + * @example $(el).layout({ + stateManagement: { + enabled: true + , stateKeys: "east.size,west.size,east.isClosed,west.isClosed" + , cookie: { name: "appLayout", path: "/" } + } + }) + * @example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies + * @example $(el).layout({ stateManagement__cookie: { name: "appLayout", path: "/" } }) + * @example $(el).layout({ stateManagement__cookie__name: "appLayout", stateManagement__cookie__path: "/" }) + * + * // STATE/COOKIE METHODS + * @example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} ); + * @example myLayout.loadCookie(); + * @example myLayout.deleteCookie(); + * @example var JSON = myLayout.readState(); // CURRENT Layout State + * @example var JSON = myLayout.readCookie(); // SAVED Layout State (from cookie) + * @example var JSON = myLayout.state.stateData; // LAST LOADED Layout State (cookie saved in layout.state hash) + * + * CUSTOM STATE-MANAGEMENT (eg, saved in a database) + * @example var JSON = myLayout.readState( "west.isClosed,north.size,south.isHidden" ); + * @example myLayout.loadState( JSON ); + */ + +/** + * UI COOKIE UTILITY + * + * A $.cookie OR $.ui.cookie namespace *should be standard*, but until then... + * This creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin + * NOTE: This utility is REQUIRED by the layout.state plugin + * + * Cookie methods in Layout are created as part of State Management + */ +if (!$.ui) $.ui = {}; +$.ui.cookie = { + + // cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6 + acceptsCookies: !!navigator.cookieEnabled + +, read: function (name) { + var + c = document.cookie + , cs = c ? c.split(';') : [] + , pair // loop var + ; + for (var i=0, n=cs.length; i < n; i++) { + pair = $.trim(cs[i]).split('='); // name=value pair + if (pair[0] == name) // found the layout cookie + return decodeURIComponent(pair[1]); + + } + return null; + } + +, write: function (name, val, cookieOpts) { + var + params = '' + , date = '' + , clear = false + , o = cookieOpts || {} + , x = o.expires + ; + if (x && x.toUTCString) + date = x; + else if (x === null || typeof x === 'number') { + date = new Date(); + if (x > 0) + date.setDate(date.getDate() + x); + else { + date.setFullYear(1970); + clear = true; + } + } + if (date) params += ';expires='+ date.toUTCString(); + if (o.path) params += ';path='+ o.path; + if (o.domain) params += ';domain='+ o.domain; + if (o.secure) params += ';secure'; + document.cookie = name +'='+ (clear ? "" : encodeURIComponent( val )) + params; // write or clear cookie + } + +, clear: function (name) { + $.ui.cookie.write(name, '', {expires: -1}); + } + +}; +// if cookie.jquery.js is not loaded, create an alias to replicate it +// this may be useful to other plugins or code dependent on that plugin +if (!$.cookie) $.cookie = function (k, v, o) { + var C = $.ui.cookie; + if (v === null) + C.clear(k); + else if (v === undefined) + return C.read(k); + else + C.write(k, v, o); +}; + + +// tell Layout that the state plugin is available +$.layout.plugins.stateManagement = true; + +// Add State-Management options to layout.defaults +$.layout.config.optionRootKeys.push("stateManagement"); +$.layout.defaults.stateManagement = { + enabled: false // true = enable state-management, even if not using cookies +, autoSave: true // Save a state-cookie when page exits? +, autoLoad: true // Load the state-cookie when Layout inits? +, animateLoad: true // animate panes when loading state into an active layout +, includeChildren: true // recurse into child layouts to include their state as well + // List state-data to save - must be pane-specific +, stateKeys: "north.size,south.size,east.size,west.size,"+ + "north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+ + "north.isHidden,south.isHidden,east.isHidden,west.isHidden" +, cookie: { + name: "" // If not specified, will use Layout.name, else just "Layout" + , domain: "" // blank = current domain + , path: "" // blank = current page, '/' = entire website + , expires: "" // 'days' to keep cookie - leave blank for 'session cookie' + , secure: false + } +}; +// Set stateManagement as a layout-option, NOT a pane-option +$.layout.optionsMap.layout.push("stateManagement"); + +/* + * State Management methods + */ +$.layout.state = { + + /** + * Get the current layout state and save it to a cookie + * + * myLayout.saveCookie( keys, cookieOpts ) + * + * @param {Object} inst + * @param {(string|Array)=} keys + * @param {Object=} cookieOpts + */ + saveCookie: function (inst, keys, cookieOpts) { + var o = inst.options + , sm = o.stateManagement + , oC = $.extend(true, {}, sm.cookie, cookieOpts || null) + , data = inst.state.stateData = inst.readState( keys || sm.stateKeys ) // read current panes-state + ; + $.ui.cookie.write( oC.name || o.name || "Layout", $.layout.state.encodeJSON(data), oC ); + return $.extend(true, {}, data); // return COPY of state.stateData data + } + + /** + * Remove the state cookie + * + * @param {Object} inst + */ +, deleteCookie: function (inst) { + var o = inst.options; + $.ui.cookie.clear( o.stateManagement.cookie.name || o.name || "Layout" ); + } + + /** + * Read & return data from the cookie - as JSON + * + * @param {Object} inst + */ +, readCookie: function (inst) { + var o = inst.options; + var c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || "Layout" ); + // convert cookie string back to a hash and return it + return c ? $.layout.state.decodeJSON(c) : {}; + } + + /** + * Get data from the cookie and USE IT to loadState + * + * @param {Object} inst + */ +, loadCookie: function (inst) { + var c = $.layout.state.readCookie(inst); // READ the cookie + if (c) { + inst.state.stateData = $.extend(true, {}, c); // SET state.stateData + inst.loadState(c); // LOAD the retrieved state + } + return c; + } + + /** + * Update layout options from the cookie, if one exists + * + * @param {Object} inst + * @param {Object=} stateData + * @param {boolean=} animate + */ +, loadState: function (inst, data, opts) { + if (!$.isPlainObject( data ) || $.isEmptyObject( data )) return; + + // normalize data & cache in the state object + data = inst.state.stateData = $.layout.transformData( data ); // panes = default subkey + + // add missing/default state-restore options + var smo = inst.options.stateManagement; + opts = $.extend({ + animateLoad: false //smo.animateLoad + , includeChildren: smo.includeChildren + }, opts ); + + if (!inst.state.initialized) { + /* + * layout NOT initialized, so just update its options + */ + // MUST remove pane.children keys before applying to options + // use a copy so we don't remove keys from original data + var o = $.extend(true, {}, data); + //delete o.center; // center has no state-data - only children + $.each($.layout.config.allPanes, function (idx, pane) { + if (o[pane]) delete o[pane].children; + }); + // update CURRENT layout-options with saved state data + $.extend(true, inst.options, o); + } + else { + /* + * layout already initialized, so modify layout's configuration + */ + var noAnimate = !opts.animateLoad + , o, c, h, state, open + ; + $.each($.layout.config.borderPanes, function (idx, pane) { + o = data[ pane ]; + if (!$.isPlainObject( o )) return; // no key, skip pane + + s = o.size; + c = o.initClosed; + h = o.initHidden; + ar = o.autoResize + state = inst.state[pane]; + open = state.isVisible; + + // reset autoResize + if (ar) + state.autoResize = ar; + // resize BEFORE opening + if (!open) + inst._sizePane(pane, s, false, false, false); // false=skipCallback/noAnimation/forceResize + // open/close as necessary - DO NOT CHANGE THIS ORDER! + if (h === true) inst.hide(pane, noAnimate); + else if (c === true) inst.close(pane, false, noAnimate); + else if (c === false) inst.open (pane, false, noAnimate); + else if (h === false) inst.show (pane, false, noAnimate); + // resize AFTER any other actions + if (open) + inst._sizePane(pane, s, false, false, noAnimate); // animate resize if option passed + }); + + /* + * RECURSE INTO CHILD-LAYOUTS + */ + if (opts.includeChildren) { + var paneStateChildren, childState; + $.each(inst.children, function (pane, paneChildren) { + paneStateChildren = data[pane] ? data[pane].children : 0; + if (paneStateChildren && paneChildren) { + $.each(paneChildren, function (stateKey, child) { + childState = paneStateChildren[stateKey]; + if (child && childState) + child.loadState( childState ); + }); + } + }); + } + } + } + + /** + * Get the *current layout state* and return it as a hash + * + * @param {Object=} inst // Layout instance to get state for + * @param {object=} [opts] // State-Managements override options + */ +, readState: function (inst, opts) { + // backward compatility + if ($.type(opts) === 'string') opts = { keys: opts }; + if (!opts) opts = {}; + var sm = inst.options.stateManagement + , ic = opts.includeChildren + , recurse = ic !== undefined ? ic : sm.includeChildren + , keys = opts.stateKeys || sm.stateKeys + , alt = { isClosed: 'initClosed', isHidden: 'initHidden' } + , state = inst.state + , panes = $.layout.config.allPanes + , data = {} + , pair, pane, key, val + , ps, pC, child, array, count, branch + ; + if ($.isArray(keys)) keys = keys.join(","); + // convert keys to an array and change delimiters from '__' to '.' + keys = keys.replace(/__/g, ".").split(','); + // loop keys and create a data hash + for (var i=0, n=keys.length; i < n; i++) { + pair = keys[i].split("."); + pane = pair[0]; + key = pair[1]; + if ($.inArray(pane, panes) < 0) continue; // bad pane! + val = state[ pane ][ key ]; + if (val == undefined) continue; + if (key=="isClosed" && state[pane]["isSliding"]) + val = true; // if sliding, then *really* isClosed + ( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val; + } + + // recurse into the child-layouts for each pane + if (recurse) { + $.each(panes, function (idx, pane) { + pC = inst.children[pane]; + ps = state.stateData[pane]; + if ($.isPlainObject( pC ) && !$.isEmptyObject( pC )) { + // ensure a key exists for this 'pane', eg: branch = data.center + branch = data[pane] || (data[pane] = {}); + if (!branch.children) branch.children = {}; + $.each( pC, function (key, child) { + // ONLY read state from an initialize layout + if ( child.state.initialized ) + branch.children[ key ] = $.layout.state.readState( child ); + // if we have PREVIOUS (onLoad) state for this child-layout, KEEP IT! + else if ( ps && ps.children && ps.children[ key ] ) { + branch.children[ key ] = $.extend(true, {}, ps.children[ key ] ); + } + }); + } + }); + } + + return data; + } + + /** + * Stringify a JSON hash so can save in a cookie or db-field + */ +, encodeJSON: function (JSON) { + return parse(JSON); + function parse (h) { + var D=[], i=0, k, v, t // k = key, v = value + , a = $.isArray(h) + ; + for (k in h) { + v = h[k]; + t = typeof v; + if (t == 'string') // STRING - add quotes + v = '"'+ v +'"'; + else if (t == 'object') // SUB-KEY - recurse into it + v = parse(v); + D[i++] = (!a ? '"'+ k +'":' : '') + v; + } + return (a ? '[' : '{') + D.join(',') + (a ? ']' : '}'); + }; + } + + /** + * Convert stringified JSON back to a hash object + * @see $.parseJSON(), adding in jQuery 1.4.1 + */ +, decodeJSON: function (str) { + try { return $.parseJSON ? $.parseJSON(str) : window["eval"]("("+ str +")") || {}; } + catch (e) { return {}; } + } + + +, _create: function (inst) { + var _ = $.layout.state + , o = inst.options + , sm = o.stateManagement + ; + // ADD State-Management plugin methods to inst + $.extend( inst, { + // readCookie - update options from cookie - returns hash of cookie data + readCookie: function () { return _.readCookie(inst); } + // deleteCookie + , deleteCookie: function () { _.deleteCookie(inst); } + // saveCookie - optionally pass keys-list and cookie-options (hash) + , saveCookie: function (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); } + // loadCookie - readCookie and use to loadState() - returns hash of cookie data + , loadCookie: function () { return _.loadCookie(inst); } + // loadState - pass a hash of state to use to update options + , loadState: function (stateData, opts) { _.loadState(inst, stateData, opts); } + // readState - returns hash of current layout-state + , readState: function (keys) { return _.readState(inst, keys); } + // add JSON utility methods too... + , encodeJSON: _.encodeJSON + , decodeJSON: _.decodeJSON + }); + + // init state.stateData key, even if plugin is initially disabled + inst.state.stateData = {}; + + // autoLoad MUST BE one of: data-array, data-hash, callback-function, or TRUE + if ( !sm.autoLoad ) return; + + // When state-data exists in the autoLoad key USE IT, + // even if stateManagement.enabled == false + if ($.isPlainObject( sm.autoLoad )) { + if (!$.isEmptyObject( sm.autoLoad )) { + inst.loadState( sm.autoLoad ); + } + } + else if ( sm.enabled ) { + // update the options from cookie or callback + // if options is a function, call it to get stateData + if ($.isFunction( sm.autoLoad )) { + var d = {}; + try { + d = sm.autoLoad( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn + } catch (e) {} + if (d && $.isPlainObject( d ) && !$.isEmptyObject( d )) + inst.loadState(d); + } + else // any other truthy value will trigger loadCookie + inst.loadCookie(); + } + } + +, _unload: function (inst) { + var sm = inst.options.stateManagement; + if (sm.enabled && sm.autoSave) { + // if options is a function, call it to save the stateData + if ($.isFunction( sm.autoSave )) { + try { + sm.autoSave( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn + } catch (e) {} + } + else // any truthy value will trigger saveCookie + inst.saveCookie(); + } + } + +}; + +// add state initialization method to Layout's onCreate array of functions +$.layout.onCreate.push( $.layout.state._create ); +$.layout.onUnload.push( $.layout.state._unload ); + + + + +/** + * jquery.layout.buttons 1.0 + * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ + * + * Copyright (c) 2012 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @requires: UI Layout 1.3.0.rc30.1 or higher + * + * @see: http://groups.google.com/group/jquery-ui-layout + * + * Docs: [ to come ] + * Tips: [ to come ] + */ + +// tell Layout that the state plugin is available +$.layout.plugins.buttons = true; + +// Add buttons options to layout.defaults +$.layout.defaults.autoBindCustomButtons = false; +// Specify autoBindCustomButtons as a layout-option, NOT a pane-option +$.layout.optionsMap.layout.push("autoBindCustomButtons"); + +/* + * Button methods + */ +$.layout.buttons = { + + /** + * Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons + * + * @see _create() + * + * @param {Object} inst Layout Instance object + */ + init: function (inst) { + var pre = "ui-layout-button-" + , layout = inst.options.name || "" + , name; + $.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) { + $.each($.layout.config.borderPanes, function (ii, pane) { + $("."+pre+action+"-"+pane).each(function(){ + // if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name' + name = $(this).data("layoutName") || $(this).attr("layoutName"); + if (name == undefined || name === layout) + inst.bindButton(this, action, pane); + }); + }); + }); + } + + /** + * Helper function to validate params received by addButton utilities + * + * Two classes are added to the element, based on the buttonClass... + * The type of button is appended to create the 2nd className: + * - ui-layout-button-pin // action btnClass + * - ui-layout-button-pin-west // action btnClass + pane + * - ui-layout-button-toggle + * - ui-layout-button-open + * - ui-layout-button-close + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * + * @return {Array.} If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null + */ +, get: function (inst, selector, pane, action) { + var $E = $(selector) + , o = inst.options + , err = o.errors.addButtonError + ; + if (!$E.length) { // element not found + $.layout.msg(err +" "+ o.errors.selector +": "+ selector, true); + } + else if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified + $.layout.msg(err +" "+ o.errors.pane +": "+ pane, true); + $E = $(""); // NO BUTTON + } + else { // VALID + var btn = o[pane].buttonClass +"-"+ action; + $E .addClass( btn +" "+ btn +"-"+ pane ) + .data("layoutName", o.name); // add layout identifier - even if blank! + } + return $E; + } + + + /** + * NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc. + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} action + * @param {string} pane + */ +, bind: function (inst, selector, action, pane) { + var _ = $.layout.buttons; + switch (action.toLowerCase()) { + case "toggle": _.addToggle (inst, selector, pane); break; + case "open": _.addOpen (inst, selector, pane); break; + case "close": _.addClose (inst, selector, pane); break; + case "pin": _.addPin (inst, selector, pane); break; + case "toggle-slide": _.addToggle (inst, selector, pane, true); break; + case "open-slide": _.addOpen (inst, selector, pane, true); break; + } + return inst; + } + + /** + * Add a custom Toggler button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * @param {boolean=} slide true = slide-open, false = pin-open + */ +, addToggle: function (inst, selector, pane, slide) { + $.layout.buttons.get(inst, selector, pane, "toggle") + .click(function(evt){ + inst.toggle(pane, !!slide); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Open button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * @param {boolean=} slide true = slide-open, false = pin-open + */ +, addOpen: function (inst, selector, pane, slide) { + $.layout.buttons.get(inst, selector, pane, "open") + .attr("title", inst.options[pane].tips.Open) + .click(function (evt) { + inst.open(pane, !!slide); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Close button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + */ +, addClose: function (inst, selector, pane) { + $.layout.buttons.get(inst, selector, pane, "close") + .attr("title", inst.options[pane].tips.Close) + .click(function (evt) { + inst.close(pane); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Pin button for a pane + * + * Four classes are added to the element, based on the paneClass for the associated pane... + * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin: + * - ui-layout-pane-pin + * - ui-layout-pane-west-pin + * - ui-layout-pane-pin-up + * - ui-layout-pane-west-pin-up + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the pin is for: 'north', 'south', etc. + */ +, addPin: function (inst, selector, pane) { + var _ = $.layout.buttons + , $E = _.get(inst, selector, pane, "pin"); + if ($E.length) { + var s = inst.state[pane]; + $E.click(function (evt) { + _.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed)); + if (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open + else inst.close( pane ); // slide-closed + evt.stopPropagation(); + }); + // add up/down pin attributes and classes + _.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding)); + // add this pin to the pane data so we can 'sync it' automatically + // PANE.pins key is an array so we can store multiple pins for each pane + s.pins.push( selector ); // just save the selector string + } + return inst; + } + + /** + * Change the class of the pin button to make it look 'up' or 'down' + * + * @see addPin(), syncPins() + * + * @param {Object} inst Layout Instance object + * @param {Array.} $Pin The pin-span element in a jQuery wrapper + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin true = set the pin 'down', false = set it 'up' + */ +, setPinState: function (inst, $Pin, pane, doPin) { + var updown = $Pin.attr("pin"); + if (updown && doPin === (updown=="down")) return; // already in correct state + var + o = inst.options[pane] + , pin = o.buttonClass +"-pin" + , side = pin +"-"+ pane + , UP = pin +"-up "+ side +"-up" + , DN = pin +"-down "+side +"-down" + ; + $Pin + .attr("pin", doPin ? "down" : "up") // logic + .attr("title", doPin ? o.tips.Unpin : o.tips.Pin) + .removeClass( doPin ? UP : DN ) + .addClass( doPin ? DN : UP ) + ; + } + + /** + * INTERNAL function to sync 'pin buttons' when pane is opened or closed + * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes + * + * @see open(), close() + * + * @param {Object} inst Layout Instance object + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin True means set the pin 'down', False means 'up' + */ +, syncPinBtns: function (inst, pane, doPin) { + // REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE + $.each(inst.state[pane].pins, function (i, selector) { + $.layout.buttons.setPinState(inst, $(selector), pane, doPin); + }); + } + + +, _load: function (inst) { + var _ = $.layout.buttons; + // ADD Button methods to Layout Instance + // Note: sel = jQuery Selector string + $.extend( inst, { + bindButton: function (sel, action, pane) { return _.bind(inst, sel, action, pane); } + // DEPRECATED METHODS + , addToggleBtn: function (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); } + , addOpenBtn: function (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); } + , addCloseBtn: function (sel, pane) { return _.addClose(inst, sel, pane); } + , addPinBtn: function (sel, pane) { return _.addPin(inst, sel, pane); } + }); + + // init state array to hold pin-buttons + for (var i=0; i<4; i++) { + var pane = $.layout.config.borderPanes[i]; + inst.state[pane].pins = []; + } + + // auto-init buttons onLoad if option is enabled + if ( inst.options.autoBindCustomButtons ) + _.init(inst); + } + +, _unload: function (inst) { + // TODO: unbind all buttons??? + } + +}; + +// add initialization method to Layout's onLoad array of functions +$.layout.onLoad.push( $.layout.buttons._load ); +//$.layout.onUnload.push( $.layout.buttons._unload ); + + + +/** + * jquery.layout.browserZoom 1.0 + * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $ + * + * Copyright (c) 2012 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @requires: UI Layout 1.3.0.rc30.1 or higher + * + * @see: http://groups.google.com/group/jquery-ui-layout + * + * TODO: Extend logic to handle other problematic zooming in browsers + * TODO: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event + */ + +// tell Layout that the plugin is available +$.layout.plugins.browserZoom = true; + +$.layout.defaults.browserZoomCheckInterval = 1000; +$.layout.optionsMap.layout.push("browserZoomCheckInterval"); + +/* + * browserZoom methods + */ +$.layout.browserZoom = { + + _init: function (inst) { + // abort if browser does not need this check + if ($.layout.browserZoom.ratio() !== false) + $.layout.browserZoom._setTimer(inst); + } + +, _setTimer: function (inst) { + // abort if layout destroyed or browser does not need this check + if (inst.destroyed) return; + var o = inst.options + , s = inst.state + // don't need check if inst has parentLayout, but check occassionally in case parent destroyed! + // MINIMUM 100ms interval, for performance + , ms = inst.hasParentLayout ? 5000 : Math.max( o.browserZoomCheckInterval, 100 ) + ; + // set the timer + setTimeout(function(){ + if (inst.destroyed || !o.resizeWithWindow) return; + var d = $.layout.browserZoom.ratio(); + if (d !== s.browserZoom) { + s.browserZoom = d; + inst.resizeAll(); + } + // set a NEW timeout + $.layout.browserZoom._setTimer(inst); + } + , ms ); + } + +, ratio: function () { + var w = window + , s = screen + , d = document + , dE = d.documentElement || d.body + , b = $.layout.browser + , v = b.version + , r, sW, cW + ; + // we can ignore all browsers that fire window.resize event onZoom + if ((b.msie && v > 8) + || !b.msie + ) return false; // don't need to track zoom + + if (s.deviceXDPI && s.systemXDPI) // syntax compiler hack + return calc(s.deviceXDPI, s.systemXDPI); + // everything below is just for future reference! + if (b.webkit && (r = d.body.getBoundingClientRect)) + return calc((r.left - r.right), d.body.offsetWidth); + if (b.webkit && (sW = w.outerWidth)) + return calc(sW, w.innerWidth); + if ((sW = s.width) && (cW = dE.clientWidth)) + return calc(sW, cW); + return false; // no match, so cannot - or don't need to - track zoom + + function calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); } + } + +}; +// add initialization method to Layout's onLoad array of functions +$.layout.onReady.push( $.layout.browserZoom._init ); + + })( jQuery ); \ No newline at end of file diff --git a/htdocs/includes/jquery/plugins/mobile/jquery.mobile-latest.min.jgz b/htdocs/includes/jquery/plugins/mobile/jquery.mobile-latest.min.jgz deleted file mode 100644 index 43f8746af6c..00000000000 Binary files a/htdocs/includes/jquery/plugins/mobile/jquery.mobile-latest.min.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd_0_5.jgz b/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd_0_5.jgz deleted file mode 100644 index 21cc5480d30..00000000000 Binary files a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd_0_5.jgz and /dev/null differ diff --git a/htdocs/includes/jquery/plugins/tiptip/jquery.tipTip.min.jgz b/htdocs/includes/jquery/plugins/tiptip/jquery.tipTip.min.jgz deleted file mode 100755 index 89019f6c730..00000000000 Binary files a/htdocs/includes/jquery/plugins/tiptip/jquery.tipTip.min.jgz and /dev/null differ diff --git a/htdocs/install/etape1.php b/htdocs/install/etape1.php index 0d7a76067d1..871068acd49 100644 --- a/htdocs/install/etape1.php +++ b/htdocs/install/etape1.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004-2012 Laurent Destailleur * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2005-2011 Regis Houssin @@ -52,6 +52,12 @@ $db_pass=GETPOST('db_pass'); $db_port=GETPOST('db_port','int'); $db_prefix=GETPOST('db_prefix','alpha'); +session_start(); // To be able to keep info into session (used for not loosing pass during navigation. pass must not transit throug parmaeters) + +// Save a flag to tell to restore input value if we do back +$_SESSION['dol_save_pass']=$db_pass; +//$_SESSION['dol_save_passroot']=$passroot; + // Now we load forced value from install.forced.php file. $useforcedwizard=false; $forcedfile="./install.forced.php"; @@ -244,24 +250,24 @@ if (! $error && $db->connected) } } -// Define $defaultCharacterSet and $defaultCollationConnection +// Define $defaultCharacterSet and $defaultDBSortingCollation if (! $error && $db->connected) { if (! empty($_POST["db_create_database"])) // If we create database, we force default value { $defaultCharacterSet=getStaticMember(get_class($db),'forcecharset'); - $defaultCollationConnection=getStaticMember(get_class($db),'forcecollate'); + $defaultDBSortingCollation=getStaticMember(get_class($db),'forcecollate'); } else // If already created, we take current value { $defaultCharacterSet=$db->getDefaultCharacterSetDatabase(); - $defaultCollationConnection=$db->getDefaultCollationDatabase(); + $defaultDBSortingCollation=$db->getDefaultCollationDatabase(); } print ''; - print ''; + print ''; $db_character_set=$defaultCharacterSet; - $db_collation=$defaultCollationConnection; + $db_collation=$defaultDBSortingCollation; } @@ -868,6 +874,15 @@ function write_conf_file($conffile) // Write params to overwrites default lib path fputs($fp,"\n"); + if (empty($force_dolibarr_lib_TCPDF_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_TCPDF_PATH=''; } + fputs($fp, '$dolibarr_lib_TCPDF_PATH=\''.$force_dolibarr_lib_TCPDF_PATH.'\';'); + fputs($fp,"\n"); + if (empty($force_dolibarr_lib_FPDF_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_FPDF_PATH=''; } + fputs($fp, '$dolibarr_lib_FPDF_PATH=\''.$force_dolibarr_lib_FPDF_PATH.'\';'); + fputs($fp,"\n"); + if (empty($force_dolibarr_lib_FPDI_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_FPDI_PATH=''; } + fputs($fp, '$dolibarr_lib_FPDI_PATH=\''.$force_dolibarr_lib_FPDI_PATH.'\';'); + fputs($fp,"\n"); if (empty($force_dolibarr_lib_ADODB_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_ADODB_PATH=''; } fputs($fp, '$dolibarr_lib_ADODB_PATH=\''.$force_dolibarr_lib_ADODB_PATH.'\';'); fputs($fp,"\n"); @@ -877,9 +892,6 @@ function write_conf_file($conffile) if (empty($force_dolibarr_lib_NUSOAP_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_NUSOAP_PATH=''; } fputs($fp, '$dolibarr_lib_NUSOAP_PATH=\''.$force_dolibarr_lib_NUSOAP_PATH.'\';'); fputs($fp,"\n"); - if (empty($force_dolibarr_lib_FPDI_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_FPDI_PATH=''; } - fputs($fp, '$dolibarr_lib_FPDI_PATH=\''.$force_dolibarr_lib_FPDI_PATH.'\';'); - fputs($fp,"\n"); if (empty($force_dolibarr_lib_PHPEXCEL_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_PHPEXCEL_PATH=''; } fputs($fp, '$dolibarr_lib_PHPEXCEL_PATH=\''.$force_dolibarr_lib_PHPEXCEL_PATH.'\';'); fputs($fp,"\n"); @@ -889,9 +901,6 @@ function write_conf_file($conffile) if (empty($force_dolibarr_lib_ODTPHP_PATHTOPCLZIP)) { fputs($fp, '//'); $force_dolibarr_lib_ODTPHP_PATHTOPCLZIP=''; } fputs($fp, '$dolibarr_lib_ODTPHP_PATHTOPCLZIP=\''.$force_dolibarr_lib_ODTPHP_PATHTOPCLZIP.'\';'); fputs($fp,"\n"); - if (empty($force_dolibarr_lib_TCPDF_PATH)) { fputs($fp, '//'); $force_dolibarr_lib_TCPDF_PATH=''; } - fputs($fp, '$dolibarr_lib_TCPDF_PATH=\''.$force_dolibarr_lib_TCPDF_PATH.'\';'); - fputs($fp,"\n"); if (empty($force_dolibarr_js_CKEDITOR)) { fputs($fp, '//'); $force_dolibarr_js_CKEDITOR=''; } fputs($fp, '$dolibarr_js_CKEDITOR=\''.$force_dolibarr_js_CKEDITOR.'\';'); fputs($fp,"\n"); diff --git a/htdocs/install/fileconf.php b/htdocs/install/fileconf.php index 2ba95dec92e..9044cb53d74 100644 --- a/htdocs/install/fileconf.php +++ b/htdocs/install/fileconf.php @@ -38,27 +38,27 @@ $langs->load("errors"); dolibarr_install_syslog("Fileconf: Entering fileconf.php page"); -// You can force preselected values of the config step of Dolibarr by adding a file -// install.forced.php into directory htdocs/install (This is the case with some wizard -// installer like DoliWamp, DoliMamp or DoliBuntu). -// We first init "forced values" to nothing. -if (! isset($force_install_noedit)) $force_install_noedit=''; // 1=To block var specific to distrib, 2 to block all technical parameters -if (! isset($force_install_type)) $force_install_type=''; -if (! isset($force_install_dbserver)) $force_install_dbserver=''; -if (! isset($force_install_port)) $force_install_port=''; -if (! isset($force_install_database)) $force_install_database=''; -if (! isset($force_install_prefix)) $force_install_prefix=''; -if (! isset($force_install_createdatabase)) $force_install_createdatabase=''; -if (! isset($force_install_databaselogin)) $force_install_databaselogin=''; -if (! isset($force_install_databasepass)) $force_install_databasepass=''; -if (! isset($force_install_databaserootlogin)) $force_install_databaserootlogin=''; -if (! isset($force_install_databaserootpass)) $force_install_databaserootpass=''; -// Now we load forced value from install.forced.php file. -$useforcedwizard=false; -$forcedfile="./install.forced.php"; -if ($conffile == "/etc/dolibarr/conf.php") $forcedfile="/etc/dolibarr/install.forced.php"; // Must be after inc.php -if (@file_exists($forcedfile)) { - $useforcedwizard=true; include_once $forcedfile; +// You can force preselected values of the config step of Dolibarr by adding a file +// install.forced.php into directory htdocs/install (This is the case with some wizard +// installer like DoliWamp, DoliMamp or DoliBuntu). +// We first init "forced values" to nothing. +if (! isset($force_install_noedit)) $force_install_noedit=''; // 1=To block var specific to distrib, 2 to block all technical parameters +if (! isset($force_install_type)) $force_install_type=''; +if (! isset($force_install_dbserver)) $force_install_dbserver=''; +if (! isset($force_install_port)) $force_install_port=''; +if (! isset($force_install_database)) $force_install_database=''; +if (! isset($force_install_prefix)) $force_install_prefix=''; +if (! isset($force_install_createdatabase)) $force_install_createdatabase=''; +if (! isset($force_install_databaselogin)) $force_install_databaselogin=''; +if (! isset($force_install_databasepass)) $force_install_databasepass=''; +if (! isset($force_install_databaserootlogin)) $force_install_databaserootlogin=''; +if (! isset($force_install_databaserootpass)) $force_install_databaserootpass=''; +// Now we load forced value from install.forced.php file. +$useforcedwizard=false; +$forcedfile="./install.forced.php"; +if ($conffile == "/etc/dolibarr/conf.php") $forcedfile="/etc/dolibarr/install.forced.php"; // Must be after inc.php +if (@file_exists($forcedfile)) { + $useforcedwizard=true; include_once $forcedfile; } //$force_install_message='This is the message'; @@ -69,6 +69,8 @@ if (@file_exists($forcedfile)) { * View */ +session_start(); // To be able to keep info into session (used for not loosing pass during navigation. pass must not transit throug parmaeters) + pHeader($langs->trans("ConfigurationFile"),"etape1","set","",(empty($force_dolibarr_js_JQUERY)?'':$force_dolibarr_js_JQUERY.'/')); // Test if we can run a first install process @@ -407,7 +409,8 @@ if (! empty($force_install_message)) @@ -438,7 +441,7 @@ if (! empty($force_install_message)) - trans("Login"); ?> + trans("Login"); ?> @@ -455,7 +458,7 @@ if (! empty($force_install_message)) - trans("Password"); ?> + trans("Password"); ?> load("main"); $langs->load("admin"); + $jquerytheme='smoothness'; + if ($forcejqueryurl) { $jQueryCustomPath = $forcejqueryurl; @@ -327,8 +330,6 @@ function pHeader($subtitle,$next,$action='set',$param='',$forcejqueryurl='') $jQueryUiCustomPath = (defined('JS_JQUERY_UI') && constant('JS_JQUERY_UI')) ? JS_JQUERY_UI : false; } - $jquerytheme='smoothness'; - // We force the content charset header("Content-type: text/html; charset=".$conf->file->character_set_client); diff --git a/htdocs/install/mysql/data/llx_c_actioncomm.sql b/htdocs/install/mysql/data/llx_c_actioncomm.sql index 618e7ff6224..3cceb0dc077 100644 --- a/htdocs/install/mysql/data/llx_c_actioncomm.sql +++ b/htdocs/install/mysql/data/llx_c_actioncomm.sql @@ -30,15 +30,16 @@ -- Types action comm -- -delete from llx_c_actioncomm where id in (1,2,3,4,5,8,9,10,30,31,50); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 1, 'AC_TEL', 'system', 'Phone call' ,NULL, 2); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 2, 'AC_FAX', 'system', 'Send Fax' ,NULL, 3); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 3, 'AC_PROP', 'systemauto', 'Send commercial proposal by email' ,'propal', 10); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 4, 'AC_EMAIL', 'system', 'Send Email' ,NULL, 4); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 5, 'AC_RDV', 'system', 'Rendez-vous' ,NULL, 1); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 8, 'AC_COM', 'systemauto', 'Send customer order by email' ,'order', 8); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 9, 'AC_FAC', 'systemauto', 'Send customer invoice by email' ,'invoice', 6); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 10, 'AC_SHIP', 'systemauto', 'Send shipping by email' ,'shipping', 11); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 30, 'AC_SUP_ORD', 'systemauto', 'Send supplier order by email' ,'order_supplier', 9); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values (31, 'AC_SUP_INV', 'systemauto', 'Send supplier invoice by email' ,'invoice_supplier', 7); -insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 50, 'AC_OTH', 'system', 'Other' ,NULL, 5); +delete from llx_c_actioncomm where id in (1,2,3,4,5,8,9,10,30,31,40,50); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 1,'AC_TEL','system','Phone call',NULL, 1, 2); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 2,'AC_FAX','system','Send Fax',NULL, 1, 3); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 3,'AC_PROP','systemauto', 'Send commercial proposal by email','propal',0,10); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 4,'AC_EMAIL','system','Send Email',NULL, 1, 4); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 5,'AC_RDV','system','Rendez-vous',NULL, 1, 1); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 8,'AC_COM','systemauto','Send customer order by email','order', 0,8); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 9,'AC_FAC','systemauto', 'Send customer invoice by email','invoice',0,6); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 10,'AC_SHIP','systemauto', 'Send shipping by email','shipping',0,11); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 30,'AC_SUP_ORD','systemauto','Send supplier order by email','order_supplier',0,9); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 31,'AC_SUP_INV','systemauto','Send supplier invoice by email','invoice_supplier',0,7); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 40,'AC_OTH_AUTO','systemauto','Other (automatically inserted events)',NULL, 1, 20); +insert into llx_c_actioncomm (id, code, type, libelle, module, active, position) values ( 50,'AC_OTH','system','Other (manually inserted events)',NULL, 1, 5); diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index b0b051a8dcf..3f48667c690 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -164,10 +164,10 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (18 insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1844, 184, '0','0','VAT Rate 0', 1); -- PORTUGAL (id country=25) -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (251, 25, '20','0','VAT standard rate',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (252, 25, '12','0','VAT reduced rate',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (251, 25, '23','0','VAT standard rate',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (252, 25, '13','0','VAT reduced rate',1); insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (253, 25, '0','0','VAT Rate 0', 1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (254, 25, '5','0','VAT reduced rate',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (254, 25, '6','0','VAT reduced rate',1); -- ROMANIA (id country=188) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1881,188, '24','0','VAT standard rate',1); @@ -255,9 +255,13 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (15 insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1543,154, '10','0','VAT Frontero',1); -- BARBADOS (id country=46) -INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (461,46, '0','0','No VAT',1); -INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (462,46, '15','0','VAT 15%',1); -INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (463,46, '7.5','0','VAT 7.5%',1); +INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES ( 461, 46, '0','0','No VAT',1); +INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES ( 462, 46, '15','0','VAT 15%',1); +INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES ( 463, 46, '7.5','0','VAT 7.5%',1); + +-- SOUTH AFRICA (id country=205) +INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (2051,205, '0','0','No VAT',1); +INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (2052,205, '14','0','VAT 14%',1); -- VENEZUELA (id country=232) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (2321,232, '0','0','No VAT',1); diff --git a/htdocs/install/mysql/data/llx_c_type_contact.sql b/htdocs/install/mysql/data/llx_c_type_contact.sql index 4249b8f731c..4e0b3a9963d 100644 --- a/htdocs/install/mysql/data/llx_c_type_contact.sql +++ b/htdocs/install/mysql/data/llx_c_type_contact.sql @@ -49,6 +49,11 @@ insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) v insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (72, 'invoice_supplier', 'external', 'SHIPPING', 'Contact fournisseur livraison', 1); insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (73, 'invoice_supplier', 'external', 'SERVICE', 'Contact fournisseur prestation', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (80, 'agenda', 'internal', 'ACTOR', 'Responsable', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (81, 'agenda', 'internal', 'GUEST', 'Guest', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (85, 'agenda', 'external', 'ACTOR', 'Responsable', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (86, 'agenda', 'external', 'GUEST', 'Guest', 1); + insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (91, 'commande','internal', 'SALESREPFOLL', 'Responsable suivi de la commande', 1); insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (100,'commande','external', 'BILLING', 'Contact client facturation commande', 1); insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (101,'commande','external', 'CUSTOMER', 'Contact client suivi commande', 1); diff --git a/htdocs/install/mysql/data/llx_const.sql b/htdocs/install/mysql/data/llx_const.sql index 23b20a0411b..ef84f9ee005 100644 --- a/htdocs/install/mysql/data/llx_const.sql +++ b/htdocs/install/mysql/data/llx_const.sql @@ -46,7 +46,7 @@ insert into llx_const (name, value, type, note, visible, entity) values ('MAIN_U -- Hidden but specific to one entity insert into llx_const (name, value, type, note, visible, entity) values ('MAIN_MONNAIE','EUR','chaine','Monnaie',0,1); -insert into llx_const (name, value, type, note, visible, entity) values ('MAIN_MAIL_EMAIL_FROM','dolibarr-robot@domain.com','chaine','EMail emetteur pour les emails automatiques Dolibarr',0,1); +insert into llx_const (name, value, type, note, visible, entity) values ('MAIN_MAIL_EMAIL_FROM','robot@domain.com','chaine','EMail emetteur pour les emails automatiques Dolibarr',0,1); -- -- IHM diff --git a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql index f279437ec09..0dcc01bd8e5 100755 --- a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql +++ b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql @@ -34,6 +34,7 @@ ALTER TABLE llx_societe ADD COLUMN idprof6 varchar(128) after idprof5; ALTER TABLE llx_societe DROP COLUMN fk_secteur; ALTER TABLE llx_societe DROP COLUMN description; ALTER TABLE llx_societe DROP COLUMN services; +ALTER TABLE llx_societe MODIFY COLUMN ref_ext varchar(128); ALTER TABLE llx_bank ADD COLUMN tms timestamp after datec; @@ -79,6 +80,8 @@ alter table llx_propaldet drop column pa_ht; alter table llx_propaldet drop column marge_tx; alter table llx_propaldet drop column marque_tx; +alter table llx_expedition add column height_unit integer after height; + ALTER TABLE llx_commande CHANGE COLUMN fk_demand_reason fk_input_reason integer NULL DEFAULT NULL; ALTER TABLE llx_propal CHANGE COLUMN fk_demand_reason fk_input_reason integer NULL DEFAULT NULL; ALTER TABLE llx_commande_fournisseur CHANGE COLUMN fk_methode_commande fk_input_method integer NULL DEFAULT 0; @@ -195,6 +198,12 @@ INSERT INTO llx_holiday_config (rowid ,name ,value) VALUES (NULL , 'nbHolidayDed INSERT INTO llx_holiday_config (rowid ,name ,value) VALUES (NULL , 'nbHolidayEveryMonth', '2.08334'); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (80, 'agenda', 'internal', 'ACTOR', 'Responsable', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (81, 'agenda', 'internal', 'GUEST', 'Guest', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (85, 'agenda', 'external', 'ACTOR', 'Responsable', 1); +insert into llx_c_type_contact(rowid, element, source, code, libelle, active ) values (86, 'agenda', 'external', 'GUEST', 'Guest', 1); + + DELETE FROM llx_document_model WHERE (nom = 'oursin' AND type ='invoice') OR (nom = 'edison' AND type ='order') OR (nom = 'jaune' AND type ='propal'); ALTER TABLE llx_boxes DROP INDEX uk_boxes; @@ -802,3 +811,54 @@ ALTER TABLE llx_c_typent DROP INDEX code, ADD UNIQUE uk_c_typent (code); ALTER TABLE llx_c_effectif DROP INDEX code, ADD UNIQUE uk_c_effectif (code); ALTER TABLE llx_c_paiement DROP INDEX code, ADD UNIQUE uk_c_paiement (code); + +delete from llx_c_actioncomm where id = 40; +INSERT INTO llx_c_actioncomm (id, code, type, libelle, module, position) values ( 40, 'AC_OTH_AUTO','systemauto', 'Other (automatically inserted events)' ,NULL, 20); +UPDATE llx_c_actioncomm SET libelle = 'Other (manually inserted events)' WHERE code = 'AC_OTH'; +UPDATE llx_c_actioncomm SET active = 0 WHERE code in ('AC_PROP', 'AC_COM', 'AC_FAC', 'AC_SHIP', 'AC_SUP_ORD', 'AC_SUP_INV'); + + +-- Update dictionnary of table llx_c_paper_format +DELETE FROM llx_c_paper_format; + +-- Europe +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (1, 'EU4A0', 'Format 4A0', '1682', '2378', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (2, 'EU2A0', 'Format 2A0', '1189', '1682', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (3, 'EUA0', 'Format A0', '840', '1189', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (4, 'EUA1', 'Format A1', '594', '840', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (5, 'EUA2', 'Format A2', '420', '594', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (6, 'EUA3', 'Format A3', '297', '420', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (7, 'EUA4', 'Format A4', '210', '297', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (8, 'EUA5', 'Format A5', '148', '210', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (9, 'EUA6', 'Format A6', '105', '148', 'mm', 1); + +-- US +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (100, 'USLetter', 'Format Letter (A)', '216', '279', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (105, 'USLegal', 'Format Legal', '216', '356', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (110, 'USExecutive', 'Format Executive', '190', '254', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (115, 'USLedger', 'Format Ledger/Tabloid (B)', '279', '432', 'mm', 1); + +-- Canadian +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (200, 'CAP1', 'Format Canadian P1', '560', '860', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (205, 'CAP2', 'Format Canadian P2', '430', '560', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (210, 'CAP3', 'Format Canadian P3', '280', '430', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (215, 'CAP4', 'Format Canadian P4', '215', '280', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (220, 'CAP5', 'Format Canadian P5', '140', '215', 'mm', 1); +INSERT INTO llx_c_paper_format (rowid, code, label, width, height, unit, active) VALUES (225, 'CAP6', 'Format Canadian P6', '107', '140', 'mm', 1); + + +-- increase field size +ALTER TABLE llx_bank_account MODIFY COLUMN code_banque varchar(8); + + + +create table llx_user_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, -- member id + import_key varchar(14) -- import key +)ENGINE=innodb; + +ALTER TABLE llx_user_extrafields ADD INDEX idx_user_extrafields (fk_object); + diff --git a/htdocs/install/mysql/tables/llx_bank_account.sql b/htdocs/install/mysql/tables/llx_bank_account.sql index 24767819c65..899adc7d5f6 100644 --- a/htdocs/install/mysql/tables/llx_bank_account.sql +++ b/htdocs/install/mysql/tables/llx_bank_account.sql @@ -1,7 +1,7 @@ -- ============================================================================= -- Copyright (C) 2000-2004 Rodolphe Quiedeville -- Copyright (C) 2004-2007 Laurent Destailleur --- Copyright (C) 2005-2009 Regis Houssin +-- Copyright (C) 2005-2012 Regis Houssin -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -23,41 +23,34 @@ create table llx_bank_account ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - datec datetime, - tms timestamp, - ref varchar(12) NOT NULL, - label varchar(30) NOT NULL, - entity integer DEFAULT 1 NOT NULL, -- multi company id - bank varchar(60), - code_banque varchar(7), - code_guichet varchar(6), - number varchar(255), - cle_rib varchar(5), - bic varchar(11), - iban_prefix varchar(34), -- 34 according to ISO 13616 - country_iban varchar(2), -- deprecated - cle_iban varchar(2), - domiciliation varchar(255), - fk_departement integer DEFAULT NULL, - fk_pays integer NOT NULL, - proprio varchar(60), - adresse_proprio varchar(255), - courant smallint DEFAULT 0 NOT NULL, - clos smallint DEFAULT 0 NOT NULL, - rappro smallint DEFAULT 1, - url varchar(128), - account_number varchar(8), - currency_code varchar(3) NOT NULL, - min_allowed integer DEFAULT 0, - min_desired integer DEFAULT 0, - comment text + rowid integer AUTO_INCREMENT PRIMARY KEY, + datec datetime, + tms timestamp, + ref varchar(12) NOT NULL, + label varchar(30) NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + bank varchar(60), + code_banque varchar(8), + code_guichet varchar(6), + number varchar(255), + cle_rib varchar(5), + bic varchar(11), + iban_prefix varchar(34), -- 34 according to ISO 13616 + country_iban varchar(2), -- deprecated + cle_iban varchar(2), + domiciliation varchar(255), + fk_departement integer DEFAULT NULL, + fk_pays integer NOT NULL, + proprio varchar(60), + adresse_proprio varchar(255), + courant smallint DEFAULT 0 NOT NULL, + clos smallint DEFAULT 0 NOT NULL, + rappro smallint DEFAULT 1, + url varchar(128), + account_number varchar(8), + currency_code varchar(3) NOT NULL, + min_allowed integer DEFAULT 0, + min_desired integer DEFAULT 0, + comment text + )ENGINE=innodb; - --- --- List of codes for the field entity --- --- 1 : first company bank account --- 2 : second company bank account --- 3 : etc... --- \ No newline at end of file diff --git a/htdocs/install/mysql/tables/llx_expedition.sql b/htdocs/install/mysql/tables/llx_expedition.sql index 9296395b120..f40521d67fd 100644 --- a/htdocs/install/mysql/tables/llx_expedition.sql +++ b/htdocs/install/mysql/tables/llx_expedition.sql @@ -1,7 +1,7 @@ -- =================================================================== -- Copyright (C) 2003-2010 Rodolphe Quiedeville -- Copyright (C) 2008-2010 Regis Houssin --- Copyright (C) 2011 Laurent Destailleur +-- Copyright (C) 2011-2012 Laurent Destailleur -- Copyright (C) 2012 Juanjo Menent -- -- This program is free software; you can redistribute it and/or modify @@ -42,12 +42,12 @@ create table llx_expedition tracking_number varchar(50), fk_statut smallint DEFAULT 0, - height integer, - width integer, - size_units integer, - size integer, - weight_units integer, - weight integer, + height integer, -- height + width integer, -- with + size_units integer, -- unit of all sizes (height, width, depth) + size integer, -- depth + weight_units integer, -- unit of weight + weight integer, -- weight note text, model_pdf varchar(255) diff --git a/htdocs/install/mysql/tables/llx_societe.sql b/htdocs/install/mysql/tables/llx_societe.sql index de753f26bbd..f0a57d0bb3f 100644 --- a/htdocs/install/mysql/tables/llx_societe.sql +++ b/htdocs/install/mysql/tables/llx_societe.sql @@ -25,7 +25,7 @@ create table llx_societe nom varchar(60), -- company reference name entity integer DEFAULT 1 NOT NULL, -- multi company id - ref_ext varchar(60), -- reference into an external system (not used by dolibarr) + ref_ext varchar(128), -- reference into an external system (not used by dolibarr) ref_int varchar(60), -- reference into an internal system (used by dolibarr) statut tinyint DEFAULT 0, -- statut diff --git a/htdocs/install/mysql/tables/llx_user_extrafields.key.sql b/htdocs/install/mysql/tables/llx_user_extrafields.key.sql new file mode 100644 index 00000000000..a4af69a614a --- /dev/null +++ b/htdocs/install/mysql/tables/llx_user_extrafields.key.sql @@ -0,0 +1,23 @@ +-- =================================================================== +-- Copyright (C) 2002-2003 Rodolphe Quiedeville +-- Copyright (C) 2002-2003 Jean-Louis Bergamo +-- Copyright (C) 2009 Regis Houssin +-- Copyright (C) 2011 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program 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 +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- =================================================================== + + +ALTER TABLE llx_user_extrafields ADD INDEX idx_user_extrafields (fk_object); diff --git a/htdocs/install/mysql/tables/llx_user_extrafields.sql b/htdocs/install/mysql/tables/llx_user_extrafields.sql new file mode 100644 index 00000000000..96b4ec69601 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_user_extrafields.sql @@ -0,0 +1,27 @@ +-- =================================================================== +-- Copyright (C) 2002-2003 Rodolphe Quiedeville +-- Copyright (C) 2002-2003 Jean-Louis Bergamo +-- Copyright (C) 2009 Regis Houssin +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program 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 +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- =================================================================== + +create table llx_user_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, -- member id + import_key varchar(14) -- import key +)ENGINE=innodb; diff --git a/htdocs/langs/ar_SA/install.lang b/htdocs/langs/ar_SA/install.lang index e5673fd9232..57d561e631d 100644 --- a/htdocs/langs/ar_SA/install.lang +++ b/htdocs/langs/ar_SA/install.lang @@ -123,8 +123,8 @@ YouMustCreateItAndAllowServerToWrite=يجب إنشاء هذا الدليل ، و CharsetChoice=اختيار مجموعة حروف CharacterSetClient=مجموعة الحروف المستخدمة في توليدها صفحات هتمل CharacterSetClientComment=اختيار الطابع المحدد لعرضها على الإنترنت.
      واقترحت مجموعة الطابع الافتراضي هو واحد من قاعدة البيانات. -CollationConnection=طابع الفرز بغية -CollationConnectionComment=اختر صفحة المدونة التي تحدد طبيعة النظام 'sفرز قاعدة البيانات التي تستخدمها. هذا هو المعلم كما دعا 'مقارنتها' بعض قواعد البيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. +DBSortingCollation=طابع الفرز بغية +DBSortingCollationComment=اختر صفحة المدونة التي تحدد طبيعة النظام 'sفرز قاعدة البيانات التي تستخدمها. هذا هو المعلم كما دعا 'مقارنتها' بعض قواعد البيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. CharacterSetDatabase=الطابع المحدد لقاعدة البيانات CharacterSetDatabaseComment=اختيار مجموعة حروف تريد لإنشاء قاعدة بيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. YouAskDatabaseCreationSoDolibarrNeedToConnect=كنت أسأل لإنشاء قاعدة بيانات ٪ ق ، ولكن لهذا ، Dolibarr الحاجة الى الاتصال بخادم ٪ ق السوبر مع المستخدم أذونات ٪ ق. diff --git a/htdocs/langs/ar_SA/members.lang b/htdocs/langs/ar_SA/members.lang index b27b341f4e4..570dfab4069 100644 --- a/htdocs/langs/ar_SA/members.lang +++ b/htdocs/langs/ar_SA/members.lang @@ -202,7 +202,7 @@ LastSubscriptionDate=آخر موعد الاكتتاب LastSubscriptionAmount=آخر مبلغ الاشتراك MembersStatisticsByCountries=أعضاء إحصاءات حسب البلد MembersStatisticsByState=أعضاء إحصاءات الولاية / المقاطعة -MembersStatisticsByTowne=أعضاء إحصاءات بلدة +MembersStatisticsByTown=أعضاء إحصاءات بلدة NbOfMembers=عدد الأعضاء NoValidatedMemberYet=العثور على أي أعضاء التحقق من صحة MembersByCountryDesc=هذه الشاشة تظهر لك إحصاءات عن أعضاء من الدول. لكن الرسم يعتمد على خدمة غوغل الرسم البياني على الإنترنت ويتوفر فقط إذا كان على اتصال بالإنترنت ويعمل. diff --git a/htdocs/langs/ar_SA/suppliers.lang b/htdocs/langs/ar_SA/suppliers.lang index 5929a7d55d3..c4ac7827029 100644 --- a/htdocs/langs/ar_SA/suppliers.lang +++ b/htdocs/langs/ar_SA/suppliers.lang @@ -14,7 +14,6 @@ Supplier=المورد AddSupplier=إضافة مورد SupplierRemoved=إزالة المورد SuppliersInvoice=فاتورة الموردين -SuppliersInvoices=فواتير الموردين NewSupplier=مورد جديد History=التاريخ ListOfSuppliers=قائمة الموردين diff --git a/htdocs/langs/bg_BG/install.lang b/htdocs/langs/bg_BG/install.lang index 7462b72ccb9..aa18691f409 100644 --- a/htdocs/langs/bg_BG/install.lang +++ b/htdocs/langs/bg_BG/install.lang @@ -132,8 +132,8 @@ YouMustCreateItAndAllowServerToWrite=Трябва да създадете таз CharsetChoice=Избор на знаците CharacterSetClient=Набор от символи, използвани за генерираните HTML уеб страници CharacterSetClientComment=Изберете набор от знаци за уеб дисплей.
      Default предлагания набор от символи е един от вашата база данни. -CollationConnection=За символи сортиране -CollationConnectionComment=Изберете кода на страницата, която определя подреждане характер, използван от база данни. Този параметър се нарича "съпоставяне" от някои бази данни.
      Този параметър не може да бъде определена, ако базата данни вече съществува. +DBSortingCollation=За символи сортиране +DBSortingCollationComment=Изберете кода на страницата, която определя подреждане характер, използван от база данни. Този параметър се нарича "съпоставяне" от някои бази данни.
      Този параметър не може да бъде определена, ако базата данни вече съществува. CharacterSetDatabase=Набор от знаци за база данни CharacterSetDatabaseComment=Изберете набор от символи, издирван за създаването на базата данни.
      Този параметър не може да бъде определена, ако базата данни вече съществува. YouAskDatabaseCreationSoDolibarrNeedToConnect=Ви помолим да създадете база данни %s, но за това, Dolibarr трябва да се свържете на сървъра %s с супер потребителски разрешения %s. diff --git a/htdocs/langs/bg_BG/members.lang b/htdocs/langs/bg_BG/members.lang index be719944efb..c2fabf1da50 100644 --- a/htdocs/langs/bg_BG/members.lang +++ b/htdocs/langs/bg_BG/members.lang @@ -178,7 +178,7 @@ LastSubscriptionDate=Последно абонамент дата LastSubscriptionAmount=Последно размера MembersStatisticsByCountries=Потребители статистика страната MembersStatisticsByState=Потребители статистика щат / провинция -MembersStatisticsByTowne=Потребители статистика града +MembersStatisticsByTown=Потребители статистика града NbOfMembers=Брой на членовете NoValidatedMemberYet=Няма потвърдени намерени MembersByCountryDesc=Този екран показва статистическите данни на членовете по страни. Графичен зависи обаче от Google онлайн услуга графика и е достъпна само ако интернет връзката се работи. diff --git a/htdocs/langs/bg_BG/suppliers.lang b/htdocs/langs/bg_BG/suppliers.lang index 283ada1c1c5..e279ad69213 100644 --- a/htdocs/langs/bg_BG/suppliers.lang +++ b/htdocs/langs/bg_BG/suppliers.lang @@ -13,7 +13,6 @@ Supplier=Снабдител AddSupplier=Добави доставчик SupplierRemoved=Изтрити доставчик SuppliersInvoice=Фактура -SuppliersInvoices=Фактури NewSupplier=Нов доставчик History=Исторически ListOfSuppliers=Списък на доставчиците diff --git a/htdocs/langs/ca_ES/admin.lang b/htdocs/langs/ca_ES/admin.lang index 06873ef9f89..768607eca53 100644 --- a/htdocs/langs/ca_ES/admin.lang +++ b/htdocs/langs/ca_ES/admin.lang @@ -718,6 +718,20 @@ VATIsNotUsedDesc=El tipus d'IVA proposat per defecte és 0. Aquest és el cas d' VATIsUsedExampleFR=A França, es tracta de les societats o organismes que trien un règim fiscal general (General simplificat o General normal), règim en el qual es declara l'IVA. VATIsNotUsedExampleFR=A França, es tracta d'associacions exemptes d'IVA o societats, organismes o professions liberals que han eligedo el règim fiscal de mòduls (IVA en franquícia), pagant un IVA en franquícia sense fer declaració d'IVA. Aquesta elecció fa aparèixer l'anotació "IVA no aplicable - art-293B del CGI" en les factures. ##### Local Taxes ##### +LocalTax1IsUsed=Subjecte +LocalTax1IsNotUsed=No subjecte +LocalTax1IsUsedDesc=Ús d'un 2on. tipus d'impost (Diferent de l'IVA) +LocalTax1IsNotUsedDesc=No utilitzar un 2on. tipus d'impost (Diferent de l'IVA) +LocalTax1Management=Gestió 2on. tipus d'impost +LocalTax1IsUsedExample= +LocalTax1IsNotUsedExample= +LocalTax2IsUsed=Subjecte +LocalTax2IsNotUsed=No subjecte +LocalTax2IsUsedDesc=Ús d'un 3er. tipus d'impost (Diferent de l'IVA) +LocalTax2IsNotUsedDesc=No utilitzar un 3er. tipus d'impost (Diferent de l'IVA) +LocalTax2Management=Gestió 2on. tipus d'impost +LocalTax2IsUsedExample= +LocalTax2IsNotUsedExample= LocalTax1ManagementES=Gestió Recàrrec d'Equivalència LocalTax1IsUsedDescES=El tipus de RE proposat per defecte en les creacions de pressupostos, factures, comandes, etc. Respon a la següent regla:
      Si el comprador no està subjecte a RE, RE per defecte= 0. Final de regla.
      Si el comprador està subjecte a RE aleshores s'aplica valor de RE per defecte. Final de regla.
      LocalTax1IsNotUsedDescES=El tipus de RE proposat per defecte es 0. Final de regla. @@ -949,6 +963,7 @@ DocumentModelOdt=Generació des dels documents amb format OpenDocument (Arxiu .O WatermarkOnDraft=Marca d'aigua en els documents esborrany CompanyIdProfChecker=Id Professional únic MustBeUnique=Ha de ser únic? +MustBeMandatory=Ha de ser obligatori? Miscellanous=Miscel·lània ##### Webcal setup ##### WebCalSetup=Configuració d'enllaç amb el calendari webcalendar diff --git a/htdocs/langs/ca_ES/bills.lang b/htdocs/langs/ca_ES/bills.lang index f6ce99e3c04..d8d87882d13 100644 --- a/htdocs/langs/ca_ES/bills.lang +++ b/htdocs/langs/ca_ES/bills.lang @@ -47,7 +47,7 @@ InvoiceCustomer=Factura a client CustomerInvoice=Factura a client CustomersInvoices=Factures a clientes SupplierInvoice=Factura de proveïdor -SuppliersInvoices=Factures de proveïdors +SuppliersInvoices=Factures proveïdors SupplierBill=Factura de proveïdor SupplierBills=Factures de proveïdors Payment=Pagament diff --git a/htdocs/langs/ca_ES/boxes.lang b/htdocs/langs/ca_ES/boxes.lang index aabee817076..c9630609526 100644 --- a/htdocs/langs/ca_ES/boxes.lang +++ b/htdocs/langs/ca_ES/boxes.lang @@ -3,6 +3,7 @@ CHARSET=UTF-8 BoxLastRssInfos=Fils d'informació RSS BoxLastProducts=Els %s últims productes/serveis BoxLastProductsInContract=Els %s últims productes/serveis contractats +BoxProductsAlertStock=Productes en alerta d'estoc BoxLastSupplierBills=Últimes factures de proveïdors BoxLastCustomerBills=Últimes factures a clients BoxOldestUnpaidCustomerBills=Factures a clients més antigues pendents de pagament @@ -25,6 +26,7 @@ BoxTitleLastBooks=Els %s darrers marcadors registrats BoxTitleNbOfCustomers=Nombre de clients BoxTitleLastRssInfos=Les %s últimes infos de %s BoxTitleLastProducts=Els %s darrers productes/serveis registrats +BoxTitleProductsAlertStock=Productes en alerta d'estoc BoxTitleLastCustomerOrders=Les %s darreres comandes de clients modificades BoxTitleLastSuppliers=Els %s darrers proveïdors registrats BoxTitleLastCustomers=Els %s darrers clients registrats diff --git a/htdocs/langs/ca_ES/cashdesk.lang b/htdocs/langs/ca_ES/cashdesk.lang index d6159645479..62f5e6a3b7b 100644 --- a/htdocs/langs/ca_ES/cashdesk.lang +++ b/htdocs/langs/ca_ES/cashdesk.lang @@ -20,7 +20,6 @@ AddThisArticle=Afegeix aquest article RestartSelling=Reprendre la venda SellFinished=Venda acabada PrintTicket=Imprimir tiquet -NoResults=Cap resultat NoProductFound=Cap article trobat ProductFound=Producte trobat ProductsFound=Productes trobats diff --git a/htdocs/langs/ca_ES/commercial.lang b/htdocs/langs/ca_ES/commercial.lang index 1efa62b8804..502ed15864f 100644 --- a/htdocs/langs/ca_ES/commercial.lang +++ b/htdocs/langs/ca_ES/commercial.lang @@ -81,6 +81,8 @@ ActionAC_SHIP=Enviament expedició per correu ActionAC_SUP_ORD=Enviament comanda a proveïdor per correu ActionAC_SUP_INV=Enviament factura de proveïdor per correu ActionAC_OTH=Altra +ActionAC_MANUAL=Esdeveniments creats manualment +ActionAC_AUTO=Esdeveniments creats automàticament Stats=Estadístiques de venda CAOrder=Volum de vendes (Comandes validades) FromTo=de %s a %s diff --git a/htdocs/langs/ca_ES/companies.lang b/htdocs/langs/ca_ES/companies.lang index caa0cfe0174..63ae033cd98 100644 --- a/htdocs/langs/ca_ES/companies.lang +++ b/htdocs/langs/ca_ES/companies.lang @@ -108,42 +108,49 @@ ProfId2AR=Ingressos bruts ProfId3AR=- ProfId4AR=- ProfId5AR=- +ProfId6AR=- ProfId1AU=ABN ProfId2AU=- ProfId3AU=- ProfId4AU=- ProfId5AU=- +ProfId6AU=- ProfId1BE=N° col·legiat ProfId2BE=- ProfId3BE=- ProfId4BE=- ProfId5BE=- -ProfId1BR=CNPJ +ProfId6BE=- +ProfId1BR=- ProfId2BR=IE (Inscricao Estadual) ProfId3BR=IM (Inscricao Municipal) ProfId4BR=CPF -#ProfId5BR=CNAE= -#ProfId6BR=INSS= +#ProfId5BR=CNAE +#ProfId6BR=INSS ProfId1CH=- ProfId2CH=- ProfId3CH=Número federat ProfId4CH=Num registre de comerç ProfId5CH=- +ProfId6CH=- ProfId1CL=R.U.T. ProfId2CL=- ProfId3CL=- ProfId4CL=- ProfId5CL=- +ProfId6CL=- ProfId1CO=R.U.T. ProfId2CO=- ProfId3CO=- ProfId4CO=- ProfId5CO=- +ProfId6CO=- ProfId1DE=Id prof. 1 (USt.-IdNr) ProfId2DE=Id prof. 2 (USt.-Nr) ProfId3DE=Id prof. 3 (Handelsregister-Nr.) ProfId4DE=- ProfId5DE=- +ProfId6DE=- ProfId1ES=CIF/NIF ProfId2ES=Núm seguretat social ProfId3ES=CNAE @@ -161,51 +168,61 @@ ProfId2GB=- ProfId3GB=SIC ProfId4GB=- ProfId5GB=- +ProfId6GB=- ProfId1HN=RTN ProfId2HN=- ProfId3HN=- ProfId4HN=- ProfId5HN=- +ProfId6HN=- ProfId1IN=Id prof. 1 (TIN) -ProfId2IN=Id prof. 2 -ProfId3IN=Id prof. 3 +ProfId2IN=Id prof. 2 (PAN) +ProfId3IN=Id prof. 3 (SRVC TAX) ProfId4IN=Id prof. 4 ProfId5IN=Id prof. 5 +ProfId6IN=- ProfId1MA=Id prof. 1 (R.C.) ProfId2MA=Id prof. 2 (Patente) ProfId3MA=Id prof. 3 (I.F.) ProfId4MA=Id prof. 4 (C.N.S.S.) ProfId5MA=- +ProfId6MA=- ProfId1MX=R.F.C. ProfId2MX=Registre Patronal IMSS ProfId3MX=Cèdula Professional ProfId4MX=- ProfId5MX=- +ProfId6MX=- ProfId1NL=Número KVK ProfId2NL=- ProfId3NL=- ProfId4NL=- ProfId5NL=- +ProfId6NL=- ProfId1PT=NIPC ProfId2PT=Núm seguretat social ProfId3PT=Num reg. comercial ProfId4PT=Conservatori ProfId5PT=- +ProfId6PT=- ProfId1RU=OGRN ProfId2RU=INN ProfId3RU=KPP ProfId4RU=OKPO ProfId5RU=- +ProfId6RU=- ProfId1SN=RC ProfId2SN=NINEA ProfId3SN=- ProfId4SN=- ProfId5SN=- +ProfId6SN=- ProfId1TN=RC ProfId2TN=Matrícula fiscal ProfId3TN=Codi en aduana ProfId4TN=CCC ProfId5TN=- +ProfId6TN=- VATIntra=NIF intracomunitari VATIntraShort=NIF intra. VATIntraVeryShort=NIF intra. diff --git a/htdocs/langs/ca_ES/errors.lang b/htdocs/langs/ca_ES/errors.lang index fd43de81c10..ec04e3ff9ce 100644 --- a/htdocs/langs/ca_ES/errors.lang +++ b/htdocs/langs/ca_ES/errors.lang @@ -21,6 +21,7 @@ ErrorThisContactIsAlreadyDefinedAsThisType=Aquest contacte ja està definit com ErrorCashAccountAcceptsOnlyCashMoney=Aquesta compte bancari és de tipus caixa i només accepta el mètode de pagament de tipus espècie. ErrorFromToAccountsMustDiffers=El compte origen i destinació han de ser diferents. ErrorBadThirdPartyName=Nom de tercer incorrecte +ErrorProdIdIsMandatory=El %s es obligatori ErrorBadCustomerCodeSyntax=La sintaxi del codi client és incorrecta ErrorCustomerCodeRequired=Codi client obligatori ErrorCustomerCodeAlreadyUsed=Codi de client ja utilitzat diff --git a/htdocs/langs/ca_ES/exports.lang b/htdocs/langs/ca_ES/exports.lang index 77d8e30c30b..04b588e68d0 100644 --- a/htdocs/langs/ca_ES/exports.lang +++ b/htdocs/langs/ca_ES/exports.lang @@ -123,4 +123,8 @@ SuppliersProducts=Productes de proveïdors BankCode=Codi banc DeskCode=Codi oficina BankAccountNumber=Número compte -BankAccountNumberKey=Dígit Control \ No newline at end of file +BankAccountNumberKey=Dígit Control +## filters +FilterableFields=Camps filtrables +FilteredFields=Campos filtrats +FilteredFieldsValues=Valors de filtres \ No newline at end of file diff --git a/htdocs/langs/ca_ES/install.lang b/htdocs/langs/ca_ES/install.lang index f27d6e24039..b37e2c114c5 100644 --- a/htdocs/langs/ca_ES/install.lang +++ b/htdocs/langs/ca_ES/install.lang @@ -125,8 +125,8 @@ YouMustCreateItAndAllowServerToWrite=Cal crear aquest expedient i permetre al se CharsetChoice=Elecció del joc de caràcters CharacterSetClient=Codificació utilitzada per a la visualització de les pàgines CharacterSetClientComment=Pot triar la codificació que voleu per a la visualització de les pàgines.
      La codificació proposada per defecte és la de la seva base de dades. -CollationConnection=Ordre de selecció utilitzat per la base de dades -CollationConnectionComment=Pot triar la pàgina de codi per la qual es defineix l'ordre de selecció dels caràcters utilitzat per la base de dades. Aquest paràmetre també és anomenat 'confrontació' per algunes bases de dades.
      Aquest paràmetre no és seleccionable si la base de dades ja està creada +DBSortingCollation=Ordre de selecció utilitzat per la base de dades +DBSortingCollationComment=Pot triar la pàgina de codi per la qual es defineix l'ordre de selecció dels caràcters utilitzat per la base de dades. Aquest paràmetre també és anomenat 'confrontació' per algunes bases de dades.
      Aquest paràmetre no és seleccionable si la base de dades ja està creada CharacterSetDatabase=Codificació utilitzada per la base de dades CharacterSetDatabaseComment=Pot triar la codificació que voleu en la creació de la base de dades.
      Aquest paràmetre no és seleccionable si la base de dades ja està creada YouAskDatabaseCreationSoDolibarrNeedToConnect=Ha vollgut crear la base de dades %s, però per a això Dolibarr ha de connectar amb el servidor %s via el superusuari %s. diff --git a/htdocs/langs/ca_ES/languages.lang b/htdocs/langs/ca_ES/languages.lang index af9d3f7d92a..97b44e22cbe 100644 --- a/htdocs/langs/ca_ES/languages.lang +++ b/htdocs/langs/ca_ES/languages.lang @@ -12,6 +12,7 @@ Language_en_AU=Anglès (Australia) Language_en_GB=Anglès (Regne Unit) Language_en_IN=Anglès (Índia) Language_en_NZ=Anglais (Nova Zelanda) +Language_en_SA=Inglés (Aràbia Saudita) Language_en_US=Anglès (Estats Units) Language_es_ES=Espanyol Language_es_AR=Espanyol (Argentina) @@ -42,4 +43,5 @@ Language_tr_TR=Turc Language_sl_SI=Eslovè Language_sv_SV=Suec Language_sv_SE=Suec -Language_zh_CN=Xinès \ No newline at end of file +Language_zh_CN=Xinès +Language_zh_TW=Xinès (Tradicional) \ No newline at end of file diff --git a/htdocs/langs/ca_ES/mails.lang b/htdocs/langs/ca_ES/mails.lang index 3e924788ed0..f5721bd7557 100644 --- a/htdocs/langs/ca_ES/mails.lang +++ b/htdocs/langs/ca_ES/mails.lang @@ -77,6 +77,8 @@ YourMailUnsubcribeOK=El correu electrònic %s és correcta desuscribe. MailtoEMail=mailto email (hyperlink) ActivateCheckRead=Activar confirmació de lectura i opció de Desubscripció ActivateCheckReadKey=Clau usada per xifrar la URL de la confirmació de lectura i la funció de desubscripció +EMailSentToNRecipients=E-Mail enviat a %s destinataris. + # Libelle des modules de liste de destinataires mailing== MailingModuleDescContactCompanies=Contactes de tercers (clients potencials, clients, proveïdors ...) MailingModuleDescDolibarrUsers=Usuaris de Dolibarr diff --git a/htdocs/langs/ca_ES/main.lang b/htdocs/langs/ca_ES/main.lang index 97683be8657..e5dd83e69e4 100644 --- a/htdocs/langs/ca_ES/main.lang +++ b/htdocs/langs/ca_ES/main.lang @@ -627,7 +627,8 @@ ByDay=Per dia BySalesRepresentative=Per comercial LinkedToSpecificUsers=Enllaçat a un contacte d'usuari particular DeleteAFile=Eliminació d'arxiu -ConfirmDeleteAFile=Confirma l'eliminació de l'arxiu +ConfirmDeleteAFile=Confirme l'eliminació de l'arxiu +NoResults=Cap resultat # Week day Monday=Dilluns Tuesday=Dimarts diff --git a/htdocs/langs/ca_ES/margins.lang b/htdocs/langs/ca_ES/margins.lang index f502a3274bf..62bb253a587 100644 --- a/htdocs/langs/ca_ES/margins.lang +++ b/htdocs/langs/ca_ES/margins.lang @@ -46,4 +46,8 @@ MargeNette=Marge net MARGIN_TYPE_DETAILS=Marge brut: Preu de venda sense IVA - Preu de compra sense IVA
      Marge net: Preu de venda sense IVA - Costos BuyingCost=Costos -UnitCharges=Càrrega unitària \ No newline at end of file +UnitCharges=Càrrega unitària +Charges=Càrreges + +AgentContactType=Tipus de contacte comissionat +AgentContactTypeDetails=Indica el tipus de contacte enllaçat a les factures que seran associats als agents comercials \ No newline at end of file diff --git a/htdocs/langs/ca_ES/members.lang b/htdocs/langs/ca_ES/members.lang index 16dc5eb7805..3ab4439d0b9 100644 --- a/htdocs/langs/ca_ES/members.lang +++ b/htdocs/langs/ca_ES/members.lang @@ -199,3 +199,6 @@ Collectivités=Col.lectivitats Particuliers=Particulars Entreprises=Empreses DOLIBARRFOUNDATION_PAYMENT_FORM=Per realitzar el pagament de la seva cotització per transferència bancària, visiteu la pàgina http://wiki.dolibarr.org/index.php/Subscribirse.
      Per pagar amb targeta de crèdit o PayPal, feu clic al botó a la part inferior d'aquesta pàgina.

      +ByProperties=Per característiques +MembersStatisticsByProperties=Estadístiques dels membres per característiques +MembersByNature=Membres per naturalesa \ No newline at end of file diff --git a/htdocs/langs/ca_ES/products.lang b/htdocs/langs/ca_ES/products.lang index f1c0fbb0616..71d8d426d2c 100644 --- a/htdocs/langs/ca_ES/products.lang +++ b/htdocs/langs/ca_ES/products.lang @@ -146,6 +146,8 @@ ProductSpecial=Especial QtyMin=Quantitat mínima PriceQty=Preu per la quantitat PriceQtyMin=Preu quantitat min. +DiscountQtyMin=Descompte per defecte quantitat min. +VATRateForSupplierProduct=Taxa IVA (per aquest producte/proveïdor) NoPriceDefinedForThisSupplier=Cap preu/quant. definit per a aquest proveïdor/producte NoSupplierPriceDefinedForThisProduct=Cap preu/quant. proveïdor definit per a aquest producte RecordedProducts=Productes en venda diff --git a/htdocs/langs/ca_ES/projects.lang b/htdocs/langs/ca_ES/projects.lang index 19defa1363c..0f6ce75309d 100644 --- a/htdocs/langs/ca_ES/projects.lang +++ b/htdocs/langs/ca_ES/projects.lang @@ -93,6 +93,8 @@ CloneFiles=Clonar els arxius adjunts ConfirmCloneProject=Esteu segur que voleu clonar aquest projecte? ProjectReportDate=Canviar les dates de les tasques en funció de la data d'inici del projecte ErrorShiftTaskDate=S'ha produït un error en el canvi de les dates de les tasques +ProjectsAndTasksLines=Projectes i tasques + ##### Types de contacts ##### TypeContact_project_internal_PROJECTLEADER=Cap de projecte TypeContact_project_external_PROJECTLEADER=Cap de projecte diff --git a/htdocs/langs/ca_ES/sendings.lang b/htdocs/langs/ca_ES/sendings.lang index df64623f238..38462265059 100644 --- a/htdocs/langs/ca_ES/sendings.lang +++ b/htdocs/langs/ca_ES/sendings.lang @@ -58,6 +58,7 @@ ActionsOnShipping=Events sobre l'expedició LinkToTrackYourPackage=Enllaç per al seguiment del seu paquet ShipmentCreationIsDoneFromOrder=De moment, la creació d'una nova expedició es realitza des de la fitxa de comanda. RelatedShippings=Expedició(ns) associades +ShipmentLine=Línia d'expedició # Sending methods SendingMethodCATCH=Recollit pel client diff --git a/htdocs/langs/ca_ES/suppliers.lang b/htdocs/langs/ca_ES/suppliers.lang index be740e4eab1..065d0404862 100644 --- a/htdocs/langs/ca_ES/suppliers.lang +++ b/htdocs/langs/ca_ES/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Proveïdor AddSupplier=Afegir proveïdor SupplierRemoved=Proveïdor eliminat SuppliersInvoice=Factura proveïdor -SuppliersInvoices=Factures proveïdors NewSupplier=Nou proveïdor History=Històric ListOfSuppliers=Llistat de proveïdors diff --git a/htdocs/langs/ca_ES/withdrawals.lang b/htdocs/langs/ca_ES/withdrawals.lang index 22b63fbda11..d088feb8598 100644 --- a/htdocs/langs/ca_ES/withdrawals.lang +++ b/htdocs/langs/ca_ES/withdrawals.lang @@ -34,7 +34,7 @@ MakeWithdrawRequest=Fer una petició de domiciliació ThirdPartyBankCode=Codi banc del tercer ThirdPartyDeskCode=Codi oficina del tercer NoInvoiceCouldBeWithdrawed=No s'ha domiciliat cap factura. Assegureu-vos que les factures són d'empreses amb les dades de comptes bancaris correctes. -ClassCredited=Abonar +ClassCredited=Classificar com "Abonada" ClassCreditedConfirm=Esteu segur de voler classificar aquesta domiciliació com abonada al seu compte bancari? TransData=Data enviament TransMetod=Mètode enviament @@ -81,6 +81,9 @@ WithdrawalFileNotCapable=No es possible generar fitxer bancari de domiciliacio p ShowWithdraw=Veure domiciliació IfInvoiceNeedOnWithdrawPaymentWontBeClosed=No obstant això, si la factura té pendent algun pagament per domiciliació, no serà tancada per a permetre la gestió de la domiciliació. DoStandingOrdersBeforePayments=Aquesta pestanya us permet realitzar una petició de domiciliació. Un cop, podeu ingressar el pagament a la factura per procedir al seu tancament. +WithdrawalFile=Arxiu de la domiciliació +SetToStatusSent=Classificar com "Arxiu enviat" +ThisWillAlsoAddPaymentOnInvoice=Es crearan els pagaments de les factures i les classificarà com pagades ### Notifications InfoCreditSubject=Abonament de domiciliació %s pel banc diff --git a/htdocs/langs/da_DK/install.lang b/htdocs/langs/da_DK/install.lang index 39391c84b32..8bd455e6cee 100644 --- a/htdocs/langs/da_DK/install.lang +++ b/htdocs/langs/da_DK/install.lang @@ -124,8 +124,8 @@ YouMustCreateItAndAllowServerToWrite=Du skal oprette denne mappe og giver muligh CharsetChoice=Tegnsæt valg CharacterSetClient=Tegnsæt anvendes til genererede HTML-websider CharacterSetClientComment=Vælg tegnsættet for web displayet.
      Default foreslåede tegnsæt er den ene af din database. -CollationConnection=Tegn sortering orden -CollationConnectionComment=Vælg side kode, der definerer karakter's sortering rækkefølge anvendes af databasen. Denne parameter kaldes også »samling« af nogle databaser.
      Denne parameter kan ikke defineres, hvis database findes allerede. +DBSortingCollation=Tegn sortering orden +DBSortingCollationComment=Vælg side kode, der definerer karakter's sortering rækkefølge anvendes af databasen. Denne parameter kaldes også »samling« af nogle databaser.
      Denne parameter kan ikke defineres, hvis database findes allerede. CharacterSetDatabase=Tegnsæt for database CharacterSetDatabaseComment=Vælg tegnsættet ønskede for database oprettelse.
      Denne parameter kan ikke defineres, hvis database findes allerede. YouAskDatabaseCreationSoDolibarrNeedToConnect=Du beder om at oprette databasen %s, men for dette, Dolibarr behovet for at oprette forbindelse til serveren %s med superbruger %s tilladelser. diff --git a/htdocs/langs/da_DK/members.lang b/htdocs/langs/da_DK/members.lang index c4ba43b50b7..c2975ad715c 100644 --- a/htdocs/langs/da_DK/members.lang +++ b/htdocs/langs/da_DK/members.lang @@ -210,7 +210,7 @@ LastSubscriptionDate=Sidste abonnement dato LastSubscriptionAmount=Sidste tegningsbeløbet MembersStatisticsByCountries=Medlemmer statistik efter land MembersStatisticsByState=Medlemmer statistikker stat / provins -MembersStatisticsByTowne=Medlemmer statistikker byen +MembersStatisticsByTown=Medlemmer statistikker byen NbOfMembers=Antal medlemmer NoValidatedMemberYet=Ingen validerede medlemmer fundet MembersByCountryDesc=Denne skærm viser dig statistikker over medlemmer af lande. Grafisk afhænger dog på Google online-graf service og er kun tilgængelig, hvis en internetforbindelse virker. diff --git a/htdocs/langs/da_DK/suppliers.lang b/htdocs/langs/da_DK/suppliers.lang index cc435074e79..5b06a4bfdba 100644 --- a/htdocs/langs/da_DK/suppliers.lang +++ b/htdocs/langs/da_DK/suppliers.lang @@ -16,7 +16,6 @@ Supplier=Leverandør AddSupplier=Tilføj en leverandør SupplierRemoved=Leverandør fjernet SuppliersInvoice=Leverandører faktura -SuppliersInvoices=Leverandører fakturaer NewSupplier=Ny leverandør History=Historie ListOfSuppliers=Liste over leverandører diff --git a/htdocs/langs/de_AT/install.lang b/htdocs/langs/de_AT/install.lang index 451f0a15ab8..765d366a219 100644 --- a/htdocs/langs/de_AT/install.lang +++ b/htdocs/langs/de_AT/install.lang @@ -119,8 +119,8 @@ YouMustCreateItAndAllowServerToWrite=Bitte erstellen Sie dieses Verzeichnis und CharsetChoice=Zeichensatzauswahl CharacterSetClient=Zeichensatz für die generierten HTML-Seiten CharacterSetClientComment=Wählen Sie den gewünschten Zeichensatz für die Anzeige im Web.
      Standardmäßig empfiehlt sich jener Ihrer Datenbank. -CollationConnection=Reihenfolge der Zeichensortierung (Collation) -CollationConnectionComment=Wählen Sie den page-code zur Definition der Sortierreihenfolge für Zeichen in der Datenbank. Dieser Parameter wird von einigen Datenbanken auch als "Collation" bezeichnet.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. +DBSortingCollation=Reihenfolge der Zeichensortierung (Collation) +DBSortingCollationComment=Wählen Sie den page-code zur Definition der Sortierreihenfolge für Zeichen in der Datenbank. Dieser Parameter wird von einigen Datenbanken auch als "Collation" bezeichnet.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. CharacterSetDatabase=Datenbankzeichensatz CharacterSetDatabaseComment=Wählen Sie den Zeichensatz für die anzulegende Datenbank.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. YouAskDatabaseCreationSoDolibarrNeedToConnect=Sie möchten die Datenbank %s erstellen. Hierfür benötigt dolibarr eine Verbindung zum Server %s mit den Berechtigungen des Super-Users %s. diff --git a/htdocs/langs/de_AT/suppliers.lang b/htdocs/langs/de_AT/suppliers.lang index 6a960705d76..5d17837ec06 100644 --- a/htdocs/langs/de_AT/suppliers.lang +++ b/htdocs/langs/de_AT/suppliers.lang @@ -12,7 +12,6 @@ Supplier=Lieferant AddSupplier=Lieferanten hinzufügen SupplierRemoved=Lieferant entfernt SuppliersInvoice=Lieferantenrechnung -SuppliersInvoices=Lieferantenrechnungen NewSupplier=Neuer Lieferant History=Verlauf ListOfSuppliers=Lieferantenliste diff --git a/htdocs/langs/de_DE/install.lang b/htdocs/langs/de_DE/install.lang index 56e403a40ee..f7e0ae7654d 100644 --- a/htdocs/langs/de_DE/install.lang +++ b/htdocs/langs/de_DE/install.lang @@ -130,8 +130,8 @@ YouMustCreateItAndAllowServerToWrite=Bitte erstellen Sie dieses Verzeichnis und CharsetChoice=Zeichensatzauswahl CharacterSetClient=Zeichensatz für die generierten HTML-Seiten CharacterSetClientComment=Wählen Sie den gewünschten Zeichensatz für die Anzeige im Web.
      Standardmäßig empfiehlt sich jener Ihrer Datenbank. -CollationConnection=Reihenfolge der Zeichensortierung -CollationConnectionComment=Wählen Sie den page-code zur Definition der Sortierreihenfolge für Zeichen in der Datenbank. Dieser Parameter wird von einigen Datenbanken auch als "Collation" bezeichnet.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. +DBSortingCollation=Reihenfolge der Zeichensortierung +DBSortingCollationComment=Wählen Sie den page-code zur Definition der Sortierreihenfolge für Zeichen in der Datenbank. Dieser Parameter wird von einigen Datenbanken auch als "Collation" bezeichnet.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. CharacterSetDatabase=Datenbankzeichensatz CharacterSetDatabaseComment=Wählen Sie den Zeichensatz für die anzulegende Datenbank.
      Dieser Wert kann nicht festgelegt werden, wenn die Datenbank bereits existiert. YouAskDatabaseCreationSoDolibarrNeedToConnect=Sie möchten die Datenbank %s erstellen. Hierfür benötigt dolibarr eine Verbindung zum Server %s mit den Berechtigungen des Super-Users %s. diff --git a/htdocs/langs/de_DE/members.lang b/htdocs/langs/de_DE/members.lang index 259f7e71a5b..45ce52e7ddf 100644 --- a/htdocs/langs/de_DE/members.lang +++ b/htdocs/langs/de_DE/members.lang @@ -175,7 +175,7 @@ LastSubscriptionDate=Letzter Abo-Termin LastSubscriptionAmount=Letzter Abo-Betrag MembersStatisticsByCountries=Mitgliederstatistik nach Ländern MembersStatisticsByState=Mitgliederstatistik nach Bundesländern -MembersStatisticsByTowne=Mitgliederstatistik nach Städten +MembersStatisticsByTown=Mitgliederstatistik nach Städten NbOfMembers=Anzahl der Mitglieder NoValidatedMemberYet=Kein freizugebenden Mitglieder gefunden MembersByCountryDesc=Diese Form zeigt Ihnen die Mitgliederstatistik nach Ländern. Die Grafik basiert auf Googles Online-Grafik-Service ab und funktioniert nur wenn eine Internverbindung besteht. diff --git a/htdocs/langs/de_DE/suppliers.lang b/htdocs/langs/de_DE/suppliers.lang index 945bea65fcd..e44f7ed7ccb 100644 --- a/htdocs/langs/de_DE/suppliers.lang +++ b/htdocs/langs/de_DE/suppliers.lang @@ -12,7 +12,6 @@ Supplier=Lieferant AddSupplier=Lieferanten hinzufügen SupplierRemoved=Lieferant entfernt SuppliersInvoice=Lieferantenrechnung -SuppliersInvoices=Lieferantenrechnungen NewSupplier=Neuer Lieferant History=Verlauf ListOfSuppliers=Lieferantenliste diff --git a/htdocs/langs/el_GR/install.lang b/htdocs/langs/el_GR/install.lang index bb68fd90a20..77b706254bc 100644 --- a/htdocs/langs/el_GR/install.lang +++ b/htdocs/langs/el_GR/install.lang @@ -119,8 +119,8 @@ YouMustCreateItAndAllowServerToWrite=You must create this directory and allow fo CharsetChoice=Character set choice CharacterSetClient=Character set used for generated HTML web pages CharacterSetClientComment=Choose character set for web display.
      Default proposed character set is the one of your database. -CollationConnection=Character sorting order -CollationConnectionComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      This parameter can't be defined if database already exists. +DBSortingCollation=Character sorting order +DBSortingCollationComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      This parameter can't be defined if database already exists. CharacterSetDatabase=Character set for database CharacterSetDatabaseComment=Choose character set wanted for database creation.
      This parameter can't be defined if database already exists. YouAskDatabaseCreationSoDolibarrNeedToConnect=You ask to create database %s, but for this, Dolibarr need to connect to server %s with super user %s permissions. diff --git a/htdocs/langs/el_GR/mails.lang b/htdocs/langs/el_GR/mails.lang index 3bde9b407b2..c2dd5f02e21 100644 --- a/htdocs/langs/el_GR/mails.lang +++ b/htdocs/langs/el_GR/mails.lang @@ -76,42 +76,7 @@ MailingModuleDescDolibarrUsers=All Dolibarr users with emails MailingModuleDescFundationMembers=Foundation members with emails MailingModuleDescEmailsFromFile=EMails from a text file (email;name;surname;comments) MailingModuleDescContactsCategories=Στοιχεία με emails (ανά κατηγορία) -MailingModuleDescDolibarrContractsLinesExpired=Third parties with expired contract's lines -LineInFile=Line %s in file -RecipientSelectionModules=Defined requests for recipient's selection -MailSelectedRecipients=Selected recipients -MailingArea=EMailings area -LastMailings=Last %s emailings -TargetsStatistics=Targets statistics -NbOfCompaniesContacts=Unique contacts of companies -MailNoChangePossible=Recipients for validated emailing can't be changed -SearchAMailing=Search mailing -SendMailing=Send emailing -SendMail=Send email -SentBy=Sent by -MailingNeedCommand=For securities reason, sending an emailing should be performed from command line. Ask your administrator to launch the following command to send the emailing to all recipients: -MailingNeedCommand2=You can however send them online by adding parameter MAILING_LIMIT_SENDBYWEB with value of max number of emails you want to send by session. For this, go on Home - Setup - Other. -ConfirmSendingEmailing=Are you sure you want to send mailing ? -LimitSendingEmailing=On line sending of emailings are limited for security and timeout reasons to %s recipients by sending session. -TargetsReset=Clear list -ToClearAllRecipientsClickHere=Click here to clear the recipient list for this emailing -ToAddRecipientsChooseHere=Add recipients by choosing from the lists -NbOfEMailingsReceived=Mass emailings received -IdRecord=ID record -DeliveryReceipt=Delivery Receipt -YouCanUseCommaSeparatorForSeveralRecipients=You can use the comma separator to specify several recipients. - -# Module Notifications -Notifications=Notifications -NoNotificationsWillBeSent=No email notifications are planned for this event and company -ANotificationsWillBeSent=1 notification will be sent by email -SomeNotificationsWillBeSent=%s notifications will be sent by email -AddNewNotification=Activate a new email notification request -ListOfActiveNotifications=List all active email notification requests -ListOfNotificationsDone=List all email notifications sent - - // START - Lines generated via autotranslator.php tool (2011-06-26 15:35:22). // Reference language: en_US -> el_GR MailingModuleDescContactsByCompanyCategory=Επαφές των τρίτων (από τρίτη κατηγορία μέρη) diff --git a/htdocs/langs/el_GR/members.lang b/htdocs/langs/el_GR/members.lang index f34d810adf1..8343aff155c 100644 --- a/htdocs/langs/el_GR/members.lang +++ b/htdocs/langs/el_GR/members.lang @@ -171,7 +171,7 @@ LastSubscriptionDate=Τελευταία ημερομηνία εγγραφής LastSubscriptionAmount=Τελευταία ποσό συνδρομής MembersStatisticsByCountries=Μέλη στατιστικές ανά χώρα MembersStatisticsByState=Τα μέλη στατιστικών στοιχείων από πολιτεία / επαρχία -MembersStatisticsByTowne=Τα μέλη στατιστικών στοιχείων από την πόλη +MembersStatisticsByTown=Τα μέλη στατιστικών στοιχείων από την πόλη NbOfMembers=Αριθμός μελών NoValidatedMemberYet=Δεν επικυρώνονται τα μέλη βρέθηκαν MembersByCountryDesc=Αυτή η οθόνη σας δείξει στατιστικά στοιχεία σχετικά με τα μέλη από τις χώρες. Graphic εξαρτάται, ωστόσο, στην υπηρεσία της Google online διάγραμμα και είναι διαθέσιμο μόνο αν μια σύνδεση στο Διαδίκτυο είναι λειτουργεί. diff --git a/htdocs/langs/el_GR/suppliers.lang b/htdocs/langs/el_GR/suppliers.lang index 5a42434f340..9db72404188 100644 --- a/htdocs/langs/el_GR/suppliers.lang +++ b/htdocs/langs/el_GR/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Προμηθευτής AddSupplier=Προσθήκη προμηθευτή SupplierRemoved=Ο προμηθευτής αφαιρέθηκε SuppliersInvoice=Τιμολόγιο προμηθευτή -SuppliersInvoices=Τιμολόγια προμηθευτών NewSupplier=Νέος προμηθευτής History=Ιστορικό ListOfSuppliers=Λίστα προμηθευτών diff --git a/htdocs/langs/en_SA/main.lang b/htdocs/langs/en_SA/main.lang new file mode 100644 index 00000000000..146ae3fd85e --- /dev/null +++ b/htdocs/langs/en_SA/main.lang @@ -0,0 +1,17 @@ +# Dolibarr language file - en_SA - main +CHARSET=UTF-8 +DIRECTION=ltr +FONTFORPDF=DejaVuSans +FONTSIZEFORPDF=9 +SeparatorDecimal=. +SeparatorThousand=, +FormatDateShort=%d/%m/%Y +FormatDateShortJava=dd/MM/yyyy +FormatDateShortJQuery=dd/mm/yy +FormatHourShort=%I:%M %p +FormatHourShortDuration=%H:%M +FormatDateTextShort=%d %b %Y +FormatDateText=%d %B %Y +FormatDateHourShort=%d/%m/%Y %I:%M %p +FormatDateHourTextShort=%d %b %Y, %I:%M %p +FormatDateHourText=%d %B %Y, %I:%M %p \ No newline at end of file diff --git a/htdocs/langs/en_SA/propal.lang b/htdocs/langs/en_SA/propal.lang new file mode 100644 index 00000000000..a985b025a19 --- /dev/null +++ b/htdocs/langs/en_SA/propal.lang @@ -0,0 +1,8 @@ +# Dolibarr language file - en_SA - propal +CHARSET=UTF-8 +Proposals=Commercial Proposals +Proposal=Commercial Proposal +Prop=Commercial Proposals +CommercialProposal=Commercial Proposal +CommercialProposals=Commercial Proposals +DateEndPropal=Validity Ending Date \ No newline at end of file diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 84a59052629..0919133f936 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -707,6 +707,20 @@ VATIsNotUsedDesc=By default the proposed VAT is 0 which can be used for cases li VATIsUsedExampleFR=In France, it means companies or organisations having a real fiscal system (Simplified real or normal real). A system in which VAT is declared. VATIsNotUsedExampleFR=In France, it means associations that are non VAT declared or companies, organisations or liberal professions that have chosen the micro enterprise fiscal system (VAT in franchise) and paid a franchise VAT without any VAT declaration. This choice will display the reference "Non applicable VAT - art-293B of CGI" on invoices. ##### Local Taxes ##### +LocalTax1IsUsed=Use second tax +LocalTax1IsNotUsed=Do not use second tax +LocalTax1IsUsedDesc=Use a second type of tax (other than VAT) +LocalTax1IsNotUsedDesc=Do not use other type of tax (other than VAT) +LocalTax1Management=Second type of tax +LocalTax1IsUsedExample= +LocalTax1IsNotUsedExample= +LocalTax2IsUsed=Use third tax +LocalTax2IsNotUsed=Do not use third tax +LocalTax2IsUsedDesc=Use a third type of tax (other than VAT) +LocalTax2IsNotUsedDesc=Do not use other type of tax (other than VAT) +LocalTax2Management=Third type of tax +LocalTax2IsUsedExample= +LocalTax2IsNotUsedExample= LocalTax1ManagementES= RE Management LocalTax1IsUsedDescES= The RE rate by default when creating prospects, invoices, orders etc follow the active standard rule:
      If te buyer is not subjected to RE, RE by default=0. End of rule.
      If the buyer is subjected to RE then the RE by default. End of rule.
      LocalTax1IsNotUsedDescES= By default the proposed RE is 0. End of rule. @@ -903,7 +917,7 @@ ExtraFieldsContacts=Complementary attributes (contact/address) ExtraFieldHasWrongValue=Attribut %s has a wrong value. AlphaNumOnlyCharsAndNoSpace=only alphanumericals characters without space SendingMailSetup=Setup of sendings by email -SendmailOptionNotComplete=Warning, on some Linux systems, to send email from your email, sendmail execution setup must conatins option -ba (parameter mail.force_extra_parameters into your php.ini file). If some recipients never receive emails, try to edit this PHP parameter with mail.force_extra_parameters = -ba). +SendmailOptionNotComplete=Warning, on some Linux systems, to send email from your email, sendmail execution setup must contains option -ba (parameter mail.force_extra_parameters into your php.ini file). If some recipients never receive emails, try to edit this PHP parameter with mail.force_extra_parameters = -ba). PathToDocuments=Path to documents PathDirectory=Directory SendmailOptionMayHurtBuggedMTA=Feature to send mails using method "PHP mail direct" will generate a mail message that might be not correctly parsed by some receiving mail servers. Result is that some mails can't be read by people hosted by thoose bugged platforms. It's case for some Internet providers (Ex: Orange in France). This is not a problem into Dolibarr nor into PHP but onto receiving mail server. You can however add option MAIN_FIX_FOR_BUGGED_MTA to 1 into setup - other to modify Dolibarr to avoid this. However, you may experience problem with other servers that respect strictly the SMTP standard. The other solution (recommanded) is to use the method "SMTP socket library" that has no disadvantages. @@ -939,6 +953,7 @@ DocumentModelOdt=Generate documents from OpenDocuments templates (.ODT files for WatermarkOnDraft=Watermark on draft document CompanyIdProfChecker=Professional Id unique MustBeUnique=Must be unique ? +MustBeMandatory=Must be mandatory ? Miscellanous=Miscellaneous ##### Webcal setup ##### WebCalSetup=Webcalendar link setup @@ -1309,6 +1324,7 @@ AccountancyCodeBuy=Purchase account. code AgendaSetup=Events and agenda module setup PasswordTogetVCalExport=Key to authorize export link PastDelayVCalExport=Do not export event older than +AGENDA_USE_EVENT_TYPE=Use events types (manage into Configuration->Dictionnary->llx_c_actioncomm) ##### ClickToDial ##### ClickToDialDesc=This module allows to add an icon after phone numbers. A click on this icon will call a server with a particular URL you define below. This can be used to call a call center system from Dolibarr that can call the phone number on a SIP system for example. ##### Point Of Sales (CashDesk) ##### diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 89238168e3a..6bd04970611 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -7,7 +7,7 @@ Agendas= Agendas Calendar= Calendar Calendars= Calendars LocalAgenda=Local calendar -AffectedTo= Affected to +AffectedTo= Assigned to DoneBy= Done by Events= Events MyEvents=My events @@ -22,7 +22,7 @@ MenuToDoMyActions= My incomplete events MenuDoneMyActions= My terminated events ListOfEvents= List of Dolibarr events ActionsAskedBy=Events reported by -ActionsToDoBy=Events affected to +ActionsToDoBy=Events assigned to ActionsDoneBy=Events done by AllMyActions= All my events/tasks AllActions= All events/tasks @@ -59,9 +59,9 @@ DateActionDoneEnd= Real end date DateActionStart= Start date DateActionEnd= End date AgendaUrlOptions1=You can also add following parameters to filter output: -AgendaUrlOptions2=login=%s to restrict output to actions created by, affected to or done by user %s. +AgendaUrlOptions2=login=%s to restrict output to actions created by, assigned to or done by user %s. AgendaUrlOptions3=logina=%s to restrict output to actions created by user %s. -AgendaUrlOptions4=logint=%s to restrict output to actions affected to user %s. +AgendaUrlOptions4=logint=%s to restrict output to actions assigned to user %s. AgendaUrlOptions5=logind=%s to restrict output to actions done by user %s. AgendaShowBirthdayEvents=Show birthday's contacts AgendaHideBirthdayEvents=Hide birthday's contacts diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 6195a5147b9..01cbb6950d4 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -49,9 +49,9 @@ Invoices=Invoices InvoiceLine=Invoice line InvoiceCustomer=Customer invoice CustomerInvoice=Customer invoice -CustomersInvoices=Customer's invoices +CustomersInvoices=Customers invoices SupplierInvoice=Supplier invoice -SuppliersInvoices=Supplier's invoices +SuppliersInvoices=Suppliers invoices SupplierBill=Supplier invoice SupplierBills=suppliers invoices Payment=Payment diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index 78a9efcc083..2f252d39923 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -20,7 +20,6 @@ AddThisArticle=Add this article RestartSelling=Go back on sell SellFinished=Sell finished PrintTicket=Print ticket -NoResults=No results NoProductFound=No article found ProductFound=product found ProductsFound=products found diff --git a/htdocs/langs/en_US/commercial.lang b/htdocs/langs/en_US/commercial.lang index 8eebe14d634..baac58e4642 100644 --- a/htdocs/langs/en_US/commercial.lang +++ b/htdocs/langs/en_US/commercial.lang @@ -31,7 +31,7 @@ SalesRepresentativeFollowUp=Sales representative (follow-up) SalesRepresentativeSignature=Sales representative (signature) CommercialInterlocutor=Commercial interlocutor ErrorWrongCode=Wrong code -NoSalesRepresentativeAffected=No particular sales representative affected +NoSalesRepresentativeAffected=No particular sales representative assigned ShowCustomer=Show customer ShowProspect=Show prospect ListOfProspects=List of prospects @@ -52,7 +52,7 @@ StatusActionToDo=To do StatusActionDone=Complete MyActionsAsked=Events I have recorded MyActionsToDo=Events I have to do -MyActionsDone=Events affected to me +MyActionsDone=Events assigned to me StatusActionInProcess=In process TasksHistoryForThisContact=Events for this contact LastProspectDoNotContact=Do not contact @@ -63,7 +63,7 @@ LastProspectContactDone=Contact done DateActionPlanned=Date event planned for DateActionDone=Date event done ActionAskedBy=Event reported by -ActionAffectedTo=Event affected to +ActionAffectedTo=Event assigned to ActionDoneBy=Event done by ActionUserAsk=Reported by ErrorStatusCantBeZeroIfStarted=If field 'Date done' is filled, action is started (or finished), so field 'Status' can't be 0%%. @@ -81,6 +81,8 @@ ActionAC_SHIP=Send shipping by mail ActionAC_SUP_ORD=Send supplier order by mail ActionAC_SUP_INV=Send supplier invoice by mail ActionAC_OTH=Other +ActionAC_MANUAL=Manually inserted events +ActionAC_AUTO=Automatically inserted events Stats=Sales statistics CAOrder=Sales volume (validated orders) FromTo=from %s to %s diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 19a36f64c22..f2f537453e7 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -25,6 +25,7 @@ ErrorThisContactIsAlreadyDefinedAsThisType=This contact is already defined as co ErrorCashAccountAcceptsOnlyCashMoney=This bank account is a cash account, so it accepts payments of type cash only. ErrorFromToAccountsMustDiffers=Source and targets bank accounts must be different. ErrorBadThirdPartyName=Bad value for third party name +ErrorProdIdIsMandatory=The %s is mandatory ErrorBadCustomerCodeSyntax=Bad syntax for customer code ErrorCustomerCodeRequired=Customer code required ErrorCustomerCodeAlreadyUsed=Customer code already used diff --git a/htdocs/langs/en_US/exports.lang b/htdocs/langs/en_US/exports.lang index e29fb718c08..4ec1482ffb3 100644 --- a/htdocs/langs/en_US/exports.lang +++ b/htdocs/langs/en_US/exports.lang @@ -115,7 +115,7 @@ CSVFormatDesc=Comma Separated Value file format (.csv).
      This is a text Excel95FormatDesc=Excel file format (.xls)
      This is native Excel 95 format (BIFF5). Excel2007FormatDesc=Excel file format (.xlsx)
      This is native Excel 2007 format (SpreadsheetML). TsvFormatDesc=Tab Separated Value file format (.tsv)
      This is a text file format where fields are separated by a tabulator [tab]. -ExportFieldAutomaticallyAdded=Field %s was automatically added. It will avoid you to have similar lines to be treated as duplicate records (with this field added, all ligne will own its own id and will differ). +ExportFieldAutomaticallyAdded=Field %s was automatically added. It will avoid you to have similar lines to be treated as duplicate records (with this field added, all lines will own their own id and will differ). CsvOptions=Csv Options Separator=Separator Enclosure=Enclosure diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index da2623028fa..f111bfad1d6 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -124,8 +124,8 @@ YouMustCreateItAndAllowServerToWrite=You must create this directory and allow fo CharsetChoice=Character set choice CharacterSetClient=Character set used for generated HTML web pages CharacterSetClientComment=Choose character set for web display.
      Default proposed character set is the one of your database. -CollationConnection=Character sorting order -CollationConnectionComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      This parameter can't be defined if database already exists. +DBSortingCollation=Character sorting order +DBSortingCollationComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      This parameter can't be defined if database already exists. CharacterSetDatabase=Character set for database CharacterSetDatabaseComment=Choose character set wanted for database creation.
      This parameter can't be defined if database already exists. YouAskDatabaseCreationSoDolibarrNeedToConnect=You ask to create database %s, but for this, Dolibarr need to connect to server %s with super user %s permissions. diff --git a/htdocs/langs/en_US/interventions.lang b/htdocs/langs/en_US/interventions.lang index 1b531deed38..117a3481bae 100644 --- a/htdocs/langs/en_US/interventions.lang +++ b/htdocs/langs/en_US/interventions.lang @@ -24,6 +24,7 @@ ConfirmDeleteInterventionLine=Are you sure you want to delete this intervention NameAndSignatureOfInternalContact=Name and signature of intervening : NameAndSignatureOfExternalContact=Name and signature of customer : DocumentModelStandard=Standard document model for interventions +InterventionCardsAndInterventionLines=Interventions and lines of interventions ClassifyBilled=Classify "Billed" StatusInterInvoiced=Billed RelatedInterventions=Related interventions diff --git a/htdocs/langs/en_US/languages.lang b/htdocs/langs/en_US/languages.lang index e2f8cd0a510..8f79cd99fe0 100644 --- a/htdocs/langs/en_US/languages.lang +++ b/htdocs/langs/en_US/languages.lang @@ -14,6 +14,7 @@ Language_en_AU=English (Australia) Language_en_GB=English (United Kingdom) Language_en_IN=English (India) Language_en_NZ=English (New Zealand) +Language_en_SA=English (Saudi Arabia) Language_en_US=English (United States) Language_es_ES=Spanish Language_es_AR=Spanish (Argentina) diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index f9c0d0f198f..f143a7fa167 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -77,8 +77,9 @@ MailingStatusRead=Read CheckRead=Read Receipt YourMailUnsubcribeOK=The email %s is correctly unsubcribe from mailing list MailtoEMail=Hyper link to email -ActivateCheckRead=Allow to use the Read receipt tracker and the unsubcribe link -ActivateCheckReadKey=Key use to encrypt URL use for Read Receipt and unsubcribe function +ActivateCheckRead=Allow to use the "Read receipt" tracker and the "Unsubcribe" link +ActivateCheckReadKey=Key use to encrypt URL use for "Read Receipt" and "Unsubcribe" feature +EMailSentToNRecipients=EMail sent to %s recipients. # Libelle des modules de liste de destinataires mailing MailingModuleDescContactCompanies=Contacts of all third parties (customer, prospect, supplier, ...) @@ -105,7 +106,7 @@ SearchAMailing=Search mailing SendMailing=Send emailing SendMail=Send email SentBy=Sent by -MailingNeedCommand=For security reason, sending an emailing should be performed from command line. Ask your administrator to launch the following command to send the emailing to all recipients: +MailingNeedCommand=For security reason, sending an emailing is better when performed from command line. Ask your administrator to launch the following command to send the emailing to all recipients: MailingNeedCommand2=You can however send them online by adding parameter MAILING_LIMIT_SENDBYWEB with value of max number of emails you want to send by session. For this, go on Home - Setup - Other. ConfirmSendingEmailing=Are you sure you want to send emailing without command line and from web mode ? LimitSendingEmailing=On line sending of emailings are limited for security and timeout reasons to %s recipients by sending session. diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 36866d73a8a..088e5076733 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -627,6 +627,7 @@ BySalesRepresentative=By sales representative LinkedToSpecificUsers=Linked to a particular user contact DeleteAFile=Delete a file ConfirmDeleteAFile=Are you sure you want to delete file +NoResults=No results # Week day Monday=Monday diff --git a/htdocs/langs/en_US/margins.lang b/htdocs/langs/en_US/margins.lang index 41203847ba5..10a8112f87e 100644 --- a/htdocs/langs/en_US/margins.lang +++ b/htdocs/langs/en_US/margins.lang @@ -47,6 +47,7 @@ MARGIN_TYPE_DETAILS=Raw margin : Selling price - Buying price
      Net margin : S BuyingCost=Cost price UnitCharges=Unit charges +Charges=Charges AgentContactType=Contact type used for commissioning AgentContactTypeDetails=Défine what contact type (linked on invoices) will be associated with commercial agents \ No newline at end of file diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index ff993ec620a..8956502c3a9 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -170,7 +170,7 @@ LastSubscriptionDate=Last subscription date LastSubscriptionAmount=Last subscription amount MembersStatisticsByCountries=Members statistics by country MembersStatisticsByState=Members statistics by state/province -MembersStatisticsByTowne=Members statistics by town +MembersStatisticsByTown=Members statistics by town NbOfMembers=Number of members NoValidatedMemberYet=No validated members found MembersByCountryDesc=This screen show you statistics on members by countries. Graphic depends however on Google online graph service and is available only if an internet connection is is working. @@ -196,3 +196,6 @@ Collectivités=Organizations Particuliers=Personal Entreprises=Companies DOLIBARRFOUNDATION_PAYMENT_FORM=To make your subscription payment using a bank transfer, see page http://wiki.dolibarr.org/index.php/Subscribe.
      To pay using a Credit Card or Paypal, click on button at bottom of this page.
      +ByProperties=By characteristics +MembersStatisticsByProperties=Members statistics by characteristics +MembersByNature=Members by nature diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 18844f91868..3851d6b9967 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -93,6 +93,7 @@ CloneFiles=Clone joined files ConfirmCloneProject=Are you sure to clone this project ? ProjectReportDate=Change task date according project start date ErrorShiftTaskDate=Impossible to shift task date according to new project start date +ProjectsAndTasksLines=Projects and tasks ##### Types de contacts ##### TypeContact_project_internal_PROJECTLEADER=Project leader TypeContact_project_external_PROJECTLEADER=Project leader diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index 78119f38ebb..3f76ca5ecda 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -61,7 +61,7 @@ FileUploaded=The file was successfully uploaded AssociatedDocuments=Documents associated with the proposal: ErrorCantOpenDir=Can't open directory DatePropal=Date of proposal -DateEndPropal=Date end validity +DateEndPropal=Validity ending date DateEndPropalShort=Date end ValidityDuration=Validity duration CloseAs=Close with status diff --git a/htdocs/langs/en_US/sendings.lang b/htdocs/langs/en_US/sendings.lang index 90fc0c7c3e2..a4299fb94ab 100644 --- a/htdocs/langs/en_US/sendings.lang +++ b/htdocs/langs/en_US/sendings.lang @@ -58,6 +58,7 @@ ActionsOnShipping=Events on shipment LinkToTrackYourPackage=Link to track your package ShipmentCreationIsDoneFromOrder=For the moment, creation of a new shipment is done from the order card. RelatedShippings=Related shippings +ShipmentLine=Shipment line # Sending methods SendingMethodCATCH=Catch by customer diff --git a/htdocs/langs/en_US/suppliers.lang b/htdocs/langs/en_US/suppliers.lang index fd5a35d3f53..8f05c209b95 100644 --- a/htdocs/langs/en_US/suppliers.lang +++ b/htdocs/langs/en_US/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Supplier AddSupplier=Add a supplier SupplierRemoved=Supplier removed SuppliersInvoice=Suppliers invoice -SuppliersInvoices=Suppliers invoices NewSupplier=New supplier History=History ListOfSuppliers=List of suppliers diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index b836554c2ea..c6f9ba97874 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -61,7 +61,7 @@ LastGroupsCreated=Last %s created groups LastUsersCreated=Last %s users created ShowGroup=Show group ShowUser=Show user -NonAffectedUsers=Non affected users +NonAffectedUsers=Non assigned users UserModified=User modified successfully GroupModified=Group modified successfully PhotoFile=Photo file diff --git a/htdocs/langs/en_US/withdrawals.lang b/htdocs/langs/en_US/withdrawals.lang index 5488f674620..fe9fa0a9b99 100644 --- a/htdocs/langs/en_US/withdrawals.lang +++ b/htdocs/langs/en_US/withdrawals.lang @@ -81,6 +81,9 @@ WithdrawalFileNotCapable=Unable to generate withdrawal receipt file for your cou ShowWithdraw=Show Withdraw IfInvoiceNeedOnWithdrawPaymentWontBeClosed=However, if invoice has at least one withdrawal payment not yet processed, it won't be set as payed to allow to manage withdrawal before. DoStandingOrdersBeforePayments=This tabs allows you to request for a standing order. Once it will be finished, you can type the payment to close the invoice. +WithdrawalFile=Withdrawal file +SetToStatusSent=Set to status "File Sent" +ThisWillAlsoAddPaymentOnInvoice=This will also create payments onto invoices and will classify them to paid ### Notifications InfoCreditSubject=Payment of standing order %s by the bank diff --git a/htdocs/langs/es_ES/admin.lang b/htdocs/langs/es_ES/admin.lang index d5a9df404a9..7a7a53a6654 100644 --- a/htdocs/langs/es_ES/admin.lang +++ b/htdocs/langs/es_ES/admin.lang @@ -720,6 +720,20 @@ VATIsNotUsedDesc=El tipo de IVA propuesto por defecto es 0. Este es el caso de a VATIsUsedExampleFR=En Francia, se trata de las sociedades u organismos que eligen un régimen fiscal general (General simplificado o General normal), régimen en el cual se declara el IVA. VATIsNotUsedExampleFR=En Francia, se trata de asociaciones exentas de IVA o sociedades, organismos o profesiones liberales que han elegido el régimen fiscal de módulos (IVA en franquicia), pagando un IVA en franquicia sin hacer declaración de IVA. Esta elección hace aparecer la anotación "IVA no aplicable - art-293B del CGI" en las facturas. ##### Local Taxes ##### +LocalTax1IsUsed=Sujeto +LocalTax1IsNotUsed=No sujeto +LocalTax1IsUsedDesc=Uso de un 2º tipo de impuesto (Distinto del IVA) +LocalTax1IsNotUsedDesc=No usar un 2º tipo de impuesto (Distinto del IVA) +LocalTax1Management=Gestión 2º tipo de impuesto +LocalTax1IsUsedExample= +LocalTax1IsNotUsedExample= +LocalTax2IsUsed=Sujeto +LocalTax2IsNotUsed=No sujeto +LocalTax2IsUsedDesc=Uso de un 3er. tipo de impuesto (Distinto del IVA) +LocalTax2IsNotUsedDesc=No usar un 3er. tipo de impuesto (Distinto del IVA) +LocalTax2Management=Gestión 3er. tipo de impuesto +LocalTax2IsUsedExample= +LocalTax2IsNotUsedExample= LocalTax1ManagementES=Gestión RE LocalTax1IsUsedDescES=El tipo de RE propuesto por defecto en las creaciones de presupuestos, facturas, pedidos, etc. Responde a la siguiente regla:
      Si el comprador no está sujeto a RE, RE por defecto=0. Final de regla.
      Si el comprador está sujeto a RE entonces se aplica valor de RE por defecto. Final de regla.
      LocalTax1IsNotUsedDescES=El tipo de RE propuesto por defecto es 0. Final de regla. @@ -952,6 +966,7 @@ DocumentModelOdt=Generación desde los documentos OpenDocument (Archivo .ODT Ope WatermarkOnDraft=Marca de agua en los documentos borrador CompanyIdProfChecker=Id Profesional único MustBeUnique=¿Debe ser único? +MustBeMandatory=¿Debe ser obligatorio? Miscellanous=Miscelánea ##### Webcal setup ##### WebCalSetup=Configuración de enlace con el calendario Webcalendar diff --git a/htdocs/langs/es_ES/bills.lang b/htdocs/langs/es_ES/bills.lang index 63a33d062b0..42e5f4c60ba 100644 --- a/htdocs/langs/es_ES/bills.lang +++ b/htdocs/langs/es_ES/bills.lang @@ -47,7 +47,7 @@ InvoiceCustomer=Factura a cliente CustomerInvoice=Factura a cliente CustomersInvoices=Facturas a clientes SupplierInvoice=Factura de proveedor -SuppliersInvoices=Facturas de proveedores +SuppliersInvoices=Facturas proveedores SupplierBill=Factura de proveedor SupplierBills=Facturas de proveedores Payment=Pago diff --git a/htdocs/langs/es_ES/boxes.lang b/htdocs/langs/es_ES/boxes.lang index 948d023efcf..72c4363ebe5 100644 --- a/htdocs/langs/es_ES/boxes.lang +++ b/htdocs/langs/es_ES/boxes.lang @@ -3,6 +3,7 @@ CHARSET=UTF-8 BoxLastRssInfos=Hilos de información RSS BoxLastProducts=Los %s últimos productos/servicios BoxLastProductsInContract=Los %s últimos productos/servicios contratados +BoxProductsAlertStock=Productos en alerta de stock BoxLastSupplierBills=Últimas facturas de proveedores BoxLastCustomerBills=Últimas facturas a clientes BoxOldestUnpaidCustomerBills=Facturas a clientes más antiguas pendientes de pago @@ -25,6 +26,7 @@ BoxTitleLastBooks=Los %s últimos marcadores registrados BoxTitleNbOfCustomers=Número de clientes BoxTitleLastRssInfos=Las %s últimas infos de %s BoxTitleLastProducts=Los %s últimos productos/servicios registrados +BoxTitleProductsAlertStock=Productos en alerta de stock BoxTitleLastCustomerOrders=Los %s últimos pedidos de clientes modificados BoxTitleLastSuppliers=Los %s últimos proveedores registrados BoxTitleLastCustomers=Los %s últimos clientes registrados diff --git a/htdocs/langs/es_ES/cashdesk.lang b/htdocs/langs/es_ES/cashdesk.lang index 2520879a012..9cba2e3c687 100644 --- a/htdocs/langs/es_ES/cashdesk.lang +++ b/htdocs/langs/es_ES/cashdesk.lang @@ -20,7 +20,6 @@ AddThisArticle=Añadir este artículo RestartSelling=Retomar la venta SellFinished=Venta terminada PrintTicket=Imprimir ticket -NoResults=Ningún resultado NoProductFound=Ningún artículo encontrado ProductFound=Producto encontrado ProductsFound=Productos encontrados diff --git a/htdocs/langs/es_ES/commercial.lang b/htdocs/langs/es_ES/commercial.lang index c05a6b26395..3b5d007aac9 100644 --- a/htdocs/langs/es_ES/commercial.lang +++ b/htdocs/langs/es_ES/commercial.lang @@ -81,6 +81,8 @@ ActionAC_SHIP=Envío expedición por correo ActionAC_SUP_ORD=Envío pedido a proveedor por correo ActionAC_SUP_INV=Envío factura de proveedor por correo ActionAC_OTH=Otra +ActionAC_MANUAL=Eventos creados manualmente +ActionAC_AUTO=Eventos creados automáticamente Stats=Estadísticas de venta CAOrder=Volumen de ventas (Pedidos validados) FromTo=de %s a %s diff --git a/htdocs/langs/es_ES/companies.lang b/htdocs/langs/es_ES/companies.lang index 9313df97434..511921a014b 100644 --- a/htdocs/langs/es_ES/companies.lang +++ b/htdocs/langs/es_ES/companies.lang @@ -109,17 +109,20 @@ ProfId2AR=Ingresos brutos ProfId3AR=- ProfId4AR=- ProfId5AR=- +ProfId6AR=- ProfId1AU=ABN ProfId2AU=- ProfId3AU=- ProfId4AU=- ProfId5AU=- +ProfId6AU=- ProfId1BE=N° colegiado ProfId2BE=- ProfId3BE=- ProfId4BE=- ProfId5BE=- -ProfId1BR=CNPJ +ProfId6BE=- +ProfId1BR=- ProfId2BR=IE (Inscricao Estadual) ProfId3BR=IM (Inscricao Municipal) ProfId4BR=CPF @@ -130,21 +133,25 @@ ProfId2CH=- ProfId3CH=Número federado ProfId4CH=Num registro de comercio ProfId5CH=- +ProfId6CH=- ProfId1CL=R.U.T. ProfId2CL=- ProfId3CL=- ProfId4CL=- ProfId5CL=- +ProfId6CL=- ProfId1CO=R.U.T. ProfId2CO=- ProfId3CO=- ProfId4CO=- ProfId5CO=- +ProfId6CO=- ProfId1DE=Id prof. 1 (USt.-IdNr) ProfId2DE=Id prof. 2 (USt.-Nr) ProfId3DE=Id prof. 3 (Handelsregister-Nr.) ProfId4DE=- ProfId5DE=- +ProfId6DE=- ProfId1ES=CIF/NIF ProfId2ES=Núm seguridad social ProfId3ES=CNAE @@ -162,51 +169,61 @@ ProfId2GB=- ProfId3GB=SIC ProfId4GB=- ProfId5GB=- +ProfId6GB=- ProfId1HN=RTN ProfId2HN=- ProfId3HN=- ProfId4HN=- ProfId5HN=- +ProfId6HN=- ProfId1IN=Id prof. 1 (TIN) ProfId2IN=Id prof. 2 ProfId3IN=Id prof. 3 ProfId4IN=Id prof. 4 ProfId5IN=Id prof. 5 +ProfId6IN=- ProfId1MA=Id prof. 1 (R.C.) ProfId2MA=Id prof. 2 (Patente) ProfId3MA=Id prof. 3 (I.F.) ProfId4MA=Id prof. 4 (C.N.S.S.) -ProfId5MA=Id prof. 5 +ProfId5MA=- +ProfId6MA=- ProfId1MX=R.F.C. ProfId2MX=Registro Patronal IMSS ProfId3MX=Cédula Profesional ProfId4MX=- ProfId5MX=- +ProfId6MX=- ProfId1NL=Número KVK ProfId2NL=- ProfId3NL=- ProfId4NL=- ProfId5NL=- +ProfId6NL=- ProfId1PT=NIPC ProfId2PT=Núm. seguridad social ProfId3PT=Num reg. comercial ProfId4PT=Conservatorio ProfId5PT=- +ProfId6PT=- ProfId1RU=OGRN ProfId2RU=INN ProfId3RU=KPP ProfId4RU=OKPO ProfId5RU=- +ProfId6RU=- ProfId1SN=RC ProfId2SN=NINEA ProfId3SN=- ProfId4SN=- ProfId5SN=- +ProfId6SN=- ProfId1TN=RC ProfId2TN=Matrícula fiscal ProfId3TN=Código en aduana ProfId4TN=CCC ProfId5TN=- +ProfId6TN=- VATIntra=NIF intracomunitario VATIntraShort=NIF intra. VATIntraVeryShort=NIF intra. diff --git a/htdocs/langs/es_ES/errors.lang b/htdocs/langs/es_ES/errors.lang index 580627e6cab..d723910a5bd 100644 --- a/htdocs/langs/es_ES/errors.lang +++ b/htdocs/langs/es_ES/errors.lang @@ -21,6 +21,7 @@ ErrorThisContactIsAlreadyDefinedAsThisType=Este contacto ya está definido como ErrorCashAccountAcceptsOnlyCashMoney=Esta cuenta bancaria es de tipo caja y solo acepta el método de pago de tipo especie. ErrorFromToAccountsMustDiffers=La cuenta origen y destino deben ser diferentes. ErrorBadThirdPartyName=Nombre de tercero incorrecto +ErrorProdIdIsMandatory=El %s es obligatorio ErrorBadCustomerCodeSyntax=La sintaxis del código cliente es incorrecta ErrorCustomerCodeRequired=Código cliente obligatorio ErrorCustomerCodeAlreadyUsed=Código de cliente ya utilizado diff --git a/htdocs/langs/es_ES/exports.lang b/htdocs/langs/es_ES/exports.lang index 667c2a645e1..5308c2fa9aa 100644 --- a/htdocs/langs/es_ES/exports.lang +++ b/htdocs/langs/es_ES/exports.lang @@ -123,4 +123,8 @@ SuppliersProducts=Productos de proveedores BankCode=Código banco DeskCode=Código oficina BankAccountNumber=Número cuenta -BankAccountNumberKey=Dígito Control \ No newline at end of file +BankAccountNumberKey=Dígito Control +## filters +FilterableFields=Campos filtrables +FilteredFields=Campos filtrados +FilteredFieldsValues=Valores de filtros \ No newline at end of file diff --git a/htdocs/langs/es_ES/install.lang b/htdocs/langs/es_ES/install.lang index 700fdf4d022..a4e15bfe9d2 100644 --- a/htdocs/langs/es_ES/install.lang +++ b/htdocs/langs/es_ES/install.lang @@ -125,8 +125,8 @@ YouMustCreateItAndAllowServerToWrite=Debe crear este directorio y permitir al se CharsetChoice=Elección del juego de caracteres CharacterSetClient=Codificación utilizada para la visualización de las páginas CharacterSetClientComment=Puede elegir la codificación que desea para la visualización de las páginas.
      La codificación propuesta por defecto es la de su base de datos. -CollationConnection=Orden de selección utilizado para la base de datos -CollationConnectionComment=Puede elegir la página de código por la que se define el orden de selección de los caracteres utilizado por la base de datos. Este parámetro también es llamado 'cotejo' por algunas bases de datos.
      Este parámetro no es seleccionable si la base de datos ya está creada +DBSortingCollation=Orden de selección utilizado para la base de datos +DBSortingCollationComment=Puede elegir la página de código por la que se define el orden de selección de los caracteres utilizado por la base de datos. Este parámetro también es llamado 'cotejo' por algunas bases de datos.
      Este parámetro no es seleccionable si la base de datos ya está creada CharacterSetDatabase=Codificación utilizada por la base de datos CharacterSetDatabaseComment=Puede elegir la codificación que desea en la creación de la base de datos.
      Este parámetro no es seleccionable si la base de datos ya está creada YouAskDatabaseCreationSoDolibarrNeedToConnect=Quiso crear la base de datos %s, pero para ello Dolibarr debe conectarse con el servidor %s vía el superusuario %s. diff --git a/htdocs/langs/es_ES/languages.lang b/htdocs/langs/es_ES/languages.lang index 41128cb4c3f..0e537271c37 100644 --- a/htdocs/langs/es_ES/languages.lang +++ b/htdocs/langs/es_ES/languages.lang @@ -14,6 +14,7 @@ Language_en_AU=Inglés (Australia) Language_en_GB=Inglés (Reino Unido) Language_en_IN=Inglés (India) Language_en_NZ=Inglés (Nueva Zelanda) +Language_en_SA=Inglés (Arabia Saudita) Language_en_US=Inglés (Estados Unidos) Language_es_ES=Español Language_es_AR=Español (Argentina) @@ -45,4 +46,5 @@ Language_tr_TR=Turco Language_sl_SI=Esloveno Language_sv_SV=Sueco Language_sv_SE=Sueco -Language_zh_CN=Chino \ No newline at end of file +Language_zh_CN=Chino +Language_zh_TW=Chino (Tradicional) \ No newline at end of file diff --git a/htdocs/langs/es_ES/mails.lang b/htdocs/langs/es_ES/mails.lang index de9216ef367..1885d285946 100644 --- a/htdocs/langs/es_ES/mails.lang +++ b/htdocs/langs/es_ES/mails.lang @@ -78,6 +78,7 @@ YourMailUnsubcribeOK=El correo electrónico %s es correcta desuscribe. MailtoEMail=mailto email (hyperlink) ActivateCheckRead=Activar confirmación de lectura y opción de desuscripción ActivateCheckReadKey=Clave usada para encriptar la URL de la confirmación de lectura y la función de desuscripción +EMailSentToNRecipients=E-Mail enviado a %s destinatarios. # Libelle des modules de liste de destinataires mailing= MailingModuleDescContactCompanies=Contactos de terceros (clientes potenciales, clientes, proveedores...) diff --git a/htdocs/langs/es_ES/main.lang b/htdocs/langs/es_ES/main.lang index 102624c20dc..17be1964762 100644 --- a/htdocs/langs/es_ES/main.lang +++ b/htdocs/langs/es_ES/main.lang @@ -627,8 +627,8 @@ ByDay=Por día BySalesRepresentative=Por comercial LinkedToSpecificUsers=Enlazado a un contacto de usuario particular DeleteAFile=Eliminación de archivo -ConfirmDeleteAFile=Confirma la eliminación del archivo - +ConfirmDeleteAFile=Confirme la eliminación del archivo +NoResults=Ningún resultado # Week day Monday=Lunes Tuesday=Martes diff --git a/htdocs/langs/es_ES/margins.lang b/htdocs/langs/es_ES/margins.lang index 5ff7b74b7d4..0dc08481c46 100644 --- a/htdocs/langs/es_ES/margins.lang +++ b/htdocs/langs/es_ES/margins.lang @@ -46,4 +46,8 @@ MargeNette=Margen neto MARGIN_TYPE_DETAILS=Margen bruto : Precio de venta sin IVA - Precio de compra sin IVA
      Margen neto : Precio de venta sin IVA - Costos BuyingCost=Costos -UnitCharges=Carga unitaria \ No newline at end of file +UnitCharges=Carga unitaria +Charges=Cargas + +AgentContactType=Tipo de contacto comisionado +AgentContactTypeDetails=Indica el tipo de contacto enlazado a las facturas que serán asociados a los agentes comerciales \ No newline at end of file diff --git a/htdocs/langs/es_ES/members.lang b/htdocs/langs/es_ES/members.lang index ecd037cbaa8..2050ca73d60 100644 --- a/htdocs/langs/es_ES/members.lang +++ b/htdocs/langs/es_ES/members.lang @@ -199,3 +199,6 @@ Collectivités=Colectividades Particuliers=Particulares Entreprises=Empresas DOLIBARRFOUNDATION_PAYMENT_FORM=Para realizar el pago de su cotización por transferencia bancaria, visite la página http://wiki.dolibarr.org/index.php/Subscribirse.
      Para pagar con tarjeta de crédito o PayPal, haga clic en el botón en la parte inferior de esta página.

      +ByProperties=Por características +MembersStatisticsByProperties=Estadísticas de los miembros por características +MembersByNature=Miembros por naturaleza \ No newline at end of file diff --git a/htdocs/langs/es_ES/products.lang b/htdocs/langs/es_ES/products.lang index 97d4586bae6..a3c2bf41eb7 100644 --- a/htdocs/langs/es_ES/products.lang +++ b/htdocs/langs/es_ES/products.lang @@ -146,6 +146,8 @@ ProductSpecial=Especial QtyMin=Cantidad mínima PriceQty=Precio para la cantidad PriceQtyMin=Precio cantidad mín. +DiscountQtyMin=Descuento por defecto cantidad mín. +VATRateForSupplierProduct=Tasa IVA (para este producto/proveedor) NoPriceDefinedForThisSupplier=Ningún precio/cant. definido para este proveedor/producto NoSupplierPriceDefinedForThisProduct=Ningún precio/cant. proveedor definida para este producto RecordedProducts=Productos en venta diff --git a/htdocs/langs/es_ES/projects.lang b/htdocs/langs/es_ES/projects.lang index 979f70f813f..0ee3925cdda 100644 --- a/htdocs/langs/es_ES/projects.lang +++ b/htdocs/langs/es_ES/projects.lang @@ -93,6 +93,7 @@ CloneFiles=Clonar los archivos adjuntos ConfirmCloneProject=¿Está seguro de querer clonar este proyecto? ProjectReportDate=Cambiar las fechas de las tareas en función de la fecha de inicio del proyecto ErrorShiftTaskDate=Se ha producido un error en el cambio de las fechas de las tareas +ProjectsAndTasksLines=Proyectos y tareas ##### Types de contacts ##### TypeContact_project_internal_PROJECTLEADER=Jefe de proyecto TypeContact_project_external_PROJECTLEADER=Jefe de proyecto diff --git a/htdocs/langs/es_ES/sendings.lang b/htdocs/langs/es_ES/sendings.lang index 113af44ba93..7efaabc81cd 100644 --- a/htdocs/langs/es_ES/sendings.lang +++ b/htdocs/langs/es_ES/sendings.lang @@ -58,6 +58,7 @@ ActionsOnShipping=Eventos sobre la expedición LinkToTrackYourPackage=Enlace para el seguimento de su paquete ShipmentCreationIsDoneFromOrder=De momento, la creación de una nueva expedición se realiza desde la ficha de pedido. RelatedShippings=Expedición(es) asociada(s) +ShipmentLine=Línea de expedición # Sending methods SendingMethodCATCH=Recogido por el cliente diff --git a/htdocs/langs/es_ES/suppliers.lang b/htdocs/langs/es_ES/suppliers.lang index a03eccb719f..e500aea17bb 100644 --- a/htdocs/langs/es_ES/suppliers.lang +++ b/htdocs/langs/es_ES/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Proveedor AddSupplier=Añadir proveedor SupplierRemoved=Proveedor eliminado SuppliersInvoice=Factura proveedor -SuppliersInvoices=Facturas proveedores NewSupplier=Nuevo proveedor History=Histórico ListOfSuppliers=Listado de proveedores diff --git a/htdocs/langs/es_ES/withdrawals.lang b/htdocs/langs/es_ES/withdrawals.lang index 6876b3f643a..bbbee4a6198 100644 --- a/htdocs/langs/es_ES/withdrawals.lang +++ b/htdocs/langs/es_ES/withdrawals.lang @@ -34,7 +34,7 @@ MakeWithdrawRequest=Realizar una petición de domiciliación ThirdPartyBankCode=Código banco del tercero ThirdPartyDeskCode=Código oficina del tercero NoInvoiceCouldBeWithdrawed=No se ha domiciliado ninguna factura. Asegúrese de que las facturas son de empresas con los datos de cuentas bancarias correctos. -ClassCredited=Abonar +ClassCredited=Clasificar como "Abonada" ClassCreditedConfirm=¿Está seguro de querer clasificar esta domiciliación como abonada en su cuenta bancaria? TransData=Fecha envío TransMetod=Método envío @@ -81,6 +81,9 @@ WithdrawalFileNotCapable=No es posible generar fichero bancario de domiciliacion ShowWithdraw=Ver domiciliación IfInvoiceNeedOnWithdrawPaymentWontBeClosed=Sin embargo, si la factura tiene pendiente algún pago por domiciliación, no será cerrada para permitir la gestión de la domiciliación. DoStandingOrdersBeforePayments=Esta pestaña le permite realizar una petición de domiciliación. Una vez terminada, puede ingresar el pago en la factura para proceder a su cierre. +WithdrawalFile=Archivo de la domiciliación +SetToStatusSent=Clasificar como "Archivo enviado" +ThisWillAlsoAddPaymentOnInvoice=Se crearán los pagos de las facturas y las clasificará como pagadas ### Notifications InfoCreditSubject=Abono de domiciliación %s por el banco diff --git a/htdocs/langs/et_EE/install.lang b/htdocs/langs/et_EE/install.lang index a6de684d06a..6ec8e605c2a 100644 --- a/htdocs/langs/et_EE/install.lang +++ b/htdocs/langs/et_EE/install.lang @@ -131,8 +131,8 @@ YouMustCreateItAndAllowServerToWrite=Peate looma selle kataloogi ning võimaldab CharsetChoice=Kooditabel valik CharacterSetClient=Märgistikku kasutatakse genereeritud HTML veebilehti CharacterSetClientComment=Vali kooditabel web ekraanil.
      Vaikimisi pakutud kooditabel on üks teie andmebaasi. -CollationConnection=Iseloom sorteerimine et -CollationConnectionComment=Vali lehekülg kood, mis määratleb tegelase sorteerimine et kasutada andmebaasi. Seda parameetrit nimetatakse ka "võrdlemine", mida mõned andmebaase.
      Seda parameetrit ei ole võimalik määratleda, kui andmebaas on juba olemas. +DBSortingCollation=Iseloom sorteerimine et +DBSortingCollationComment=Vali lehekülg kood, mis määratleb tegelase sorteerimine et kasutada andmebaasi. Seda parameetrit nimetatakse ka "võrdlemine", mida mõned andmebaase.
      Seda parameetrit ei ole võimalik määratleda, kui andmebaas on juba olemas. CharacterSetDatabase=Kooditabel andmebaasi CharacterSetDatabaseComment=Vali kooditabel otsitakse andmebaasi loomist.
      Seda parameetrit ei ole võimalik määratleda, kui andmebaas on juba olemas. YouAskDatabaseCreationSoDolibarrNeedToConnect=Te küsite, et luua andmebaas %s, kuid selleks, Dolibarr vaja ühendada server %s super kasutaja %s õigused. diff --git a/htdocs/langs/et_EE/members.lang b/htdocs/langs/et_EE/members.lang index a1b4e9f383d..b2d7eb1bc7a 100644 --- a/htdocs/langs/et_EE/members.lang +++ b/htdocs/langs/et_EE/members.lang @@ -177,7 +177,7 @@ LastSubscriptionDate=Last tellimise kuupäev LastSubscriptionAmount=Last märkimissummast MembersStatisticsByCountries=Liikmed statistika riik MembersStatisticsByState=Liikmed statistika / maakond -MembersStatisticsByTowne=Liikmed statistika linn +MembersStatisticsByTown=Liikmed statistika linn NbOfMembers=Liikmete arv NoValidatedMemberYet=Ükski valideeritud liikmed leitud MembersByCountryDesc=See ekraan näitab teile, statistika liikmetele riikides. Graphic sõltub siiski Google Interneti graafik teenust ning on saadaval vaid siis, kui internetiühendus on töötab. diff --git a/htdocs/langs/et_EE/suppliers.lang b/htdocs/langs/et_EE/suppliers.lang index 57f6ab11194..c9487dad634 100644 --- a/htdocs/langs/et_EE/suppliers.lang +++ b/htdocs/langs/et_EE/suppliers.lang @@ -13,7 +13,6 @@ Supplier=Tarnija AddSupplier=Lisa tarnija SupplierRemoved=Tarnija välja SuppliersInvoice=Tarnijate arve -SuppliersInvoices=Tarnijate arvete NewSupplier=New tarnija History=Ajalugu ListOfSuppliers=Tarnijate diff --git a/htdocs/langs/fa_IR/install.lang b/htdocs/langs/fa_IR/install.lang index 61d5853ade7..545d17c8f76 100644 --- a/htdocs/langs/fa_IR/install.lang +++ b/htdocs/langs/fa_IR/install.lang @@ -123,8 +123,8 @@ YouMustCreateItAndAllowServerToWrite=يجب إنشاء هذا الدليل ، و CharsetChoice=اختيار مجموعة حروف CharacterSetClient=مجموعة الحروف المستخدمة في توليدها صفحات هتمل CharacterSetClientComment=اختيار الطابع المحدد لعرضها على الإنترنت.
      واقترحت مجموعة الطابع الافتراضي هو واحد من قاعدة البيانات. -CollationConnection=طابع الفرز بغية -CollationConnectionComment=اختر صفحة المدونة التي تحدد طبيعة النظام 'sفرز قاعدة البيانات التي تستخدمها. هذا هو المعلم كما دعا 'مقارنتها' بعض قواعد البيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. +DBSortingCollation=طابع الفرز بغية +DBSortingCollationComment=اختر صفحة المدونة التي تحدد طبيعة النظام 'sفرز قاعدة البيانات التي تستخدمها. هذا هو المعلم كما دعا 'مقارنتها' بعض قواعد البيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. CharacterSetDatabase=الطابع المحدد لقاعدة البيانات CharacterSetDatabaseComment=اختيار مجموعة حروف تريد لإنشاء قاعدة بيانات.
      هذا المعلم لا يمكن أن يعرف إذا كانت قاعدة البيانات موجودة بالفعل. YouAskDatabaseCreationSoDolibarrNeedToConnect=كنت أسأل لإنشاء قاعدة بيانات ٪ ق ، ولكن لهذا ، Dolibarr الحاجة الى الاتصال بخادم ٪ ق السوبر مع المستخدم أذونات ٪ ق. diff --git a/htdocs/langs/fa_IR/suppliers.lang b/htdocs/langs/fa_IR/suppliers.lang index 327d6ecc56e..d24ea173e77 100644 --- a/htdocs/langs/fa_IR/suppliers.lang +++ b/htdocs/langs/fa_IR/suppliers.lang @@ -14,7 +14,6 @@ Supplier=المورد AddSupplier=إضافة مورد SupplierRemoved=إزالة المورد SuppliersInvoice=فاتورة الموردين -SuppliersInvoices=فواتير الموردين NewSupplier=مورد جديد History=التاريخ ListOfSuppliers=قائمة الموردين diff --git a/htdocs/langs/fi_FI/install.lang b/htdocs/langs/fi_FI/install.lang index 4201b815a94..81448a6ab86 100644 --- a/htdocs/langs/fi_FI/install.lang +++ b/htdocs/langs/fi_FI/install.lang @@ -121,8 +121,8 @@ YouMustCreateItAndAllowServerToWrite=Sinun on luotava tähän hakemistoon ja mah CharsetChoice=Merkistö valinta CharacterSetClient=Merkistö käytetään tuotettu HTML-sivuja CharacterSetClientComment=Valitse merkistö Web-näytön.
      Oletus ehdotettu merkistö on yksi tietokannan. -CollationConnection=Luonne lajittelu jotta -CollationConnectionComment=Valitse sivun koodi, joka määrittää merkin n lajittelu jotta käyttää tietokantaa. Tämä parametri on myös kutsuttu "kokoamisen" noin tietokantoja.
      Tämä parametri ei voida määritellä, jos tietokanta on jo olemassa. +DBSortingCollation=Luonne lajittelu jotta +DBSortingCollationComment=Valitse sivun koodi, joka määrittää merkin n lajittelu jotta käyttää tietokantaa. Tämä parametri on myös kutsuttu "kokoamisen" noin tietokantoja.
      Tämä parametri ei voida määritellä, jos tietokanta on jo olemassa. CharacterSetDatabase=Merkistö tietokanta CharacterSetDatabaseComment=Valitse merkistö etsintäkuulutettu tietokannan luomista.
      Tämä parametri ei voida määritellä, jos tietokanta on jo olemassa. YouAskDatabaseCreationSoDolibarrNeedToConnect=Te kysytte luoda tietokanta %s, mutta tästä Dolibarr tarvitse liittää palvelimeen %s Super käyttäjän %s käyttöoikeudet. diff --git a/htdocs/langs/fi_FI/members.lang b/htdocs/langs/fi_FI/members.lang index 831892de7d7..b4c5c52f2d4 100644 --- a/htdocs/langs/fi_FI/members.lang +++ b/htdocs/langs/fi_FI/members.lang @@ -208,7 +208,7 @@ LastSubscriptionDate=Viimeinen merkintäpäivä LastSubscriptionAmount=Viime merkinnän määrästä MembersStatisticsByCountries=Jäsenten tilastot maittain MembersStatisticsByState=Jäsenten tilastot valtio / lääni -MembersStatisticsByTowne=Jäsenten tilastot kaupunki +MembersStatisticsByTown=Jäsenten tilastot kaupunki NbOfMembers=Jäsenmäärä NoValidatedMemberYet=Ei validoitu jäsenet pitivät MembersByCountryDesc=Tämä ruutu näyttää tilastoja jäseniä maittain. Graphic riippuu kuitenkin Googlen online-käyrä palvelu ja on käytettävissä vain, jos internet-yhteys toimii. diff --git a/htdocs/langs/fi_FI/suppliers.lang b/htdocs/langs/fi_FI/suppliers.lang index 8d8d8e5fb0d..43e75c7d246 100644 --- a/htdocs/langs/fi_FI/suppliers.lang +++ b/htdocs/langs/fi_FI/suppliers.lang @@ -14,7 +14,6 @@ Supplier=Toimittaja AddSupplier=Lisää toimittaja SupplierRemoved=Toimittaja poistettu SuppliersInvoice=Tavarantoimittajat lasku -SuppliersInvoices=Tavarantoimittajat laskut NewSupplier=Uuden toimittajan History=Historia ListOfSuppliers=Luettelo toimittajat diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 6afab6c47ab..67c1c1f6e19 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -715,6 +715,20 @@ VATIsNotUsedDesc= Le taux de TVA proposé par défaut est 0. C'est le cas d'asso VATIsUsedExampleFR= En France, il s'agit des sociétés ou organismes ayant choisi un régime fiscale réel (Réel simplifié ou Réel normal), régime dans lequel la TVA est déclarée. VATIsNotUsedExampleFR= En France, il s'agit des associations ne déclarant pas de TVA ou sociétés, organismes ou professions libérales ayant choisi le régime fiscal micro entreprise (TVA en franchise) et payant une TVA en franchise sans faire de déclaration de TVA. Ce choix fait de plus apparaitre la mention "TVA non applicable - art-293B du CGI" sur les factures. ##### Local Taxes ##### +LocalTax1IsUsed=Assujeti +LocalTax1IsNotUsed=Non assujeti +LocalTax1IsUsedDesc=Utilisation d'une 2eme type taxe (autre que TVA) +LocalTax1IsNotUsedDesc=Pas d'utilisation de 2eme type taxe (autre que TVA) +LocalTax1Management=Gestion 2eme type de tax +LocalTax1IsUsedExample= +LocalTax1IsNotUsedExample= +LocalTax2IsUsed=Assujeti +LocalTax2IsNotUsed=Non assujeti +LocalTax2IsUsedDesc=Utilisation d'une 3eme type taxe (autre que TVA) +LocalTax2IsNotUsedDesc=Pas d'utilisation de 3eme type taxe (autre que TVA) +LocalTax2Management=Gestion 3eme type de tax +LocalTax2IsUsedExample= +LocalTax2IsNotUsedExample= LocalTax1ManagementES= Gestion RE LocalTax1IsUsedDescES= Le taux de RE proposé par défaut lors de la création de propale, facture, commande, etc... répond à la règle standard suivante:
      Si acheteur non assujetti à RE, RE par défaut=0. Fin de règle.
      Si acheteur assujetti à RE alors RE par défaut. Fin de règle.
      LocalTax1IsNotUsedDescES= Le taux de RE proposé par défaut est 0. Fin de règle. @@ -946,6 +960,7 @@ DocumentModelOdt=Genération depuis des modèles OpenDocument (Fichier .ODT Open WatermarkOnDraft=Filigrane sur les documents brouillons CompanyIdProfChecker=Id professionel unique MustBeUnique=Doit être unique ? +MustBeMandatory=Doit être obligatoire? Miscellanous=Divers ##### Webcal setup ##### WebCalSetup= Configuration du lien vers le calendrier Webcalendar @@ -1316,6 +1331,7 @@ AccountancyCodeBuy=Code compta achat AgendaSetup= Configuration du module actions et agenda PasswordTogetVCalExport= Clé pour autoriser lien export PastDelayVCalExport=Ne pas exporter les événements de plus de +AGENDA_USE_EVENT_TYPE=Utilisez les type des évenements (administrable dans Configuration->Dictionnary->llx_c_actioncomm) ##### ClickToDial ##### ClickToDialDesc= Ce module permet d'ajouter un petit picto à côté des numéros de téléphones. Un clic sur ce picto provoque l'appel de l'URL définie dans ce paramétrage. Ceci permet de provoquer des appels à un serveur de téléphonie depuis Dolibarr qui peut alors composer le numéro sur un système SIP par exemple. ##### Point Of Sales (CashDesk) ##### diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang index 866773ee131..30786b6e542 100644 --- a/htdocs/langs/fr_FR/bills.lang +++ b/htdocs/langs/fr_FR/bills.lang @@ -47,7 +47,6 @@ InvoiceCustomer=Facture client CustomerInvoice=Facture client CustomersInvoices=Factures clients SupplierInvoice=Facture fournisseur -SuppliersInvoices=Factures fournisseurs SupplierBill=Facture fournisseur SupplierBills=Factures fournisseurs Payment=Règlement diff --git a/htdocs/langs/fr_FR/cashdesk.lang b/htdocs/langs/fr_FR/cashdesk.lang index cb7e7f25251..5c59db99c57 100644 --- a/htdocs/langs/fr_FR/cashdesk.lang +++ b/htdocs/langs/fr_FR/cashdesk.lang @@ -20,7 +20,6 @@ AddThisArticle=Ajouter cet article RestartSelling=Reprendre la vente SellFinished=Vente terminée PrintTicket=Imprimer ticket -NoResults=Aucun résultat NoProductFound=Aucun article trouvé ProductFound=produit trouvé ProductsFound=produits trouvés diff --git a/htdocs/langs/fr_FR/commercial.lang b/htdocs/langs/fr_FR/commercial.lang index bb76700ba53..79937cb84fb 100644 --- a/htdocs/langs/fr_FR/commercial.lang +++ b/htdocs/langs/fr_FR/commercial.lang @@ -81,6 +81,8 @@ ActionAC_SHIP=Envoi bon d'expédition par mail ActionAC_SUP_ORD=Envoi commande fournisseur par mail ActionAC_SUP_INV=Envoi facture fournisseur par mail ActionAC_OTH=Autre +ActionAC_MANUAL=Evênements insérés manuellement +ActionAC_AUTO=Evênements insérés automatiquement Stats=Statistiques de vente CAOrder=Chiffre d'affaires (Commandes validées) FromTo=du %s au %s diff --git a/htdocs/langs/fr_FR/errors.lang b/htdocs/langs/fr_FR/errors.lang index 87715bea1fe..b6fcbb6611b 100644 --- a/htdocs/langs/fr_FR/errors.lang +++ b/htdocs/langs/fr_FR/errors.lang @@ -26,6 +26,7 @@ ErrorThisContactIsAlreadyDefinedAsThisType=Ce contact est déjà défini comme c ErrorCashAccountAcceptsOnlyCashMoney=Ce compte bancaire est de type caisse et n'accepte que les mode de règlement de type espèce. ErrorFromToAccountsMustDiffers=Le compte source et destination doivent être différents. ErrorBadThirdPartyName=Nom de tiers incorrect +ErrorProdIdIsMandatory=Le %s est obligatoire ErrorBadCustomerCodeSyntax=La syntaxe du code client est incorrecte ErrorCustomerCodeRequired=Code client obligatoire ErrorCustomerCodeAlreadyUsed=Code client déjà utilisé diff --git a/htdocs/langs/fr_FR/install.lang b/htdocs/langs/fr_FR/install.lang index 7bc7ce811d1..da7fbe1b610 100644 --- a/htdocs/langs/fr_FR/install.lang +++ b/htdocs/langs/fr_FR/install.lang @@ -125,8 +125,8 @@ YouMustCreateItAndAllowServerToWrite=Vous devez créer ce dossier et permettre a CharsetChoice=Choix du codage des caractères CharacterSetClient=Codage utilisé pour l'affichage des pages CharacterSetClientComment=Veuillez choisir le codage que vous souhaitez pour l'affichage des pages.
      Le codage proposé par défaut est celui de votre base de données par défaut. -CollationConnection=Ordre de tri utilisé pour la base de données -CollationConnectionComment=Veuillez choisir la page de code définissant l'ordre de tri des caractères utilisés par la base de données. Ce paramètre est aussi appelé 'collation' par certaines bases de données.
      Ce paramètre n'est pas sélectionnable si votre base est déjà créée. +DBSortingCollation=Ordre de tri utilisé pour la base de données +DBSortingCollationComment=Veuillez choisir la page de code définissant l'ordre de tri des caractères utilisés par la base de données. Ce paramètre est aussi appelé 'collation' par certaines bases de données.
      Ce paramètre n'est pas sélectionnable si votre base est déjà créée. CharacterSetDatabase=Codage utilisé pour la base de données CharacterSetDatabaseComment=Veuillez choisir le codage que vous désirez choisir pour la création de la base de données.
      Ce paramètre n'est pas sélectionnable si votre base est déjà créée. YouAskDatabaseCreationSoDolibarrNeedToConnect=Vous avez demandé la création de la base de données %s, mais pour cela, Dolibarr doit se connecter sur le serveur %s via le super utilisateur %s. diff --git a/htdocs/langs/fr_FR/languages.lang b/htdocs/langs/fr_FR/languages.lang index 09231867347..40efc72e533 100644 --- a/htdocs/langs/fr_FR/languages.lang +++ b/htdocs/langs/fr_FR/languages.lang @@ -14,6 +14,7 @@ Language_en_AU=Anglais (Australie) Language_en_GB=Anglais (Royaume-Uni) Language_en_IN=Anglais (Inde) Language_en_NZ=Anglais (Nouvelle Zeland) +Language_en_SA=Anglais (Arabie Saoudite) Language_en_US=Anglais (Etats-Unis) Language_es_ES=Espagnol Language_es_AR=Espagnol (Argentine) diff --git a/htdocs/langs/fr_FR/mails.lang b/htdocs/langs/fr_FR/mails.lang index 78c70886cd0..be08ccad7e8 100644 --- a/htdocs/langs/fr_FR/mails.lang +++ b/htdocs/langs/fr_FR/mails.lang @@ -75,17 +75,18 @@ DateSending=Date envoi SentTo=Envoyés à %s MailingStatusRead=Lu CheckRead=Accusé de lecture -YourMailUnsubcribeOK=L'adresse e-mail %s est bien désincrite de la liste. -MailtoEMail=Ecrire a e-mail (lien) -ActivateCheckRead=Permettre l'utilisation du tracker d'accusé de lecture et du lien de désincription -ActivateCheckReadKey=Clef de sécurité utilisée pour l'encryption des URL utilisées dans les fonctions d'accusé de lecture et de désincription +YourMailUnsubcribeOK=L'adresse e-mail %s est bien désinscrite de la liste. +MailtoEMail=Ecrire un e-mail (lien) +ActivateCheckRead=Permettre l'utilisation du tracker d'accusé de lecture et du lien de désinscription +ActivateCheckReadKey=Clef de sécurité permettant l'encryption des URL utilisées dans les fonctions d'accusé de lecture et de désinscription +EMailSentToNRecipients=EMail envoyé à %s destinataires. # Libelle des modules de liste de destinataires mailing MailingModuleDescContactCompanies=Contacts de tiers (prospects, clients, fournisseurs...) MailingModuleDescDolibarrUsers=Utilisateurs de Dolibarr MailingModuleDescFundationMembers=Adhérents MailingModuleDescEmailsFromFile=EMails issus d'un fichier texte (email;nom;prenom;autre) -MailingModuleDescEmailsFromUser=EMails saisi manuellement (email;nom;prenom;autre) +MailingModuleDescEmailsFromUser=EMails saisis manuellement (email;nom;prenom;autre) MailingModuleDescContactsCategories=Tiers (par catégorie) MailingModuleDescDolibarrContractsLinesExpired=Tiers avec lignes de contrats de services expirées MailingModuleDescContactsByCompanyCategory=Contacts de tiers (par catégorie de tiers) @@ -105,11 +106,11 @@ SendMailing=Envoi emailing SendMail=Envoi mail SentBy=Envoyé par MailingNeedCommand=Pour des raisons de sécurité, il est recommandé de faire les envois d'un mailing de masse depuis une ligne de commande. Demandez à votre administrateur de lancer la commande suivante pour envoyer le mailing à tous les destinataires : -MailingNeedCommand2=Vous pouvez toutefois quand même les envoyer par l'interface écrans en ajoutant le paramètre MAILING_LIMIT_SENDBYWEB avec la valeur du nombre max de mails envoyés par session d'envoi. Pour cela, aller dans Accueil - Configuration - Divers. +MailingNeedCommand2=Vous pouvez toutefois quand même les envoyer par l'interface écran en ajoutant le paramètre MAILING_LIMIT_SENDBYWEB avec la valeur du nombre max de mails envoyés par session d'envoi. Pour cela, aller dans Accueil - Configuration - Divers. ConfirmSendingEmailing=Confirmez-vous l'envoi de l'emailing depuis le mode web ? LimitSendingEmailing=L'envoi d'un emailing depuis les écrans est limité pour raisons de sécurité et de timeout à %s destinataires par session d'envoi. TargetsReset=Vider liste -ToClearAllRecipientsClickHere=Pour vider la liste des destinataires de cet emailing, cliquer le bouton +ToClearAllRecipientsClickHere=Pour vider la liste des destinataires de cet emailing, cliquez sur le bouton ToAddRecipientsChooseHere=Pour ajouter des destinataires, choisir dans les listes ci-dessous NbOfEMailingsReceived=EMailings de masse reçus IdRecord=ID enregistrement diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index b2147ce7e20..ff50038f5c2 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -629,6 +629,7 @@ BySalesRepresentative=Par commerciaux LinkedToSpecificUsers=Liés à un contact utilisateur particulier DeleteAFile=Suppression de fichier ConfirmDeleteAFile=Confirmez-vous la suppression du fichier +NoResults=Aucun résultat # Week day Monday=Lundi diff --git a/htdocs/langs/fr_FR/margins.lang b/htdocs/langs/fr_FR/margins.lang index 02dfedbbe9a..3c81a9a1e4d 100644 --- a/htdocs/langs/fr_FR/margins.lang +++ b/htdocs/langs/fr_FR/margins.lang @@ -47,6 +47,7 @@ MARGIN_TYPE_DETAILS=Marge brute : Prix de vente HT - Prix d'achat HT
      Marge n BuyingCost=Coût de revient UnitCharges=Charge unitaire +Charges=Charges AgentContactType=Type de contact commissionné AgentContactTypeDetails=Permet de définir le type de contact associé aux factures qui sera associé aux agents commerciaux \ No newline at end of file diff --git a/htdocs/langs/fr_FR/members.lang b/htdocs/langs/fr_FR/members.lang index 87bb226f317..2ccafef4cab 100644 --- a/htdocs/langs/fr_FR/members.lang +++ b/htdocs/langs/fr_FR/members.lang @@ -201,3 +201,6 @@ Collectivités=Collectivités Particuliers=Particuliers Entreprises=Entreprises DOLIBARRFOUNDATION_PAYMENT_FORM=Pour réaliser le paiement de votre cotisation par virement bancaire ou par chèque, consultez la page http://wiki.dolibarr.org/index.php/Adhérer.
      Pour payer dès maintenant par Carte Bancaire ou Paypal, cliquez sur le bouton au bas de cette page.
      +ByProperties=Par caractéristiques +MembersStatisticsByProperties=Statistiques des adhérents par caractéristiques +MembersByNature=Adhérents par nature diff --git a/htdocs/langs/fr_FR/projects.lang b/htdocs/langs/fr_FR/projects.lang index 01c6b337e98..d73ade4b1a1 100644 --- a/htdocs/langs/fr_FR/projects.lang +++ b/htdocs/langs/fr_FR/projects.lang @@ -93,6 +93,7 @@ CloneFiles=Cloner les pièces jointes ConfirmCloneProject=Êtes-vous sûr de vouloir cloner ce projet ? ProjectReportDate=Reporter les dates des taches en fonction de la date de départ. ErrorShiftTaskDate=Une erreur c'est produite dans le report des dates des taches. +ProjectsAndTasksLines=Projets et taches ##### Types de contacts ##### TypeContact_project_internal_PROJECTLEADER=Chef de projet TypeContact_project_external_PROJECTLEADER=Chef de projet diff --git a/htdocs/langs/fr_FR/sendings.lang b/htdocs/langs/fr_FR/sendings.lang index 1b316ab6c70..a80b61649da 100644 --- a/htdocs/langs/fr_FR/sendings.lang +++ b/htdocs/langs/fr_FR/sendings.lang @@ -58,6 +58,7 @@ ActionsOnShipping=Événements sur l'expédition LinkToTrackYourPackage=Lien pour suivi de votre colis ShipmentCreationIsDoneFromOrder=Pour le moment, la création d'une nouvelle expédition se fait depuis la fiche commande. RelatedShippings=Expédition(s) associée(s) +ShipmentLine=Ligne d'expédition # Sending methods SendingMethodCATCH=Enlèvement par le client diff --git a/htdocs/langs/fr_FR/suppliers.lang b/htdocs/langs/fr_FR/suppliers.lang index c042b74ea89..932615ff181 100644 --- a/htdocs/langs/fr_FR/suppliers.lang +++ b/htdocs/langs/fr_FR/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Fournisseur AddSupplier=Ajouter un fournisseur SupplierRemoved=Fournisseur supprimé SuppliersInvoice=Facture fournisseur -SuppliersInvoices=Factures fournisseurs NewSupplier=Nouveau fournisseur History=Historique ListOfSuppliers=Liste des fournisseurs diff --git a/htdocs/langs/fr_FR/withdrawals.lang b/htdocs/langs/fr_FR/withdrawals.lang index b66f2bca344..27c00e307cf 100644 --- a/htdocs/langs/fr_FR/withdrawals.lang +++ b/htdocs/langs/fr_FR/withdrawals.lang @@ -40,8 +40,8 @@ TransData=Date Transmission TransMetod=Méthode Transmission Send=Envoyer Lines=Lignes -StandingOrderReject=Emmètre un rejet -InvoiceRefused=Facture rejeté +StandingOrderReject=Émettre un rejet +InvoiceRefused=Facture rejetée WithdrawalRefused=Rejet de prélèvement WithdrawalRefusedConfirm=Êtes-vous sûr de vouloir saisir un rejet de prélèvement pour la société RefusedData=Date du rejet @@ -70,25 +70,28 @@ CreateBanque=Seulement banque OrderWaiting=En attente de traitement NotifyTransmision=Transmission du bon NotifyEmision=Emission du bon -NotifyCredit=Credit du bon +NotifyCredit=Crédit du bon NumeroNationalEmetter= Numéro National Émetteur PleaseSelectCustomerBankBANToWithdraw=Saisissez les informations du compte bancaire client à prélever WithBankUsingRIB=Pour les comptes bancaires utilisant le RIB WithBankUsingBANBIC=Pour les comptes bancaires utilisant le code BAN/BIC/SWIFT BankToReceiveWithdraw=Compte bancaire recevant les prélèvements CreditDate=Crédité le -WithdrawalFileNotCapable=Impossible de generer fichier de bon de prelevements pour votre pays +WithdrawalFileNotCapable=Impossible de générer un fichier de bons de prélèvements pour votre pays ShowWithdraw=Voir prélèvement IfInvoiceNeedOnWithdrawPaymentWontBeClosed=Toutefois, si la facture a au moins un paiement par prélèvement non traité, elle ne le sera pas afin de permettre la gestion du prélèvement d'abord. -DoStandingOrdersBeforePayments=Cet onglet permet de faire une demande de pélèvement bancaire. Une fois réalisé, vous pourrez saisir le paiement sur la facture pour la clore. +DoStandingOrdersBeforePayments=Cet onglet permet de faire une demande de prélèvement bancaire. Une fois réalisé, vous pourrez saisir le paiement sur la facture pour la clore. +WithdrawalFile=Fichier de prélèvement +SetToStatusSent=Mettre status "Fichier envoyé" +ThisWillAlsoAddPaymentOnInvoice=Ceci créera également les paiements sur les factures et les classera payées ### Notifications -InfoCreditSubject=Credit prélèvement %s a la banque -InfoCreditMessage=Le bon de prélèvement %s a eté credité par la banque.
      Date credit : %s -InfoTransSubject=Transmission du prélèvement %s a la banque -InfoTransMessage=Le bon de prélèvement %s a eté transmis a la banque par %s %s.

      -InfoTransData=Montant: %s
      Methode: %s
      Date: %s -InfoFoot=Ceci est un message automatique envoye par Dolibarr +InfoCreditSubject=Crédit prélèvement %s à la banque +InfoCreditMessage=Le bon de prélèvement %s a été crédité par la banque.
      Date crédit : %s +InfoTransSubject=Transmission du prélèvement %s à la banque +InfoTransMessage=Le bon de prélèvement %s a été transmis à la banque par %s %s.

      +InfoTransData=Montant: %s
      Méthode: %s
      Date: %s +InfoFoot=Ceci est un message automatique envoyé par Dolibarr InfoRejectSubject=Prélèvement rejeté -InfoRejectMessage=Bonjour,

      Le prelevement de la facture %s pour le compte de la societé %s, d'un montant de %s a été rejeté par la banque.

      --
      %$ +InfoRejectMessage=Bonjour,

      Le prélèvement de la facture %s pour le compte de la société %s, d'un montant de %s a été rejeté par la banque.

      --
      %$ ModeWarning=Option mode réel non établi, nous allons arrêter après cette simulation \ No newline at end of file diff --git a/htdocs/langs/he_IL/install.lang b/htdocs/langs/he_IL/install.lang index c2d4ee2d44d..8fa0761a30c 100644 --- a/htdocs/langs/he_IL/install.lang +++ b/htdocs/langs/he_IL/install.lang @@ -131,8 +131,8 @@ YouMustCreateItAndAllowServerToWrite=עליך ליצור את הספרייה ו CharsetChoice=התווים הבחירה CharacterSetClient=התווים המשמש שנוצר דפי אינטרנט ב-HTML CharacterSetClientComment=בחר בערכת התווים להצגה באינטרנט.
      מערכת המוצעת מחדל הדמות היא זו של מסד הנתונים. -CollationConnection=מיון תו כדי -CollationConnectionComment=בחר קוד מקור המגדיר סדר המיון של הדמות בשימוש על ידי מסד הנתונים. פרמטר זה נקרא גם "איסוף" של כמה מסדי נתונים.
      פרמטר זה לא ניתן להגדיר אם מסד הנתונים כבר קיים. +DBSortingCollation=מיון תו כדי +DBSortingCollationComment=בחר קוד מקור המגדיר סדר המיון של הדמות בשימוש על ידי מסד הנתונים. פרמטר זה נקרא גם "איסוף" של כמה מסדי נתונים.
      פרמטר זה לא ניתן להגדיר אם מסד הנתונים כבר קיים. CharacterSetDatabase=התווים עבור מסד הנתונים CharacterSetDatabaseComment=בחר בערכת התווים רצה ליצירת מסד הנתונים.
      פרמטר זה לא ניתן להגדיר אם מסד הנתונים כבר קיים. YouAskDatabaseCreationSoDolibarrNeedToConnect=אתה שואל כדי ליצור מסד נתונים %s, אבל בשביל זה, Dolibarr צריך להתחבר %s שרת עם הרשאות %s סופר משתמש. diff --git a/htdocs/langs/he_IL/members.lang b/htdocs/langs/he_IL/members.lang index dc23fd846ce..b8f1a2389d0 100644 --- a/htdocs/langs/he_IL/members.lang +++ b/htdocs/langs/he_IL/members.lang @@ -177,7 +177,7 @@ LastSubscriptionDate=מנוי אחרונה תאריך LastSubscriptionAmount=המינוי האחרון כמות MembersStatisticsByCountries=משתמשים סטטיסטיקה לפי מדינות MembersStatisticsByState=חברים הסטטיסטיקה של מדינה / מחוז -MembersStatisticsByTowne=חברים הסטטיסטיקה של העיר +MembersStatisticsByTown=חברים הסטטיסטיקה של העיר NbOfMembers=מספר החברים NoValidatedMemberYet=אין חברים תוקף נמצא MembersByCountryDesc=מסך זה מראה לך נתונים סטטיסטיים על החברים של מדינות. עם זאת גרפי תלוי על שירות Google גרף באינטרנט זמינה רק אם החיבור לאינטרנט הוא עובד. diff --git a/htdocs/langs/he_IL/suppliers.lang b/htdocs/langs/he_IL/suppliers.lang index 0949262da42..3706da71c41 100644 --- a/htdocs/langs/he_IL/suppliers.lang +++ b/htdocs/langs/he_IL/suppliers.lang @@ -13,7 +13,6 @@ Supplier=ספק AddSupplier=הוסף הספק SupplierRemoved=הספק הוסר SuppliersInvoice=ספקים חשבונית -SuppliersInvoices=חשבוניות ספקים NewSupplier=חדש הספק History=היסטוריה ListOfSuppliers=רשימת הספקים diff --git a/htdocs/langs/hu_HU/install.lang b/htdocs/langs/hu_HU/install.lang index bb729ba7ce9..b912875ca51 100644 --- a/htdocs/langs/hu_HU/install.lang +++ b/htdocs/langs/hu_HU/install.lang @@ -119,8 +119,8 @@ YouMustCreateItAndAllowServerToWrite=Létre kell hoznia ezt a könyvtárat és e CharsetChoice=Karakter készlet választás CharacterSetClient=A generált web oldalakhoz használt karakterkészlet CharacterSetClientComment=Válasszon karakterkészletet a webes megjelenitéshez.
      Az alapértelmezett az adatbázis karakterkészlete. -CollationConnection=Karakter rendezés -CollationConnectionComment=Válasszon kódot ami deifiniálja az adatbázis által használt karakter rendezést. Ezt a paraméter 'illesztés'/'collation'-ként is imseretes egyes adatbázisok esetén.
      Ez a paraméter nem megadható ha az adatbázisban már létezik. +DBSortingCollation=Karakter rendezés +DBSortingCollationComment=Válasszon kódot ami deifiniálja az adatbázis által használt karakter rendezést. Ezt a paraméter 'illesztés'/'collation'-ként is imseretes egyes adatbázisok esetén.
      Ez a paraméter nem megadható ha az adatbázisban már létezik. CharacterSetDatabase=Az adatbázis karakterkészlete CharacterSetDatabaseComment=Válasszon karakterkészletet az adatbázis létrehozásához.
      Ez a paraméter nem megadható ha az adatbázisban már létezik. YouAskDatabaseCreationSoDolibarrNeedToConnect=A(z) %s adatbázis létrehozásához az adatbázis szerverhez SuperUser jogosúltságokkal kell csatlakozni. diff --git a/htdocs/langs/hu_HU/members.lang b/htdocs/langs/hu_HU/members.lang index 9d4026e2e59..a1baf95f0c6 100644 --- a/htdocs/langs/hu_HU/members.lang +++ b/htdocs/langs/hu_HU/members.lang @@ -177,7 +177,7 @@ LastSubscriptionDate=Utolsó dátum előfizetés LastSubscriptionAmount=Utolsó előfizetés összege MembersStatisticsByCountries=Tagok statisztikája ország MembersStatisticsByState=Tagok statisztikája állam / tartomány -MembersStatisticsByTowne=Tagok statisztikája város +MembersStatisticsByTown=Tagok statisztikája város NbOfMembers=Tagok száma NoValidatedMemberYet=Nem hitelesített tagok található MembersByCountryDesc=Ez a képernyő megmutatja statisztikát tagok országokban. Grafikus függ azonban a Google online grafikon szolgáltatást és csak akkor elérhető, ha az internet kapcsolat működik. diff --git a/htdocs/langs/hu_HU/suppliers.lang b/htdocs/langs/hu_HU/suppliers.lang index 9a0c2643fc7..89bdd570292 100644 --- a/htdocs/langs/hu_HU/suppliers.lang +++ b/htdocs/langs/hu_HU/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Beszállító AddSupplier=Beszállító hozzáadása SupplierRemoved=Beszállító eltávolítva SuppliersInvoice=Beszállító számla -SuppliersInvoices=Beszállítók számlái NewSupplier=Új beszállító History=Történet ListOfSuppliers=Beszállító listája diff --git a/htdocs/langs/is_IS/install.lang b/htdocs/langs/is_IS/install.lang index 4035e2a2fbb..6435b12fc13 100644 --- a/htdocs/langs/is_IS/install.lang +++ b/htdocs/langs/is_IS/install.lang @@ -131,8 +131,8 @@ YouMustCreateItAndAllowServerToWrite=Þú verður að búa til þessa möppu og CharsetChoice=Stafasett val CharacterSetClient=Stafasett notað mynda HTML vefsíðum CharacterSetClientComment=Veldu stafasett til birtingar á vefnum.
      Default fyrirhugaðar stafasett er einn af gagnasafninu. -CollationConnection=Eðli flokkun þess -CollationConnectionComment=Veldu kóða sem skilgreinir flokka til persónu er notaður við gagnagrunn. Þessi stika er einnig kallaður "samanburði" af sumum gagnasöfnum.
      Þessi stika er ekki hægt að útskýra ef gagnagrunnur er þegar til. +DBSortingCollation=Eðli flokkun þess +DBSortingCollationComment=Veldu kóða sem skilgreinir flokka til persónu er notaður við gagnagrunn. Þessi stika er einnig kallaður "samanburði" af sumum gagnasöfnum.
      Þessi stika er ekki hægt að útskýra ef gagnagrunnur er þegar til. CharacterSetDatabase=Stafasett fyrir gagnasafn CharacterSetDatabaseComment=Veldu stafasett langaði að skapa gagnagrunn.
      Þessi stika er ekki hægt að útskýra ef gagnagrunnur er þegar til. YouAskDatabaseCreationSoDolibarrNeedToConnect=Þú biður að búa til gagnasafn %s , en fyrir þetta, Dolibarr þarf til að tengjast við miðlara %s með frábær notanda %s aðgangsheimildir. diff --git a/htdocs/langs/is_IS/members.lang b/htdocs/langs/is_IS/members.lang index f73002b70d5..d64fc0dbd55 100644 --- a/htdocs/langs/is_IS/members.lang +++ b/htdocs/langs/is_IS/members.lang @@ -190,7 +190,7 @@ LastSubscriptionDate=Síðast áskrift dagsetning LastSubscriptionAmount=Síðast áskrift upphæð MembersStatisticsByCountries=Notendur tölfræði eftir landi MembersStatisticsByState=Notendur tölfræði eftir fylki / hérað -MembersStatisticsByTowne=Notendur tölfræði eftir bænum +MembersStatisticsByTown=Notendur tölfræði eftir bænum NbOfMembers=Fjöldi félaga NoValidatedMemberYet=Engar fullgiltar meðlimir fundust MembersByCountryDesc=Þessi skjár sýnir þér tölfræði á meðlimum með löndum. Grafísk veltur þó á Google netinu línurit þjónustu og er aðeins í boði ef nettengingin er er að vinna. diff --git a/htdocs/langs/is_IS/suppliers.lang b/htdocs/langs/is_IS/suppliers.lang index 625ded3432e..a33597212b3 100644 --- a/htdocs/langs/is_IS/suppliers.lang +++ b/htdocs/langs/is_IS/suppliers.lang @@ -13,7 +13,6 @@ Supplier=Birgir AddSupplier=Bæta við birgja SupplierRemoved=Birgir fjarri SuppliersInvoice=Birgjar Reikningar -SuppliersInvoices=Birgjar reikningum NewSupplier=New birgir History=Saga ListOfSuppliers=Listi yfir birgja diff --git a/htdocs/langs/it_IT/install.lang b/htdocs/langs/it_IT/install.lang index 0639923b980..510d5a7abbe 100644 --- a/htdocs/langs/it_IT/install.lang +++ b/htdocs/langs/it_IT/install.lang @@ -21,8 +21,8 @@ CheckToCreateUser =Seleziona questa opzione se l'utente non esiste e deve es CheckToForceHttps =Seleziona questa opzione per forzare le connessioni sicure (HTTPS).
      L'host dev'essere configurato per usare un certificato SSL. ChoosedMigrateScript =Scegli script di migrazione ChooseYourSetupMode =Scegli la modalità di impostazione e clicca "start" -CollationConnectionComment =Scegli la codifica per definire l'ordinamento caratteri nel database (Collation).
      Questo parametro non può essere definito se il database esiste già. -CollationConnection =Ordinamento caratteri (Collation) +DBSortingCollationComment =Scegli la codifica per definire l'ordinamento caratteri nel database (Collation).
      Questo parametro non può essere definito se il database esiste già. +DBSortingCollation =Ordinamento caratteri (Collation) ConfFileCouldBeCreated =Il file %s può essere creato. ConfFileDoesNotExistsAndCouldNotBeCreated =Il file di configurazione %s non esiste e non può essere creato! ConfFileDoesNotExists =Il file di configurazione %s non esiste! diff --git a/htdocs/langs/it_IT/members.lang b/htdocs/langs/it_IT/members.lang index 0d67a3952cd..4000e50c514 100644 --- a/htdocs/langs/it_IT/members.lang +++ b/htdocs/langs/it_IT/members.lang @@ -105,7 +105,7 @@ MembersListValid =Elenco dei membri validi Members =Membri MembersStatisticsByCountries =Statistiche per paese MembersStatisticsByState =Statistiche per stato/provincia -MembersStatisticsByTowne =Statistiche per città +MembersStatisticsByTown =Statistiche per città MembersStatisticsDesc =Scegli quali statistiche visualizzare... MembersStatusNotPaid =Membri non pagati MembersStatusNotPaidShort =Non pagati diff --git a/htdocs/langs/it_IT/suppliers.lang b/htdocs/langs/it_IT/suppliers.lang index 7f21a0f73c3..8771326292b 100644 --- a/htdocs/langs/it_IT/suppliers.lang +++ b/htdocs/langs/it_IT/suppliers.lang @@ -39,4 +39,3 @@ SupplierRemoved =Fornitore rimosso SuppliersArea =Area fornitori Suppliers =Fornitori SuppliersInvoice =Fattura Fornitore -SuppliersInvoices =Fatture fornitori diff --git a/htdocs/langs/ja_JP/install.lang b/htdocs/langs/ja_JP/install.lang index 46cbef38e03..0d74ebfdd7a 100644 --- a/htdocs/langs/ja_JP/install.lang +++ b/htdocs/langs/ja_JP/install.lang @@ -84,8 +84,8 @@ YouMustCreateItAndAllowServerToWrite=このディレクトリを作成し、そ CharsetChoice=文字セットの選択 CharacterSetClient=生成されたHTML Webページに使用される文字セット CharacterSetClientComment=Web表示用の文字セットを選択します。
      デフォルト提案された文字セットは、データベースの一つです。 -CollationConnection=文字のソート順 -CollationConnectionComment=データベースで使用される文字のソート順序を定義するページのコードを選択してください。このパラメータは、いくつかのデータベースで"照合順序"と呼ばれています。
      データベースがすでに存在している場合、このパラメータは定義することはできません。 +DBSortingCollation=文字のソート順 +DBSortingCollationComment=データベースで使用される文字のソート順序を定義するページのコードを選択してください。このパラメータは、いくつかのデータベースで"照合順序"と呼ばれています。
      データベースがすでに存在している場合、このパラメータは定義することはできません。 CharacterSetDatabase=データベースの文字セット CharacterSetDatabaseComment=データベース作成のためにしたい文字セットを選択します。
      データベースがすでに存在している場合、このパラメータは定義することはできません。 YouAskDatabaseCreationSoDolibarrNeedToConnect=あなたは、データベースの%sを作成するために求めるが、このために、Dolibarrは、スーパーユーザーの%sの権限でサーバの%sに接続する必要があります。 diff --git a/htdocs/langs/ja_JP/members.lang b/htdocs/langs/ja_JP/members.lang index d736d3b6386..4fee5b42355 100644 --- a/htdocs/langs/ja_JP/members.lang +++ b/htdocs/langs/ja_JP/members.lang @@ -177,7 +177,7 @@ LastSubscriptionDate=最後のサブスクリプションの日付 LastSubscriptionAmount=最後のサブスクリプションの量 MembersStatisticsByCountries=国別メンバー統計 MembersStatisticsByState=都道府県/州によってメンバーの統計 -MembersStatisticsByTowne=町によってメンバーの統計 +MembersStatisticsByTown=町によってメンバーの統計 NbOfMembers=会員数 NoValidatedMemberYet=いいえ検証メンバーが見つかりませんでした MembersByCountryDesc=この画面には、国によるメンバーの統計情報を表示します。グラフィックは、Googleのオンライングラフサービスに依存しますが、インターネット接続が機能している場合にのみ使用できます。 diff --git a/htdocs/langs/ja_JP/suppliers.lang b/htdocs/langs/ja_JP/suppliers.lang index 3cb36fb8a85..70416c864a9 100644 --- a/htdocs/langs/ja_JP/suppliers.lang +++ b/htdocs/langs/ja_JP/suppliers.lang @@ -13,7 +13,6 @@ Supplier=サプライヤー AddSupplier=サプライヤーを追加します。 SupplierRemoved=サプライヤーは、削除 SuppliersInvoice=仕入先の請求書 -SuppliersInvoices=仕入先の請求書 NewSupplier=新しいサプライヤー History=歴史 ListOfSuppliers=サプライヤーのリスト diff --git a/htdocs/langs/nb_NO/install.lang b/htdocs/langs/nb_NO/install.lang index d90bf62954a..7597062d7ea 100644 --- a/htdocs/langs/nb_NO/install.lang +++ b/htdocs/langs/nb_NO/install.lang @@ -127,8 +127,8 @@ YouMustCreateItAndAllowServerToWrite=Du må lage denne katalogen og la for web-s CharsetChoice=Tegnsett valg CharacterSetClient=Tegnsett brukes for genererte HTML-nettsider CharacterSetClientComment=Velg tegnsettet for web visning.
      Standard foreslåtte tegnsett er en av databasen. -CollationConnection=Tegn sorteringsrekkefølgen -CollationConnectionComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. +DBSortingCollation=Tegn sorteringsrekkefølgen +DBSortingCollationComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. CharacterSetDatabase=Tegnsettet for databasen CharacterSetDatabaseComment=Velg tegnsettet ettersøkt for database skaperverk.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. YouAskDatabaseCreationSoDolibarrNeedToConnect=ber deg opprette database %s, men for dette, Dolibarr trenger å koble til serveren %s med superbruker %s tillatelser. diff --git a/htdocs/langs/nb_NO/members.lang b/htdocs/langs/nb_NO/members.lang index 3b732a08851..471b4e735a9 100644 --- a/htdocs/langs/nb_NO/members.lang +++ b/htdocs/langs/nb_NO/members.lang @@ -185,7 +185,7 @@ LastSubscriptionDate=Siste abonnement dato LastSubscriptionAmount=Siste tegningsbeløp MembersStatisticsByCountries=Medlemmer statistikk etter land MembersStatisticsByState=Medlemmer statistikk etter delstat / provins -MembersStatisticsByTowne=Medlemmer statistikk etter by +MembersStatisticsByTown=Medlemmer statistikk etter by NbOfMembers=Antall medlemmer NoValidatedMemberYet=Ingen validerte medlemmer funnet MembersByCountryDesc=Denne skjermen viser deg statistikk på medlemmer av land. Graphic imidlertid avhengig Google elektroniske grafen service og er bare tilgjengelig hvis en internett-tilkobling er fungerer. diff --git a/htdocs/langs/nb_NO/suppliers.lang b/htdocs/langs/nb_NO/suppliers.lang index 120b83656a5..9ee3898c986 100644 --- a/htdocs/langs/nb_NO/suppliers.lang +++ b/htdocs/langs/nb_NO/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Leverandør AddSupplier=Legg til en leverandør SupplierRemoved=Leverandør slettet SuppliersInvoice=Leverandørfaktura -SuppliersInvoices=Leverandørfakturaer NewSupplier=Ny leverandør History=Historikk ListOfSuppliers=Leverandøroversikt diff --git a/htdocs/langs/nl_BE/install.lang b/htdocs/langs/nl_BE/install.lang index fc6c4f132c6..6c013aa58c8 100644 --- a/htdocs/langs/nl_BE/install.lang +++ b/htdocs/langs/nl_BE/install.lang @@ -115,8 +115,8 @@ YouMustCreateItAndAllowServerToWrite=U moet deze directorie creëren en schrijfr CharsetChoice=Tekenset keuze CharacterSetClient=Tekenset gebruikt voor gegenereerde HTML-webpagina's CharacterSetClientComment=Kies tekenset voor web display.
      Standaard voorgesteld tekenset die van uw database. -CollationConnection=Teken sorteervolgorde -CollationConnectionComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      Deze parameter kan niet worden gedefiniëerd als de database al bestaat. +DBSortingCollation=Teken sorteervolgorde +DBSortingCollationComment=Choose page code that defines character's sorting order used by database. This parameter is also called 'collation' by some databases.
      Deze parameter kan niet worden gedefiniëerd als de database al bestaat. CharacterSetDatabase=Tekenset voor database CharacterSetDatabaseComment=Kies tekenset gewild voor database creatie.
      Deze parameter kan niet worden gedefinieerd als database al bestaat. YouAskDatabaseCreationSoDolibarrNeedToConnect=U vraagt om database %s te creëren, maar voor dit moet Dolibarr verbinding maken met server %s met super-gebruiker %s machtigingen. diff --git a/htdocs/langs/nl_BE/suppliers.lang b/htdocs/langs/nl_BE/suppliers.lang index 2c3a226584f..5326e9b7fe5 100644 --- a/htdocs/langs/nl_BE/suppliers.lang +++ b/htdocs/langs/nl_BE/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Leverancier AddSupplier=Voeg een leverancier toe SupplierRemoved=Leverancier verwijderd SuppliersInvoice=Leveranciers factuur -SuppliersInvoices=Leveranciers facturen NewSupplier=Nieuwe leverancier History=Geschiedenis ListOfSuppliers=Lijst van de leveranciers diff --git a/htdocs/langs/nl_NL/install.lang b/htdocs/langs/nl_NL/install.lang index 279c1e0541d..b6bccb5d049 100644 --- a/htdocs/langs/nl_NL/install.lang +++ b/htdocs/langs/nl_NL/install.lang @@ -121,8 +121,8 @@ YouMustCreateItAndAllowServerToWrite = U dient deze map te creëren en de juiste CharsetChoice = Keuze van de karakterset CharacterSetClient = Karakterset gebruikt door gegenereerde HTML webpagina's CharacterSetClientComment = Kies de karakterset voor webweergave.
      De standaard voorgestelde karakterset is die van uw database. -CollationConnection = Karakter sorteervolgorde -CollationConnectionComment = Kies een paginacodering die de karaktersortering die gebruikt wordt door de database definieert. Deze instelling wordt ook wel 'collatie' genoemd door een aantal databases.
      Deze instelling kan niet worden ingesteld als de database al bestaat. +DBSortingCollation = Karakter sorteervolgorde +DBSortingCollationComment = Kies een paginacodering die de karaktersortering die gebruikt wordt door de database definieert. Deze instelling wordt ook wel 'collatie' genoemd door een aantal databases.
      Deze instelling kan niet worden ingesteld als de database al bestaat. CharacterSetDatabase = Karakterset voor de database CharacterSetDatabaseComment = Kies de gewenste karakterset die gebruikt wordt voor de databasecreatie. YouAskDatabaseCreationSoDolibarrNeedToConnect = U wilt de database %s, creëren, maar hiervoor moet Dolibarr met de server %s verbinden met superuser (root) %s rechten. diff --git a/htdocs/langs/nl_NL/members.lang b/htdocs/langs/nl_NL/members.lang index 88039618f94..385be2142b8 100644 --- a/htdocs/langs/nl_NL/members.lang +++ b/htdocs/langs/nl_NL/members.lang @@ -171,7 +171,7 @@ LastSubscriptionAmount = Laatste abonnementsaantal // START - Lines generated via autotranslator.php tool (2011-10-10 01:46:39). // Reference language: en_US -> nl_NL MembersStatisticsByState=Leden statistieken per staat / provincie -MembersStatisticsByTowne=Leden van de statistieken per gemeente +MembersStatisticsByTown=Leden van de statistieken per gemeente NbOfMembers=Aantal leden NoValidatedMemberYet=Geen gevalideerde leden gevonden MembersByCountryDesc=Dit scherm tonen statistieken over de leden door de landen. Grafisch is echter afhankelijk van Google online grafiek service en is alleen beschikbaar als een internet verbinding is werkt. diff --git a/htdocs/langs/nl_NL/suppliers.lang b/htdocs/langs/nl_NL/suppliers.lang index 6d43ab7831b..1d8f1a032d8 100644 --- a/htdocs/langs/nl_NL/suppliers.lang +++ b/htdocs/langs/nl_NL/suppliers.lang @@ -5,7 +5,6 @@ Supplier = Leverancier AddSupplier = Voeg een leverancier toe SupplierRemoved = Leverancier verwijderd SuppliersInvoice = Leveranciersfactuur -SuppliersInvoices = Leveranciersfacturen NewSupplier = Nieuwe leverancier History = Geschiedenis ListOfSuppliers = Leverancierslijst diff --git a/htdocs/langs/pl_PL/install.lang b/htdocs/langs/pl_PL/install.lang index 3a09bff58ed..aac038cf676 100644 --- a/htdocs/langs/pl_PL/install.lang +++ b/htdocs/langs/pl_PL/install.lang @@ -112,8 +112,8 @@ YouMustCreateItAndAllowServerToWrite=Musisz utworzyć ten katalog i zezwolić se CharsetChoice=Wybór zestawu kodowania CharacterSetClient=Zestaw kodowania dla wygenerowanych stron HTML CharacterSetClientComment=Wybierz zestaw kodowania znaków dla stron HTML.
      Domyślnym wyborem zestawu znaków jest ten zastosowany w bazie danych. -CollationConnection=Sposób sortowania znaków -CollationConnectionComment=Wybierz stronę kodową, która definiuje sposób sortowania znaków używany przez bazę danych. Ten parametr jest często nazywany 'collation'.
      Jeśli baza już istnieje, nie ma możliwości zdefiniowania tego parametru. +DBSortingCollation=Sposób sortowania znaków +DBSortingCollationComment=Wybierz stronę kodową, która definiuje sposób sortowania znaków używany przez bazę danych. Ten parametr jest często nazywany 'collation'.
      Jeśli baza już istnieje, nie ma możliwości zdefiniowania tego parametru. CharacterSetDatabase=Zestaw znaków dla bazy danych CharacterSetDatabaseComment=Wybierz zesta znaków, który zostanie użyty do utworzenia bazy danych.
      Jeśli baza już istnieje, nie ma możliwości zdefiniowania tego parametru. YouAskDatabaseCreationSoDolibarrNeedToConnect=Wybrano by utworzyć bazę danych %s, ale by tego dokonać Dolibarr musi połączyć się z serwerem %s na prawach superużytkownika %s. @@ -330,8 +330,8 @@ YouMustCreateItAndAllowServerToWrite=Du må lage denne katalogen og la for web-s CharsetChoice=Tegnsett valg CharacterSetClient=Tegnsett brukes for genererte HTML-nettsider CharacterSetClientComment=Velg tegnsettet for web visning.
      Standard foreslåtte tegnsett er en av databasen. -CollationConnection=Tegn sorteringsrekkefølgen -CollationConnectionComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. +DBSortingCollation=Tegn sorteringsrekkefølgen +DBSortingCollationComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. CharacterSetDatabase=Tegnsettet for databasen CharacterSetDatabaseComment=Velg tegnsettet ettersøkt for database skaperverk.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. YouAskDatabaseCreationSoDolibarrNeedToConnect=ber deg opprette database %s, men for dette, Dolibarr trenger å koble til serveren %s med superbruker %s tillatelser. diff --git a/htdocs/langs/pl_PL/members.lang b/htdocs/langs/pl_PL/members.lang index 169b1865f4d..4782007adfd 100644 --- a/htdocs/langs/pl_PL/members.lang +++ b/htdocs/langs/pl_PL/members.lang @@ -200,7 +200,7 @@ LastSubscriptionDate=Ostatnia data abonament LastSubscriptionAmount=Ostatnio kwota subskrypcji MembersStatisticsByCountries=Użytkownicy statystyki według kraju MembersStatisticsByState=Użytkownicy statystyki na State / Province -MembersStatisticsByTowne=Użytkownicy statystyki na miasto +MembersStatisticsByTown=Użytkownicy statystyki na miasto NbOfMembers=Liczba członków NoValidatedMemberYet=Żadna potwierdzona znaleziono użytkowników MembersByCountryDesc=Ten ekran pokaże statystyki członków przez poszczególne kraje. Graficzny zależy jednak na Google usługi online grafów i jest dostępna tylko wtedy, gdy połączenie internetowe działa. diff --git a/htdocs/langs/pl_PL/suppliers.lang b/htdocs/langs/pl_PL/suppliers.lang index 88c424f5ab0..ce47c187730 100644 --- a/htdocs/langs/pl_PL/suppliers.lang +++ b/htdocs/langs/pl_PL/suppliers.lang @@ -16,7 +16,6 @@ Supplier=Dostawca AddSupplier=Dodaj dostawcy SupplierRemoved=Dostawca usunięte SuppliersInvoice=Dostawcy faktury -SuppliersInvoices=Dostawcy faktur NewSupplier=Nowy dostawca History=Historia ListOfSuppliers=Lista dostawców diff --git a/htdocs/langs/pt_BR/install.lang b/htdocs/langs/pt_BR/install.lang index f3fa394075e..c398d91fcbd 100644 --- a/htdocs/langs/pt_BR/install.lang +++ b/htdocs/langs/pt_BR/install.lang @@ -115,8 +115,8 @@ YouMustCreateItAndAllowServerToWrite=Você deve criar este diretório e para per CharsetChoice=Conjunto de caracteres escolha CharacterSetClient=Conjunto de caracteres utilizados para páginas HTML geradas CharacterSetClientComment=Escolher conjunto de caracteres para exibir na web.
      Padrão proposto um conjunto de caracteres é o do seu banco de dados. -CollationConnection=Caracteres triagem fim -CollationConnectionComment=Escolha página código que define o caráter triagem fim utilizado por base de dados. Este parâmetro é também chamado de "recolha" por alguns bancos de dados.
      Esse parâmetro não pode ser definido se de dados já existe. +DBSortingCollation=Caracteres triagem fim +DBSortingCollationComment=Escolha página código que define o caráter triagem fim utilizado por base de dados. Este parâmetro é também chamado de "recolha" por alguns bancos de dados.
      Esse parâmetro não pode ser definido se de dados já existe. CharacterSetDatabase=Conjunto de caracteres para o banco de dados CharacterSetDatabaseComment=Escolher conjunto de caracteres queria para o banco de dados criação.
      Esse parâmetro não pode ser definido se de dados já existe. YouAskDatabaseCreationSoDolibarrNeedToConnect=Você pergunta para criar base de dados %s, mas, para isso, Dolibarr necessidade de se conectar ao servidor com o super-usuário %s %s permissões. diff --git a/htdocs/langs/pt_BR/suppliers.lang b/htdocs/langs/pt_BR/suppliers.lang index acc5ad3d5e6..537a39c03f8 100644 --- a/htdocs/langs/pt_BR/suppliers.lang +++ b/htdocs/langs/pt_BR/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Fornecedor AddSupplier=Adicionar Fornecedor SupplierRemoved=Fornecedor Eliminado SuppliersInvoice=Faturas do Fornecedor -SuppliersInvoices=Faturas de Fornecedores NewSupplier=Novo Fornecedor History=Histórico ListOfSuppliers=Lista de Fornecedores diff --git a/htdocs/langs/pt_PT/install.lang b/htdocs/langs/pt_PT/install.lang index 505824e52c4..4110c879efe 100644 --- a/htdocs/langs/pt_PT/install.lang +++ b/htdocs/langs/pt_PT/install.lang @@ -19,8 +19,8 @@ CheckToCreateUser=Caixa de login, se não existe e deve ser criado.
      Neste c CheckToForceHttps=Marque esta opção para forçar conexões seguras (https).
      Isso exige que o servidor web está configurado com um certificado SSL. ChoosedMigrateScript=Escolhido migrar script ChooseYourSetupMode=Escolha o seu modo de configuração e clique em "Iniciar" ... -CollationConnection=Caracteres triagem fim -CollationConnectionComment=Escolha página código que define o caráter triagem fim utilizado por base de dados. Este parâmetro é também chamado de "recolha" por alguns bancos de dados.
      Esse parâmetro não pode ser definido se de dados já existe. +DBSortingCollation=Caracteres triagem fim +DBSortingCollationComment=Escolha página código que define o caráter triagem fim utilizado por base de dados. Este parâmetro é também chamado de "recolha" por alguns bancos de dados.
      Esse parâmetro não pode ser definido se de dados já existe. ConfFileCouldBeCreated=O ficheiro de configuração conf.php pôde ser criado. ConfFileDoesNotExists=Ficheiro de configuração %s não existe! ConfFileDoesNotExistsAndCouldNotBeCreated=Ficheiro de configuração %s não existe e não poderia ser criado! diff --git a/htdocs/langs/pt_PT/members.lang b/htdocs/langs/pt_PT/members.lang index 0fb1b068b90..48f2ee0a65b 100644 --- a/htdocs/langs/pt_PT/members.lang +++ b/htdocs/langs/pt_PT/members.lang @@ -187,7 +187,7 @@ LastSubscriptionDate=Última data de subscrição LastSubscriptionAmount=Montante de subscrição Última MembersStatisticsByCountries=Membros estatísticas por país MembersStatisticsByState=Membros estatísticas por estado / província -MembersStatisticsByTowne=Membros estatísticas por cidade +MembersStatisticsByTown=Membros estatísticas por cidade NbOfMembers=Número de membros NoValidatedMemberYet=Nenhum membro validado encontrado MembersByCountryDesc=Esta tela mostrará estatísticas sobre membros dos países. Gráfico depende, contudo, o serviço Google gráfico on-line e está disponível apenas se uma ligação à Internet é está funcionando. diff --git a/htdocs/langs/pt_PT/suppliers.lang b/htdocs/langs/pt_PT/suppliers.lang index faab981a749..85dfde74227 100644 --- a/htdocs/langs/pt_PT/suppliers.lang +++ b/htdocs/langs/pt_PT/suppliers.lang @@ -5,7 +5,6 @@ Supplier=Fornecedor AddSupplier=Adicionar Fornecedor SupplierRemoved=Fornecedor Eliminado SuppliersInvoice=Facturas do Fornecedor -SuppliersInvoices=Facturas de Fornecedores NewSupplier=Novo Fornecedor History=Histórico ListOfSuppliers=Lista de Fornecedores diff --git a/htdocs/langs/ro_RO/install.lang b/htdocs/langs/ro_RO/install.lang index 8e1012b307a..bbf504158fc 100644 --- a/htdocs/langs/ro_RO/install.lang +++ b/htdocs/langs/ro_RO/install.lang @@ -922,8 +922,8 @@ YouMustCreateItAndAllowServerToWrite=Trebuie să creaţi acest director şi pent CharsetChoice=Set de caractere alegere CharacterSetClient=Setul de caractere utilizat pentru paginile web generate HTML CharacterSetClientComment=Alegeţi setul de caractere pentru afişarea Web.
      Set de caractere implicit propusă este una din baza de date. -CollationConnection=Caracter de sortare pentru -CollationConnectionComment=Alege codul paginii, pentru că defineşte caracterul de sortare folosit de baza de date. Acest parametru este, de asemenea, numit "confruntarea" de unele baze de date.
      Acest parametru nu poate fi definit în cazul în care baza de date există deja. +DBSortingCollation=Caracter de sortare pentru +DBSortingCollationComment=Alege codul paginii, pentru că defineşte caracterul de sortare folosit de baza de date. Acest parametru este, de asemenea, numit "confruntarea" de unele baze de date.
      Acest parametru nu poate fi definit în cazul în care baza de date există deja. CharacterSetDatabase=Set de caractere pentru baza de date CharacterSetDatabaseComment=Alegeţi setul de caractere dorit pentru crearea de baze de date.
      Acest parametru nu poate fi definit în cazul în care baza de date există deja. YouAskDatabaseCreationSoDolibarrNeedToConnect=Să vă întreb pentru a crea %s de baze de date, dar pentru acest lucru, Dolibarr trebuie să se conecteze la server %s cu permisiuni super %s de utilizator. diff --git a/htdocs/langs/ro_RO/members.lang b/htdocs/langs/ro_RO/members.lang index 99eba7915ad..067614c8b30 100644 --- a/htdocs/langs/ro_RO/members.lang +++ b/htdocs/langs/ro_RO/members.lang @@ -203,7 +203,7 @@ LastSubscriptionDate=Ultima data de abonament LastSubscriptionAmount=Ultima sumă abonament MembersStatisticsByCountries=Membri statisticilor în funcţie de ţară MembersStatisticsByState=Statistici Membri de stat / provincie -MembersStatisticsByTowne=Statistici Membri de oraş +MembersStatisticsByTown=Statistici Membri de oraş NbOfMembers=Număr de membri NoValidatedMemberYet=Nici membrii validate găsit MembersByCountryDesc=Acest ecran vă arată statisticile cu privire la membrii de ţări. Graphic depinde de toate acestea, cu privire la serviciul on-line Google grafic şi este disponibil numai în cazul în care o conexiune la internet este este de lucru. diff --git a/htdocs/langs/ro_RO/suppliers.lang b/htdocs/langs/ro_RO/suppliers.lang index 9603ceaeb1d..e1a10dc72be 100644 --- a/htdocs/langs/ro_RO/suppliers.lang +++ b/htdocs/langs/ro_RO/suppliers.lang @@ -14,7 +14,6 @@ Supplier=Furnizor AddSupplier=Adauga un furnizor SupplierRemoved=Furnizor eliminat SuppliersInvoice=Furnizori de factură -SuppliersInvoices=Furnizori facturi NewSupplier=New furnizor History=Istorie ListOfSuppliers=Lista de furnizori diff --git a/htdocs/langs/ru_RU/install.lang b/htdocs/langs/ru_RU/install.lang index 745564c84f1..c1697be23ba 100644 --- a/htdocs/langs/ru_RU/install.lang +++ b/htdocs/langs/ru_RU/install.lang @@ -121,8 +121,8 @@ YouMustCreateItAndAllowServerToWrite=Вы должны создать этот CharsetChoice=Выбор набора символов CharacterSetClient=Набор символов, используемых для порожденных HTML веб-страниц CharacterSetClientComment=Выберите набор символов для отображения веб.
      Предлагаемый по умолчанию набор символов является одной из Ваших данных. -CollationConnection=Характер сортировки -CollationConnectionComment=Выберите страницу код, который определяет характер в сортировки используемых данных. Этот параметр называется также 'обобщение' некоторые базы данных.
      Этот параметр не может быть определен, если база данных уже существует. +DBSortingCollation=Характер сортировки +DBSortingCollationComment=Выберите страницу код, который определяет характер в сортировки используемых данных. Этот параметр называется также 'обобщение' некоторые базы данных.
      Этот параметр не может быть определен, если база данных уже существует. CharacterSetDatabase=Набор символов для базы данных CharacterSetDatabaseComment=Выберите набор символов, разыскиваемых за создание базы данных.
      Этот параметр не может быть определен, если база данных уже существует. YouAskDatabaseCreationSoDolibarrNeedToConnect=Вы спросите для создания базы данных %s, но для этого, Dolibarr необходимо подключиться к серверу %s с супер пользователя% с разрешениями. @@ -314,8 +314,8 @@ YouMustCreateItAndAllowServerToWrite=Du må lage denne katalogen og la for web-s CharsetChoice=Tegnsett valg CharacterSetClient=Tegnsett brukes for genererte HTML-nettsider CharacterSetClientComment=Velg tegnsettet for web visning.
      Standard foreslåtte tegnsett er en av databasen. -CollationConnection=Tegn sorteringsrekkefølgen -CollationConnectionComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. +DBSortingCollation=Tegn sorteringsrekkefølgen +DBSortingCollationComment=Velg side kode som definerer figuren sorteringsrekkefølgen brukes av databasen. Denne parameteren blir også kalt "sortering" av noen databaser.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. CharacterSetDatabase=Tegnsettet for databasen CharacterSetDatabaseComment=Velg tegnsettet ettersøkt for database skaperverk.
      Denne parameteren kan ikke defineres dersom databasen allerede eksisterer. YouAskDatabaseCreationSoDolibarrNeedToConnect=ber deg opprette database %s, men for dette, Dolibarr trenger å koble til serveren %s med superbruker %s tillatelser. diff --git a/htdocs/langs/ru_RU/members.lang b/htdocs/langs/ru_RU/members.lang index 2c20a9b9006..926338e3119 100644 --- a/htdocs/langs/ru_RU/members.lang +++ b/htdocs/langs/ru_RU/members.lang @@ -198,7 +198,7 @@ LastSubscriptionDate=Последний день подписки LastSubscriptionAmount=Последняя сумма подписки MembersStatisticsByCountries=Члены статистику по странам MembersStatisticsByState=Члены статистики штата / провинции -MembersStatisticsByTowne=Члены статистики города +MembersStatisticsByTown=Члены статистики города NbOfMembers=Количество членов NoValidatedMemberYet=Нет проверки члены найдены MembersByCountryDesc=Этот экран покажет вам статистику членов странами. Графический зависит однако от Google сервис график онлайн и доступна, только если подключение к Интернету работает. diff --git a/htdocs/langs/ru_RU/suppliers.lang b/htdocs/langs/ru_RU/suppliers.lang index 252c838ad1e..c118f0af1a9 100644 --- a/htdocs/langs/ru_RU/suppliers.lang +++ b/htdocs/langs/ru_RU/suppliers.lang @@ -14,7 +14,6 @@ Supplier=Поставщик AddSupplier=Добавить поставщиком SupplierRemoved=Поставщик удален SuppliersInvoice=Поставщики счета -SuppliersInvoices=Поставщики счета NewSupplier=Новый поставщик History=История ListOfSuppliers=Список поставщиков diff --git a/htdocs/langs/ru_UA/install.lang b/htdocs/langs/ru_UA/install.lang index b23fdef3145..45d05d6eb5a 100644 --- a/htdocs/langs/ru_UA/install.lang +++ b/htdocs/langs/ru_UA/install.lang @@ -102,8 +102,8 @@ YouMustCreateItAndAllowServerToWrite=Вы должны создать эту д CharsetChoice=Выбор набора символов CharacterSetClient=Набор символов, используемый для сгенерированных HTML веб-страниц CharacterSetClientComment=Выберите набор символов для веба.
      По умолчанию предлагается набор символов является одним из базы данных. -CollationConnection=Порядок сортировки символов -CollationConnectionComment=Выберите страницу код, который определяет порядок сортировки персонажа используются базы данных. Этот параметр также называется "сортировки" на некоторых базах данных.
      Этот параметр не может быть определен, если база данных уже существует. +DBSortingCollation=Порядок сортировки символов +DBSortingCollationComment=Выберите страницу код, который определяет порядок сортировки персонажа используются базы данных. Этот параметр также называется "сортировки" на некоторых базах данных.
      Этот параметр не может быть определен, если база данных уже существует. CharacterSetDatabase=Набор символов для базы данных KeepDefaultValuesWamp=Вы можете использовать мастер установки из Dolibarr DoliWamp, поэтому значения предлагаемых здесь уже оптимизированы. Изменение их, только если вы знаете, что вы делаете. KeepDefaultValuesDeb=Вы можете использовать мастер Dolibarr установки из Linux-пакет (Ubuntu, Debian, Fedora ...), поэтому значения предлагаемых здесь уже оптимизированы. Только пароль владельца базы данных для создания должны быть заполнены. Изменение других параметров, только если вы знаете что вы делаете. diff --git a/htdocs/langs/sl_SI/install.lang b/htdocs/langs/sl_SI/install.lang index cda7ad0229e..ecc44497626 100644 --- a/htdocs/langs/sl_SI/install.lang +++ b/htdocs/langs/sl_SI/install.lang @@ -121,8 +121,8 @@ YouMustCreateItAndAllowServerToWrite = Ustvariti morate to mapo in dovoliti sple CharsetChoice = Izbira nabora znakov CharacterSetClient = Nabor znakov, uporabljen za generiranje HTML spletnih strani CharacterSetClientComment = Izbira nabora znakov za spletni prikaz.
      Privzet predlagan nabor znakov je tisti iz vaše baze podatkov. -CollationConnection = Vrstni red znakov -CollationConnectionComment = Izberite kodno tabelo, ki definira zaporedje znakov, ki ga uporablja baza podatkov. Ta parameter se v nekaterih bazah podatkov imenuje tudi 'collation'.
      Tega parametra ni možno definirati, če baza podatkov že obstaja. +DBSortingCollation = Vrstni red znakov +DBSortingCollationComment = Izberite kodno tabelo, ki definira zaporedje znakov, ki ga uporablja baza podatkov. Ta parameter se v nekaterih bazah podatkov imenuje tudi 'collation'.
      Tega parametra ni možno definirati, če baza podatkov že obstaja. CharacterSetDatabase = Nabor znakov za bazo podatkov CharacterSetDatabaseComment = Izberite nabor znakov, ki ga želite za kreiranje baze podatkov.
      Tega parametra ni možno definirati, če baza podatkov že obstaja. YouAskDatabaseCreationSoDolibarrNeedToConnect = Želeli ste kreirati bazo podatkov %s, vendar se mora za to Dolibarr povezati s strežnikom %s z dovoljenji super uporabnika %s. diff --git a/htdocs/langs/sl_SI/members.lang b/htdocs/langs/sl_SI/members.lang index 62e47644903..a16b20fbca8 100644 --- a/htdocs/langs/sl_SI/members.lang +++ b/htdocs/langs/sl_SI/members.lang @@ -167,7 +167,7 @@ LastSubscriptionDate = Zadnji datum članarine LastSubscriptionAmount = Zadnji znesek članarine MembersStatisticsByCountries = Statistika članov po državah MembersStatisticsByState = Statistika članov po deželah -MembersStatisticsByTowne = Statistika članov po mestih +MembersStatisticsByTown = Statistika članov po mestih NbOfMembers = Število članov NoValidatedMemberYet = Najdeni so nepotrjeni člani MembersByCountryDesc = Na tem zaslonu je prikazana statistika članov po državah. Grafika je odvisna od Google storitve in je na voljo samo pri delujoči internetni povezavi. diff --git a/htdocs/langs/sl_SI/suppliers.lang b/htdocs/langs/sl_SI/suppliers.lang index 42e73cd433e..4df1bc83641 100644 --- a/htdocs/langs/sl_SI/suppliers.lang +++ b/htdocs/langs/sl_SI/suppliers.lang @@ -5,7 +5,6 @@ Supplier = Dobavitelj AddSupplier = Dodaj dobavitelja SupplierRemoved = Dobavitelj odstranjen SuppliersInvoice = Računi dobavitelja -SuppliersInvoices = Računi dobaviteljev NewSupplier = Nov dobavitelj History = Zgodovina ListOfSuppliers = Seznam dobaviteljev diff --git a/htdocs/langs/sv_SE/install.lang b/htdocs/langs/sv_SE/install.lang index d5faa03021d..27b3611032b 100644 --- a/htdocs/langs/sv_SE/install.lang +++ b/htdocs/langs/sv_SE/install.lang @@ -127,8 +127,8 @@ YouMustCreateItAndAllowServerToWrite=Du måste skapa denna katalog och möjligg CharsetChoice=Teckenuppsättning val CharacterSetClient=Teckenuppsättning som används för genererade HTML-sidor CharacterSetClientComment=Välj teckenuppsättning för visning på webben.
      Standard föreslagna teckenuppsättning är en av din databas. -CollationConnection=Tecken sorteringsordning -CollationConnectionComment=Välj sida kod som definierar karaktärens sorteringsordningen används av databasen. Denna parameter kallas även "sammanställning" av vissa databaser.
      Denna parameter kan inte definieras om databasen redan finns. +DBSortingCollation=Tecken sorteringsordning +DBSortingCollationComment=Välj sida kod som definierar karaktärens sorteringsordningen används av databasen. Denna parameter kallas även "sammanställning" av vissa databaser.
      Denna parameter kan inte definieras om databasen redan finns. CharacterSetDatabase=Teckenuppsättningen för databasen CharacterSetDatabaseComment=Välj teckenuppsättning som söks för databas skapas.
      Denna parameter kan inte definieras om databasen redan finns. YouAskDatabaseCreationSoDolibarrNeedToConnect=Du ber att skapa databasen %s, men för detta Dolibarr behöver ansluta till servern %s med super user %s behörigheter. diff --git a/htdocs/langs/sv_SE/members.lang b/htdocs/langs/sv_SE/members.lang index 38e94794837..bf398731fe3 100644 --- a/htdocs/langs/sv_SE/members.lang +++ b/htdocs/langs/sv_SE/members.lang @@ -190,7 +190,7 @@ LastSubscriptionDate=Senast teckningsdag LastSubscriptionAmount=Senast teckningsbelopp MembersStatisticsByCountries=Medlemmar statistik per land MembersStatisticsByState=Medlemmar statistik från stat / provins -MembersStatisticsByTowne=Medlemmar statistik per kommun +MembersStatisticsByTown=Medlemmar statistik per kommun NbOfMembers=Antal medlemmar NoValidatedMemberYet=Inga godkända medlemmar hittades MembersByCountryDesc=Denna skärm visar statistik om medlemmar med länder. Grafisk beror dock på Google online grafen service och är tillgänglig endast om en Internet-anslutning fungerar. diff --git a/htdocs/langs/sv_SE/suppliers.lang b/htdocs/langs/sv_SE/suppliers.lang index 159fff54da5..3d99a40f5fe 100644 --- a/htdocs/langs/sv_SE/suppliers.lang +++ b/htdocs/langs/sv_SE/suppliers.lang @@ -13,7 +13,6 @@ Supplier=Leverantör AddSupplier=Lägg till en leverantör SupplierRemoved=Leverantör bort SuppliersInvoice=Leverantörer faktura -SuppliersInvoices=Leverantörer fakturor NewSupplier=Ny leverantör History=Historia ListOfSuppliers=Lista över leverantörer diff --git a/htdocs/langs/tr_TR/install.lang b/htdocs/langs/tr_TR/install.lang index f3abb1d4cb2..7967446d570 100755 --- a/htdocs/langs/tr_TR/install.lang +++ b/htdocs/langs/tr_TR/install.lang @@ -131,8 +131,8 @@ YouMustCreateItAndAllowServerToWrite=Bu dizini oluşturmanız ve web sunucusuna CharsetChoice=Karakter seti seçimi CharacterSetClient=HTML web sayfalarında kullanılmak üzere oluşturulan karakter seti CharacterSetClientComment=Web görüntüsü için karakter seti seçin.
      Varsayılan önerilen karakter seti veritabanınızda olanlardan biridir. -CollationConnection=Karakter sıralama düzeni -CollationConnectionComment=Veritabanı tarafından kullanılan karakterlerin sıralam düzenini tanımlayan sayfa kodunu kullanın. Bu parametre bazı veritabanları tarafından 'harmanlama' olarak adlandırılır.
      Eğer veritabanı zaten varsa bu parametre tanımlanamaz. +DBSortingCollation=Karakter sıralama düzeni +DBSortingCollationComment=Veritabanı tarafından kullanılan karakterlerin sıralam düzenini tanımlayan sayfa kodunu kullanın. Bu parametre bazı veritabanları tarafından 'harmanlama' olarak adlandırılır.
      Eğer veritabanı zaten varsa bu parametre tanımlanamaz. CharacterSetDatabase=Veritabanı için karakter seti CharacterSetDatabaseComment=Veritabanı oluşturmak istenen karakter setini seçin.
      Eğer veritabanı zaten varsa bu parametre tanımlanamaz. YouAskDatabaseCreationSoDolibarrNeedToConnect=%s veritabanını oluşturmanız istenebilir, bunun için, Dolibarr %s sunucusuna %s süper kullanıcı izniyle bağlanmak ister. diff --git a/htdocs/langs/tr_TR/members.lang b/htdocs/langs/tr_TR/members.lang index 45cf570e6de..fc201e9e829 100644 --- a/htdocs/langs/tr_TR/members.lang +++ b/htdocs/langs/tr_TR/members.lang @@ -180,7 +180,7 @@ LastSubscriptionAmount=Son abonelik tutarı "MembersStatisticsByCountries=Ülkelere göre üyelik istatistikleri " MembersStatisticsByState=Eyalete/ile göre üyelik istatistikleri -MembersStatisticsByTowne=İlçelere göre üyelik istatistikleri +MembersStatisticsByTown=İlçelere göre üyelik istatistikleri NbOfMembers=Üye sayısı NoValidatedMemberYet=Doğrulanmamış üye bulunmadı MembersByCountryDesc=Bu ekran ülkelere göre üyelik istatisklerini görüntüler. Grafik eğer internet hizmeti çalışıyor ise sadece google çevrimiçi grafik hizmetince sağlanır. diff --git a/htdocs/langs/tr_TR/suppliers.lang b/htdocs/langs/tr_TR/suppliers.lang index f9543986615..fb3f2aa2945 100644 --- a/htdocs/langs/tr_TR/suppliers.lang +++ b/htdocs/langs/tr_TR/suppliers.lang @@ -12,7 +12,6 @@ Supplier=Tedarikçi AddSupplier=Bir tedarikçi ekle SupplierRemoved=Tedarikçi kaldırıldı SuppliersInvoice=Tedarikçi faturası -SuppliersInvoices=Tedarikçi faturaları NewSupplier=Yeni tedarikçi History=Geçmiş ListOfSuppliers=Tedarikçiler listesi diff --git a/htdocs/langs/zh_CN/install.lang b/htdocs/langs/zh_CN/install.lang index 1ed86cd67a2..9685a7b9f4b 100644 --- a/htdocs/langs/zh_CN/install.lang +++ b/htdocs/langs/zh_CN/install.lang @@ -126,8 +126,8 @@ YouMustCreateItAndAllowServerToWrite=您必须创建此目录和Web服务器允 CharsetChoice=字符集的选择 CharacterSetClient=字符集生成的HTML网页使用 CharacterSetClientComment=选择字符集的网页显示。
      默认建议的字符集是您的数据库之一。 -CollationConnection=字符排序 -CollationConnectionComment=选择页面的代码定义字符的排序顺序由数据库使用。此参数也被称为'整理一些数据库的。
      此参数不能被定义,如果数据库已经存在。 +DBSortingCollation=字符排序 +DBSortingCollationComment=选择页面的代码定义字符的排序顺序由数据库使用。此参数也被称为'整理一些数据库的。
      此参数不能被定义,如果数据库已经存在。 CharacterSetDatabase=数据库字符集 CharacterSetDatabaseComment=选择想要的字符集的数据库创建。
      此参数不能被定义,如果数据库已经存在。 YouAskDatabaseCreationSoDolibarrNeedToConnect=你问到创建数据库%s,但对于这一点,Dolibarr需要连接到伺服器%S与超级用户%s的权限。 diff --git a/htdocs/langs/zh_CN/members.lang b/htdocs/langs/zh_CN/members.lang index 9e4704586fa..e8ad2efad6f 100644 --- a/htdocs/langs/zh_CN/members.lang +++ b/htdocs/langs/zh_CN/members.lang @@ -190,7 +190,7 @@ LastSubscriptionDate=最后认购日期 LastSubscriptionAmount=最后认购金额 MembersStatisticsByCountries=成员由国家统计 MembersStatisticsByState=成员由州/省的统计信息 -MembersStatisticsByTowne=成员由镇统计 +MembersStatisticsByTown=成员由镇统计 NbOfMembers=成员数 NoValidatedMemberYet=没有验证的成员发现 MembersByCountryDesc=该屏幕显示您成员国的统计数字。然而,图形取决于谷歌在线图服务,可只有一个互联网连接工作。 diff --git a/htdocs/langs/zh_CN/suppliers.lang b/htdocs/langs/zh_CN/suppliers.lang index be4673ed4e4..49769de806b 100644 --- a/htdocs/langs/zh_CN/suppliers.lang +++ b/htdocs/langs/zh_CN/suppliers.lang @@ -13,7 +13,6 @@ Supplier=供应商 AddSupplier=新增供应商 SupplierRemoved=供应商删除 SuppliersInvoice=供应商发票 -SuppliersInvoices=供应商发票 NewSupplier=新供应商 History=历史 ListOfSuppliers=供应商名单 diff --git a/htdocs/langs/zh_TW/install.lang b/htdocs/langs/zh_TW/install.lang index 329f4c39c62..192528ec126 100644 --- a/htdocs/langs/zh_TW/install.lang +++ b/htdocs/langs/zh_TW/install.lang @@ -126,8 +126,8 @@ YouMustCreateItAndAllowServerToWrite=您必須創建此目錄和Web服務器允 CharsetChoice=字符集的選擇 CharacterSetClient=字符集生成的HTML網頁使用 CharacterSetClientComment=選擇字符集的網頁顯示。
      默認建議的字符集是您的數據庫之一。 -CollationConnection=字符排序 -CollationConnectionComment=選擇頁面的代碼定義字符的排序順序由數據庫使用。此參數也被稱為'整理一些數據庫的。
      此參數不能被定義,如果數據庫已經存在。 +DBSortingCollation=字符排序 +DBSortingCollationComment=選擇頁面的代碼定義字符的排序順序由數據庫使用。此參數也被稱為'整理一些數據庫的。
      此參數不能被定義,如果數據庫已經存在。 CharacterSetDatabase=數據庫字符集 CharacterSetDatabaseComment=選擇想要的字符集的數據庫創建。
      此參數不能被定義,如果數據庫已經存在。 YouAskDatabaseCreationSoDolibarrNeedToConnect=你問到創建數據庫%s,但對於這一點,Dolibarr需要連接到伺服器%S與超級用戶%s的權限。 diff --git a/htdocs/langs/zh_TW/members.lang b/htdocs/langs/zh_TW/members.lang index 6b4aff0ee8e..c08035af7a1 100644 --- a/htdocs/langs/zh_TW/members.lang +++ b/htdocs/langs/zh_TW/members.lang @@ -190,7 +190,7 @@ LastSubscriptionDate=最後認購日期 LastSubscriptionAmount=最後認購金額 MembersStatisticsByCountries=成員由國家統計 MembersStatisticsByState=成員由州/省的統計信息 -MembersStatisticsByTowne=成員由鎮統計 +MembersStatisticsByTown=成員由鎮統計 NbOfMembers=成員數 NoValidatedMemberYet=沒有驗證的成員發現 MembersByCountryDesc=該屏幕顯示您成員國的統計數字。然而,圖形取決於谷歌在線圖服務,可只有一個互聯網連接工作。 diff --git a/htdocs/langs/zh_TW/suppliers.lang b/htdocs/langs/zh_TW/suppliers.lang index 8a3e4b5ee2f..24bb921b63c 100644 --- a/htdocs/langs/zh_TW/suppliers.lang +++ b/htdocs/langs/zh_TW/suppliers.lang @@ -13,7 +13,6 @@ Supplier=供應商 AddSupplier=新增供應商 SupplierRemoved=供應商刪除 SuppliersInvoice=供應商的發票 -SuppliersInvoices=供應商的發票 NewSupplier=新供應商 History=歷史 ListOfSuppliers=供應商名單 diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index bcd0ed5c77a..a0b28c7ff25 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -946,13 +946,10 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs if (! $disablejs && ! empty($conf->use_javascript_ajax)) { $ext='.js'; - if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) { - $ext='.jgz'; - } // mini='_mini', ext='.gz' // JQuery. Must be before other includes print ''."\n"; - if (constant('JS_JQUERY')) print ''."\n"; + if (constant('JS_JQUERY')) print ''."\n"; else print ''."\n"; if (constant('JS_JQUERY_UI')) print ''."\n"; else print ''."\n"; diff --git a/htdocs/margin/lib/margins.lib.php b/htdocs/margin/lib/margins.lib.php index 99e46b1161c..34cecb83e05 100644 --- a/htdocs/margin/lib/margins.lib.php +++ b/htdocs/margin/lib/margins.lib.php @@ -40,10 +40,12 @@ function marges_admin_prepare_head() // Show more tabs from modules // Entries must be declared in modules descriptor with line - // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,'',$head,$h,'margesadmin'); + complete_head_from_modules($conf,$langs,'',$head,$h,'margesadmin','remove'); + return $head; } diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 9d6897c6de1..732215c9149 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -212,6 +212,6 @@ if (! defined('NOREQUIRETRAN')) if (! defined('MAIN_LABEL_MENTION_NPR') ) define('MAIN_LABEL_MENTION_NPR','NPR'); // We force feature to help debug -$conf->global->MAIN_JS_ON_PAYMENT=0; // We set to zero to unifrmize way of working between customer and supplier payments +//$conf->global->MAIN_JS_ON_PAYMENT=0; ?> diff --git a/htdocs/paypal/lib/paypal.lib.php b/htdocs/paypal/lib/paypal.lib.php index 72843f6aeeb..b1dd74c35a7 100755 --- a/htdocs/paypal/lib/paypal.lib.php +++ b/htdocs/paypal/lib/paypal.lib.php @@ -36,6 +36,9 @@ function llxHeaderPaypal($title, $head = "") header("Content-type: text/html; charset=".$conf->file->character_set_client); + $appli='Dolibarr'; + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE; + print ''; //print ''; print "\n"; @@ -43,7 +46,7 @@ function llxHeaderPaypal($title, $head = "") print "\n"; print ''."\n"; print ''."\n"; - print ''."\n"; + print ''."\n"; print "".$title."\n"; if ($head) print $head."\n"; if (! empty($conf->global->PAYPAL_CSS_URL)) print ''."\n"; @@ -63,9 +66,6 @@ function llxHeaderPaypal($title, $head = "") // Output standard javascript links $ext='.js'; - if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) { - $ext='.jgz'; - } // mini='_mini', ext='.gz' // JQuery. Must be before other includes print ''."\n"; @@ -73,8 +73,8 @@ function llxHeaderPaypal($title, $head = "") // jQuery jnotify if (empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY)) { - print ''."\n"; - print ''."\n"; + print ''."\n"; + print ''."\n"; } } print "\n"; @@ -182,8 +182,10 @@ function paypaladmin_prepare_head() // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab - // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab - complete_head_from_modules($conf,$langs,$object,$head,$h,'paypaladmin'); + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf,$langs,$object,$head,$h,'paypaladmin'); + + complete_head_from_modules($conf,$langs,$object,$head,$h,'paypaladmin','remove'); return $head; } diff --git a/htdocs/product/fiche.php b/htdocs/product/fiche.php index ce68665cb69..443b0bc4be4 100644 --- a/htdocs/product/fiche.php +++ b/htdocs/product/fiche.php @@ -1380,7 +1380,7 @@ print "\n
      \n"; * All the "Add to" areas */ -if ($id && ($action == '' || $action == 'view') && $object->status) +if ($object->id && ($action == '' || $action == 'view') && $object->status) { print ''; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 4f631358c9f..3dca030a921 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2012 Laurent Destailleur * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2010-2011 Juanjo Menent + * Copyright (C) 2010-2012 Juanjo Menent * Copyright (C) 2012 Christophe Battarel * * This program is free software; you can redistribute it and/or modify @@ -34,6 +34,8 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; $langs->load("products"); $langs->load("suppliers"); $langs->load("bills"); +// Charges ???? +if (! empty($conf->margin->enabled)) $langs->load("margins"); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -349,11 +351,8 @@ if ($id || $ref) //print $form->load_tva('tva_tx',$product->tva_tx,$supplier,$mysoc); // Do not use list here as it may be any vat rates for any country if (! empty($socid)) // When update { - $supplierselected=new Societe($db); - $supplierselected->fetch($socid); $default_vat=get_default_tva($supplier, $mysoc, $product->id); } - if ($action == 'add_price' && $socid) $default_vat=$product->tva_tx; // If editing product-fourn print ''; print ''; diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php index b34bfb472ec..c7990224d69 100644 --- a/htdocs/product/stats/facture_fournisseur.php +++ b/htdocs/product/stats/facture_fournisseur.php @@ -165,8 +165,7 @@ if ($id > 0 || ! empty($ref)) print ""; print "\n"; - $fac=new Facture($db); - print ''; + print ''; print "\n"; $i++; } diff --git a/htdocs/public/paybox/newpayment.php b/htdocs/public/paybox/newpayment.php index 89c57e87139..c311fd20893 100644 --- a/htdocs/public/paybox/newpayment.php +++ b/htdocs/public/paybox/newpayment.php @@ -761,7 +761,7 @@ if ($found && ! $error) // We are in a management option and no error } else { - dol_print_error_email(); + dol_print_error_email('ERRORNEWPAYMENTPAYBOX'); } print ''."\n"; diff --git a/htdocs/public/paypal/newpayment.php b/htdocs/public/paypal/newpayment.php index afd0cb40c1d..2bec850d6c2 100755 --- a/htdocs/public/paypal/newpayment.php +++ b/htdocs/public/paypal/newpayment.php @@ -944,7 +944,7 @@ if ($found && ! $error) // We are in a management option and no error } else { - dol_print_error_email(); + dol_print_error_email('ERRORNEWPAYMENTPAYPAL'); } print ''."\n"; diff --git a/htdocs/societe/admin/societe.php b/htdocs/societe/admin/societe.php index bfff310636f..a96062f5950 100644 --- a/htdocs/societe/admin/societe.php +++ b/htdocs/societe/admin/societe.php @@ -195,6 +195,23 @@ if ($action == 'setprofid') } } +//Activate ProfId +if ($action == 'setprofidmandatory') +{ + $status = GETPOST('status','alpha'); + + $idprof="SOCIETE_IDPROF".$value."_MANDATORY"; + if (dolibarr_set_const($db, $idprof,$status,'chaine',0,'',$conf->entity) > 0) + { + header("Location: ".$_SERVER["PHP_SELF"]); + exit; + } + else + { + dol_print_error($db); + } +} + /* * View @@ -522,6 +539,7 @@ print ''; print ''; print ''; print ''; +print ''; print "\n"; $profid[0][0]=$langs->trans("ProfId1"); @@ -532,6 +550,10 @@ $profid[2][0]=$langs->trans("ProfId3"); $profid[2][1]=$langs->transcountry('ProfId3', $mysoc->country_code); $profid[3][0]=$langs->trans("ProfId4"); $profid[3][1]=$langs->transcountry('ProfId4', $mysoc->country_code); +$profid[4][0]=$langs->trans("ProfId5"); +$profid[4][1]=$langs->transcountry('ProfId5', $mysoc->country_code); +$profid[5][0]=$langs->trans("ProfId6"); +$profid[5][1]=$langs->transcountry('ProfId6', $mysoc->country_code); $var = true; $i=0; @@ -539,42 +561,47 @@ $i=0; $nbofloop=count($profid); while ($i < $nbofloop) { - $var = !$var; - - print ''; - print ''; - - switch($i) + if ($profid[$i][1]!='-') { - case 0: - $verif=(empty($conf->global->SOCIETE_IDPROF1_UNIQUE)?false:true); - break; - case 1: - $verif=(empty($conf->global->SOCIETE_IDPROF2_UNIQUE)?false:true); - break; - case 2: - $verif=(empty($conf->global->SOCIETE_IDPROF3_UNIQUE)?false:true); - break; - case 3: - $verif=(empty($conf->global->SOCIETE_IDPROF4_UNIQUE)?false:true); - break; + $var = !$var; + + print ''; + print ''; + + $idprof_unique ='SOCIETE_IDPROF'.($i+1).'_UNIQUE'; + $idprof_mandatory ='SOCIETE_IDPROF'.($i+1).'_MANDATORY'; + $verif=(empty($conf->global->$idprof_unique)?false:true); + $mandatory=(empty($conf->global->$idprof_mandatory)?false:true); + + if ($verif) + { + print ''; + } + else + { + print ''; + } + + if ($mandatory) + { + print ''; + } + else + { + print ''; + } + print "\n"; } - - if ($verif) - { - print ''; - } - else - { - print ''; - } - print "\n"; $i++; } diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 378cae1f8b0..6a43e5e4396 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1041,9 +1041,22 @@ class Societe extends CommonObject } } - // Remove third party + // Remove extrafields if (! $error) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_extrafields WHERE fk_object = ".$id; + dol_syslog(get_class($this)."::delete sql=".$sql); + if (! $this->db->query($sql)) + { + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR); + } + } + + // Remove third party + if (! $error) + { $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe"; $sql.= " WHERE rowid = " . $id; dol_syslog(get_class($this)."::delete sql=".$sql, LOG_DEBUG); @@ -1051,7 +1064,7 @@ class Societe extends CommonObject { $error++; $this->error = $this->db->lasterror(); - dol_syslog(get_class($this)."::delete erreur -3 ".$this->error, LOG_ERR); + dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR); } } @@ -2570,6 +2583,43 @@ class Societe extends CommonObject $this->idprof6='idprof6'; } + /** + * Check if localtax define for company + * Used to build previews or test instances. + * id must be 0 if object instance is a specimen. + * + * @param localTaxNum $localTaxNum 1 or 2 + * @return boolean true / false + */ + function hasLocalTax($localTaxNum) { + global $user,$langs,$conf; + + // check parameter + if ($localTaxNum != 1 && $localTaxNum != 2) + return false; + + // Search local taxes + $sql = "SELECT t.localtax1, t.localtax2"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_pays as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$this->country_code."'"; + $sql .= " AND t.active = 1"; + if ($localTaxNum == 1) + $sql .= " AND t.localtax1 <> 0"; + elseif ($localTaxNum == 2) + $sql .= " AND t.localtax2 <> 0"; + + dol_syslog("get_localtax sql=".$sql); + $resql=$this->db->query($sql); + if ($resql) + { + return ($this->db->num_rows($resql) > 0); + + } + else + return false; + + } + } ?> diff --git a/htdocs/societe/notify/fiche.php b/htdocs/societe/notify/fiche.php index 73a78eca503..26df6553559 100644 --- a/htdocs/societe/notify/fiche.php +++ b/htdocs/societe/notify/fiche.php @@ -1,7 +1,7 @@ * Copyright (C) 2004-2011 Laurent Destailleur - * Copyright (C) 2010 Juanjo Menent + * Copyright (C) 2010-2012 Juanjo Menent * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -232,7 +232,7 @@ if ($result > 0) foreach($listofnotifiedevents as $notifiedevent) { - $label=$langs->trans("Notify_".$notifiedevent['code'])!=$langs->trans("Notify_".$notifiedevent['code'])?$langs->trans("Notify_".$notifiedevent['code']):$notifiedevent['label']; + $label=($langs->trans("Notify_".$notifiedevent['code'])!="Notify_".$notifiedevent['code']?$langs->trans("Notify_".$notifiedevent['code']):$notifiedevent['label']); $actions[$notifiedevent['rowid']]=$label; } print '\n"; - // Autres caracteristiques issus des autres modules - + // Other attributes + $parameters=array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"'); + $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + if (empty($reshook) && ! empty($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key=>$label) + { + $value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]); + print 'attribute_required[$key])) print ' class="fieldrequired"'; + print '>'.$label.''."\n"; + } + } + // Module Webcalendar // TODO external module if (! empty($conf->webcalendar->enabled)) @@ -888,19 +918,20 @@ else if ($id) { - $fuser = new User($db); - $fuser->fetch($id); - + $object->fetch($id); + if ($res < 0) { dol_print_error($db,$object->error); exit; } + $res=$object->fetch_optionals($object->id,$extralabels); + // Connexion ldap // pour recuperer passDoNotExpire et userChangePassNextLogon - if (! empty($conf->ldap->enabled) && ! empty($fuser->ldap_sid)) + if (! empty($conf->ldap->enabled) && ! empty($object->ldap_sid)) { $ldap = new Ldap(); $result=$ldap->connect_bind(); if ($result > 0) { - $userSearchFilter = '('.$conf->global->LDAP_FILTER_CONNECTION.'('.$ldap->getUserIdentifier().'='.$fuser->login.'))'; - $entries = $ldap->fetch($fuser->login,$userSearchFilter); + $userSearchFilter = '('.$conf->global->LDAP_FILTER_CONNECTION.'('.$ldap->getUserIdentifier().'='.$object->login.'))'; + $entries = $ldap->fetch($object->login,$userSearchFilter); if (! $entries) { $message .= $ldap->error; @@ -937,7 +968,7 @@ else } // Show tabs - $head = user_prepare_head($fuser); + $head = user_prepare_head($object); $title = $langs->trans("User"); dol_fiche_head($head, 'user', $title, 0, 'user'); @@ -947,7 +978,7 @@ else */ if ($action == 'password') { - $ret=$form->form_confirm("fiche.php?id=$fuser->id",$langs->trans("ReinitPassword"),$langs->trans("ConfirmReinitPassword",$fuser->login),"confirm_password", '', 0, 1); + $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("ReinitPassword"),$langs->trans("ConfirmReinitPassword",$object->login),"confirm_password", '', 0, 1); if ($ret == 'html') print '
      '; } @@ -956,7 +987,7 @@ else */ if ($action == 'passwordsend') { - $ret=$form->form_confirm("fiche.php?id=$fuser->id",$langs->trans("SendNewPassword"),$langs->trans("ConfirmSendNewPassword",$fuser->login),"confirm_passwordsend", '', 0, 1); + $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("SendNewPassword"),$langs->trans("ConfirmSendNewPassword",$object->login),"confirm_passwordsend", '', 0, 1); if ($ret == 'html') print '
      '; } @@ -965,7 +996,7 @@ else */ if ($action == 'disable') { - $ret=$form->form_confirm("fiche.php?id=$fuser->id",$langs->trans("DisableAUser"),$langs->trans("ConfirmDisableUser",$fuser->login),"confirm_disable", '', 0, 1); + $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("DisableAUser"),$langs->trans("ConfirmDisableUser",$object->login),"confirm_disable", '', 0, 1); if ($ret == 'html') print '
      '; } @@ -974,7 +1005,7 @@ else */ if ($action == 'enable') { - $ret=$form->form_confirm("fiche.php?id=$fuser->id",$langs->trans("EnableAUser"),$langs->trans("ConfirmEnableUser",$fuser->login),"confirm_enable", '', 0, 1); + $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("EnableAUser"),$langs->trans("ConfirmEnableUser",$object->login),"confirm_enable", '', 0, 1); if ($ret == 'html') print '
      '; } @@ -983,7 +1014,7 @@ else */ if ($action == 'delete') { - $ret=$form->form_confirm("fiche.php?id=$fuser->id",$langs->trans("DeleteAUser"),$langs->trans("ConfirmDeleteUser",$fuser->login),"confirm_delete", '', 0, 1); + $ret=$form->form_confirm("fiche.php?id=$object->id",$langs->trans("DeleteAUser"),$langs->trans("ConfirmDeleteUser",$object->login),"confirm_delete", '', 0, 1); if ($ret == 'html') print '
      '; } @@ -999,52 +1030,54 @@ else // Ref print ''; print ''; print ''."\n"; - $rowspan=14; + $rowspan=15; + if (isset($conf->authmode) && preg_match('/myopenid/',$conf->authmode)) $rowspan++; if (! empty($conf->societe->enabled)) $rowspan++; if (! empty($conf->adherent->enabled)) $rowspan++; if (! empty($conf->webcalendar->enabled)) $rowspan++; // TODO external module if (! empty($conf->phenix->enabled)) $rowspan+=2; // TODO external module + // Lastname print ''; - print ''; + print ''; // Photo print ''; print ''."\n"; // Firstname print ''; - print ''; + print ''; print ''."\n"; // Position/Job print ''; - print ''; + print ''; print ''."\n"; // Login print ''; - if (! empty($fuser->ldap_sid) && $fuser->statut==0) + if (! empty($object->ldap_sid) && $object->statut==0) { print ''; } else { - print ''; + print ''; } print ''."\n"; // Password print ''; - if (! empty($fuser->ldap_sid)) + if (! empty($object->ldap_sid)) { if ($passDoNotExpire) { @@ -1066,10 +1099,10 @@ else else { print '"; @@ -1078,17 +1111,17 @@ else // Administrator print ''."\n"; @@ -1096,13 +1129,13 @@ else if (! empty($conf->multicompany->enabled) && empty($conf->multicompany->transverse_mode) && $conf->entity == 1 && $user->admin && ! $user->entity) { print '\n"; @@ -1110,11 +1143,11 @@ else // Type print ''; - print ''; + print ''; print ''."\n"; // Tel mobile print ''; - print ''; + print ''; print ''."\n"; // Fax print ''; - print ''; + print ''; print ''."\n"; // EMail print ''; - print ''; + print ''; print "\n"; // Signature print '\n"; // Statut print ''; print ''; print ''."\n"; print ''; - print ''; + print ''; print "\n"; print ''; - print ''; + print ''; print "\n"; if (isset($conf->authmode) && preg_match('/myopenid/',$conf->authmode)) { print ''; - print ''; + print ''; print "\n"; } - // Autres caracteristiques issus des autres modules // Module Webcalendar // TODO external module @@ -1179,7 +1211,7 @@ else { $langs->load("other"); print ''; - print ''; + print ''; print ''."\n"; } @@ -1189,10 +1221,10 @@ else { $langs->load("other"); print ''; - print ''; + print ''; print "\n"; print ''; - print ''; + print ''; print ''."\n"; } @@ -1201,23 +1233,23 @@ else { print ''; print ''; print ''."\n"; @@ -1229,10 +1261,10 @@ else $langs->load("members"); print ''; print ''."\n"; } - print "
      "; print dol_print_date($db->jdate($objp->datef))."".price($objp->total_ht)."'.$fac->LibStatut($objp->paye,$objp->statut,5).''.$supplierinvoicestatic->LibStatut($objp->paye,$objp->statut,5).'
      '.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("MustBeUnique").''.$langs->trans("MustBeMandatory").'
      '.$profid[$i][0]."\n"; - print $profid[$i][1]; - print '
      '.$profid[$i][0]."\n"; + print $profid[$i][1]; + print ''; + print img_picto($langs->trans("Activated"),'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"),'switch_off'); + print ''; + print img_picto($langs->trans("Activated"),'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"),'switch_off'); + print '
      '; - print img_picto($langs->trans("Activated"),'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"),'switch_off'); - print '
      '; diff --git a/htdocs/societe/soc.php b/htdocs/societe/soc.php index 48ed418a62d..3ecd0a8c29c 100644 --- a/htdocs/societe/soc.php +++ b/htdocs/societe/soc.php @@ -5,7 +5,7 @@ * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2008 Patrick Raguin - * Copyright (C) 2010-2011 Juanjo Menent + * Copyright (C) 2010-2012 Juanjo Menent * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -202,9 +202,18 @@ if (empty($reshook)) $error++; $errors[] = $langs->trans("ErrorSupplierModuleNotEnabled"); $action = ($action=='add'?'create':'edit'); } + + // We set country_id, country_code and country for the selected country + $object->country_id=GETPOST('country_id')?GETPOST('country_id'):$mysoc->country_id; + if ($object->country_id) + { + $tmparray=getCountry($object->country_id,'all'); + $object->country_code=$tmparray['code']; + $object->country=$tmparray['label']; + } - // Check for duplicate prof id - for ($i = 1; $i < 3; $i++) + // Check for duplicate or mandatory prof id + for ($i = 1; $i < 5; $i++) { $slabel="idprof".$i; $_POST[$slabel]=trim($_POST[$slabel]); @@ -218,8 +227,18 @@ if (empty($reshook)) $action = ($action=='add'?'create':'edit'); } } + + $idprof_mandatory ='SOCIETE_IDPROF'.($i).'_MANDATORY'; + if (! $vallabel && ! empty($conf->global->$idprof_mandatory)) + { + $langs->load("errors"); + $error++; + $errors[] = $langs->trans("ErrorProdIdIsMandatory", $langs->transcountry('ProfId'.$i, $object->country_code)); + $action = ($action=='add'?'create':'edit'); + } } } + if (! $error) { if ($action == 'add') @@ -293,7 +312,7 @@ if (empty($reshook)) // Gestion du logo de la société } else - { + { $error=$object->error; $errors=$object->errors; } @@ -512,6 +531,9 @@ else /* * Creation */ + $private=GETPOST("private","int"); + if (! empty($conf->global->MAIN_THIRPARTY_CREATION_INDIVIDUAL) && ! isset($_GET['private']) && ! isset($_POST['private'])) $private=1; + if (empty($private)) $private=0; // Load object modCodeTiers $module=(! empty($conf->global->SOCIETE_CODECLIENT_ADDON)?$conf->global->SOCIETE_CODECLIENT_ADDON:'mod_codeclient_leopard'); @@ -545,11 +567,10 @@ else if (GETPOST("type")=='c') { $object->client=1; } if (GETPOST("type")=='p') { $object->client=2; } if (! empty($conf->fournisseur->enabled) && (GETPOST("type")=='f' || GETPOST("type")=='')) { $object->fournisseur=1; } - if (GETPOST("private")==1) { $object->particulier=1; } $object->name = GETPOST('nom'); $object->firstname = GETPOST('prenom'); - $object->particulier = GETPOST('private', 'int'); + $object->particulier = $private; $object->prefix_comm = GETPOST('prefix_comm'); $object->client = GETPOST('client')?GETPOST('client'):$object->client; $object->code_client = GETPOST('code_client'); @@ -638,7 +659,7 @@ else print '$(document).ready(function () { id_te_private=8; id_ef15=1; - is_private='.(GETPOST("private")?GETPOST("private"):0).'; + is_private='.$private.'; if (is_private) { $(".individualline").show(); } else { @@ -667,10 +688,10 @@ else print "
      \n"; print $langs->trans("ThirdPartyType").':   '; - print ' '.$langs->trans("Company/Fundation"); print '     '; - print ' '.$langs->trans("Individual"); print ' ('.$langs->trans("ToCreateContactWithSameName").')'; print "
      \n"; @@ -693,7 +714,7 @@ else print ''; // Name, firstname - if ($object->particulier || GETPOST("private")) + if ($object->particulier || $private) { print 'global->SOCIETE_USEPREFIX)?' colspan="3"':'').'>'; if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field @@ -832,7 +853,13 @@ else if ($idprof!='-') { if (($j % 2) == 0) print ''; - print ''; @@ -905,30 +932,26 @@ else print ''; // Local Taxes - // TODO add specific function by country - if($mysoc->country_code=='ES') + if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") { - if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") - { - print ''; + print ''; - } - elseif($mysoc->localtax1_assuj=="1") - { - print ''; - } - elseif($mysoc->localtax2_assuj=="1") - { - print ''; - } + } + elseif($mysoc->localtax1_assuj=="1") + { + print ''; + } + elseif($mysoc->localtax2_assuj=="1") + { + print ''; } if (! empty($conf->global->MAIN_MULTILANGS)) @@ -1119,7 +1142,7 @@ else print '
      '.$langs->trans('LastName').'
      '.$idprof.''; + + $idprof_mandatory ='SOCIETE_IDPROF'.($i).'_MANDATORY'; + if(empty($conf->global->$idprof_mandatory)) + print ''.$idprof.''; + else + print ''.$idprof.''; + $key='idprof'.$i; print $formcompany->get_input_id_prof($i,'idprof'.$i,$object->$key,$object->country_code); print '
      '.$langs->trans('Capital').' '.$langs->trans("Currency".$conf->currency).'
      '.$langs->trans("LocalTax1IsUsedES").''; - print $form->selectyesno('localtax1assuj_value',0,1); - print ''.$langs->trans("LocalTax2IsUsedES").''; - print $form->selectyesno('localtax2assuj_value',0,1); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax1assuj_value',0,1); + print ''.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax2assuj_value',0,1); + print '
      '.$langs->trans("LocalTax1IsUsedES").''; - print $form->selectyesno('localtax1assuj_value',0,1); - print '
      '.$langs->trans("LocalTax2IsUsedES").''; - print $form->selectyesno('localtax2assuj_value',0,1); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax1assuj_value',0,1); + print '
      '.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax2assuj_value',0,1); + print '
      '; // Name - print ''; + print ''; // Prefix if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field @@ -1128,12 +1151,12 @@ else // It does not change the prefix mode using the auto numbering prefix if (($prefixCustomerIsUsed || $prefixSupplierIsUsed) && $object->prefix_comm) { - print ''; + print ''; print $object->prefix_comm; } else { - print ''; + print ''; } print ''; } @@ -1273,7 +1296,13 @@ else if ($idprof!='-') { if (($j % 2) == 0) print ''; - print ''; @@ -1320,31 +1349,27 @@ else print ''; // Local Taxes - // TODO add specific function by country - if($mysoc->country_code=='ES') + if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") { - if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") - { - print ''; + print ''; - } - elseif($mysoc->localtax1_assuj=="1") - { - print ''; + } + elseif($mysoc->localtax1_assuj=="1") + { + print ''; - } - elseif($mysoc->localtax2_assuj=="1") - { - print ''; - } + } + elseif($mysoc->localtax2_assuj=="1") + { + print ''; } // Type - Size @@ -1640,30 +1665,26 @@ else print ''; // Local Taxes - // TODO add specific function by country - if($mysoc->country_code=='ES') + if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") { - if($mysoc->localtax1_assuj=="1" && $mysoc->localtax2_assuj=="1") - { - print ''; + print ''; - } - elseif($mysoc->localtax1_assuj=="1") - { - print ''; - } - elseif($mysoc->localtax2_assuj=="1") - { - print ''; - } + } + elseif($mysoc->localtax1_assuj=="1") + { + print ''; + } + elseif($mysoc->localtax2_assuj=="1") + { + print ''; } // Type + Staff diff --git a/htdocs/theme/auguria/style.css.php b/htdocs/theme/auguria/style.css.php index b981dc6d69b..13c466f7bfc 100644 --- a/htdocs/theme/auguria/style.css.php +++ b/htdocs/theme/auguria/style.css.php @@ -1441,7 +1441,7 @@ font-family: ; .ok { color: #114466; } .warning { color: #887711; } -.error { color: #550000; font-weight: bold; } +.error { color: #550000 !important; font-weight: bold; } td.highlights { background: #f9c5c6; } diff --git a/htdocs/theme/bureau2crea/style.css.php b/htdocs/theme/bureau2crea/style.css.php index e1c8f5a6abf..6bbaddc7f45 100644 --- a/htdocs/theme/bureau2crea/style.css.php +++ b/htdocs/theme/bureau2crea/style.css.php @@ -1595,7 +1595,7 @@ font-family: ; .ok { color: #114466; } .warning { color: #887711; } -.error { color: #550000; font-weight: bold; } +.error { color: #550000 !important; font-weight: bold; } td.highlights { background: #f9c5c6; } diff --git a/htdocs/theme/bureau2crea/tpl/login.tpl.php b/htdocs/theme/bureau2crea/tpl/login.tpl.php index 27a4ea87adf..0d4b34fa555 100644 --- a/htdocs/theme/bureau2crea/tpl/login.tpl.php +++ b/htdocs/theme/bureau2crea/tpl/login.tpl.php @@ -52,9 +52,8 @@ if (isset($conf->modules_parts['css'])) } // JQuery. Must be before other includes $ext='.js'; -if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) $ext='.jgz'; print ''."\n"; -if (constant('JS_JQUERY')) print ''."\n"; +if (constant('JS_JQUERY')) print ''."\n"; else print ''."\n"; print ''."\n"; print ' diff --git a/htdocs/theme/bureau2crea/tpl/passwordforgotten.tpl.php b/htdocs/theme/bureau2crea/tpl/passwordforgotten.tpl.php index becc5fe16f3..6bfc38917e8 100644 --- a/htdocs/theme/bureau2crea/tpl/passwordforgotten.tpl.php +++ b/htdocs/theme/bureau2crea/tpl/passwordforgotten.tpl.php @@ -53,9 +53,8 @@ if (isset($conf->modules_parts['css'])) } // JQuery. Must be before other includes $ext='.js'; -if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) $ext='.jgz'; print ''."\n"; -if (constant('JS_JQUERY')) print ''."\n"; +if (constant('JS_JQUERY')) print ''."\n"; else print ''."\n"; print ''."\n"; if (! empty($conf->global->MAIN_HTML_HEADER)) print $conf->global->MAIN_HTML_HEADER; diff --git a/htdocs/theme/cameleo/style.css.php b/htdocs/theme/cameleo/style.css.php index 085e5227251..70a5bd23ddb 100644 --- a/htdocs/theme/cameleo/style.css.php +++ b/htdocs/theme/cameleo/style.css.php @@ -1511,7 +1511,7 @@ font-family: ; */ .ok { color: #114466; } .warning { color: #887711; } -.error { color: #550000; font-weight: bold; } +.error { color: #550000 !important; font-weight: bold; } div.ok { color: #114466; diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 5f0e563a1cf..3e77e3df23b 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -1762,9 +1762,7 @@ tr.fiche { */ .ok { color: #114466; } .warning { color: #887711; } -.error { color: #550000; font-weight: bold; } - -td.highlights { background: #f9c5c6; } +.error { color: #550000 !important; font-weight: bold; } div.ok { color: #114466; diff --git a/htdocs/user/admin/user_extrafields.php b/htdocs/user/admin/user_extrafields.php new file mode 100644 index 00000000000..dbe4ace030b --- /dev/null +++ b/htdocs/user/admin/user_extrafields.php @@ -0,0 +1,157 @@ + + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2012 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/adherents/admin/adherent_extrafields.php + * \ingroup member + * \brief Page to setup extra fields of members + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + +$langs->load("users"); +$langs->load("admin"); + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label=getStaticMember(get_class($extrafields),'type2label'); +$type2label=array(''); +foreach ($tmptype2label as $key => $val) $type2label[$key]=$langs->trans($val); + +$action=GETPOST('action', 'alpha'); +$attrname=GETPOST('attrname', 'alpha'); +$elementtype='user'; + +if (!$user->admin) accessforbidden(); + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT.'/core/admin_extrafields.inc.php'; + + + +/* + * View + */ + +$textobject=$langs->transnoentitiesnoconv("Users"); + +$help_url='EN:Module_Users|FR:Module_Utilisateurs|ES:Módulo_Usuarios'; +llxHeader('',$langs->trans("UsersSetup"),$help_url); + + +$linkback=''.$langs->trans("BackToModuleList").''; +print_fiche_titre($langs->trans("UsersSetup"),$linkback,'setup'); + + +$head = user_admin_prepare_head(); + +dol_fiche_head($head, 'attributes', $langs->trans("User"), 0, 'user'); + + +print $langs->trans("DefineHereComplementaryAttributes",$textobject).'
      '."\n"; +print '
      '; + +dol_htmloutput_errors($mesg); + +// Load attribute_label +$extrafields->fetch_name_optionals_label($elementtype); + +print "
      '.$langs->trans('ThirdPartyName').'
      '.$langs->trans('ThirdPartyName').'
      '.$idprof.''; + + $idprof_mandatory ='SOCIETE_IDPROF'.($i).'_MANDATORY'; + if(empty($conf->global->$idprof_mandatory)) + print ''.$idprof.''; + else + print ''.$idprof.''; + $key='idprof'.$i; print $formcompany->get_input_id_prof($i,'idprof'.$i,$object->$key,$object->country_code); print '
      '.$langs->trans("LocalTax1IsUsedES").''; - print $form->selectyesno('localtax1assuj_value',$object->localtax1_assuj,1); - print ''.$langs->trans("LocalTax2IsUsedES").''; - print $form->selectyesno('localtax2assuj_value',$object->localtax2_assuj,1); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax1assuj_value',$object->localtax1_assuj,1); + print ''.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax2assuj_value',$object->localtax2_assuj,1); + print '
      '.$langs->trans("LocalTax1IsUsedES").''; - print $form->selectyesno('localtax1assuj_value',$object->localtax1_assuj,1); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax1assuj_value',$object->localtax1_assuj,1); + print '
      '.$langs->trans("LocalTax2IsUsedES").''; - print $form->selectyesno('localtax2assuj_value',$object->localtax2_assuj,1); - print '
      '.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print $form->selectyesno('localtax2assuj_value',$object->localtax2_assuj,1); + print '
      '.$langs->trans("LocalTax1IsUsedES").''; - print yn($object->localtax1_assuj); - print ''.$langs->trans("LocalTax2IsUsedES").''; - print yn($object->localtax2_assuj); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print yn($object->localtax1_assuj); + print ''.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print yn($object->localtax2_assuj); + print '
      '.$langs->trans("LocalTax1IsUsedES").''; - print yn($object->localtax1_assuj); - print '
      '.$langs->trans("LocalTax2IsUsedES").''; - print yn($object->localtax2_assuj); - print '
      '.$langs->trans("LocalTax1IsUsed",$mysoc->country_code).''; + print yn($object->localtax1_assuj); + print '
      '.$langs->trans("LocalTax2IsUsed",$mysoc->country_code).''; + print yn($object->localtax2_assuj); + print '
      "; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print "\n"; + +$var=True; +foreach($extrafields->attribute_type as $key => $value) +{ + $var=!$var; + print ""; + print "\n"; + print "\n"; + print "\n"; + print '\n"; + print '\n"; + print '\n"; + print '\n"; + print ""; + // $i++; +} + +print "
      '.$langs->trans("Label").''.$langs->trans("AttributeCode").''.$langs->trans("Type").''.$langs->trans("Size").''.$langs->trans("Unique").''.$langs->trans("Required").' 
      ".$extrafields->attribute_label[$key]."".$key."".$type2label[$extrafields->attribute_type[$key]]."'.$extrafields->attribute_size[$key]."'.yn($extrafields->attribute_unique[$key])."'.yn($extrafields->attribute_required[$key])."'.img_edit().''; + print "  ".img_delete()."
      "; + +dol_fiche_end(); + + +// Buttons +if ($action != 'create' && $action != 'edit') +{ + print '
      '; + print "".$langs->trans("NewAttribute").""; + print "
      "; +} + + +/* ************************************************************************** */ +/* */ +/* Creation d'un champ optionnel + /* */ +/* ************************************************************************** */ + +if ($action == 'create') +{ + print "
      "; + print_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; +} + +/* ************************************************************************** */ +/* */ +/* Edition d'un champ optionnel */ +/* */ +/* ************************************************************************** */ +if ($action == 'edit' && ! empty($attrname)) +{ + print "
      "; + print_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; +} + +llxFooter(); + +$db->close(); +?> diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 314a8b6d584..8276f4adaca 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -689,33 +689,61 @@ class User extends CommonObject // Supprime droits $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = ".$this->id; - if ($this->db->query($sql)) + if (! $error && ! $this->db->query($sql)) { - + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -1 ".$this->error, LOG_ERR); } // Remove group $sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user WHERE fk_user = ".$this->id; - if ($this->db->query($sql)) + if (! $error && ! $this->db->query($sql)) { - + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -2 ".$this->error, LOG_ERR); } // Si contact, supprime lien if ($this->contact_id) { $sql = "UPDATE ".MAIN_DB_PREFIX."socpeople SET fk_user_creat = null WHERE rowid = ".$this->contact_id; - if ($this->db->query($sql)) + if (! $error && ! $this->db->query($sql)) { - + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR); } } - // Supprime utilisateur - $sql = "DELETE FROM ".MAIN_DB_PREFIX."user WHERE rowid = $this->id"; - $result = $this->db->query($sql); + // Remove extrafields + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_extrafields WHERE fk_object = ".$this->id; + dol_syslog(get_class($this)."::delete sql=".$sql); + if (! $this->db->query($sql)) + { + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR); + } + } - if ($result) + // Remove user + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".$this->id; + dol_syslog(get_class($this)."::delete sql=".$sql); + if (! $this->db->query($sql)) + { + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::delete error -5 ".$this->error, LOG_ERR); + } + } + + if (! $error) { // Appel des triggers include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; @@ -1189,6 +1217,25 @@ class User extends CommonObject } } + // Actions on extra fields (by external module or standard code) + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager=new HookManager($this->db); + $hookmanager->initHooks(array('userdao')); + $parameters=array('socid'=>$this->id); + $reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + if (empty($reshook)) + { + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used + { + $result=$this->insertExtraFields(); + if ($result < 0) + { + $error++; + } + } + } + else if ($reshook < 0) $error++; + if (! $error && ! $notrigger) { // Appel des triggers diff --git a/htdocs/user/fiche.php b/htdocs/user/fiche.php index 3921afa6a6b..820e5c94dd6 100644 --- a/htdocs/user/fiche.php +++ b/htdocs/user/fiche.php @@ -33,6 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; if (! empty($conf->ldap->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/class/ldap.class.php'; if (! empty($conf->adherent->enabled)) require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; if (! empty($conf->multicompany->enabled)) dol_include_once('/multicompany/class/actions_multicompany.class.php'); @@ -85,6 +86,8 @@ $langs->load("companies"); $langs->load("ldap"); $form = new Form($db); +$object = new User($db); +$extrafields = new ExtraFields($db); /** @@ -95,9 +98,8 @@ if ($action == 'confirm_disable' && $confirm == "yes" && $candisableuser) { if ($id <> $user->id) { - $edituser = new User($db); - $edituser->fetch($id); - $edituser->setstatus(0); + $object->fetch($id); + $object->setstatus(0); header("Location: ".$_SERVER['PHP_SELF'].'?id='.$id); exit; } @@ -106,12 +108,11 @@ if ($action == 'confirm_enable' && $confirm == "yes" && $candisableuser) { if ($id <> $user->id) { - $edituser = new User($db); - $edituser->fetch($id); + $object->fetch($id); if (!empty($conf->file->main_limit_users)) { - $nb = $edituser->getNbOfUsers("active"); + $nb = $object->getNbOfUsers("active"); if ($nb >= $conf->file->main_limit_users) { $message='
      '.$langs->trans("YourQuotaOfUsersIsReached").'
      '; @@ -120,7 +121,7 @@ if ($action == 'confirm_enable' && $confirm == "yes" && $candisableuser) if (! $message) { - $edituser->setstatus(1); + $object->setstatus(1); header("Location: ".$_SERVER['PHP_SELF'].'?id='.$id); exit; } @@ -131,9 +132,9 @@ if ($action == 'confirm_delete' && $confirm == "yes" && $candisableuser) { if ($id <> $user->id) { - $edituser = new User($db); - $edituser->id=$id; - $result = $edituser->delete(); + $object = new User($db); + $object->id=$id; + $result = $object->delete(); if ($result < 0) { $langs->load("errors"); @@ -161,11 +162,9 @@ if ($action == 'add' && $canadduser) $action="create"; // Go back to create page } - $edituser = new User($db); - if (! empty($conf->file->main_limit_users)) // If option to limit users is set { - $nb = $edituser->getNbOfUsers("active"); + $nb = $object->getNbOfUsers("active"); if ($nb >= $conf->file->main_limit_users) { $message='
      '.$langs->trans("YourQuotaOfUsersIsReached").'
      '; @@ -175,57 +174,66 @@ if ($action == 'add' && $canadduser) if (! $message) { - $edituser->lastname = $_POST["nom"]; - $edituser->firstname = $_POST["prenom"]; - $edituser->login = $_POST["login"]; - $edituser->admin = $_POST["admin"]; - $edituser->office_phone = $_POST["office_phone"]; - $edituser->office_fax = $_POST["office_fax"]; - $edituser->user_mobile = $_POST["user_mobile"]; - $edituser->email = $_POST["email"]; - $edituser->job = $_POST["job"]; - $edituser->signature = $_POST["signature"]; - $edituser->note = $_POST["note"]; - $edituser->ldap_sid = $_POST["ldap_sid"]; + $object->lastname = $_POST["nom"]; + $object->firstname = $_POST["prenom"]; + $object->login = $_POST["login"]; + $object->admin = $_POST["admin"]; + $object->office_phone = $_POST["office_phone"]; + $object->office_fax = $_POST["office_fax"]; + $object->user_mobile = $_POST["user_mobile"]; + $object->email = $_POST["email"]; + $object->job = $_POST["job"]; + $object->signature = $_POST["signature"]; + $object->note = $_POST["note"]; + $object->ldap_sid = $_POST["ldap_sid"]; + // Get extra fields + foreach($_POST as $key => $value) + { + if (preg_match("/^options_/",$key)) + { + $object->array_options[$key]=GETPOST($key); + } + } + // FIXME external module - $edituser->webcal_login = $_POST["webcal_login"]; - $edituser->phenix_login = $_POST["phenix_login"]; - $edituser->phenix_pass = $_POST["phenix_pass"]; + $object->webcal_login = $_POST["webcal_login"]; + $object->phenix_login = $_POST["phenix_login"]; + $object->phenix_pass = $_POST["phenix_pass"]; // If multicompany is off, admin users must all be on entity 0. if (! empty($conf->multicompany->enabled)) { if (! empty($_POST["superadmin"])) { - $edituser->entity = 0; + $object->entity = 0; } else if ($conf->multicompany->transverse_mode) { - $edituser->entity = 1; // all users in master entity + $object->entity = 1; // all users in master entity } else { - $edituser->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); + $object->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); } } else if (! empty($_POST["admin"])) { - $edituser->entity=0; + $object->entity=0; } else { - $edituser->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); + $object->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); } $db->begin(); - $id = $edituser->create($user); + $id = $object->create($user); if ($id > 0) { if (isset($_POST['password']) && trim($_POST['password'])) { - $edituser->setPassword($user,trim($_POST['password'])); + $object->setPassword($user,trim($_POST['password'])); } $db->commit(); @@ -237,8 +245,8 @@ if ($action == 'add' && $canadduser) { $langs->load("errors"); $db->rollback(); - if (is_array($edituser->errors) && count($edituser->errors)) $message='
      '.join('
      ',$langs->trans($edituser->errors)).'
      '; - else $message='
      '.$langs->trans($edituser->error).'
      '; + if (is_array($object->errors) && count($object->errors)) $message='
      '.join('
      ',$langs->trans($object->errors)).'
      '; + else $message='
      '.$langs->trans($object->error).'
      '; $action="create"; // Go back to create page } @@ -254,10 +262,9 @@ if (($action == 'addgroup' || $action == 'removegroup') && $caneditfield) $editgroup->fetch($group); $editgroup->oldcopy=dol_clone($editgroup); - $edituser = new User($db); - $edituser->fetch($id); - if ($action == 'addgroup') $edituser->SetInGroup($group,($conf->multicompany->transverse_mode?GETPOST("entity"):$editgroup->entity)); - if ($action == 'removegroup') $edituser->RemoveFromGroup($group,($conf->multicompany->transverse_mode?GETPOST("entity"):$editgroup->entity)); + $object->fetch($id); + if ($action == 'addgroup') $object->SetInGroup($group,($conf->multicompany->transverse_mode?GETPOST("entity"):$editgroup->entity)); + if ($action == 'removegroup') $object->RemoveFromGroup($group,($conf->multicompany->transverse_mode?GETPOST("entity"):$editgroup->entity)); if ($result > 0) { @@ -266,7 +273,7 @@ if (($action == 'addgroup' || $action == 'removegroup') && $caneditfield) } else { - $message.=$edituser->error; + $message.=$object->error; } } } @@ -291,83 +298,91 @@ if ($action == 'update' && ! $_POST["cancel"]) if (! $message) { $db->begin(); - $edituser = new User($db); - $edituser->fetch($id); + $object->fetch($id); - $edituser->oldcopy=dol_clone($edituser); + $object->oldcopy=dol_clone($object); - $edituser->lastname = $_POST["nom"]; - $edituser->firstname = $_POST["prenom"]; - $edituser->login = $_POST["login"]; - $edituser->pass = $_POST["password"]; - $edituser->admin = $_POST["admin"]; - $edituser->office_phone = $_POST["office_phone"]; - $edituser->office_fax = $_POST["office_fax"]; - $edituser->user_mobile = $_POST["user_mobile"]; - $edituser->email = $_POST["email"]; - $edituser->job = $_POST["job"]; - $edituser->signature = $_POST["signature"]; - $edituser->openid = $_POST["openid"]; + $object->lastname = $_POST["nom"]; + $object->firstname = $_POST["prenom"]; + $object->login = $_POST["login"]; + $object->pass = $_POST["password"]; + $object->admin = $_POST["admin"]; + $object->office_phone = $_POST["office_phone"]; + $object->office_fax = $_POST["office_fax"]; + $object->user_mobile = $_POST["user_mobile"]; + $object->email = $_POST["email"]; + $object->job = $_POST["job"]; + $object->signature = $_POST["signature"]; + $object->openid = $_POST["openid"]; + // Get extra fields + foreach($_POST as $key => $value) + { + if (preg_match("/^options_/",$key)) + { + $object->array_options[$key]=GETPOST($key); + } + } + // FIXME external module - $edituser->webcal_login = $_POST["webcal_login"]; - $edituser->phenix_login = $_POST["phenix_login"]; - $edituser->phenix_pass = $_POST["phenix_pass"]; + $object->webcal_login = $_POST["webcal_login"]; + $object->phenix_login = $_POST["phenix_login"]; + $object->phenix_pass = $_POST["phenix_pass"]; if (! empty($conf->multicompany->enabled)) { if (! empty($_POST["superadmin"])) { - $edituser->entity = 0; + $object->entity = 0; } else if ($conf->multicompany->transverse_mode) { - $edituser->entity = 1; // all users in master entity + $object->entity = 1; // all users in master entity } else { - $edituser->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); + $object->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); } } else if(! empty($_POST["admin"])) { - $edituser->entity=0; + $object->entity=0; } else { - $edituser->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); + $object->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]); } - if (GETPOST('deletephoto')) $edituser->photo=''; - if (! empty($_FILES['photo']['name'])) $edituser->photo = dol_sanitizeFileName($_FILES['photo']['name']); + if (GETPOST('deletephoto')) $object->photo=''; + if (! empty($_FILES['photo']['name'])) $object->photo = dol_sanitizeFileName($_FILES['photo']['name']); - $ret=$edituser->update($user); + $ret=$object->update($user); if ($ret < 0) { if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - $message.='
      '.$langs->trans("ErrorLoginAlreadyExists",$edituser->login).'
      '; + $message.='
      '.$langs->trans("ErrorLoginAlreadyExists",$object->login).'
      '; } else { - $message.='
      '.$edituser->error.'
      '; + $message.='
      '.$object->error.'
      '; } } - if ($ret >=0 && ! count($edituser->errors)) + if ($ret >=0 && ! count($object->errors)) { - if (GETPOST('deletephoto') && $edituser->photo) + if (GETPOST('deletephoto') && $object->photo) { - $fileimg=$conf->user->dir_output.'/'.get_exdir($edituser->id,2,0,1).'/logos/'.$edituser->photo; - $dirthumbs=$conf->user->dir_output.'/'.get_exdir($edituser->id,2,0,1).'/logos/thumbs'; + $fileimg=$conf->user->dir_output.'/'.get_exdir($object->id,2,0,1).'/logos/'.$object->photo; + $dirthumbs=$conf->user->dir_output.'/'.get_exdir($object->id,2,0,1).'/logos/thumbs'; dol_delete_file($fileimg); dol_delete_dir_recursive($dirthumbs); } if (isset($_FILES['photo']['tmp_name']) && trim($_FILES['photo']['tmp_name'])) { - $dir= $conf->user->dir_output . '/' . get_exdir($edituser->id,2,0,1); + $dir= $conf->user->dir_output . '/' . get_exdir($object->id,2,0,1); dol_mkdir($dir); @@ -394,7 +409,7 @@ if ($action == 'update' && ! $_POST["cancel"]) } } - if ($ret >= 0 && ! count($edituser->errors)) + if ($ret >= 0 && ! count($object->errors)) { $message.='
      '.$langs->trans("UserModified").'
      '; $db->commit(); @@ -407,15 +422,14 @@ if ($action == 'update' && ! $_POST["cancel"]) } else if ($caneditpassword) // Case we can edit only password { - $edituser = new User($db); - $edituser->fetch($id); + $object->fetch($id); - $edituser->oldcopy=dol_clone($edituser); + $object->oldcopy=dol_clone($object); - $ret=$edituser->setPassword($user,$_POST["password"]); + $ret=$object->setPassword($user,$_POST["password"]); if ($ret < 0) { - $message.='
      '.$edituser->error.'
      '; + $message.='
      '.$object->error.'
      '; } } } @@ -424,10 +438,9 @@ if ($action == 'update' && ! $_POST["cancel"]) if ((($action == 'confirm_password' && $confirm == 'yes') || ($action == 'confirm_passwordsend' && $confirm == 'yes')) && $caneditpassword) { - $edituser = new User($db); - $edituser->fetch($id); + $object->fetch($id); - $newpassword=$edituser->setPassword($user,''); + $newpassword=$object->setPassword($user,''); if ($newpassword < 0) { // Echec @@ -438,15 +451,15 @@ if ((($action == 'confirm_password' && $confirm == 'yes') // Succes if ($action == 'confirm_passwordsend' && $confirm == 'yes') { - if ($edituser->send_password($user,$newpassword) > 0) + if ($object->send_password($user,$newpassword) > 0) { - $message = '
      '.$langs->trans("PasswordChangedAndSentTo",$edituser->email).'
      '; + $message = '
      '.$langs->trans("PasswordChangedAndSentTo",$object->email).'
      '; //$message.=$newpassword; } else { $message = '
      '.$langs->trans("PasswordChangedTo",$newpassword).'
      '; - $message.= '
      '.$edituser->error.'
      '; + $message.= '
      '.$object->error.'
      '; } } else @@ -517,6 +530,9 @@ if ($action == 'adduserldap') * View */ +// fetch optionals attributes and labels +$extralabels=$extrafields->fetch_name_optionals_label('user'); + llxHeader('',$langs->trans("UserCard")); $form = new Form($db); @@ -853,8 +869,22 @@ if (($action == 'create') || ($action == 'adduserldap')) $doleditor->Create(); print "
      '; + print $extrafields->showInputField($key,$value); + print '
      '.$langs->trans("Ref").''; - print $form->showrefnav($fuser,'id','',$user->rights->user->user->lire || $user->admin); + print $form->showrefnav($object,'id','',$user->rights->user->user->lire || $user->admin); print '
      '.$langs->trans("Lastname").''.$fuser->nom.''.$object->nom.''; - print $form->showphoto('userphoto',$fuser,100); + print $form->showphoto('userphoto',$object,100); print '
      '.$langs->trans("Firstname").''.$fuser->prenom.''.$object->prenom.'
      '.$langs->trans("PostOrFunction").''.$fuser->job.''.$object->job.'
      '.$langs->trans("Login").''.$langs->trans("LoginAccountDisableInDolibarr").''.$fuser->login.''.$object->login.'
      '.$langs->trans("Password").''; - if ($fuser->pass) print preg_replace('/./i','*',$fuser->pass); + if ($object->pass) print preg_replace('/./i','*',$object->pass); else { - if ($user->admin) print $langs->trans("Crypted").': '.$fuser->pass_indatabase_crypted; + if ($user->admin) print $langs->trans("Crypted").': '.$object->pass_indatabase_crypted; else print $langs->trans("Hidden"); } print "
      '.$langs->trans("Administrator").''; - if (! empty($conf->multicompany->enabled) && $fuser->admin && ! $fuser->entity) + if (! empty($conf->multicompany->enabled) && $object->admin && ! $object->entity) { - print $form->textwithpicto(yn($fuser->admin),$langs->trans("SuperAdministratorDesc"),1,"superadmin"); + print $form->textwithpicto(yn($object->admin),$langs->trans("SuperAdministratorDesc"),1,"superadmin"); } - else if ($fuser->admin) + else if ($object->admin) { - print $form->textwithpicto(yn($fuser->admin),$langs->trans("AdministratorDesc"),1,"admin"); + print $form->textwithpicto(yn($object->admin),$langs->trans("AdministratorDesc"),1,"admin"); } else { - print yn($fuser->admin); + print yn($object->admin); } print '
      '.$langs->trans("Entity").''; - if ($fuser->admin && ! $fuser->entity) + if ($object->admin && ! $object->entity) { print $langs->trans("AllEntities"); } else { - $mc->getInfo($fuser->entity); + $mc->getInfo($object->entity); print $mc->label; } print "
      '.$langs->trans("Type").''; - if ($fuser->societe_id) + if ($object->societe_id) { print $form->textwithpicto($langs->trans("External"),$langs->trans("InternalExternalDesc")); } - else if ($fuser->ldap_sid) + else if ($object->ldap_sid) { print $langs->trans("DomainUser",$ldap->domainFQDN); } @@ -1126,52 +1159,51 @@ else // Tel pro print '
      '.$langs->trans("PhonePro").''.dol_print_phone($fuser->office_phone,'',0,0,1).''.dol_print_phone($object->office_phone,'',0,0,1).'
      '.$langs->trans("PhoneMobile").''.dol_print_phone($fuser->user_mobile,'',0,0,1).''.dol_print_phone($object->user_mobile,'',0,0,1).'
      '.$langs->trans("Fax").''.dol_print_phone($fuser->office_fax,'',0,0,1).''.dol_print_phone($object->office_fax,'',0,0,1).'
      '.$langs->trans("EMail").''.dol_print_email($fuser->email,0,0,1).''.dol_print_email($object->email,0,0,1).'
      '.$langs->trans('Signature').''; - print dol_textishtml($fuser->signature)?$fuser->signature:dol_nl2br($fuser->signature,1,false); + print dol_textishtml($object->signature)?$object->signature:dol_nl2br($object->signature,1,false); print "
      '.$langs->trans("Status").''; - print $fuser->getLibStatut(4); + print $object->getLibStatut(4); print '
      '.$langs->trans("LastConnexion").''.dol_print_date($fuser->datelastlogin,"dayhour").''.dol_print_date($object->datelastlogin,"dayhour").'
      '.$langs->trans("PreviousConnexion").''.dol_print_date($fuser->datepreviouslogin,"dayhour").''.dol_print_date($object->datepreviouslogin,"dayhour").'
      '.$langs->trans("url_openid").''.$fuser->openid.''.$object->openid.'
      '.$langs->trans("LoginWebcal").''.$fuser->webcal_login.' '.$object->webcal_login.' 
      '.$langs->trans("LoginPhenix").''.$fuser->phenix_login.' '.$object->phenix_login.' 
      '.$langs->trans("PassPhenix").''.preg_replace('/./i','*',$fuser->phenix_pass_crypted).' '.preg_replace('/./i','*',$object->phenix_pass_crypted).' 
      '.$langs->trans("LinkToCompanyContact").''; - if (isset($fuser->societe_id) && $fuser->societe_id > 0) + if (isset($object->societe_id) && $object->societe_id > 0) { $societe = new Societe($db); - $societe->fetch($fuser->societe_id); + $societe->fetch($object->societe_id); print $societe->getNomUrl(1,''); } else { print $langs->trans("ThisUserIsNot"); } - if (! empty($fuser->contact_id)) + if (! empty($object->contact_id)) { $contact = new Contact($db); - $contact->fetch($fuser->contact_id); - if ($fuser->societe_id > 0) print ' / '; + $contact->fetch($object->contact_id); + if ($object->societe_id > 0) print ' / '; else print '
      '; - print ''.img_object($langs->trans("ShowContact"),'contact').' '.dol_trunc($contact->getFullName($langs),32).''; + print ''.img_object($langs->trans("ShowContact"),'contact').' '.dol_trunc($contact->getFullName($langs),32).''; } print '
      '.$langs->trans("LinkedToDolibarrMember").''; - if ($fuser->fk_member) + if ($object->fk_member) { $adh=new Adherent($db); - $adh->fetch($fuser->fk_member); + $adh->fetch($object->fk_member); $adh->ref=$adh->getFullname($langs); // Force to show login instead of id print $adh->getNomUrl(1); } @@ -1244,7 +1276,23 @@ else print '
      \n"; + // Other attributes + $parameters=array('colspan' => ' colspan="2"'); + $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + if (empty($reshook) && ! empty($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key=>$label) + { + $value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]); + print 'attribute_required[$key])) print ' class="fieldrequired"'; + print '>'.$label.''; + print $extrafields->showOutputField($key,$value); + print ''."\n"; + } + } + + print "\n"; print "\n"; @@ -1255,7 +1303,7 @@ else print '
      '; - if ($caneditfield && (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + if ($caneditfield && (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { if (! empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) { @@ -1263,57 +1311,57 @@ else } else { - print ''.$langs->trans("Modify").''; + print ''.$langs->trans("Modify").''; } } - elseif ($caneditpassword && ! $fuser->ldap_sid && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + elseif ($caneditpassword && ! $object->ldap_sid && + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - print ''.$langs->trans("EditPassword").''; + print ''.$langs->trans("EditPassword").''; } // Si on a un gestionnaire de generation de mot de passe actif if ($conf->global->USER_PASSWORD_GENERATED != 'none') { - if ($fuser->statut == 0) + if ($object->statut == 0) { print ''.$langs->trans("ReinitPassword").''; } - elseif (($user->id != $id && $caneditpassword) && $fuser->login && !$fuser->ldap_sid && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + elseif (($user->id != $id && $caneditpassword) && $object->login && !$object->ldap_sid && + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - print ''.$langs->trans("ReinitPassword").''; + print ''.$langs->trans("ReinitPassword").''; } - if ($fuser->statut == 0) + if ($object->statut == 0) { print ''.$langs->trans("SendNewPassword").''; } - else if (($user->id != $id && $caneditpassword) && $fuser->login && !$fuser->ldap_sid && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + else if (($user->id != $id && $caneditpassword) && $object->login && !$object->ldap_sid && + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - if ($fuser->email) print ''.$langs->trans("SendNewPassword").''; + if ($object->email) print ''.$langs->trans("SendNewPassword").''; else print ''.$langs->trans("SendNewPassword").''; } } // Activer - if ($user->id <> $id && $candisableuser && $fuser->statut == 0 && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + if ($user->id <> $id && $candisableuser && $object->statut == 0 && + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - print ''.$langs->trans("Reactivate").''; + print ''.$langs->trans("Reactivate").''; } // Desactiver - if ($user->id <> $id && $candisableuser && $fuser->statut == 1 && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + if ($user->id <> $id && $candisableuser && $object->statut == 1 && + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - print ''.$langs->trans("DisableUser").''; + print ''.$langs->trans("DisableUser").''; } // Delete if ($user->id <> $id && $candisableuser && - (empty($conf->multicompany->enabled) || ! $user->entity || ($fuser->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) + (empty($conf->multicompany->enabled) || ! $user->entity || ($object->entity == $conf->entity) || ($conf->multicompany->transverse_mode && $conf->entity == 1))) { - print ''.$langs->trans("DeleteUser").''; + print ''.$langs->trans("DeleteUser").''; } print "
      \n"; @@ -1333,7 +1381,7 @@ else $exclude = array(); $usergroup=new UserGroup($db); - $groupslist = $usergroup->listGroupsForUser($fuser->id); + $groupslist = $usergroup->listGroupsForUser($object->id); if (! empty($groupslist)) { @@ -1355,7 +1403,7 @@ else print ''."\n"; print ''."\n"; print '
      '.$langs->trans("GroupsToAdd").''; - print $form->select_dolgroups('', 'group', 1, $exclude, 0, '', '', $fuser->entity); + print $form->select_dolgroups('', 'group', 1, $exclude, 0, '', '', $object->entity); print '   '; // Multicompany if (! empty($conf->multicompany->enabled)) @@ -1422,7 +1470,7 @@ else { $mc->getInfo($group_entity); print ($nb > 0 ? ', ' : '').$mc->label; - print ''; + print ''; print img_delete($langs->trans("RemoveFromGroup")); print ''; $nb++; @@ -1432,7 +1480,7 @@ else print ''; if ($caneditgroup && empty($conf->multicompany->transverse_mode)) { - print ''; + print ''; print img_delete($langs->trans("RemoveFromGroup")); print ''; } @@ -1457,15 +1505,15 @@ else * Fiche en mode edition */ - if ($action == 'edit' && ($canedituser || ($user->id == $fuser->id))) + if ($action == 'edit' && ($canedituser || ($user->id == $object->id))) { - print '
      '; + print ''; print ''; print ''; print ''; print ''; - $rowspan=12; + $rowspan=13; if (! empty($conf->societe->enabled)) $rowspan++; if (! empty($conf->adherent->enabled)) $rowspan++; @@ -1474,7 +1522,7 @@ else print ''; print ''; print ''; @@ -1482,24 +1530,24 @@ else print ""; print ''; print ''; // Photo print '".''; print ''; // Position/Job print ''; print ''; // Login print "".''; print ''; print ''; @@ -1546,13 +1594,13 @@ else // Pass print ''; print '\n"; // Administrator print ''; - if ($fuser->societe_id > 0) + if ($object->societe_id > 0) { print ''; } @@ -1579,11 +1627,11 @@ else print ''; @@ -1647,7 +1695,7 @@ else if (empty($conf->multicompany->transverse_mode) && $conf->entity == 1 && $user->admin && ! $user->entity) { print "".''; - print "\n"; } else @@ -1660,11 +1708,11 @@ else // Type print ''; print '".''; print ''; // Tel mobile print "".''; print ''; // Fax print "".''; print ''; // EMail print "".''; print ''; // Signature print "".''; print ''; // openid @@ -1742,14 +1790,14 @@ else { print "".''; print ''; } @@ -1757,11 +1805,9 @@ else // Statut print ''; print ''; - // Autres caracteristiques issus des autres modules - // Module Webcalendar // TODO external module if (! empty($conf->webcalendar->enabled)) @@ -1769,8 +1815,8 @@ else $langs->load("other"); print "".''; print ''; } @@ -1781,13 +1827,13 @@ else $langs->load("other"); print "".''; print ''; print "".''; print ''; } @@ -1796,16 +1842,16 @@ else { print ''; print ''; print '\n"; } + // Other attributes + $parameters=array('colspan' => ' colspan="2"'); + $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + if (empty($reshook) && ! empty($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key=>$label) + { + $value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]); + print 'attribute_required[$key])) print ' class="fieldrequired"'; + print '>'.$label.''."\n"; + } + } + print '
      '.$langs->trans("Ref").''; - print $fuser->id; + print $object->id; print '
      '.$langs->trans("Lastname").''; - if ($caneditfield && !$fuser->ldap_sid) + if ($caneditfield && !$object->ldap_sid) { - print ''; + print ''; } else { - print ''; - print $fuser->nom; + print ''; + print $object->nom; } print ''; - print $form->showphoto('userphoto',$fuser); + print $form->showphoto('userphoto',$object); if ($caneditfield) { - if ($fuser->photo) print "
      \n"; + if ($object->photo) print "
      \n"; print ''; - if ($fuser->photo) print ''; + if ($object->photo) print ''; print ''; print ''; print '
      '.$langs->trans("Delete").'

      '.$langs->trans("Delete").'

      '.$langs->trans("PhotoFile").'
      '; @@ -1511,34 +1559,34 @@ else // Firstname print "
      '.$langs->trans("Firstname").''; - if ($caneditfield && !$fuser->ldap_sid) + if ($caneditfield && !$object->ldap_sid) { - print ''; + print ''; } else { - print ''; - print $fuser->prenom; + print ''; + print $object->prenom; } print '
      '.$langs->trans("PostOrFunction").''; - print ''; + print ''; print '
      '.$langs->trans("Login").''; - if ($user->admin && !$fuser->ldap_sid) + if ($user->admin && !$object->ldap_sid) { - print ''; + print ''; } else { - print ''; - print $fuser->login; + print ''; + print $object->login; } print '
      '.$langs->trans("Password").''; - if ($fuser->ldap_sid) + if ($object->ldap_sid) { $text=$langs->trans("DomainPassword"); } else if ($caneditpassword) { - $text=''; + $text=''; if ($dolibarr_main_authentication && $dolibarr_main_authentication == 'http') { $text=$form->textwithpicto($text,$langs->trans("DolibarrInHttpAuthenticationSoPasswordUseless",$dolibarr_main_authentication),1,'warning'); @@ -1560,17 +1608,17 @@ else } else { - $text=preg_replace('/./i','*',$fuser->pass); + $text=preg_replace('/./i','*',$object->pass); } print $text; print "
      '.$langs->trans("Administrator").''; - print ''.yn($fuser->admin); + print ''.yn($object->admin); print ' ('.$langs->trans("ExternalUser").')'; print '
      '; $nbSuperAdmin = $user->getNbOfUsers('superadmin'); if ($user->admin - && ($user->id != $fuser->id) // Don't downgrade ourself - && ($fuser->entity > 0 || $nbSuperAdmin > 1) // Don't downgrade a superadmin if alone + && ($user->id != $object->id) // Don't downgrade ourself + && ($object->entity > 0 || $nbSuperAdmin > 1) // Don't downgrade a superadmin if alone ) { - print $form->selectyesno('admin',$fuser->admin,1); + print $form->selectyesno('admin',$object->admin,1); if (! empty($conf->multicompany->enabled) && ! $user->entity && empty($conf->multicompany->transverse_mode)) { @@ -1626,16 +1674,16 @@ else '; } - $checked=(($fuser->admin && ! $fuser->entity) ? ' checked' : ''); + $checked=(($object->admin && ! $object->entity) ? ' checked' : ''); print ' '.$langs->trans("SuperAdministrator"); } } else { - $yn = yn($fuser->admin); - print ''; - print ''; - if (! empty($conf->multicompany->enabled) && empty($fuser->entity)) print $form->textwithpicto($yn,$langs->trans("DontDowngradeSuperAdmin"),1,'warning'); + $yn = yn($object->admin); + print ''; + print ''; + if (! empty($conf->multicompany->enabled) && empty($object->entity)) print $form->textwithpicto($yn,$langs->trans("DontDowngradeSuperAdmin"),1,'warning'); else print $yn; } print '
      '.$langs->trans("Entity").'".$mc->select_entities($fuser->entity); + print "".$mc->select_entities($object->entity); print "
      '.$langs->trans("Type").''; - if ($fuser->societe_id) + if ($object->societe_id) { print $langs->trans("External"); } - else if ($fuser->ldap_sid) + else if ($object->ldap_sid) { print $langs->trans("DomainUser"); } @@ -1678,63 +1726,63 @@ else // Tel pro print "
      '.$langs->trans("PhonePro").''; - if ($caneditfield && empty($fuser->ldap_sid)) + if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { - print ''; - print $fuser->office_phone; + print ''; + print $object->office_phone; } print '
      '.$langs->trans("PhoneMobile").''; - if ($caneditfield && empty($fuser->ldap_sid)) + if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { - print ''; - print $fuser->user_mobile; + print ''; + print $object->user_mobile; } print '
      '.$langs->trans("Fax").''; - if ($caneditfield && empty($fuser->ldap_sid)) + if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { - print ''; - print $fuser->office_fax; + print ''; + print $object->office_fax; } print '
      global->USER_MAIL_REQUIRED)?' class="fieldrequired"':'').'>'.$langs->trans("EMail").''; - if ($caneditfield && empty($fuser->ldap_sid)) + if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { - print ''; - print $fuser->email; + print ''; + print $object->email; } print '
      '.$langs->trans("Signature").''; - print ''; + print ''; print '
      '.$langs->trans("url_openid").''; - if ($caneditfield && !$fuser->ldap_sid) + if ($caneditfield && !$object->ldap_sid) { - print ''; + print ''; } else { - print ''; - print $fuser->openid; + print ''; + print $object->openid; } print '
      '.$langs->trans("Status").''; - print $fuser->getLibStatut(4); + print $object->getLibStatut(4); print '
      '.$langs->trans("LoginWebcal").''; - if ($caneditfield) print ''; - else print $fuser->webcal_login; + if ($caneditfield) print ''; + else print $object->webcal_login; print '
      '.$langs->trans("LoginPhenix").''; - if ($caneditfield) print ''; - else print $fuser->phenix_login; + if ($caneditfield) print ''; + else print $object->phenix_login; print '
      '.$langs->trans("PassPhenix").''; - if ($caneditfield) print ''; - else print preg_replace('/./i','*',$fuser->phenix_pass_crypted); + if ($caneditfield) print ''; + else print preg_replace('/./i','*',$object->phenix_pass_crypted); print '
      '.$langs->trans("LinkToCompanyContact").''; - if ($fuser->societe_id > 0) + if ($object->societe_id > 0) { $societe = new Societe($db); - $societe->fetch($fuser->societe_id); + $societe->fetch($object->societe_id); print $societe->getNomUrl(1,''); - if ($fuser->contact_id) + if ($object->contact_id) { $contact = new Contact($db); - $contact->fetch($fuser->contact_id); - print ' / '.img_object($langs->trans("ShowContact"),'contact').' '.dol_trunc($contact->getFullName($langs),32).''; + $contact->fetch($object->contact_id); + print ' / '.img_object($langs->trans("ShowContact"),'contact').' '.dol_trunc($contact->getFullName($langs),32).''; } } else @@ -1822,10 +1868,10 @@ else $langs->load("members"); print '
      '.$langs->trans("LinkedToDolibarrMember").''; - if ($fuser->fk_member) + if ($object->fk_member) { $adh=new Adherent($db); - $adh->fetch($fuser->fk_member); + $adh->fetch($object->fk_member); $adh->ref=$adh->login; // Force to show login instead of id print $adh->getNomUrl(1); } @@ -1837,6 +1883,22 @@ else print "
      '; + print $extrafields->showInputField($key,$value); + print '
      '; print '
      '; @@ -1850,7 +1912,7 @@ else print ''; } - if (! empty($conf->ldap->enabled) && ! empty($fuser->ldap_sid)) $ldap->close; + if (! empty($conf->ldap->enabled) && ! empty($object->ldap_sid)) $ldap->close; } } diff --git a/htdocs/webservices/server_category.php b/htdocs/webservices/server_category.php index b08aa90d763..713fcd70fe4 100755 --- a/htdocs/webservices/server_category.php +++ b/htdocs/webservices/server_category.php @@ -1,7 +1,7 @@ * Copyright (C) 2012 JF FERRY - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -67,7 +67,7 @@ $server->wsdl->addComplexType( 'entity' => array('name'=>'entity','type'=>'xsd:string'), ) ); - + /* * Une catégorie */ @@ -90,7 +90,7 @@ $server->wsdl->addComplexType( 'filles' => array('name'=>'filles','type'=>'tns:FillesArray') ) ); - + /* * Les catégories filles, sous tableau dez la catégorie */ @@ -123,12 +123,12 @@ $server->wsdl->addComplexType( 'tns:categories' ); */ - + /* * Les photos de la catégorie (un tableau indéxé qui contient les images avec leur vignette) */ - $server->wsdl->addComplexType( - 'PhotosArray', +$server->wsdl->addComplexType( + 'PhotosArray', 'complexType', 'array', '', @@ -137,7 +137,7 @@ $server->wsdl->addComplexType( array( array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:image[]') ), -'' + '' ); /* @@ -235,7 +235,7 @@ function getCategory($authentication,$id) $dir = (!empty($conf->categorie->dir_output)?$conf->categorie->dir_output:$conf->service->dir_output); $pdir = get_exdir($categorie->id,2) . $categorie->id ."/photos/"; $dir = $dir . '/'. $pdir; - + $cat = array( 'id' => $categorie->id, 'id_mere' => $categorie->id_mere, @@ -247,11 +247,10 @@ function getCategory($authentication,$id) 'dir' => $pdir, 'photos' => $categorie->liste_photos($dir,$nbmax=10) ); - + $cats = $categorie->get_filles(); - if (sizeof ($cats) > 0) + if (count($cats) > 0) { - foreach($cats as $fille) { $dir = (!empty($conf->categorie->dir_output)?$conf->categorie->dir_output:$conf->service->dir_output); @@ -268,11 +267,11 @@ function getCategory($authentication,$id) 'dir' => $pdir, 'photos' => $fille->liste_photos($dir,$nbmax=10) ); - + } - + } - + // Create $objectresp = array( 'result'=>array('result_code'=>'OK', 'result_label'=>''), diff --git a/htdocs/webservices/server_productorservice.php b/htdocs/webservices/server_productorservice.php index b256621fb79..cb6e033e85a 100755 --- a/htdocs/webservices/server_productorservice.php +++ b/htdocs/webservices/server_productorservice.php @@ -116,7 +116,7 @@ $server->wsdl->addComplexType( 'price_ttc' => array('name'=>'price_ttc','type'=>'xsd:string'), 'price_min' => array('name'=>'price_min','type'=>'xsd:string'), 'price_min_ttc' => array('name'=>'price_min_ttc','type'=>'xsd:string'), - + 'price_base_type' => array('name'=>'price_base_type','type'=>'xsd:string'), 'vat_rate' => array('name'=>'vat_rate','type'=>'xsd:string'), @@ -622,68 +622,64 @@ function getProductsForCategory($authentication,$id) $res = $db->query($sql); if ($res) { - - while ($rec = $db->fetch_array ($res)) + while ($rec = $db->fetch_array($res)) { - $obj = new Product ($db); - $obj->fetch ($rec['fk_'.$field]); - if($obj->status > 0 ) { - + $obj = new Product($db); + $obj->fetch($rec['fk_'.$field]); + if($obj->status > 0 ) + { $dir = (!empty($conf->product->dir_output)?$conf->product->dir_output:$conf->service->dir_output); $pdir = get_exdir($obj->id,2) . $obj->id ."/photos/"; $dir = $dir . '/'. $pdir; - + $products[] = array( - - 'id' => $obj->id, - 'ref' => $obj->ref, - 'ref_ext' => $obj->ref_ext, - 'label' => $obj->label, - 'description' => $obj->description, - 'date_creation' => dol_print_date($obj->date_creation,'dayhourrfc'), - 'date_modification' => dol_print_date($obj->date_modification,'dayhourrfc'), - 'note' => $obj->note, - 'status_tosell' => $obj->status, - 'status_tobuy' => $obj->status_buy, - 'type' => $obj->type, - 'barcode' => $obj->barcode, - 'barcode_type' => $obj->barcode_type, - 'country_id' => $obj->country_id>0?$obj->country_id:'', - 'country_code' => $obj->country_code, - 'custom_code' => $obj->customcode, + 'id' => $obj->id, + 'ref' => $obj->ref, + 'ref_ext' => $obj->ref_ext, + 'label' => $obj->label, + 'description' => $obj->description, + 'date_creation' => dol_print_date($obj->date_creation,'dayhourrfc'), + 'date_modification' => dol_print_date($obj->date_modification,'dayhourrfc'), + 'note' => $obj->note, + 'status_tosell' => $obj->status, + 'status_tobuy' => $obj->status_buy, + 'type' => $obj->type, + 'barcode' => $obj->barcode, + 'barcode_type' => $obj->barcode_type, + 'country_id' => $obj->country_id>0?$obj->country_id:'', + 'country_code' => $obj->country_code, + 'custom_code' => $obj->customcode, - 'price_net' => $obj->price, - 'price' => ($obj->price_ttc-$obj->price), - 'vat_rate' => $obj->tva_tx, - 'price_ttc' => $obj->price_ttc, - 'price_base_type' => $obj->price_base_type, + 'price_net' => $obj->price, + 'price' => ($obj->price_ttc-$obj->price), + 'vat_rate' => $obj->tva_tx, + 'price_ttc' => $obj->price_ttc, + 'price_base_type' => $obj->price_base_type, - 'stock_real' => $obj->stock_reel, - 'stock_alert' => $obj->seuil_stock_alerte, - 'pmp' => $obj->pmp, - 'import_key' => $obj->import_key, - 'dir' => $pdir, - 'photos' => $obj->liste_photos($dir,$nbmax=10) - - + 'stock_real' => $obj->stock_reel, + 'stock_alert' => $obj->seuil_stock_alerte, + 'pmp' => $obj->pmp, + 'import_key' => $obj->import_key, + 'dir' => $pdir, + 'photos' => $obj->liste_photos($dir,$nbmax=10) ); } } - + // Retour $objectresp = array( 'result'=>array('result_code'=>'OK', 'result_label'=>''), 'products'=> $products ); - + } else { $errorcode='NORECORDS_FOR_ASSOCIATION'; $errorlabel='No products associated'.$sql; $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel)); dol_syslog("getProductsForCategory:: ".$c->error, LOG_DEBUG); - + } } else diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000000..ee23dd24607 --- /dev/null +++ b/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Disallow: /build +Disallow: /dev +Disallow: /doc +Disallow: /scripts +Disallow: /test \ No newline at end of file diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 2b254a5fc99..0d81438bd3c 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -109,8 +109,10 @@ class AllTests require_once dirname(__FILE__).'/CommandeTest.php'; $suite->addTestSuite('CommandeTest'); - require_once dirname(__FILE__).'/CommandeFournisseurTest.php'; + + require_once dirname(__FILE__).'/CommandeFournisseurTest.php'; $suite->addTestSuite('CommandeFournisseurTest'); + require_once dirname(__FILE__).'/ContratTest.php'; $suite->addTestSuite('ContratTest'); require_once dirname(__FILE__).'/FactureTest.php'; diff --git a/test/phpunit/CommandeFournisseurTest.php b/test/phpunit/CommandeFournisseurTest.php index d73e8661c8c..5e948a64757 100644 --- a/test/phpunit/CommandeFournisseurTest.php +++ b/test/phpunit/CommandeFournisseurTest.php @@ -27,7 +27,8 @@ global $conf,$user,$langs,$db; //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver require_once 'PHPUnit/Autoload.php'; require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; -require_once dirname(__FILE__).'/../../htdocs/fourn/class/fournisseur.commande.class.php'; +require_once dirname(__FILE__).'/../../htdocs/fourn/class/fournisseur.commande.class.php'; +require_once dirname(__FILE__).'/../../htdocs/fourn/class/fournisseur.product.class.php'; if (empty($user->id)) { @@ -128,15 +129,61 @@ class CommandeFournisseurTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; - $localobject=new CommandeFournisseur($this->savdb); - $localobject->initAsSpecimen(); - $result=$localobject->create($user); + // Set supplier and product to use + $socid=1; + $prodid=1; + $societe=new Societe($db); + $societe->fetch($socid); + $product=new ProductFournisseur($db); + $product->fetch($prodid); + $quantity=10; + $ref_fourn='SUPPLIER_REF_PHPUNIT'; + $tva_tx=19.6; + + // Create supplier price + $result=$product->add_fournisseur($user, $societe->id, $ref_fourn, $quantity); // This insert record with no value for price. Values are update later with update_buyprice + $this->assertGreaterThanOrEqual(1, $result); + $result=$product->update_buyprice($quantity, 10, $user, 'HT', $societe, '', $ref_fourn, $tva_tx, 0, 0); + $this->assertGreaterThanOrEqual(0, $result); + + // Create supplier order with a too low quantity + $localobject=new CommandeFournisseur($db); + $localobject->initAsSpecimen(); + $localobject->lines=array(); // Overwrite lines of order + $line=new CommandeFournisseurLigne($db); + $line->desc=$langs->trans("Description")." specimen line too low"; + $line->qty=1; // So lower than $quantity + $line->fk_product=$product->id; + $line->ref_fourn=$ref_fourn; + $localobject->lines[]=$line; + + $result=$localobject->create($user); print __METHOD__." result=".$result."\n"; - $this->assertLessThan($result, 0); - return $result; + $this->assertEquals(-1, $result); // must be -1 because quantity is lower than minimum of supplier price + + $sql="DELETE FROM ".MAIN_DB_PREFIX."commande_fournisseur where ref=''"; + $db->query($sql); + + // Create supplier order + $localobject2=new CommandeFournisseur($db); + $localobject2->initAsSpecimen(); // This create 5 lines of first product found for socid 1 + $localobject2->lines=array(); // Overwrite lines of order + $line=new CommandeFournisseurLigne($db); + $line->desc=$langs->trans("Description")." specimen line ok"; + $line->qty=10; // So enough quantity + $line->fk_product=$product->id; + $line->ref_fourn=$ref_fourn; + $localobject2->lines[]=$line; + + $result=$localobject2->create($user); + print __METHOD__." result=".$result."\n"; + $this->assertGreaterThanOrEqual(0, $result); + + return $result; } + /** * testCommandeFournisseurFetch * diff --git a/test/phpunit/ExportTest.php b/test/phpunit/ExportTest.php index 860e6cc09e6..103869e1850 100755 --- a/test/phpunit/ExportTest.php +++ b/test/phpunit/ExportTest.php @@ -144,21 +144,21 @@ class ExportTest extends PHPUnit_Framework_TestCase $model='csv'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), array(), $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); $model='tsv'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), array(), $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); $model='excel'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), array(), $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); @@ -195,21 +195,21 @@ class ExportTest extends PHPUnit_Framework_TestCase $model='csv'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $array_filtered, $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); $model='tsv'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $array_filtered, $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); $model='excel'; // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $array_filtered, $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); @@ -234,7 +234,7 @@ class ExportTest extends PHPUnit_Framework_TestCase $result=$objexport->load_arrays($user,$datatoexport); // Build export file - $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), array(), $sql); + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql); $expectedresult=1; $this->assertEquals($result,$expectedresult); diff --git a/test/phpunit/HolidayTest.php b/test/phpunit/HolidayTest.php new file mode 100644 index 00000000000..919b1a0162a --- /dev/null +++ b/test/phpunit/HolidayTest.php @@ -0,0 +1,319 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file test/phpunit/HolidayTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/holiday/class/holiday.class.php'; +$langs->load("dict"); + +if (empty($user->id)) +{ + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} + +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class HolidayTest extends PHPUnit_Framework_TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return HolidayTest + */ + function __construct() + { + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + // Static methods + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + } + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + /** + * testHolidayCreate + * + * @return int + */ + public function testHolidayCreate() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new Holiday($this->savdb); + $localobject->initAsSpecimen(); + $result=$localobject->create($user); + + print __METHOD__." result=".$result."\n"; + $this->assertLessThan($result, 0); + + return $result; + } + + /** + * testHolidayFetch + * + * @param int $id Id of Holiday + * @return int + * @depends testHolidayCreate + * The depends says test is run only if previous is ok + */ + public function testHolidayFetch($id) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new Holiday($this->savdb); + $result=$localobject->fetch($id); + + print __METHOD__." id=".$id." result=".$result."\n"; + $this->assertLessThan($result, 0); + + return $localobject; + } + + /** + * testHolidayUpdate + * + * @param Holiday $localobject Holiday + * @return int + * + * @depends testHolidayFetch + * The depends says test is run only if previous is ok + */ + public function testHolidayUpdate($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject->oldcopy=dol_clone($localobject); + + $localobject->note='New note after update'; + //$localobject->note_public='New note public after update'; + $localobject->lastname='New name'; + $localobject->firstname='New firstname'; + $localobject->address='New address'; + $localobject->zip='New zip'; + $localobject->town='New town'; + $localobject->country_id=2; + //$localobject->status=0; + $localobject->phone_pro='New tel pro'; + $localobject->phone_perso='New tel perso'; + $localobject->phone_mobile='New tel mobile'; + $localobject->fax='New fax'; + $localobject->email='newemail@newemail.com'; + $localobject->jabberid='New im id'; + $localobject->default_lang='es_ES'; + $result=$localobject->update($localobject->id,$user); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0, 'Holiday::update error'); + $result=$localobject->update_note($localobject->note); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0, 'Holiday::update_note error'); + //$result=$localobject->update_note_public($localobject->note_public); + //print __METHOD__." id=".$localobject->id." result=".$result."\n"; + //$this->assertLessThan($result, 0); + + $newobject=new Holiday($this->savdb); + $result=$newobject->fetch($localobject->id); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0, 'Holiday::fetch error'); + + print __METHOD__." old=".$localobject->note." new=".$newobject->note."\n"; + $this->assertEquals($localobject->note, $newobject->note); + //print __METHOD__." old=".$localobject->note_public." new=".$newobject->note_public."\n"; + //$this->assertEquals($localobject->note_public, $newobject->note_public); + print __METHOD__." old=".$localobject->lastname." new=".$newobject->lastname."\n"; + $this->assertEquals($localobject->lastname, $newobject->lastname); + print __METHOD__." old=".$localobject->firstname." new=".$newobject->firstname."\n"; + $this->assertEquals($localobject->firstname, $newobject->firstname); + print __METHOD__." old=".$localobject->address." new=".$newobject->address."\n"; + $this->assertEquals($localobject->address, $newobject->address); + print __METHOD__." old=".$localobject->zip." new=".$newobject->zip."\n"; + $this->assertEquals($localobject->zip, $newobject->zip); + print __METHOD__." old=".$localobject->town." new=".$newobject->town."\n"; + $this->assertEquals($localobject->town, $newobject->town); + print __METHOD__." old=".$localobject->country_id." new=".$newobject->country_id."\n"; + $this->assertEquals($localobject->country_id, $newobject->country_id); + print __METHOD__." old=BE new=".$newobject->country_code."\n"; + $this->assertEquals('BE', $newobject->country_code); + //print __METHOD__." old=".$localobject->status." new=".$newobject->status."\n"; + //$this->assertEquals($localobject->status, $newobject->status); + print __METHOD__." old=".$localobject->phone_pro." new=".$newobject->phone_pro."\n"; + $this->assertEquals($localobject->phone_pro, $newobject->phone_pro); + print __METHOD__." old=".$localobject->phone_pro." new=".$newobject->phone_pro."\n"; + $this->assertEquals($localobject->phone_perso, $newobject->phone_perso); + print __METHOD__." old=".$localobject->phone_mobile." new=".$newobject->phone_mobile."\n"; + $this->assertEquals($localobject->phone_mobile, $newobject->phone_mobile); + print __METHOD__." old=".$localobject->fax." new=".$newobject->fax."\n"; + $this->assertEquals($localobject->fax, $newobject->fax); + print __METHOD__." old=".$localobject->email." new=".$newobject->email."\n"; + $this->assertEquals($localobject->email, $newobject->email); + print __METHOD__." old=".$localobject->jabberid." new=".$newobject->jabberid."\n"; + $this->assertEquals($localobject->jabberid, $newobject->jabberid); + print __METHOD__." old=".$localobject->default_lang." new=".$newobject->default_lang."\n"; + $this->assertEquals($localobject->default_lang, $newobject->default_lang); + + return $localobject; + } + + /** + * testHolidayOther + * + * @param Holiday $localobject Holiday + * @return void + * + * @depends testHolidayUpdate + * The depends says test is run only if previous is ok + */ + public function testHolidayOther($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + //$localobject->fetch($localobject->id); + + /* + $result=$localobject->getNomUrl(1); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertNotEquals($result, ''); + + $result=$localobject->getFullAddress(1); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertContains("New address\nNew zip New town\nBelgium", $result); + + $localobject->info($localobject->id); + print __METHOD__." localobject->date_creation=".$localobject->date_creation."\n"; + $this->assertNotEquals($localobject->date_creation, ''); + */ + + return $localobject->id; + } + + /** + * testHolidayDelete + * + * @param int $id Id of Holiday + * @return void + * + * @depends testHolidayOther + * The depends says test is run only if previous is ok + */ + public function testHolidayDelete($id) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new Holiday($this->savdb); + $result=$localobject->fetch($id); + + $result=$localobject->delete(0); + print __METHOD__." id=".$id." result=".$result."\n"; + $this->assertLessThan($result, 0); + + return $result; + } + +} +?>