進階主題

From Joomla! Documentation

This page is a translated version of the page Advanced topics and the translation is 100% complete.

Other languages:
български • ‎বাংলা • ‎Deutsch • ‎English • ‎español • ‎فارسی • ‎français • ‎हिन्दी • ‎Nederlands • ‎中文(台灣)‎
Joomla! 
2.5 & 3.x
系列

佈景主題是如何運作的?

佈景主題的執行是一個2階段運作,完整利用了PHP解析器的佈景主題設計工具提供了相當高的靈活彈性與性能。佈景主題會根據文件物件來執行,所以$this 總會是物件 JDocument class 實例化。

在佈景主題開始執行之前,會先執行元件,然後儲存於緩衝供未來使用。

接著佈景主題依以下程序執行:

  • 載入佈景主題參數(假使有的話)
  • 載入佈景主題語言(假使有的話)
  • 假使啟用相容模式,則會將設定變數複製為全站
  • 載入佈景主題檔案 (index.php) 並透過PHP執行,儲存輸出於緩衝,此為二階段程序中的第一階段。所有在標籤 <?php and ?> 都會當成 PHP 程式語言來執行。所有在標籤以外的會被輸出,其餘的會被忽略。由於輸出是被緩衝起來,所以在此階段,客戶端的瀏覽器看不到任何東西。
  • 尋找 favicon.ico 檔案。首先會在 Joomla! 根目錄尋找,接著在佈景主題根目錄,找到的話,後者會覆蓋前者。
  • 此時,緩衝於第一階段的輸出會為 <jdoc:include> 元素進行解析。這是第二階段。根據找到的每一個jdoc元素,會載入適當的解析器 class ,並且會呼叫其解析 method。從解析方法輸出的內容,會取代輸出緩衝中的 <jdoc:include> 元素。In the case of module renderer classes this triggers the execution of the modules and the buffering of their output.
  • 加入佈景主題特定的 HTTP 頁首到要輸出的頁首清單中
  • Control is then passed back to the JApplication object which will handle the rest of the process of getting the now rendered web page back to the client web browser.


系統錯誤頁面

錯誤頁面模版

預設 Joomla! 使用特殊的模版,來顯示錯誤的回應,檔案位於 templates/system 目錄底下。 For server-level status codes these are named for the status code that is being raised. 預設的系統錯誤頁面如下:

  • templates/system/403.php (Status code: 403 Forbidden)
  • templates/system/404.php (Status code: 404 Not Found)
  • templates/system/500.php (Status code: 500 Internal Server Error)

In addition, these system error pages are also available:

  • templates/system/component.php (not sure when this is used)
  • templates/system/offline.php is used to render the "site is offline" message.

Note that jdoc:include elements are not parsed in these error pages.

The status codes are defined as part of the HTTP protocol in RFC2616. For further information on HTTP status codes see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Styling the Error Pages

These pages can be styled using the following CSS classes:

  • errorboxheader
  • errorboxbody
  • techinfo


客製化錯誤頁面

Joomla! 使用 templates/system/error.php 檔案來管理各種 HTTP 狀態錯誤,包含 "403 Forbidden"、"404 Not Found"、以及 "500 Internal Server" 錯誤。如果想要的話,您可以改變錯誤訊息的樣式。

It is important to understand that error.php is an independent file from the Joomla! CMS but dependent on the Joomla! Platform. Plugins do not run on the file. You cannot include modules or use <jdoc:include> statements.

要覆寫系統錯誤結果

要覆寫系統錯誤結果,可以複製 templates/system/error.php 檔案到您的 templates/<template-name> 路徑。

If it finds one, Joomla! will use the error.php file from the current template, in place of the system file.

You can format the page, as desired, to match your template.

Overriding the System Styling

If you want to change the styling, copy the templates/system/css/error.css file into your templates/<template-name>/css directory. Next, update your templates/<template-name>/error.php file to reference the new location of the stylesheet by changing this line, accordingly:

