/** * Initialising Theme Customiser if necessary * @param (bool) If true, additional LESS variables will be added to Theme Customiser */ protected function attachThemeCustomiser($useVars = true) { if (self::$less_js_included == false) { //JHTML::_('behavior.framework', true); JHtml::_('jquery.ui', array('core', 'sortable')); // For standard color picker JHtml::_('script', 'system/html5fallback.js', false, true); JHtml::_('behavior.colorpicker'); if (!defined('JMF_TPL_ASSETS')) { define('JMF_TPL_ASSETS', JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/'); } $app = JFactory::getApplication(); $jconf = JFactory::getConfig(); $cookie_path = $jconf->get('cookie_path') == '' ? JUri::base(true) : $jconf->get('cookie_path'); $cookie_domain = $jconf->get('cookie_domain') == '' ? $_SERVER['HTTP_HOST'] : $jconf->get('cookie_domain'); $global_vars = array(); // taking LESS initial variables generated by the template (based on parameters) if ($useVars) { $params = $this->document->params->toArray(); $variables = $this->params->get('jm_bootstrap_variables', array()); $variables = array_merge($params, $variables); if (!empty($variables)) { foreach ($variables as $k => $v) { $global_vars['@' . $k] = $v; } } } // Making sure that variables don't start with @. // Less.js doesn't want @ before variable name, whicle LessC PHP compiler requires it. $form_vars = array(); foreach ($global_vars as $k => $v) { $form_vars[str_replace('@', '', $k)] = $v; } // Including and merging variables stored in a Cookie by Theme Customiser, which override default params. $ts_cookie = JFactory::getApplication()->input->cookie->get('JMTH_TIMESTAMP_' . $this->template, 0); if ((int) $ts_cookie != -1) { //$form_cookie_vars = JFactory::getApplication()->input->cookie->get('JM_form_vars_'.$this->template, false, 'raw'); $form_cookie_vars = JFactory::getApplication()->getUserState($this->template . '.themer.state', false); if ($form_cookie_vars) { $cashed_vars = json_decode($form_cookie_vars, true); foreach ($cashed_vars as $k => $v) { if (preg_replace('#[^0-9a-z]#i', '', $v) != '') { $form_vars[$k] = $v; } } } } JFactory::getApplication()->input->cookie->set('JMTH_TIMESTAMP_' . $this->template, time(), 0, $cookie_path); // Saving all set of variables into Cookie. Just to be sure they won't get lost somewhere. //JFactory::getApplication()->input->cookie->set('JM_form_vars_'.$this->template, json_encode($form_vars), 0, $cookie_path); JFactory::getApplication()->setUserState($this->template . '.themer.state', json_encode($form_vars)); // All LESS vars that go directly in LESS object start with 'JM'. We don't need to pass any other variables. $less_vars = array(); foreach ($form_vars as $k => $v) { if (substr($k, 0, 2) == 'JM') { $less_vars[$k] = $v; } } $developer_mode = $this->params->get('devmode', false) == '1' ? true : false; $less_mode = $developer_mode ? 'development' : 'production'; $less_log = $developer_mode ? '2' : '0'; $less_dump = $developer_mode ? 'comments' : ''; $script_init = ' less = { env: "' . $less_mode . '", mode: "browser", async: false, logLevel: ' . $less_log . ', fileAsync: false, poll: 1000, functions: {}, dumpLineNumbers: "' . $less_dump . '", relativeUrls: false, rootpath: "' . JMF_TPL_URL . '/less/", globalVars: ' . json_encode($less_vars) . ' };'; // Must use addCustomTag() instead of addScript(), because LESS's init script has to go before LESS library. $this->document->addCustomTag('<script type="text/javascript">' . $script_init . '</script>'); $this->document->addCustomTag('<script type="text/javascript" src="' . JMF_FRAMEWORK_URL . '/includes/assets/template/themecustomiser/less-1.7.0.js' . '"></script>'); $this->document->addCustomTag('<script type="text/javascript" src="' . JMF_FRAMEWORK_URL . '/includes/assets/template/themecustomiser/jmthemecustomiser.jquery.js' . '"></script>'); $language = array('LANG_PLEASE_WAIT' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEMER_WAIT'), 'LANG_PLEASE_WAIT_APPLYING' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEMER_WAIT_APPLYING'), 'LANG_PLEASE_WAIT_SAVING' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEMER_WAIT_SAVING'), 'LANG_PLEASE_WAIT_RELOADING' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEMER_WAIT_RELOADING'), 'LANG_ERROR_FORBIDDEN' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEME_LOGIN_ERROR'), 'LANG_ERROR_UNAUTHORISED' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEME_ACCESS_ERROR'), 'LANG_ERROR_BAD_REQUEST' => JText::_('PLG_SYSTEM_JMFRAMEWORK_THEME_BAD_REQUEST_ERROR')); // extending JMThemeCustomiser with some variables and initialising Theme Customiser $script_interface = "\n jQuery.extend(JMThemeCustomiser, {\n url: '" . JFactory::getURI()->toString() . "',\n lang: " . json_encode($language) . ",\n lessVars: " . json_encode($form_vars) . ",\n cookie: {path: '" . $cookie_path . "', domain: '" . $cookie_domain . "'},\n styleId : " . (int) $app->getTemplate('template')->id . ",\n login_form : " . (int) $this->document->params->get('themerlogin', 0) . "\n });\n\n JMThemeCustomiser.init(\"" . $this->template . "\");\n \n jQuery(document).ready(function(){\n JMThemeCustomiser.render();\n jQuery(document).trigger('JMFrameworkInit');\n });\n "; $this->document->addCustomTag('<script type="text/javascript">' . $script_interface . '</script>'); // Adding all scripts manually $this->document->addStyleSheet(JMF_FRAMEWORK_URL . '/includes/assets/template/themecustomiser/jmthemecustomiser.css'); //$this->document->addStyleSheet(JURI::root(false).'plugins/system/ef4_jmframework/includes/assets/admin/formfields/jmiriscolor/iris.min.css'); $this->document->addScript(JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/js/jquery/jquery.ui.draggable.js'); $this->document->addScript(JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/js/jquery/jquery.ui.slider.js'); $this->document->addScript(JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/js/jquery/jquery.ui.accordion.js'); //$this->document->addScript(JURI::root(false).'plugins/system/ef4_jmframework/includes/assets/admin/formfields/jmiriscolor/iris.js'); $this->document->addScript(JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/js/jmoptiongroups.js'); $this->document->addScript(JURI::root(false) . 'plugins/system/ef4_jmframework/includes/assets/admin/js/jmgooglefont.js'); $this->document->addScriptDeclaration("\n jQuery(document).on('JMFrameworkInit', function(){\n jQuery('.jmirispicker').each(function() {\n jQuery(this).iris({\n hide: true,\n palettes: true\n });\n });\n \n jQuery('.minicolors').each(function() {\n jQuery(this).minicolors({\n control: jQuery(this).attr('data-control') || 'hue',\n position: jQuery(this).attr('data-position') || 'right',\n theme: 'bootstrap'\n });\n });\n \n jQuery(document).on('click',function(event){\n jQuery('.jmirispicker').each(function() {\n if (event.target != this && typeof jQuery(this).iris != 'undefined') {\n jQuery(this).iris('hide');\n }\n });\n });\n \n var JMThemerGoogleFonts = new JMGoogleFontHelper('.google-font-url').initialise();\n \n });\n "); self::$less_js_included = true; } }
/** * Overriden JMFTemplate::getPosition() function for Layout Builder purpose */ function getPosition($name) { return parent::getPosition($name) . '" data-name="' . $name; }
public static function getTemplateStyleId() { if (self::$style_id !== false) { return self::$style_id; } $app = JFactory::getApplication(); if ($app->isAdmin()) { $option = $app->input->get('option', null, 'string'); $view = $app->input->get('view', null, 'string'); $task = $app->input->get('task', '', 'string'); $controller = current(explode('.', $task)); $id = $app->input->get('id', null, 'int'); if ($option == 'com_templates' && ($view == 'style' || $controller == 'style' || $task == 'apply' || $task == 'save' || $task == 'save2copy') && $id > 0) { self::$style_id = $id; } } else { $id = @JFactory::getApplication()->getTemplate(true)->id; if (!$id) { $menu = $app->getMenu(); $item = $menu->getActive(); if (!$item) { $item = $menu->getItem($this->input->getInt('Itemid', null)); } $id = 0; if (is_object($item)) { // Valid item retrieved $id = $item->template_style_id; } $tid = $app->input->getUint('templateStyle', 0); if (is_numeric($tid) && (int) $tid > 0) { $id = (int) $tid; } // Load styles $db = JFactory::getDbo(); $query = $db->getQuery(true)->select('id, home, template, s.params')->from('#__template_styles as s')->where('s.client_id = 0')->where('e.enabled = 1')->join('LEFT', '#__extensions as e ON e.element=s.template AND e.type=' . $db->quote('template') . ' AND e.client_id=s.client_id'); $db->setQuery($query); $templates = $db->loadObjectList('id'); $template = false; foreach ($templates as &$template) { // Create home element if ($template->home == 1 && !isset($templates[0]) || $app->getLanguageFilter() && $template->home == $tag) { $templates[0] = clone $template; } } if (isset($templates[$id])) { $template = $templates[$id]; } else { $template = $templates[0]; } self::$style_id = $template->id; } else { self::$style_id = $id; } } return self::$style_id; }
/** * Here go all the actions that have to be performed right before document's HEAD has been rendered. */ function onBeforeCompileHead() { $app = JFactory::getApplication(); $document = JFactory::getDocument(); // Don't proceed when current template is not compatible with EF4 Framework or we are in the Joomla back-end if (empty($this->template) || $app->isAdmin()) { return true; } $params = $app->getTemplate(true)->params; // Handling Facebook's Open Graph if ((bool) $params->get('facebookOpenGraph', true)) { $fbAppId = $params->get('facebookOpenGraphAppID', false); $this->addOpenGraph($fbAppId); } // Removing obsolete CSS stylesheets $css_to_remove = $app->get('jm_remove_stylesheets', array()); if (!empty($css_to_remove) && is_array($css_to_remove)) { foreach ($document->_styleSheets as $url => $cssData) { foreach ($css_to_remove as $oursUrl => $replacement) { if (strpos($url, $oursUrl) !== false) { unset($document->_styleSheets[$url]); if ($replacement && is_array($replacement) && isset($replacement['url']) && isset($replacement['type'])) { switch ($replacement['type']) { case 'css': $document->addStyleSheet($replacement['url'], 'text/css'); break; case 'less': $document->addHeadLink($replacement['url'], 'stylesheet/less'); break; default: break; } } } } } $app->set('jm_remove_stylesheets', false); } $themer = false; if ($tpl = JMFTemplate::getInstance()) { $themer = $tpl->params->get('themermode', false) == '1' ? true : false; $customPath = JPath::clean(JMF_TPL_PATH . '/less/custom.less'); if (JFile::exists($customPath)) { $tpl->addCompiledStyleSheet($customPath, true, $themer); } } $cssCompress = $params->get('cssCompress', '0') == '1' ? true : false; $jsCompress = $params->get('jsCompress', '0') == '1' ? true : false; // Don't compress CSS/JS when Development Mode or Joomla Debugging is enabled if ($themer || $params->get('devmode', 0) || JDEBUG || $app->input->get('option') == 'com_config') { if ($jsCompress) { $scripts = $document->_scripts; $newscripts = array(); foreach ($scripts as $url => $data) { // remove DJ-jQueryMonster placeholder for compressed javascript if (strstr($url, 'DJHOLDER_EF4COMPRESS') === false) { $newscripts[$url] = $data; } } $document->_scripts = $newscripts; } return true; } // Defer scripts loading excluding the jquery, mootools and selected scripts $canDefer = preg_match('/(?i)msie [6-9]/', $_SERVER['HTTP_USER_AGENT']) ? false : $params->get('jsDefer', '0') == '1'; //$excludeViews = array();//array('edit','form','additem','itemform','cart','checkout','contact','profileedit','renewitem','query'); if ($canDefer) { //&& !in_array($app->input->get('view'), $excludeViews)) { $scripts = $document->_scripts; $newscripts = array(); $skips = explode("\n", $params->get('skipDefer')); $skips[] = 'DJHOLDER_JQUERY'; $skips[] = 'DJHOLDER_NOCONFLICT'; $skips[] = 'DJHOLDER_EF4COMPRESS'; $skips[] = 'media/jui/js/jquery.min.js'; $skips[] = 'media/jui/js/jquery-noconflict.js'; $skips[] = 'media/system/js/mootools-core.js'; $skips[] = 'media/system/js/core.js'; $skips[] = 'media/system/js/calendar.js'; $skips[] = 'media/system/js/calendar-setup.js'; $skips[] = 'components/com_virtuemart/assets/js'; $skips[] = 'modules/mod_virtuemart_cart/assets/js'; $skips[] = '//maps.google.com/maps/api/js'; foreach ($scripts as $url => $data) { $defer = true; // skip excluded scripts from defer loading foreach ($skips as $skip) { $skip = trim($skip); if (empty($skip)) { continue; } //$this->debug("URL: ".$url."\nSKIP: ".$skip."\nCMP: ".(strstr($url, $skip)!==false ? 'TRUE':'FALSE')); if (strstr($url, $skip) !== false) { $defer = false; break; } } if ($defer) { $data['defer'] = true; } $newscripts[$url] = $data; } $document->_scripts = $newscripts; } // Preparing cache folder for CSS/JS compressed files if (JFolder::exists(JMF_TPL_PATH . DIRECTORY_SEPARATOR . 'cache') == false) { if (!JFolder::create(JMF_TPL_PATH . DIRECTORY_SEPARATOR . 'cache')) { if (JDEBUG) { throw new Exception(JText::_('PLG_SYSTEM_JMFRAMEWORK_CACHE_FOLDER_NOT_ACCESSIBLE')); } else { return false; } } } // Handling CSS minifications and compression. if ($cssCompress) { $styles = $document->_styleSheets; $compress = array(); $mtime = 0; foreach ($styles as $url => $style) { // Getting stylesheet path $path = $this->getPath($url); if (!$path || !JFile::exists($path)) { continue; } // Getting the last modification time of stylesheet $ftime = filemtime($path); if ($ftime > $mtime) { $mtime = $ftime; } $compress[$url] = $path; } $key = md5(serialize($compress)); $stylepath = JPath::clean(JMF_TPL_PATH . '/cache/jmf_' . $key . '.css'); $cachetime = JFile::exists($stylepath) ? filemtime($stylepath) : 0; $styleurl = JMF_TPL_URL . '/cache/jmf_' . $key . '.css?t=' . $cachetime; // Minify and merge stylesheets only if minified stylesheet isn't cached already or one of the stylesheets was modified if (!JFile::exists($stylepath) || $mtime > $cachetime) { require_once JPath::clean(JMF_FRAMEWORK_PATH . '/includes/libraries/minify/CSSmin.php'); $cssmin = new CSSmin(); $css = array(); $css[] = "/* EF4 CSSmin */"; //$css[] = " * --------------------------------------- */"; foreach ($compress as $url => $path) { $src = JFile::read($path); $src = $this->updateUrls($src, dirname($url)); //$css[] = "\n/* src: ".$url." */"; $css[] = $cssmin->run($src, 1024); } $css = implode("\n", $css); JFile::write($stylepath, $css); } // Removing all merged stylesheets from the head and adding the minified stylesheet instead if (JFile::exists($stylepath)) { $newstyles = array(); if ($app->input->get('inlinecss') == '1') { $document->_style['text/css'] .= file_get_contents($stylepath); } else { $newstyles[$styleurl] = array('mime' => 'text/css', 'media' => null, 'attribs' => array()); } foreach ($styles as $url => $data) { if (!array_key_exists($url, $compress)) { $newstyles[$url] = $data; } } $document->_styleSheets = $newstyles; } } // Handling JS minifications and compression. if ($jsCompress) { $scripts = $document->_scripts; $compress = array('noattr' => array(), 'async' => array(), 'defer' => array()); $mtime = 0; foreach ($scripts as $url => $data) { //$this->debug($data, true); // Getting script path $path = $this->getPath($url); if (!$path || !JFile::exists($path)) { continue; } // Getting the last modification time of script $ftime = filemtime($path); if ($ftime > $mtime) { $mtime = $ftime; } $idx = $data['async'] ? 'async' : $data['defer'] ? 'defer' : 'noattr'; $compress[$idx][$url] = $path; } $key = md5(serialize($compress['noattr'])); $scriptpath = JPath::clean(JMF_TPL_PATH . '/cache/jmf_' . $key . '.js'); $cachetime = JFile::exists($scriptpath) ? filemtime($scriptpath) : 0; $scripturl = JMF_TPL_URL . '/cache/jmf_' . $key . '.js?t=' . $cachetime; // Minify and merge scripts only if minified script isn't cached already or one of the scripts was modified if (!JFile::exists($scriptpath) || $mtime > $cachetime) { require_once JPath::clean(JMF_FRAMEWORK_PATH . '/includes/libraries/minify/JSMin.php'); $js = array(); $js[] = "/* EF4 JSMin */"; //$js[] = " * -------------------------------------- */"; foreach ($compress['noattr'] as $url => $path) { $src = JFile::read($path); //$js[] = "\n/* src: " . $url . " */"; $js[] = JSMin::minify($src) . ";"; } $js = implode("\n", $js); JFile::write($scriptpath, $js); } if (count($compress['async'])) { $key = md5(serialize($compress['async'])); $scriptpath_async = JPath::clean(JMF_TPL_PATH . '/cache/jmf_' . $key . '.js'); $cachetime = JFile::exists($scriptpath_async) ? filemtime($scriptpath_async) : 0; $scripturl_async = JMF_TPL_URL . '/cache/jmf_' . $key . '.js?t=' . $cachetime; // Minify and merge scripts only if minified script isn't cached already or one of the scripts was modified if (!JFile::exists($scriptpath_async) || $mtime > $cachetime) { require_once JPath::clean(JMF_FRAMEWORK_PATH . '/includes/libraries/minify/JSMin.php'); $js = array(); $js[] = "/* EF4 JSMin */"; //$js[] = " * -------------------------------------- */"; foreach ($compress['async'] as $url => $path) { $src = JFile::read($path); //$js[] = "\n/* src: " . $url . " */"; $js[] = JSMin::minify($src) . ";"; } $js = implode("\n", $js); JFile::write($scriptpath_async, $js); } } if (count($compress['defer'])) { $key = md5(serialize($compress['defer'])); $scriptpath_defer = JPath::clean(JMF_TPL_PATH . '/cache/jmf_' . $key . '.js'); $cachetime = JFile::exists($scriptpath_defer) ? filemtime($scriptpath_defer) : 0; $scripturl_defer = JMF_TPL_URL . '/cache/jmf_' . $key . '.js?t=' . $cachetime; // Minify and merge scripts only if minified script isn't cached already or one of the scripts was modified if (!JFile::exists($scriptpath_defer) || $mtime > $cachetime) { require_once JPath::clean(JMF_FRAMEWORK_PATH . '/includes/libraries/minify/JSMin.php'); $js = array(); $js[] = "/* EF4 JSMin */"; //$js[] = " * -------------------------------------- */"; foreach ($compress['defer'] as $url => $path) { $src = JFile::read($path); //$js[] = "\n/* src: " . $url . " */"; $js[] = JSMin::minify($src) . ";"; } $js = implode("\n", $js); JFile::write($scriptpath_defer, $js); } } // Removing all merged scripts from the head and adding the minified script instead if (JFile::exists($scriptpath)) { $newscripts = array(); if (!array_key_exists('DJHOLDER_EF4COMPRESS', $scripts)) { if ($app->input->get('inlinejs') == '1') { $document->_script['text/javascript'] = file_get_contents($scriptpath) . ";\n" . $document->_script['text/javascript']; } else { $newscripts[$scripturl] = array('mime' => 'text/javascript', 'defer' => false, 'async' => false); } } foreach ($scripts as $url => $data) { if ($url == 'DJHOLDER_EF4COMPRESS') { if ($app->input->get('inlinejs') == '1') { $document->_script['text/javascript'] = file_get_contents($scriptpath) . ";\n" . $document->_script['text/javascript']; } else { $newscripts[$scripturl] = $data; } } else { if (!array_key_exists($url, $compress['noattr']) && !array_key_exists($url, $compress['async']) && !array_key_exists($url, $compress['defer'])) { $newscripts[$url] = $data; } } } if (count($compress['async']) && JFile::exists($scriptpath_async)) { $newscripts[$scripturl_async] = array('mime' => 'text/javascript', 'defer' => true, 'async' => true); } if (count($compress['defer']) && JFile::exists($scriptpath_defer)) { $newscripts[$scripturl_defer] = array('mime' => 'text/javascript', 'defer' => true, 'async' => false); } $document->_scripts = $newscripts; } } }