diff --git a/.codeclimate.yml b/.codeclimate.yml index 72d1a0307..fe51f29f1 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,5 +1,6 @@ --- -engines: +version: "2" +plugins: csslint: enabled: false duplication: @@ -36,20 +37,25 @@ engines: config: file_extensions: "php" rulesets: "cleancode,unusedcode,codesize" -ratings: - paths: - - "**.css" - - "**.js" - - "**.php" -exclude_paths: -- e107_admin/core_image.php -- e107_plugins/log/js/awesomechart.js -- e107_docs/**/* -- e107_images/**/* -- e107_handlers/hybridauth/**/* -- e107_handlers/jsshrink/**/* -- e107_handlers/phpmailer/**/* -- e107_handlers/phpthumb/**/* -- e107_handlers/xmlrpc/**/* -- e107_web/**/* - +exclude_patterns: +- "config/" +- "db/" +- "dist/" +- "features/" +- "**/node_modules/" +- "script/" +- "**/spec/" +- "**/test/" +- "**/tests/" +- "**/vendor/" +- "**/*.d.ts" +- "e107_admin/core_image.php" +- "e107_plugins/log/js/awesomechart.js" +- "e107_docs/**/*" +- "e107_images/**/*" +- "e107_handlers/hybridauth/**/*" +- "e107_handlers/jsshrink/**/*" +- "e107_handlers/phpmailer/**/*" +- "e107_handlers/phpthumb/**/*" +- "e107_handlers/xmlrpc/**/*" +- "e107_web/**/*" diff --git a/.gitignore b/.gitignore index b9b73c25d..37bc22dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ e107_core/override # Ignore Vim swap files *.swp *.swo +e107.htaccess +e107InstallLog.log diff --git a/class2.php b/class2.php index f6b227d73..bbe5494b1 100755 --- a/class2.php +++ b/class2.php @@ -1957,6 +1957,9 @@ function init_session() unset($tz); } +e107::getDebug()->log("Timezone: ".USERTIMEZONE); // remove later on. + + define('USERIP', e107::getIPHandler()->getIP(FALSE)); define('POST_REFERER', md5($user->getToken())); diff --git a/comment.php b/comment.php index d38a5b0f9..d17577a5a 100644 --- a/comment.php +++ b/comment.php @@ -140,7 +140,12 @@ if(e_AJAX_REQUEST) // TODO improve security $width = ($pid) ? 1 : 0; $ret['html'] = "\n\n
  • "; - $ret['html'] .= e107::getComment()->render_comment($row,'comments','comment',intval($_POST['itemid']),$width); + + /** + * Fix for issue e107inc/e107#3154 (Comments not refreshing on submission) + * Missing 6th argument ($subject) caused an exception + */ + $ret['html'] .= e107::getComment()->render_comment($row,'comments','comment',intval($_POST['itemid']),$width, $tp->toDB($clean_subject)); $ret['html'] .= "
  • \n\n"; $ret['error'] = false; diff --git a/e107_admin/cpage.php b/e107_admin/cpage.php index 2fc69f912..693777190 100644 --- a/e107_admin/cpage.php +++ b/e107_admin/cpage.php @@ -141,7 +141,7 @@ class page_admin_form_ui extends e_admin_form_ui parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS $query['action'] = 'edit'; $query['id'] = $id; - $query = http_build_query($query); + $query = http_build_query($query,null, '&'); $text = " ".ADMIN_EDIT_ICON.""; diff --git a/e107_admin/footer.php b/e107_admin/footer.php index dacce49e9..1132b3868 100644 --- a/e107_admin/footer.php +++ b/e107_admin/footer.php @@ -367,6 +367,14 @@ echo ""; // SecretR - EXPERIMENT! SEND CSS data to header. Performance tests in progress. $tmp = array(); $e_js = e107::getJs(); + +$tmp0 = $e_js->renderJs('library_css', false, 'css', true); +if($tmp0) +{ + $tmp['search'][] = ''; + $tmp['replace'][] = $tmp0; +} + // Other CSS - from unknown location, different from core/theme/plugin location or backward compatibility $tmp1 = $e_js->renderJs('other_css', false, 'css', true); if($tmp1) diff --git a/e107_admin/header.php b/e107_admin/header.php index dd858f6b2..4b705759e 100644 --- a/e107_admin/header.php +++ b/e107_admin/header.php @@ -165,6 +165,7 @@ echo "".(defined("e_PAGETITLE") ? e_PAGETITLE." - " : (defined("PAGE_NAME echo "<!-- *CSS* -->\n"; $e_js = e107::getJs(); + // Core CSS - XXX awaiting for path changes if (!isset($no_core_css) || !$no_core_css) { @@ -267,9 +268,14 @@ unset($e_headers); // ################### RENDER CSS +echo "\n<!-- Library CSS -->\n"; + +$e_js->renderJs('library_css', false, 'css', false); +echo "\n<!-- footer_library_css -->\n"; // substituted in footer when detected. + // Other CSS - from unknown location, different from core/theme/plugin location or backward compatibility $e_js->renderJs('other_css', false, 'css', false); -echo "\n<!-- footer_other_css -->\n"; +echo "\n<!-- footer_other_css -->\n"; // substituted in footer when detected. // Core CSS $e_js->renderJs('core_css', false, 'css', false); diff --git a/e107_admin/plugin.php b/e107_admin/plugin.php index 6581019ce..38416524d 100755 --- a/e107_admin/plugin.php +++ b/e107_admin/plugin.php @@ -969,7 +969,7 @@ class plugin_form_ui extends e_admin_form_ui if($var['plugin_version'] != $var['plugin_version_file'] && $var['plugin_installflag']) { - $text .= "<a class='btn btn-default' href='" . e_SELF . "?mode=".$mode."&action=upgrade&id={$var['plugin_path']}' title=\"" . EPL_UPGRADE . " v" . $var['plugin_version'] . "\" >" . ADMIN_UPGRADEPLUGIN_ICON . "</a>"; + $text .= "<a class='btn btn-default' href='" . e_SELF . "?mode=".$mode."&action=upgrade&id={$var['plugin_path']}' title=\"" . EPL_UPGRADE . " v" . $var['plugin_version_file'] . "\" >" . ADMIN_UPGRADEPLUGIN_ICON . "</a>"; } if($var['plugin_installflag'] && e_DEBUG == true) @@ -5122,7 +5122,9 @@ $text .= " "; } $text .= " - // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P') + // 'main/div0' => array('divider'=> true), + // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P'), + ); protected \$adminMenuAliases = array( diff --git a/e107_admin/prefs.php b/e107_admin/prefs.php index c7588b68b..dd3cb3d59 100644 --- a/e107_admin/prefs.php +++ b/e107_admin/prefs.php @@ -643,7 +643,7 @@ $text .= " "; // Date options. -$ga = new convert(); +$ga = e107::getDate(); $date1 = $ga->convert_date(time(), "short"); $date2 = $ga->convert_date(time(), "long"); $date3 = $ga->convert_date(time(), "forum"); diff --git a/e107_admin/upload.php b/e107_admin/upload.php index 0b854bfd1..da787ac2e 100644 --- a/e107_admin/upload.php +++ b/e107_admin/upload.php @@ -204,7 +204,15 @@ class upload_ui extends e_admin_ui $this->getModel()->addValidationError(UPLLAN_62); $new_data['upload_active'] = 0; return $new_data; - } + } + + // Make sure the upload_category contains only integers + // Make sure the owner correspondents to the category id + list($catOwner, $catID) = explode("__", $new_data['upload_category'], 2); + $new_data['upload_category'] = intval($catID); + $new_data['upload_owner'] = $catOwner; + + return $new_data; } /** @@ -262,7 +270,8 @@ class upload_ui extends e_admin_ui return 0; } - $owner = varset($upload['upload_owner'], 'download'); + // Make sure the owner is not empty + $owner = vartrue($upload['upload_owner'], 'download'); $uploadObj = e107::getAddon($owner,'e_upload'); @@ -371,7 +380,9 @@ class upload_form_ui extends e_admin_form_ui case 'write': $owner = $this->getController()->getModel()->get('upload_owner'); - return $value."-- ".$owner; // $this->radio_switch('upload_active', $value, LAN_ACCEPT, LAN_PENDING, $options); + //return $value."-- ".$owner; // $this->radio_switch('upload_active', $value, LAN_ACCEPT, LAN_PENDING, $options); + // make category editable instead of just displaying data + return e107::getForm()->select('upload_category', $opts, $value); break; case 'batch': diff --git a/e107_admin/users.php b/e107_admin/users.php index dcd17bdff..aa02fc828 100644 --- a/e107_admin/users.php +++ b/e107_admin/users.php @@ -60,7 +60,7 @@ class users_admin extends e_admin_dispatcher 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0|4'), 'main/add' => array('caption'=> LAN_USER_QUICKADD, 'perm' => '4|U0|U1'), 'main/prefs' => array('caption'=> LAN_OPTIONS, 'perm' => '4|U2'), - 'main/ranks' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), + 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), 'main/maintenance' => array('caption'=> LAN_MAINTENANCE, 'perms'=>'4') // 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3') ); @@ -86,11 +86,6 @@ class users_admin extends e_admin_dispatcher function init() { - if(E107_DEBUG_LEVEL > 0) - { - $this->adminMenu['ranks/list'] = array('caption'=> LAN_USER_RANKS. " (experimental)", 'perm' => '4|U3'); - } - $JS = <<<JS @@ -470,7 +465,7 @@ class users_admin_ui extends e_admin_ui } - public function afterDelete($deletedData,$id=null) + public function afterDelete($deletedData, $id=null, $deleted_check) { if(!empty($id)) { @@ -2860,10 +2855,10 @@ class users_admin_form_ui extends e_admin_form_ui } unset($tmp); - natsort($imageList); + // natsort($imageList); } - public function afterDelete($data) + public function afterDelete($data, $id, $deleted_check) { e107::getCache()->clear_sys('nomd5_user_ranks'); } @@ -2938,7 +2933,7 @@ class users_admin_form_ui extends e_admin_form_ui parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS $query['action'] = 'edit'; $query['id'] = $id; - $query = http_build_query($query); + $query = http_build_query($query, null, '&'); $text = "<a href='".e_SELF."?{$query}' class='btn btn-default' title='".LAN_EDIT."' data-toggle='tooltip' data-placement='left'> ".ADMIN_EDIT_ICON."</a>"; diff --git a/e107_core/shortcodes/batch/admin_shortcodes.php b/e107_core/shortcodes/batch/admin_shortcodes.php index ead1b419a..878e5bfa5 100644 --- a/e107_core/shortcodes/batch/admin_shortcodes.php +++ b/e107_core/shortcodes/batch/admin_shortcodes.php @@ -2276,7 +2276,7 @@ Inverse 10 <span class="badge badge-inverse">10</span> $get = $_GET; $get['elan'] = $code; - $qry = http_build_query($get); + $qry = http_build_query($get, null, '&'); $link = e_REQUEST_SELF.'?'.$qry; } diff --git a/e107_core/shortcodes/batch/news_shortcodes.php b/e107_core/shortcodes/batch/news_shortcodes.php index 8685222f2..b157d1812 100644 --- a/e107_core/shortcodes/batch/news_shortcodes.php +++ b/e107_core/shortcodes/batch/news_shortcodes.php @@ -1116,7 +1116,7 @@ class news_shortcodes extends e_shortcode { $news_item = $this->news_item; $param = $this->param; - $con = new convert; + $con = e107::getDate(); $news_item['news_start'] = (isset($news_item['news_start']) && $news_item['news_start'] ? str_replace(' - 00:00:00', '', $con->convert_date($news_item['news_start'], 'long')) : LAN_NEWS_19); $news_item['news_end'] = (isset($news_item['news_end']) && $news_item['news_end'] ? ' to '.str_replace(' - 00:00:00', '', $con->convert_date($news_item['news_end'], 'long')) : ''); $info = $news_item['news_render_type'] == 1 ? LAN_NEWS_9 : ''; diff --git a/e107_core/shortcodes/batch/usersettings_shortcodes.php b/e107_core/shortcodes/batch/usersettings_shortcodes.php index 29f36637a..b9994fee0 100755 --- a/e107_core/shortcodes/batch/usersettings_shortcodes.php +++ b/e107_core/shortcodes/batch/usersettings_shortcodes.php @@ -554,5 +554,22 @@ class usersettings_shortcodes extends e_shortcode } + function sc_deleteaccountbutton($parm=array()) + { + + if((int) $_GET['id'] !== USERID) + { + return null; + } + + $confirm = defset("LAN_USET_51", "Are you sure? This procedure cannot be reversed! Once completed all personal data that you have entered on this site will be permanently lost and you will no longer be able to login."); + $label = defset('LAN_USET_50', "Delete All Account Information"); + + $parm['confirm'] = $confirm; + + return e107::getForm()->button('delete_account',1, 'delete', $label, $parm); + + } + } ?> \ No newline at end of file diff --git a/e107_core/templates/footer_default.php b/e107_core/templates/footer_default.php index 3fafe674e..bf734657a 100644 --- a/e107_core/templates/footer_default.php +++ b/e107_core/templates/footer_default.php @@ -305,7 +305,7 @@ if(deftrue('e_DEVELOPER')) { echo "\n\n<!-- ======= [JSManager] FOOTER: Remaining CSS ======= -->"; } -$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('other','core','plugin','theme'); // INLINE CSS in Body not supported by HTML5. . +$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('library','other','core','plugin','theme'); // INLINE CSS in Body not supported by HTML5. . foreach($CSSORDER as $val) { @@ -374,6 +374,22 @@ $show = deftrue('e_POWEREDBY_DISABLE') ? "none" : "block"; // Let search engines unset($show); echo "\n</body>\n</html>"; +//hook into the end of page (usefull for example for capturing output buffering) +//Load e_output.php files. +if (!empty($pref['e_output_list']) && is_array($pref['e_output_list'])) +{ + foreach($pref['e_output_list'] as $val) + { + $fname = e_PLUGIN.$val."/e_output.php"; // Do not place inside a function - BC $pref required. . + + if(is_readable($fname)) + { + + $ret = ($e107_debug || isset($_E107['debug'])) ? include_once($fname) : @include_once($fname); + } + } + unset($ret); +} // // I Send the buffered page data, along with appropriate headers diff --git a/e107_core/templates/header_default.php b/e107_core/templates/header_default.php index 286fb31cc..869a3f546 100644 --- a/e107_core/templates/header_default.php +++ b/e107_core/templates/header_default.php @@ -172,6 +172,7 @@ echo "<title>".(defined('e_PAGETITLE') ? e_PAGETITLE.' - ' : (defined('PAGE_NAME // D: Register CSS // $e_js = e107::getJs(); + $e_pref = e107::getConfig('core'); // Other Meta tags. @@ -315,7 +316,7 @@ else -$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('other','core','plugin','theme','inline'); +$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('library', 'other','core','plugin','theme','inline'); foreach($CSSORDER as $val) diff --git a/e107_core/templates/usersettings_template.php b/e107_core/templates/usersettings_template.php index c5222a588..330f0ca4d 100755 --- a/e107_core/templates/usersettings_template.php +++ b/e107_core/templates/usersettings_template.php @@ -173,6 +173,7 @@ $USERSETTINGS_EDIT = " </table> <div> {UPDATESETTINGSBUTTON} + {DELETEACCOUNTBUTTON} </div> </div> "; @@ -303,6 +304,7 @@ $USERSETTINGS_TEMPLATE['edit'] = " <div class='form-group'> <div class='col-sm-offset-3 col-sm-9'> {UPDATESETTINGSBUTTON} + {DELETEACCOUNTBUTTON} </div> </div> diff --git a/e107_handlers/admin_ui.php b/e107_handlers/admin_ui.php index 4e78309ca..2ab8383ca 100755 --- a/e107_handlers/admin_ui.php +++ b/e107_handlers/admin_ui.php @@ -1479,6 +1479,7 @@ class e_admin_dispatcher $tp = e107::getParser(); $var = array(); $selected = false; + foreach($this->adminMenu as $key => $val) { @@ -1516,6 +1517,12 @@ class e_admin_dispatcher case 'uri': $k2 = 'link'; $v = $tp->replaceConstants($v, 'abs'); + + if(!empty($v) && (e_REQUEST_URI === $v)) + { + $selected = $key; + } + break; default: @@ -1880,6 +1887,8 @@ class e_admin_controller $data = $_dispatcher->getPageTitles(); $search = $this->getMode().'/'.$this->getAction(); + + if(isset($data[$search])) { $res['caption'] = $data[$search]; @@ -2152,9 +2161,9 @@ class e_admin_controller return $response; } - if($action != 'Prefs' && $action != 'Create' && $action !='Edit' && $action != 'List') // Custom Page method in use, so add the title. + if($action != 'Prefs' && $action != 'Create' && $action !='Edit' && $action != 'List') // Custom Page method in use, so add the title. { - $this->addTitle(); + $this->addTitle(); } @@ -2164,6 +2173,9 @@ class e_admin_controller { $this->addTitle('#'.$this->getId()); // Inform user of which record is being edited. } + + + ob_start(); //catch any output $ret = $this->{$actionName}(); @@ -5478,6 +5490,13 @@ class e_admin_ui extends e_admin_controller_ui $this->getTreeModel()->setParam('db_query', $this->_modifyListQry(false, false, false, false, $this->listQry))->load(); $this->addTitle(); + + if($this->getQuery('filter_options')) + { + // var_dump($this); + // $this->addTitle("to-do"); // display filter option when active. + } + } /** @@ -6680,7 +6699,7 @@ class e_admin_form_ui extends e_form $vars = $this->getController()->getQuery(); $vars['from'] = '[FROM]'; - $paginate = http_build_query($vars); + $paginate = http_build_query($vars, null, '&'); return $this->pagination(e_REQUEST_SELF.'?'.$paginate,$totalRecords,$fromPage,$perPage,array('template'=>'basic')); @@ -6744,7 +6763,7 @@ class e_admin_form_ui extends e_form $gridAction = $this->getController()->getAction() === 'grid' ? 'list' : 'grid'; $gridQuery = (array) $_GET; $gridQuery['action'] = $gridAction; - $toggleUrl = e_REQUEST_SELF."?".http_build_query($gridQuery); + $toggleUrl = e_REQUEST_SELF."?".http_build_query($gridQuery, null, '&'); $gridIcon = ($gridAction === 'grid') ? ADMIN_GRID_ICON : ADMIN_LIST_ICON; $gridTitle = ($gridAction === 'grid') ? LAN_UI_VIEW_GRID_LABEL : LAN_UI_VIEW_LIST_LABEL; $gridToggle = "<a class='btn btn-default' href='".$toggleUrl."' title=\"".$gridTitle."\">".$gridIcon."</a>"; diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index 34aa2b104..b9e5a0b0d 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -16,7 +16,7 @@ if (!defined('e107_INIT')) { exit; } e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE."/lan_date.php"); -class convert +class e_date { function __construct() @@ -81,8 +81,7 @@ class convert /** * Return an array of language terms representing months * @param $type string : month, month-short, day, day-short, day-shortest - * @return array - * TODO Cache! + * @return array|bool */ public function terms($type='month') { @@ -173,7 +172,7 @@ class convert break; case 'inputtime': - $mask .= e107::getPref('inputtime', '%H:%M'); + $mask = e107::getPref('inputtime', '%H:%M'); break; case 'forum': // DEPRECATED - temporary here from BC reasons only @@ -225,17 +224,26 @@ class convert return is_numeric($string) ? $this->convert_date($string, $mask) : $this->toTime($string, $mask); } - + + + /** - * Converts to new date-mask format or vice-versa when $legacy is TRUE + * Converts to new date-mask format or vice-versa when $legacy is TRUE + * + * string $mask + * string|bool $legacy false= strftime > datetimepicker, true = datetimepicker > strftime, 'DateTime' = strftime > DateTime format. + * @see https://secure.php.net/manual/en/function.strftime.php + * @see https://github.com/AuspeXeu/bootstrap-datetimepicker + * @see https://secure.php.net/manual/en/datetime.createfromformat.php */ function toMask($mask, $legacy = false) { + //strftime() -> datetimepicker format. $convert = array( - '%Y' => 'yyyy', // jquery-ui docs say 'yy' but yy produces '13' instead of '2013' - '%d' => 'dd', - '%m' => 'mm', + '%Y' => 'yyyy', // Year 4-digits '2013' + '%d' => 'dd', // day of the month 2-digits + '%m' => 'mm', // month number 2-digits '%B' => 'MM', // Full month name, based on the locale '%A' => 'DD', // A full textual representation of the day @@ -250,22 +258,58 @@ class convert '%M' => 'ii', // Two digit representation of the minute '%S' => 'ss', // Two digit representation of the second '%P' => 'p', // %P lower-case 'am' or 'pm' based on the given time - '%p' => 'P', // %p UPPER-CASE 'AM' or 'PM' based on the given time + '%p' => 'P', // %p UPPER-CASE 'AM' or 'PM' based on the given time '%T' => 'hh:mm:ss', '%r' => "hh:mmm:ss TT" // 12 hour format ); - + + // strftime() > DateTime:: + if($legacy === 'DateTime') + { + $convert = array( + '%Y' => 'Y', // Year 4-digits '2013' + '%d' => 'd', // Two-digit day of the month (with leading zeros) (01 through 31) + '%e' => 'j', // Day of the month, with a space preceding single digits. Not implemented on Windows with strftime. + '%m' => 'm', // Two digit representation of the month (01 throught 12) + '%B' => 'F', // Full month name, based on the locale + '%A' => 'l', // A full textual representation of the day + + '%y' => 'y', + '%a' => 'D', // An abbreviated textual representation of the day + '%b' => 'M', // Abbreviated month name, based on the locale + '%h' => 'M', // Abbreviated month name, based on the locale (an alias of %b) + + '%k' => 'G', // Hour in 24-hour format, with a space preceding single digits (0 through 23) + '%I' => 'h', // Two digit representation of the hour in 12-hour format ( 01 through 12) + '%l' => 'g', // 12 hour format - no leading zero (1 through 12) + '%H' => 'H', // Two digit representation of the hour in 24-hour format (00 through 23) + + '%M' => 'i', // Two digit representation of the minute (00 through 59) + '%S' => 's', // Two digit representation of the second (00 through 59) + '%P' => 'a', // lower-case 'am' or 'pm' based on the given time + '%p' => 'A', // UPPER-CASE 'AM' or 'PM' based on the given time + '%Z' => 'e', // The time zone abbreviation. Not implemented as described on Windows with strftime. + + // TODO Add anything that is missing. + // '%T' => 'hh:mm:ss', + // '%r' => "hh:mmm:ss TT" // 12 hour format + ); + } + + $s = array_keys($convert); $r = array_values($convert); - if(strpos($mask, '%') === FALSE && $legacy == TRUE) + if(strpos($mask, '%') === false && $legacy === true) { - return str_replace($r, $s,$mask); + $ret = str_replace($r, $s,$mask); + return str_replace('%%p', '%P', $ret); // quick fix. } - elseif(strpos($mask,'%')!==FALSE) + elseif(strpos($mask,'%')!==false) { - return str_replace($s,$r, $mask); + return str_replace($s,$r, $mask); + } return $mask; @@ -357,8 +401,24 @@ class convert $mask = e107::getPref('inputtime', '%H:%M'); break; } - - // also in php compat handler for plugins that might use it. + + // convert to PHP 5+ @see https://secure.php.net/manual/en/datetime.createfromformat.php + $newMask = $this->toMask($mask, 'DateTime'); + $tdata = date_parse_from_format($newMask, $date_string); + + return mktime( + $tdata['hour'], + $tdata['minute'], + $tdata['second'], + $tdata['month'] , + $tdata['day'], + $tdata['year'] + ); + + + // also in php compat handler for plugins that might use it. + + /* $tdata = $this->strptime($date_string, $mask); @@ -385,14 +445,9 @@ class convert $tdata['tm_mday'], ($tdata['tm_year'] + 1900) ); - - - // echo "<br />UNIX=".$unxTimestamp - TIMEOFFSET; - // echo "<br />".date("l, d M Y g:i A",$unxTimestamp); - - // var_dump($tdata, $date_string, $this->convert_date($unxTimestamp, $mask), $unxTimestamp); return $unxTimestamp; + */ } // ----------------------- @@ -642,24 +697,22 @@ class convert } - - /** * This work of Lionel SAURON (http://sauron.lionel.free.fr:80) is licensed under the * Creative Commons Attribution-Noncommercial-Share Alike 2.0 France License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. - * + * * http://snipplr.com/view/4964/emulate-php-5-for-backwards-compatibility/ - * + * * Parse a date generated with strftime(). - * - * @author Lionel SAURON and reworked by e107 Inc. for month names. + * + * @author Lionel SAURON and reworked by e107 Inc. for month names. * @version 1.0 * @public * * @param string $str date string to parse (e.g. returned from strftime()). - * @param string $sFormat strftime format used to create the date + * @param $format * @return array|bool Returns an array with the <code>$str</code> parsed, or <code>false</code> on error. */ public function strptime($str, $format) @@ -787,11 +840,32 @@ class convert #-- calculate wday/yday //$vals['tm_mon'] = $vals['tm_mon'] + 1; // returns months from 0 - 11 so we need to +1 - - + + if (!isset($vals['tm_sec'])) + { + $vals['tm_sec'] = 0; + } + + if (!isset($vals['tm_min'])) + { + $vals['tm_min'] = 0; + } + + if (!isset($vals['tm_hour'])) + { + $vals['tm_hour'] = 0; + } + + + if (!isset($vals['unparsed'])) + { + $vals['unparsed'] = ''; + } + $unxTimestamp = mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], ($vals['tm_mon'] + 1), $vals['tm_mday'], ($vals['tm_year'] + 1900)); - - $vals['tm_fmon'] = strftime('%B', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'])); + + $vals['tm_amon'] = strftime('%b', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'] + 1)); + $vals['tm_fmon'] = strftime('%B', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'] + 1)); $vals['tm_wday'] = (int) strftime('%w', $unxTimestamp); // Days since Sunday (0-6) $vals['tm_yday'] = (strftime('%j', $unxTimestamp) - 1); // Days since January 1 (0-365) @@ -919,4 +993,15 @@ class convert } -?> \ No newline at end of file + + +/** + * BC Fix convert + */ +class convert extends e_date +{ + + + + +} \ No newline at end of file diff --git a/e107_handlers/db_verify_class.php b/e107_handlers/db_verify_class.php index 6418be6bc..338235091 100755 --- a/e107_handlers/db_verify_class.php +++ b/e107_handlers/db_verify_class.php @@ -641,7 +641,10 @@ class db_verify // print_a($data); if($data['type']) { - return $data['type']." (".$data['field'].");"; + //return $data['type']." (".$data['field'].");"; + // Check if index keyname exists and add backticks + $keyname = (!empty($data['keyname']) ? " `".$data['keyname']."`" : ""); + return $data['type'] . $keyname . " (" . $data['field'] . ");"; } else { @@ -919,9 +922,15 @@ class db_verify function getIndex($data, $print = false) { // $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?`?([\w,]*[\s]?)`?\))?,?/i"; - $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; + // $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; + $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?(INDEX|KEY) (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; preg_match_all($regex,$data,$m); - + + if (count($m) > 0) + { + unset($m[2]); + $m = array_combine(range(0, count($m)-1), array_values($m)); + } $ret = array(); if($print) @@ -933,6 +942,7 @@ class db_verify $fieldReplace = array("`"," "); + foreach($m[3] as $k=>$val) { if(!$val) continue; diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index eaef7ed63..8e98213d1 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -160,7 +160,8 @@ class e107 protected static $_known_handlers = array( 'UserHandler' => '{e_HANDLER}user_handler.php', 'comment' => '{e_HANDLER}comment_class.php', - 'convert' => '{e_HANDLER}date_handler.php', + 'e_date' => '{e_HANDLER}date_handler.php', + 'convert' => '{e_HANDLER}date_handler.php', // BC Fix. 'db' => '{e_HANDLER}mysql_class.php', 'e107Email' => '{e_HANDLER}mail.php', 'e107_event' => '{e_HANDLER}event_class.php', @@ -1588,7 +1589,7 @@ class e107 */ public static function getDateConvert() { - return self::getSingleton('convert', true); + return self::getSingleton('e_date', true); } /** @@ -1598,7 +1599,7 @@ class e107 */ public static function getDate() { - return self::getSingleton('convert', true); + return self::getSingleton('e_date', true); } @@ -2608,7 +2609,7 @@ class e107 */ public static function getThemeInfo($for = true, $path = '') { - global $user_pref; // FIXME - user model, kill user_pref global + // global $user_pref; // FIXME - user model, kill user_pref global if(true === $for) { @@ -2628,7 +2629,8 @@ class e107 } else { - $for = isset($user_pref['sitetheme']) ? $user_pref['sitetheme'] : self::getPref('sitetheme'); + $user_pref = self::getUser()->getPref(); + $for = !empty($user_pref['sitetheme']) ? $user_pref['sitetheme'] : self::getPref('sitetheme'); } break; @@ -3788,7 +3790,7 @@ class e107 // setup some php options self::ini_set('magic_quotes_runtime', 0); self::ini_set('magic_quotes_sybase', 0); - self::ini_set('arg_separator.output', '&'); + // self::ini_set('arg_separator.output', '&'); // non-standard and bad for third-party script compatibility. @see https://github.com/e107inc/e107/issues/3116 self::ini_set('session.use_only_cookies', 1); self::ini_set('session.use_trans_sid', 0); self::ini_set('session.cookie_httponly', 1); // cookie won't be accessible by scripting languages, such as JavaScript. Can effectively help to reduce identity theft through XSS attacks diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 6beee9b6b..b4c3b8512 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -2385,6 +2385,32 @@ class e_parse extends e_parser } + /** + * Convert a string to a number (int/float) + * + * @param string $value + * @return int|float + */ + function toNumber($value) + { + // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 + $dotPos = strrpos($value, '.'); + $commaPos = strrpos($value, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : + ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) { + return preg_replace("/[^-0-9]/", "", $value); + } + + return ( + preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . + preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) + ); + } + + + /** * Clean and Encode Ampersands '&' for output to browser. * @param string $text @@ -4634,7 +4660,7 @@ class e_parser $ytpref['cc_lang_pref'] = e_LAN; // switch captions with chosen user language. } - $ytqry = http_build_query($ytpref); + $ytqry = http_build_query($ytpref, null, '&'); $defClass = (deftrue('BOOTSTRAP')) ? "embed-responsive embed-responsive-16by9" : "video-responsive"; // levacy backup. diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index a3c267c7b..fa95efc36 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -820,7 +820,22 @@ class e_form } - + /** + * Create a input [type number] + * + * Additional options: + * - decimals: default 0; defines the number of decimals allowed in this field (0 = only integers; 1 = integers & floats with 1 decimal e.g. 4.1, etc.) + * - step: default 1; defines the step for the spinner and the max. number of decimals. If decimals is given, step will be ignored + * - min: default 0; minimum value allowed + * - max: default empty; maximum value allowed + * - pattern: default empty; allows to define an complex input pattern + * + * @param string $name + * @param integer $value + * @param integer $maxlength + * @param array $options decimals, step, min, max, pattern + * @return string + */ function number($name, $value=0, $maxlength = 200, $options = array()) { if(is_string($options)) parse_str($options, $options); @@ -850,17 +865,67 @@ class e_form $options['class'] .= " form-control"; $options['type'] ='number'; - $mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; + // Not used anymore + //$mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; - $min = isset($options['min']) ? 'min="'.$options['min'].'"' : ''; - $max = isset($options['max']) ? 'max="'.$options['max'].'"' : ''; + // Always define the min. parameter + // defaults to 0 + // setting the min option to a negative value allows negative inputs + $min = " min='".varsettrue($options['min'], '0')."'"; + $max = isset($options['max']) ? " max='".$options['max']."'" : ''; + if (!empty($options['pattern'])) + { + $pattern = ' pattern="'.trim($options['pattern']).'"'; + } + else + { + $options['pattern'] = '^'; + // ^\-?[0-9]*\.?[0-9]{0,2} + if (varset($options['min'], 0) < 0) + { + $options['pattern'] .= '\-?'; + } + $options['pattern'] .= '[0-9]*'; + + // Integer & Floaat/Double value handling + if (isset($options['decimals'])) + { + if (intval($options['decimals']) > 0) + { + $options['pattern'] .= '\.?[0-9]{0,'.intval($options['decimals']).'}'; + } + + // defined the step based on number of decimals + // 2 = 0.01 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = OK; 3.123 = NOK) + // 1 = 0.1 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = NOK) + // 0 = 1 > allows only integers, no float values + if (intval($options['decimals']) <= 0) + { + $step = "step='1'"; + } + else + { + $step = "step='0." . str_pad(1, intval($options['decimals']), 0, STR_PAD_LEFT) . "'"; + } + } + else + { + // decimal option not defined + // check for step option (1, 0.1, 0.01, and so on) + // or set default step 1 (integers only) + $step = "step='" . varsettrue($options['step'], '1') . "'"; + } + + $pattern = ' pattern="'.$options['pattern'].'"'; + } $options = $this->format_options('text', $name, $options); //never allow id in format name-value for text fields if(THEME_LEGACY === false) { - return "<input pattern='[0-9]*' type='number' name='{$name}' value='{$value}' {$mlength} {$min} {$max} ".$this->get_attributes($options, $name)." />"; + // return "<input pattern='[0-9]*' type='number' name='{$name}' value='{$value}' {$mlength} {$step} {$min} {$max} ".$this->get_attributes($options, $name)." />"; + return "<input type='number' name='{$name}' {$min} {$max} {$step} value='{$value}' ".$this->get_attributes($options, $name)." />"; } return $this->text($name, $value, $maxlength, $options); @@ -1372,7 +1437,10 @@ class e_form * on Submit returns unix timestamp or string value. * @param string $name the name of the field * @param integer $datestamp UNIX timestamp - default value of the field - * @param array or str + * @param array or str + * @param string $options['type'] date or datetime + * @param string $options['format'] strftime format eg. '%Y-%m-%d' + * @param string $options['timezone'] eg. 'America/Los_Angeles' - intended timezone of the date/time entered. (offsets UTC value) * @example $frm->datepicker('my_field',time(),'type=date'); * @example $frm->datepicker('my_field',time(),'type=datetime&inline=1'); * @example $frm->datepicker('my_field',time(),'type=date&format=yyyy-mm-dd'); @@ -1428,17 +1496,26 @@ class e_form $firstDay = vartrue($options['firstDay']) ? $options['firstDay'] : 0; $xsize = (vartrue($options['size']) && !is_numeric($options['size'])) ? $options['size'] : 'xlarge'; $disabled = vartrue($options['disabled']) ? "disabled" : ""; + $timezone = ''; + + if(!empty($options['timezone'])) // since datetimepicker does not support timezones and assumes the browser timezone is the intended timezone. + { + date_default_timezone_set($options['timezone']); + $targetOffset = date('Z'); + date_default_timezone_set(USERTIMEZONE); + $timezone = "data-date-timezone-offset='".$targetOffset."'"; + } $text = ""; if(vartrue($options['inline'])) { $text .= "<div class='{$class}' id='inline-{$id}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}'></div>"; - $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' />"; + $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' />"; } else { - $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} />"; + $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} {$timezone} />"; $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; $text .= "<input type='{$ftype}' name='{$name}' id='{$id}' value='{$hiddenValue}' />"; } @@ -2637,6 +2714,7 @@ class e_form * @param boolean $selected [optional] * @param string|array $options [optional] * @param bool $options['useValues'] when true uses array values as the key. + * @param array $options['disabled'] list of $option_array keys which should be disabled. eg. array('key_1', 'key_2'); * @param bool|string $defaultBlank [optional] set to TRUE if the first entry should be blank, or to a string to use it for the blank description. * @return string HTML text for display */ @@ -2681,7 +2759,7 @@ class e_form $option_array = $new; } - $text .= $this->option_multi($option_array, $selected)."\n".$this->select_close(); + $text .= $this->option_multi($option_array, $selected, $options)."\n".$this->select_close(); return $text; } @@ -2863,11 +2941,13 @@ class e_form function option($option_title, $value, $selected = false, $options = '') { if(is_string($options)) parse_str($options, $options); - + if(false === $value) $value = ''; $options = $this->format_options('option', '', $options); $options['selected'] = $selected; //comes as separate argument just for convenience + + return "<option value='{$value}'".$this->get_attributes($options).">".defset($option_title, $option_title)."</option>"; } @@ -2889,18 +2969,24 @@ class e_form return $this->option('',''); } + $opts = $options; - foreach ($option_array as $value => $label) + foreach ((array) $option_array as $value => $label) { if(is_array($label)) { - $text .= $this->optgroup($value,$label,$selected,$options, 0); - + $text .= $this->optgroup($value, $label, $selected, $options, 0); } else { + $sel = is_array($selected) ? in_array($value, $selected) : ($value == $selected); - $text .= $this->option($label, $value, (is_array($selected) ? in_array($value, $selected) : $selected == $value), $options)."\n"; + if(!empty($options['disabled'])) + { + $opts['disabled'] = in_array($value, $options['disabled']); + } + + $text .= $this->option($label, $value, $sel, $opts)."\n"; } } @@ -2922,6 +3008,8 @@ class e_form $level++; $text = $this->optgroup_open($value, null, array('class'=>'level-'.$level)); + $opts = $options; + foreach($label as $val => $lab) { if(is_array($lab)) @@ -2930,7 +3018,12 @@ class e_form } else { - $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $options)."\n"; + if(!empty($options['disabled'])) + { + $opts['disabled'] = in_array($val, $options['disabled']); + } + + $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $opts)."\n"; } } @@ -3071,7 +3164,7 @@ class e_form return $text; } - + return $this->admin_button($name, $value, $action, $label, $options); @@ -3176,6 +3269,13 @@ class e_form $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' data-disable='true'" : ""; } + $confirmation = LAN_JSCONFIRM; + + if(!empty($options['confirm'])) + { + $confirmation = $options['confirm']; + } + $options = $this->format_options('admin_button', $name, $options); $options['class'] = vartrue($options['class']); @@ -3200,7 +3300,10 @@ class e_form case 'delete': case 'danger': - $options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"'; + + + + $options['other'] = 'data-confirm="'.$confirmation.'"'; break; case 'batch': @@ -4221,7 +4324,7 @@ class e_form $eModalCap = ""; } - $query = http_build_query($query); + $query = http_build_query($query, null, '&'); $value .= "<a href='".e_SELF."?{$query}' class='btn btn-default btn-secondary".$eModal."' ".$eModalCap." title='".LAN_EDIT."' data-toggle='tooltip' data-placement='left'> ".$editIconDefault."</a>"; } @@ -5658,15 +5761,13 @@ class e_form $eloptions = vartrue($parms['__options'], array()); } - $value = (isset($eloptions['empty']) && empty($value)) ? $eloptions['empty'] : $value; + $value = (isset($eloptions['empty']) && ($value === null)) ? $eloptions['empty'] : $value; if(is_string($eloptions)) parse_str($eloptions, $eloptions); if($attributes['type'] === 'comma') $eloptions['multiple'] = true; unset($parms['__options']); if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); - - // Allow Ajax API. if(!empty($ajaxParms)) { diff --git a/e107_handlers/js_manager.php b/e107_handlers/js_manager.php index 1ee36df99..e21211d90 100644 --- a/e107_handlers/js_manager.php +++ b/e107_handlers/js_manager.php @@ -358,6 +358,21 @@ class e_jsmanager return $this; } + /** + * Add CSS file(s) for inclusion in site header in the 'library' category. + * + * @param string|array $file_path path, shortcodes usage is prefered + * @param string $media any valid media attribute string - http://www.w3schools.com/TAGS/att_link_media.asp + * @return e_jsmanager + */ + public function libraryCSS($file_path, $media = 'all', $preComment = '', $postComment = '') + { + $this->addJs('library_css', $file_path, $media, $preComment, $postComment); + return $this; + } + + + /** * Add CSS file(s) for inclusion in site header * @@ -962,6 +977,14 @@ class e_jsmanager $runtime = true; break; + case 'library_css': + $file_path = $runtime_location.$this->_sep.$tp->createConstants($file_path, 'mix').$this->_sep.$pre.$this->_sep.$post; + // e107::getDebug()->log($file_path); + if(!isset($this->_e_css['library'])) $this->_e_css['library'] = array(); + $registry = &$this->_e_css['library']; + $runtime = true; + break; + case 'inline_css': // no zones, TODO - media? $this->_e_css_src[] = $file_path; return $this; @@ -1129,6 +1152,11 @@ class e_jsmanager unset($this->_e_css['other']); break; + case 'library_css': + $this->renderFile(varset($this->_e_css['library'], array()), $external, 'Library CSS', $mod, false); + unset($this->_e_css['library']); + break; + case 'inline_css': $this->renderInline($this->_e_css_src, 'Inline CSS', 'css'); $this->_e_css_src = array(); diff --git a/e107_handlers/library_manager.php b/e107_handlers/library_manager.php index 57be5a1f0..8ff92d68a 100755 --- a/e107_handlers/library_manager.php +++ b/e107_handlers/library_manager.php @@ -300,7 +300,7 @@ class core_library ), 'css' => array( 'dist/css/bootstrap.min.css' => array( - 'zone' => 2, + 'zone' => 1, ), ), ), @@ -1724,7 +1724,8 @@ class e_library_manager } elseif($type == 'css') { - e107::css($options['type'], $data, null); + e107::getJs()->libraryCSS($data); // load before others. + // e107::css($options['type'], $data, null); } $count++; } diff --git a/e107_handlers/model_class.php b/e107_handlers/model_class.php index c905c8a65..e7157ac6d 100755 --- a/e107_handlers/model_class.php +++ b/e107_handlers/model_class.php @@ -1792,21 +1792,22 @@ class e_model extends e_object * @param string $value * @return integer|float */ - public function toNumber($value) - { - $larr = localeconv(); - $search = array( - $larr['decimal_point'], - $larr['mon_decimal_point'], - $larr['thousands_sep'], - $larr['mon_thousands_sep'], - $larr['currency_symbol'], - $larr['int_curr_symbol'] - ); - $replace = array('.', '.', '', '', '', ''); + // moved to e_parse + // public function toNumber($value) + // { + // $larr = localeconv(); + // $search = array( + // $larr['decimal_point'], + // $larr['mon_decimal_point'], + // $larr['thousands_sep'], + // $larr['mon_thousands_sep'], + // $larr['currency_symbol'], + // $larr['int_curr_symbol'] + // ); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, $value); - } + // return str_replace($search, $replace, $value); + // } /** * Convert object data to a string @@ -2704,7 +2705,8 @@ class e_front_model extends e_model { case 'int': case 'integer': - return intval($this->toNumber($value)); + //return intval($this->toNumber($value)); + return intval($tp->toNumber($value)); break; case 'safestr': @@ -2731,7 +2733,8 @@ class e_front_model extends e_model break; case 'float': - return $this->toNumber($value); + // return $this->toNumber($value); + return $tp->toNumber($value); break; case 'bool': diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index c2a7d91f0..af93de116 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -867,6 +867,7 @@ class e_db_mysql $this->mySQLcurTable = $table; $REPLACE = false; // kill any PHP notices $DUPEKEY_UPDATE = false; + $IGNORE = ''; if(is_array($arg)) { @@ -885,7 +886,12 @@ class e_db_mysql { $DUPEKEY_UPDATE = true; unset($arg['_DUPLICATE_KEY_UPDATE']); + } + if(isset($arg['_IGNORE'])) + { + $IGNORE = ' IGNORE'; + unset($arg['_IGNORE']); } if(!isset($arg['_FIELD_TYPES']) && !isset($arg['data'])) @@ -942,7 +948,7 @@ class e_db_mysql if($REPLACE === false) { - $query = "INSERT INTO `".$this->mySQLPrefix."{$table}` ({$keyList}) VALUES ({$valList})"; + $query = "INSERT".$IGNORE." INTO `".$this->mySQLPrefix."{$table}` ({$keyList}) VALUES ({$valList})"; if($DUPEKEY_UPDATE === true) { @@ -1301,11 +1307,13 @@ class e_db_mysql case 'float': // fix - convert localized float numbers - $larr = localeconv(); - $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); - $replace = array('.', '.', '', '', '', ''); + // $larr = localeconv(); + // $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, floatval($fieldValue)); + // return str_replace($search, $replace, floatval($fieldValue)); + + return e107::getParser()->toNumber($fieldValue); break; case 'null': @@ -1360,11 +1368,12 @@ class e_db_mysql case 'float': // fix - convert localized float numbers - $larr = localeconv(); - $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); - $replace = array('.', '.', '', '', '', ''); + // $larr = localeconv(); + // $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, floatval($fieldValue)); + // return str_replace($search, $replace, floatval($fieldValue)); + return e107::getParser()->toNumber($fieldValue); break; case 'null': @@ -1436,8 +1445,6 @@ class e_db_mysql } - - /** * @DEPRECATED Similar to db_Update(), but splits the variables and the 'WHERE' clause. @@ -2349,6 +2356,77 @@ class e_db_mysql } + /** + * Determines if a table index (key) exist. + * + * @param string $table - table name (no prefix) + * @param string $keyname - Name of the key to + * @param array $fields - OPTIONAL list of fieldnames, the index (key) must contain + * @param boolean $retinfo = FALSE - just returns true|false. TRUE - returns all key info + * @return array|boolean - FALSE on error, key information on success + */ + function index($table, $keyname, $fields=null, $retinfo = FALSE) + { + if(!$this->mySQLdefaultdb) + { + global $mySQLdefaultdb; + $this->mySQLdefaultdb = $mySQLdefaultdb; + } + + if(!$this->mySQLaccess) + { + global $db_ConnectionID; + $this->mySQLaccess = $db_ConnectionID; + } + + if (!empty($fields) && !is_array($fields)) + { + $fields = explode(',', str_replace(' ', '', $fields)); + } + elseif(empty($fields)) + { + $fields = array(); + } + + $check_field = count($fields) > 0; + + $info = array(); + $result = $this->gen("SHOW INDEX FROM ".$this->mySQLPrefix.$table); + if ($result && ($this->rowCount() > 0)) + { + $c=0; + while ($row = $this->fetch()) + { + // Check for match of key name - and allow that key might not be used + if($keyname == $row['Key_name']) + { + // a key can contain severeal fields which are returned as 1 row per field + if (!$check_field) + { // Check only for keyname + $info[] = $row; + } + elseif ($check_field && in_array($row['Column_name'], $fields)) + { // Check also for fieldnames + $info[] = $row; + } + $c++; + } + } + + if (count($info) > 0) + { + // Kex does not consist of all keys + if ($check_field && $c != count($fields)) return false; + // Return full information + if ($retinfo) return $info; + // Return only if index was found + return true; + } + } + return FALSE; + } + + /** * A pointer to mysql_real_escape_string() - see http://www.php.net/mysql_real_escape_string * diff --git a/e107_handlers/news_class.php b/e107_handlers/news_class.php index 68e4d7df3..43781be88 100644 --- a/e107_handlers/news_class.php +++ b/e107_handlers/news_class.php @@ -49,7 +49,8 @@ class news { if(empty($news['news_title'])) { $error = true; - $emessage->add('Validation error: News title can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_47; + $emessage->add(LAN_ERROR_47, E_MESSAGE_ERROR, $smessages); if(!empty($news['news_sef'])) { $news['news_sef'] = eHelper::secureSef($news['news_sef']); @@ -72,18 +73,21 @@ class news { if(empty($news['news_sef'])) { $error = true; - $emessage->add('Validation error: News SEF URL value is required field and can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_48; + $emessage->add(LAN_ERROR_48, E_MESSAGE_ERROR, $smessages); } elseif($sql->db_Count('news', '(news_id)', ($news['news_sef'] ? 'news_id<>'.intval($news['news_id']).' AND ' : '')."news_sef='".$tp->toDB($news['news_sef'])."'")) { $error = true; - $emessage->add('Validation error: News SEF URL is unique field - current value already in use! Please choose another SEF URL value.', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_49; + $emessage->add(LAN_ERROR_49, E_MESSAGE_ERROR, $smessages); } if(empty($news['news_category'])) { $error = true; - $emessage->add('Validation error: News category can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_50; + $emessage->add(LAN_ERROR_50, E_MESSAGE_ERROR, $smessages); } diff --git a/e107_handlers/plugin_class.php b/e107_handlers/plugin_class.php index 4af32abcc..7c5200d1b 100644 --- a/e107_handlers/plugin_class.php +++ b/e107_handlers/plugin_class.php @@ -76,6 +76,7 @@ class e_plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', + 'e_output', //hook into all pages at the end (after closing </html>) ); @@ -1069,6 +1070,7 @@ class e107plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', + 'e_output', //hook into all pages at the end (after closing </html>) ); @@ -1114,8 +1116,8 @@ class e107plugin 'e_upload' => "Use data from your plugin in the user upload form.", 'e_user' => "Have your plugin include data on the user-profile page.", 'e_library' => "Include a third-party library", - 'e_parse' => "Hook into e107's text/html parser" - + 'e_parse' => "Hook into e107's text/html parser", + 'e_output' => "Hook into all pages at the end (after closing </html>)" ); diff --git a/e107_handlers/validator_class.php b/e107_handlers/validator_class.php index d000f31b5..b91fe03f2 100644 --- a/e107_handlers/validator_class.php +++ b/e107_handlers/validator_class.php @@ -577,7 +577,7 @@ class e_validator break; case 'float': - $value = $this->toNumber($value); + $value = e107::getParser()->toNumber($value); if(!is_numeric($value)) { $this->addValidateResult($name, self::ERR_FLOAT_EXPECTED); @@ -728,22 +728,23 @@ class e_validator break; } } - - public function toNumber($value) - { - $larr = localeconv(); - $search = array( - $larr['decimal_point'], - $larr['mon_decimal_point'], - $larr['thousands_sep'], - $larr['mon_thousands_sep'], - $larr['currency_symbol'], - $larr['int_curr_symbol'] - ); - $replace = array('.', '.', '', '', '', ''); + + // moved to e_parse + // public function toNumber($value) + // { + // $larr = localeconv(); + // $search = array( + // $larr['decimal_point'], + // $larr['mon_decimal_point'], + // $larr['thousands_sep'], + // $larr['mon_thousands_sep'], + // $larr['currency_symbol'], + // $larr['int_curr_symbol'] + // ); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, $value); - } + // return str_replace($search, $replace, $value); + // } protected function parseMinMax($string) { diff --git a/e107_languages/English/lan_error.php b/e107_languages/English/lan_error.php index b7e1e5d53..7ea413f67 100644 --- a/e107_languages/English/lan_error.php +++ b/e107_languages/English/lan_error.php @@ -64,4 +64,8 @@ define("LAN_ERROR_44", "Site logo"); define("LAN_ERROR_45", "What can you do now?"); define("LAN_ERROR_46", "Check log for details."); +define("LAN_ERROR_47", "Validation error: News title can't be empty!"); +define("LAN_ERROR_48", "Validation error: News SEF URL value is required field and can't be empty!"); +define("LAN_ERROR_49", "Validation error: News SEF URL is unique field - current value already in use! Please choose another SEF URL value."); +define("LAN_ERROR_50", "Validation error: News category can't be empty!"); ?> diff --git a/e107_languages/English/lan_userposts.php b/e107_languages/English/lan_userposts.php index c23fc6037..d598e0adb 100644 --- a/e107_languages/English/lan_userposts.php +++ b/e107_languages/English/lan_userposts.php @@ -11,8 +11,8 @@ */ define("PAGE_NAME", "User Posts"); -define("UP_LAN_0", "All Forum Posts for "); -define("UP_LAN_1", "All Comments for "); +define("UP_LAN_0", "All Forum Posts for [x]"); +define("UP_LAN_1", "All Comments for [x]"); define("UP_LAN_2", "Thread"); define("UP_LAN_3", "Views"); define("UP_LAN_4", "Replies"); @@ -28,4 +28,4 @@ define("UP_LAN_12", "Search"); define("UP_LAN_14", "Forum Posts"); define("UP_LAN_15", "Re"); define("UP_LAN_16", "IP Address"); -?> \ No newline at end of file +?> diff --git a/e107_languages/English/lan_usersettings.php b/e107_languages/English/lan_usersettings.php index f5fb4bf54..2892622b0 100644 --- a/e107_languages/English/lan_usersettings.php +++ b/e107_languages/English/lan_usersettings.php @@ -145,4 +145,6 @@ define("LAN_CUSTOMTITLE", "Custom title"); define("LAN_USET_5", "Subscribed to"); define("LAN_USET_6", "Subscribe to our mailing-list(s) and/or sections of this site."); // define("LAN_USET_8", "Signature / Time zone"); -?> \ No newline at end of file + +define("LAN_USET_50", "Delete Account"); +define("LAN_USET_51", "Are you sure? This procedure cannot be reversed! Once completed, your account and any personal data that you have entered on this site will be permanently lost and you will no longer be able to login."); \ No newline at end of file diff --git a/e107_plugins/_blank/_blank_setup.php b/e107_plugins/_blank/_blank_setup.php index d435b0a7e..5b937725d 100644 --- a/e107_plugins/_blank/_blank_setup.php +++ b/e107_plugins/_blank/_blank_setup.php @@ -78,6 +78,96 @@ if(!class_exists("_blank_setup")) // print_a($var); } + + /* + * Call During Upgrade Check. May be used to check for existance of tables etc and if not found return TRUE to call for an upgrade. + * + * @return bool true = upgrade required; false = upgrade not required + */ + function upgrade_required() + { + // Check if a specific table exists and if not, return true to force a db update + // In this example, it checks if the table "blank_table" exists +// if(!e107::getDb()->isTable('blank_table')) +// { +// return true; // true to trigger an upgrade alert, and false to not. +// } + + + // Check if a specific field exists in the specified table + // and if not return false to force a db update to add this field + // from the "_blank_sql.php" file + // In this case: Exists field "blank_id" in table "blank_table" +// if(!e107::getDb()->field('blank_table','blank_id')) +// { +// return true; // true to trigger an upgrade alert, and false to not. +// } + + + // In case you need to delete a field that is not used anymore, + // first check if the field exists, than run a sql command to drop (delete) the field + // !!! ATTENTION !!! + // !!! Deleting a field, deletes also the data stored in that field !!! + // !!! Make sure you know what you are doing !!! + // + // In this example, the field "blank_unused_field" from table "blank_table" + // isn't used anymore and will be deleted (dropped) if it still exists +// if(e107::getDb()->field('blank_table', 'blank_unused_field')) +// { + // this statement directly deletes the field, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP `blank_unused_field` "); +// } + + + // In case you need to delete a index that is not used anymore, + // first check if the index exists, than run a sql command to drop (delete) the field + // Be aware, that deleting an index is not very harmfull, as the data of the + // index will be recreated when the index is added again. +// if(e107::getDb()->index('blank_table','blank_unused_index')) +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } + + // In case you need to check an index and which fields it is build of, + // use the fourth parameter to return the index definition. + // In this case, the index should be deleted if consists only of 1 field ("blank_fieldname"), +// if(e107::getDb()->index('blank_table','blank_unused_index', array('blank_fieldname'))) +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } + + + // In case you need to check an index and which fields it is build of, + // use the third parameter to return the index definition. + // In this case, the index should be deleted if consists only of 1 field ("blank_fieldname"), +// if ($index_def = e107::getDb()->index('blank_table','blank_unused_index', array('blank_fieldname'))) +// { + // Check if the key should be UNIQUE +// $unique = array_count_values(array_column($index_def, 'Non_unique')); +// if($unique[1] > 0) // Keys are not unique +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } +// } + + + $legacyMenuPref = e107::getConfig('menu')->getPref(); + if(isset($legacyMenuPref['newforumposts_caption'])) + { + + } + + return false; + } + + function upgrade_post($var) { // $sql = e107::getDb(); diff --git a/e107_plugins/_blank/blank_sql.php b/e107_plugins/_blank/blank_sql.php index 3a0c771c5..3ab5902ee 100644 --- a/e107_plugins/_blank/blank_sql.php +++ b/e107_plugins/_blank/blank_sql.php @@ -1,3 +1,48 @@ +/** + * e107 website system + * + * Copyright (C) 2008-2013 e107 Inc (e107.org) + * Released under the terms and conditions of the + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) + * + * INFORMATION + * + * BEFORE DOING ANY DATABASE CHANGES OR UPDATES, CREATE A FRESH BACKUP!!! + * + * Add the SQL statements for your table here. + * Make sure that you do not add the e107 table prefix (by default e107) to the table name!! + * This file will be analyzed on plugin install and missing tables will be installed automatically. + * To check if the table structure is still valid, run the "Tools -> Database -> Check for Updates" command. + * Any differences between the defined structure here and the table structure on the server will than be detected. + * In another step, you are able to update the table structure to the latest version from this file! + * + * + * For the moment, the following operations are supported: + * ------------------------------------------------------- + * - Create table + * - Change field type, field size, field null or not, field default value + * - Add index + * + * + * What is currently NOT supported: + * -------------------------------- + * - Rename table (by renaming the tablename, e.g. "blank" > "blank2"). The renamed table will be considered as new! + * - Drop a table (e.g. if you remove the "blank" table definition from this file, the table will NOT be deleted from the database!) + * - Rename or drop a field (a renamed field will be considered new, a missing field definition will NOT be recognized at all!) + * - Change an index/key (e.g. the change is recognized, but leads to an error message and the change is not applied) + * - Rename or drop an index/key (Rename is recognized as a new index and the missing index is not recognized at all!) + * - A field definition containing "NULL DEFAULT NULL". The "Check for updates" method will always detect a change, + * but fails silently when trying to update. In that case remove the first "NULL" and run the the "Check for updates" again. + * + * + * How to rename or drop tables, fields and indexes or modify indexes: + * ------------------------------------------------------------------- + * There are methods that can be used to detect tables, fields and indexes. Some examples of how to use them + * can be found in the "_blank_setup.php". There are also examples on how to drop a field or index or to check for specific properties. + * Other examples can be found also in the "forum_setup.php" + */ + + CREATE TABLE blank ( `blank_id` int(10) NOT NULL AUTO_INCREMENT, `blank_icon` varchar(255) NOT NULL, diff --git a/e107_plugins/_blank/e_user.php b/e107_plugins/_blank/e_user.php index 546355081..42e96bd2f 100644 --- a/e107_plugins/_blank/e_user.php +++ b/e107_plugins/_blank/e_user.php @@ -25,16 +25,30 @@ class _blank_user // plugin-folder + '_user' } - - function fields() + /** + * Experimental and subject to change without notice. + * @return mixed + */ + function delete() { - $fields = array( - - - + $config['user'] = array( + 'user_id' => '[primary]', + 'user_name' => '[unique]', + 'user_loginname' => '[unique]', + 'user_email' => '[unique]', + 'user_ip' => '', + // etc. + 'WHERE' => 'user_id = '.USERID, + 'MODE' => 'update' ); + $config['user_extended'] = array( + 'WHERE' => 'user_extended_id = '.USERID, + 'MODE' => 'delete' + ); + + return $config; } diff --git a/e107_plugins/download/download_shortcodes.php b/e107_plugins/download/download_shortcodes.php index d8a6ea43d..f197855b8 100644 --- a/e107_plugins/download/download_shortcodes.php +++ b/e107_plugins/download/download_shortcodes.php @@ -291,7 +291,7 @@ class download_shortcodes extends e_shortcode } - return "<a href='".e_REQUEST_SELF."?".http_build_query($qry)."'>".$text."</a>" ; + return "<a href='".e_REQUEST_SELF."?".http_build_query($qry, null, '&')."'>".$text."</a>" ; } diff --git a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php new file mode 100644 index 000000000..a3b62c955 --- /dev/null +++ b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php @@ -0,0 +1,52 @@ +<?php +require_once('SecureLinkDecorator.php'); + +class NginxSecureLinkMd5Decorator implements SecureLinkDecorator +{ + protected $url = null; + protected $prefs = array(); + + public static $SUPPORTED_VARIABLES = array( + '$secure_link_expires', + '$uri', + '$remote_addr' + ); + + static function supported_variables() { + return self::$SUPPORTED_VARIABLES; + } + + function __construct($url, $preferences) + { + $this->url = $url; + $this->prefs = $preferences; + } + + public function decorate() + { + $prefs = $this->prefs; + $url = $this->url; + $expiry = intval($prefs['download_security_link_expiry']); + if ($expiry <= 0) + $expiry = PHP_INT_MAX; + else + $expiry = time() + $expiry; + $url_parts = parse_url($url); + $evaluation = str_replace( + self::supported_variables(), + array( + $expiry, + $url_parts['path'], + $_SERVER['REMOTE_ADDR'] + ), + $prefs['download_security_expression'] + ); + $query_string = $url_parts['query']; + parse_str($query_string, $query_args); + $query_args['md5'] = str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode(md5($evaluation, true))); + if (strpos($prefs['download_security_expression'], '$secure_link_expires') !== false) + $query_args['expires'] = $expiry; + require_once(__DIR__ . '/../vendor/shim_http_build_url.php'); + return http_build_url($url_parts, array('query' => http_build_query($query_args))); + } +} \ No newline at end of file diff --git a/e107_plugins/download/handlers/SecureLinkDecorator.php b/e107_plugins/download/handlers/SecureLinkDecorator.php new file mode 100644 index 000000000..0dd48ab93 --- /dev/null +++ b/e107_plugins/download/handlers/SecureLinkDecorator.php @@ -0,0 +1,6 @@ +<?php + +interface SecureLinkDecorator +{ + public function decorate(); +} \ No newline at end of file diff --git a/e107_plugins/download/includes/admin.php b/e107_plugins/download/includes/admin.php index e992375aa..d8548109e 100644 --- a/e107_plugins/download/includes/admin.php +++ b/e107_plugins/download/includes/admin.php @@ -286,7 +286,11 @@ class download_main_admin_ui extends e_admin_ui //required - default column user prefs protected $fieldpref = array('checkboxes', 'download_image', 'download_id', 'download_datestamp', 'download_category', 'download_name', 'download_active', 'download_class', 'fb_order', 'options'); - // + // Security modes + protected $security_options = array( + 'none' => LAN_DL_SECURITY_MODE_NONE, + 'nginx-secure_link_md5' => LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5 + ); // optional - required only in case of e.g. tables JOIN. This also could be done with custom model (set it in init()) //protected $editQry = "SELECT * FROM #release WHERE release_id = {ID}"; @@ -1133,22 +1137,32 @@ $columnInfo = array( global $admin_log,$pref; $tp = e107::getParser(); + + $expected_params = array( + 'download_php', 'download_view', 'download_sort', 'download_order', + 'mirror_order', 'recent_download_days', 'agree_flag', 'download_email', + 'agree_text', 'download_denied', 'download_reportbroken', + 'download_security_mode', 'download_security_expression', 'download_security_link_expiry' + ); $temp = array(); - $temp['download_php'] = $_POST['download_php']; - $temp['download_view'] = $_POST['download_view']; - $temp['download_sort'] = $_POST['download_sort']; - $temp['download_order'] = $_POST['download_order']; - $temp['mirror_order'] = $_POST['mirror_order']; - $temp['recent_download_days'] = $_POST['recent_download_days']; - $temp['agree_flag'] = $_POST['agree_flag']; - $temp['download_email'] = $_POST['download_email']; - $temp['agree_text'] = $tp->toDB($_POST['agree_text']); - $temp['download_denied'] = $tp->toDB($_POST['download_denied']); - $temp['download_reportbroken'] = $_POST['download_reportbroken']; - - if ($_POST['download_subsub']) $temp['download_subsub'] = '1'; else $temp['download_subsub'] = '0'; - if ($_POST['download_incinfo']) $temp['download_incinfo'] = '1'; else $temp['download_incinfo'] = '0'; + foreach($expected_params as $expected_param) + { + $temp[$expected_param] = $_POST[$expected_param]; + } + + $temp['download_subsub'] = $_POST['download_subsub'] ? '1' : '0'; + $temp['download_incinfo'] = $_POST['download_incinfo'] ? '1' : '0'; + + if ($_POST['download_security_mode'] !== 'nginx-secure_link_md5') + { + unset($temp['download_security_mode']); + unset($temp['download_security_expression']); + unset($temp['download_security_link_expiry']); + e107::getConfig('core')->removePref('download_security_mode'); + e107::getConfig('core')->removePref('download_security_expression'); + e107::getConfig('core')->removePref('download_security_link_expiry'); + } e107::getConfig('core')->setPref($temp)->save(false); @@ -2093,14 +2107,33 @@ $columnInfo = array( } } + private function supported_secure_link_variables_html() + { + require_once(__DIR__."/../handlers/NginxSecureLinkMd5Decorator.php"); + $supported_secure_link_variables_html = "<ul>"; + foreach(NginxSecureLinkMd5Decorator::supported_variables() as $variable) + { + $supported_secure_link_variables_html .= "<li><code>$variable</code></li>"; + } + $supported_secure_link_variables_html .= "</ul>"; + return $supported_secure_link_variables_html; + } + + private function mirror_order_options_html($pref) + { + return ($pref['mirror_order'] == "0" ? "<option value='0' selected='selected'>".DOWLAN_161."</option>" : "<option value='0'>".DOWLAN_161."</option>"). + ($pref['mirror_order'] == "1" ? "<option value='1' selected='selected'>".LAN_ID."</option>" : "<option value='1'>".LAN_ID."</option>"). + ($pref['mirror_order'] == "2" ? "<option value='2' selected='selected'>".DOWLAN_12."</option>" : "<option value='2'>".DOWLAN_12."</option>"); + } + function show_download_options() { global $pref, $ns; - - require_once(e_HANDLER."form_handler.php"); - $frm = new e_form(true); //enable inner tabindex counter - - $agree_flag = $pref['agree_flag']; + + require_once(e_HANDLER."form_handler.php"); + $frm = new e_form(true); //enable inner tabindex counter + + $agree_flag = $pref['agree_flag']; $agree_text = $pref['agree_text']; $c = $pref['download_php'] ? " checked = 'checked' " : ""; $sacc = (varset($pref['download_incinfo'],0) == '1') ? " checked = 'checked' " : ""; @@ -2115,14 +2148,15 @@ $columnInfo = array( "ASC" => DOWLAN_62, "DESC" => DOWLAN_63 ); - + $text = " <ul class='nav nav-tabs'> <li class='active'><a data-toggle='tab' href='#core-download-download1'>".LAN_DL_DOWNLOAD_OPT_GENERAL."</a></li> <li><a data-toggle='tab' href='#core-download-download2'>".LAN_DL_DOWNLOAD_OPT_BROKEN."</a></li> <li><a data-toggle='tab' href='#core-download-download3'>".LAN_DL_DOWNLOAD_OPT_AGREE."</a></li> - <li><a data-toggle='tab' href='#core-download-download4'>".LAN_DL_UPLOAD."</a></li> + <li><a data-toggle='tab' href='#core-download-download4'>".LAN_DL_DOWNLOAD_OPT_SECURITY."</a></li> + <li><a data-toggle='tab' href='#core-download-download5'>".LAN_DL_UPLOAD."</a></li> </ul> <form method='post' action='".e_SELF."?".e_QUERY."'>\n @@ -2170,10 +2204,7 @@ $columnInfo = array( <tr> <td>".DOWLAN_160."</td> <td> - <select name='mirror_order' class='form-control'>". - ($pref['mirror_order'] == "0" ? "<option value='0' selected='selected'>".DOWLAN_161."</option>" : "<option value='0'>".DOWLAN_161."</option>"). - ($pref['mirror_order'] == "1" ? "<option value='1' selected='selected'>".LAN_ID."</option>" : "<option value='1'>".LAN_ID."</option>"). - ($pref['mirror_order'] == "2" ? "<option value='2' selected='selected'>".DOWLAN_163."</option>" : "<option value='2'>".DOWLAN_12."</option>")." + <select name='mirror_order' class='form-control'>".$this->mirror_order_options_html($pref)." </select> </td> </tr> @@ -2226,6 +2257,45 @@ $columnInfo = array( </div> </div> <div class='tab-pane' id='core-download-download4'> + <div> + <p style='padding: 8px'> + ".LAN_DL_SECURITY_DESCRIPTION." + </p> + <table class='table adminform'> + <colgroup> + <col style='width:30%'/> + <col style='width:70%'/> + </colgroup> + <tr> + <td>".LAN_DL_SECURITY_MODE."</td> + <td>".$frm->select('download_security_mode', $this->security_options, $pref['download_security_mode'])."</td> + </tr> + <tbody id='nginx-secure_link_md5' ".($pref['download_security_mode'] === 'nginx-secure_link_md5' ? "" : "style='display:none'")."> + <tr> + <td>".LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION."</td> + <td> + ".$frm->text('download_security_expression', $pref['download_security_expression'], 1024)." + <div class='field-help'>".LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP."</div> + <small><a href='#' onclick='event.preventDefault();$(\"#supported-nginx-variables\").toggle();this.blur()'> + ".LAN_DL_SECURITY_NGINX_SUPPORTED_VARIABLES_TOGGLE." + </a></small> + <div id='supported-nginx-variables' style='display:none'> + ".$this->supported_secure_link_variables_html()." + </div> + </td> + </tr> + <tr> + <td>".LAN_DL_SECURITY_LINK_EXPIRY."</td> + <td> + ".$frm->text('download_security_link_expiry', $pref['download_security_link_expiry'], 16, array('pattern' => '\d+'))." + <div class='field-help'>".LAN_DL_SECURITY_LINK_EXPIRY_HELP."</div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + <div class='tab-pane' id='core-download-download5'> <div> <table class='table adminform'> <colgroup> @@ -2246,7 +2316,20 @@ $columnInfo = array( </div> </form> "; - // $ns->tablerender(LAN_DL_OPTIONS, $text); + + e107::js('footer-inline', " + $('#download-security-mode').on('change', function() { + var mode = $(this).val(); + + if (mode == 'nginx-secure_link_md5') { + $('#nginx-secure_link_md5').show('slow'); + return; + } + + $('#nginx-secure_link_md5').hide('slow'); + }); + "); + echo $text; } diff --git a/e107_plugins/download/languages/English/English_admin.php b/e107_plugins/download/languages/English/English_admin.php index 4f5f60ec2..a59d794dc 100644 --- a/e107_plugins/download/languages/English/English_admin.php +++ b/e107_plugins/download/languages/English/English_admin.php @@ -12,6 +12,7 @@ define("LAN_DL_OPTIONS", "Options"); //FIXME Use Generic define("LAN_DL_DOWNLOAD_OPT_GENERAL", "General"); define("LAN_DL_DOWNLOAD_OPT_BROKEN", "Reporting"); define("LAN_DL_DOWNLOAD_OPT_AGREE", "Agreements"); +define("LAN_DL_DOWNLOAD_OPT_SECURITY", "Protection"); define("LAN_DL_UPLOAD", "Upload"); //FIXME Use Generic define("LAN_DL_USE_PHP", "Use PHP"); define("LAN_DL_USE_PHP_INFO", "Checking this will send all download requests through PHP"); @@ -228,4 +229,17 @@ define("DOWLAN_HELP_10", "Help for upload options"); // define("DOWLAN_INSTALL_DONE", "Your download plugin is now installed"); // define("DOWLAN_DESCRIPTION", "This plugin is a fully featured Download system"); // define("DOWLAN_CAPTION", "Configure Download"); -?> + +define("LAN_DL_SECURITY_DESCRIPTION", "Downloads can make use of server-side URL protection features to prevent hotlinking and/or enforce link expiry. " . + "This section should be configured before the download server is configured to reduce the chance of disruption to downloaders."); +define("LAN_DL_SECURITY_MODE", "URL protection mode"); +define("LAN_DL_SECURITY_MODE_NONE", "None (Default)"); +define("LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5", "NGINX secure_link_md5"); +define("LAN_DL_SECURITY_NGINX_SUPPORTED_VARIABLES_TOGGLE", "Click to toggle list of supported NGINX variables"); +define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION", + "<a target='_blank' href='https://nginx.org/en/docs/http/ngx_http_secure_link_module.html#secure_link_md5'>NGINX secure_link_md5 expression</a>"); +define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP", "Same expression as configured on the server"); +define("LAN_DL_SECURITY_LINK_EXPIRY", "Duration of validity in seconds"); +define("LAN_DL_SECURITY_LINK_EXPIRY_HELP", "Number of seconds the download link should last after being generated. " . + "Only effective if the expression supports expiry time. " . + "Defaults to a very long time if this field is left blank."); \ No newline at end of file diff --git a/e107_plugins/download/plugin.xml b/e107_plugins/download/plugin.xml index 08dcdcb01..ece353f73 100755 --- a/e107_plugins/download/plugin.xml +++ b/e107_plugins/download/plugin.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> -<e107Plugin name="Downloads" lan="LAN_PLUGIN_DOWNLOAD_NAME" version="1.1" date="2017-04-27" compatibility="2.0" installRequired="true"> +<e107Plugin name="Downloads" lan="LAN_PLUGIN_DOWNLOAD_NAME" version="1.2" date="2018-05-01" compatibility="2.0" installRequired="true"> <author name="e107 Inc." url="http://e107.org" /> - <description lan="LAN_PLUGIN_DOWNLOAD_DIZ">This plugin is a fully featured File-download system</description> + <description lan="LAN_PLUGIN_DOWNLOAD_DIZ">This plugin is a fully featured file download system</description> <category>content</category> <adminLinks> <link url='admin_download.php' description='LAN_CONFIGURE' icon='images/downloads_32.png' iconSmall='images/downloads_16.png' primary='true' >DOWLAN_CAPTION</link> diff --git a/e107_plugins/download/request.php b/e107_plugins/download/request.php index fecf3c75c..afe4de188 100644 --- a/e107_plugins/download/request.php +++ b/e107_plugins/download/request.php @@ -72,7 +72,7 @@ if(strstr(e_QUERY, "mirror")) } $sql->update("download", "download_requested = download_requested + 1, download_mirror = '{$mstr}' WHERE download_id = '".intval($download_id)."'"); $sql->update("download_mirror", "mirror_count = mirror_count + 1 WHERE mirror_id = '".intval($mirror_id)."'"); - header("Location: {$gaddress}"); + header("Location: ".decorate_download_location($gaddress)); exit(); } @@ -189,7 +189,7 @@ if ($type == "file") $sql->update("download", "download_requested = download_requested + 1, download_mirror = '{$mstr}' WHERE download_id = '".intval($download_id)."'"); $sql->update("download_mirror", "mirror_count = mirror_count + 1 WHERE mirror_id = '".intval($mirror_id)."'"); - header("Location: ".$gaddress); + header("Location: ".decorate_download_location($gaddress)); exit(); } @@ -217,7 +217,7 @@ if ($type == "file") if (strstr($download_url, "http://") || strstr($download_url, "ftp://") || strstr($download_url, "https://")) { $download_url = e107::getParser()->parseTemplate($download_url,true); // support for shortcode-driven dynamic URLS. - e107::redirect($download_url); + e107::redirect(decorate_download_location($download_url)); // header("Location: {$download_url}"); exit(); } @@ -435,4 +435,12 @@ function check_download_limits() } } -?> +function decorate_download_location($url) +{ + $pref = e107::getPref(); + if ($pref['download_security_mode'] !== 'nginx-secure_link_md5') + return $url; + require_once(__DIR__."/handlers/NginxSecureLinkMd5Decorator.php"); + $decorator = new NginxSecureLinkMd5Decorator($url, $pref); + return $decorator->decorate(); +} \ No newline at end of file diff --git a/e107_plugins/download/vendor/shim_http_build_url.php b/e107_plugins/download/vendor/shim_http_build_url.php new file mode 100644 index 000000000..99b3337a3 --- /dev/null +++ b/e107_plugins/download/vendor/shim_http_build_url.php @@ -0,0 +1,104 @@ +<?php +if (!function_exists('http_build_url')) +{ + define('HTTP_URL_REPLACE', 1); // Replace every part of the first URL when there's one of the second URL + define('HTTP_URL_JOIN_PATH', 2); // Join relative paths + define('HTTP_URL_JOIN_QUERY', 4); // Join query strings + define('HTTP_URL_STRIP_USER', 8); // Strip any user authentication information + define('HTTP_URL_STRIP_PASS', 16); // Strip any password authentication information + define('HTTP_URL_STRIP_AUTH', 32); // Strip any authentication information + define('HTTP_URL_STRIP_PORT', 64); // Strip explicit port numbers + define('HTTP_URL_STRIP_PATH', 128); // Strip complete path + define('HTTP_URL_STRIP_QUERY', 256); // Strip query string + define('HTTP_URL_STRIP_FRAGMENT', 512); // Strip any fragments (#identifier) + define('HTTP_URL_STRIP_ALL', 1024); // Strip anything but scheme and host + + // Build an URL + // The parts of the second URL will be merged into the first according to the flags argument. + // + // @param mixed (Part(s) of) an URL in form of a string or associative array like parse_url() returns + // @param mixed Same as the first argument + // @param int A bitmask of binary or'ed HTTP_URL constants (Optional)HTTP_URL_REPLACE is the default + // @param array If set, it will be filled with the parts of the composed url like parse_url() would return + function http_build_url($url, $parts=array(), $flags=HTTP_URL_REPLACE, &$new_url=false) + { + $keys = array('user','pass','port','path','query','fragment'); + + // HTTP_URL_STRIP_ALL becomes all the HTTP_URL_STRIP_Xs + if ($flags & HTTP_URL_STRIP_ALL) + { + $flags |= HTTP_URL_STRIP_USER; + $flags |= HTTP_URL_STRIP_PASS; + $flags |= HTTP_URL_STRIP_PORT; + $flags |= HTTP_URL_STRIP_PATH; + $flags |= HTTP_URL_STRIP_QUERY; + $flags |= HTTP_URL_STRIP_FRAGMENT; + } + // HTTP_URL_STRIP_AUTH becomes HTTP_URL_STRIP_USER and HTTP_URL_STRIP_PASS + else if ($flags & HTTP_URL_STRIP_AUTH) + { + $flags |= HTTP_URL_STRIP_USER; + $flags |= HTTP_URL_STRIP_PASS; + } + + // Parse the original URL + $parse_url = !is_array($url) ? parse_url($url) : $url; + + // Scheme and Host are always replaced + if (isset($parts['scheme'])) + $parse_url['scheme'] = $parts['scheme']; + if (isset($parts['host'])) + $parse_url['host'] = $parts['host']; + + // (If applicable) Replace the original URL with it's new parts + if ($flags & HTTP_URL_REPLACE) + { + foreach ($keys as $key) + { + if (isset($parts[$key])) + $parse_url[$key] = $parts[$key]; + } + } + else + { + // Join the original URL path with the new path + if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) + { + if (isset($parse_url['path'])) + $parse_url['path'] = rtrim(str_replace(basename($parse_url['path']), '', $parse_url['path']), '/') . '/' . ltrim($parts['path'], '/'); + else + $parse_url['path'] = $parts['path']; + } + + // Join the original query string with the new query string + if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) + { + if (isset($parse_url['query'])) + $parse_url['query'] .= '&' . $parts['query']; + else + $parse_url['query'] = $parts['query']; + } + } + + // Strips all the applicable sections of the URL + // Note: Scheme and Host are never stripped + foreach ($keys as $key) + { + if ($flags & (int)constant('HTTP_URL_STRIP_' . strtoupper($key))) + unset($parse_url[$key]); + } + + + $new_url = $parse_url; + + return + ((isset($parse_url['scheme'])) ? $parse_url['scheme'] . '://' : '') + .((isset($parse_url['user'])) ? $parse_url['user'] . ((isset($parse_url['pass'])) ? ':' . $parse_url['pass'] : '') .'@' : '') + .((isset($parse_url['host'])) ? $parse_url['host'] : '') + .((isset($parse_url['port'])) ? ':' . $parse_url['port'] : '') + .((isset($parse_url['path'])) ? $parse_url['path'] : '') + .((isset($parse_url['query'])) ? '?' . $parse_url['query'] : '') + .((isset($parse_url['fragment'])) ? '#' . $parse_url['fragment'] : '') + ; + } +} diff --git a/e107_plugins/forum/forum_admin.php b/e107_plugins/forum/forum_admin.php index c39c1af50..102ed1e5a 100644 --- a/e107_plugins/forum/forum_admin.php +++ b/e107_plugins/forum/forum_admin.php @@ -116,7 +116,7 @@ if(!deftrue('OLD_FORUMADMIN')) protected $pid = 'forum_id'; protected $perPage = 30; protected $batchDelete = true; - // protected $batchCopy = true; + protected $batchCopy = true; protected $sortField = 'forum_order'; protected $sortParent = 'forum_parent'; protected $orderStep = 50; diff --git a/e107_plugins/forum/templates/forum_viewforum_template.php b/e107_plugins/forum/templates/forum_viewforum_template.php index 9c84889b5..77cf88cab 100644 --- a/e107_plugins/forum/templates/forum_viewforum_template.php +++ b/e107_plugins/forum/templates/forum_viewforum_template.php @@ -345,7 +345,7 @@ $FORUM_VIEWFORUM_TEMPLATE['divider-normal'] = "<tr><th colspan='2'>".LAN_FORUM_ $FORUM_VIEWFORUM_TEMPLATE['divider-important'] = "<tr><th colspan='2'>".LAN_FORUM_1006."</th><th class='text-center'>".LAN_FORUM_0003."</th><th class='hidden-xs text-center'>".LAN_FORUM_1005."</th><th class='hidden-xs'>".LAN_FORUM_0004."</th></tr>"; $FORUM_VIEWFORUM_TEMPLATE['divider-normal'] = "<tr><th colspan='2'>".LAN_FORUM_1007."</th><th class='text-center' >".LAN_FORUM_0003."</th><th class='hidden-xs text-center'>".LAN_FORUM_1005."</th><th class='hidden-xs'>".LAN_FORUM_0004."</th></tr>"; -$SC_WRAPPER['VIEWABLE_BY'] = "<div class='panel panel-default' style='margin-top:10px'><div class='panel-heading'>".LAN_FORUM_8012."</div><div class='panel-body'>{---}</div></div></div>"; +$SC_WRAPPER['VIEWABLE_BY'] = "<div class='panel panel-default' style='margin-top:10px'><div class='panel-heading'>".LAN_FORUM_8012."</div><div class='panel-body'>{---}</div></div>"; $FORUM_VIEWFORUM_TEMPLATE['footer'] = "</table> <div class='row row-fluid'> diff --git a/e107_plugins/tinymce4/e_footer.php b/e107_plugins/tinymce4/e_footer.php index 3c131bbd0..24c9c6dd7 100644 --- a/e107_plugins/tinymce4/e_footer.php +++ b/e107_plugins/tinymce4/e_footer.php @@ -23,7 +23,15 @@ if((e107::wysiwyg() === true && check_class($pref['post_html'])) || strpos(e_SEL // e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.3/tinymce.min.js'); - e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.8/tinymce.min.js'); + // e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.11/tinymce.min.js'); + /** + * tinymce 4.7.10 and newer do not work. + * Looks like an issue introduced with 4.7.10 + * Reverting back to 4.7.9 makes everything work in e107 + * Issue #3136 + */ + e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.9/tinymce.min.js'); + // e107::js('footer', "//cdn.tinymce.com/4/tinymce.min.js"); @@ -180,4 +188,4 @@ if((e107::wysiwyg() === true && check_class($pref['post_html'])) || strpos(e_SEL } -?> \ No newline at end of file +?> diff --git a/e107_plugins/tinymce4/langs/en.js b/e107_plugins/tinymce4/langs/en_GB.js similarity index 79% rename from e107_plugins/tinymce4/langs/en.js rename to e107_plugins/tinymce4/langs/en_GB.js index a588b8874..0f388fd7b 100644 --- a/e107_plugins/tinymce4/langs/en.js +++ b/e107_plugins/tinymce4/langs/en_GB.js @@ -1,8 +1,11 @@ tinymce.addI18n('en_GB',{ "Cut": "Cut", +"Heading 5": "Heading 5", "Header 2": "Header 2", "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.", +"Heading 4": "Heading 4", "Div": "Div", +"Heading 2": "Heading 2", "Paste": "Paste", "Close": "Close", "Font Family": "Font Family", @@ -11,6 +14,8 @@ tinymce.addI18n('en_GB',{ "New document": "New document", "Blockquote": "Blockquote", "Numbered list": "Numbered list", +"Heading 1": "Heading 1", +"Headings": "Headings", "Increase indent": "Increase indent", "Formats": "Formats", "Headers": "Headers", @@ -34,6 +39,8 @@ tinymce.addI18n('en_GB',{ "Italic": "Italic", "Align center": "Align centre", "Header 5": "Header 5", +"Heading 6": "Heading 6", +"Heading 3": "Heading 3", "Decrease indent": "Decrease indent", "Header 4": "Header 4", "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.", @@ -53,12 +60,20 @@ tinymce.addI18n('en_GB',{ "Upper Alpha": "Upper Alpha", "Upper Roman": "Upper Roman", "Lower Roman": "Lower Roman", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.", "Name": "Name", "Anchor": "Anchor", +"Id": "ID", "You have unsaved changes are you sure you want to navigate away?": "You have unsaved changes are you sure you want to navigate away?", "Restore last draft": "Restore last draft", "Special character": "Special character", "Source code": "Source code", +"Language": "Language", +"Insert\/Edit code sample": "Insert\/Edit code sample", +"B": "B", +"R": "R", +"G": "G", +"Color": "Colour", "Right to left": "Right to left", "Left to right": "Left to right", "Emoticons": "Emoticons", @@ -83,23 +98,48 @@ tinymce.addI18n('en_GB',{ "Style": "Style", "Dimensions": "Dimensions", "Insert image": "Insert image", +"Image": "Image", +"Zoom in": "Zoom in", +"Contrast": "Contrast", +"Back": "Back", +"Gamma": "Gamma", +"Flip horizontally": "Flip horizontally", +"Resize": "Resize", +"Sharpen": "Sharpen", +"Zoom out": "Zoom out", +"Image options": "Image options", +"Apply": "Apply", +"Brightness": "Brightness", +"Rotate clockwise": "Rotate clockwise", +"Rotate counterclockwise": "Rotate counterclockwise", +"Edit image": "Edit image", +"Color levels": "Colour levels", +"Crop": "Crop", +"Orientation": "Orientation", +"Flip vertically": "Flip vertically", +"Invert": "Invert", +"Date\/time": "Date\/time", "Insert date\/time": "Insert date\/time", "Remove link": "Remove link", "Url": "URL", "Text to display": "Text to display", "Anchors": "Anchors", "Insert link": "Insert link", +"Link": "Link", "New window": "New window", "None": "None", "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?", +"Paste or type a link": "Paste or type a link", "Target": "Target", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?", "Insert\/edit link": "Insert\/edit link", "Insert\/edit video": "Insert\/edit video", -"Poster": "Poster", +"Media": "Media", "Alternative source": "Alternative source", "Paste your embed code below:": "Paste your embed code below:", "Insert video": "Insert video", +"Poster": "Poster", +"Insert\/edit media": "Insert\/edit media", "Embed": "Embed", "Nonbreaking space": "Non-breaking space", "Page break": "Page break", @@ -121,11 +161,13 @@ tinymce.addI18n('en_GB',{ "Finish": "Finish", "Ignore all": "Ignore all", "Ignore": "Ignore", +"Add to Dictionary": "Add to Dictionary", "Insert row before": "Insert row before", "Rows": "Rows", "Height": "Height", "Paste row after": "Paste row after", "Alignment": "Alignment", +"Border color": "Border colour", "Column group": "Column group", "Row": "Row", "Insert column before": "Insert column before", @@ -141,15 +183,20 @@ tinymce.addI18n('en_GB',{ "Paste row before": "Paste row before", "Scope": "Scope", "Delete table": "Delete table", +"H Align": "H Align", +"Top": "Top", "Header cell": "Header cell", "Column": "Column", +"Row group": "Row group", "Cell": "Cell", -"Header": "Header", +"Middle": "Middle", "Cell type": "Cell type", "Copy row": "Copy row", "Row properties": "Row properties", "Table properties": "Table properties", -"Row group": "Row group", +"Bottom": "Bottom", +"V Align": "V Align", +"Header": "Header", "Right": "Right", "Insert column after": "Insert column after", "Cols": "Cols", @@ -164,7 +211,11 @@ tinymce.addI18n('en_GB',{ "Insert template": "Insert template", "Templates": "Templates", "Background color": "Background colour", +"Custom...": "Custom...", +"Custom color": "Custom colour", +"No color": "No colour", "Text color": "Text colour", +"Table of Contents": "Table of Contents", "Show blocks": "Show blocks", "Show invisible characters": "Show invisible characters", "Words: {0}": "Words: {0}", diff --git a/e107_plugins/tinymce4/plugins/bbcode/plugin.js b/e107_plugins/tinymce4/plugins/bbcode/plugin.js index b3ac04b80..10bb7cb9f 100644 --- a/e107_plugins/tinymce4/plugins/bbcode/plugin.js +++ b/e107_plugins/tinymce4/plugins/bbcode/plugin.js @@ -1,123 +1,101 @@ -/** - * plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ +(function () { +var bbcode = (function () { + 'use strict'; -/*global tinymce:true */ + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); -(function() { - tinymce.create('tinymce.plugins.BBCodePlugin', { - init : function(ed) { - var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase(); + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); - ed.on('beforeSetContent', function(e) { - e.content = t['_' + dialect + '_bbcode2html'](e.content); - }); + var html2bbcode = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi, '[url=$1]$2[/url]'); + rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi, '[color=$1]$2[/color]'); + rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, '[color=$1]$2[/color]'); + rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi, '[size=$1]$2[/size]'); + rep(/<font>(.*?)<\/font>/gi, '$1'); + rep(/<img.*?src=\"(.*?)\".*?\/>/gi, '[img]$1[/img]'); + rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi, '[code]$1[/code]'); + rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi, '[quote]$1[/quote]'); + rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi, '[code][b]$1[/b][/code]'); + rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi, '[quote][b]$1[/b][/quote]'); + rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi, '[code][i]$1[/i][/code]'); + rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi, '[quote][i]$1[/i][/quote]'); + rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi, '[code][u]$1[/u][/code]'); + rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi, '[quote][u]$1[/u][/quote]'); + rep(/<\/(strong|b)>/gi, '[/b]'); + rep(/<(strong|b)>/gi, '[b]'); + rep(/<\/(em|i)>/gi, '[/i]'); + rep(/<(em|i)>/gi, '[i]'); + rep(/<\/u>/gi, '[/u]'); + rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi, '[u]$1[/u]'); + rep(/<u>/gi, '[u]'); + rep(/<blockquote[^>]*>/gi, '[quote]'); + rep(/<\/blockquote>/gi, '[/quote]'); + rep(/<br \/>/gi, '\n'); + rep(/<br\/>/gi, '\n'); + rep(/<br>/gi, '\n'); + rep(/<p>/gi, ''); + rep(/<\/p>/gi, '\n'); + rep(/ |\u00a0/gi, ' '); + rep(/"/gi, '"'); + rep(/</gi, '<'); + rep(/>/gi, '>'); + rep(/&/gi, '&'); + return s; + }; + var bbcode2html = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/\n/gi, '<br />'); + rep(/\[b\]/gi, '<strong>'); + rep(/\[\/b\]/gi, '</strong>'); + rep(/\[i\]/gi, '<em>'); + rep(/\[\/i\]/gi, '</em>'); + rep(/\[u\]/gi, '<u>'); + rep(/\[\/u\]/gi, '</u>'); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi, '<a href="$1">$2</a>'); + rep(/\[url\](.*?)\[\/url\]/gi, '<a href="$1">$1</a>'); + rep(/\[img\](.*?)\[\/img\]/gi, '<img src="$1" />'); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi, '<font color="$1">$2</font>'); + rep(/\[code\](.*?)\[\/code\]/gi, '<span class="codeStyle">$1</span> '); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi, '<span class="quoteStyle">$1</span> '); + return s; + }; + var $_36akuw96jgqkwz4e = { + html2bbcode: html2bbcode, + bbcode2html: bbcode2html + }; - ed.on('postProcess', function(e) { - if (e.set) { - e.content = t['_' + dialect + '_bbcode2html'](e.content); - } + global.add('bbcode', function () { + return { + init: function (editor) { + editor.on('beforeSetContent', function (e) { + e.content = $_36akuw96jgqkwz4e.bbcode2html(e.content); + }); + editor.on('postProcess', function (e) { + if (e.set) { + e.content = $_36akuw96jgqkwz4e.bbcode2html(e.content); + } + if (e.get) { + e.content = $_36akuw96jgqkwz4e.html2bbcode(e.content); + } + }); + } + }; + }); + function Plugin () { + } - if (e.get) { - e.content = t['_' + dialect + '_html2bbcode'](e.content); - } - }); - }, + return Plugin; - getInfo: function() { - return { - longname: 'BBCode Plugin', - author: 'Moxiecode Systems AB', - authorurl: 'http://www.tinymce.com', - infourl: 'http://www.tinymce.com/wiki.php/Plugin:bbcode' - }; - }, - - // Private methods - - // HTML -> BBCode in PunBB dialect - _punbb_html2bbcode : function(s) { - s = tinymce.trim(s); - - function rep(re, str) { - s = s.replace(re, str); - } - - // example: <strong> to [b] - rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"); - rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); - rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); - rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); - rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); - rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"); - rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"); - rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"); - rep(/<font>(.*?)<\/font>/gi,"$1"); - rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"); - rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"); - rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"); - rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"); - rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"); - rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"); - rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"); - rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"); - rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"); - rep(/<\/(strong|b)>/gi,"[/b]"); - rep(/<(strong|b)>/gi,"[b]"); - rep(/<\/(em|i)>/gi,"[/i]"); - rep(/<(em|i)>/gi,"[i]"); - rep(/<\/u>/gi,"[/u]"); - rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"); - rep(/<u>/gi,"[u]"); - rep(/<blockquote[^>]*>/gi,"[quote]"); - rep(/<\/blockquote>/gi,"[/quote]"); - rep(/<br \/>/gi,"\n"); - rep(/<br\/>/gi,"\n"); - rep(/<br>/gi,"\n"); - rep(/<p>/gi,""); - rep(/<\/p>/gi,"\n"); - rep(/ |\u00a0/gi," "); - rep(/"/gi,"\""); - rep(/</gi,"<"); - rep(/>/gi,">"); - rep(/&/gi,"&"); - - return s; - }, - - // BBCode -> HTML from PunBB dialect - _punbb_bbcode2html : function(s) { - s = tinymce.trim(s); - - function rep(re, str) { - s = s.replace(re, str); - } - - // example: [b] to <strong> - rep(/\n/gi,"<br />"); - rep(/\[b\]/gi,"<strong>"); - rep(/\[\/b\]/gi,"</strong>"); - rep(/\[i\]/gi,"<em>"); - rep(/\[\/i\]/gi,"</em>"); - rep(/\[u\]/gi,"<u>"); - rep(/\[\/u\]/gi,"</u>"); - rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>"); - rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>"); - rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />"); - rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>"); - rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span> "); - rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span> "); - - return s; - } - }); - - // Register plugin - tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin); -})(); \ No newline at end of file +}()); +})(); diff --git a/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js b/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js index 70a88a7d6..b2b9d701c 100644 --- a/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js +++ b/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js @@ -1 +1 @@ -!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e){var t=this,n=e.getParam("bbcode_dialect","punbb").toLowerCase();e.on("beforeSetContent",function(e){e.content=t["_"+n+"_bbcode2html"](e.content)}),e.on("postProcess",function(e){e.set&&(e.content=t["_"+n+"_bbcode2html"](e.content)),e.get&&(e.content=t["_"+n+"_html2bbcode"](e.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),t(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),t(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),t(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),t(/<font>(.*?)<\/font>/gi,"$1"),t(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),t(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),t(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),t(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),t(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),t(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),t(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),t(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),t(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),t(/<\/(strong|b)>/gi,"[/b]"),t(/<(strong|b)>/gi,"[b]"),t(/<\/(em|i)>/gi,"[/i]"),t(/<(em|i)>/gi,"[i]"),t(/<\/u>/gi,"[/u]"),t(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),t(/<u>/gi,"[u]"),t(/<blockquote[^>]*>/gi,"[quote]"),t(/<\/blockquote>/gi,"[/quote]"),t(/<br \/>/gi,"\n"),t(/<br\/>/gi,"\n"),t(/<br>/gi,"\n"),t(/<p>/gi,""),t(/<\/p>/gi,"\n"),t(/ |\u00a0/gi," "),t(/"/gi,'"'),t(/</gi,"<"),t(/>/gi,">"),t(/&/gi,"&"),e},_punbb_bbcode2html:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/\n/gi,"<br />"),t(/\[b\]/gi,"<strong>"),t(/\[\/b\]/gi,"</strong>"),t(/\[i\]/gi,"<em>"),t(/\[\/i\]/gi,"</em>"),t(/\[u\]/gi,"<u>"),t(/\[\/u\]/gi,"</u>"),t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),t(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),t(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),t(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span> '),t(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span> '),e}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}(); \ No newline at end of file +!function(){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.util.Tools"),e=function(e){e=t.trim(e);var o=function(o,t){e=e.replace(o,t)};return o(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/<font>(.*?)<\/font>/gi,"$1"),o(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),o(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),o(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),o(/<u>/gi,"[u]"),o(/<blockquote[^>]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/<br \/>/gi,"\n"),o(/<br\/>/gi,"\n"),o(/<br>/gi,"\n"),o(/<p>/gi,""),o(/<\/p>/gi,"\n"),o(/ |\u00a0/gi," "),o(/"/gi,'"'),o(/</gi,"<"),o(/>/gi,">"),o(/&/gi,"&"),e},i=function(e){e=t.trim(e);var o=function(o,t){e=e.replace(o,t)};return o(/\n/gi,"<br />"),o(/\[b\]/gi,"<strong>"),o(/\[\/b\]/gi,"</strong>"),o(/\[i\]/gi,"<em>"),o(/\[\/i\]/gi,"</em>"),o(/\[u\]/gi,"<u>"),o(/\[\/u\]/gi,"</u>"),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),o(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),o(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),o(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span> '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span> '),e};o.add("bbcode",function(){return{init:function(o){o.on("beforeSetContent",function(o){o.content=i(o.content)}),o.on("postProcess",function(o){o.set&&(o.content=i(o.content)),o.get&&(o.content=e(o.content))})}}})}(); \ No newline at end of file diff --git a/e107_plugins/tinymce4/plugins/compat3x/plugin.js b/e107_plugins/tinymce4/plugins/compat3x/plugin.js index 85b2e0578..92d433edc 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/plugin.js +++ b/e107_plugins/tinymce4/plugins/compat3x/plugin.js @@ -1,8 +1,8 @@ /** * plugin.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -19,279 +19,304 @@ * - No editor.onEvent * - Can't cancel execCommands with beforeExecCommand */ -(function(tinymce) { - var reported; +(function (tinymce) { + var reported; - function noop() { - } + function noop() { + } - function log(apiCall) { - if (!reported && window && window.console) { - reported = true; - console.log("Deprecated TinyMCE API call: " + apiCall); - } - } + function log(apiCall) { + if (!reported && window && window.console) { + reported = true; + console.log("Deprecated TinyMCE API call: " + apiCall); + } + } - function Dispatcher(target, newEventName, argsMap, defaultScope) { - target = target || this; + function Dispatcher(target, newEventName, argsMap, defaultScope) { + target = target || this; + var cbs = []; - if (!newEventName) { - this.add = this.addToTop = this.remove = this.dispatch = noop; - return; - } + if (!newEventName) { + this.add = this.addToTop = this.remove = this.dispatch = noop; + return; + } - this.add = function(callback, scope, prepend) { - log('<target>.on' + newEventName + ".add(..)"); + this.add = function (callback, scope, prepend) { + log('<target>.on' + newEventName + ".add(..)"); - // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2) - function patchedEventCallback(e) { - var callbackArgs = []; + // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2) + function patchedEventCallback(e) { + var callbackArgs = []; - if (typeof argsMap == "string") { - argsMap = argsMap.split(" "); - } + if (typeof argsMap == "string") { + argsMap = argsMap.split(" "); + } - if (argsMap && typeof argsMap != "function") { - for (var i = 0; i < argsMap.length; i++) { - callbackArgs.push(e[argsMap[i]]); - } - } + if (argsMap && typeof argsMap !== "function") { + for (var i = 0; i < argsMap.length; i++) { + callbackArgs.push(e[argsMap[i]]); + } + } - if (typeof argsMap == "function") { - callbackArgs = argsMap(newEventName, e, target); - if (!callbackArgs) { - return; - } - } + if (typeof argsMap == "function") { + callbackArgs = argsMap(newEventName, e, target); + if (!callbackArgs) { + return; + } + } - if (!argsMap) { - callbackArgs = [e]; - } + if (!argsMap) { + callbackArgs = [e]; + } - callbackArgs.unshift(defaultScope || target); + callbackArgs.unshift(defaultScope || target); - if (callback.apply(scope || defaultScope || target, callbackArgs) === false) { - e.stopImmediatePropagation(); - } - } + if (callback.apply(scope || defaultScope || target, callbackArgs) === false) { + e.stopImmediatePropagation(); + } + } - target.on(newEventName, patchedEventCallback, prepend); + target.on(newEventName, patchedEventCallback, prepend); - return patchedEventCallback; - }; + var handlers = { + original: callback, + patched: patchedEventCallback + }; - this.addToTop = function(callback, scope) { - this.add(callback, scope, true); - }; + cbs.push(handlers); + return patchedEventCallback; + }; - this.remove = function(callback) { - return target.off(newEventName, callback); - }; + this.addToTop = function (callback, scope) { + this.add(callback, scope, true); + }; - this.dispatch = function() { - target.fire(newEventName); + this.remove = function (callback) { + cbs.forEach(function (item, i) { + if (item.original === callback) { + cbs.splice(i, 1); + return target.off(newEventName, item.patched); + } + }); - return true; - }; - } + return target.off(newEventName, callback); + }; - tinymce.util.Dispatcher = Dispatcher; - tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload"); - tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor"); - tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor"); + this.dispatch = function () { + target.fire(newEventName); + return true; + }; + } - tinymce.util.Cookie = { - get: noop, getHash: noop, remove: noop, set: noop, setHash: noop - }; + tinymce.util.Dispatcher = Dispatcher; + tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload"); + tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor"); + tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor"); - function patchEditor(editor) { - function patchEditorEvents(oldEventNames, argsMap) { - tinymce.each(oldEventNames.split(" "), function(oldName) { - editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap); - }); - } + tinymce.util.Cookie = { + get: noop, getHash: noop, remove: noop, set: noop, setHash: noop + }; - function convertUndoEventArgs(type, event, target) { - return [ - event.level, - target - ]; - } + function patchEditor(editor) { - function filterSelectionEvents(needsSelection) { - return function(type, e) { - if ((!e.selection && !needsSelection) || e.selection == needsSelection) { - return [e]; - } - }; - } + function translate(str) { + var prefix = editor.settings.language || "en"; + var prefixedStr = [prefix, str].join('.'); + var translatedStr = tinymce.i18n.translate(prefixedStr); - if (editor.controlManager) { - return; - } + return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str); + } - function cmNoop() { - var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' + - 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' + - 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' + - 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update'; + function patchEditorEvents(oldEventNames, argsMap) { + tinymce.each(oldEventNames.split(" "), function (oldName) { + editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap); + }); + } - log('editor.controlManager.*'); + function convertUndoEventArgs(type, event, target) { + return [ + event.level, + target + ]; + } - function _noop() { - return cmNoop(); - } + function filterSelectionEvents(needsSelection) { + return function (type, e) { + if ((!e.selection && !needsSelection) || e.selection == needsSelection) { + return [e]; + } + }; + } - tinymce.each(methods.split(' '), function(method) { - obj[method] = _noop; - }); + if (editor.controlManager) { + return; + } - return obj; - } + function cmNoop() { + var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' + + 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' + + 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' + + 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update'; - editor.controlManager = { - buttons: {}, + log('editor.controlManager.*'); - setDisabled: function(name, state) { - log("controlManager.setDisabled(..)"); + function _noop() { + return cmNoop(); + } - if (this.buttons[name]) { - this.buttons[name].disabled(state); - } - }, + tinymce.each(methods.split(' '), function (method) { + obj[method] = _noop; + }); - setActive: function(name, state) { - log("controlManager.setActive(..)"); + return obj; + } - if (this.buttons[name]) { - this.buttons[name].active(state); - } - }, + editor.controlManager = { + buttons: {}, - onAdd: new Dispatcher(), - onPostRender: new Dispatcher(), + setDisabled: function (name, state) { + log("controlManager.setDisabled(..)"); - add: function(obj) { - return obj; - }, - createButton: cmNoop, - createColorSplitButton: cmNoop, - createControl: cmNoop, - createDropMenu: cmNoop, - createListBox: cmNoop, - createMenuButton: cmNoop, - createSeparator: cmNoop, - createSplitButton: cmNoop, - createToolbar: cmNoop, - createToolbarGroup: cmNoop, - destroy: noop, - get: noop, - setControlType: cmNoop - }; + if (this.buttons[name]) { + this.buttons[name].disabled(state); + } + }, - patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor"); - patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"); - patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported - patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change"); - patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false)); - patchEditorEvents("SetProgressState", "state time"); - patchEditorEvents("VisualAid", "element hasVisual"); - patchEditorEvents("Undo Redo", convertUndoEventArgs); + setActive: function (name, state) { + log("controlManager.setActive(..)"); - patchEditorEvents("NodeChange", function(type, e) { - return [ - editor.controlManager, - e.element, - editor.selection.isCollapsed(), - e - ]; - }); + if (this.buttons[name]) { + this.buttons[name].active(state); + } + }, - var originalAddButton = editor.addButton; - editor.addButton = function(name, settings) { - var originalOnPostRender; + onAdd: new Dispatcher(), + onPostRender: new Dispatcher(), - function patchedPostRender() { - editor.controlManager.buttons[name] = this; + add: function (obj) { + return obj; + }, + createButton: cmNoop, + createColorSplitButton: cmNoop, + createControl: cmNoop, + createDropMenu: cmNoop, + createListBox: cmNoop, + createMenuButton: cmNoop, + createSeparator: cmNoop, + createSplitButton: cmNoop, + createToolbar: cmNoop, + createToolbarGroup: cmNoop, + destroy: noop, + get: noop, + setControlType: cmNoop + }; - if (originalOnPostRender) { - return originalOnPostRender.call(this); - } - } + patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor"); + patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"); + patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported + patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change"); + patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false)); + patchEditorEvents("SetProgressState", "state time"); + patchEditorEvents("VisualAid", "element hasVisual"); + patchEditorEvents("Undo Redo", convertUndoEventArgs); - for (var key in settings) { - if (key.toLowerCase() === "onpostrender") { - originalOnPostRender = settings[key]; - settings.onPostRender = patchedPostRender; - } - } + patchEditorEvents("NodeChange", function (type, e) { + return [ + editor.controlManager, + e.element, + editor.selection.isCollapsed(), + e + ]; + }); - if (!originalOnPostRender) { - settings.onPostRender = patchedPostRender; - } + var originalAddButton = editor.addButton; + editor.addButton = function (name, settings) { + var originalOnPostRender; - if (settings.title) { - settings.title = tinymce.i18n.translate((editor.settings.language || "en") + "." + settings.title); - } + function patchedPostRender() { + editor.controlManager.buttons[name] = this; - return originalAddButton.call(this, name, settings); - }; + if (originalOnPostRender) { + return originalOnPostRender.apply(this, arguments); + } + } - editor.on('init', function() { - var undoManager = editor.undoManager, selection = editor.selection; + for (var key in settings) { + if (key.toLowerCase() === "onpostrender") { + originalOnPostRender = settings[key]; + settings.onPostRender = patchedPostRender; + } + } - undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager); - undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager); - undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager); - undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager); + if (!originalOnPostRender) { + settings.onPostRender = patchedPostRender; + } - selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection); - selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection); - selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection); - selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection); - }); + if (settings.title) { + settings.title = translate(settings.title); + } - editor.on('BeforeRenderUI', function() { - var windowManager = editor.windowManager; + return originalAddButton.call(this, name, settings); + }; - windowManager.onOpen = new Dispatcher(); - windowManager.onClose = new Dispatcher(); - windowManager.createInstance = function(className, a, b, c, d, e) { - log("windowManager.createInstance(..)"); + editor.on('init', function () { + var undoManager = editor.undoManager, selection = editor.selection; - var constr = tinymce.resolve(className); - return new constr(a, b, c, d, e); - }; - }); - } + undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager); + undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager); + undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager); + undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager); - tinymce.on('SetupEditor', patchEditor); - tinymce.PluginManager.add("compat3x", patchEditor); + selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection); + selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection); + selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection); + selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection); + }); - tinymce.addI18n = function(prefix, o) { - var I18n = tinymce.util.I18n, each = tinymce.each; + editor.on('BeforeRenderUI', function () { + var windowManager = editor.windowManager; - if (typeof prefix == "string" && prefix.indexOf('.') === -1) { - I18n.add(prefix, o); - return; - } + windowManager.onOpen = new Dispatcher(); + windowManager.onClose = new Dispatcher(); + windowManager.createInstance = function (className, a, b, c, d, e) { + log("windowManager.createInstance(..)"); - if (!tinymce.is(prefix, 'string')) { - each(prefix, function(o, lc) { - each(o, function(o, g) { - each(o, function(o, k) { - if (g === 'common') { - I18n.data[lc + '.' + k] = o; - } else { - I18n.data[lc + '.' + g + '.' + k] = o; - } - }); - }); - }); - } else { - each(o, function(o, k) { - I18n.data[prefix + '.' + k] = o; - }); - } - }; + var constr = tinymce.resolve(className); + return new constr(a, b, c, d, e); + }; + }); + } + + tinymce.on('SetupEditor', function (e) { + patchEditor(e.editor); + }); + + tinymce.PluginManager.add("compat3x", patchEditor); + + tinymce.addI18n = function (prefix, o) { + var I18n = tinymce.util.I18n, each = tinymce.each; + + if (typeof prefix == "string" && prefix.indexOf('.') === -1) { + I18n.add(prefix, o); + return; + } + + if (!tinymce.is(prefix, 'string')) { + each(prefix, function (o, lc) { + each(o, function (o, g) { + each(o, function (o, k) { + if (g === 'common') { + I18n.data[lc + '.' + k] = o; + } else { + I18n.data[lc + '.' + g + '.' + k] = o; + } + }); + }); + }); + } else { + each(o, function (o, k) { + I18n.data[prefix + '.' + k] = o; + }); + } + }; })(tinymce); diff --git a/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js b/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js index d9fee4629..8562cb7c7 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js +++ b/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js @@ -1 +1 @@ -!function(a){function b(){}function c(a){!f&&window&&window.console&&(f=!0,console.log("Deprecated TinyMCE API call: "+a))}function d(a,d,e,f){return a=a||this,d?(this.add=function(b,g,h){function i(c){var h=[];if("string"==typeof e&&(e=e.split(" ")),e&&"function"!=typeof e)for(var i=0;i<e.length;i++)h.push(c[e[i]]);("function"!=typeof e||(h=e(d,c,a)))&&(e||(h=[c]),h.unshift(f||a),b.apply(g||f||a,h)===!1&&c.stopImmediatePropagation())}return c("<target>.on"+d+".add(..)"),a.on(d,i,h),i},this.addToTop=function(a,b){this.add(a,b,!0)},this.remove=function(b){return a.off(d,b)},void(this.dispatch=function(){return a.fire(d),!0})):void(this.add=this.addToTop=this.remove=this.dispatch=b)}function e(e){function f(b,c){a.each(b.split(" "),function(a){e["on"+a]=new d(e,a,c)})}function g(a,b,c){return[b.level,c]}function h(a){return function(b,c){return!c.selection&&!a||c.selection==a?[c]:void 0}}function i(){function b(){return i()}var d={},e="add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update";return c("editor.controlManager.*"),a.each(e.split(" "),function(a){d[a]=b}),d}if(!e.controlManager){e.controlManager={buttons:{},setDisabled:function(a,b){c("controlManager.setDisabled(..)"),this.buttons[a]&&this.buttons[a].disabled(b)},setActive:function(a,b){c("controlManager.setActive(..)"),this.buttons[a]&&this.buttons[a].active(b)},onAdd:new d,onPostRender:new d,add:function(a){return a},createButton:i,createColorSplitButton:i,createControl:i,createDropMenu:i,createListBox:i,createMenuButton:i,createSeparator:i,createSplitButton:i,createToolbar:i,createToolbarGroup:i,destroy:b,get:b,setControlType:i},f("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),f("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),f("BeforeExecCommand ExecCommand","command ui value args"),f("PreProcess PostProcess LoadContent SaveContent Change"),f("BeforeSetContent BeforeGetContent SetContent GetContent",h(!1)),f("SetProgressState","state time"),f("VisualAid","element hasVisual"),f("Undo Redo",g),f("NodeChange",function(a,b){return[e.controlManager,b.element,e.selection.isCollapsed(),b]});var j=e.addButton;e.addButton=function(b,c){function d(){return e.controlManager.buttons[b]=this,f?f.call(this):void 0}var f;for(var g in c)"onpostrender"===g.toLowerCase()&&(f=c[g],c.onPostRender=d);return f||(c.onPostRender=d),c.title&&(c.title=a.i18n.translate((e.settings.language||"en")+"."+c.title)),j.call(this,b,c)},e.on("init",function(){var a=e.undoManager,b=e.selection;a.onUndo=new d(e,"Undo",g,null,a),a.onRedo=new d(e,"Redo",g,null,a),a.onBeforeAdd=new d(e,"BeforeAddUndo",null,a),a.onAdd=new d(e,"AddUndo",null,a),b.onBeforeGetContent=new d(e,"BeforeGetContent",h(!0),b),b.onGetContent=new d(e,"GetContent",h(!0),b),b.onBeforeSetContent=new d(e,"BeforeSetContent",h(!0),b),b.onSetContent=new d(e,"SetContent",h(!0),b)}),e.on("BeforeRenderUI",function(){var b=e.windowManager;b.onOpen=new d,b.onClose=new d,b.createInstance=function(b,d,e,f,g,h){c("windowManager.createInstance(..)");var i=a.resolve(b);return new i(d,e,f,g,h)}})}}var f;a.util.Dispatcher=d,a.onBeforeUnload=new d(a,"BeforeUnload"),a.onAddEditor=new d(a,"AddEditor","editor"),a.onRemoveEditor=new d(a,"RemoveEditor","editor"),a.util.Cookie={get:b,getHash:b,remove:b,set:b,setHash:b},a.on("SetupEditor",e),a.PluginManager.add("compat3x",e),a.addI18n=function(b,c){var d=a.util.I18n,e=a.each;return"string"==typeof b&&-1===b.indexOf(".")?void d.add(b,c):void(a.is(b,"string")?e(c,function(a,c){d.data[b+"."+c]=a}):e(b,function(a,b){e(a,function(a,c){e(a,function(a,e){"common"===c?d.data[b+"."+e]=a:d.data[b+"."+c+"."+e]=a})})}))}}(tinymce); \ No newline at end of file +!function(u){var t;function l(){}function f(e){!t&&window&&window.console&&(t=!0,console.log("Deprecated TinyMCE API call: "+e))}function i(i,a,d,s){i=i||this;var c=[];a?(this.add=function(o,r,e){function t(e){var t=[];if("string"==typeof d&&(d=d.split(" ")),d&&"function"!=typeof d)for(var n=0;n<d.length;n++)t.push(e[d[n]]);("function"!=typeof d||(t=d(a,e,i)))&&(d||(t=[e]),t.unshift(s||i),!1===o.apply(r||s||i,t)&&e.stopImmediatePropagation())}f("<target>.on"+a+".add(..)"),i.on(a,t,e);var n={original:o,patched:t};return c.push(n),t},this.addToTop=function(e,t){this.add(e,t,!0)},this.remove=function(n){return c.forEach(function(e,t){if(e.original===n)return c.splice(t,1),i.off(a,e.patched)}),i.off(a,n)},this.dispatch=function(){return i.fire(a),!0}):this.add=this.addToTop=this.remove=this.dispatch=l}function n(s){function e(e,t){u.each(e.split(" "),function(e){s["on"+e]=new i(s,e,t)})}function n(e,t,n){return[t.level,n]}function o(n){return function(e,t){if(!t.selection&&!n||t.selection==n)return[t]}}if(!s.controlManager){s.controlManager={buttons:{},setDisabled:function(e,t){f("controlManager.setDisabled(..)"),this.buttons[e]&&this.buttons[e].disabled(t)},setActive:function(e,t){f("controlManager.setActive(..)"),this.buttons[e]&&this.buttons[e].active(t)},onAdd:new i,onPostRender:new i,add:function(e){return e},createButton:r,createColorSplitButton:r,createControl:r,createDropMenu:r,createListBox:r,createMenuButton:r,createSeparator:r,createSplitButton:r,createToolbar:r,createToolbarGroup:r,destroy:l,get:l,setControlType:r},e("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),e("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),e("BeforeExecCommand ExecCommand","command ui value args"),e("PreProcess PostProcess LoadContent SaveContent Change"),e("BeforeSetContent BeforeGetContent SetContent GetContent",o(!1)),e("SetProgressState","state time"),e("VisualAid","element hasVisual"),e("Undo Redo",n),e("NodeChange",function(e,t){return[s.controlManager,t.element,s.selection.isCollapsed(),t]});var c=s.addButton;s.addButton=function(e,t){var n,o,r,i;function a(){if(s.controlManager.buttons[e]=this,n)return n.apply(this,arguments)}for(var d in t)"onpostrender"===d.toLowerCase()&&(n=t[d],t.onPostRender=a);return n||(t.onPostRender=a),t.title&&(t.title=(o=t.title,r=[s.settings.language||"en",o].join("."),i=u.i18n.translate(r),r!==i?i:u.i18n.translate(o))),c.call(this,e,t)},s.on("init",function(){var e=s.undoManager,t=s.selection;e.onUndo=new i(s,"Undo",n,null,e),e.onRedo=new i(s,"Redo",n,null,e),e.onBeforeAdd=new i(s,"BeforeAddUndo",null,e),e.onAdd=new i(s,"AddUndo",null,e),t.onBeforeGetContent=new i(s,"BeforeGetContent",o(!0),t),t.onGetContent=new i(s,"GetContent",o(!0),t),t.onBeforeSetContent=new i(s,"BeforeSetContent",o(!0),t),t.onSetContent=new i(s,"SetContent",o(!0),t)}),s.on("BeforeRenderUI",function(){var e=s.windowManager;e.onOpen=new i,e.onClose=new i,e.createInstance=function(e,t,n,o,r,i){return f("windowManager.createInstance(..)"),new(u.resolve(e))(t,n,o,r,i)}})}function r(){var t={};function n(){return r()}return f("editor.controlManager.*"),u.each("add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update".split(" "),function(e){t[e]=n}),t}}u.util.Dispatcher=i,u.onBeforeUnload=new i(u,"BeforeUnload"),u.onAddEditor=new i(u,"AddEditor","editor"),u.onRemoveEditor=new i(u,"RemoveEditor","editor"),u.util.Cookie={get:l,getHash:l,remove:l,set:l,setHash:l},u.on("SetupEditor",function(e){n(e.editor)}),u.PluginManager.add("compat3x",n),u.addI18n=function(n,e){var r=u.util.I18n,t=u.each;"string"!=typeof n||-1!==n.indexOf(".")?u.is(n,"string")?t(e,function(e,t){r.data[n+"."+t]=e}):t(n,function(e,o){t(e,function(e,n){t(e,function(e,t){"common"===n?r.data[o+"."+t]=e:r.data[o+"."+n+"."+t]=e})})}):r.add(n,e)}}(tinymce); \ No newline at end of file diff --git a/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js b/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js index 733f4397e..92e87effe 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js +++ b/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js @@ -1,8 +1,8 @@ /** - * Popup.js + * tinymce_mce_popup.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -19,524 +19,524 @@ var tinymce, tinyMCE; * @class tinyMCEPopup */ var tinyMCEPopup = { - /** - * Initializes the popup this will be called automatically. - * - * @method init - */ - init: function() { - var self = this, parentWin, settings, uiWindow; - - // Find window & API - parentWin = self.getWin(); - tinymce = tinyMCE = parentWin.tinymce; - self.editor = tinymce.EditorManager.activeEditor; - self.params = self.editor.windowManager.getParams(); - - uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1]; - self.features = uiWindow.features; - self.uiWindow = uiWindow; - - settings = self.editor.settings; - - // Setup popup CSS path(s) - if (settings.popup_css !== false) { - if (settings.popup_css) { - settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css); - } else { - settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css"); - } - } - - if (settings.popup_css_add) { - settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add); - } - - // Setup local DOM - self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, { - ownEvents: true, - proxy: tinyMCEPopup._eventProxy - }); - - self.dom.bind(window, 'ready', self._onDOMLoaded, self); - - // Enables you to skip loading the default css - if (self.features.popup_css !== false) { - self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css); - } - - // Setup on init listeners - self.listeners = []; - - /** - * Fires when the popup is initialized. - * - * @event onInit - * @param {tinymce.Editor} editor Editor instance. - * @example - * // Alerts the selected contents when the dialog is loaded - * tinyMCEPopup.onInit.add(function(ed) { - * alert(ed.selection.getContent()); - * }); - * - * // Executes the init method on page load in some object using the SomeObject scope - * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); - */ - self.onInit = { - add: function(func, scope) { - self.listeners.push({func : func, scope : scope}); - } - }; - - self.isWindow = !self.getWindowArg('mce_inline'); - self.id = self.getWindowArg('mce_window_id'); - }, - - /** - * Returns the reference to the parent window that opened the dialog. - * - * @method getWin - * @return {Window} Reference to the parent window that opened the dialog. - */ - getWin: function() { - // Added frameElement check to fix bug: #2817583 - return (!window.frameElement && window.dialogArguments) || opener || parent || top; - }, - - /** - * Returns a window argument/parameter by name. - * - * @method getWindowArg - * @param {String} name Name of the window argument to retrive. - * @param {String} defaultValue Optional default value to return. - * @return {String} Argument value or default value if it wasn't found. - */ - getWindowArg : function(name, defaultValue) { - var value = this.params[name]; - - return tinymce.is(value) ? value : defaultValue; - }, - - /** - * Returns a editor parameter/config option value. - * - * @method getParam - * @param {String} name Name of the editor config option to retrive. - * @param {String} defaultValue Optional default value to return. - * @return {String} Parameter value or default value if it wasn't found. - */ - getParam : function(name, defaultValue) { - return this.editor.getParam(name, defaultValue); - }, - - /** - * Returns a language item by key. - * - * @method getLang - * @param {String} name Language item like mydialog.something. - * @param {String} defaultValue Optional default value to return. - * @return {String} Language value for the item like "my string" or the default value if it wasn't found. - */ - getLang : function(name, defaultValue) { - return this.editor.getLang(name, defaultValue); - }, - - /** - * Executed a command on editor that opened the dialog/popup. - * - * @method execCommand - * @param {String} cmd Command to execute. - * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. - * @param {Object} val Optional value to pass with the comman like an URL. - * @param {Object} a Optional arguments object. - */ - execCommand : function(cmd, ui, val, args) { - args = args || {}; - args.skip_focus = 1; - - this.restoreSelection(); - return this.editor.execCommand(cmd, ui, val, args); - }, - - /** - * Resizes the dialog to the inner size of the window. This is needed since various browsers - * have different border sizes on windows. - * - * @method resizeToInnerSize - */ - resizeToInnerSize : function() { - /*var self = this; - - // Detach it to workaround a Chrome specific bug - // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 - setTimeout(function() { - var vp = self.dom.getViewPort(window); - - self.editor.windowManager.resizeBy( - self.getWindowArg('mce_width') - vp.w, - self.getWindowArg('mce_height') - vp.h, - self.id || window - ); - }, 10);*/ - }, - - /** - * Will executed the specified string when the page has been loaded. This function - * was added for compatibility with the 2.x branch. - * - * @method executeOnLoad - * @param {String} evil String to evalutate on init. - */ - executeOnLoad : function(evil) { - this.onInit.add(function() { - eval(evil); - }); - }, - - /** - * Stores the current editor selection for later restoration. This can be useful since some browsers - * looses it's selection if a control element is selected/focused inside the dialogs. - * - * @method storeSelection - */ - storeSelection : function() { - this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); - }, - - /** - * Restores any stored selection. This can be useful since some browsers - * looses it's selection if a control element is selected/focused inside the dialogs. - * - * @method restoreSelection - */ - restoreSelection : function() { - var self = tinyMCEPopup; - - if (!self.isWindow && tinymce.isIE) { - self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark); - } - }, - - /** - * Loads a specific dialog language pack. If you pass in plugin_url as a argument - * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file. - * - * @method requireLangPack - */ - requireLangPack : function() { - var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang; - - if (settings.language !== false) { - lang = settings.language || "en"; - } - - if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) { - url += '/langs/' + lang + '_dlg.js'; - - if (!tinymce.ScriptLoader.isDone(url)) { - document.write('<script type="text/javascript" src="' + url + '"></script>'); - tinymce.ScriptLoader.markDone(url); - } - } - }, - - /** - * Executes a color picker on the specified element id. When the user - * then selects a color it will be set as the value of the specified element. - * - * @method pickColor - * @param {DOMEvent} e DOM event object. - * @param {string} element_id Element id to be filled with the color value from the picker. - */ - pickColor : function(e, element_id) { - var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback; - if (colorPickerCallback) { - colorPickerCallback.call( - this.editor, - function (value) { - el.value = value; - try { - el.onchange(); - } catch (ex) { - // Try fire event, ignore errors - } - }, - el.value - ); - } - }, - - /** - * Opens a filebrowser/imagebrowser this will set the output value from - * the browser as a value on the specified element. - * - * @method openBrowser - * @param {string} element_id Id of the element to set value in. - * @param {string} type Type of browser to open image/file/flash. - * @param {string} option Option name to get the file_broswer_callback function name from. - */ - openBrowser : function(element_id, type) { - tinyMCEPopup.restoreSelection(); - this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); - }, - - /** - * Creates a confirm dialog. Please don't use the blocking behavior of this - * native version use the callback method instead then it can be extended. - * - * @method confirm - * @param {String} t Title for the new confirm dialog. - * @param {function} cb Callback function to be executed after the user has selected ok or cancel. - * @param {Object} s Optional scope to execute the callback in. - */ - confirm : function(t, cb, s) { - this.editor.windowManager.confirm(t, cb, s, window); - }, - - /** - * Creates a alert dialog. Please don't use the blocking behavior of this - * native version use the callback method instead then it can be extended. - * - * @method alert - * @param {String} tx Title for the new alert dialog. - * @param {function} cb Callback function to be executed after the user has selected ok. - * @param {Object} s Optional scope to execute the callback in. - */ - alert : function(tx, cb, s) { - this.editor.windowManager.alert(tx, cb, s, window); - }, - - /** - * Closes the current window. - * - * @method close - */ - close : function() { - var t = this; - - // To avoid domain relaxing issue in Opera - function close() { - t.editor.windowManager.close(window); - tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup - } - - if (tinymce.isOpera) { - t.getWin().setTimeout(close, 0); - } else { - close(); - } - }, - - // Internal functions - - _restoreSelection : function() { - var e = window.event.srcElement; - - if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) { - tinyMCEPopup.restoreSelection(); - } - }, - -/* _restoreSelection : function() { - var e = window.event.srcElement; - - // If user focus a non text input or textarea - if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') - tinyMCEPopup.restoreSelection(); - },*/ - - _onDOMLoaded : function() { - var t = tinyMCEPopup, ti = document.title, h, nv; - - // Translate page - if (t.features.translate_i18n !== false) { - var map = { - "update": "Ok", - "insert": "Ok", - "cancel": "Cancel", - "not_set": "--", - "class_name": "Class name", - "browse": "Browse" - }; - - var langCode = tinymce.settings.language || 'en'; - for (var key in map) { - tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]); - } - - h = document.body.innerHTML; - - // Replace a=x with a="x" in IE - if (tinymce.isIE) { - h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"'); - } - - document.dir = t.editor.getParam('directionality',''); - - if ((nv = t.editor.translate(h)) && nv != h) { - document.body.innerHTML = nv; - } - - if ((nv = t.editor.translate(ti)) && nv != ti) { - document.title = ti = nv; - } - } - - if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) { - t.dom.addClass(document.body, 'forceColors'); - } - - document.body.style.display = ''; - - // Restore selection in IE when focus is placed on a non textarea or input element of the type text - if (tinymce.Env.ie) { - if (tinymce.Env.ie < 11) { - document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); - - // Add base target element for it since it would fail with modal dialogs - t.dom.add(t.dom.select('head')[0], 'base', {target: '_self'}); - } else { - document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false); - } - } - - t.restoreSelection(); - t.resizeToInnerSize(); - - // Set inline title - if (!t.isWindow) { - t.editor.windowManager.setTitle(window, ti); - } else { - window.focus(); - } - - if (!tinymce.isIE && !t.isWindow) { - t.dom.bind(document, 'focus', function() { - t.editor.windowManager.focus(t.id); - }); - } - - // Patch for accessibility - tinymce.each(t.dom.select('select'), function(e) { - e.onkeydown = tinyMCEPopup._accessHandler; - }); - - // Call onInit - // Init must be called before focus so the selection won't get lost by the focus call - tinymce.each(t.listeners, function(o) { - o.func.call(o.scope, t.editor); - }); - - // Move focus to window - if (t.getWindowArg('mce_auto_focus', true)) { - window.focus(); - - // Focus element with mceFocus class - tinymce.each(document.forms, function(f) { - tinymce.each(f.elements, function(e) { - if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { - e.focus(); - return false; // Break loop - } - }); - }); - } - - document.onkeyup = tinyMCEPopup._closeWinKeyHandler; - - if ('textContent' in document) { - t.uiWindow.getEl('head').firstChild.textContent = document.title; - } else { - t.uiWindow.getEl('head').firstChild.innerText = document.title; - } - }, - - _accessHandler : function(e) { - e = e || window.event; - - if (e.keyCode == 13 || e.keyCode == 32) { - var elm = e.target || e.srcElement; - - if (elm.onchange) { - elm.onchange(); - } - - return tinymce.dom.Event.cancel(e); - } - }, - - _closeWinKeyHandler : function(e) { - e = e || window.event; - - if (e.keyCode == 27) { - tinyMCEPopup.close(); - } - }, - - _eventProxy: function(id) { - return function(evt) { - tinyMCEPopup.dom.events.callNativeHandler(id, evt); - }; - } + /** + * Initializes the popup this will be called automatically. + * + * @method init + */ + init: function () { + var self = this, parentWin, settings, uiWindow; + + // Find window & API + parentWin = self.getWin(); + tinymce = tinyMCE = parentWin.tinymce; + self.editor = tinymce.EditorManager.activeEditor; + self.params = self.editor.windowManager.getParams(); + + uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1]; + self.features = uiWindow.features; + self.uiWindow = uiWindow; + + settings = self.editor.settings; + + // Setup popup CSS path(s) + if (settings.popup_css !== false) { + if (settings.popup_css) { + settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css); + } else { + settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css"); + } + } + + if (settings.popup_css_add) { + settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add); + } + + // Setup local DOM + self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, { + ownEvents: true, + proxy: tinyMCEPopup._eventProxy + }); + + self.dom.bind(window, 'ready', self._onDOMLoaded, self); + + // Enables you to skip loading the default css + if (self.features.popup_css !== false) { + self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css); + } + + // Setup on init listeners + self.listeners = []; + + /** + * Fires when the popup is initialized. + * + * @event onInit + * @param {tinymce.Editor} editor Editor instance. + * @example + * // Alerts the selected contents when the dialog is loaded + * tinyMCEPopup.onInit.add(function(ed) { + * alert(ed.selection.getContent()); + * }); + * + * // Executes the init method on page load in some object using the SomeObject scope + * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); + */ + self.onInit = { + add: function (func, scope) { + self.listeners.push({ func: func, scope: scope }); + } + }; + + self.isWindow = !self.getWindowArg('mce_inline'); + self.id = self.getWindowArg('mce_window_id'); + }, + + /** + * Returns the reference to the parent window that opened the dialog. + * + * @method getWin + * @return {Window} Reference to the parent window that opened the dialog. + */ + getWin: function () { + // Added frameElement check to fix bug: #2817583 + return (!window.frameElement && window.dialogArguments) || opener || parent || top; + }, + + /** + * Returns a window argument/parameter by name. + * + * @method getWindowArg + * @param {String} name Name of the window argument to retrieve. + * @param {String} defaultValue Optional default value to return. + * @return {String} Argument value or default value if it wasn't found. + */ + getWindowArg: function (name, defaultValue) { + var value = this.params[name]; + + return tinymce.is(value) ? value : defaultValue; + }, + + /** + * Returns a editor parameter/config option value. + * + * @method getParam + * @param {String} name Name of the editor config option to retrieve. + * @param {String} defaultValue Optional default value to return. + * @return {String} Parameter value or default value if it wasn't found. + */ + getParam: function (name, defaultValue) { + return this.editor.getParam(name, defaultValue); + }, + + /** + * Returns a language item by key. + * + * @method getLang + * @param {String} name Language item like mydialog.something. + * @param {String} defaultValue Optional default value to return. + * @return {String} Language value for the item like "my string" or the default value if it wasn't found. + */ + getLang: function (name, defaultValue) { + return this.editor.getLang(name, defaultValue); + }, + + /** + * Executed a command on editor that opened the dialog/popup. + * + * @method execCommand + * @param {String} cmd Command to execute. + * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. + * @param {Object} val Optional value to pass with the comman like an URL. + * @param {Object} a Optional arguments object. + */ + execCommand: function (cmd, ui, val, args) { + args = args || {}; + args.skip_focus = 1; + + this.restoreSelection(); + return this.editor.execCommand(cmd, ui, val, args); + }, + + /** + * Resizes the dialog to the inner size of the window. This is needed since various browsers + * have different border sizes on windows. + * + * @method resizeToInnerSize + */ + resizeToInnerSize: function () { + /*var self = this; + + // Detach it to workaround a Chrome specific bug + // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 + setTimeout(function() { + var vp = self.dom.getViewPort(window); + + self.editor.windowManager.resizeBy( + self.getWindowArg('mce_width') - vp.w, + self.getWindowArg('mce_height') - vp.h, + self.id || window + ); + }, 10);*/ + }, + + /** + * Will executed the specified string when the page has been loaded. This function + * was added for compatibility with the 2.x branch. + * + * @method executeOnLoad + * @param {String} evil String to evalutate on init. + */ + executeOnLoad: function (evil) { + this.onInit.add(function () { + eval(evil); + }); + }, + + /** + * Stores the current editor selection for later restoration. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method storeSelection + */ + storeSelection: function () { + this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); + }, + + /** + * Restores any stored selection. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method restoreSelection + */ + restoreSelection: function () { + var self = tinyMCEPopup; + + if (!self.isWindow && tinymce.isIE) { + self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark); + } + }, + + /** + * Loads a specific dialog language pack. If you pass in plugin_url as a argument + * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file. + * + * @method requireLangPack + */ + requireLangPack: function () { + var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang; + + if (settings.language !== false) { + lang = settings.language || "en"; + } + + if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) { + url += '/langs/' + lang + '_dlg.js'; + + if (!tinymce.ScriptLoader.isDone(url)) { + document.write('<script type="text/javascript" src="' + url + '"></script>'); + tinymce.ScriptLoader.markDone(url); + } + } + }, + + /** + * Executes a color picker on the specified element id. When the user + * then selects a color it will be set as the value of the specified element. + * + * @method pickColor + * @param {DOMEvent} e DOM event object. + * @param {string} element_id Element id to be filled with the color value from the picker. + */ + pickColor: function (e, element_id) { + var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback; + if (colorPickerCallback) { + colorPickerCallback.call( + this.editor, + function (value) { + el.value = value; + try { + el.onchange(); + } catch (ex) { + // Try fire event, ignore errors + } + }, + el.value + ); + } + }, + + /** + * Opens a filebrowser/imagebrowser this will set the output value from + * the browser as a value on the specified element. + * + * @method openBrowser + * @param {string} element_id Id of the element to set value in. + * @param {string} type Type of browser to open image/file/flash. + * @param {string} option Option name to get the file_broswer_callback function name from. + */ + openBrowser: function (element_id, type) { + tinyMCEPopup.restoreSelection(); + this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); + }, + + /** + * Creates a confirm dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method confirm + * @param {String} t Title for the new confirm dialog. + * @param {function} cb Callback function to be executed after the user has selected ok or cancel. + * @param {Object} s Optional scope to execute the callback in. + */ + confirm: function (t, cb, s) { + this.editor.windowManager.confirm(t, cb, s, window); + }, + + /** + * Creates a alert dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method alert + * @param {String} tx Title for the new alert dialog. + * @param {function} cb Callback function to be executed after the user has selected ok. + * @param {Object} s Optional scope to execute the callback in. + */ + alert: function (tx, cb, s) { + this.editor.windowManager.alert(tx, cb, s, window); + }, + + /** + * Closes the current window. + * + * @method close + */ + close: function () { + var t = this; + + // To avoid domain relaxing issue in Opera + function close() { + t.editor.windowManager.close(window); + tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup + } + + if (tinymce.isOpera) { + t.getWin().setTimeout(close, 0); + } else { + close(); + } + }, + + // Internal functions + + _restoreSelection: function () { + var e = window.event.srcElement; + + if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) { + tinyMCEPopup.restoreSelection(); + } + }, + + /* _restoreSelection : function() { + var e = window.event.srcElement; + + // If user focus a non text input or textarea + if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') + tinyMCEPopup.restoreSelection(); + },*/ + + _onDOMLoaded: function () { + var t = tinyMCEPopup, ti = document.title, h, nv; + + // Translate page + if (t.features.translate_i18n !== false) { + var map = { + "update": "Ok", + "insert": "Ok", + "cancel": "Cancel", + "not_set": "--", + "class_name": "Class name", + "browse": "Browse" + }; + + var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en'; + for (var key in map) { + tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]); + } + + h = document.body.innerHTML; + + // Replace a=x with a="x" in IE + if (tinymce.isIE) { + h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"'); + } + + document.dir = t.editor.getParam('directionality', ''); + + if ((nv = t.editor.translate(h)) && nv != h) { + document.body.innerHTML = nv; + } + + if ((nv = t.editor.translate(ti)) && nv != ti) { + document.title = ti = nv; + } + } + + if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) { + t.dom.addClass(document.body, 'forceColors'); + } + + document.body.style.display = ''; + + // Restore selection in IE when focus is placed on a non textarea or input element of the type text + if (tinymce.Env.ie) { + if (tinymce.Env.ie < 11) { + document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); + + // Add base target element for it since it would fail with modal dialogs + t.dom.add(t.dom.select('head')[0], 'base', { target: '_self' }); + } else { + document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false); + } + } + + t.restoreSelection(); + t.resizeToInnerSize(); + + // Set inline title + if (!t.isWindow) { + t.editor.windowManager.setTitle(window, ti); + } else { + window.focus(); + } + + if (!tinymce.isIE && !t.isWindow) { + t.dom.bind(document, 'focus', function () { + t.editor.windowManager.focus(t.id); + }); + } + + // Patch for accessibility + tinymce.each(t.dom.select('select'), function (e) { + e.onkeydown = tinyMCEPopup._accessHandler; + }); + + // Call onInit + // Init must be called before focus so the selection won't get lost by the focus call + tinymce.each(t.listeners, function (o) { + o.func.call(o.scope, t.editor); + }); + + // Move focus to window + if (t.getWindowArg('mce_auto_focus', true)) { + window.focus(); + + // Focus element with mceFocus class + tinymce.each(document.forms, function (f) { + tinymce.each(f.elements, function (e) { + if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { + e.focus(); + return false; // Break loop + } + }); + }); + } + + document.onkeyup = tinyMCEPopup._closeWinKeyHandler; + + if ('textContent' in document) { + t.uiWindow.getEl('head').firstChild.textContent = document.title; + } else { + t.uiWindow.getEl('head').firstChild.innerText = document.title; + } + }, + + _accessHandler: function (e) { + e = e || window.event; + + if (e.keyCode == 13 || e.keyCode == 32) { + var elm = e.target || e.srcElement; + + if (elm.onchange) { + elm.onchange(); + } + + return tinymce.dom.Event.cancel(e); + } + }, + + _closeWinKeyHandler: function (e) { + e = e || window.event; + + if (e.keyCode == 27) { + tinyMCEPopup.close(); + } + }, + + _eventProxy: function (id) { + return function (evt) { + tinyMCEPopup.dom.events.callNativeHandler(id, evt); + }; + } }; tinyMCEPopup.init(); -tinymce.util.Dispatcher = function(scope) { - this.scope = scope || this; - this.listeners = []; +tinymce.util.Dispatcher = function (scope) { + this.scope = scope || this; + this.listeners = []; - this.add = function(callback, scope) { - this.listeners.push({cb : callback, scope : scope || this.scope}); + this.add = function (callback, scope) { + this.listeners.push({ cb: callback, scope: scope || this.scope }); - return callback; - }; + return callback; + }; - this.addToTop = function(callback, scope) { - var self = this, listener = {cb : callback, scope : scope || self.scope}; + this.addToTop = function (callback, scope) { + var self = this, listener = { cb: callback, scope: scope || self.scope }; - // Create new listeners if addToTop is executed in a dispatch loop - if (self.inDispatch) { - self.listeners = [listener].concat(self.listeners); - } else { - self.listeners.unshift(listener); - } + // Create new listeners if addToTop is executed in a dispatch loop + if (self.inDispatch) { + self.listeners = [listener].concat(self.listeners); + } else { + self.listeners.unshift(listener); + } - return callback; - }; + return callback; + }; - this.remove = function(callback) { - var listeners = this.listeners, output = null; + this.remove = function (callback) { + var listeners = this.listeners, output = null; - tinymce.each(listeners, function(listener, i) { - if (callback == listener.cb) { - output = listener; - listeners.splice(i, 1); - return false; - } - }); + tinymce.each(listeners, function (listener, i) { + if (callback == listener.cb) { + output = listener; + listeners.splice(i, 1); + return false; + } + }); - return output; - }; + return output; + }; - this.dispatch = function() { - var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener; + this.dispatch = function () { + var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener; - self.inDispatch = true; - - // Needs to be a real loop since the listener count might change while looping - // And this is also more efficient - for (i = 0; i < listeners.length; i++) { - listener = listeners[i]; - returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]); + self.inDispatch = true; - if (returnValue === false) { - break; - } - } + // Needs to be a real loop since the listener count might change while looping + // And this is also more efficient + for (i = 0; i < listeners.length; i++) { + listener = listeners[i]; + returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]); - self.inDispatch = false; + if (returnValue === false) { + break; + } + } - return returnValue; - }; + self.inDispatch = false; + + return returnValue; + }; }; diff --git a/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js b/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js index 8d30787d5..3dd44a8f1 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js +++ b/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js @@ -1,70 +1,72 @@ /** * editable_selects.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var TinyMCE_EditableSelects = { - editSelectElm : null, + editSelectElm : null, - init : function() { - var nl = document.getElementsByTagName("select"), i, d = document, o; + init : function () { + var nl = document.getElementsByTagName("select"), i, d = document, o; - for (i=0; i<nl.length; i++) { - if (nl[i].className.indexOf('mceEditableSelect') != -1) { - o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); + for (i = 0; i < nl.length; i++) { + if (nl[i].className.indexOf('mceEditableSelect') != -1) { + o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); - o.className = 'mceAddSelectValue'; + o.className = 'mceAddSelectValue'; - nl[i].options[nl[i].options.length] = o; - nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; - } - } - }, + nl[i].options[nl[i].options.length] = o; + nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; + } + } + }, - onChangeEditableSelect : function(e) { - var d = document, ne, se = window.event ? window.event.srcElement : e.target; + onChangeEditableSelect : function (e) { + var d = document, ne, se = window.event ? window.event.srcElement : e.target; - if (se.options[se.selectedIndex].value == '__mce_add_custom__') { - ne = d.createElement("input"); - ne.id = se.id + "_custom"; - ne.name = se.name + "_custom"; - ne.type = "text"; + if (se.options[se.selectedIndex].value == '__mce_add_custom__') { + ne = d.createElement("input"); + ne.id = se.id + "_custom"; + ne.name = se.name + "_custom"; + ne.type = "text"; - ne.style.width = se.offsetWidth + 'px'; - se.parentNode.insertBefore(ne, se); - se.style.display = 'none'; - ne.focus(); - ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; - ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; - TinyMCE_EditableSelects.editSelectElm = se; - } - }, + ne.style.width = se.offsetWidth + 'px'; + se.parentNode.insertBefore(ne, se); + se.style.display = 'none'; + ne.focus(); + ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; + ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; + TinyMCE_EditableSelects.editSelectElm = se; + } + }, - onBlurEditableSelectInput : function() { - var se = TinyMCE_EditableSelects.editSelectElm; + onBlurEditableSelectInput : function () { + var se = TinyMCE_EditableSelects.editSelectElm; - if (se) { - if (se.previousSibling.value != '') { - addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); - selectByValue(document.forms[0], se.id, se.previousSibling.value); - } else - selectByValue(document.forms[0], se.id, ''); + if (se) { + if (se.previousSibling.value != '') { + addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); + selectByValue(document.forms[0], se.id, se.previousSibling.value); + } else { + selectByValue(document.forms[0], se.id, ''); + } - se.style.display = 'inline'; - se.parentNode.removeChild(se.previousSibling); - TinyMCE_EditableSelects.editSelectElm = null; - } - }, + se.style.display = 'inline'; + se.parentNode.removeChild(se.previousSibling); + TinyMCE_EditableSelects.editSelectElm = null; + } + }, - onKeyDown : function(e) { - e = e || window.event; + onKeyDown : function (e) { + e = e || window.event; - if (e.keyCode == 13) - TinyMCE_EditableSelects.onBlurEditableSelectInput(); - } + if (e.keyCode == 13) { + TinyMCE_EditableSelects.onBlurEditableSelectInput(); + } + } }; diff --git a/e107_plugins/tinymce4/plugins/compat3x/utils/form_utils.js b/e107_plugins/tinymce4/plugins/compat3x/utils/form_utils.js index 5c7134fca..358ad60a9 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/utils/form_utils.js +++ b/e107_plugins/tinymce4/plugins/compat3x/utils/form_utils.js @@ -1,8 +1,8 @@ /** * form_utils.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -11,200 +11,212 @@ var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); function getColorPickerHTML(id, target_form_element) { - var h = "", dom = tinyMCEPopup.dom; + var h = "", dom = tinyMCEPopup.dom; - if (label = dom.select('label[for=' + target_form_element + ']')[0]) { - label.id = label.id || dom.uniqueId(); - } + if (label = dom.select('label[for=' + target_form_element + ']')[0]) { + label.id = label.id || dom.uniqueId(); + } - h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">'; - h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> <span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>'; + h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element + '\');" onmousedown="return false;" class="pickcolor">'; + h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> <span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>'; - return h; + return h; } function updateColor(img_id, form_element_id) { - document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; + document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; } function setBrowserDisabled(id, state) { - var img = document.getElementById(id); - var lnk = document.getElementById(id + "_link"); + var img = document.getElementById(id); + var lnk = document.getElementById(id + "_link"); - if (lnk) { - if (state) { - lnk.setAttribute("realhref", lnk.getAttribute("href")); - lnk.removeAttribute("href"); - tinyMCEPopup.dom.addClass(img, 'disabled'); - } else { - if (lnk.getAttribute("realhref")) - lnk.setAttribute("href", lnk.getAttribute("realhref")); + if (lnk) { + if (state) { + lnk.setAttribute("realhref", lnk.getAttribute("href")); + lnk.removeAttribute("href"); + tinyMCEPopup.dom.addClass(img, 'disabled'); + } else { + if (lnk.getAttribute("realhref")) { + lnk.setAttribute("href", lnk.getAttribute("realhref")); + } - tinyMCEPopup.dom.removeClass(img, 'disabled'); - } - } + tinyMCEPopup.dom.removeClass(img, 'disabled'); + } + } } function getBrowserHTML(id, target_form_element, type, prefix) { - var option = prefix + "_" + type + "_browser_callback", cb, html; + var option = prefix + "_" + type + "_browser_callback", cb, html; - cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); + cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); - if (!cb) - return ""; + if (!cb) { + return ""; + } - html = ""; - html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">'; - html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> </span></a>'; + html = ""; + html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">'; + html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> </span></a>'; - return html; + return html; } function openBrowser(img_id, target_form_element, type, option) { - var img = document.getElementById(img_id); + var img = document.getElementById(img_id); - if (img.className != "mceButtonDisabled") - tinyMCEPopup.openBrowser(target_form_element, type, option); + if (img.className != "mceButtonDisabled") { + tinyMCEPopup.openBrowser(target_form_element, type, option); + } } function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { - if (!form_obj || !form_obj.elements[field_name]) - return; + if (!form_obj || !form_obj.elements[field_name]) { + return; + } - if (!value) - value = ""; + if (!value) { + value = ""; + } - var sel = form_obj.elements[field_name]; + var sel = form_obj.elements[field_name]; - var found = false; - for (var i=0; i<sel.options.length; i++) { - var option = sel.options[i]; + var found = false; + for (var i = 0; i < sel.options.length; i++) { + var option = sel.options[i]; - if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { - option.selected = true; - found = true; - } else - option.selected = false; - } + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else { + option.selected = false; + } + } - if (!found && add_custom && value != '') { - var option = new Option(value, value); - option.selected = true; - sel.options[sel.options.length] = option; - sel.selectedIndex = sel.options.length - 1; - } + if (!found && add_custom && value != '') { + var option = new Option(value, value); + option.selected = true; + sel.options[sel.options.length] = option; + sel.selectedIndex = sel.options.length - 1; + } - return found; + return found; } function getSelectValue(form_obj, field_name) { - var elm = form_obj.elements[field_name]; + var elm = form_obj.elements[field_name]; - if (elm == null || elm.options == null || elm.selectedIndex === -1) - return ""; + if (elm == null || elm.options == null || elm.selectedIndex === -1) { + return ""; + } - return elm.options[elm.selectedIndex].value; + return elm.options[elm.selectedIndex].value; } function addSelectValue(form_obj, field_name, name, value) { - var s = form_obj.elements[field_name]; - var o = new Option(name, value); - s.options[s.options.length] = o; + var s = form_obj.elements[field_name]; + var o = new Option(name, value); + s.options[s.options.length] = o; } function addClassesToList(list_id, specific_option) { - // Setup class droplist - var styleSelectElm = document.getElementById(list_id); - var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); - styles = tinyMCEPopup.getParam(specific_option, styles); + // Setup class droplist + var styleSelectElm = document.getElementById(list_id); + var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); + styles = tinyMCEPopup.getParam(specific_option, styles); - if (styles) { - var stylesAr = styles.split(';'); + if (styles) { + var stylesAr = styles.split(';'); - for (var i=0; i<stylesAr.length; i++) { - if (stylesAr != "") { - var key, value; + for (var i = 0; i < stylesAr.length; i++) { + if (stylesAr != "") { + var key, value; - key = stylesAr[i].split('=')[0]; - value = stylesAr[i].split('=')[1]; + key = stylesAr[i].split('=')[0]; + value = stylesAr[i].split('=')[1]; - styleSelectElm.options[styleSelectElm.length] = new Option(key, value); - } - } - } else { - /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { - styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); - });*/ - } + styleSelectElm.options[styleSelectElm.length] = new Option(key, value); + } + } + } else { + /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { + styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); + });*/ + } } function isVisible(element_id) { - var elm = document.getElementById(element_id); + var elm = document.getElementById(element_id); - return elm && elm.style.display != "none"; + return elm && elm.style.display != "none"; } function convertRGBToHex(col) { - var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); - var rgb = col.replace(re, "$1,$2,$3").split(','); - if (rgb.length == 3) { - r = parseInt(rgb[0]).toString(16); - g = parseInt(rgb[1]).toString(16); - b = parseInt(rgb[2]).toString(16); + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); - r = r.length == 1 ? '0' + r : r; - g = g.length == 1 ? '0' + g : g; - b = b.length == 1 ? '0' + b : b; + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; - return "#" + r + g + b; - } + return "#" + r + g + b; + } - return col; + return col; } function convertHexToRGB(col) { - if (col.indexOf('#') != -1) { - col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); - r = parseInt(col.substring(0, 2), 16); - g = parseInt(col.substring(2, 4), 16); - b = parseInt(col.substring(4, 6), 16); + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); - return "rgb(" + r + "," + g + "," + b + ")"; - } + return "rgb(" + r + "," + g + "," + b + ")"; + } - return col; + return col; } function trimSize(size) { - return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); + return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); } function getCSSSize(size) { - size = trimSize(size); + size = trimSize(size); - if (size == "") - return ""; + if (size == "") { + return ""; + } - // Add px - if (/^[0-9]+$/.test(size)) - size += 'px'; - // Sanity check, IE doesn't like broken values - else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) - return ""; + // Add px + if (/^[0-9]+$/.test(size)) { + size += 'px'; + } + // Sanity check, IE doesn't like broken values + else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) { + return ""; + } - return size; + return size; } function getStyle(elm, attrib, style) { - var val = tinyMCEPopup.dom.getAttrib(elm, attrib); + var val = tinyMCEPopup.dom.getAttrib(elm, attrib); - if (val != '') - return '' + val; + if (val != '') { + return '' + val; + } - if (typeof(style) == 'undefined') - style = attrib; + if (typeof (style) == 'undefined') { + style = attrib; + } - return tinyMCEPopup.dom.getStyle(elm, style); + return tinyMCEPopup.dom.getStyle(elm, style); } diff --git a/e107_plugins/tinymce4/plugins/compat3x/utils/mctabs.js b/e107_plugins/tinymce4/plugins/compat3x/utils/mctabs.js index 2391c782f..a04519be7 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/utils/mctabs.js +++ b/e107_plugins/tinymce4/plugins/compat3x/utils/mctabs.js @@ -1,8 +1,8 @@ /** * mctabs.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -11,154 +11,158 @@ /*jshint globals: tinyMCEPopup */ function MCTabs() { - this.settings = []; - this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); + this.settings = []; + this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); +} + +MCTabs.prototype.init = function (settings) { + this.settings = settings; }; -MCTabs.prototype.init = function(settings) { - this.settings = settings; +MCTabs.prototype.getParam = function (name, default_value) { + var value = null; + + value = (typeof (this.settings[name]) == "undefined") ? default_value : this.settings[name]; + + // Fix bool values + if (value == "true" || value == "false") { + return (value == "true"); + } + + return value; }; -MCTabs.prototype.getParam = function(name, default_value) { - var value = null; - - value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; - - // Fix bool values - if (value == "true" || value == "false") - return (value == "true"); - - return value; +MCTabs.prototype.showTab = function (tab) { + tab.className = 'current'; + tab.setAttribute("aria-selected", true); + tab.setAttribute("aria-expanded", true); + tab.tabIndex = 0; }; -MCTabs.prototype.showTab =function(tab){ - tab.className = 'current'; - tab.setAttribute("aria-selected", true); - tab.setAttribute("aria-expanded", true); - tab.tabIndex = 0; +MCTabs.prototype.hideTab = function (tab) { + var t = this; + + tab.className = ''; + tab.setAttribute("aria-selected", false); + tab.setAttribute("aria-expanded", false); + tab.tabIndex = -1; }; -MCTabs.prototype.hideTab =function(tab){ - var t=this; - - tab.className = ''; - tab.setAttribute("aria-selected", false); - tab.setAttribute("aria-expanded", false); - tab.tabIndex = -1; +MCTabs.prototype.showPanel = function (panel) { + panel.className = 'current'; + panel.setAttribute("aria-hidden", false); }; -MCTabs.prototype.showPanel = function(panel) { - panel.className = 'current'; - panel.setAttribute("aria-hidden", false); +MCTabs.prototype.hidePanel = function (panel) { + panel.className = 'panel'; + panel.setAttribute("aria-hidden", true); }; -MCTabs.prototype.hidePanel = function(panel) { - panel.className = 'panel'; - panel.setAttribute("aria-hidden", true); -}; - -MCTabs.prototype.getPanelForTab = function(tabElm) { - return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); +MCTabs.prototype.getPanelForTab = function (tabElm) { + return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); }; -MCTabs.prototype.displayTab = function(tab_id, panel_id, avoid_focus) { - var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; +MCTabs.prototype.displayTab = function (tab_id, panel_id, avoid_focus) { + var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; - tabElm = document.getElementById(tab_id); + tabElm = document.getElementById(tab_id); - if (panel_id === undefined) { - panel_id = t.getPanelForTab(tabElm); - } + if (panel_id === undefined) { + panel_id = t.getPanelForTab(tabElm); + } - panelElm= document.getElementById(panel_id); - panelContainerElm = panelElm ? panelElm.parentNode : null; - tabContainerElm = tabElm ? tabElm.parentNode : null; - selectionClass = t.getParam('selection_class', 'current'); + panelElm = document.getElementById(panel_id); + panelContainerElm = panelElm ? panelElm.parentNode : null; + tabContainerElm = tabElm ? tabElm.parentNode : null; + selectionClass = t.getParam('selection_class', 'current'); - if (tabElm && tabContainerElm) { - nodes = tabContainerElm.childNodes; + if (tabElm && tabContainerElm) { + nodes = tabContainerElm.childNodes; - // Hide all other tabs - for (i = 0; i < nodes.length; i++) { - if (nodes[i].nodeName == "LI") { - t.hideTab(nodes[i]); - } - } + // Hide all other tabs + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "LI") { + t.hideTab(nodes[i]); + } + } - // Show selected tab - t.showTab(tabElm); - } + // Show selected tab + t.showTab(tabElm); + } - if (panelElm && panelContainerElm) { - nodes = panelContainerElm.childNodes; + if (panelElm && panelContainerElm) { + nodes = panelContainerElm.childNodes; - // Hide all other panels - for (i = 0; i < nodes.length; i++) { - if (nodes[i].nodeName == "DIV") - t.hidePanel(nodes[i]); - } + // Hide all other panels + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "DIV") { + t.hidePanel(nodes[i]); + } + } - if (!avoid_focus) { - tabElm.focus(); - } + if (!avoid_focus) { + tabElm.focus(); + } - // Show selected panel - t.showPanel(panelElm); - } + // Show selected panel + t.showPanel(panelElm); + } }; -MCTabs.prototype.getAnchor = function() { - var pos, url = document.location.href; +MCTabs.prototype.getAnchor = function () { + var pos, url = document.location.href; - if ((pos = url.lastIndexOf('#')) != -1) - return url.substring(pos + 1); + if ((pos = url.lastIndexOf('#')) != -1) { + return url.substring(pos + 1); + } - return ""; + return ""; }; //Global instance var mcTabs = new MCTabs(); -tinyMCEPopup.onInit.add(function() { - var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; +tinyMCEPopup.onInit.add(function () { + var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; - each(dom.select('div.tabs'), function(tabContainerElm) { - //var keyNav; + each(dom.select('div.tabs'), function (tabContainerElm) { + //var keyNav; - dom.setAttrib(tabContainerElm, "role", "tablist"); + dom.setAttrib(tabContainerElm, "role", "tablist"); - var items = tinyMCEPopup.dom.select('li', tabContainerElm); - var action = function(id) { - mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); - mcTabs.onChange.dispatch(id); - }; + var items = tinyMCEPopup.dom.select('li', tabContainerElm); + var action = function (id) { + mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); + mcTabs.onChange.dispatch(id); + }; - each(items, function(item) { - dom.setAttrib(item, 'role', 'tab'); - dom.bind(item, 'click', function(evt) { - action(item.id); - }); - }); + each(items, function (item) { + dom.setAttrib(item, 'role', 'tab'); + dom.bind(item, 'click', function (evt) { + action(item.id); + }); + }); - dom.bind(dom.getRoot(), 'keydown', function(evt) { - if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab - //keyNav.moveFocus(evt.shiftKey ? -1 : 1); - tinymce.dom.Event.cancel(evt); - } - }); + dom.bind(dom.getRoot(), 'keydown', function (evt) { + if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab + //keyNav.moveFocus(evt.shiftKey ? -1 : 1); + tinymce.dom.Event.cancel(evt); + } + }); - each(dom.select('a', tabContainerElm), function(a) { - dom.setAttrib(a, 'tabindex', '-1'); - }); + each(dom.select('a', tabContainerElm), function (a) { + dom.setAttrib(a, 'tabindex', '-1'); + }); - /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { - root: tabContainerElm, - items: items, - onAction: action, - actOnFocus: true, - enableLeftRight: true, - enableUpDown: true - }, tinyMCEPopup.dom);*/ - }); + /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: tabContainerElm, + items: items, + onAction: action, + actOnFocus: true, + enableLeftRight: true, + enableUpDown: true + }, tinyMCEPopup.dom);*/ + } +); }); \ No newline at end of file diff --git a/e107_plugins/tinymce4/plugins/compat3x/utils/validate.js b/e107_plugins/tinymce4/plugins/compat3x/utils/validate.js index d13aaa1ba..5600666d3 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/utils/validate.js +++ b/e107_plugins/tinymce4/plugins/compat3x/utils/validate.js @@ -1,252 +1,267 @@ /** * validate.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /** - // String validation: + // String validation: - if (!Validator.isEmail('myemail')) - alert('Invalid email.'); + if (!Validator.isEmail('myemail')) + alert('Invalid email.'); - // Form validation: + // Form validation: - var f = document.forms['myform']; + var f = document.forms['myform']; - if (!Validator.isEmail(f.myemail)) - alert('Invalid email.'); + if (!Validator.isEmail(f.myemail)) + alert('Invalid email.'); */ var Validator = { - isEmail : function(s) { - return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); - }, + isEmail : function (s) { + return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); + }, - isAbsUrl : function(s) { - return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); - }, + isAbsUrl : function (s) { + return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); + }, - isSize : function(s) { - return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); - }, + isSize : function (s) { + return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); + }, - isId : function(s) { - return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); - }, + isId : function (s) { + return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); + }, - isEmpty : function(s) { - var nl, i; + isEmpty : function (s) { + var nl, i; - if (s.nodeName == 'SELECT' && s.selectedIndex < 1) - return true; + if (s.nodeName == 'SELECT' && s.selectedIndex < 1) { + return true; + } - if (s.type == 'checkbox' && !s.checked) - return true; + if (s.type == 'checkbox' && !s.checked) { + return true; + } - if (s.type == 'radio') { - for (i=0, nl = s.form.elements; i<nl.length; i++) { - if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) - return false; - } + if (s.type == 'radio') { + for (i = 0, nl = s.form.elements; i < nl.length; i++) { + if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) { + return false; + } + } - return true; - } + return true; + } - return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); - }, + return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); + }, - isNumber : function(s, d) { - return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); - }, + isNumber : function (s, d) { + return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); + }, - test : function(s, p) { - s = s.nodeType == 1 ? s.value : s; + test : function (s, p) { + s = s.nodeType == 1 ? s.value : s; - return s == '' || new RegExp(p).test(s); - } + return s == '' || new RegExp(p).test(s); + } }; var AutoValidator = { - settings : { - id_cls : 'id', - int_cls : 'int', - url_cls : 'url', - number_cls : 'number', - email_cls : 'email', - size_cls : 'size', - required_cls : 'required', - invalid_cls : 'invalid', - min_cls : 'min', - max_cls : 'max' - }, + settings : { + id_cls : 'id', + int_cls : 'int', + url_cls : 'url', + number_cls : 'number', + email_cls : 'email', + size_cls : 'size', + required_cls : 'required', + invalid_cls : 'invalid', + min_cls : 'min', + max_cls : 'max' + }, - init : function(s) { - var n; + init : function (s) { + var n; - for (n in s) - this.settings[n] = s[n]; - }, + for (n in s) { + this.settings[n] = s[n]; + } + }, - validate : function(f) { - var i, nl, s = this.settings, c = 0; + validate : function (f) { + var i, nl, s = this.settings, c = 0; - nl = this.tags(f, 'label'); - for (i=0; i<nl.length; i++) { - this.removeClass(nl[i], s.invalid_cls); - nl[i].setAttribute('aria-invalid', false); - } + nl = this.tags(f, 'label'); + for (i = 0; i < nl.length; i++) { + this.removeClass(nl[i], s.invalid_cls); + nl[i].setAttribute('aria-invalid', false); + } - c += this.validateElms(f, 'input'); - c += this.validateElms(f, 'select'); - c += this.validateElms(f, 'textarea'); + c += this.validateElms(f, 'input'); + c += this.validateElms(f, 'select'); + c += this.validateElms(f, 'textarea'); - return c == 3; - }, + return c == 3; + }, - invalidate : function(n) { - this.mark(n.form, n); - }, - - getErrorMessages : function(f) { - var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; - nl = this.tags(f, "label"); - for (i=0; i<nl.length; i++) { - if (this.hasClass(nl[i], s.invalid_cls)) { - field = document.getElementById(nl[i].getAttribute("for")); - values = { field: nl[i].textContent }; - if (this.hasClass(field, s.min_cls, true)) { - message = ed.getLang('invalid_data_min'); - values.min = this.getNum(field, s.min_cls); - } else if (this.hasClass(field, s.number_cls)) { - message = ed.getLang('invalid_data_number'); - } else if (this.hasClass(field, s.size_cls)) { - message = ed.getLang('invalid_data_size'); - } else { - message = ed.getLang('invalid_data'); - } - - message = message.replace(/{\#([^}]+)\}/g, function(a, b) { - return values[b] || '{#' + b + '}'; - }); - messages.push(message); - } - } - return messages; - }, + invalidate : function (n) { + this.mark(n.form, n); + }, - reset : function(e) { - var t = ['label', 'input', 'select', 'textarea']; - var i, j, nl, s = this.settings; + getErrorMessages : function (f) { + var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; + nl = this.tags(f, "label"); + for (i = 0; i < nl.length; i++) { + if (this.hasClass(nl[i], s.invalid_cls)) { + field = document.getElementById(nl[i].getAttribute("for")); + values = { field: nl[i].textContent }; + if (this.hasClass(field, s.min_cls, true)) { + message = ed.getLang('invalid_data_min'); + values.min = this.getNum(field, s.min_cls); + } else if (this.hasClass(field, s.number_cls)) { + message = ed.getLang('invalid_data_number'); + } else if (this.hasClass(field, s.size_cls)) { + message = ed.getLang('invalid_data_size'); + } else { + message = ed.getLang('invalid_data'); + } - if (e == null) - return; + message = message.replace(/{\#([^}]+)\}/g, function (a, b) { + return values[b] || '{#' + b + '}'; + }); + messages.push(message); + } + } + return messages; + }, - for (i=0; i<t.length; i++) { - nl = this.tags(e.form ? e.form : e, t[i]); - for (j=0; j<nl.length; j++) { - this.removeClass(nl[j], s.invalid_cls); - nl[j].setAttribute('aria-invalid', false); - } - } - }, + reset : function (e) { + var t = ['label', 'input', 'select', 'textarea']; + var i, j, nl, s = this.settings; - validateElms : function(f, e) { - var nl, i, n, s = this.settings, st = true, va = Validator, v; + if (e == null) { + return; + } - nl = this.tags(f, e); - for (i=0; i<nl.length; i++) { - n = nl[i]; + for (i = 0; i < t.length; i++) { + nl = this.tags(e.form ? e.form : e, t[i]); + for (j = 0; j < nl.length; j++) { + this.removeClass(nl[j], s.invalid_cls); + nl[j].setAttribute('aria-invalid', false); + } + } + }, - this.removeClass(n, s.invalid_cls); + validateElms : function (f, e) { + var nl, i, n, s = this.settings, st = true, va = Validator, v; - if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) - st = this.mark(f, n); + nl = this.tags(f, e); + for (i = 0; i < nl.length; i++) { + n = nl[i]; - if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) - st = this.mark(f, n); + this.removeClass(n, s.invalid_cls); - if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) - st = this.mark(f, n); + if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) - st = this.mark(f, n); + if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) - st = this.mark(f, n); + if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.size_cls) && !va.isSize(n)) - st = this.mark(f, n); + if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.id_cls) && !va.isId(n)) - st = this.mark(f, n); + if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.min_cls, true)) { - v = this.getNum(n, s.min_cls); + if (this.hasClass(n, s.size_cls) && !va.isSize(n)) { + st = this.mark(f, n); + } - if (isNaN(v) || parseInt(n.value) < parseInt(v)) - st = this.mark(f, n); - } + if (this.hasClass(n, s.id_cls) && !va.isId(n)) { + st = this.mark(f, n); + } - if (this.hasClass(n, s.max_cls, true)) { - v = this.getNum(n, s.max_cls); + if (this.hasClass(n, s.min_cls, true)) { + v = this.getNum(n, s.min_cls); - if (isNaN(v) || parseInt(n.value) > parseInt(v)) - st = this.mark(f, n); - } - } + if (isNaN(v) || parseInt(n.value) < parseInt(v)) { + st = this.mark(f, n); + } + } - return st; - }, + if (this.hasClass(n, s.max_cls, true)) { + v = this.getNum(n, s.max_cls); - hasClass : function(n, c, d) { - return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); - }, + if (isNaN(v) || parseInt(n.value) > parseInt(v)) { + st = this.mark(f, n); + } + } + } - getNum : function(n, c) { - c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; - c = c.replace(/[^0-9]/g, ''); + return st; + }, - return c; - }, + hasClass : function (n, c, d) { + return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); + }, - addClass : function(n, c, b) { - var o = this.removeClass(n, c); - n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; - }, + getNum : function (n, c) { + c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; + c = c.replace(/[^0-9]/g, ''); - removeClass : function(n, c) { - c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); - return n.className = c != ' ' ? c : ''; - }, + return c; + }, - tags : function(f, s) { - return f.getElementsByTagName(s); - }, + addClass : function (n, c, b) { + var o = this.removeClass(n, c); + n.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c; + }, - mark : function(f, n) { - var s = this.settings; + removeClass : function (n, c) { + c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return n.className = c !== ' ' ? c : ''; + }, - this.addClass(n, s.invalid_cls); - n.setAttribute('aria-invalid', 'true'); - this.markLabels(f, n, s.invalid_cls); + tags : function (f, s) { + return f.getElementsByTagName(s); + }, - return false; - }, + mark : function (f, n) { + var s = this.settings; - markLabels : function(f, n, ic) { - var nl, i; + this.addClass(n, s.invalid_cls); + n.setAttribute('aria-invalid', 'true'); + this.markLabels(f, n, s.invalid_cls); - nl = this.tags(f, "label"); - for (i=0; i<nl.length; i++) { - if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) - this.addClass(nl[i], ic); - } + return false; + }, - return null; - } + markLabels : function (f, n, ic) { + var nl, i; + + nl = this.tags(f, "label"); + for (i = 0; i < nl.length; i++) { + if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) { + this.addClass(nl[i], ic); + } + } + + return null; + } }; diff --git a/e107_plugins/tinymce4/wysiwyg.php b/e107_plugins/tinymce4/wysiwyg.php index 68a876fdc..646d7750b 100644 --- a/e107_plugins/tinymce4/wysiwyg.php +++ b/e107_plugins/tinymce4/wysiwyg.php @@ -240,7 +240,7 @@ class wysiwyg 'Danish' => 'da', // 'Divehi' => 'dv', 'Dutch' => 'nl', - 'English' => 'en', // Default language file. + 'English' => 'en_GB', // Default language file. // 'English (Canada)' => 'en_CA', // 'English (United Kingdom)' => 'en_GB', 'Esperanto' => 'eo', diff --git a/e107_themes/bootstrap4/theme.php b/e107_themes/bootstrap4/theme.php index 1cf1cbb08..7439e1185 100644 --- a/e107_themes/bootstrap4/theme.php +++ b/e107_themes/bootstrap4/theme.php @@ -7,7 +7,7 @@ if ( ! defined('e107_INIT')) { exit(); } e107::meta('viewport', 'width=device-width, initial-scale=1.0'); //e107::meta('apple-mobile-web-app-capable','yes'); - +e107::css("url", "https://bootswatch.com/4/slate/bootstrap.min.css" ); $HEADER = array(); $FOOTER = array(); diff --git a/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css b/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css index d0f3dff66..78485fee7 100644 --- a/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css +++ b/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css @@ -6,4 +6,4 @@ * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * - */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(top,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px} \ No newline at end of file + */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px} \ No newline at end of file diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js index 21aa00543..6c872e12f 100755 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js @@ -36,7 +36,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; autoclose: true, format: $item.attr("data-date-format"), weekStart: $item.attr("data-date-firstday"), - language: $item.attr("data-date-language") + language: $item.attr("data-date-language"), }).on("changeDate", function (ev) { var useUnix = $(this).attr("data-date-unix"); var newValue = ""; @@ -49,7 +49,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } - $(newTarget).val(newValue); + $(newTarget).val( newValue); }); }); @@ -62,6 +62,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; weekStart: $item.attr("data-date-firstday"), showMeridian: $item.attr("data-date-ampm"), language: $item.attr("data-date-language") + }).on("changeDate", function (ev) { var useUnix = $(this).attr("data-date-unix"); var newValue = ""; @@ -74,7 +75,22 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } + offset = parseInt($item.attr("data-date-timezone-offset")); + + if(offset) // adjust UTC value to target timezone. ie. timezone other than the one of the browser. + { + browserOffset = ev.date.getTimezoneOffset() * 60; + relativeOffset = browserOffset + offset; + + console.log("Browser Offset: " + browserOffset); + console.log('Offset: ' + offset); + console.log('Relative Offset: ' + relativeOffset); + + newValue = newValue - relativeOffset; + } + $(newTarget).val(newValue); + }) }); } diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js index 512fcbbb9..eba15ce5d 100644 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js @@ -1 +1 @@ -(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(f,c){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===c){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function e(l){var k=f(l);var j=k.add(k.parents());var m=false;j.each(function(){if(f(this).css("position")==="fixed"){m=true;return false}});return m}function h(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var j=new Date();return h(j.getUTCFullYear(),j.getUTCMonth(),j.getUTCDate(),j.getUTCHours(),j.getUTCMinutes(),j.getUTCSeconds(),0)}var i=function(l,k){var n=this;this.element=f(l);this.container=k.container||"body";this.language=k.language||this.element.data("date-language")||"en";this.language=this.language in a?this.language:this.language.split("-")[0];this.language=this.language in a?this.language:"en";this.isRTL=a[this.language].rtl||false;this.formatType=k.formatType||this.element.data("format-type")||"standard";this.format=g.parseFormat(k.format||this.element.data("date-format")||a[this.language].format||g.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=k.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=k.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer==3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer==3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=k.linkField||this.element.data("link-field")||false;this.linkFormat=g.parseFormat(k.linkFormat||this.element.data("link-format")||g.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=k.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=k.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=k.showMeridian||this.element.data("show-meridian")||false;this.initialDate=k.initialDate||new Date();this.zIndex=k.zIndex||this.element.data("z-index")||c;this.title=typeof k.title==="undefined"?false:k.title;this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(o){if(f(o.target).closest(".datetimepicker").length===0){n.hide()}};this.formatViewType="datetime";if("formatViewType" in k){this.formatViewType=k.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in k){this.minView=k.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=g.convertViewMode(this.minView);this.maxView=g.modes.length-1;if("maxView" in k){this.maxView=k.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=g.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in k){this.wheelViewModeNavigation=k.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in k){this.wheelViewModeNavigationInverseDirection=k.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in k){this.wheelViewModeNavigationDelay=k.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in k){this.startViewMode=k.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=g.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in k){this.viewSelect=k.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=g.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in k){this.forceParse=k.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var m=this.bootcssVer===3?g.templateV3:g.template;while(m.indexOf("{iconType}")!==-1){m=m.replace("{iconType}",this.icontype)}while(m.indexOf("{leftArrow}")!==-1){m=m.replace("{leftArrow}",this.icons.leftArrow)}while(m.indexOf("{rightArrow}")!==-1){m=m.replace("{rightArrow}",this.icons.rightArrow)}this.picker=f(m).appendTo(this.isInline?this.element:this.container).on({click:f.proxy(this.click,this),mousedown:f.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(f.fn.mousewheel){this.picker.on({mousewheel:f.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var j=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(j).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}f(document).on("mousedown",this.clickedOutside);this.autoclose=false;if("autoclose" in k){this.autoclose=k.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in k){this.keyboardNavigation=k.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(k.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(k.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(k.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=((k.weekStart||this.element.data("date-weekstart")||a[this.language].weekStart||0)%7);this.weekEnd=((this.weekStart+6)%7);this.startDate=-Infinity;this.endDate=Infinity;this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(k.startDate||this.element.data("date-startdate"));this.setEndDate(k.endDate||this.element.data("date-enddate"));this.setDatesDisabled(k.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(k.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(k.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(k.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};i.prototype={constructor:i,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:f.proxy(this.show,this),keyup:f.proxy(this.update,this),keydown:f.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:f.proxy(this.show,this),keyup:f.proxy(this.update,this),keydown:f.proxy(this.keydown,this)}],[this.component,{click:f.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:f.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:f.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(j){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();f(window).on("resize",f.proxy(this.place,this));if(j){j.stopPropagation();j.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(j){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();f(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){f(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();f(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var j=this.getUTCDate();return new Date(j.getTime()+(j.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},setDate:function(j){this.setUTCDate(new Date(j.getTime()-(j.getTimezoneOffset()*60000)))},setUTCDate:function(j){if(j>=this.startDate&&j<=this.endDate){this.date=j;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:j,startDate:this.startDate,endDate:this.endDate})}},setFormat:function(k){this.format=g.parseFormat(k,this.formatType);var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j&&j.val()){this.setValue()}},setValue:function(){var j=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(j)}this.element.data("date",j)}else{this.element.val(j)}if(this.linkField){f("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(j){if(j==c){j=this.format}return g.formatDate(this.date,j,this.language,this.formatType)},setStartDate:function(j){this.startDate=j||-Infinity;if(this.startDate!==-Infinity){this.startDate=g.parseDate(this.startDate,this.format,this.language,this.formatType)}this.update();this.updateNavArrows()},setEndDate:function(j){this.endDate=j||Infinity;if(this.endDate!==Infinity){this.endDate=g.parseDate(this.endDate,this.format,this.language,this.formatType)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!f.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}this.datesDisabled=f.map(this.datesDisabled,function(k){return g.parseDate(k,this.format,this.language,this.formatType).toDateString()});this.update();this.updateNavArrows()},setTitle:function(j,k){return this.picker.find(j).find("th:eq(1)").text(this.title===false?k:this.title)},setDaysOfWeekDisabled:function(j){this.daysOfWeekDisabled=j||[];if(!f.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=f.map(this.daysOfWeekDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(j){this.minutesDisabled=j||[];if(!f.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=f.map(this.minutesDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(j){this.hoursDisabled=j||[];if(!f.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=f.map(this.hoursDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var k=0;f("div").each(function(){var p=parseInt(f(this).css("zIndex"),10);if(p>k){k=p}});this.zIndex=k+10}var o,n,m,l;if(this.container instanceof f){l=this.container.offset()}else{l=f(this.container).offset()}if(this.component){o=this.component.offset();m=o.left;if(this.pickerPosition=="bottom-left"||this.pickerPosition=="top-left"){m+=this.component.outerWidth()-this.picker.outerWidth()}}else{o=this.element.offset();m=o.left;if(this.pickerPosition=="bottom-left"||this.pickerPosition=="top-left"){m+=this.element.outerWidth()-this.picker.outerWidth()}}var j=document.body.clientWidth||window.innerWidth;if(m+220>j){m=j-220}if(this.component){n=n-l.top+169;m=m-l.left+210}else{if(this.pickerPosition=="top-left"||this.pickerPosition=="top-right"){n=o.top-this.picker.outerHeight()}else{n=o.top+this.height}}this.picker.css({top:n,left:m,zIndex:this.zIndex})},update:function(){var j,k=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){j=arguments[0];k=true}else{j=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof j=="string"||j instanceof String){j=j.replace(/^\s+|\s+$/g,"")}}if(!j){j=new Date();k=false}this.date=g.parseDate(j,this.format,this.language,this.formatType);if(k){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var j=this.weekStart,k="<tr>";while(j<this.weekStart+7){k+='<th class="dow">'+a[this.language].daysMin[(j++)%7]+"</th>"}k+="</tr>";this.picker.find(".datetimepicker-days thead").append(k)},fillMonths:function(){var k="",j=0;while(j<12){k+='<span class="month">'+a[this.language].monthsShort[j++]+"</span>"}this.picker.find(".datetimepicker-months td").html(k)},fill:function(){if(this.date==null||this.viewDate==null){return}var H=new Date(this.viewDate),u=H.getUTCFullYear(),I=H.getUTCMonth(),n=H.getUTCDate(),D=H.getUTCHours(),y=H.getUTCMinutes(),z=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,E=this.startDate!==-Infinity?this.startDate.getUTCMonth()+1:-Infinity,q=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,A=this.endDate!==Infinity?this.endDate.getUTCMonth()+1:Infinity,r=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),G=new Date();this.setTitle(".datetimepicker-days",a[this.language].months[I]+" "+u);if(this.formatViewType=="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+a[this.language].months[I]+" "+u);this.setTitle(".datetimepicker-minutes",n+" "+a[this.language].months[I]+" "+u)}this.picker.find("tfoot th.today").text(a[this.language].today||a.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(a[this.language].clear||a.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var K=h(u,I-1,28,0,0,0,0),C=g.getDaysInMonth(K.getUTCFullYear(),K.getUTCMonth());K.setUTCDate(C);K.setUTCDate(C-(K.getUTCDay()-this.weekStart+7)%7);var j=new Date(K);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var s=[];var v;while(K.valueOf()<j){if(K.getUTCDay()==this.weekStart){s.push("<tr>")}v="";if(K.getUTCFullYear()<u||(K.getUTCFullYear()==u&&K.getUTCMonth()<I)){v+=" old"}else{if(K.getUTCFullYear()>u||(K.getUTCFullYear()==u&&K.getUTCMonth()>I)){v+=" new"}}if(this.todayHighlight&&K.getUTCFullYear()==G.getFullYear()&&K.getUTCMonth()==G.getMonth()&&K.getUTCDate()==G.getDate()){v+=" today"}if(K.valueOf()==r){v+=" active"}if((K.valueOf()+86400000)<=this.startDate||K.valueOf()>this.endDate||f.inArray(K.getUTCDay(),this.daysOfWeekDisabled)!==-1||f.inArray(K.toDateString(),this.datesDisabled)!==-1){v+=" disabled"}s.push('<td class="day'+v+'">'+K.getUTCDate()+"</td>");if(K.getUTCDay()==this.weekEnd){s.push("</tr>")}K.setUTCDate(K.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(s.join(""));s=[];var w="",F="",t="";var l=this.hoursDisabled||[];for(var B=0;B<24;B++){if(l.indexOf(B)!==-1){continue}var x=h(u,I,n,B);v="";if((x.valueOf()+3600000)<=this.startDate||x.valueOf()>this.endDate){v+=" disabled"}else{if(D==B){v+=" active"}}if(this.showMeridian&&a[this.language].meridiem.length==2){F=(B<12?a[this.language].meridiem[0]:a[this.language].meridiem[1]);if(F!=t){if(t!=""){s.push("</fieldset>")}s.push('<fieldset class="hour"><legend>'+F.toUpperCase()+"</legend>")}t=F;w=(B%12?B%12:12);s.push('<span class="hour'+v+" hour_"+(B<12?"am":"pm")+'">'+w+"</span>");if(B==23){s.push("</fieldset>")}}else{w=B+":00";s.push('<span class="hour'+v+'">'+w+"</span>")}}this.picker.find(".datetimepicker-hours td").html(s.join(""));s=[];w="",F="",t="";var m=this.minutesDisabled||[];for(var B=0;B<60;B+=this.minuteStep){if(m.indexOf(B)!==-1){continue}var x=h(u,I,n,D,B,0);v="";if(x.valueOf()<this.startDate||x.valueOf()>this.endDate){v+=" disabled"}else{if(Math.floor(y/this.minuteStep)==Math.floor(B/this.minuteStep)){v+=" active"}}if(this.showMeridian&&a[this.language].meridiem.length==2){F=(D<12?a[this.language].meridiem[0]:a[this.language].meridiem[1]);if(F!=t){if(t!=""){s.push("</fieldset>")}s.push('<fieldset class="minute"><legend>'+F.toUpperCase()+"</legend>")}t=F;w=(D%12?D%12:12);s.push('<span class="minute'+v+'">'+w+":"+(B<10?"0"+B:B)+"</span>");if(B==59){s.push("</fieldset>")}}else{w=B+":00";s.push('<span class="minute'+v+'">'+D+":"+(B<10?"0"+B:B)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(s.join(""));var L=this.date.getUTCFullYear();var p=this.setTitle(".datetimepicker-months",u).end().find("span").removeClass("active");if(L==u){var o=p.length-12;p.eq(this.date.getUTCMonth()+o).addClass("active")}if(u<z||u>q){p.addClass("disabled")}if(u==z){p.slice(0,E+1).addClass("disabled")}if(u==q){p.slice(A).addClass("disabled")}s="";u=parseInt(u/10,10)*10;var J=this.setTitle(".datetimepicker-years",u+"-"+(u+9)).end().find("td");u-=1;for(var B=-1;B<11;B++){s+='<span class="year'+(B==-1||B==10?" old":"")+(L==u?" active":"")+(u<z||u>q?" disabled":"")+'">'+u+"</span>";u+=1}J.html(s);this.place()},updateNavArrows:function(){var n=new Date(this.viewDate),l=n.getUTCFullYear(),m=n.getUTCMonth(),k=n.getUTCDate(),j=n.getUTCHours();switch(this.viewMode){case 0:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()&&k<=this.startDate.getUTCDate()&&j<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()&&k>=this.endDate.getUTCDate()&&j>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()&&k<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()&&k>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(k){k.preventDefault();k.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var j=k.originalEvent;var m=j.wheelDelta;var l=m>0?1:(m===0)?0:-1;if(this.wheelViewModeNavigationInverseDirection){l=-l}this.showMode(l);setTimeout(f.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(n){n.stopPropagation();n.preventDefault();var o=f(n.target).closest("span, td, th, legend");if(o.is("."+this.icontype)){o=f(o).parent().closest("span, td, th, legend")}if(o.length==1){if(o.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(o[0].nodeName.toLowerCase()){case"th":switch(o[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var j=g.modes[this.viewMode].navStep*(o[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,j);break;case 1:this.viewDate=this.moveDate(this.viewDate,j);break;case 2:this.viewDate=this.moveMonth(this.viewDate,j);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,j);break}this.fill();this.element.trigger({type:o[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var k=new Date();k=h(k.getFullYear(),k.getMonth(),k.getDate(),k.getHours(),k.getMinutes(),k.getSeconds(),0);if(k<this.startDate){k=this.startDate}else{if(k>this.endDate){k=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(k);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!o.is(".disabled")){var q=this.viewDate.getUTCFullYear(),p=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCDate(),s=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),t=this.viewDate.getUTCSeconds();if(o.is(".month")){this.viewDate.setUTCDate(1);p=o.parent().find("span").index(o);r=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(p);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".year")){this.viewDate.setUTCDate(1);q=parseInt(o.text(),10)||0;this.viewDate.setUTCFullYear(q);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".hour")){s=parseInt(o.text(),10)||0;if(o.hasClass("hour_am")||o.hasClass("hour_pm")){if(s==12&&o.hasClass("hour_am")){s=0}else{if(s!=12&&o.hasClass("hour_pm")){s+=12}}}this.viewDate.setUTCHours(s);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".minute")){l=parseInt(o.text().substr(o.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(l);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(q,p,r,s,l,t,0))}}}}}if(this.viewMode!=0){var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(o.is(".day")&&!o.is(".disabled")){var r=parseInt(o.text(),10)||1;var q=this.viewDate.getUTCFullYear(),p=this.viewDate.getUTCMonth(),s=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),t=this.viewDate.getUTCSeconds();if(o.is(".old")){if(p===0){p=11;q-=1}else{p-=1}}else{if(o.is(".new")){if(p==11){p=0;q+=1}else{p+=1}}}this.viewDate.setUTCFullYear(q);this.viewDate.setUTCMonth(p,r);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(q,p,r,s,l,t,0))}}var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(j,l){if(!l||l=="date"){this.date=j}if(!l||l=="view"){this.viewDate=j}this.fill();this.setValue();var k;if(this.isInput){k=this.element}else{if(this.component){k=this.element.find("input")}}if(k){k.change();if(this.autoclose&&(!l||l=="date")){}}this.element.trigger({type:"changeDate",date:this.getDate()});if(j==null){this.date=this.viewDate}},moveMinute:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCMinutes(l.getUTCMinutes()+(j*this.minuteStep));return l},moveHour:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCHours(l.getUTCHours()+j);return l},moveDate:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCDate(l.getUTCDate()+j);return l},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m==1){p=k==-1?function(){return n.getUTCMonth()==o}:function(){return n.getUTCMonth()!=q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!=n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(k,j){return this.moveMonth(k,j*12)},dateWithinRange:function(j){return j>=this.startDate&&j<=this.endDate},keydown:function(n){if(this.picker.is(":not(:visible)")){if(n.keyCode==27){this.show()}return}var p=false,k,q,o,r,j;switch(n.keyCode){case 27:this.hide();n.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}k=n.keyCode==37?-1:1;viewMode=this.viewMode;if(n.ctrlKey){viewMode+=2}else{if(n.shiftKey){viewMode+=1}}if(viewMode==4){r=this.moveYear(this.date,k);j=this.moveYear(this.viewDate,k)}else{if(viewMode==3){r=this.moveMonth(this.date,k);j=this.moveMonth(this.viewDate,k)}else{if(viewMode==2){r=this.moveDate(this.date,k);j=this.moveDate(this.viewDate,k)}else{if(viewMode==1){r=this.moveHour(this.date,k);j=this.moveHour(this.viewDate,k)}else{if(viewMode==0){r=this.moveMinute(this.date,k);j=this.moveMinute(this.viewDate,k)}}}}}if(this.dateWithinRange(r)){this.date=r;this.viewDate=j;this.setValue();this.update();n.preventDefault();p=true}break;case 38:case 40:if(!this.keyboardNavigation){break}k=n.keyCode==38?-1:1;viewMode=this.viewMode;if(n.ctrlKey){viewMode+=2}else{if(n.shiftKey){viewMode+=1}}if(viewMode==4){r=this.moveYear(this.date,k);j=this.moveYear(this.viewDate,k)}else{if(viewMode==3){r=this.moveMonth(this.date,k);j=this.moveMonth(this.viewDate,k)}else{if(viewMode==2){r=this.moveDate(this.date,k*7);j=this.moveDate(this.viewDate,k*7)}else{if(viewMode==1){if(this.showMeridian){r=this.moveHour(this.date,k*6);j=this.moveHour(this.viewDate,k*6)}else{r=this.moveHour(this.date,k*4);j=this.moveHour(this.viewDate,k*4)}}else{if(viewMode==0){r=this.moveMinute(this.date,k*4);j=this.moveMinute(this.viewDate,k*4)}}}}}if(this.dateWithinRange(r)){this.date=r;this.viewDate=j;this.setValue();this.update();n.preventDefault();p=true}break;case 13:if(this.viewMode!=0){var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}n.preventDefault();break;case 9:this.hide();break}if(p){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(j){if(j){var k=Math.max(0,Math.min(g.modes.length-1,this.viewMode+j));if(k>=this.minView&&k<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:k});this.viewMode=k}}this.picker.find(">div").hide().filter(".datetimepicker-"+g.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(j){this._setDate(null,"date")},convertViewModeText:function(j){switch(j){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=f.fn.datetimepicker;f.fn.datetimepicker=function(l){var j=Array.apply(null,arguments);j.shift();var k;this.each(function(){var o=f(this),n=o.data("datetimepicker"),m=typeof l=="object"&&l;if(!n){o.data("datetimepicker",(n=new i(this,f.extend({},f.fn.datetimepicker.defaults,m))))}if(typeof l=="string"&&typeof n[l]=="function"){k=n[l].apply(n,j);if(k!==c){return false}}});if(k!==c){return k}else{return this}};f.fn.datetimepicker.defaults={};f.fn.datetimepicker.Constructor=i;var a=f.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var g={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(j){return(((j%4===0)&&(j%100!==0))||(j%400===0))},getDaysInMonth:function(j,k){return[31,(g.isLeapYear(j)?29:28),31,30,31,30,31,31,30,31,30,31][k]},getDefaultFormat:function(j,k){if(j=="standard"){if(k=="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(j=="php"){if(k=="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(j){if(j=="standard"){return/t|hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(j=="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(m,k){var j=m.replace(this.validParts(k),"\0").split("\0"),l=m.match(this.validParts(k));if(!j||!j.length||!l||l.length==0){throw new Error("Invalid date format.")}return{separators:j,parts:l}},parseDate:function(n,w,q,u){if(n instanceof Date){var y=new Date(n.valueOf()-n.getTimezoneOffset()*60000);y.setMilliseconds(0);return y}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(n)){w=this.parseFormat("yyyy-mm-dd",u)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(n)){w=this.parseFormat("yyyy-mm-dd hh:ii",u)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(n)){w=this.parseFormat("yyyy-mm-dd hh:ii:ss",u)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var z=/([-+]\d+)([dmwy])/,o=n.match(/([-+]\d+)([dmwy])/g),j,m;n=new Date();for(var p=0;p<o.length;p++){j=z.exec(o[p]);m=parseInt(j[1]);switch(j[2]){case"d":n.setUTCDate(n.getUTCDate()+m);break;case"m":n=i.prototype.moveMonth.call(i.prototype,n,m);break;case"w":n.setUTCDate(n.getUTCDate()+m*7);break;case"y":n=i.prototype.moveYear.call(i.prototype,n,m);break}}return h(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),n.getUTCHours(),n.getUTCMinutes(),n.getUTCSeconds(),0)}var o=n&&n.toString().match(this.nonpunctuation)||[],n=new Date(0,0,0,0,0,0,0),t={},v=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P"],x={hh:function(B,s){return B.setUTCHours(s)},h:function(B,s){return B.setUTCHours(s)},HH:function(B,s){return B.setUTCHours(s==12?0:s)},H:function(B,s){return B.setUTCHours(s==12?0:s)},ii:function(B,s){return B.setUTCMinutes(s)},i:function(B,s){return B.setUTCMinutes(s)},ss:function(B,s){return B.setUTCSeconds(s)},s:function(B,s){return B.setUTCSeconds(s)},yyyy:function(B,s){return B.setUTCFullYear(s)},yy:function(B,s){return B.setUTCFullYear(2000+s)},m:function(B,s){s-=1;while(s<0){s+=12}s%=12;B.setUTCMonth(s);while(B.getUTCMonth()!=s){if(isNaN(B.getUTCMonth())){return B}else{B.setUTCDate(B.getUTCDate()-1)}}return B},d:function(B,s){return B.setUTCDate(s)},p:function(B,s){return B.setUTCHours(s==1?B.getUTCHours()+12:B.getUTCHours())}},l,r,j;x.M=x.MM=x.mm=x.m;x.dd=x.d;x.P=x.p;n=h(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours(),n.getMinutes(),n.getSeconds());if(o.length==w.parts.length){for(var p=0,k=w.parts.length;p<k;p++){l=parseInt(o[p],10);j=w.parts[p];if(isNaN(l)){switch(j){case"MM":r=f(a[q].months).filter(function(){var s=this.slice(0,o[p].length),B=o[p].slice(0,s.length);return s==B});l=f.inArray(r[0],a[q].months)+1;break;case"M":r=f(a[q].monthsShort).filter(function(){var s=this.slice(0,o[p].length),B=o[p].slice(0,s.length);return s.toLowerCase()==B.toLowerCase()});l=f.inArray(r[0],a[q].monthsShort)+1;break;case"p":case"P":l=f.inArray(o[p].toLowerCase(),a[q].meridiem);break}}t[j]=l}for(var p=0,A;p<v.length;p++){A=v[p];if(A in t&&!isNaN(t[A])){x[A](n,t[A])}}}return n},formatDate:function(j,o,q,m){if(j==null){return""}var p;if(m=="standard"){p={t:j.getTime(),yy:j.getUTCFullYear().toString().substring(2),yyyy:j.getUTCFullYear(),m:j.getUTCMonth()+1,M:a[q].monthsShort[j.getUTCMonth()],MM:a[q].months[j.getUTCMonth()],d:j.getUTCDate(),D:a[q].daysShort[j.getUTCDay()],DD:a[q].days[j.getUTCDay()],p:(a[q].meridiem.length==2?a[q].meridiem[j.getUTCHours()<12?0:1]:""),h:j.getUTCHours(),i:j.getUTCMinutes(),s:j.getUTCSeconds()};if(a[q].meridiem.length==2){p.H=(p.h%12==0?12:p.h%12)}else{p.H=p.h}p.HH=(p.H<10?"0":"")+p.H;p.P=p.p.toUpperCase();p.hh=(p.h<10?"0":"")+p.h;p.ii=(p.i<10?"0":"")+p.i;p.ss=(p.s<10?"0":"")+p.s;p.dd=(p.d<10?"0":"")+p.d;p.mm=(p.m<10?"0":"")+p.m}else{if(m=="php"){p={y:j.getUTCFullYear().toString().substring(2),Y:j.getUTCFullYear(),F:a[q].months[j.getUTCMonth()],M:a[q].monthsShort[j.getUTCMonth()],n:j.getUTCMonth()+1,t:g.getDaysInMonth(j.getUTCFullYear(),j.getUTCMonth()),j:j.getUTCDate(),l:a[q].days[j.getUTCDay()],D:a[q].daysShort[j.getUTCDay()],w:j.getUTCDay(),N:(j.getUTCDay()==0?7:j.getUTCDay()),S:(j.getUTCDate()%10<=a[q].suffix.length?a[q].suffix[j.getUTCDate()%10-1]:""),a:(a[q].meridiem.length==2?a[q].meridiem[j.getUTCHours()<12?0:1]:""),g:(j.getUTCHours()%12==0?12:j.getUTCHours()%12),G:j.getUTCHours(),i:j.getUTCMinutes(),s:j.getUTCSeconds()};p.m=(p.n<10?"0":"")+p.n;p.d=(p.j<10?"0":"")+p.j;p.A=p.a.toString().toUpperCase();p.h=(p.g<10?"0":"")+p.g;p.H=(p.G<10?"0":"")+p.G;p.i=(p.i<10?"0":"")+p.i;p.s=(p.s<10?"0":"")+p.s}else{throw new Error("Invalid format type.")}}var j=[],n=f.extend([],o.separators);for(var l=0,k=o.parts.length;l<k;l++){if(n.length){j.push(n.shift())}j.push(p[o.parts[l]])}if(n.length){j.push(n.shift())}return j.join("")},convertViewMode:function(j){switch(j){case 4:case"decade":j=4;break;case 3:case"year":j=3;break;case 2:case"month":j=2;break;case 1:case"day":j=1;break;case 0:case"hour":j=0;break}return j},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};g.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+g.headTemplate+"<tbody></tbody>"+g.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+"</table></div></div>";g.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+g.headTemplateV3+"<tbody></tbody>"+g.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+"</table></div></div>";f.fn.datetimepicker.DPGlobal=g;f.fn.datetimepicker.noConflict=function(){f.fn.datetimepicker=b;return this};f(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(k){var j=f(this);if(j.data("datetimepicker")){return}k.preventDefault();j.datetimepicker("show")});f(function(){f('[data-provide="datetimepicker-inline"]').datetimepicker()})})); \ No newline at end of file +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(d,f){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===f){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function a(){var q,k,p,l,j,n,m,o;k=(new Date()).toString();p=((m=k.split("(")[1])!=null?m.slice(0,-1):0)||k.split(" ");if(p instanceof Array){n=[];for(var l=0,j=p.length;l<j;l++){o=p[l];if((q=(m=o.match(/\b[A-Z]+\b/))!==null)?m[0]:0){n.push(q)}}p=n.pop()}return p}function h(){return new Date(Date.UTC.apply(Date,arguments))}var g=function(k,j){var m=this;this.element=d(k);this.container=j.container||"body";this.language=j.language||this.element.data("date-language")||"en";this.language=this.language in e?this.language:this.language.split("-")[0];this.language=this.language in e?this.language:"en";this.isRTL=e[this.language].rtl||false;this.formatType=j.formatType||this.element.data("format-type")||"standard";this.format=c.parseFormat(j.format||this.element.data("date-format")||e[this.language].format||c.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=j.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=j.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=j.linkField||this.element.data("link-field")||false;this.linkFormat=c.parseFormat(j.linkFormat||this.element.data("link-format")||c.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=j.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=j.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=j.showMeridian||this.element.data("show-meridian")||false;this.initialDate=j.initialDate||new Date();this.zIndex=j.zIndex||this.element.data("z-index")||f;this.title=typeof j.title==="undefined"?false:j.title;this.timezone=j.timezone||a();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(n){if(d(n.target).closest(".datetimepicker").length===0){m.hide()}};this.formatViewType="datetime";if("formatViewType" in j){this.formatViewType=j.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in j){this.minView=j.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=c.convertViewMode(this.minView);this.maxView=c.modes.length-1;if("maxView" in j){this.maxView=j.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=c.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in j){this.wheelViewModeNavigation=j.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in j){this.wheelViewModeNavigationInverseDirection=j.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in j){this.wheelViewModeNavigationDelay=j.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in j){this.startViewMode=j.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=c.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in j){this.viewSelect=j.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=c.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in j){this.forceParse=j.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var l=this.bootcssVer===3?c.templateV3:c.template;while(l.indexOf("{iconType}")!==-1){l=l.replace("{iconType}",this.icontype)}while(l.indexOf("{leftArrow}")!==-1){l=l.replace("{leftArrow}",this.icons.leftArrow)}while(l.indexOf("{rightArrow}")!==-1){l=l.replace("{rightArrow}",this.icons.rightArrow)}this.picker=d(l).appendTo(this.isInline?this.element:this.container).on({click:d.proxy(this.click,this),mousedown:d.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(d.fn.mousewheel){this.picker.on({mousewheel:d.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var i=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(i).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}d(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in j){this.autoclose=j.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in j){this.keyboardNavigation=j.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(j.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(j.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(j.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof j.weekStart!=="undefined"){this.weekStart=j.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof e[this.language].weekStart!=="undefined"){this.weekStart=e[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(n){var p=(j.onRenderDay||function(){return[]})(n);if(typeof p==="string"){p=[p]}var o=["day"];return o.concat((p?p:[]))};this.onRenderHour=function(n){var p=(j.onRenderHour||function(){return[]})(n);var o=["hour"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.onRenderMinute=function(n){var p=(j.onRenderMinute||function(){return[]})(n);var o=["minute"];if(typeof p==="string"){p=[p]}if(n<this.startDate||n>this.endDate){o.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(n.getUTCMinutes()/this.minuteStep)){o.push("active")}}return o.concat((p?p:[]))};this.onRenderYear=function(o){var q=(j.onRenderYear||function(){return[]})(o);var p=["year"];if(typeof q==="string"){q=[q]}if(this.date.getUTCFullYear()===o.getUTCFullYear()){p.push("active")}var n=o.getUTCFullYear();var r=this.endDate.getUTCFullYear();if(o<this.startDate||n>r){p.push("disabled")}return p.concat((q?q:[]))};this.onRenderMonth=function(n){var p=(j.onRenderMonth||function(){return[]})(n);var o=["month"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(j.startDate||this.element.data("date-startdate"));this.setEndDate(j.endDate||this.element.data("date-enddate"));this.setDatesDisabled(j.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(j.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(j.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(j.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};g.prototype={constructor:g,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}],[this.component,{click:d.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:d.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:d.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(i){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();d(window).on("resize",d.proxy(this.place,this));if(i){i.stopPropagation();i.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();d(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){d(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();d(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var i=this.getUTCDate();if(i===null){return null}return new Date(i.getTime()+(i.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(i){this.initialDate=i},setDate:function(i){this.setUTCDate(new Date(i.getTime()-(i.getTimezoneOffset()*60000)))},setUTCDate:function(i){if(i>=this.startDate&&i<=this.endDate){this.date=i;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:i,startDate:this.startDate,endDate:this.endDate})}},setFormat:function(j){this.format=c.parseFormat(j,this.formatType);var i;if(this.isInput){i=this.element}else{if(this.component){i=this.element.find("input")}}if(i&&i.val()){this.setValue()}},setValue:function(){var i=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(i)}this.element.data("date",i)}else{this.element.val(i)}if(this.linkField){d("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(i){i=i||this.format;return c.formatDate(this.date,i,this.language,this.formatType,this.timezone)},setStartDate:function(i){this.startDate=i||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=c.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(i){this.endDate=i||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=c.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!d.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var i=this;this.datesDisabled=d.map(this.datesDisabled,function(k){return c.parseDate(k,i.format,i.language,i.formatType,i.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(i,j){return this.picker.find(i).find("th:eq(1)").text(this.title===false?j:this.title)},setDaysOfWeekDisabled:function(i){this.daysOfWeekDisabled=i||[];if(!d.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=d.map(this.daysOfWeekDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(i){this.minutesDisabled=i||[];if(!d.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=d.map(this.minutesDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(i){this.hoursDisabled=i||[];if(!d.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=d.map(this.hoursDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var j=0;d("div").each(function(){var o=parseInt(d(this).css("zIndex"),10);if(o>j){j=o}});this.zIndex=j+10}var n,m,l,k;if(this.container instanceof d){k=this.container.offset()}else{k=d(this.container).offset()}if(this.component){n=this.component.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.component.outerWidth()-this.picker.outerWidth()}}else{n=this.element.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.element.outerWidth()-this.picker.outerWidth()}}var i=document.body.clientWidth||window.innerWidth;if(l+220>i){l=i-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){m=n.top-this.picker.outerHeight()}else{m=n.top+this.height}m=m-k.top;l=l-k.left;this.picker.css({top:m,left:l,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var i,j=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){i=arguments[0];j=true}else{i=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof i==="string"){i=i.replace(/^\s+|\s+$/g,"")}}if(!i){i=new Date();j=false}if(typeof i==="string"){if(new RegExp(this.hour_minute).test(i)||new RegExp(this.hour_minute+":[0-5][0-9]").test(i)){i=this.getDate()}}this.date=c.parseDate(i,this.format,this.language,this.formatType,this.timezone);if(j){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var i=this.weekStart,j="<tr>";while(i<this.weekStart+7){j+='<th class="dow">'+e[this.language].daysMin[(i++)%7]+"</th>"}j+="</tr>";this.picker.find(".datetimepicker-days thead").append(j)},fillMonths:function(){var l="";var m=new Date(this.viewDate);for(var k=0;k<12;k++){m.setUTCMonth(k);var j=this.onRenderMonth(m);l+='<span class="'+j.join(" ")+'">'+e[this.language].monthsShort[k]+"</span>"}this.picker.find(".datetimepicker-months td").html(l)},fill:function(){if(!this.date||!this.viewDate){return}var E=new Date(this.viewDate),t=E.getUTCFullYear(),G=E.getUTCMonth(),n=E.getUTCDate(),A=E.getUTCHours(),w=this.startDate.getUTCFullYear(),B=this.startDate.getUTCMonth(),p=this.endDate.getUTCFullYear(),x=this.endDate.getUTCMonth()+1,q=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),D=new Date();this.setTitle(".datetimepicker-days",e[this.language].months[G]+" "+t);if(this.formatViewType==="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+e[this.language].months[G]+" "+t);this.setTitle(".datetimepicker-minutes",n+" "+e[this.language].months[G]+" "+t)}this.picker.find("tfoot th.today").text(e[this.language].today||e.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(e[this.language].clear||e.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var I=h(t,G-1,28,0,0,0,0),z=c.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());I.setUTCDate(z);I.setUTCDate(z-(I.getUTCDay()-this.weekStart+7)%7);var j=new Date(I);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var r=[];var F;while(I.valueOf()<j){if(I.getUTCDay()===this.weekStart){r.push("<tr>")}F=this.onRenderDay(I);if(I.getUTCFullYear()<t||(I.getUTCFullYear()===t&&I.getUTCMonth()<G)){F.push("old")}else{if(I.getUTCFullYear()>t||(I.getUTCFullYear()===t&&I.getUTCMonth()>G)){F.push("new")}}if(this.todayHighlight&&I.getUTCFullYear()===D.getFullYear()&&I.getUTCMonth()===D.getMonth()&&I.getUTCDate()===D.getDate()){F.push("today")}if(I.valueOf()===q){F.push("active")}if((I.valueOf()+86400000)<=this.startDate||I.valueOf()>this.endDate||d.inArray(I.getUTCDay(),this.daysOfWeekDisabled)!==-1||d.inArray(I.toDateString(),this.datesDisabled)!==-1){F.push("disabled")}r.push('<td class="'+F.join(" ")+'">'+I.getUTCDate()+"</td>");if(I.getUTCDay()===this.weekEnd){r.push("</tr>")}I.setUTCDate(I.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(r.join(""));r=[];var u="",C="",s="";var l=this.hoursDisabled||[];E=new Date(this.viewDate);for(var y=0;y<24;y++){E.setUTCHours(y);F=this.onRenderHour(E);if(l.indexOf(y)!==-1){F.push("disabled")}var v=h(t,G,n,y);if((v.valueOf()+3600000)<=this.startDate||v.valueOf()>this.endDate){F.push("disabled")}else{if(A===y){F.push("active")}}if(this.showMeridian&&e[this.language].meridiem.length===2){C=(y<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="hour"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(y%12?y%12:12);if(y<12){F.push("hour_am")}else{F.push("hour_pm")}r.push('<span class="'+F.join(" ")+'">'+u+"</span>");if(y===23){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+u+"</span>")}}this.picker.find(".datetimepicker-hours td").html(r.join(""));r=[];u="";C="";s="";var m=this.minutesDisabled||[];E=new Date(this.viewDate);for(var y=0;y<60;y+=this.minuteStep){if(m.indexOf(y)!==-1){continue}E.setUTCMinutes(y);E.setUTCSeconds(0);F=this.onRenderMinute(E);if(this.showMeridian&&e[this.language].meridiem.length===2){C=(A<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="minute"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(A%12?A%12:12);r.push('<span class="'+F.join(" ")+'">'+u+":"+(y<10?"0"+y:y)+"</span>");if(y===59){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+A+":"+(y<10?"0"+y:y)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(r.join(""));var J=this.date.getUTCFullYear();var o=this.setTitle(".datetimepicker-months",t).end().find(".month").removeClass("active");if(J===t){o.eq(this.date.getUTCMonth()).addClass("active")}if(t<w||t>p){o.addClass("disabled")}if(t===w){o.slice(0,B).addClass("disabled")}if(t===p){o.slice(x).addClass("disabled")}r="";t=parseInt(t/10,10)*10;var H=this.setTitle(".datetimepicker-years",t+"-"+(t+9)).end().find("td");t-=1;E=new Date(this.viewDate);for(var y=-1;y<11;y++){E.setUTCFullYear(t);F=this.onRenderYear(E);if(y===-1||y===10){F.push(b)}r+='<span class="'+F.join(" ")+'">'+t+"</span>";t+=1}H.html(r);this.place()},updateNavArrows:function(){var m=new Date(this.viewDate),k=m.getUTCFullYear(),l=m.getUTCMonth(),j=m.getUTCDate(),i=m.getUTCHours();switch(this.viewMode){case 0:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()&&i<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()&&i>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(k<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(j){j.preventDefault();j.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var i=j.originalEvent;var l=i.wheelDelta;var k=l>0?1:(l===0)?0:-1;if(this.wheelViewModeNavigationInverseDirection){k=-k}this.showMode(k);setTimeout(d.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(m){m.stopPropagation();m.preventDefault();var n=d(m.target).closest("span, td, th, legend");if(n.is("."+this.icontype)){n=d(n).parent().closest("span, td, th, legend")}if(n.length===1){if(n.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(n[0].nodeName.toLowerCase()){case"th":switch(n[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=c.modes[this.viewMode].navStep*(n[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,i);break;case 1:this.viewDate=this.moveDate(this.viewDate,i);break;case 2:this.viewDate=this.moveMonth(this.viewDate,i);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,i);break}this.fill();this.element.trigger({type:n[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var j=new Date();j=h(j.getFullYear(),j.getMonth(),j.getDate(),j.getHours(),j.getMinutes(),j.getSeconds(),0);if(j<this.startDate){j=this.startDate}else{if(j>this.endDate){j=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(j);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!n.is(".disabled")){var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),q=this.viewDate.getUTCDate(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".month")){this.viewDate.setUTCDate(1);o=n.parent().find("span").index(n);q=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(o);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".year")){this.viewDate.setUTCDate(1);p=parseInt(n.text(),10)||0;this.viewDate.setUTCFullYear(p);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".hour")){r=parseInt(n.text(),10)||0;if(n.hasClass("hour_am")||n.hasClass("hour_pm")){if(r===12&&n.hasClass("hour_am")){r=0}else{if(r!==12&&n.hasClass("hour_pm")){r+=12}}}this.viewDate.setUTCHours(r);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".minute")){k=parseInt(n.text().substr(n.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(k);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(p,o,q,r,k,s,0))}}}}}if(this.viewMode!==0){var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(n.is(".day")&&!n.is(".disabled")){var q=parseInt(n.text(),10)||1;var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".old")){if(o===0){o=11;p-=1}else{o-=1}}else{if(n.is(".new")){if(o===11){o=0;p+=1}else{o+=1}}}this.viewDate.setUTCFullYear(p);this.viewDate.setUTCMonth(o,q);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(p,o,q,r,k,s,0))}}var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(i,k){if(!k||k==="date"){this.date=i}if(!k||k==="view"){this.viewDate=i}this.fill();this.setValue();var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j){j.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(i===null){this.date=this.viewDate}},moveMinute:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCMinutes(k.getUTCMinutes()+(i*this.minuteStep));return k},moveHour:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCHours(k.getUTCHours()+i);return k},moveDate:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCDate(k.getUTCDate()+i);return k},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m===1){p=k===-1?function(){return n.getUTCMonth()===o}:function(){return n.getUTCMonth()!==q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!==n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(j,i){return this.moveMonth(j,i*12)},dateWithinRange:function(i){return i>=this.startDate&&i<=this.endDate},keydown:function(o){if(this.picker.is(":not(:visible)")){if(o.keyCode===27){this.show()}return}var k=false,j,i,n;switch(o.keyCode){case 27:this.hide();o.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}j=o.keyCode===37?-1:1;var m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j);n=this.moveDate(this.viewDate,j)}else{if(m===1){i=this.moveHour(this.date,j);n=this.moveHour(this.viewDate,j)}else{if(m===0){i=this.moveMinute(this.date,j);n=this.moveMinute(this.viewDate,j)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 38:case 40:if(!this.keyboardNavigation){break}j=o.keyCode===38?-1:1;m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j*7);n=this.moveDate(this.viewDate,j*7)}else{if(m===1){if(this.showMeridian){i=this.moveHour(this.date,j*6);n=this.moveHour(this.viewDate,j*6)}else{i=this.moveHour(this.date,j*4);n=this.moveHour(this.viewDate,j*4)}}else{if(m===0){i=this.moveMinute(this.date,j*4);n=this.moveMinute(this.viewDate,j*4)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 13:if(this.viewMode!==0){var p=this.viewMode;this.showMode(-1);this.fill();if(p===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}o.preventDefault();break;case 9:this.hide();break}if(k){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(i){if(i){var j=Math.max(0,Math.min(c.modes.length-1,this.viewMode+i));if(j>=this.minView&&j<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:j});this.viewMode=j}}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(i){switch(i){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=d.fn.datetimepicker;d.fn.datetimepicker=function(k){var i=Array.apply(null,arguments);i.shift();var j;this.each(function(){var n=d(this),m=n.data("datetimepicker"),l=typeof k==="object"&&k;if(!m){n.data("datetimepicker",(m=new g(this,d.extend({},d.fn.datetimepicker.defaults,l))))}if(typeof k==="string"&&typeof m[k]==="function"){j=m[k].apply(m,i);if(j!==f){return false}}});if(j!==f){return j}else{return this}};d.fn.datetimepicker.defaults={};d.fn.datetimepicker.Constructor=g;var e=d.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(i){return(((i%4===0)&&(i%100!==0))||(i%400===0))},getDaysInMonth:function(i,j){return[31,(c.isLeapYear(i)?29:28),31,30,31,30,31,31,30,31,30,31][j]},getDefaultFormat:function(i,j){if(i==="standard"){if(j==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(i==="php"){if(j==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(i){if(i==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(i==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(l,j){var i=l.replace(this.validParts(j),"\0").split("\0"),k=l.match(this.validParts(j));if(!i||!i.length||!k||k.length===0){throw new Error("Invalid date format.")}return{separators:i,parts:k}},parseDate:function(A,y,v,j,r){if(A instanceof Date){var u=new Date(A.valueOf()-A.getTimezoneOffset()*60000);u.setMilliseconds(0);return u}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii:ss",j)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(A)){var l=/([-+]\d+)([dmwy])/,q=A.match(/([-+]\d+)([dmwy])/g),t,p;A=new Date();for(var x=0;x<q.length;x++){t=l.exec(q[x]);p=parseInt(t[1]);switch(t[2]){case"d":A.setUTCDate(A.getUTCDate()+p);break;case"m":A=g.prototype.moveMonth.call(g.prototype,A,p);break;case"w":A.setUTCDate(A.getUTCDate()+p*7);break;case"y":A=g.prototype.moveYear.call(g.prototype,A,p);break}}return h(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate(),A.getUTCHours(),A.getUTCMinutes(),A.getUTCSeconds(),0)}var q=A&&A.toString().match(this.nonpunctuation)||[],A=new Date(0,0,0,0,0,0,0),m={},z=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],o={hh:function(s,i){return s.setUTCHours(i)},h:function(s,i){return s.setUTCHours(i)},HH:function(s,i){return s.setUTCHours(i===12?0:i)},H:function(s,i){return s.setUTCHours(i===12?0:i)},ii:function(s,i){return s.setUTCMinutes(i)},i:function(s,i){return s.setUTCMinutes(i)},ss:function(s,i){return s.setUTCSeconds(i)},s:function(s,i){return s.setUTCSeconds(i)},yyyy:function(s,i){return s.setUTCFullYear(i)},yy:function(s,i){return s.setUTCFullYear(2000+i)},m:function(s,i){i-=1;while(i<0){i+=12}i%=12;s.setUTCMonth(i);while(s.getUTCMonth()!==i){if(isNaN(s.getUTCMonth())){return s}else{s.setUTCDate(s.getUTCDate()-1)}}return s},d:function(s,i){return s.setUTCDate(i)},p:function(s,i){return s.setUTCHours(i===1?s.getUTCHours()+12:s.getUTCHours())},z:function(){return r}},B,k,t;o.M=o.MM=o.mm=o.m;o.dd=o.d;o.P=o.p;o.Z=o.z;A=h(A.getFullYear(),A.getMonth(),A.getDate(),A.getHours(),A.getMinutes(),A.getSeconds());if(q.length===y.parts.length){for(var x=0,w=y.parts.length;x<w;x++){B=parseInt(q[x],10);t=y.parts[x];if(isNaN(B)){switch(t){case"MM":k=d(e[v].months).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i===s});B=d.inArray(k[0],e[v].months)+1;break;case"M":k=d(e[v].monthsShort).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i.toLowerCase()===s.toLowerCase()});B=d.inArray(k[0],e[v].monthsShort)+1;break;case"p":case"P":B=d.inArray(q[x].toLowerCase(),e[v].meridiem);break;case"z":case"Z":r;break}}m[t]=B}for(var x=0,n;x<z.length;x++){n=z[x];if(n in m&&!isNaN(m[n])){o[n](A,m[n])}}}return A},formatDate:function(l,q,m,p,o){if(l===null){return""}var k;if(p==="standard"){k={t:l.getTime(),yy:l.getUTCFullYear().toString().substring(2),yyyy:l.getUTCFullYear(),m:l.getUTCMonth()+1,M:e[m].monthsShort[l.getUTCMonth()],MM:e[m].months[l.getUTCMonth()],d:l.getUTCDate(),D:e[m].daysShort[l.getUTCDay()],DD:e[m].days[l.getUTCDay()],p:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),h:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds(),z:o};if(e[m].meridiem.length===2){k.H=(k.h%12===0?12:k.h%12)}else{k.H=k.h}k.HH=(k.H<10?"0":"")+k.H;k.P=k.p.toUpperCase();k.Z=k.z;k.hh=(k.h<10?"0":"")+k.h;k.ii=(k.i<10?"0":"")+k.i;k.ss=(k.s<10?"0":"")+k.s;k.dd=(k.d<10?"0":"")+k.d;k.mm=(k.m<10?"0":"")+k.m}else{if(p==="php"){k={y:l.getUTCFullYear().toString().substring(2),Y:l.getUTCFullYear(),F:e[m].months[l.getUTCMonth()],M:e[m].monthsShort[l.getUTCMonth()],n:l.getUTCMonth()+1,t:c.getDaysInMonth(l.getUTCFullYear(),l.getUTCMonth()),j:l.getUTCDate(),l:e[m].days[l.getUTCDay()],D:e[m].daysShort[l.getUTCDay()],w:l.getUTCDay(),N:(l.getUTCDay()===0?7:l.getUTCDay()),S:(l.getUTCDate()%10<=e[m].suffix.length?e[m].suffix[l.getUTCDate()%10-1]:""),a:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),g:(l.getUTCHours()%12===0?12:l.getUTCHours()%12),G:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds()};k.m=(k.n<10?"0":"")+k.n;k.d=(k.j<10?"0":"")+k.j;k.A=k.a.toString().toUpperCase();k.h=(k.g<10?"0":"")+k.g;k.H=(k.G<10?"0":"")+k.G;k.i=(k.i<10?"0":"")+k.i;k.s=(k.s<10?"0":"")+k.s}else{throw new Error("Invalid format type.")}}var l=[],r=d.extend([],q.separators);for(var n=0,j=q.parts.length;n<j;n++){if(r.length){l.push(r.shift())}l.push(k[q.parts[n]])}if(r.length){l.push(r.shift())}return l.join("")},convertViewMode:function(i){switch(i){case 4:case"decade":i=4;break;case 3:case"year":i=3;break;case 2:case"month":i=2;break;case 1:case"day":i=1;break;case 0:case"hour":i=0;break}return i},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};c.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplate+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+"</table></div></div>";c.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplateV3+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+"</table></div></div>";d.fn.datetimepicker.DPGlobal=c;d.fn.datetimepicker.noConflict=function(){d.fn.datetimepicker=b;return this};d(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(j){var i=d(this);if(i.data("datetimepicker")){return}j.preventDefault();i.datetimepicker("show")});d(function(){d('[data-provide="datetimepicker-inline"]').datetimepicker()})})); \ No newline at end of file diff --git a/e107_web/js/core/all.jquery.js b/e107_web/js/core/all.jquery.js index 18f587ed5..efa5ef078 100644 --- a/e107_web/js/core/all.jquery.js +++ b/e107_web/js/core/all.jquery.js @@ -351,7 +351,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; { var $button = $(this); var $form = $button.closest('form'); - + var form_submited = false; var type = $button.data('loading-icon'); if(type === undefined || $form.length === 0) @@ -365,6 +365,10 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; return false; } + if (form_submited) { + return false; + } + var caption = "<i class='fa fa-spin " + type + " fa-fw'></i>"; caption += "<span>" + $button.text() + "</span>"; @@ -373,6 +377,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; if($button.attr('data-disable') == 'true') { $button.addClass('disabled'); + form_submited = true; } }); @@ -783,6 +788,19 @@ $.ajaxSetup({ $(document).ready(function() { + + // Basic Delete Confirmation + $('input.delete,button.delete,a[data-confirm]').click(function(){ + answer = confirm($(this).attr("data-confirm")); + return answer; // answer is a boolean + }); + + $(".e-confirm").click(function(){ + answer = confirm($(this).attr("title")); + return answer; // answer is a boolean + }); + + //check all $("#check-all").click(function(event){ var val = $(this).val(), selector = '.field-spacer'; diff --git a/e107_web/js/password/jquery.pwdMeter.js b/e107_web/js/password/jquery.pwdMeter.js index 6876184a2..7026262ca 100644 --- a/e107_web/js/password/jquery.pwdMeter.js +++ b/e107_web/js/password/jquery.pwdMeter.js @@ -201,5 +201,9 @@ jQuery.fn.pwdMeter = function(options){ }); } - -})(jQuery) +/** + * ALLWAYS add a semicolon at the end, otherwise + * it may cause issues when js is cached! + * see issue e107inc/e107#2265 + */ +})(jQuery); diff --git a/install.php b/install.php index 3002519b5..252cf97b9 100644 --- a/install.php +++ b/install.php @@ -885,6 +885,7 @@ class e_install */ $extensionCheck = array( + 'pdo' => array('label'=> "PDO (MySQL)", 'status' => extension_loaded('pdo_mysql'), 'url'=> ''), 'xml' => array('label'=> LANINS_050, 'status' => function_exists('utf8_encode'), 'url'=> 'http://php.net/manual/en/ref.xml.php'), 'exif' => array('label'=> LANINS_048, 'status' => function_exists('exif_imagetype'), 'url'=> 'http://php.net/manual/en/book.exif.php'), 'curl' => array('label'=> 'Curl Library', 'status' => function_exists('curl_version'), 'url'=> 'http://php.net/manual/en/book.curl.php'), diff --git a/news.php b/news.php index 224bc5f33..434e3a8b7 100644 --- a/news.php +++ b/news.php @@ -20,1296 +20,9 @@ */ require_once("class2.php"); +require_once(e_PLUGIN."news/news.php"); +exit; -if(!deftrue('e_LEGACY_NEWS')) // subject to removal at any time. -{ - require_once(e_PLUGIN."news/news.php"); - exit; -} -// --------------------- everything below this point will be removed in future -------------------------- - - -e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_'.e_PAGE); - -require_once(e_HANDLER."news_class.php"); -//require_once(e_HANDLER."comment_class.php"); -//$cobj = new comment; - -if (isset($NEWSHEADER)) -{ - require_once(HEADERF); - require_once(FOOTERF); - exit; -} - -e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_news.php'); // Temporary - -$cacheString = 'news.php_default_'; -$action = ''; -$sub_action = ''; -$order = 'news_datestamp'; -$newsfrom = 0; - -if (!defined('ITEMVIEW')) -{ - define('ITEMVIEW', varset($pref['newsposts'],15)); -} - -// ?all and ?cat.x and ?tag are the same listing functions - just filtered differently. -// NEWSLIST_LIMIT is suitable for all - -if(!defined("NEWSLIST_LIMIT")) -{ - define("NEWSLIST_LIMIT", varset($pref['news_list_limit'],15)); -} - -$defTemplate = e107::getPref('news_default_template'); - -if (e_QUERY) //TODO add support for $_GET['cat'] and $_GET['mode'] and phase-out the x.x.x format. -{ - - $tmp = explode(".",e_QUERY); - $action = $tmp[0]; // At least one parameter here - $sub_action = varset($tmp[1],''); // Usually a numeric category, or numeric news item number, but don't presume yet - // $id = varset($tmp[2],''); // ID of specific news item where required - $newsfrom = intval(varset($tmp[2],0)); // Item number for first item on multi-page lists - $cacheString = 'news.php_'.e_QUERY; -} -else -{ - - $opt = array('default'=>'', 'list'=>'all'); - $action = varset($opt[$defTemplate],''); -} - -//$newsfrom = (!is_numeric($action) || !e_QUERY ? 0 : ($action ? $action : e_QUERY)); - -// Usually the first query parameter is the action. -// For any of the 'list' modes (inc month, day), the action being second is a legacy situation -// .... which can hopefully go sometime -//SecretR: Gone, gone... -if (is_numeric($action) && isset($tmp[1]) && (($tmp[1] == 'list') || ($tmp[1] == 'month') || ($tmp[1] == 'day'))) -{ - $action = $tmp[1]; - $sub_action = varset($tmp[0],''); -} - - - -if ($action == 'all' || $action == 'cat') -{ - $sub_action = intval(varset($tmp[1],0)); -} - - - - - -/* -Variables Used: -$action - the basic display format/filter -$sub_action - category number or news item number -$newsfrom - first item number in list (default 0) - derived from nextprev -$order - sets the listing order for 'list' format -*/ - - -$ix = new news; -$nobody_regexp = "'(^|,)(".str_replace(",", "|", e_UC_NOBODY).")(,|$)'"; - -// URL settings (nextprev) - $newsUrlparms = array('page' => '--FROM--'); - if($sub_action) - { - - switch ($action) - { - case 'list': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/category'; - break; - - case 'cat': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/short'; - break; - - case 'day': - case 'month': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/'.$action; - break; - - default: - $newsRoute = 'list/items'; - break; - } - } - elseif($action == 'all') - { - $newsRoute = 'list/all'; - $newsUrlparms['id'] = $sub_action; - } - else - { - $newsRoute = 'list/items'; - } - - - - $newsRoute = 'news/'.$newsRoute; - - - - -if(vartrue($_GET['tag']) || substr($action,0,4) == 'tag=') -{ - - $newsRoute = 'news/list/tag'; - if(!vartrue($_GET['tag'])) - { - list($action,$word) = explode("=",$action,2); - $_GET['tag'] = $word; - unset($word,$tmp); - } - - $newsUrlparms['tag'] = $tp->filter($_GET['tag']); - $newsfrom = intval(varset($_GET['page'],0)); -} - -if(!empty($_GET['author']) || substr($action,0,4) == 'author=') -{ - - $newsRoute = 'news/list/author'; - if(!vartrue($_GET['author'])) - { - list($action,$author) = explode("=",$action,2); - $_GET['author'] = $author; - unset($author,$tmp); - } - - $newsUrlparms['author'] = $tp->filter($_GET['author']); - $newsfrom = intval(varset($_GET['page'],0)); - -} - - -if(e_DEBUG === 'news') -{ - echo "<div class='alert alert-info'>"; - echo "<h4>SEF Debug Info</h4>"; - echo "action= ".$action." "; - echo "<br />route= ".$newsRoute." "; - echo "<br />e_QUERY= ".e_QUERY." "; - - echo "<br />_GET= ".print_r($_GET,true); - echo "</div>"; -} - -//------------------------------------------------------ -// DISPLAY NEWS IN 'CATEGORY' LIST FORMAT HERE -//------------------------------------------------------ -// Just title and a few other details - -if ($action == 'cat' || $action == 'all' || !empty($_GET['tag']) || !empty($_GET['author'])) -{ // --> Cache - if($newsCachedPage = checkCache($cacheString)) - { - require_once(HEADERF); - renderCache($newsCachedPage, TRUE); - } - // <-- Cache - - - $category = intval($sub_action); - if ($action == 'cat' && $category != 0) - { - $gen = new convert; - $sql->select("news_category", "*", "category_id='{$category}'"); - $row = $sql->fetch(); - extract($row); // still required for the table-render. :( - } - - //XXX These are all correctly using LIST templates. - - if ($action == 'all') // show archive of all news items using list-style template. - { - $renTypeQry = ''; - - if(!empty($pref['news_list_templates']) && is_array($pref['news_list_templates'])) - { - $renTypeQry = " AND (n.news_render_type REGEXP '(^|,)(".implode("|", $pref['news_list_templates']).")(,|$)')"; - } - - // $news_total = $sql->count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().")". str_replace("n.news", "news", $renTypeQry)); - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") AND n.news_start < ".time()." - AND (n.news_end=0 || n.news_end>".time().") "; - - $query .= $renTypeQry; - - $query .= " - ORDER BY n.news_sticky DESC, n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".deftrue('NEWSALL_LIMIT', NEWSLIST_LIMIT); // NEWSALL_LIMIT just for BC. NEWSLIST_LIMIT is sufficient. - $category_name = ($defTemplate == 'list') ? PAGE_NAME : "All"; - unset($renTypeQry); - } - elseif ($action == 'cat') // show archive of all news items in a particular category using list-style template. - { - - // $news_total = $sql->count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().") AND news_category=".intval($sub_action)); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_category=".intval($sub_action)." - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - } - elseif(vartrue($_GET['tag'])) - { - $tagsearch = e107::getParser()->filter($_GET['tag']); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_meta_keywords LIKE '%".$tagsearch."%' - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - $category_name = 'Tag: "'.$tagsearch.'"'; - - } - elseif(!empty($_GET['author'])) - { - $authorSearch = e107::getParser()->filter($_GET['author']); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE u.user_name = '".$authorSearch."' - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - $category_name = 'Author: "'.$authorSearch.'"'; - - - - } - - $newsList = array(); - - if($sql->gen($query)) - { - $news_total = $sql->foundRows(); - $newsList = $sql->db_getList(); - $ogImageCount = 0; - foreach($newsList as $row) - { - if(!empty($row['news_thumbnail'])) - { - $iurl = (substr($row['news_thumbnail'],0,3)=="{e_") ? $row['news_thumbnail'] : SITEURL.e_IMAGE."newspost_images/".$news['news_thumbnail']; - $tmp = explode(",", $iurl); - - if($tp->isImage($tmp[0])) - { - if($ogImageCount > 6) - { - break; - } - - e107::meta('og:image',$tp->thumbUrl($tmp[0],'w=500',false,true) ); - $ogImageCount++; - - } - } - - } - } - - - if($action == 'cat') - { - setNewsFrontMeta($newsList[1], 'category'); - } -// elseif($category_name) -// { -// define('e_PAGETITLE', $tp->toHTML($category_name,FALSE,'TITLE')); -// } -e107::getDebug()->log("PageTitle: ".e_PAGETITLE); - $currentNewsAction = $action; - require_once(HEADERF); - $action = $currentNewsAction; - - if(deftrue('BOOTSTRAP')) // v2.x - { - $template = e107::getTemplate('news', 'news', 'list'); - } - else // v1.x - { - if(empty($NEWSLISTSTYLE)) - { - $NEWSLISTSTYLE = " - <div style='padding:3px;width:100%'> - <table style='border-bottom:1px solid black;width:100%' cellpadding='0' cellspacing='0'> - <tr> - <td style='vertical-align:top;padding:3px;width:20px'> - {NEWS_CATEGORY_ICON} - </td><td style='text-align:left;padding:3px'> - {NEWSTITLELINK=extend} - <br /> - {NEWS_SUMMARY} - <span class='smalltext'> - {NEWS_DATE} - {NEWSCOMMENTS} - </span> - </td><td style='width:55px'> - {SETIMAGE: w=55&h=55&crop=1} - {NEWSTHUMBNAIL} - </td></tr></table> - </div>\n"; - } - - $template = array('start'=>'', 'item'=>$NEWSLISTSTYLE, 'end'=>''); - - } - - // Legacy Styling.. - $param = array(); - $param['itemlink'] = (defined("NEWSLIST_ITEMLINK")) ? NEWSLIST_ITEMLINK : ""; - $param['thumbnail'] =(defined("NEWSLIST_THUMB")) ? NEWSLIST_THUMB : "border:0px"; - $param['catlink'] = (defined("NEWSLIST_CATLINK")) ? NEWSLIST_CATLINK : ""; - $param['caticon'] = (defined("NEWSLIST_CATICON")) ? NEWSLIST_CATICON : defset('ICONSTYLE',''); - $param['current_action'] = $action; - $param['template_key'] = 'list'; - - // NEW - allow news batch shortcode override (e.g. e107::getScBatch('news', 'myplugin', true); ) - e107::getEvent()->trigger('news_list_parse', $newsList); - - $text = ''; - - if(vartrue($template['start'])) - { - $text .= $tp->parseTemplate($template['start'], true); - } - - if(!empty($newsList)) - { - foreach($newsList as $row) - { - $text .= $ix->render_newsitem($row, 'return', '', $template['item'], $param); - } - } - else // No News - empty. - { - $text .= "<div class='news-empty'><div class='alert alert-info'>".(strstr(e_QUERY, "month") ? LAN_NEWS_462 : LAN_NEWS_83)."</div></div>"; - } - - if(vartrue($template['end'])) - { - $text .= $tp->parseTemplate($template['end'], true); - } - - $icon = ($row['category_icon']) ? "<img src='".e_IMAGE."icons/".$row['category_icon']."' alt='' />" : ""; - - // Deprecated. - // $parms = $news_total.",".$amount.",".$newsfrom.",".$e107->url->getUrl('core:news', 'main', "action=nextprev&to_action={$action}&subaction={$category}"); - // $parms = $news_total.",".$amount.",".$newsfrom.",".e_SELF.'?'.$action.".".$category.".[FROM]"; - // - // $text .= "<div class='nextprev'>".$tp->parseTemplate("{NEXTPREV={$parms}}")."</div>"; - - $amount = NEWSLIST_LIMIT; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - - // e107::getDebug()->log($newsUrlparms); - - $text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - - if(varset($template['caption'])) // v2.x - { - $NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'), $template['caption']); - } - elseif(!$NEWSLISTTITLE) // default - { - $NEWSLISTTITLE = LAN_NEWS_82." '".$tp->toHTML($category_name,FALSE,'TITLE')."'"; - } - else // v1.x - { - $NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTTITLE); - } - - if($defTemplate != 'list') - { - $text .= "<div class='center news-list-footer'><a class='btn btn-default' href='".e107::getUrl()->create('news/list/all')."'>".LAN_NEWS_84."</a></div>"; - } - - ob_start(); - $ns->tablerender($NEWSLISTTITLE, $text, 'news'); - $cache_data = ob_get_flush(); - setNewsCache($cacheString, $cache_data); - require_once(FOOTERF); - exit; -} - - - -//------------------------------------------------------ -// DISPLAY SINGLE ITEM IN EXTENDED FORMAT HERE -//------------------------------------------------------ -if ($action == 'extend') -{ // --> Cache - if($newsCachedPage = checkCache($cacheString)) - { - require_once(HEADERF); - renderCache($newsCachedPage, TRUE); // This exits if cache used - } - // <-- Cache - - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) - { - $query = " - SELECT COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_id=".intval($sub_action)." AND n.news_class REGEXP '".e_CLASS_REGEXP."' - AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - GROUP by n.news_id"; - } - else - { - $query = " - SELECT n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' - AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." - AND (n.news_end=0 || n.news_end>".time().") - AND n.news_id=".intval($sub_action); - } - if ($sql->gen($query)) - { - $news = $sql->fetch(); - $id = $news['news_category']; // Use category of this news item to generate next/prev links - - e107::getEvent()->trigger('user_news_item_viewed', $news); - - //***NEW [SecretR] - comments handled inside now - e107::setRegistry('news/page_allow_comments', !$news['news_allow_comments']); - if(!$news['news_allow_comments'] && isset($_POST['commentsubmit'])) - { - $pid = intval(varset($_POST['pid'], 0)); // ID of the specific comment being edited (nested comments - replies) - - $clean_authorname = $_POST['author_name']; - $clean_comment = $_POST['comment']; - $clean_subject = $_POST['subject']; - - e107::getSingleton('comment')->enter_comment($clean_authorname, $clean_comment, 'news', $sub_action, $pid, $clean_subject); - } - - //More SEO - setNewsFrontMeta($news); - /* - if($news['news_title']) - { - if($pref['meta_news_summary'] && $news['news_title']) - { - define("META_DESCRIPTION",SITENAME.": ".$news['news_title']." - ".$news['news_summary']); - } - define("e_PAGETITLE",$news['news_title']); - }*/ - /* FIXME - better implementation: cache, shortcodes, do it inside the model/shortcode class itself. - if (TRUE) - { - // Added by nlStart - show links to previous and next news - if (!isset($news['news_extended'])) $news['news_extended'] = ''; - $news['news_extended'].="<div style='text-align:center;'><a href='".e_SELF."?cat.".$id."'>".LAN_NEWS_85."</a>   <a href='".e_SELF."'>".LAN_NEWS_84."</a></div>"; - $prev_query = "SELECT news_id, news_title FROM `#news` - WHERE `news_id` < ".intval($sub_action)." AND `news_category`=".$id." AND `news_class` REGEXP '".e_CLASS_REGEXP."' - AND NOT (`news_class` REGEXP ".$nobody_regexp.") - AND `news_start` < ".time()." AND (`news_end`=0 || `news_end` > ".time().') ORDER BY `news_id` DESC LIMIT 1'; - $sql->db_Select_gen($prev_query); - $prev_news = $sql->db_Fetch(); - if ($prev_news) - { - $news['news_extended'].="<div style='float:right;'><a href='".e_SELF."?extend.".$prev_news['news_id']."'>".LAN_NEWS_86."</a></div>"; - } - $next_query = "SELECT news_id, news_title FROM `#news` AS n - WHERE `news_id` > ".intval($sub_action)." AND `news_category` = ".$id." AND `news_class` REGEXP '".e_CLASS_REGEXP."' - AND NOT (`news_class` REGEXP ".$nobody_regexp.") - AND `news_start` < ".time()." AND (`news_end`=0 || `news_end` > ".time().') ORDER BY `news_id` ASC LIMIT 1'; - $sql->db_Select_gen($next_query); - $next_news = $sql->db_Fetch(); - if ($next_news) - { - $news['news_extended'].="<div style='float:left;'><a href='".e_SELF."?extend.".$next_news['news_id']."'>".LAN_NEWS_87."</a></div>"; - } - $news['news_extended'].="<br /><br />"; - }*/ - - $currentNewsAction = $action; - require_once(HEADERF); - $action = $currentNewsAction; - - $param = array(); - $param['current_action'] = $action; - $param['template_key'] = 'view'; - - if(vartrue($NEWSSTYLE)) - { - $template = $NEWSSTYLE; - } - elseif(function_exists("news_style")) // BC - { - $template = news_style($news, 'extend', $param); - } - else - { - $tmp = e107::getTemplate('news', 'news', 'view'); - $template = $tmp['item']; - unset($tmp); - } - ob_start(); - $ix->render_newsitem($news, 'extend', '', $template, $param); - if(e107::getRegistry('news/page_allow_comments')) - { - global $comment_edit_query; //FIXME - kill me - $comment_edit_query = 'comment.news.'.$news['news_id']; - e107::getSingleton('comment')->compose_comment('news', 'comment', $news['news_id'], null, $news['news_title'], FALSE); - } - $cache_data = ob_get_contents(); - ob_end_flush(); - setNewsCache($cacheString, $cache_data); - require_once(FOOTERF); - exit; - } - else - { - // $action = 'default'; - - //XXX item not found, redirect to avoid messing up search-engine data. - $defaultUrl = e107::getUrl()->create('news/list/items'); - e107::getRedirect()->go($defaultUrl, null, 301); - exit; - - } -} - - -//------------------------------------------------------ -// DISPLAY NEWS IN LIST FORMAT HERE -//------------------------------------------------------ -// Show title, author, first part of news item... -if (empty($order)) -{ - $order = 'news_datestamp'; -} -$order = $tp -> toDB($order, true); /// @todo - try not to use toDB() - triggers prefilter - -$interval = $pref['newsposts']; - - - -switch ($action) -{ - case "list" : - $sub_action = intval($sub_action); - // $news_total = $sql->db_Count("news", "(*)", "WHERE news_category={$sub_action} AND news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().")"); - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_category={$sub_action} - ORDER BY n.news_sticky DESC,".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - - $noNewsMessage = LAN_NEWS_463; - break; - - - case "item" : - $sub_action = intval($sub_action); - $news_total = 1; - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) - { - $query = " - SELECT COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_id={$sub_action} AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - GROUP by n.news_id"; - } - else - { - $query = " - SELECT n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_id={$sub_action} AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().")"; - } - - $noNewsMessage = LAN_NEWS_83; - break; - - - case "month" : - case "day" : - $item = $tp -> toDB($sub_action).'20000101'; - $year = substr($item, 0, 4); - $month = substr($item, 4,2); - if ($action == 'day') - { - $day = substr($item, 6, 2); - $lastday = $day; - } - else - { // A month's worth - $day = 1; - $lastday = date("t", $startdate); - } - - $startdate = mktime(0, 0, 0, $month, $day, $year); - $enddate = mktime(23, 59, 59, $month, $lastday, $year); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) AND n.news_datestamp BETWEEN {$startdate} AND {$enddate} - ORDER BY ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - - $noNewsMessage = LAN_NEWS_462; - - break; - - case 'default' : - default : - //$action = ''; - $cacheString = 'news.php_default_'; // Make sure its sensible - // $news_total = $sql->db_Count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().") AND news_render_type<2" ); - - if(!isset($pref['newsposts_archive'])) - { - $pref['newsposts_archive'] = 0; - } - $interval = $pref['newsposts']-$pref['newsposts_archive']; // Number of 'full' posts to show - - // Get number of news item to show - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) { - $query = " - SELECT SQL_CALC_FOUND_ROWS COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, - nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, nc.category_meta_description, - COUNT(*) AS tbcount - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) - GROUP by n.news_id - ORDER BY news_sticky DESC, ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - } - else - { - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) - ORDER BY n.news_sticky DESC, ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - } - - $noNewsMessage = LAN_NEWS_83; -} // END - switch($action) - - -if($newsCachedPage = checkCache($cacheString)) // normal news front-page - with cache. -{ - require_once(HEADERF); - - if(!$action) - { - // Removed, themes should use {FEATUREBOX} shortcode instead - // if (isset($pref['fb_active'])) - // { - // require_once(e_PLUGIN."featurebox/featurebox.php"); - // } - // Removed, legacy - // if (isset($pref['nfp_display']) && $pref['nfp_display'] == 1) - // { - // require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - // } - - } - - //news archive - if ($action != "item" && $action != 'list' && $pref['newsposts_archive']) { - if ($sql->db_Select_gen($query)) { - $newsAr = $sql -> db_getList(); - if($newsarchive = checkCache('newsarchive')){ - $newsCachedPage = $newsCachedPage.$newsarchive; - }else{ - show_newsarchive($newsAr,$interval); - } - } - } - renderCache($newsCachedPage, TRUE); -} - - -if (!($news_total = $sql->gen($query))) -{ // No news items - require_once(HEADERF); - echo "<div class='news-empty'><div class='alert alert-info' style='text-align:center'>".$noNewsMessage."</div></div>"; - require_once(FOOTERF); - exit; -} - -$newsAr = $sql -> db_getList(); -$news_total=$sql->total_results; -// Get number of entries -//$sql -> db_Select_gen("SELECT FOUND_ROWS()"); -$frows = $sql -> db_Fetch(); -//$news_total = $frows[0]; - -//echo "<br />Total ".$news_total." items found, ".count($newsAr)." displayed, Interval = {$interval}<br /><br />"; - -$p_title = ($action == "item") ? $newsAr[1]['news_title'] : $tp->toHTML($newsAr[1]['category_name'],FALSE,'TITLE'); - -switch($action) -{ - case 'item': - setNewsFrontMeta($newsAr[1]); - break; - - case 'list': - default: - setNewsFrontMeta($newsAr[1], 'list'); - break; -} - -/*if($action != "" && !is_numeric($action)) -{ -if($action == "item" && $pref['meta_news_summary'] && $newsAr[1]['news_title']) -{ -define("META_DESCRIPTION",SITENAME.": ".$newsAr[1]['news_title']." - ".$newsAr[1]['news_summary']); -} -define("e_PAGETITLE", $p_title); -}*/ - -$currentNewsAction = $action; -require_once(HEADERF); -$action = $currentNewsAction; - -if(!$action) -{ - // Removed, themes should use {FEATUREBOX} shortcode instead - // if (isset($pref['fb_active'])){ // --->feature box - // require_once(e_PLUGIN."featurebox/featurebox.php"); - // } - - // Removed, legacy - // if (isset($pref['nfp_display']) && $pref['nfp_display'] == 1){ - // require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - // } -} - -if(isset($pref['news_unstemplate']) && $pref['news_unstemplate'] && file_exists(THEME."news_template.php")) -{ - // theme specific template required ... - require_once(THEME."news_template.php"); - - if($ALTERNATECLASS1) - { - return TRUE; - } - - $newscolumns = (isset($NEWSCOLUMNS) ? $NEWSCOLUMNS : 1); - $newspercolumn = (isset($NEWSITEMSPERCOLUMN) ? $NEWSITEMSPERCOLUMN : 10); - $newsdata = array(); - $loop = 1; - $param = array(); - $param['current_action'] = $action; - foreach($newsAr as $news) { - - if(is_array($ALTERNATECLASSES)) { - $newsdata[$loop] .= "<div class='{$ALTERNATECLASSES[0]}'>".$ix->render_newsitem($news, "return", '', '', $param)."</div>"; - $ALTERNATECLASSES = array_reverse($ALTERNATECLASSES); - } else { - $newsdata[$loop] .= $ix->render_newsitem($news, 'return', '', '', $param); - } - $loop ++; - if($loop > $newscolumns) { - $loop = 1; - } - } - $loop = 1; - foreach($newsdata as $data) { - $var = "ITEMS{$loop}"; - $$var = $data; - $loop ++; - } - $text = preg_replace("/\{(.*?)\}/e", '$\1', $NEWSCLAYOUT); - - require_once(HEADERF); - // Deprecated - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".$e107->url->getUrl('core:news', 'main', "action=nextprev&to_action=".($action ? $action : 'default' )."&subaction=".($sub_action ? $sub_action : "0")); - - $sub_action = intval($sub_action); - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'.($action ? $action : 'default' ).($sub_action ? ".".$sub_action : ".0").".[FROM]"; - - $amount = ITEMVIEW; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - $text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // $text .= ($nextprev ? "<div class='nextprev'>".$nextprev."</div>" : ""); - // $text=''.$text.'<center>'.$nextprev.'</center>'; - - echo $text; - setNewsCache($cacheString, $text); -} -else -{ - ob_start(); - - $newpostday = 0; - $thispostday = 0; - $pref['newsHeaderDate'] = 1; - $gen = new convert(); - /* - if(vartrue($NEWSLISTSTYLE)) $template = $NEWSLISTSTYLE; v1.x doesn't do this.. so no point doing it here. - else - { - $tmp = e107::getTemplate('news', 'news', 'list'); - $template = $tmp['item']; - unset($tmp); - } - */ - if (!defined("DATEHEADERCLASS")) { - define("DATEHEADERCLASS", "nextprev"); - // if not defined in the theme, default class nextprev will be used for new date header - } - - // #### normal newsitems, rendered via render_newsitem(), the $query is changed above (no other changes made) --------- - $param = array(); - $param['current_action'] = $action; - $param['template_key'] = 'default'; - - // Get Correct Template - // XXX we use $NEWSLISTSTYLE above - correct as we are currently in list mode - XXX No this is not NEWSLISTSTYLE - which provides only summaries. - // TODO requires BC testing if we comment this one - if(vartrue($NEWSSTYLE)) - { - $template = $NEWSSTYLE; - } - else - { - $tmp = e107::getTemplate('news', 'news', 'default'); // default - we show the full items, except for the 'extended' part.. - $template = $tmp['item']; - unset($tmp); - } - - - - - - // NEW - news category title when in list - if($sub_action && 'list' == $action && vartrue($newsAr[1]['category_name'])) - { - // we know category name - pass it to the nexprev url - $category_name = $newsAr[1]['category_name']; - if(vartrue($newsAr[1]['category_sef'])) $newsUrlparms['name'] = $newsAr[1]['category_sef']; - if(!isset($NEWSLISTCATTITLE)) - { - $NEWSLISTCATTITLE = "<h1 class='newscatlist-title'>".$tp->toHTML($category_name,FALSE,'TITLE')."</h1>"; - } - else - { - $NEWSLISTCATTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTCATTITLE); - } - echo $NEWSLISTCATTITLE; - } - - $i= 1; - - $socialInstalled = e107::isInstalled('social'); - - while(isset($newsAr[$i]) && $i <= $interval) - { - $news = $newsAr[$i]; - - // Set the Values for the social shortcode usage. - if($socialInstalled == true) - { - $socialArray = array('url'=>e107::getUrl()->create('news/view/item', $news, 'full=1'), 'title'=>$tp->toText($news['news_title']), 'tags'=>$news['news_meta_keywords']); - $socialObj = e107::getScBatch('social'); - - if(is_object($socialObj)) - { - $socialObj->setVars($socialArray); - } - } - - if(function_exists("news_style")) // BC - { - $template = news_style($news, $action, $param); - } - - - // render new date header if pref selected ... - $thispostday = strftime("%j", $news['news_datestamp']); - if ($newpostday != $thispostday && (isset($pref['news_newdateheader']) && $pref['news_newdateheader'])) - { - echo "<div class='".DATEHEADERCLASS."'>".strftime("%A %d %B %Y", $news['news_datestamp'])."</div>"; - } - $newpostday = $thispostday; - $news['category_id'] = $news['news_category']; - if ($action == "item") - { - unset($news['news_render_type']); - e107::getEvent()->trigger('user_news_item_viewed', $news); - //e107::getDebug()->log($news); - } - // $template = false; - $ix->render_newsitem($news, 'default', '', $template, $param); - - - $i++; - } - - $amount = ITEMVIEW; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - // Example of passing route data instead building the URL outside the shortcode - for a reference only - // $url = rawurlencode('url::'.$newsRoute.'::'.http_build_query($newsUrlparms, null, '&')); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - echo $tp->parseTemplate("{NEXTPREV={$parms}}"); - - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'.($action ? $action : 'default' ).($sub_action ? ".".$sub_action : ".0").".[FROM]"; - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // echo ($nextprev ? "<div class='nextprev'>".$nextprev."</div>" : ""); - - $cache_data = ob_get_clean(); - require_once(HEADERF); - echo $cache_data; - setNewsCache($cacheString, $cache_data); -} - -// ##### -------------------------------------------------------------------------------------------------------------- - -function show_newsarchive($newsAr, $i = 1) -{ - global $ns, $gen, $pref, $tp, $news_archive_shortcodes, $NEWSARCHIVE, $news2; - - // do not show the news archive on the news.php?item.X page (but only on the news mainpage) - require_once(e_CORE.'shortcodes/batch/news_archives.php'); - - $textnewsarchive = ''; - ob_start(); - - $i++; // First entry to show - while(isset($newsAr[$i])) - { - $news2 = $newsAr[$i]; - // Code from Lisa - // copied from the rss creation, but added here to make sure the url for the newsitem is to the news.php?item.X - // instead of the actual hyperlink that may have been added to a newstitle on creation - $search = array(); - $replace = array(); - $search[0] = "/\<a href=\"(.*?)\">(.*?)<\/a>/si"; - $replace[0] = '\\2'; - $search[1] = "/\<a href='(.*?)'>(.*?)<\/a>/si"; - $replace[1] = '\\2'; - $search[2] = "/\<a href='(.*?)'>(.*?)<\/a>/si"; - $replace[2] = '\\2'; - $search[3] = "/\<a href="(.*?)">(.*?)<\/a>/si"; - $replace[3] = '\\2'; - $search[4] = "/\<a href='(.*?)'>(.*?)<\/a>/si"; - $replace[4] = '\\2'; - $news2['news_title'] = preg_replace($search, $replace, $news2['news_title']); - // End of code from Lisa - - $gen = new convert; - $news2['news_datestamp'] = $gen->convert_date($news2['news_datestamp'], "short"); - - - if(!$NEWSARCHIVE){ - $NEWSARCHIVE ="<div> - <table style='width:98%;'> - <tr> - <td> - <div>{ARCHIVE_BULLET} <b>{ARCHIVE_LINK}</b> <span class='smalltext'><i>{ARCHIVE_AUTHOR} @ ({ARCHIVE_DATESTAMP}) ({ARCHIVE_CATEGORY})</i></span></div> - </td> - </tr> - </table> - </div>"; - } - - $textnewsarchive .= $tp->parseTemplate($NEWSARCHIVE, FALSE, $news_archive_shortcodes); - $i++; - } - $ns->tablerender($pref['newsposts_archive_title'], $textnewsarchive, 'news_archive'); - $newsarchive = ob_get_contents(); - ob_end_flush(); // dump collected data - setNewsCache('newsarchive', $newsarchive); -} - -// #### new: news archive --------------------------------------------------------------------------------------------- -if ($action != "item" && $action != 'list' && $pref['newsposts_archive']) -{ - show_newsarchive($newsAr,$interval); -} -// #### END ----------------------------------------------------------------------------------------------------------- - -if ($action != "item") { - if (is_numeric($action)){ - $action = ""; - } - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'."[FROM].".$action.(isset($sub_action) ? ".".$sub_action : ""); - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // echo ($nextprev ? "<div class='nextprev'>".$nextprev."</div>" : ""); -} - -if(is_dir("remotefile")) { - require_once(e_HANDLER."file_class.php"); - $file = new e_file; - // $reject = array('$.','$..','/','CVS','thumbs.db','*._$', 'index', 'null*', 'Readme.txt'); - // $crem = $file -> get_files(e_BASE."remotefile", "", $reject); - $crem = $file -> get_files(e_BASE."remotefile", '~Readme\.txt'); - if(count($crem)) { - foreach($crem as $loadrem) { - if(strstr($loadrem['fname'], "load_")) { - require_once(e_BASE."remotefile/".$loadrem['fname']); - } - } - } -} - -if (isset($pref['nfp_display']) && $pref['nfp_display'] == 2 && is_readable(e_PLUGIN."newforumposts_main/newforumposts_main.php")) -{ - require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); -} - -render_newscats(); - -require_once(FOOTERF); - - -// ========================================================================= -function setNewsCache($cache_tag, $cache_data) { - global $e107cache; - $e107cache->set($cache_tag, $cache_data); - $e107cache->set($cache_tag."_title", defined("e_PAGETITLE") ? e_PAGETITLE : ''); - $e107cache->set($cache_tag."_diz", defined("META_DESCRIPTION") ? META_DESCRIPTION : ''); -} - -function checkCache($cacheString){ - global $pref,$e107cache; - $cache_data = $e107cache->retrieve($cacheString); - $cache_title = $e107cache->retrieve($cacheString."_title"); - $cache_diz = $e107cache->retrieve($cacheString."_diz"); - $etitle = ($cache_title != "e_PAGETITLE") ? $cache_title : ""; - $ediz = ($cache_diz != "META_DESCRIPTION") ? $cache_diz : ""; - if($etitle){ - define(e_PAGETITLE,$etitle); - } - if($ediz){ - define("META_DESCRIPTION",$ediz); - } - if ($cache_data) { - return $cache_data; - } else { - return false; - } -} - -function renderCache($cache, $nfp = FALSE){ - global $pref,$tp,$sql,$CUSTOMFOOTER, $FOOTER,$cust_footer,$ph; - global $db_debug,$ns,$eTimingStart, $error_handler, $db_time, $sql2, $mySQLserver, $mySQLuser, $mySQLpassword, $mySQLdefaultdb,$e107; - echo $cache; - if (isset($nfp) && isset($pref['nfp_display']) && $pref['nfp_display'] == 2) { - require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - } - render_newscats(); - require_once(FOOTERF); - exit; -} - -function render_newscats(){ // -- CNN Style Categories. ---- - $tp = e107::getParser(); - $ns = e107::getRender(); - $pref = e107::getPref(); - - if (isset($pref['news_cats']) && $pref['news_cats'] == '1') - { - $text3 = $tp->toHTML("{NEWS_CATEGORIES}", TRUE, 'TITLE'); - $ns->tablerender(LAN_NEWS_23, $text3, 'news_cat'); - } -} - -function setNewsFrontMeta($news, $type='news') -{ - - $tp = e107::getParser(); - - if($type == 'news') - { - if($news['news_title'] && !defined('e_PAGETITLE')) - { - define('e_PAGETITLE', $news['news_title']); - e107::meta('og:title',$news['news_title']); - e107::meta('og:type','article'); - } - - if($news['news_meta_description'] && !defined('META_DESCRIPTION')) - { - e107::meta('description',$news['news_meta_description']); - e107::meta('og:description',$news['news_meta_description']); - //define('META_DESCRIPTION', $news['news_meta_description']); // deprecated - } - elseif($news['news_summary']) // BC compatibility - { - e107::meta('og:description',$news['news_summary']); - } - - // include news-thumbnail/image in meta. - always put this one first. - if($news['news_thumbnail']) - { - $iurl = (substr($news['news_thumbnail'],0,3)=="{e_") ? $news['news_thumbnail'] : SITEURL.e_IMAGE."newspost_images/".$news['news_thumbnail']; - $tmp = explode(",", $iurl); - foreach($tmp as $mimg) - { - if(substr($mimg,-8) == '.youtube') - { - continue; - } - e107::meta('og:image',$tp->thumbUrl($tmp[0],'w=500',false,true) ); - // e107::meta('og:image',$mimg); - } - - } - - // grab all images in news-body and add to meta. - $images = e107::getBB()->getContent('img',$news['news_body'],SITEURL.e_IMAGE."newspost_images/"); - $c =1; - foreach($images as $im) - { - if($c == 4){ break; } - e107::meta('og:image',$im); - $c++; - } - - // grab all youtube videos in news-body and add thumbnails to meta. - $youtube = e107::getBB()->getContent('youtube',$news['news_body']); - $c = 1; - foreach($youtube as $yt) - { - if($c == 3){ break; } - list($img,$tmp) = explode("?",$yt); - e107::meta('og:image',"http://img.youtube.com/vi/".$img."/0.jpg"); - $c++; - } - - - - $url = e107::getUrl()->create('news/view/item', $news,'full=1'); - e107::meta('og:url',$url); - - e107::meta('article:section',$news['category_name']); - - if($news['news_meta_keywords'] && !defined('META_KEYWORDS')) - { - e107::meta('keywords',$news['news_meta_keywords']); - $tmp = explode(",",$news['news_meta_keywords']); - foreach($tmp as $t) - { - e107::meta('article:tag', trim($t)); - } - - // define('META_KEYWORDS', $news['news_meta_keywords']); // deprecated - } - - - /* Facebook reference. - * http://developers.facebook.com/docs/opengraph/objects/builtin/ - */ - - return; - } - - - - if($news['category_name'] && !defined('e_PAGETITLE') && $type == 'category') - { - define('e_PAGETITLE', $tp->toHtml($news['category_name'],false,'TITLE_PLAIN')); - } - - if($news['category_meta_keywords'] && !defined('META_KEYWORDS')) - { - define('META_KEYWORDS', $news['category_meta_keywords']); - } - - if($news['category_meta_description'] && !defined('META_DESCRIPTION')) - { - define('META_DESCRIPTION', $news['category_meta_description']); - } - - - -} - - -?> +?> \ No newline at end of file diff --git a/search.php b/search.php index 00572b115..5aac25d26 100644 --- a/search.php +++ b/search.php @@ -1084,7 +1084,7 @@ if (check_class($search_prefs['google'])) { if ($perform_search) { - $con = new convert; + $con = e107::getDate(); $sch = new e_search; diff --git a/upload.php b/upload.php index 41e637902..e32f784de 100644 --- a/upload.php +++ b/upload.php @@ -107,7 +107,7 @@ class userUpload $catID = null; $catOwner = null; $file = null; - $image = null; + $image = ''; $filesize = 0; diff --git a/userposts.php b/userposts.php index 7613d4b26..f95ae64f6 100644 --- a/userposts.php +++ b/userposts.php @@ -70,7 +70,8 @@ if ($action == "comments") $sql2 = e107::getDb('sql2'); if($user_name) { - $ccaption = UP_LAN_1.$user_name; + // $ccaption = UP_LAN_1.$user_name; + $ccaption = str_replace('[x]', $user_name, UP_LAN_1); /*$sql->db_Select("user", "user_comments", "user_id=".$id); $row = $sql->db_Fetch(); $ctotal = $row['user_comments'];*/ @@ -159,7 +160,8 @@ elseif ($action == 'forums') exit; } - $fcaption = UP_LAN_0.' '.$user_name; +// $fcaption = UP_LAN_0.' '.$user_name; + $fcaption = str_replace('[x]', $user_name, UP_LAN_0); /* if (!$USERPOSTS_FORUM_TABLE) { @@ -312,4 +314,4 @@ function parse_userposts_comments_table($row, $template) return e107::getParser()->simpleParse($template, $vars); } -?> \ No newline at end of file +?> diff --git a/usersettings.php b/usersettings.php index 2f3f64b97..7cc9e50f8 100644 --- a/usersettings.php +++ b/usersettings.php @@ -69,7 +69,7 @@ class usersettings_front // Begin Usersettings rewrite. function __construct() { - if(deftrue('BOOTSTRAP')===3) + if(deftrue('BOOTSTRAP')) { $template = e107::getCoreTemplate('usersettings','', true, true); // always merge @@ -172,6 +172,11 @@ class usersettings_front // Begin Usersettings rewrite. $adminEdit = false; // @deprecated // FALSE if editing own data. TRUE if admin edit + if(!empty($_POST['delete_account'])) + { + echo e107::getMessage()->addWarning("This feature is currently under development. Your data has not been modified")->render(); // do not LAN. + } + /* todo subject of removal */ if(is_numeric(e_QUERY)) { // Trying to edit specific user record