<link rel="stylesheet" href="<?php echo $this->baseurl; ?>/templates/system/css/error.css" type="text/css" />

Then, simply change the error.css, as desired, for your styling requirements.

Customizing Error Messages

You can add conditional logic to vary the message returned, dependent upon the specific error code.

Here is an example of how to trap a 404 error and provide a custom message.

<?php  if ($this->error->getCode() == '404') { ?>
	<div id="errorboxheader">Page not found</div>
		<div id="errorboxbody"><p>Sorry! That page cannot be found.</p>
		</div>
	</div>
<?php } ?>

HTTP Status Code

When a request is made for a page on your site, the server returns an HTTP status code in response to the request. Joomla! returns a '200 - the server successfully returned the page' for error pages. This is problematic for those working with Google Webmaster Services and trying to get a sitemap resolved.

If you want Joomla! to return a status code for the error, you can do so by adding logic before the DOCTYPE line, as follows:

<?php 
if ($this->error->getCode() == '404') {
	header("HTTP/1.0 404 Not Found");
} ?>

更多 HTTP Status Code 資訊

在標準錯誤頁面使用主題頁首頁尾

Joomla 1.5 If you want to see the error page in theme design and don't like redirecting to error page URL or duplicating HTML in the error page template, here is a way to apply your theme template to the error page.

First, put the following code in templates/<template-name>/error.php:

<?php
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

include dirname(__FILE__) . "/index.php";
?>

Then make the following edits to templates/<template-name>/index.php:

1. 在 index.php 找到以下的程式碼

<jdoc:include type="head" />

替換為以下的內容

<?php if (!$this->error->getCode()) : ?>
<jdoc:include type="head" />
<?php else : ?> 
<title><?php echo $this->error->getCode() ?> - <?php echo $this->title; ?></title>
<?php endif; ?>

2. 在 index.php找到以下的程式碼

<jdoc:include type="component" />

替換為以下的內容

<?php if ($this->error->getCode()) : /* check if we are on error page, if yes - display error message */ ?>
  <p><strong><?php echo $this->error->getCode() ?> - <?php echo $this->error->message ?></strong></p>
  <p><strong><?php echo JText::_('JERROR_LAYOUT_NOT_ABLE_TO_VISIT'); ?></strong></p>
  <ol>
    <li><?php echo JText::_('JERROR_LAYOUT_AN_OUT_OF_DATE_BOOKMARK_FAVOURITE'); ?></li>
    <li><?php echo JText::_('JERROR_LAYOUT_SEARCH_ENGINE_OUT_OF_DATE_LISTING'); ?></li>
    <li><?php echo JText::_('JERROR_LAYOUT_MIS_TYPED_ADDRESS'); ?></li>
    <li><?php echo JText::_('JERROR_LAYOUT_YOU_HAVE_NO_ACCESS_TO_THIS_PAGE'); ?></li>
    <li><?php echo JText::_('JERROR_LAYOUT_REQUESTED_RESOURCE_WAS_NOT_FOUND'); ?></li>
    <li><?php echo JText::_('JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST'); ?></li>
  </ol>
  <p><strong><?php echo JText::_('JERROR_LAYOUT_PLEASE_TRY_ONE_OF_THE_FOLLOWING_PAGES'); ?></strong></p>

  <ul>
  <li><a href="<?php echo $this->baseurl; ?>/index.php" title="<?php echo JText::_('JERROR_LAYOUT_GO_TO_THE_HOME_PAGE'); ?>"><?php echo JText::_('JERROR_LAYOUT_HOME_PAGE'); ?></a></li>
  </ul>

  <p><?php echo JText::_('JERROR_LAYOUT_PLEASE_CONTACT_THE_SYSTEM_ADMINISTRATOR'); ?>.</p>
<?php else : ?>
  <jdoc:include type="component" />
<?php endif; ?>

現在您的佈景主題會被套用在錯誤訊息頁面

注意: 這個方法建立的錯誤訊息頁面,會讓佈景主題規劃的模組無法作用(但會在其他頁面上作用)。

在錯誤頁面中使用模組

同樣地,不像佈景主題index.php,因為您不能使用 <jdoc:include> 聲明,在錯誤訊息頁面中,不能使用佈景主題規劃的模組。您可以使用 JModuleHelper

要依據標題 include 單一模組,您可以使用:

if (JModuleHelper::getModule('menu')) { 
    echo $doc->getBuffer('module', 'menu');
}

要依據位置 include 多個模組,您可以使用:

$modules = JModuleHelper::getModules( 'footer_3' );
$attribs['style'] = 'xhtml';
foreach ($modules AS $module ) {
    echo JModuleHelper::renderModule( $module, $attribs );
}


加入 JavaScript

Note that a more up-to-date Joomla document covering this topic can be found at Adding JavaScript and CSS to the page, although it currently doesn't cover the more advanced topics at the bottom of this page.

JavaScript(也稱為ECMAScript)是一種應用於用戶端網站開發的腳本語言,用於擴展和增強末端使用者的網頁體驗。Joomla為開發者提供容易使用的方式來加入Javascript,使用我們的API來擴展。 在Joomla中加入JavaScript的方法有很多,其中一些如下所述。

使用方法

There are three methods for embedding JavaScript into your code using the Joomla API; JDocument::addScriptDeclaration, JDocument::addScript and script. These methods should be called either in your component's View class <yourcomponent>/views/<yourview>/view.html.php or template script <yourcomponent>/views/<yourview>/tmpl/<yourtemplate>.php or in the case of a module, in its template script <yourmodule>/tmpl/<yourtemplate>.php.

行內 JavaScript

Blocks of JavaScript code can be declared directly within a component or module's display template using the JDocument class' addScriptDeclaration method:

<?php
$document = JFactory::getDocument();
$document->addScriptDeclaration('
    window.event("domready", function() {
        alert("An inline JavaScript Declaration");
    });
');
?>

外部 JavaScript

Alternatively, you may wish to separate your JavaScript into a separate file. Separating your JavaScript into an external file can make your template code easier to read especially if the JavaScript is lengthy or complex.

There are two ways to include a JavaScript file using the Joomla! API. The first involves using the JDocument class' addScript method:

<?php
$document = JFactory::getDocument();
$document->addScript('/media/system/js/sample.js');
?>

The second uses the JHTML class' script method:

<?php
// Add the path parameter if the path is different than 'media/system/js/'
JHTML::script('sample.js', 'templates/custom/js/');
?>

API has changed in 3.x, so the second parameter cannot be a string. If you really need to use this method, you must include the absolute link to your JavaScript file:

<?php
JHtml::script(Juri::base() . 'templates/custom/js/sample.js');
?>

You can use options in a third parameter. This example shows the options version and relative . The file example should be saved in the folder media/com_example/js/example.min.js. So you do NOT need to insert the js in the path you insert as second parameter.

<?php
JHtml::_('script', 'com_example/example.min.js', array('version' => 'auto', 'relative' => true));
?>

Description

The Joomla API's JDocument::addScriptDeclaration, JDocument::addScript and script methods embed JavaScript into Joomla's index.php via the jdoc head tag:

<jdoc:include type="head"/>

Using the JDocument::addScript or script methods to embed JavaScript includes would result in the index.php rendering the following HTML:

<head>
...
<script type="text/javaScript" src="/media/system/js/sample.js"></script>
...
</head>

Calling the class method JDocument::addScriptDeclaration would render the following HTML:

<head>
...
<script type="text/javaScript">
window.addEvent("domready", function() {
    alert("Embedded block of JS here");
});
</script>
...
</head>

Using these methods is highly recommended as it clearly differentiates another scripting language (JavaScript) from the main PHP code, ensures all JavaScript is correctly embedded between the <head></head> tags and, in the case of JDocument::addScript and JHTML::script ensures that a JavaScript file is included only once (I.e. there is no .js file duplication).

Using a JavaScript Framework

A Javascript framework provides developers with generic functionality for handling various coding tasks in a familiar, consistent and platform-independent way. A framework enables the developer to forget about the intricacies of implementing a certain function in different web browsers and focus on the requirements of the software.

Two Javascript Frameworks are provided as part of Joomla 3.x; jQuery and Mootools. jQuery is a newly introduced framework which integrates with Joomla's new Bootstrap HTML framework; Mootools is Joomla's legacy Javascript library which is now superseded by jQuery and is included for backwards compatibility with 3rd party extensions.

In nearly all cases you should use a framework when developing Javascript in your extensions or templates and including one is very simple with Joomla's API.

Joomla 3.x jQuery

Please see the guide on Javascript Frameworks in Joomla 3.x for information about including a framework in Joomla 3.x

Joomla 1.5/2.5 Mootools

Unless you are maintaining Javascript code which leverages Mootools or you are developing an extension for Joomla 2.5 or earlier it is recommended you use jQuery instead.

Firstly, you will need to include the Mootools code in your extension. To include the Mootools framework in your extension, you add the following code to your view.html.php or tmpl file:

FOR JOOMLA 1.5

JHTML::_('behavior.mootools');

FOR JOOMLA 2.5

JHtml::_('behavior.framework');

The above code results in the same outcome as the similar jQuery framework statement; that is it ensures Mootools is included correctly and only once.

Then using Mootools is almost identical to jQuery:

JFactory::getDocument()->addScriptDeclaration('
window.addEvent("domready", function() {
    alert($("list").getElements("li").length);
});
');

More information about Mootools is available at http://mootools.net/. For API documentation, visit http://mootools.net/docs/core.

Important notes for 3rd party developers

If you are creating a custom template override or extension that needs to add a custom JS file, make sure to add important dependencies such as Jquery or Mootools before your custom JS files. JS framework files must always be loaded before any other files to make sure they get executed first, otherwise other files that load before the frameworks they need are likely to end in JS exceptions.

Some templates like Protostar or Beez insert all the dependencies you need using functions like

JHtml::_('bootstrap.framework');

to load Jquery + Bootstrap, but you should not rely in this fact on your extensions or custom templates overrides. Always make sure your extension or custom override load the dependencies you need before the template does it, I will explain why later:

For example if you got a custom template override that needs to insert a JS file with some Jquery scripts that does fancy things on all the pages where that template override is being used. In that case you should declare this on the top section of that override file:

JHtml::_('jquery.framework');
$doc->addScript('templates/'.$this->template.'/js/fancy-script.js');

If you are developing a 3rd party extension that you plan to put on the Joomla! extension directory you should do something like this:

if($params->get('add_extension_resources', false))
{
    JHtml::_('jquery.framework');
    $doc->addScript('media/com_fancy/js/fancy-script.js');
}

The conditional clause to decide whether to add or not the extension resources is strongly encouraged and considered a good practice because it gives flexibility to 3rd party developers who don't want to use your extension resources and use custom/modified files without having to battle with Joomla! using workarounds and hacks to be able to remove your original extensions resources in order to avoid duplicates and conflicts.

Explanation

If you check the source code of the index.php from the Protostar template, you can see that the statements

JHtml::_('bootstrap.framework');

is added way before the statement

<jdoc:include type="head" />

this can make you think that the framework files and your 3rd party files using methods like

$doc->addScript('templates/'.$this->template.'/js/fancy-script.js');
$doc->addScript('media/com_fancy/js/fancy-script.js');

will be added in the right order at the right spot, but that is not the case, because extension files and template override files are processed first and the index.php file of your current template is processed the last. This will cause that your custom JS files get inserted first and the framework files inserted from the template get inserted after.

This happens because the Joomla! API (such as $doc->addScript) uses an array to store the JS files paths and they get rendered in the document in the same order they where inserted into that array (FIFO stack). Also, once a file path is inserted on the array and another API call tries to insert the same file this action is ignored to avoid duplicates. It also means that the order of the files is not altered when the same files is attempted to be inserted several times.

Having said that doing this

JHtml::_('jquery.framework');
$doc->addScript('templates/'.$this->template.'/js/fancy-script.js');

at your custom templates overrides and extension, is required and does not cause harm or conflict with the call

JHtml::_('bootstrap.framework');

at your template index.php file.

外部連結

Joomla 2.5 https://api.joomla.org/cms-2.5/classes/JHtmlBehavior.html#method_framework

Joomla 3.x https://api.joomla.org/cms-3/classes/JHtmlBehavior.html#method_framework

http://en.wikipedia.org/wiki/JavaScript

http://www.w3schools.com/js/default.asp

http://mootools.net/

http://jquery.com/


如何確定瀏覽器相容性

Different web browsers sometimes show differences in the way that they render a page. For this reason you may wish to find out which particular browser a visitor is using, in order to use some browser-specific CSS.

The following JavaScript defines a simple browser detection object which determines the browser's name and version by decoding the navigator.userAgent string.

function browserDetect()
{
  var browserNames=new Array("Opera", "MSIE","Netscape","Firefox");
  this.name="NK";
  this.mainVersion="NK";
  this.minorVersion="NK";
  
  for (var i=0; i< browserNames.length; i++)
  {
   var pattern='('+browserNames[i]+')'+'.([0-9]+)\.([0-9]+)';    
   var myRegExp=new RegExp(pattern);
   if (myRegExp.test(navigator.userAgent))
    {
      var results=myRegExp.exec(navigator.userAgent);
      this.name=results[1];
      this.mainVersion=results[2];
      this.minorVersion=results[3];
      break;
    }
  }
}

In order to use this in a script, you then create an instance of this object:

var browser = new browserDetect();

The property browser.name will then give you then name of the browser (MSIE, Opera, Netscape or Firefox), browser.mainVersion will give you the main version number and browser.minorVersion will give you the minor version number.

However you should be aware that this is not foolproof, and it is generally better (in this writer's opinion) to avoid writing browser-specific code as far as possible.


為其他裝置新增樣式表(stylesheets)

要使用 CSS 樣式表,可以 it is possible to use a set of directives(styles) depending upon the device being used to browse web pages.

媒體類型

可以識別的媒體類型有:

  • all - 適用於所有裝置
  • aural - For speech synthesizers.
  • braille - Intended for braille tactile feedback devices.
  • embossed - 用於 paged braille printers.
  • handheld - 用於手持裝置
  • print - 用於組織印表機輸出頁面
  • projection - 用於 projected presentations。例如投影裝置或是 print to transparencies.
  • screen - 主要用於彩色電腦螢幕
  • tty - Intended for media using a fixed-pitch character grid, such as teletypes, terminals, or portable devices with limited display capabilities. Authors should not use pixel units with the "tty" media type.
  • tv - Intended for television-type devices (low resolution, color, limited-scrollability screens, sound available).

範例

您可以使用底下的語法,指定 CSS declaration媒體類型

@media print {
  body { 
    font-size: 12pt;
    font-color: #000000; 
  }
}

要指定多個媒體類型到多個declaration style:

@media print, handheld{
  body { 
    font-size: 12pt;
    font-color: #000000;
  }
  img {
    max-width: 100%;
    height: auto;
  }
}

指令可以被用於主要的 CSS 檔案或是在另一個給媒體類型用的樣式表。There must be an include to the CSS file in the templates <head> section (以下是從 Joomla! Beez 佈景主題取得):

<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/beez/css/print.css" type="text/css" media="Print" />

include 樣式表,推薦的方式是:

<?php
$document = JFactory::getDocument();
 $tpath = $this->baseurl . '/templates/' . $this->template;
$document->addStyleSheet( $tpath . '/css/print.css', 'text/css', 'print'); // arguments: $path, $type, $media
?>

用這個方式,您可以確保樣式表被加到文件中,也可以讓外掛使用(亦即,用來組合或是壓縮樣式表)