diff options
Diffstat (limited to 'files/zh-cn/mozilla/add-ons')
73 files changed, 0 insertions, 11285 deletions
diff --git a/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html b/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html deleted file mode 100644 index 58b185e048..0000000000 --- a/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: 附加组件准则 -slug: Mozilla/Add-ons/Add-on_guidelines -tags: - - add-on - - 附加组件 -translation_of: 'https://extensionworkshop.com/documentation/publish/add-on-policies/' ---- -<p>REDIRECT <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/AMO/Policy/Reviews">https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/AMO/Policy/Reviews</a></p> diff --git a/files/zh-cn/mozilla/add-ons/amo/index.html b/files/zh-cn/mozilla/add-ons/amo/index.html deleted file mode 100644 index 0845e54e3d..0000000000 --- a/files/zh-cn/mozilla/add-ons/amo/index.html +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: AMO -slug: Mozilla/Add-ons/AMO -tags: - - NeedsTranslation - - TopicStub -translation_of: Mozilla/Add-ons/AMO ---- -<p>{{AddonSidebar}}</p> - -<p>Content to be added.</p> diff --git a/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html b/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html deleted file mode 100644 index c847ed92d1..0000000000 --- a/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: AMO 联系信息 -slug: Mozilla/Add-ons/AMO/Policy/Contact -tags: - - 附加组件支持 -translation_of: Mozilla/Add-ons#Contact_us ---- -<p>{{AddonSideBar}}</p> - -<p><span id="result_box" lang="zh-CN"><span>感谢您愿意与Mozilla 附加组件小组联络。</span> <span>请仔细阅读此页面,以确保您的请求能到达正确的地方。</span></span></p> - -<h4 id="附加组件支持">附加组件支持</h4> - -<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您有关于特定</span></span><span class="long_text" lang="zh-CN"><span>附加组件的支持问题,例如“如何使用此附加组件?”</span> <span>或“为什么不能正常工作?”,请通过附加组件列表页上列出的支持渠道联系该附加组件作者。</span></span></p> - -<h4 id="附加组件审查相关">附加组件审查相关</h4> - -<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您有关于附加组件审核希望报告违反政策的问题,请发送电子邮件至</span></span> <a href="mailto:amo-editors@mozilla.org">amo-editors@mozilla.org</a><span class="long_text" lang="zh-CN"><span>。几乎所有的附加组件报告都属于这个类别。请务必包含相关附加组件的链接以及您的问题或评论的详细说明。</span></span></p> - -<h4 id="附加组件安全漏洞">附加组件安全漏洞</h4> - -<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您在附加程序中发现了安全漏洞,即使它不在此处托管,Mozilla也对您的发现感兴趣并将与附加开发人员一起尽快更正该问题。</span></span><span><span>附加组件的安全问题可以直接报告</span></span>在 <a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=addons.mozilla.org&component=Add-on%20Security&maketemplate=Add-on%20Security%20Bug&bit-23=1&rep_platform=All&op_sys=All">Bugzilla</a> 的 <a href="http://www.mozilla.org/projects/security/security-bugs-policy.html">confidentially</a> 或发邮件给 <a href="mailto:amo-admins@mozilla.org">amo-admins@mozilla.org</a>.</p> - -<h4 id="网站功能与发展"><span><span>网站功能与发展</span></span></h4> - -<p><span><span>如果您发现本网站有问题</span></span> , 我们乐意修复。请在Github <a href="https://github.com/mozilla/addons/issues/new">上传BUG报告</a>, 报告中包括问题的位置以及您如何遇到这个问题。</p> - -<p><span class="comment seoSummary">关于这些政策或您的插件如何与我们联系。</span></p> diff --git a/files/zh-cn/mozilla/add-ons/amo/policy/index.html b/files/zh-cn/mozilla/add-ons/amo/policy/index.html deleted file mode 100644 index 58179ed4fa..0000000000 --- a/files/zh-cn/mozilla/add-ons/amo/policy/index.html +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: AMO Policies -slug: Mozilla/Add-ons/AMO/Policy -tags: - - NeedsTranslation - - TopicStub -translation_of: Mozilla/Add-ons/AMO/Policy ---- -<p>{{AddonSidebar}}</p> - -<p>Mozilla 致力于为我们的用户和开发人员确保极佳的附加体验,在提交您的附加组件之前,请查阅下列政策。</p> - -<dl> - <dd></dd><dt><a href="/Mozilla/Add-ons/AMO/Policy/Agreement">开发者协议</a></dt> -<dd>Effective January 5, 2016</dd> <dt><a href="/Mozilla/Add-ons/AMO/Policy/Reviews">审核处理</a></dt> -<dd>Add-ons extend the core capabilities of Firefox, allowing users to modify and personalize their Web experience. A healthy add-on ecosystem, built on trust, is vital for developers to be successful and users to feel safe making Firefox their own. For these reasons, Mozilla requires all add-ons to comply with the following set of policies on acceptable practices. The below is not intended to serve as legal advice, nor is it intended to serve as a comprehensive list of terms to include in your add-on’s privacy policy.</dd><br> - <dt><a href="/Mozilla/Add-ons/AMO/Policy/Featured">精选的Add-ons</a></dt> -<dd>How up-and-coming add-ons become featured and what's involved in the process. </dd><br> - <strong><a href="https://developer.mozilla.org/en-US/Add-ons#Contact_us">联系我们</a></strong> - - <p> How to get in touch with us regarding these policies or your add-on.</p> - -</dl> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html deleted file mode 100644 index 002a1b8600..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Canvas 代码片段 -slug: Mozilla/Add-ons/Code_snippets/Canvas -translation_of: Archive/Add-ons/Code_snippets/Canvas ---- -<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p> - -<p>关于使用<code><canvas></code>的一般信息,请参阅 <a class="internal" href="/en-US/docs/Web/API/Canvas_API" title="En/HTML/Canvas">canvas topic page</a>.</p> - -<h2 id="网页中可以用到的代码">网页中可以用到的代码</h2> - -<h3 id="在画布中获取特定颜色的像素数量">在画布中获取特定颜色的像素数量</h3> - -<p>下面的函数将返回画布上颜色(RGB格式)为r、g、b的像素数量。如果用户希望像<a href="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/" title="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/">这篇博客文章</a>中在另一个区域绘画,那么这将非常有用。 </p> - -<pre class="brush: js">function getpixelamount(canvas, r, g, b) { - var cx = canvas.getContext('2d'); - var pixels = cx.getImageData(0, 0, canvas.width, canvas.height); - var all = pixels.data.length; - var amount = 0; - for (i = 0; i < all; i += 4) { - if (pixels.data[i] === r && - pixels.data[i + 1] === g && - pixels.data[i + 2] === b) { - amount++; - } - } - return amount; -}; -</pre> - -<h3 id="在画布中获取某一个像素的颜色">在画布中获取某一个像素的颜色</h3> - -<p>下面的代码片段返回一个对象,该对象在画布的x和y的位置上具有RGBA值。这可以用来确定鼠标光标是否在一个特定的形状中。</p> - -<pre class="brush: js">function getpixelcolour(canvas, x, y) { - var cx = canvas.getContext('2d'); - var pixel = cx.getImageData(x, y, 1, 1); - return { - r: pixel.data[0], - g: pixel.data[1], - b: pixel.data[2], - a: pixel.data[3] - }; -} -</pre> - -<h3 id="链式调用方法">链式调用方法</h3> - -<p>这个类允许可以像jQuery那样链式地访问 2D 渲染上下文的方法和属性 。</p> - -<pre class="brush: js">function Canvas2DContext(canvas) { - if (typeof canvas === 'string') { - canvas = document.getElementById(canvas); - } - if (!(this instanceof Canvas2DContext)) { - return new Canvas2DContext(canvas); - } - this.context = this.ctx = canvas.getContext('2d'); - if (!Canvas2DContext.prototype.arc) { - Canvas2DContext.setup.call(this, this.ctx); - } -} -Canvas2DContext.setup = function() { - var methods = ['arc', 'arcTo', 'beginPath', 'bezierCurveTo', 'clearRect', 'clip', - 'closePath', 'drawImage', 'fill', 'fillRect', 'fillText', 'lineTo', 'moveTo', - 'quadraticCurveTo', 'rect', 'restore', 'rotate', 'save', 'scale', 'setTransform', - 'stroke', 'strokeRect', 'strokeText', 'transform', 'translate']; - - var getterMethods = ['createPattern', 'drawFocusRing', 'isPointInPath', 'measureText', // drawFocusRing not currently supported - // The following might instead be wrapped to be able to chain their child objects - 'createImageData', 'createLinearGradient', - 'createRadialGradient', 'getImageData', 'putImageData' - ]; - - var props = ['canvas', 'fillStyle', 'font', 'globalAlpha', 'globalCompositeOperation', - 'lineCap', 'lineJoin', 'lineWidth', 'miterLimit', 'shadowOffsetX', 'shadowOffsetY', - 'shadowBlur', 'shadowColor', 'strokeStyle', 'textAlign', 'textBaseline']; - - for (let m of methods) { - let method = m; - Canvas2DContext.prototype[method] = function() { - this.ctx[method].apply(this.ctx, arguments); - return this; - }; - } - - for (let m of getterMethods) { - let method = m; - Canvas2DContext.prototype[method] = function() { - return this.ctx[method].apply(this.ctx, arguments); - }; - } - - for (let p of props) { - let prop = p; - Canvas2DContext.prototype[prop] = function(value) { - if (value === undefined) - return this.ctx[prop]; - this.ctx[prop] = value; - return this; - }; - } -}; - -var canvas = document.getElementById('canvas'); - -// Use context to get access to underlying context -var ctx = Canvas2DContext(canvas) - .strokeStyle('rgb(30, 110, 210)') - .transform(10, 3, 4, 5, 1, 0) - .strokeRect(2, 10, 15, 20) - .context; - -// Use property name as a function (but without arguments) to get the value -var strokeStyle = Canvas2DContext(canvas) - .strokeStyle('rgb(50, 110, 210)') - .strokeStyle(); -</pre> - -<h2 id="Saving_a_canvas_image_to_a_file" name="Saving_a_canvas_image_to_a_file">Code usable only from privileged code</h2> - -<p>These snippets are only useful from privileged code, such as extensions or privileged apps.</p> - -<h3 id="Saving_a_canvas_image_to_a_file" name="Saving_a_canvas_image_to_a_file">将canvas图片保存到文件中</h3> - -<p>The following function accepts a canvas object and a destination file path string. The canvas is converted to a PNG file and saved to the specified location. The function returns a promise which resolves when the file has been completely saved.</p> - -<pre class="brush: js">function saveCanvas(canvas, path, type, options) { - return Task.spawn(function *() { - var reader = new FileReader; - var blob = yield new Promise(accept => canvas.toBlob(accept, type, options)); - reader.readAsArrayBuffer(blob); - - yield new Promise(accept => { reader.onloadend = accept }); - - return yield OS.File.writeAtomic(path, new Uint8Array(reader.result), - { tmpPath: path + '.tmp' }); - }); -} -</pre> - -<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">将一个远程页面加载到canvas元素上</h3> - -<p>The following class first creates a hidden iframe element and attaches a listener to the frame's load event. Once the remote page has loaded, the remotePageLoaded method fires. This method gets a reference to the iframe's window and draws this window to a canvas object.</p> - -<p>Note that this only works if you are running the page from chrome. If you try running the code as a plain webpage, you will get a 'Security error" code: "1000' error.</p> - -<pre class="brush: js">RemoteCanvas = function() { - this.url = 'http://developer.mozilla.org'; -}; - -RemoteCanvas.CANVAS_WIDTH = 300; -RemoteCanvas.CANVAS_HEIGHT = 300; - -RemoteCanvas.prototype.load = function() { - var windowWidth = window.innerWidth - 25; - var iframe; - iframe = document.createElement('iframe'); - iframe.id = 'test-iframe'; - iframe.height = '10px'; - iframe.width = windowWidth + 'px'; - iframe.style.visibility = 'hidden'; - iframe.src = this.url; - // Here is where the magic happens... add a listener to the - // frame's onload event - iframe.addEventListener('load', this.remotePageLoaded, true); - //append to the end of the page - window.document.body.appendChild(iframe); - return; -}; - -RemoteCanvas.prototype.remotePageLoaded = function() { - // Look back up the iframe by id - var ldrFrame = document.getElementById('test-iframe'); - // Get a reference to the window object you need for the canvas - // drawWindow method - var remoteWindow = ldrFrame.contentWindow; - - //Draw canvas - var canvas = document.createElement('canvas'); - canvas.style.width = RemoteCanvas.CANVAS_WIDTH + 'px'; - canvas.style.height = RemoteCanvas.CANVAS_HEIGHT + 'px'; - canvas.width = RemoteCanvas.CANVAS_WIDTH; - canvas.height = RemoteCanvas.CANVAS_HEIGHT; - var windowWidth = window.innerWidth - 25; - var windowHeight = window.innerHeight; - - var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, - RemoteCanvas.CANVAS_WIDTH, - RemoteCanvas.CANVAS_HEIGHT); - ctx.save(); - ctx.scale(RemoteCanvas.CANVAS_WIDTH / windowWidth, - RemoteCanvas.CANVAS_HEIGHT / windowHeight); - ctx.drawWindow(remoteWindow, - 0, 0, - windowWidth, windowHeight, - 'rgb(255, 255, 255)'); - ctx.restore(); -}; -</pre> - -<p>Usage:</p> - -<pre class="brush: js">var remoteCanvas = new RemoteCanvas(); -remoteCanvas.load(); -</pre> - -<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">将图像文件转换为base64字符串</h3> - -<p>下面代码加载远程图片,并把它的内容转化为 <code><a href="/en/data_URIs">Data URI scheme</a></code>。</p> - -<pre class="brush: js">var canvas = document.createElement('canvas'); -var ctxt = canvas.getContext('2d'); -function loadImageFile(url, callback) { - var image = new Image(); - image.src = url; - return new Promise((accept, reject) => { - image.onload = accept; - image.onerror = reject; - }).then(accept => { - canvas.width = this.width; - canvas.height = this.height; - ctxt.clearRect(0, 0, this.width, this.height); - ctxt.drawImage(this, 0, 0); - accept(canvas.toDataURL()); - }); -} -</pre> - -<p>Usage:</p> - -<pre class="brush: js">loadImageFile('myimage.jpg').then(string64 => { alert(string64); }); -</pre> - -<p>如果你想获取本地文件(使用文件选择input元素)的 base64 内容,你必须使用 <code><a href="/en/DOM/FileReader#readAsDataURL%28%29" title="en/DOM/FileReader#readAsDataURL%28%29">FileReader</a></code> 对象。</p> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/index.html deleted file mode 100644 index bfe77a4e38..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/index.html +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: Code snippets -slug: Mozilla/Add-ons/Code_snippets -tags: - - Add-ons - - Code snippets - - Extensions - - NeedsTranslation - - TopicStub -translation_of: Archive/Add-ons/Code_snippets ---- -<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p> - -<p>This is a quick list of useful code snippets (small code samples) available for developers of extensions for the various Mozilla applications. Many of these samples can also be used in XULRunner applications, as well as in actual Mozilla code itself.</p> - -<p>These examples demonstrate how to accomplish basic tasks that might not be immediately obvious.</p> - -<h2 id="General" name="General">General</h2> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/From_articles" title="/en-US/docs/Code_snippets/From_articles">Examples and demos from MDN articles</a></dt> - <dd>A collection of examples and demos from articles.</dd> - <dt><a href="/en-US/docs/Code_snippets/Windows" title="/en-US/docs/Code_snippets/Windows">Window code</a></dt> - <dd>Opening and manipulating windows</dd> - <dt><a href="/en-US/docs/Code_snippets/Toolbar" title="/en-US/docs/Code_snippets/Toolbar">Toolbar</a></dt> - <dd>Toolbar related code</dd> - <dt><a href="/en-US/docs/Code_snippets/Sidebar" title="/en-US/docs/Code_snippets/Sidebar">Sidebar</a></dt> - <dd>Sidebar related code</dd> - <dt><a href="/en-US/docs/Code_snippets/Forms">Forms</a></dt> - <dd>Forms related code</dd> - <dt><a href="/en-US/docs/Code_snippets/XML" title="/en-US/docs/Code_snippets/XML">XML</a></dt> - <dd>Code used to parse, write, manipulate, etc. XML</dd> - <dt><a href="/en-US/docs/Code_snippets/File_I_O" title="/en-US/docs/Code_snippets/File_I/O">File I/O</a></dt> - <dd>Code used to read, write and process files</dd> - <dt><a href="/en-US/docs/Code_snippets/Drag_&_Drop" title="/en-US/docs/Code_snippets/Drag_&_Drop">Drag & Drop</a></dt> - <dd>Code used to setup and handle drag and drop events</dd> - <dt><a href="/en-US/docs/Code_snippets/Dialogs_and_Prompts" title="/en-US/docs/Code_snippets/Dialogs_and_Prompts">Dialogs</a></dt> - <dd>Code used to display and process dialog boxes</dd> - <dt><a href="/en-US/docs/Code_snippets/Alerts_and_Notifications" title="/en-US/docs/Code snippets/Alerts and Notifications">Alerts and Notifications </a></dt> - <dd>Modal and non-modal ways to notify users</dd> - <dt><a href="/en-US/docs/Code_snippets/Preferences" title="/en-US/docs/Code_snippets/Preferences">Preferences</a></dt> - <dd>Code used to read, write, and modify preferences</dd> - <dt><a href="/en-US/docs/Code_snippets/JS_XPCOM" title="/en-US/docs/Code_snippets/JS_XPCOM">JS XPCOM</a></dt> - <dd>Code used to define and call XPCOM components in JavaScript</dd> - <dt><a href="/en-US/docs/Code_snippets/Running_applications" title="/en-US/docs/Code_snippets/Running_applications">Running applications</a></dt> - <dd>Code used to run other applications</dd> - <dt><a href="/en-US/docs/Code_snippets/Canvas" title="/en-US/docs/Code_snippets/Canvas"><code><canvas></code> related</a></dt> - <dd><a href="/en-US/docs/HTML/Canvas" title="/en-US/docs/HTML/Canvas">WHAT WG Canvas</a>-related code</dd> - <dt><a href="/en-US/docs/Signing_a_XPI" title="/en-US/docs/Signing_a_XPI">Signing a XPI</a></dt> - <dd>How to sign an XPI with PKI</dd> - <dt><a href="/en-US/docs/Code_snippets/Threads">Delayed Execution</a></dt> - <dd>Performing background operations.</dd> - <dt><a href="/en-US/docs/Code_snippets/Miscellaneous" title="/en-US/docs/Code_snippets/Miscellaneous">Miscellaneous</a></dt> - <dd>Miscellaneous useful code fragments</dd> - <dt><a href="/en-US/docs/Code_snippets/HTML_to_DOM" title="/en-US/docs/Code_snippets/HTML_to_DOM">HTML to DOM</a></dt> - <dd>Using a hidden browser element to parse HTML to a window's DOM</dd> -</dl> - -<h2 id="javascript-libraries" name="javascript-libraries">JavaScript libraries</h2> - -<p>Here are some JavaScript libraries that may come in handy.</p> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/StringView" title="/en-US/docs/Code_snippets/StringView">StringView</a></dt> - <dd>A library that implements a <code>StringView</code> view for <a href="/en-US/docs/Web/JavaScript/Typed_arrays" title="/en-US/docs/Web/JavaScript/Typed_arrays">JavaScript typed arrays</a>. This lets you access data in typed arrays using C-like string functions.</dd> - <dt><a href="/en-US/Add-ons/Code_snippets/Rosetta" title="/en-US/docs/Code_snippets/Rosetta">Rosetta</a></dt> - <dd>By default, the only possible standardized scripting language for HTML is <strong>ECMAScript</strong>. Hence, if you are going to use another scripting language you might expect that most of the browsers will not recognize it. Nevertheless, the increasing computational power of modern browsers together with the introduction of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays">typed arrays</a> in ECMAScript allow us, in theory, to build full <a class="external external-icon" href="http://en.wikipedia.org/wiki/Virtual_machine">virtual machines</a> in pure ECMAScript. Therefore, it is also possible, in theory, to use ECMAScript for a smaller task: parsing exotic programming languages (i.e., creating compilers). This snippets shows a possible way to start from.</dd> -</dl> - -<h2 id="Browser-oriented_code" name="Browser-oriented_code">Browser-oriented code</h2> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/Tabbed_browser" title="/en-US/docs/Code_snippets/Tabbed_browser">Tabbed browser code</a> (Firefox/SeaMonkey)</dt> - <dd>Basic operations, such as page loading, with the tabbed browser, which is the heart of Mozilla's browser applications</dd> - <dt><a href="/en-US/docs/Code_snippets/Cookies" title="/en-US/docs/Code_snippets/Cookies">Cookies</a></dt> - <dd>Reading, writing, modifying, and removing cookies</dd> - <dt><a href="/en-US/docs/Code_snippets/Page_Loading" title="/en-US/docs/Code_snippets/Page_Loading">Page Loading</a></dt> - <dd>Code used to load pages, reload pages, and listen for page loads</dd> - <dt><a href="/en-US/docs/Code_snippets/Interaction_between_privileged_and_non-privileged_pages" title="/en-US/docs/Code_snippets/Interaction_between_privileged_and_non-privileged_pages">Interaction between privileged and non-privileged code</a></dt> - <dd>How to communicate from extensions to websites and vice-versa.</dd> - <dt><a href="/en-US/docs/Code_snippets/Downloading_Files" title="/en-US/docs/Code_snippets/Downloading_Files">Downloading Files</a></dt> - <dd>Code to download files, images, and to monitor download progress</dd> - <dt><a href="/en-US/docs/Code_snippets/Password_Manager" title="/en-US/docs/Code_snippets/Password_Manager">Password Manager</a></dt> - <dd>Code used to read and write passwords to/from the integrated password manager</dd> - <dt><a href="/en-US/docs/Code_snippets/Bookmarks" title="/en-US/docs/Code_snippets/Bookmarks">Bookmarks</a></dt> - <dd>Code used to read and write bookmarks</dd> - <dt><a href="/en-US/docs/Code_snippets/JavaScript_Debugger_Service" title="/en-US/docs/Code_snippets/JavaScript_Debugger_Service">JavaScript Debugger Service</a></dt> - <dd>Code used to interact with the JavaScript Debugger Service</dd> -</dl> - -<h2 id="SVG" name="SVG">SVG</h2> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/SVG_General" title="/en-US/docs/Code_snippets/SVG_General">General</a></dt> - <dd>General information and utilities</dd> - <dt><a href="/en-US/docs/Code_snippets/SVG_Animation" title="/en-US/docs/Code_snippets/SVG_Animation">SVG Animation</a></dt> - <dd>Animate SVG using JavaScript and SMIL</dd> - <dt><a href="/en-US/docs/Code_snippets/SVG_Interacting_with_script" title="/en-US/docs/Code_snippets/SVG_Interacting_with_script">SVG Interacting with Script</a></dt> - <dd>Using JavaScript and DOM events to create interactive SVG</dd> - <dt><a href="/en-US/docs/Code_snippets/Embedding_SVG" title="/en-US/docs/Code_snippets/Embedding_SVG">Embedding SVG in HTML and XUL</a></dt> - <dd>Using SVG to enhance HTML or XUL based markup</dd> -</dl> - -<h2 id="XUL_Widgets" name="XUL_Widgets">XUL Widgets</h2> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/HTML_in_XUL_for_rich_tooltips" title="/en-US/docs/Code_snippets/HTML_in_XUL_for_rich_tooltips">HTML in XUL for Rich Tooltips</a></dt> - <dd>Dynamically embed HTML into a XUL element to attain markup in a tooltip</dd> - <dt><a href="/en-US/docs/Code_snippets/Label_and_description" title="/en-US/docs/Code_snippets/Label_and_description">Label and description</a></dt> - <dd>Special uses and line breaking examples</dd> - <dt><a href="/en-US/docs/Code_snippets/Tree" title="/en-US/docs/Code_snippets/Tree">Tree</a></dt> - <dd>Setup and manipulation of trees using XUL and JS</dd> - <dt><a href="/en-US/docs/Code_snippets/Scrollbar" title="/en-US/docs/Code_snippets/Scrollbar">Scrollbar</a></dt> - <dd>Changing style of scrollbars. Applies to scrollbars in browser and iframe as well.</dd> - <dt><a href="/en-US/docs/Code_snippets/Autocomplete" title="/en-US/docs/Code_snippets/Autocomplete">Autocomplete</a></dt> - <dd>Code used to enable form autocomplete in a browser</dd> - <dt><a href="/en-US/docs/Code_snippets/Boxes" title="/en-US/docs/Code_snippets/Boxes">Boxes</a></dt> - <dd>Tips and tricks when using boxes as containers</dd> - <dt><a class="internal" href="/en-US/docs/Code_snippets/Tabbox" title="/en-US/docs/Code snippets/Tabbox">Tabbox</a></dt> - <dd>Removing and manipulating tabs in a tabbox</dd> -</dl> - -<h2 id="Windows-specific" name="Windows-specific">Windows-specific</h2> - -<dl> - <dt><a href="/en-US/docs/Code_snippets/Finding_Window_Handles" title="/en-US/docs/Code_snippets/Finding_Window_Handles">Finding Window Handles (HWND)</a> (Firefox)</dt> - <dd>How to use Windows API calls to find various kinds of Mozilla window handles. Window handles can be used for IPC and Accessibility purposes.</dd> - <dt><a href="/en-US/docs/Accessing_the_Windows_Registry_Using_XPCOM" title="/en-US/docs/Accessing_the_Windows_Registry_Using_XPCOM">Using the Windows Registry with XPCOM</a></dt> - <dd>How to read, write, modify, delete, enumerate, and watch registry keys and values.</dd> -</dl> - -<h2 id="External_links" name="External_links">External links</h2> - -<p>The content at <a class="external" href="http://kb.mozillazine.org/Category:Example_code">MozillaZine Example Code</a> is slowly being moved here, but you can still find useful examples there for now.</p> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html deleted file mode 100644 index e5ab2b6189..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: JS XPCOM -slug: Mozilla/Add-ons/Code_snippets/JS_XPCOM -translation_of: Archive/Add-ons/Code_snippets/JS_XPCOM ---- -<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p> - -<p>这是一些解决XPCOM组件相关的有用的JavaScript代码。</p> - -<h3 id="Contract_IDs" name="Contract_IDs">Contract IDs</h3> - -<p>契约ID是XPCOM对象独一无二的名字。它们用于创建或者获得XPCOM中的对象。</p> - -<h3 id="Interfaces" name="Interfaces">Interfaces</h3> - -<p>Every XPCOM object implements one or more interfaces. An interface is simply a list of constants and methods that can be called on the object, an example is <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile" title="nsIFile is the correct platform-agnostic way to specify a file; you should always use this instead of a string to ensure compatibility.">nsIFile</a></code>. Every XPCOM object must implement the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsISupports</a></code> interface.</p> - -<h3 id="Accessing_XPCOM_components_from_JavaScript" name="Accessing_XPCOM_components_from_JavaScript">Accessing XPCOM components from JavaScript</h3> - -<p>XPCOM objects are either created as new instances (each creation gives you a completely new COM object) or as services (each access gives you the same COM object, often called a singleton). Whether you must create a new instance or access as a service depends on the contract. In order to get an XPCOM object you need to know the contract ID of the object and the interface that you wish to use on it.</p> - -<h4 id="Creating_an_instance_of_a_component" name="Creating_an_instance_of_a_component">Creating an instance of a component</h4> - -<p>The preferred method of creating XPCOM instances is via the <code><a href="/en-US/docs/Components.Constructor">Components.Constructor</a></code> helper. For example,</p> - -<pre class="brush: js">var nsFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath"); - -var file = new nsFile(filePath); -</pre> - -<p>They can also be created and initialized manually:</p> - -<pre class="brush: js">var file = Components.classes["@mozilla.org/file/local;1"] - .createInstance(Components.interfaces.nsIFile); -file.initWithPath(filePath); -</pre> - -<p>This creates a new instance of the object with contract ID <code>@mozilla.org/file/local;1</code> and allows you to call methods from the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile" title="nsIFile is the correct platform-agnostic way to specify a file; you should always use this instead of a string to ensure compatibility.">nsIFile</a></code> interface on it.</p> - -<h4 id="Getting_an_XPCOM_service" name="Getting_an_XPCOM_service">Getting an XPCOM service</h4> - -<pre class="brush: js">var preferences = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); -</pre> - -<p>You can then call any methods in the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsIPrefService</a></code> interface on the preferences object.</p> - -<h4 id="Getting_a_different_interface_for_a_component" name="Getting_a_different_interface_for_a_component">Getting a different interface for a component</h4> - -<p>Some components implement more than one interface. Sometimes JavaScript is clever enough to know all the interfaces available on a component, but in most cases you will have to explicitly check for an interface. With the preferences service from the previous example we can do the following:</p> - -<pre class="brush: js">var preferences = preferences.QueryInterface(Components.interfaces.nsIPrefBranch2); -</pre> - -<p>This allows you to use the methods in the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsIPrefBranch2</a></code> interface.</p> - -<h4 id="Determining_which_interfaces_an_XPCOM_component_supports" name="Determining_which_interfaces_an_XPCOM_component_supports">Determining which interfaces an XPCOM component supports</h4> - -<p>To display a list of all interfaces that an XPCOM component supports, do the following:</p> - -<pre class="brush: js">// |c| is the XPCOM component instance -for each (i in Components.interfaces) { if (c instanceof i) { alert(i); } } -</pre> - -<p>In this context, <code>instanceof</code> is the same as <code>QueryInterface</code> except that it returns false instead of throwing an exception when <code>|c|</code> doesn't support interface <code>|i|</code>. Another difference is that <code>QueryInterface</code> returns an object, where as <code>instanceof</code> returns a <code>boolean</code>.</p> - -<h3 id="XPCOMUtils_-_About_protocol_handler" name="XPCOMUtils_-_About_protocol_handler">XPCOMUtils - About protocol handler</h3> - -<p>{{ Fx_minversion_inline(3) }}This example implements a quick about protocol handler in JS using <a href="/en/XPCOMUtils.jsm" title="en/XPCOMUtils.jsm">XPCOMUtils.jsm</a>.</p> - -<pre class="brush: js">Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -const Cc = Components.classes; -const Ci = Components.interfaces; - -function AboutHandler() {} -AboutHandler.prototype = { - newChannel: function(uri) { - var channel = Services.io.newChannel("chrome://mystuff/content/mystuff.xul", null, null); - channel.originalURI = uri; - return channel; - }, - getURIFlags: function(uri) { - // Do NOT return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT unless - // you make sure to set a non-system principal in newChannel. - return 0; - }, - - classDescription: "About MyStuff Page", - classID: Components.ID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), - contractID: "@mozilla.org/network/protocol/about;1?what=mystuff", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]) -} - -var NSGetModule = XPCOMUtils.generateNSGetModule([AboutHandler]); -} -</pre> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html deleted file mode 100644 index 413e32f59a..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Modules -slug: Mozilla/Add-ons/Code_snippets/Modules -translation_of: Archive/Add-ons/Code_snippets/Modules ---- -<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;"><font><font>{{LegacyAddonsNotice}}</font></font></span></p> - -<p><font><font>一些简单的代码将</font></font><a href="/en/JavaScript_code_modules" title="en / JavaScript代码模块"><font><font>JavaScript模块</font></font></a><font><font>转换为非Mozilla特定的代码(例如,如果移植到浏览器)。</font><font>eval()的使用可能不会被关注,因为它仅在</font></font><code>EXPORTED_SYMBOLS</code><font><font> 数组</font><font>上使用,</font><font>而不依赖于用户输入。</font></font></p> - -<pre class="brush: js"><font><font>函数importModule(thatObj){</font></font><font><font> - thatObj = thatObj || </font><font>窗口;</font></font> -<font><font> - var EXPORTED_SYMBOLS = [</font></font><font><font> - //把符号放在这里</font></font><font><font> - ]。</font></font> -<font><font> - //你的代码在这里...</font></font> -<font><font> - //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)</font></font><font><font> - for(var i = 0; i <EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}</font></font><font><font> -}</font></font> -</pre> - -<p><font><font>或一次性使用模块:</font></font></p> - -<pre class="brush: js"><font><font>(function(thatObj){</font></font><font><font> - thatObj = thatObj || </font><font>窗口;</font></font> -<font><font> - var EXPORTED_SYMBOLS = [</font></font><font><font> - //把符号放在这里</font></font><font><font> - ]。</font></font> -<font><font> - //你的代码在这里...</font></font> -<font><font> - //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)</font></font><font><font> - for(var i = 0; i <EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}</font></font><font><font> -})(); </font><font>//可以在这里放置一个对象参数</font></font></pre> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html deleted file mode 100644 index 364909681f..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: QuerySelector -slug: Mozilla/Add-ons/Code_snippets/QuerySelector -tags: - - $ - - $$ - - querySelector -translation_of: Archive/Add-ons/Code_snippets/QuerySelector ---- -<p> {{ fx_minversion_header(3.5) }}</p> - -<p>沿着其他框架,如jQuery或Prototype, 缩短“querySelector”的名称可以很方便:</p> - -<pre class="brush: js"> HTMLDocument.prototype.$ = function (selector) { - // Only for HTML - return this.querySelector(selector); - }; - $(`div`); - HTMLDocument.prototype.$$ = function (selector) { - // Only for HTML - return this.querySelectorAll(selector); - }; - $$(`div`);</pre> - -<pre class="brush: js">function $ (selector, el) { - if (!el) {el = document;} - return el.querySelector(selector); -} -function $$ (selector, el) { - if (!el) {el = document;} - return el.querySelectorAll(selector); - // Note: the returned object is a NodeList. - // If you'd like to convert it to a Array for convenience, use this instead: - // return Array.prototype.slice.call(el.querySelectorAll(selector)); -} -alert($('#myID').id); -</pre> - -<p>(请注意,在使用火狐浏览器控制台时,上述功能可自动使用.)</p> - -<p> XUL 甚至 XML可以很简单的支持(有以下两种替代方法,添加ChromeWindow.prototype 或者 Window.prototype,访问 this.document.querySelector, 或者根据jQuery 风格的链接,即在每个原型的$()方法中返回的‘this'</p> - -<pre class="brush: js">HTMLDocument.prototype.$ = function (selector) { // 只用于HTML - return this.querySelector(selector); -}; - -Example: - -<h1>Test!</h1> -<script> -HTMLDocument.prototype.$ = function (selector) { - return this.querySelector(selector); -}; -alert(document.$('h1')); // [object HTMLHeadingElement] -</script> -</pre> - -<pre class="brush: js">XULDocument.prototype.$ = function (selector) { // 只用于XUL - return this.querySelector(selector); -}; - -Example: - -<label value="Test!"/> -<script type="text/javascript"><![CDATA[ -XULDocument.prototype.$ = function (selector) { // 只用于XUL - return this.querySelector(selector); -}; - -alert(document.$('label')); // [object XULElement] -]]></script> -</pre> - -<pre class="brush: js">Document.prototype.$ = function (selector) { // 只用于XML - return this.querySelector(selector); -}; -var foo = document.implementation.createDocument('someNS', 'foo', null); // Create an XML document <foo xmlns="someNS"/> -var bar = foo.createElementNS('someNS', 'bar'); // add <bar xmlns="someNS"/> -foo.documentElement.appendChild(bar); -alert(foo.$('bar').nodeName); // gives 'bar' -</pre> - -<pre class="brush: js">Element.prototype.$ = function (selector) { // 可用于HTML,XUL,XML - return this.querySelector(selector); -}; - -HTML 例子: -<h1><a>Test!<a/></h1> -<script> -Element.prototype.$ = function (selector) { - return this.querySelector(selector); -}; -alert(document.getElementsByTagName('h1')[0].$('a').nodeName); // 'A' - -XUL 例子: -<hbox><vbox/></hbox> -<script type="text/javascript"><![CDATA[ -Element.prototype.$ = function (selector) { - return this.querySelector(selector); -}; -var XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; -alert(document.getElementsByTagNameNS(XULNS, 'hbox')[0].$('vbox').nodeName); // vbox -]]></script> - -XML 例子: -<foo xmlns="someNS"><bar/></foo> in document earlier -var foo = document.getElementsByTagNameNS('someNS', 'foo')[0]; -alert(foo.$('bar')); - -</pre> - -<p>注意在XML中, # 'id'选择器将不能体现为'id'属性(因此一个这样名字的属性不一定是XML的ID,尽管他在HTML 和XUL中是这样的), 也不会对 <a href="/en/xml/xml:id" title="en/xml/id">xml:id</a> 起作用.</p> - -<p>然而,它将工作于指向没有无前缀属性选择器 (例如'id',但是不是 xml:id: <a class="external" href="http://www.w3.org/TR/selectors-api/#resolving" rel="freelink">http://www.w3.org/TR/selectors-api/#resolving</a>) (即使 CSS3 支持命名空间属性选择器: <a class="external" href="http://www.w3.org/TR/css3-selectors/#attrnmsp" rel="freelink">http://www.w3.org/TR/css3-selectors/#attrnmsp</a> 以及可能将xml:id 当作 #: <a class="external" href="http://www.w3.org/TR/css3-selectors/#id-selectors" rel="freelink">http://www.w3.org/TR/css3-selectors/#id-selectors</a> ).</p> diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html deleted file mode 100644 index f15f127f61..0000000000 --- a/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: JavaScript timers -slug: Mozilla/Add-ons/Code_snippets/Timers -translation_of: Archive/Add-ons/Code_snippets/Timers ---- -<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p> - -<p> </p> - -<p>JavaScript的代码块通常情况下是顺序执行的。不过有几个JavaScript内置函数(计时器),能够让我们推迟任意指令的执行:</p> - -<ul> - <li>{{domxref("window.setTimeout","setTimeout()")}}</li> - <li>{{domxref("window.setInterval","setInterval()")}}</li> - <li>{{domxref("window.setImmediate","setImmediate()")}}</li> - <li>{{domxref("window.requestAnimationFrame","requestAnimationFrame()")}}</li> -</ul> - -<p>The <code>setTimeout()</code> function is commonly used if you wish to have your function called <em>once</em> after the specified delay. The <code>setInterval()</code> function is commonly used to set a delay for functions that are executed again and again, such as animations. The <code>setImmediate()</code> function can be used instead of the <code>setTimeout(<em>fn</em>, <strong>0</strong>)</code> method to execute heavy operations in IE. The <code>requestAnimationFrame()</code> function tells the browser that you wish to perform an animation and requests that the browser schedule a repaint of the window for the next animation frame.</p> - -<h2 class="Documentation" id="Documentation" name="Documentation">Documentation</h2> - -<dl> - <dt>{{domxref("window.setTimeout","setTimeout()")}}</dt> - <dd>Calls a function or executes a code snippet after specified delay.</dd> - <dt>{{domxref("window.setInterval","setInterval()")}}</dt> - <dd>Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.</dd> - <dt>{{domxref("window.setImmediate","setImmediate()")}}</dt> - <dd>Calls a function immediately after the browser has completed other operations, such as events and display updates.</dd> - <dt>{{domxref("window.clearTimeout","clearTimeout()")}}</dt> - <dd>Clears the delay set by <code>setTimeout()</code>.</dd> - <dt>{{domxref("window.clearInterval","clearInterval()")}}</dt> - <dd>Cancels repeated action which was set up using <code>setInterval()</code>.</dd> - <dt>{{domxref("window.clearImmediate","clearImmediate()")}}</dt> - <dd>Cancels the immediate actions, just like {{domxref("window.clearTimeout","clearTimeout()")}} for {{domxref("window.setTimeout","setTimeout()")}}.</dd> - <dt><a href="/en-US/docs/Web/JavaScript/Timers/Daemons">Using JavaScript timers within animations (Javascript Daemons Management)</a></dt> - <dd>In Computer science a <em>daemon</em> is a task that runs as a background process, rather than being under the direct control of an interactive user. In JavaScript programming language, all <em>daemons</em> are processes created by JavaScript timers or by a {{domxref("Worker")}} instantiation. Here are some code snippets which simplify and abstract the management of daemons.</dd> - <dt>{{domxref("window.requestAnimationFrame","requestAnimationFrame()")}}</dt> - <dd><code>requestAnimationFrame()</code> tells the browser that you wish to perform an animation and requests that the browser schedule a repaint of the window for the next animation frame. The method takes as an argument a callback to be invoked before the repaint.</dd> - <dt>{{domxref("performance.now","performance.now()")}}</dt> - <dd> - <p><code>performance.now()</code> returns a timestamp, measured in milliseconds, accurate to one thousandth of a millisecond. This timestamp is equal to the number of milliseconds since the <code>navigationStart </code>attribute of the <a href="/en-US/docs/Navigation_timing" title="/en-US/docs/Navigation_timing"><code>performance.timing</code></a> interface.</p> - </dd> - <dt><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now"><code>Date.now()</code></a></dt> - <dd><code>Date.now()</code> returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.</dd> - <dt><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers#Timeouts_and_intervals">Using JavaScript timers within workers</a></dt> - <dd>Workers can use timeouts and intervals just like the main thread can. This can be useful, for example, if you want to have your worker thread run code periodically instead of nonstop.</dd> - <dt><a href="/en-US/docs/Web/Guide/Needs_categorization/Functions_available_to_workers">Functions available to workers</a></dt> - <dd>In addition to the standard JavaScript set of functions (such as String, Array, Object, JSON etc), there are a variety of functions available from the DOM to workers. This article provides a list of those.</dd> - <dt><a href="/en-US/docs/Web/HTML/Canvas/Tutorial/Basic_animations">Basic animations</a></dt> - <dd>Since we're using script to control canvas elements it's also very easy to make (interactive) animations. Unfortunately the canvas element was never designed to be used in this way (unlike Flash) so there are limitations.</dd> - <dt><a href="/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm" title="/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm">Timer.jsm</a></dt> - <dd>The <code>Timer.jsm</code> JavaScript code module contains pure-JavaScript implementations of <a href="/en-US/docs/DOM/window.setTimeout" title="/en-US/docs/DOM/window.setTimeout"><code>setTimeout </code></a>and <a href="/en-US/docs/DOM/window.clearTimeout" title="/en-US/docs/DOM/window.clearTimeout"><code>clearTimeout</code></a> that are compatible with the DOM window functions, but that can be used by code that does not have access to a DOM window (for example, <a href="/en-US/docs/Mozilla/JavaScript_code_modules" title="/en-US/docs/Mozilla/JavaScript_code_modules">JavaScript code modules </a>or <a href="/en-US/docs/The_message_manager" title="/en-US/docs/The_message_manager">content frame scripts</a>).</dd> -</dl> - -<h2 id="See_also">See also</h2> - -<ul> - <li><a href="/en-US/docs/Web/API/window.setTimeout#Callback_arguments">Callback arguments polyfill</a></li> - <li><a href="/en-US/docs/Web/API/window.setInterval#A_little_framework">A little <code>setInterval</code> framework</a></li> - <li><a href="/en-US/docs/Web/JavaScript">JavaScript</a>, <a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Workers</a></li> - <li><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Using web workers</a></li> - <li>{{domxref("window.performance")}}</li> - <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date"><code>Date</code></a></li> -</ul> - -<p><embed height="0" id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd" type="application/thunder_download_plugin" width="0"></p> diff --git a/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html b/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html deleted file mode 100644 index 617d86487c..0000000000 --- a/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html +++ /dev/null @@ -1,470 +0,0 @@ ---- -title: Creating Custom Firefox Extensions with the Mozilla Build System -slug: >- - Mozilla/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System -translation_of: >- - Archive/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System ---- -<div class="note"> - <strong>Note:</strong> All instructions in this article apply to the Mozilla 1.8 branch only (i.e. Firefox 1.5). I'll try to keep it up-to-date as the trunk changes, but you certainly should not assume that this will work with the 1.7 branch (i.e. Firefox 1.0) or older.</div> -<p>There is a <a href="/en/Extensions" title="en/Extensions">wealth of material</a> on creating extensions for Firefox. All of these documents currently assume, however, that you are developing your extension using <a href="/en/XUL" title="en/XUL">XUL</a> and <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a> only. For complex extensions, it may be necessary to create components in C++ that provide additional functionality. Reasons why you might want to include C++ components in your extension include:</p> -<p>有大量如何创建扩展的资料, 但是这些文档都假定仅仅使用XUL和Javascript开发扩展. 对于复杂的扩展, 可能需要C++开发相关的功能代码. 下列原因可能使你想要在扩展中包括C++组件(Components):</p> -<ul> - <li>Need for high-performance beyond what can be delivered by JavaScript code.</li> - <li>性能要求高, Javascript达不到要求</li> - <li>Use of third-party libraries written in C or C++.</li> - <li>需要使用第三方C/C++库</li> - <li>Use of Mozilla interfaces that are not exposed via <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> (e.g. <a href="/en/NSPR" title="en/NSPR">NSPR</a>).</li> - <li>使用Mozilla接口,不仅仅是XPCOM提供的接口</li> -</ul> -<p>This article describes how to set up the development environment for a large, complex Firefox extension with any or all of the above-mentioned requirements. The process of garnering this information has been somewhat painful due to the lack of published information on this topic, but has been assisted by the contributions of various members of the Mozilla development community, who have shown extraordinary patience in fielding ignorant newbie questions. I can’t stress enough that I’m far from a Mozilla expert, though I’m getting better. There may be much in this document that is inaccurate, misleading or just plain wrong. In fact, one of my goals in writing this is to fine-tune these instructions until they constitute a definite guide for hardcore hackers who want to extend the Firefox platform. If you’re one of the many people who know more about this than I do, your help in improving this article would be greatly appreciated.</p> -<p>I should also stress that you do <em>not</em> have to build Mozilla or use the Mozilla build system if you want to create C++ components for Mozilla. If you are just looking to create an <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> component or two, this is probably overkill, and you might want to take a look at <a class="external" href="http://www.iosart.com/firefox/xpcom/">this guide</a> instead. On the other hand, if you are an experienced developer or team, and you know that you are going to build a large, complex extension, you would do well to consider the approach described in this article.</p> -<p>One final note: I’ve only tried these techniques inside Firefox, but they’ll probably work more or less unchanged on other Gecko-based platforms like Thunderbird or Seamonkey. If someone can confirm this and/or provide guidelines for what’s different, I’ll update the article to incorporate this information.</p> -<h3 id="Bambi_Meets_Mozilla(小鹿斑比遇见Mozilla)">Bambi Meets Mozilla(小鹿斑比遇见Mozilla)</h3> -<p>None of this is for the faint of heart. In particular, the initial step involves building Mozilla, which is a huge - nay, gargantuan! - project. Many intelligent developers have been driven to the brink of insanity trying to build it for the first time. If you're not an experienced C++ developer, I wouldn’t even bother. Stick to JavaScript.</p> -<p>(小鹿斑比小时候很胆小)其实这些并不适合胆小者. 尤其是, 第一步编译Mozilla, 那是庞大的 -- 非常非常巨大的 -- 项目. 在初次编译Mozilla时, 许多聪明的开发者都快被逼疯了. 如果你不是资深的C++开发者, 就别烦恼了, 继续玩Javascript.</p> -<h4 id="On_Windows_Platforms">On Windows Platforms</h4> -<p>The first time I built Mozilla I used <a href="/En/Developer_Guide/Build_Instructions/Windows_Prerequisites" title="En/Developer_Guide/Build_Instructions/Windows_Prerequisites">this guide</a>. I can’t even remember why anymore, but I got stuck in a number of places, and the whole affair ended up taking far longer than I originally expected. Much furniture was smashed, much hair torn out by the roots. Here’s a <a class="external" href="http://whereswalden.com/mozilla/msvcfree/">comprehensive looking guide</a> that’s gotten good reviews. Follow every step methodically and you’ll probably be alright. Focus on the fact that once you get the build working, it’ll probably work effortlessly from then on. Maybe.</p> -<h4 id="On_Other_Platforms">On Other Platforms</h4> -<p>On other platforms, namely Linux and MacOS, the process is much easier. All the tools for building are available built-in, and therefore all you have to do is run some commands in the terminal. You can find full instructions for almost any OS <a href="/En/Developer_Guide/Build_Instructions" title="En/Developer_Guide/Build_Instructions">here</a>.</p> -<h3 id="Structuring_Your_Project(构造您的项目)">Structuring Your Project(构造您的项目)</h3> -<p>Mozilla includes a number of complex extensions that are integrated into its build process. It has thus been necessary to solve all of the issues involved in creating and registering XPCOM components, building JAR files and manifests, installing the lot into the Firefox <code>extensions/</code> directory and so forth. So it behooves us to piggyback on this infrastructure to build our extension.</p> -<p>First of all, think of a catchy name for your extension and create a directory with that name under the <code>/mozilla/extensions/</code> directory. Use only lowercase letters. You should see a bunch of other directories (<code>inspector/</code>, <code>reporter/</code> and so forth) at the same level in the build tree.</p> -<p>Note that before actually building anything, the Mozilla build system invokes a configuration process that generates the actual makefiles used for the build from makefile templates called <code>Makefile.in</code>. The actual makefiles tend to be very similar or identical to the templates, but the extra flexibility gained from having the makefiles generated dynamically is one of the things that makes the build system so powerful.</p> -<h4 id="Anatomy_of_a_Simple_C_Extension(分析一个简单的C扩展)">Anatomy of a Simple C++ Extension(分析一个简单的C++扩展)</h4> -<p>We assume that you are using C++ to write XPCOM components that can be used either from other C++ components or from JavaScript. The process of creating a component is actually relatively straightforward when the Mozilla build system is used.</p> -<p>In the simplest case, a component will consist of a single main directory with two subdirectories, <code>public/</code> and <code>src/</code>. The main directory and each subdirectory must contain a <code>Makefile.in</code> (from now on I’ll just refer to this file as a makefile although we know that it is actually used to generate the real makefile). This makefile says two things. First of all, it lists the subdirectories that make up the extension, so the build system knows where to look for additional makefiles. Secondly, it instructs the build system to create a new extension, rather than copying the components directly into Firefox’s binary directory. The main advantage of using an extension is that it is easy to package everything up and install it on another machine.</p> -<p>So here’s your basic, plain-vanilla top-level makefile (<code>Makefile.in</code> in the main extension directory):</p> -<pre>DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = myextension - -DIRS = public src - -XPI_NAME = myextension -INSTALL_EXTENSION_ID = myextension@mycompany.com -XPI_PKGNAME = myextension - -DIST_FILES = install.rdf - -include $(topsrcdir)/config/rules.mk -</pre> -<p>A detailed description of the make process, describing the key features of this makefile, can be found <a href="/en/How_Mozilla's_build_system_works" title="en/How_Mozilla's_build_system_works">here</a>. <strong>MODULE</strong> and <strong>XPI_NAME</strong> are both set to the name of your extension; they should be repeated in all project makefiles so that all of the files land in the same place in the XPI staging area (see below). <strong>INSTALL_EXTENSION_ID</strong> is the unique ID of your extension. This can be a GUID, but the format shown above is prettier and, let’s face it, a lot easier to remember. You don’t have to provide an <strong>XPI_PKGNAME</strong>, but if you do an XPI file, suitable for distribution, is automatically created in the root of the XPI staging area (<code>/mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/</code>).</p> -<p>Every extension must include an <code>install.rdf</code> file that tells Firefox how to install it. This file should be located in the main extension directory and look something like this:</p> -<pre><?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:install-manifest"> - <em:id>myextension@mycompany.com</em:id> - <em:version>0.1</em:version> - - <em:targetApplication> - <!-- Firefox --> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>1.0+</em:minVersion> - <em:maxVersion>1.0+</em:maxVersion> - </Description> - </em:targetApplication> - - <!-- front-end metadata --> - <em:name>My First Extension</em:name> - <em:description>Just an example.</em:description> - <em:creator>allpeers.com</em:creator> - <em:homepageURL>http://www.allpeers.com/blog/</em:homepageURL> - </Description> -</RDF> -</pre> -<p>There's a <a href="/en/Install_Manifests" title="en/Install_Manifests">detailed description</a> of the format of the <code>install.rdf</code> file. Use the <strong>DIST_FILES</strong> variable in the makefile to tell <code>make</code> to copy the file into the extension directory and (optional) XPI file.</p> -<h4 id="Public_Interfaces(公共接口)">Public Interfaces(公共接口)</h4> -<p>The <code>public/</code> directory contains any interfaces that need to be accessed by other modules. These can be <a class="external" href="http://www.mozilla.org/scriptable/xpidl/idl-authors-guide/index.html">IDL</a> files describing <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> interfaces, which are used to generate normal C++ header files for inclusion in your source files. They can also be normal C++ header files that are to be used directly by other modules. The easiest way to accomplish the latter is to use inline implementations for all methods so you don’t have any additional linking dependencies. Otherwise you will have to link statically to your module if you use these public headers in other modules. Personally I would discourage this practice (among other things, static linking means the same code gets loaded more than once into memory, and the code won’t be available from JavaScript or other non-C++ languages) and encourage the use of XPCOM wherever possible.</p> -<p>The makefile in the <code>public/</code> directory should follow this model:</p> -<pre>DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = myextension -XPIDL_MODULE = myextension - -XPI_NAME = myextension - -EXPORTS = \ - myHeader.h \ - $(NULL) - -XPIDLSRCS = \ - myIFirstComponent.idl \ - myISecondComponent.idl \ - $(NULL) - -include $(topsrcdir)/config/rules.mk -</pre> -<p><strong>XPIDL_MODULE</strong> is the name of the generated XPT file that contains type information about your <a class="external" href="http://www.mozilla.org/scriptable/xpidl/idl-authors-guide/index.html">IDL</a> interfaces. If you have multiple modules, make absolutely sure that you use a different value for <strong>XPIDL_MODULE</strong> for each one. Otherwise the first module’s XPT file will be overwritten by the second and you’ll get <strong>NS_ERROR_XPC_BAD_IID</strong> errors when you try to access its IDL interfaces from your code. The files under <strong>EXPORTS</strong> are copied directly to the <code>/mozilla/$(MOZ_OBJDIR)/dist/include/myextension/</code> directory and are thus accessible from other modules (the value of <strong>MOZ_OBJDIR</strong> is defined in <code>/mozilla/.mozconfig</code>). XPIDLSRCS are run through the IDL processor, and the generated C++ headers are copied into the same include directory. In addition, an XPT (type library) file is generated and placed in the <code>components/</code> subdirectory of your extension.</p> -<h4 id="Source_Files(源文件)">Source Files(源文件)</h4> -<p>Now it’s time to create the makefile and source files in the <code>src/</code> subdirectory. If you're implementing interfaces that you've described using IDL, the easiest way to do this is to leave the <code>src/</code> directory empty and run <code>make</code> on the <code>public/</code> directory only; this will be explained shortly.</p> -<p>Then open the generated header file for your interface from <code>/mozilla/$(MOZ_OBJDIR)/dist/include/myextension/</code>. It contains stubs for the component .H and .CPP files that you can copy and paste into your implementation files. All you have to do is fill in the implementation stubs in the C++ file and you’re good to go.</p> -<p>Here’s an example of the makefile you need to place into your <code>src</code> directory:</p> -<pre class="eval">DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -IS_COMPONENT = 1 -<a href="/en/MODULE" title="en/MODULE">MODULE</a> = myextension -<a href="/en/LIBRARY_NAME" title="en/LIBRARY_NAME">LIBRARY_NAME</a> = myExtension -<a href="/en/USE_STATIC_LIBS" title="en/USE_STATIC_LIBS">USE_STATIC_LIBS</a> = 1 - -XPI_NAME = myextension - -REQUIRES = xpcom \ - string \ - $(NULL) - -<a href="/en/CPPSRCS" title="en/CPPSRCS">CPPSRCS</a> = \ - myFirstComponent.cpp \ - mySecondComponent.cpp \ - myExtension.cpp \ - $(NULL) - -include $(topsrcdir)/config/rules.mk - -<a href="/en/EXTRA_DSO_LDOPTS" title="en/EXTRA_DSO_LDOPTS">EXTRA_DSO_LDOPTS</a> += \ - $(XPCOM_GLUE_LDOPTS) \ - $(NSPR_LIBS) \ - $(NULL) - -# <span class="highlightred">NOTE: If you are coding against the 1.8.0 branch (not 1.8 branch or trunk), the</span> -# <span class="highlightred">above line won't work, due to linker flag issues.</span> Use the following -# variables instead: -# -# EXTRA_DSO_LDOPTS += \ -# $(MOZ_COMPONENT_LIBS) \ -# $(NULL) -# -# Unfortunately, using MOZ_COMPONENT_LIBS links against xpcom_core, which means -# your components will not work in future versions of Firefox. -</pre> -<p>The <code>REQUIRES</code> section tells <code>make</code> which modules your components uses. This causes the relevant subdirectories of <code>/mozilla/$(MOZ_OBJDIR)/dist/include/</code> to be added to the C++ compiler's include path. If you’re including Mozilla headers and the compiler isn’t finding them, it could well mean that you haven’t listed all of the necessary modules here. <code>CPPSRCS</code> lists the source files that need to be built.</p> -<p>In this example, the first two files contain the implementation of the extension’s two components. The final file, <code>myExtension.cpp</code>, contains the code necessary to register these components, as described in the next section.</p> -<h4 id="Registering_Your_Components(注册组件)">Registering Your Components(注册组件)</h4> -<p>In order to use your components from other C++ modules and JavaScript, you first have to register them. To do this, your extension needs to implement a class that exposes the <code><a href="/en/XPCOM_Interface_Reference/nsIModule" title="en/XPCOM_Interface_Reference/nsIModule">nsIModule</a></code> interface, which has methods for accessing the components defined in a module. Luckily, this can be accomplished through the use of a few simple macros, so you don’t have to concern yourself with the messy details of what’s happening under the hood.</p> -<p>The first step is to define a CID, contract ID and class name for each of your components. Place the following code (adapting the <strong>#defines</strong> accordingly) into the header of each component that you want to be able to instantiate using the component manager:</p> -<pre>// {00000000-0000-0000-0000-000000000000} -#define MYFIRSTCOMPONENT_CID \ - { 0x00000000, 0x0000, 0x0000, \ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } - -#define MYFIRSTCOMPONENT_CONTRACTID "@mycompany.com/myfirst;1" -#define MYFIRSTCOMPONENT_CLASSNAME "My First Component" -</pre> -<p>Obviously you need to fill in the CID with a real GUID. Under Windows, this can be generated using <a class="external" href="http://www.microsoft.com/downloads/details.aspx?familyid=94551F58-484F-4A8C-BB39-ADB270833AFC">guidgen.exe</a>. Unix people can use uuidgen (comes standard with most unixes and Linux distros).</p> -<p>Now create the <code>myExtension.cpp</code> file like so:</p> -<pre>#include "nsXPCOM.h" - -#include "nsIGenericFactory.h" - -/** - * Components to be registered - */ -#include "myFirstComponent.h" -#include "mySecondComponent.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(myFirstComponent) -NS_GENERIC_FACTORY_CONSTRUCTOR(mySecondComponent) - -//---------------------------------------------------------- - -static const nsModuleComponentInfo components[] = -{ - { - MYFIRSTCOMPONENT_CLASSNAME, - MYFIRSTCOMPONENT_CID, - MYFIRSTCOMPONENT_CONTRACTID, - myFirstComponentConstructor - }, - { - MYSECONDCOMPONENT_CLASSNAME, - MYSECONDCOMPONENT_CID, - MYSECONDCOMPONENT_CONTRACTID, - mySecondComponentConstructor - }, -}; - -NS_IMPL_NSGETMODULE(MyExtension, components) -</pre> -<p>The <strong>NS_IMPL_NSGETMODULE</strong> macro creates the appropriate module object providing access to all of the components listed in the <code><a href="/en/NsModuleComponentInfo" title="en/NsModuleComponentInfo">nsModuleComponentInfo</a></code> array.</p> -<h4 id="Building_It(编译扩展)">Building It(编译扩展)</h4> -<p>As mentioned above, you’ll probably want to build your extension immediately after creating your IDL files in order to generate the C++ stubs for your component implementations. I’m assuming that you’ve already built Firefox successfully. If not, return immediately to the beginning of this article and don’t come back til you have a functioning <code>firefox.exe</code>. Do not pass go. Do not collect $200.</p> -<p>Still here? Okay, now we have to modify your <code>.mozconfig</code> (in the <code>/mozilla/</code> root directory) so that your extension is built along with Mozilla. Add the following line at the end of the file:</p> -<pre>ac_add_options --enable-extensions=default,myextension -</pre> -<p>Now launch <code>make</code> from the Mozilla root:</p> -<pre>make -f client.mk build -</pre> -<p>Even if you have an up-to-date Firefox build, you’ll have to wait a while for <code>make</code> to recurse over the entire Mozilla source tree looking for new stuff (on my machine, which is pretty fast, this takes a good 10-15 minutes). Eventually it will reach your extension and generate a bunch of stuff under <code>/mozilla/$(MOZ_OBJDIR)/</code>:</p> -<ul> - <li>Exported header files and generated header files (from IDL) in <code>dist/include/myextension/</code></li> - <li>Static libraries for your modules in <code>dist/lib/</code> (in case other modules want to link statically to your stuff instead of using XPCOM).</li> - <li>XPI file in <code>dist/xpi-stage/myextension.xpi</code>.</li> - <li>Generated makefiles for your projects in <code>extensions/myextension/</code> (remember, we’re under <code>/mozilla/$(MOZ_OBJDIR)/</code>.</li> - <li>Everything else in <code><a class="link-mailto" href="mailto:dist/bin/extensions/myextension@mycompany.com" rel="freelink">dist/bin/extensions/myextension@mycompany.com</a>/</code>.</li> -</ul> -<p>A lot of this stuff won’t get created on this first pass since <code>make</code> will gag when it doesn’t find the source files for your components. Don’t worry about this; all you need are the generated header files that contain the C++ implementation stubs. Go back and flesh out the C++ implementation of your components so that the build can complete next time. Remember that you should never, ever modify any of these generated files. Always modify the files used to generate them and rerun <code>make</code>. There might be exceptions to this rule, but if you’re changing the generated files directly, you’re probably doing something wrong.</p> -<p>The process of walking the entire Mozilla tree takes a long time. If you already have a Mozilla build, you can avoid this by creating a makefile for your extension directly. Go to the root of your $(MOZ_OBJDIR) and (from a bash-compatible shell) enter:</p> -<pre class="eval">../build/autoconf/make-makefile extensions/myextension -</pre> -<p>If your $(MOZ_OBJDIR) is located outside your $(TOPSRCDIR), you'll need to do:</p> -<pre class="eval">$(TOPSRCDIR)/build/autoconf/make-makefile -t $(TOPSRCDIR) extensions/myextension -</pre> -<p>in order for the script to know where your source is (it'll use the extension path you gave it relative to the current dir to figure out where you want your makefiles to go).</p> -<p>This will generate the proper makefile for your extension. Whether you build the whole Mozilla tree or take this shortcut, you can build from now on by going to <code>/mozilla/$(MOZ_OBJDIR)/extensions/myextension/</code> and typing "make" on the command line. It should build your component without bothering with the rest of Mozilla. If everything works out, you’ll see your XPI file in the XPI staging area. You’ll also see the "exploded" version of the XPI (i.e. the unzipped directory structure) underneath <code>/mozilla/$(MOZ_OBJDIR)/dist/bin/extensions</code>. (If something goes wrong, figure out what, fix it and then come back here and add it to this article.)</p> -<p>To make sure that the build really finished, launch Firefox and check that your extension is listed when you select Tools/Extensions. If you are using Firefox as your regular browser (and if you’re not, why not!?), you might be annoyed by the fact that you have to close regular Firefox before running your custom-built version. If so, try setting the <strong>MOZ_NO_REMOTE</strong> environment variable to "1" before running the development version of Firefox. You’ll also need to use a different profile for your development version:</p> -<pre class="eval">firefox -P <em>development</em> -</pre> -<p>Where <em>development</em> is replaced with the name of the extra profile you’ve created. This will let you run both versions of Firefox simultaneously, saving you oodles of time over the course of the build/test cycle.</p> -<h4 id="No_Place_Like_Chrome">No Place Like Chrome</h4> -<p>Yippee-ki-yay! Now you have an extension that does, well, absolutely nothing. It’s time to do something with those groovy components that you’ve implemented and registered. The simplest way to do this is to write some <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a> and <a href="/en/XUL" title="en/XUL">XUL</a> code. At this point, it would be very helpful to have a bit of experience <a href="/en/Extensions" title="en/Extensions">writing "regular" extensions</a> (i.e. without using custom C++ components). If you’ve never done this, I strongly recommend that you think of a cool idea for something simple that you’ve always wanted to tweak in Firefox and write it. Just displaying a new menu item that opens a "Hello, World!" dialog box would be already be a great exercise to get warmed up with.</p> -<p>Assuming you know how to write XUL/JavaScript extensions, you’re aware that the most important stuff goes in the <code>chrome/</code> directory of your extension. Well, the fact that you’re also using C++ components doesn’t change that one whit. So now you need to create the normal <code>content/</code>, <code>locale/</code> and <code>skin/</code> directories in which to place your chrome files. Personally I like placing these directly under the root directory of my module, but I don’t suppose it makes any difference if you prefer putting them under a <code>chrome/</code> subdirectory or whatever. Let freedom reign!</p> -<p>Once you’ve written the necessary chrome files (for instance, an overlay that adds a menu item to instantiate and use one of your components), you need to package them up as part of your extension. This is accomplished through the use of a <a href="/en/JAR_Manifests" title="en/JAR_Manifests">JAR Manifest</a>. For our simple extension example, this file might look something like this:</p> -<pre>myextension.jar: -% content myextension %content/ -% locale myextension en-US %locale/en-US/ -% skin myextension classic/1.0 %skin/classic/ -% overlay chrome://browser/content/browser.xul chrome://myextension/content/MyExtensionOverlay.xul - content/MyExtensionOverlay.js (content/MyExtensionOverlay.js) - content/MyExtensionOverlay.xul (content/MyExtensionOverlay.xul) - locale/en-US/MyExtension.dtd (locale/en-US/MyExtension.dtd) - locale/en-US/MyExtension.properties (locale/en-US/MyExtension.properties) - skin/classic/MyExtension.css (skin/classic/MyExtension.css) -</pre> -<p>Place this code in a file called <code>jar.mn</code> in the root directory of your extension, making sure that the paths in parentheses point to actual files (when interpreted relative to the root directory). You also have to make one small change to the makefile in the same directory, adding the following line:</p> -<pre class="eval">USE_EXTENSION_MANIFEST = 1 -</pre> -<p>This tells <code>make</code> to create a single manifest file called <code>chrome.manifest</code> instead of creating separate manifests with goofy names for each package.</p> -<p>Now launch <code>make</code> again, and you should see a <code>chrome</code> subdirectory appear in your extension (<code>/mozilla/$(MOZ_OBJDIR)<a class="link-mailto" href="mailto:/dist/bin/extensions/myextension@mycompany.com" rel="freelink">/dist/bin/extensions/myextension@mycompany.com</a>/</code>). Note that the <code>chrome</code> directory contains a JAR (i.e. ZIP) file with all the chrome files listed in <code>jar.mn</code> as well as a complete directory structure mirroring that of the JAR file. The directory structure, however, is empty. Why? I don’t know. Don’t worry about this, the files in the JAR are the ones that are actually used.</p> -<h4 id="Keeping_it_Complex">Keeping it Complex</h4> -<p>If you’re developing a really complex extension with lots of <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> components, you’ll probably want to divide your code up into smaller modules.</p> -<h5 id="Kinda_Sorta_Complex_Extensions">Kinda, Sorta Complex Extensions</h5> -<p>For a moderately complex extension, it’s probably enough just to subdivide the code into a single level of modules. Let’s assume that you have a <code>base/</code> module that defines a bunch of basic XPCOM components and an <code>advanced/</code> module that defines some chrome as well as other components that use the basic components. Your complete directory structure will look something like this:</p> -<ul> - <li>myextension - <ul> - <li>base - <ul> - <li>public</li> - <li>src</li> - </ul> - </li> - <li>advanced - <ul> - <li>content</li> - <li>locale - <ul> - <li>en-US</li> - <li>...other locales...</li> - </ul> - </li> - <li>public</li> - <li>skin - <ul> - <li>classic</li> - <li>...other skins...</li> - </ul> - </li> - <li>src</li> - </ul> - </li> - </ul> - </li> -</ul> -<p>Other than that, nothing really changes. The makefiles in the <code>base/</code> and <code>advanced/</code> directories should look more or less like your original root makefile, remembering to change the <strong>DEPTH</strong> variable to account for the fact that they’ve moved a level further away from the Mozilla root. You also need to remove the <strong>DIST_FILES</strong> variable since that’s going to be in the top-level makefile. Every makefile that generates anything should define the <strong>XPI_NAME</strong> variable to make sure generated files go into your extension and not into the global <code>components/</code> directory. In fact, just define this in every makefile to be safe. You can use the same <strong>MODULE</strong> in both <code>base/</code> and <code>advanced/</code> so that all the generated include files go into the same directory, but make sure that you don’t use the same <strong>XPIDL_MODULE</strong> in the two <code>public/</code> directories or one of the component type libraries (i.e. XPT files) will overwrite the other one and all hell will break loose.</p> -<p>Each module must also have a different value for the <strong>LIBRARY_NAME</strong> variable. This is the name of the generated dynamic library, so if we call the libraries "myBase" and "myAdvanced", we’ll end up with <code>myBase.dll</code> and <code>myAdvanced.dll</code> (on Windows, at least). And each of these modules is going to have a separate C++ file for registering components. So there will be two files that look like <code>myExtension.cpp</code> in the original example, say <code>Base.cpp</code> and <code>Advanced.cpp</code>. Finally, each module will obviously have its own <code>jar.mn</code>, though they can reference the same JAR filename and package name if you want all the chrome files to be organized in a single JAR file and package. The only file that really stays put is <code>install.rdf</code>, which still exists once and only once in the extension root directory.</p> -<p>As for the top-level makefile, it will now look like this:</p> -<pre>DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = myextension - -DIRS = base advanced - -XPI_NAME = myextension -INSTALL_EXTENSION_ID = myextension@mycompany.com -XPI_PKGNAME = myextension - -DIST_FILES = install.rdf - -include $(topsrcdir)/config/rules.mk -</pre> -<h5 id="Seriously_Complex_Extensions">Seriously Complex Extensions</h5> -<p>At some point, even a single module may grow to the point where you want to divide it further into submodules. The difference between having separate modules and having a single module with separate submodules is that the submodules all share the same file for registering components (the famous <code>myExtension.cpp</code> file), and when compiled they create a single dynamic library. The decision to split a module into submodules is all about code organization; it doesn’t really affect the final product at all.</p> -<p>To split a module into submodules, first create a subdirectory for each submodule. Then create an additional directory called <code>build/</code>. Each submodule will be configured to create a static library, and the <code>build/</code> directory will pull these libraries together to create a single dynamic component library. Confused? Here’s an example, showing just the <code>advanced/</code> subbranch of the <code>myextension/</code> directory:</p> -<ul> - <li>advanced - <ul> - <li>build</li> - <li>intricate - <ul> - <li>public</li> - <li>src</li> - </ul> - </li> - <li>multifarious - <ul> - <li>public</li> - <li>src</li> - </ul> - </li> - <li>content</li> - <li>locale - <ul> - <li>en-US</li> - <li>...other locales...</li> - </ul> - </li> - <li>skin - <ul> - <li>classic</li> - <li>...other skins...</li> - </ul> - </li> - </ul> - </li> -</ul> -<p>As you can see, we’ve split <code>advanced/</code> into two submodules: <code>intricate/</code> and <code>multifarious/</code>, and we’ve added an additional <code>build/</code> subdirectory. We’ve left the chrome directories directly under <code>advanced/</code>, since they aren’t tied to any specific submodule. This means that <code>jar.mn</code> will stay in the same place.</p> -<p>The <code>intricate/</code> and <code>multifarious/</code> makefiles will look a lot like the original <code>advanced/</code> makefile, but we’ll need to tweak them a bit. As always, we have to adjust the <strong>DEPTH</strong> variable since the makefiles are deeper in the directory structure. And we should change the <strong>LIBRARY_NAME</strong> to indicate that we’re generating a static library for each submodule. By convention the "_s" suffix is used for this purpose. So let’s call them "myIntricate_s" and "myMultifarious_s". Finally, we define the variable <strong>FORCE_STATIC_LIB</strong>, resulting in a makefile that starts something like this:</p> -<pre>DEPTH = ../../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = myextension -LIBRARY_NAME = myIntricate_s -FORCE_STATIC_LIB = 1 -USE_STATIC_LIBS = 1 - -XPI_NAME = myextension - -...more stuff here... -</pre> -<p>The <code>build</code> makefile pulls together the static libraries generated by the submodules and creates a single (dynamic) component library:</p> -<pre>DEPTH = ../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -IS_COMPONENT = 1 -MODULE = myextension -LIBRARY_NAME = myAdvanced -USE_STATIC_LIBS = 1 - -XPI_NAME = myextension - -DEFINES += XPCOM_GLUE - -SHARED_LIBRARY_LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)myIntricate_s.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)myMultifarious_s.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)xpcom.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nspr4.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)plds4.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)plc4.$(LIB_SUFFIX) \ - $(NULL) - -REQUIRES = \ - xpcom \ - string \ - $(NULL) - -CPPSRCS = \ - Advanced.cpp \ - $(NULL) - -include $(topsrcdir)/config/rules.mk - -LOCAL_INCLUDES += \ - -I$(srcdir)/../intricate/src \ - -I$(srcdir)/../multifarious/src \ - $(NULL) -</pre> -<p>The makefile in the <code>advanced/</code> directory should list the <code>intricate/</code>, <code>multifarious/</code> and <code>build/</code> directories in its <strong>DIRS</strong> variable. Make sure that <code>build/</code> comes last since it can’t create the component library until the other makefiles have completed.</p> -<h3 id="Other_Topics">Other Topics</h3> -<h4 id="Adding_Data_Files_to_Your_Extensions">Adding Data Files to Your Extensions</h4> -<p>In some cases, you may wish to include additional files in your extension that don’t belong in the <code>chrome/</code> subdirectory. Examples might be database files or XML schemas. This can be achieved by adding a custom step to your makefile that copies the files from the source tree into the extension’s target directory.</p> -<h5 id="Copying_Data_Files_Into_Target_Directory">Copying Data Files Into Target Directory</h5> -<p>Let’s say that you have some data files containing statistical information that you want to include in your extension and make available to your components. You’ve placed these files, which have the extension .TXT, into a <code>stats/</code> subdirectory under your extension directory in the source tree. The following makefile rule can be used to copy these files into the final target directory of the extension:</p> -<pre>export:: - if test ! -d $(FINAL_TARGET)/stats; then \ - $(NSINSTALL) -D $(FINAL_TARGET)/stats; \ - fi - $(INSTALL) $(srcdir)/*.txt $(FINAL_TARGET)/stats -</pre> -<h5 id="Accessing_Data_Files_From_Components">Accessing Data Files From Components</h5> -<p>The trick to accessing your data files is to figure out where the home directory of your extension is. Rumor has it that at some future date, this will possible through the <code><a href="/en/XPCOM_Interface_Reference/nsIExtensionManager" title="en/XPCOM_Interface_Reference/nsIExtensionManager">nsIExtensionManager</a></code> interface or something similar. In the meantime, there is a simple and reliable hack that can be used to achieve this. In the implementation of any JavaScript XPCOM component, there is a special <strong>__LOCATION__</strong> (two leading and two trailing underscores) symbol that points to the component’s implementation file. So you can write a simple component which deduces the root directory of your extensions by extrapolating from its location.</p> -<p><a class="external" href="http://www.builderau.com.au/program/soa/Creating_XPCOM_components_with_JavaScript/0,39024614,39206503,00.htm">This article</a> explains how to create an XPCOM component in JavaScript. You’ll need an IDL file for an interface that looks something like this:</p> -<pre>interface myILocation : nsISupports -{ - readonly attribute nsIFile locationFile; -}; -</pre> -<p>Place the IDL file in the <code>public/</code> directory of your project or subproject. In the <code>src/</code> directory, place the JavaScript file that implements the component. The component implementation will include the methods for retrieving the path or file for the extension’s home directory:</p> -<pre>myLocation.prototype = -{ - QueryInterface: function(iid) - { - if (iid.equals(nsISupports)) - return this; - if (iid.equals(myILocation)) - return this; - - Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE; - return null; - }, - - get locationFile() - { - return __LOCATION__.parent.parent; - } -} -</pre> -<p>This assumes that the component resides in a subdirectory of the extension directory (by convention, this directory is called <code>components/</code>). The <code>parent</code> property of <strong>__LOCATION__</strong> returns the <code>components/</code>, and the <code>parent</code> of this is the extension directory.</p> -<p>The last step is to modify the makefile of the source directory where you placed your JavaScript file so that it is copied into the appropriate location in the extension:</p> -<pre>export:: - $(INSTALL) $(srcdir)/*.js $(FINAL_TARGET)/components -</pre> -<p>Now you can instantiate an instance of this component and use the <code>locationFile</code> property to get an <code><a href="/en/XPCOM_Interface_Reference/nsIFile" title="en/XPCOM_Interface_Reference/nsIFile">nsIFile</a></code> interface that points to your extension’s home directory.</p> -<h4 id="Using_Third-Party_Libraries">Using Third-Party Libraries</h4> -<p>For more sophisticated extensions, you may want to integrate third-party libraries that provide specialized functionality for database connectivity, image processing, networking and the like. If you want your extension to run on all Firefox platforms, you will need to have the source code for the library in question, so I assume that this is available.</p> -<p>The most convenient approach from the perspective of the development cycle is to create a Mozilla-style makefile for the library. This works well for libraries that have a straightforward make process without extensive configuration. A good example of this is the SQLite library included in the Mozilla build tree at <code>db/sqlite</code>. By adapting the makefile in this way, the library is created as part of the standard Mozilla build process, which eliminates additional build steps. The downside is that you will need to update the modified makefile any time a new version of the library is released.</p> -<p>For libraries that have complex configuration processes, use a non-standard compiler or have other special characteristics, it may be unfeasible to create a Mozilla-compliant makefile. In this case, I would recommend placing the entire library distribution inside the project or subproject that uses it. So if library <code>acmelib</code> is used inside the <code>multifarious/</code> subproject in the above example, it would be placed as a subdirectory underneath that subproject (at the same level as <code>public/</code> and <code>src/</code>).</p> -<p>Of course, this means that you will have to build <code>acmelib</code> manually on all platforms before launching the Mozilla build. But at least you can then refer to include files and import libraries from your component using relative paths.</p> -<h4 id="Building_for_Multiple_Platforms">Building for Multiple Platforms</h4> -<p>TODO</p> -<div class="originaldocinfo"> - <h2 id="Original_Document_Information">Original Document Information</h2> - <ul> - <li>Author: Matthew Gertner - July 26, 2005.</li> - <li>Permission granted to migrate in Jan 2006, including permission to relicense under the CC:By-SA.</li> - <li>Original Source: <a class="external" href="http://www.allpeers.com/blog/creating-complex-firefox-extensions/" rel="freelink">http://www.allpeers.com/blog/creatin...ox-extensions/</a></li> - </ul> -</div> -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html deleted file mode 100644 index b03cc689c9..0000000000 --- a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: 为 Firefox 创建 OpenSearch 插件 -slug: Mozilla/Add-ons/Creating_OpenSearch_plugins_for_Firefox -translation_of: Web/OpenSearch ---- -<p>{{ fx_minversion_header("2") }}</p> -<p><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a> 支持使用 <a class="external" href="http://opensearch.org/">OpenSearch</a> 格式开发搜索引擎插件. 使用 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch 格式</a>开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.</p> -<p>Firefox 也支持不被包括在 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch格式</a> 中的其它的搜索功能,例如搜索建议(search suggestion)以及 <code>SearchForm</code> 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.</p> -<p>OpenSearch 描述文件也能被如在 <a href="#Autodiscovery_of_search_plugins">Autodiscovery of search plugins</a> 中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 <a href="/en/Adding_search_engines_from_web_pages" title="en/Adding_search_engines_from_web_pages">Adding search engines from web pages</a>中所说的进行编程安装.</p> -<h2 id="OpenSearch_描述文件">OpenSearch 描述文件</h2> -<p>遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。</p> -<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?> -<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" - xmlns:moz="http://www.mozilla.org/2006/browser/search/"> - <ShortName><strong>engineName</strong></ShortName> - <Description><strong>engineDescription</strong></Description> - <InputEncoding><strong>inputEncoding</strong></InputEncoding> - <Image width="16" height="16" type="image/x-icon">data:image/x-icon;base64,<strong>imageData</strong></Image> - <Url type="text/html" method="<strong>method</strong>" template="<strong>searchURL</strong>"> - <Param name="<strong>paramName1</strong>" value="<strong>paramValue1</strong>"/> - ... - <Param name="<strong>paramNameN</strong>" value="<strong>paramValueN</strong>"/> - </Url> - <Url type="application/x-suggestions+json" template="<strong>suggestionURL</strong>"/> - <moz:SearchForm><strong>searchFormURL</strong></moz:SearchForm> -</OpenSearchDescription></pre> -<dl> - <dt> - <strong>ShortName</strong></dt> - <dd> - 对搜索引擎的简称</dd> - <dd> - <strong>限制:</strong> 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.</dd> -</dl> -<dl> - <dt> - <strong>Description</strong></dt> - <dd> - 对于搜索引擎的简单描述</dd> - <dd> - <strong>限制:</strong> 描述仅能包含少于1024个字符的纯文本. 名称不能包含HTML标志或其他标志.</dd> -</dl> -<dl> - <dt> - <strong>InputEncoding</strong></dt> - <dd> - 向搜索引擎所输内容的字符编码.例如: <code><InputEncoding>UTF-8</InputEncoding></code>.</dd> -</dl> -<dl> - <dt> - <strong>Image</strong></dt> - <dd> - 使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 <a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme">data: URI scheme</a>. <a class="external" href="http://software.hixie.ch/utilities/cgi/data/data">The data: URI kitchen</a>在这能找到一个能有效地帮助你构建写在此处的数据的工具. - <pre class="eval"><Image height="16" width="16" type="image/x-icon"><a class="external" href="http://example.com/favicon.ico" rel="freelink">http://example.com/favicon.ico</a></Image> - OR -<Image height="16" width="16">data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=</Image> -</pre> - Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.</dd> -</dl> -<dl> - <dt> - <strong>Url</strong></dt> - <dd> - 描述用来实现搜索请求的一个或多个URL. <code>method</code> 属性决定使用 <code>GET</code> 还是 <code>POST</code>请求来获取返回的数据. <code>template</code> 属性指定实现搜索请求的 URL.</dd> - <dd> - <div class="note"> - <strong>注意:</strong> IE7 不支持 <code>POST</code> 请求.</div> - </dd> -</dl> -<dl> - <dd> - 这是两种firefox支持的URL类型:</dd> -</dl> -<ul> - <li><code>type="text/html"</code> 用来指定进行搜索查询的URL.</li> - <li><code>type="application/x-suggestions+json"</code> 用来指定获取搜索建议(search suggestions)的URL.</li> -</ul> -<dl> - <dd> - 这两种URL任何一种你都能使用 <code>{searchTerms}</code>来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_3#OpenSearch_1.1_parameters">OpenSearch 1.1 parameters</a>.</dd> -</dl> -<dl> - <dd> - 对使用搜索建议查询来说, URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 <a href="/en/Supporting_search_suggestions_in_search_plugins" title="en/Supporting_search_suggestions_in_search_plugins">Supporting search suggestions in search plugins</a>.</dd> -</dl> -<p><img alt="Image:SearchSuggestionSample.png" class="internal" src="/@api/deki/files/358/=SearchSuggestionSample.png"></p> -<dl> - <dt> - <strong>Param</strong></dt> - <dd> - 这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数.<code> 你能使用{searchTerms}</code>来指代用户输入的搜索条目.</dd> - <dd> - <div class="note"> - <strong>注意:</strong> IE7不支持此元素.</div> - </dd> -</dl> -<dl> - <dt> - <strong>SearchForm</strong></dt> - <dd> - 跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.</dd> - <dd> - <div class="note"> - <strong>注意:</strong> 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "<code>moz:</code>" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.</div> - </dd> -</dl> -<h2 id="自动搜寻搜索插件">自动搜寻搜索插件</h2> -<p>提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.</p> -<p>要支持自动搜寻 你仅需在 你网页的<code><head></code> 中加上一条:</p> -<pre class="eval"><link rel="search" type="application/opensearchdescription+xml" title="<em>searchTitle</em>" href="<em>pluginURL</em>"> -</pre> -<p>斜体字部分解释如下:</p> -<dl> - <dt> - <strong>searchTitle</strong></dt> - <dd> - 搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.</dd> -</dl> -<dl> - <dt> - <strong>pluginURL</strong></dt> - <dd> - 指向 XML搜索插件的URL, 能让浏览者下载插件.</dd> -</dl> -<p>如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:</p> -<pre class="eval"><link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="<a class="external" href="http://www.mysite.com/mysiteauthor.xml" rel="freelink">http://www.mysite.com/mysiteauthor.xml</a>"> -<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="<a class="external" href="http://www.mysite.com/mysitetitle.xml" rel="freelink">http://www.mysite.com/mysitetitle.xml</a>"> -</pre> -<p>这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.</p> -<h2 id="为_OpenSearch_插件支持自动更新">为 OpenSearch 插件支持自动更新</h2> -<p>{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}</p> -<p>从Firefox 3.5开始, OpenSearch 插件能够自动更新. 要支持这个, 需要包括一个额外的 "<code>application/opensearchdescription+xml</code>"类型<code>Url</code> 元素. <code>rel</code>属性需要设为 "<code>self</code>" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.</p> -<p>例如:</p> -<pre><Url type="application/opensearchdescription+xml" - rel="self" - template="http://www.foo.com/mysearchdescription.xml" /> -</pre> -<div class="note"> - <strong>注意:</strong> <a class="external" href="http://addons.mozilla.org" title="http://addons.mozilla.org/">addons.mozilla.org</a> (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.</div> -<h2 id="排错指南">排错指南</h2> -<p>如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.</p> -<ul> - <li>你的服务器应当运行使用MIME类型为<code>application/opensearchdescription+xml的</code> OpenSearch 插件.</li> - <li>确保你的搜索插件正确地格式化了. 你能通过直接将插件加载入firefox来检查. template URL 中的&符号需要使用 &amp代替;标签需要以斜杠或是相匹配的结束标志结束。</li> - <li><code>xmlns</code>属性是很重要的, 没有了他你会得到 "Firefox could not download the search plugin from: (URL)"错误信息.</li> - <li>注意你必须包含一个 <code>text/html</code> URL — 仅包含 Atom 或 <a href="/en/RSS" title="en/RSS">RSS</a> URL 类型 (有效但firefox不支持)的插件将产生 "could not download the search plugin"错误.</li> - <li>远程获取的收藏夹图标大小不能超过10KB (见 {{ Bug(361923) }}).</li> -</ul> -<p>另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 <em>about:config</em> 设定 '<code>browser.search.log</code>' 为 <code>true</code>. 插件被加载后日志信息将显示在火狐的 <a href="/en/Error_Console" title="en/Error_Console">Error Console</a> 中(Tools->Error Console).</p> -<h2 id="参考资料">参考资料</h2> -<ul> - <li><a class="external" href="http://opensearch.org/">OpenSearch Documentation</a>, <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0">OpenSearch Documentation about the Url and Param element</a></li> - <li>Technorati.com has a <a class="external" href="http://technorati.com/osd.xml">working osd.xml</a></li> - <li>More on Autodiscovery difficulties at bugzilla {{ Bug(340208) }}</li> - <li><a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme"><code>data:</code> URI scheme</a></li> - <li><a class="external" href="http://www.searchplugins.net">searchplugins.net</a> - create OpenSearch plugins for use with Firefox 2. <a class="external" href="http://www.searchplugins.net/pluginlist.aspx">List of generated search plugins</a></li> - <li><a class="external" href="http://keijisaito.info/ready2search/e/">Ready2Search</a> - create OpenSearch plugins. <a class="external" href="http://keijisaito.info/arc/search/en_make_plugin.htm">Customized Search through Ready2Search</a></li> -</ul> -<p>{{ languages( { "es": "es/Creación_de_plugins_OpenSearch_para_Firefox", "de": "de/OpenSearch_Plugin_für_Firefox_erstellen", "ca": "ca/Creació_de_connectors_OpenSearch_per_al_Firefox", "fr": "fr/Création_de_plugins_OpenSearch_pour_Firefox", "ja": "ja/Creating_OpenSearch_plugins_for_Firefox", "pl": "pl/Tworzenie_wtyczek_OpenSearch_dla_Firefoksa", "pt": "pt/Criando_plugins_OpenSearch_para_o_Firefox" } ) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html deleted file mode 100644 index 5c511cc132..0000000000 --- a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: 为 Firefox 创建 OpenSearch 插件 -slug: Mozilla/Add-ons/Creating_OpenSearch_plugins_for_Firefox_clone -tags: - - 定制 - - 搜索 ---- -<p>{{ fx_minversion_header("2") }}</p> - -<p><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a> 支持使用 <a class="external" href="http://opensearch.org/">OpenSearch</a> 格式开发搜索引擎插件. 使用 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch 格式</a>开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.</p> - -<p>Firefox 也支持不被包括在 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch格式</a> 中的其它的搜索功能,例如搜索建议(search suggestion)以及 <code>SearchForm</code> 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.</p> - -<p>OpenSearch 描述文件也能被如在 <a href="#Autodiscovery_of_search_plugins">Autodiscovery of search plugins</a> 中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 <a href="/en/Adding_search_engines_from_web_pages" title="en/Adding_search_engines_from_web_pages">Adding search engines from web pages</a>中所说的进行编程安装.</p> - -<h2 id="OpenSearch_描述文件">OpenSearch 描述文件</h2> - -<p>遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。</p> - -<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?> -<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" - xmlns:moz="http://www.mozilla.org/2006/browser/search/"> - <ShortName><strong>engineName</strong></ShortName> - <Description><strong>engineDescription</strong></Description> - <InputEncoding><strong>inputEncoding</strong></InputEncoding> - <Image width="16" height="16" type="image/x-icon">data:image/x-icon;base64,<strong>imageData</strong></Image> - <Url type="text/html" method="<strong>method</strong>" template="<strong>searchURL</strong>"> - <Param name="<strong>paramName1</strong>" value="<strong>paramValue1</strong>"/> - ... - <Param name="<strong>paramNameN</strong>" value="<strong>paramValueN</strong>"/> - </Url> - <Url type="application/x-suggestions+json" template="<strong>suggestionURL</strong>"/> - <moz:SearchForm><strong>searchFormURL</strong></moz:SearchForm> -</OpenSearchDescription></pre> - -<dl> - <dt><strong>ShortName</strong></dt> - <dd>对搜索引擎的简称</dd> - <dd><strong>限制:</strong> 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.</dd> -</dl> - -<dl> - <dt><strong>Description</strong></dt> - <dd>对于搜索引擎的简单描述</dd> - <dd><strong>限制:</strong> 描述仅能包含少于1024个字符的纯文本. 名称不能包含HTML标志或其他标志.</dd> -</dl> - -<dl> - <dt><strong>InputEncoding</strong></dt> - <dd>向搜索引擎所输内容的字符编码.例如: <code><InputEncoding>UTF-8</InputEncoding></code>.</dd> -</dl> - -<dl> - <dt><strong>Image</strong></dt> - <dd>使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 <a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme">data: URI scheme</a>. <a class="external" href="http://software.hixie.ch/utilities/cgi/data/data">The data: URI kitchen</a>在这能找到一个能有效地帮助你构建写在此处的数据的工具. - <pre class="eval"><Image height="16" width="16" type="image/x-icon"><a class="external" href="http://example.com/favicon.ico" rel="freelink">http://example.com/favicon.ico</a></Image> - OR -<Image height="16" width="16">data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=</Image> -</pre> - Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.</dd> -</dl> - -<dl> - <dt><strong>Url</strong></dt> - <dd>描述用来实现搜索请求的一个或多个URL. <code>method</code> 属性决定使用 <code>GET</code> 还是 <code>POST</code>请求来获取返回的数据. <code>template</code> 属性指定实现搜索请求的 URL.</dd> - <dd> - <div class="note"><strong>注意:</strong> IE7 不支持 <code>POST</code> 请求.</div> - </dd> -</dl> - -<dl> - <dd>这是两种firefox支持的URL类型:</dd> -</dl> - -<ul> - <li><code>type="text/html"</code> 用来指定进行搜索查询的URL.</li> - <li><code>type="application/x-suggestions+json"</code> 用来指定获取搜索建议(search suggestions)的URL.</li> -</ul> - -<dl> - <dd>这两种URL任何一种你都能使用 <code>{searchTerms}</code>来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_3#OpenSearch_1.1_parameters">OpenSearch 1.1 parameters</a>.</dd> -</dl> - -<dl> - <dd>对使用搜索建议查询来说, URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 <a href="/en/Supporting_search_suggestions_in_search_plugins" title="en/Supporting_search_suggestions_in_search_plugins">Supporting search suggestions in search plugins</a>.</dd> -</dl> - -<p><img alt="Image:SearchSuggestionSample.png" class="internal" src="/@api/deki/files/358/=SearchSuggestionSample.png"></p> - -<dl> - <dt><strong>Param</strong></dt> - <dd>这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数.<code> 你能使用{searchTerms}</code>来指代用户输入的搜索条目.</dd> - <dd> - <div class="note"><strong>注意:</strong> IE7不支持此元素.</div> - </dd> -</dl> - -<dl> - <dt><strong>SearchForm</strong></dt> - <dd>跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.</dd> - <dd> - <div class="note"><strong>注意:</strong> 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "<code>moz:</code>" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.</div> - </dd> -</dl> - -<h2 id="自动搜寻搜索插件">自动搜寻搜索插件</h2> - -<p>提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.</p> - -<p>要支持自动搜寻 你仅需在 你网页的<code><head></code> 中加上一条:</p> - -<pre class="eval"><link rel="search" type="application/opensearchdescription+xml" title="<em>searchTitle</em>" href="<em>pluginURL</em>"> -</pre> - -<p>斜体字部分解释如下:</p> - -<dl> - <dt><strong>searchTitle</strong></dt> - <dd>搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.</dd> -</dl> - -<dl> - <dt><strong>pluginURL</strong></dt> - <dd>指向 XML搜索插件的URL, 能让浏览者下载插件.</dd> -</dl> - -<p>如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:</p> - -<pre class="eval"><link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="<a class="external" href="http://www.mysite.com/mysiteauthor.xml" rel="freelink">http://www.mysite.com/mysiteauthor.xml</a>"> -<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="<a class="external" href="http://www.mysite.com/mysitetitle.xml" rel="freelink">http://www.mysite.com/mysitetitle.xml</a>"> -</pre> - -<p>这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.</p> - -<h2 id="为_OpenSearch_插件支持自动更新">为 OpenSearch 插件支持自动更新</h2> - -<p>{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}</p> - -<p>从Firefox 3.5开始, OpenSearch 插件能够自动更新. 要支持这个, 需要包括一个额外的 "<code>application/opensearchdescription+xml</code>"类型<code>Url</code> 元素. <code>rel</code>属性需要设为 "<code>self</code>" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.</p> - -<p>例如:</p> - -<pre><Url type="application/opensearchdescription+xml" - rel="self" - template="http://www.foo.com/mysearchdescription.xml" /> -</pre> - -<div class="note"><strong>注意:</strong> <a class="external" href="http://addons.mozilla.org" title="http://addons.mozilla.org/">addons.mozilla.org</a> (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.</div> - -<h2 id="排错指南">排错指南</h2> - -<p>如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.</p> - -<ul> - <li>你的服务器应当运行使用MIME类型为<code>application/opensearchdescription+xml的</code> OpenSearch 插件.</li> - <li>确保你的搜索插件正确地格式化了. 你能通过直接将插件加载入firefox来检查. template URL 中的&符号需要使用 &amp代替;标签需要以斜杠或是相匹配的结束标志结束。</li> - <li><code>xmlns</code>属性是很重要的, 没有了他你会得到 "Firefox could not download the search plugin from: (URL)"错误信息.</li> - <li>注意你必须包含一个 <code>text/html</code> URL — 仅包含 Atom 或 <a href="/en/RSS" title="en/RSS">RSS</a> URL 类型 (有效但firefox不支持)的插件将产生 "could not download the search plugin"错误.</li> - <li>远程获取的收藏夹图标大小不能超过10KB (见 {{ Bug(361923) }}).</li> -</ul> - -<p>另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 <em>about:config</em> 设定 '<code>browser.search.log</code>' 为 <code>true</code>. 插件被加载后日志信息将显示在火狐的 <a href="/en/Error_Console" title="en/Error_Console">Error Console</a> 中(Tools->Error Console).</p> - -<h2 id="参考资料">参考资料</h2> - -<ul> - <li><a class="external" href="http://opensearch.org/">OpenSearch Documentation</a>, <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0">OpenSearch Documentation about the Url and Param element</a></li> - <li>Technorati.com has a <a class="external" href="http://technorati.com/osd.xml">working osd.xml</a></li> - <li>More on Autodiscovery difficulties at bugzilla {{ Bug(340208) }}</li> - <li><a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme"><code>data:</code> URI scheme</a></li> - <li><a class="external" href="http://www.searchplugins.net">searchplugins.net</a> - create OpenSearch plugins for use with Firefox 2. <a class="external" href="http://www.searchplugins.net/pluginlist.aspx">List of generated search plugins</a></li> - <li><a class="external" href="http://keijisaito.info/ready2search/e/">Ready2Search</a> - create OpenSearch plugins. <a class="external" href="http://keijisaito.info/arc/search/en_make_plugin.htm">Customized Search through Ready2Search</a></li> -</ul> - -<p>{{ languages( { "es": "es/Creación_de_plugins_OpenSearch_para_Firefox", "de": "de/OpenSearch_Plugin_für_Firefox_erstellen", "ca": "ca/Creació_de_connectors_OpenSearch_per_al_Firefox", "fr": "fr/Création_de_plugins_OpenSearch_pour_Firefox", "ja": "ja/Creating_OpenSearch_plugins_for_Firefox", "pl": "pl/Tworzenie_wtyczek_OpenSearch_dla_Firefoksa", "pt": "pt/Criando_plugins_OpenSearch_para_o_Firefox" } ) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html b/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html deleted file mode 100644 index 6b9e091642..0000000000 --- a/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: 扩展的常见问题解答 -slug: Mozilla/Add-ons/Extension_Frequently_Asked_Questions_move -translation_of: Archive/Mozilla/Extension_Frequently_Asked_Questions ---- -<p>这里是关于<a class="internal" href="/cn/%E6%89%A9%E5%B1%95" title="cn/扩展">扩展</a>开发中最常见问题的解答集锦。其中的绝大多数是关于 FireFox 的,但是大部分能够方便的移植到 SeaMonkey,Thunderbird 或其它 Mozilla 应用上。</p> -<p>如果你还不知道怎么开始,可以先看看我们的教程:<a class="internal" href="/cn/%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%89%A9%E5%B1%95" title="Cn/构建一个扩展">构建一个扩展</a>或者 <a class="external" href="http://kb.mozillazine.org/Getting_started_with_extension_development" title="http://kb.mozillazine.org/Getting_started_with_extension_development">MozillaZine 上的新手教程</a>。然后用<a class="external" href="http://ted.mielczarek.org/code/mozilla/extensionwiz/" title="http://ted.mielczarek.org/code/mozilla/extensionwiz/">扩展向导</a>创建一个供开始用的简单扩展。</p> -<p>不要忘记先<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境">设置好扩展的开发环境</a>。</p> -<h2 id="调试">调试</h2> -<p>调试之前先<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境">设置扩展的开发环境</a>。</p> -<p>如果调试的代码很复杂,可能会用到 <a class="internal" href="/cn/venkman" title="cn/Venkman">Venkman</a> JavaScript 调试器。在用 Venkman 调试扩展代码之前需要把 "Debug -> Exclude Browser Files" 选项勾掉。</p> -<h3 id="怎样记录代码中的错误?">怎样记录代码中的错误?</h3> -<p>将<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境"><strong>javascript.options.showInConsole</strong> 设为 <strong>true</strong></a>,这样错误就会被记录在<a class="internal" href="/cn/%E9%94%99%E8%AF%AF%E6%8E%A7%E5%88%B6%E5%8F%B0" title="cn/错误控制台">错误控制台</a>中,使得 bug 容易追踪些。</p> -<h3 id="怎样显示扩展当前状态?">怎样显示扩展当前状态?</h3> -<p>要想显示变量值,调试消息等,可以使用 alert(),dump() ,Components.utils.reportError() 或者控制台服务。当然也可以用 Venkman 调试器。</p> -<h3 id="为什么我的脚本不能正确运行?">为什么我的脚本不能正确运行?</h3> -<p>如果你的脚本不能如预期运行,第一个要检查的是错误控制台(参见#)。</p> -<p>访问尚未加载完毕的 DOM 也常常是错误的来源。这种错误通常是因为初始化代码被放在程序顶层(即所有函数之外)。通过监听 <span style="font-family: Courier New;">load</span> 事件延期执行初始化代码可以解决这个问题(<span style="font-family: Courier New;">load</span> 事件表示窗口已经加载完毕):</p> -<pre class="eval">function exampleBrowserStartup(event) -{ - // 初始化代码 -} -window.addEventListener("load", exampleBrowserStartup, false); -</pre> -<p> </p> -<h3 id="不能访问网页的文档(document)对象">不能访问网页的文档(document)对象</h3> -<p>要从 browser.xul 这个 overlay 中访问当前网页,应当使用 <span style="font-family: Courier New;">content.document </span>而不是 <span style="font-family: Courier New;">document。这是因为 document 表示浏览器窗口自身。更多信息参考 <a class="internal" href="/en/Working_with_windows_in_chrome_code" title="En/Working with windows in chrome code">Working with windows in chrome code</a>。</span></p> -<h3 id="无法在扩展中使用_XMLHttpRequest">无法在扩展中使用 XMLHttpRequest</h3> -<p>使用 XMLHttpRequest 发送接收信息时,一般都需要做跨域(crosss domain)操作。 一般来说跨域很麻烦,但因为在 chrome 窗口内发起请求时,是在安全区域内的,所以请求会被默许。</p> -<p>You need to make sure that you are initializing the cross domain XMLHttpRequest from JavaScript code that is referencing a XUL window. If you try and execute the request in relation to the browser content document, as opposed to the "document" of the XUL window, you will receive a Permission Denied error.</p> -<h3 id="XML_文件是规范的,但是却出现_XML_解析错误!">XML 文件是规范的,但是却出现 XML 解析错误!</h3> -<h3 id="示例代码">示例代码</h3> -<h3 id="得到更多帮助">得到更多帮助</h3> -<p> </p> -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/extension_packaging/index.html b/files/zh-cn/mozilla/add-ons/extension_packaging/index.html deleted file mode 100644 index 8057385c7c..0000000000 --- a/files/zh-cn/mozilla/add-ons/extension_packaging/index.html +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: 扩展打包 -slug: Mozilla/Add-ons/Extension_Packaging -tags: - - Extensions - - Toolkit API -translation_of: Archive/Add-ons/Extension_Packaging ---- -<p> </p> -<p>扩展为一种<a href="cn/Bundles">可安装包</a>的形式,它可以由使用者下载并安装,或者是由外部程序或应用程序提供的预安装包。扩展使用<a href="cn/Bundles">目录结构</a>,此结构提供有chrome,components,和其他文件以扩展XUL程序的功能。</p> -<p>每个扩展必须提供一个<a href="cn/Install.rdf">install.rdf</a>文件,包含关于扩展的元数据,例如唯一的ID,版本,作者,和兼容性信息。</p> -<p>扩展文件和install.rdf准备好之后,有几种方法准备扩展以便安装:将扩展目录ZIP打包为用户可安装的<a href="cn/XPI">XPI</a>(xpinstall)文件,直接将扩展解开到用户程序或设置目录中,或将扩展注册到Windows注册表中。</p> -<h3 id=".E5.88.B6.E4.BD.9C.E6.89.A9.E5.B1.95XPI" name=".E5.88.B6.E4.BD.9C.E6.89.A9.E5.B1.95XPI">制作扩展XPI</h3> -<p>一个<a href="cn/XPI">XPI</a> (XPInstall) 文件就是一个简单的ZIP文件,包括了扩展文件,<a href="cn/Install.rdf">install.rdf</a>文件在ZIP的根目录中。使用者可以从网站上下载或者从本地安装XPI文件,将其打开或拖拽到扩展管理窗口。</p> -<p>XPI文件的MIME类型被Firefox识别为 - <i> - application/x-xpinstall</i> - ,因为大多数HTTP服务器不能够默认设置为将.xpi返回MIME类型。在Apache HTTP服务器上,可以在设置文件或.htaccess中增加以下命令来实现:</p> -<pre class="eval">AddType application/x-xpinstall .xpi -</pre> -<h3 id=".E7.9B.B4.E6.8E.A5.E5.AE.89.E8.A3.85.E6.89.A9.E5.B1.95.E6.96.87.E4.BB.B6" name=".E7.9B.B4.E6.8E.A5.E5.AE.89.E8.A3.85.E6.89.A9.E5.B1.95.E6.96.87.E4.BB.B6">直接安装扩展文件</h3> -<p>如果你知道程序的位置(例如,如果你作为应用程序安装者的角色来安装扩展),你可以直接将扩展文件安装到<appdir>/extensions/<extensionID>中。在下次程序启动的时候扩展管理器会自动找到此扩展。</p> -<p>当使用此方法的时候你必须核实以确保系统允许扩展目录和文件正确设置。否则,扩展管理器在此扩展下不能够正确运行,或者扩展本身不能正确工作。</p> -<h3 id=".E4.BD.BF.E7.94.A8Windows.E6.B3.A8.E5.86.8C.E8.A1.A8.E5.B7.A5.E5.85.B7.E6.B3.A8.E5.86.8C.E6.89.A9.E5.B1.95.E6.89.80.E5.9C.A8.E7.9B.AE.E5.BD.95" name=".E4.BD.BF.E7.94.A8Windows.E6.B3.A8.E5.86.8C.E8.A1.A8.E5.B7.A5.E5.85.B7.E6.B3.A8.E5.86.8C.E6.89.A9.E5.B1.95.E6.89.80.E5.9C.A8.E7.9B.AE.E5.BD.95">使用Windows注册表工具注册扩展所在目录</h3> -<p>外部安装程序(例如Java虚拟机)也许希望将应用程序整合点作为扩展安装,即便是应用程序还没有安装。这可以在Windows中<a href="cn/Adding_Extensions_using_the_Windows_Registry">使用注册表</a>来完成。</p> -<h3 id=".E5.A4.9A.E6.9D.A1.E7.9B.AE.E6.89.A9.E5.B1.95_XPIs" name=".E5.A4.9A.E6.9D.A1.E7.9B.AE.E6.89.A9.E5.B1.95_XPIs">多条目扩展 XPIs</h3> -<p>在有些情况下也许希望用单独的XPI文件安装多个扩展/主题。一种特殊的扩展XPI称为<a href="cn/Multiple_Item_Packaging">多条目包</a>,用来解释如何创建此类型的扩展包。(需要Firefox 1.5/XULRunner 1.8。)</p> -<h3 id="Toolkit_API.E7.9A.84.E5.AE.98.E6.96.B9.E5.8F.82.E8.80.83" name="Toolkit_API.E7.9A.84.E5.AE.98.E6.96.B9.E5.8F.82.E8.80.83"><a href="cn/Toolkit_API">Toolkit API</a>的官方参考</h3> -<p> - </p><ul> - <li><a href="/en/Bundles" title="en/Bundles">Structure of an Installable Bundle</a>: describes the common structure of installable bundles, including extensions, themes, and XULRunner applications</li> - <li><a href="/en/Extension_Packaging" title="en/Extension_Packaging">Extension Packaging</a>: specific information about how to package extensions</li> - <li><a href="/en/Theme_Packaging" title="en/Theme_Packaging">Theme Packaging</a>: specific information about how to package themes</li> - <li><a href="/en/Multiple_Item_Packaging" title="en/Multiple_Item_Packaging">Multiple-item Extension Packaging</a>: specific information about multiple-item extension XPIs</li> - <li><a href="/en/XUL_Application_Packaging" title="en/XUL_Application_Packaging">XUL Application Packaging</a>: specific information about how to package XULRunner applications</li> - <li><a href="/en/Chrome_Registration" title="en/Chrome_Registration">Chrome Registration</a></li> - <li><a href="/en-US/docs/Mozilla/Tech/XUL/Printing">Printing in XUL Apps</a></li> - </ul> diff --git a/files/zh-cn/mozilla/add-ons/install_manifests/index.html b/files/zh-cn/mozilla/add-ons/install_manifests/index.html deleted file mode 100644 index 936ae3fb86..0000000000 --- a/files/zh-cn/mozilla/add-ons/install_manifests/index.html +++ /dev/null @@ -1,363 +0,0 @@ ---- -title: 安装清单 -slug: Mozilla/Add-ons/Install_Manifests -tags: - - bug-840092 - - bug-840092-dup -translation_of: Archive/Add-ons/Install_Manifests ---- -<h2 id="简介">简介</h2> -<p>安装清单是一个附加文件,具有Add-on的XUL程序(例如火狐或者雷鸟),用这个文件来确定即将要安装的add-on的安装信息。他包含了add-on的元数据验证、创建者信息、add-on的详细介绍页面地址、版本号、如何更新、兼容性、等等。</p> -<p>安装清单的格式是 RDF/XML.</p> -<p>这个文件名字必须为 <code>install.rdf</code> 并且必须放在 XPI 文件的根目录。</p> -<h2 id="结构">结构</h2> -<p>安装清单的最基本结构如下:</p> -<div style="overflow: hidden;"> - <pre class="brush:xml;auto-links:false"><?xml version="1.0"?> - -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:install-manifest"> - <!-- properties --> - </Description> -</RDF> -</pre> -</div> -<p>有些属性是是必须的,有些是可选的。有些属性只是简单的字符串啥啥啥的,有些属性会很复杂。</p> -<h2 id="必要的属性">必要的属性</h2> -<p>你的清单必须要包含下面的这些属性,不听话的话,你的add-on是不会安装成功滴。</p> -<h3 id="id">id</h3> -<p>id是一个这样子的东东:</p> -<ul> - <li><a href="/en-US/docs/Generating_GUIDs" title="Generating_GUIDs">GUID</a> (Firefox 1.0)</li> - <li>{{ Fx_minversion_inline(1.5) }}是一个这样结构的字符串:</li> -</ul> -<pre><code class="plain">extensionname@example.org</code></pre> -<p>后面的这个格式更容易生成和操作。火狐1.5已经检测你的id,确保它是属于第一种格式还是其他格式,并且让那些id格式乱七八糟的add-on不会被安装。</p> -<p>例如:</p> -<pre class="brush:xml;auto-links:false"><em:id>extensionname@example.org</em:id> - -<em:id>{daf44bf7-a45e-4450-979c-91cf07434c3d}</em:id></pre> -<h3 id="版本">版本</h3> -<p>一个标志当前add-on版本的字符串。</p> -<p>对于火狐/雷鸟1.0来说,这个格式必须满足这里所说的要求: <a href="/en-US/docs/Extension_Versioning,_Update_and_Compatibility" title="Extension_Versioning,_Update_and_Compatibility">Extension Versioning, Update and Compatibility</a>. 对于火狐/雷鸟1.5, 看这里:<a href="/en-US/docs/Toolkit_version_format" title="Toolkit_version_format">Toolkit version format</a>.</p> -<p>示例:</p> -<pre class="brush:xml"><em:version>2.0</em:version> - -<em:version>1.0.2</em:version> - -<em:version>0.4.1.2005090112</em:version></pre> -<p><strong>Firefox 1.5 / XULRunner 1.8</strong> - add-ons that do not use a valid version format will not be installed. The version format is different from, although backwards-compatible with, 1.0's.</p> -<p><strong>For addons hosted on addons.mozilla.org</strong> - Mozilla's update website may repackage your add-on and correct or reject malformed version strings.</p> -<h3 id="类型">类型</h3> -<p>一个整数代表add-on的类型</p> -<table> - <tbody> - <tr> - <td>2</td> - <td>扩展</td> - </tr> - <tr> - <td>4</td> - <td>主题</td> - </tr> - <tr> - <td>8</td> - <td>地区(译者注:多语言)</td> - </tr> - <tr> - <td>32</td> - <td><a href="/en-US/docs/Multiple_Item_Packaging" title="Multiple_Item_Packaging">多个物品包</a></td> - </tr> - <tr> - <td>64</td> - <td>拼写检测字典</td> - </tr> - </tbody> -</table> -<p>例如:</p> -<pre class="brush:xml"><em:type>2</em:type></pre> -<p>{{ Fx_minversion_inline(1.5) }} This property was added for Firefox 1.5, and is only required for add-on types other than Extensions and Themes.</p> -<p>{{ Fx_minversion_inline(3) }} Firefox 2 and previous supported a value of 16 to represent plug-ins. In Firefox 3 this has been removed.</p> -<h3 id="targetApplication">targetApplication</h3> -<p>An object specifying an application targeted by this add-on. This means that the add-on will work with the application identified by the id property (<code><em:id></code>) specified (for a comprehensive list of application IDs and valid min/maxVersions for them see <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/pages/appversions">Valid application versions for add-on developers</a>), from the minimum version (<code><em:minVersion></code>) up to and including the maximum version (<code><em:maxVersion></code>). These version strings are formatted in the same fashion as the <a href="#version"><code>version</code> property</a> and will be compared to the application version; this allows the extension author to specify which versions of Firefox an extension has been tested with.</p> -<p><code>id</code>, <code>minVersion</code>, and <code>maxVersion</code> are all required.</p> -<div class="note"> - Extensions compatible with Firefox 3.5 should specify a <code>maxVersion</code> of<code> 3.5.*</code>, so that they are automatically compatible with security and stability updates. For Firefox 3.0, a <code>maxVersion</code> of<code> 3.0.*</code> should be used. Extensions compatible only with Firefox or Thunderbird 2 should specify a <code>maxVersion</code> of <code>2.0.0.*</code>.</div> -<p>The Install Manifest must specify at least one of these objects, and may specify more if the add-on targets multiple applications that support the Add-on Manager (e.g. Firefox and Thunderbird)</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--Firefox--> - <em:minVersion>1.5</em:minVersion> - <em:maxVersion>3.0.*</em:maxVersion> - </Description> -</em:targetApplication></pre> -<p>{{ Fx_minversion_inline(3) }} Gecko 1.9 based applications allow you to use the special <code>targetApplication </code>id <code class="plain">toolkit@mozilla.org</code> to say that the add-on is compatible with any toolkit app with a toolkit version matching the <code>minVersion</code> and <code>maxVersion</code>.</p> -<h3 id="name">name</h3> -<p>The name of the add-on; intended for display in the UI.</p> -<p><strong>Examples </strong></p> -<pre class="brush:xml"><em:name>My Extension</em:name></pre> -<h2 id="Optional_Property_Reference">Optional Property Reference</h2> -<p>You may need to supply these properties, depending on the capabilities of your add-on.</p> -<h3 id="bootstrap">bootstrap</h3> -<p>{{ Fx_minversion_inline(4) }} A Boolean value that tells the application whether the extension is boot-strappable. At the moment this only works for add-ons with em:type="2". The default value is <code>false</code>. For more information, see <a href="/en-US/docs/Extensions/Bootstrapped_extensions" title="Extensions/Bootstrapped extensions">Bootstrapped extensions</a>.</p> -<h3 id="unpack">unpack</h3> -<p>{{ Fx_minversion_inline(4) }} A true or false value that tells the application whether the extension requires its files be unpacked into a directory in order to work or whether the extension can be loaded direct from the XPI. In versions before Gecko 2.0 all extensions were unpacked, in Gecko 2.0 and later the default is to not unpack. If an extension includes the following then it must request unpacking:</p> -<ul> - <li>Binary <a href="/en-US/docs/XPCOM" title="XPCOM">XPCOM</a> components</li> - <li><a href="/en-US/docs/Shipping_a_plugin_as_a_Toolkit_bundle" title="Shipping a plugin as a Toolkit bundle">Plugins</a></li> - <li><a href="/en-US/docs/Creating_MozSearch_plugins" title="Creating MozSearch plugins">Search plugins</a></li> - <li>DLLs loaded with <a href="/en-US/docs/Mozilla/js-ctypes" title="js-ctypes">ctypes</a></li> - <li>Dictionaries</li> - <li>Window icons</li> -</ul> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><Description about="urn:mozilla:install-manifest"> - <em:id>extension@mysite.com</em:id> - <em:unpack>true</em:unpack> - ... -</Description></pre> -<h3 id="localized">localized</h3> -<p>{{ Fx_minversion_inline(3) }} Allows you to localize the add-on's name, description, contributors and other metadata. The localized description must specify at least one <code>em:locale</code> which indicates which locales to use this information for.</p> -<p><strong>Examples</strong></p> -<p>This declares a set of add-on metadata to be displayed when the application is running in the de-DE locale.</p> -<pre class="brush:xml"><em:localized> - <Description> - <em:locale>de-DE</em:locale> - <em:name>Tab Sidebar</em:name> - <em:description>Zeigt in einer Sidebar Vorschaubilder der Inhalte aller offenen Tabs an.</em:description> - </Description> -</em:localized></pre> -<p>The following properties which are described elsewhere in this page can be included in the localized property:</p> -<ul> - <li>name</li> - <li>description</li> - <li>creator</li> - <li>homepageURL</li> - <li>developer</li> - <li>translator</li> - <li>contributor</li> -</ul> -<p>More documentation can be found at <a href="/en-US/docs/Localizing_extension_descriptions" title="Localizing_extension_descriptions">Localizing extension descriptions</a>.</p> -<h3 id="description">description</h3> -<p>A short description of the add-on - intended for display in the user interface. This description should fit on one short line of text.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:description>Advanced foo tools.</em:description></pre> -<h3 id="creator">creator</h3> -<p>The name of the creator/principal developer - intended for display in the user interface.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:creator>John Doe</em:creator></pre> -<p>or</p> -<pre class="brush:xml"><em:creator>CoolExtension Team</em:creator></pre> -<h3 id="developer">developer</h3> -<p>{{ Fx_minversion_inline(2) }} The name(s) of co-developers. You may specify more than one of this value to specify multiple developers.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:developer>Jane Doe</em:developer> -<em:developer>Koos van der Merwe</em:developer> -</pre> -<h3 id="translator">translator</h3> -<p>{{ Fx_minversion_inline(2) }} The name(s) of translators. You may specify more than one of this value to specify multiple translators.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:translator>Janez Novak</em:translator> -<em:translator>Kari Nordmann</em:translator> -</pre> -<h3 id="contributor">contributor</h3> -<p>The name(s) of additional contributors. You may specify more than one of this value to specify multiple contributors.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:contributor>John Doe</em:contributor> - -<em:contributor>John Doe</em:contributor> -<em:contributor>Jane Doe</em:contributor> -<em:contributor>Elvis Presley</em:contributor> -</pre> -<h3 id="homepageURL">homepageURL</h3> -<p>A link to the add-on's home page - intended for display in the user interface.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml;auto-links:false"><em:homepageURL>http://www.foo.com/</em:homepageURL> -</pre> -<h3 id="updateURL">updateURL</h3> -<p>A link to a custom Update Manifest file that specifies available updates to the add-on. The format is described below. If enabled, the add-on manager periodically checks with this Manifest file to determine if newer versions are available.</p> -<div class="note"> - <strong>Note:</strong> It is strongly recommended that the <code>updateURL</code> be an HTTPS (secure) link. Non-secure update URLs can be hijacked by a malicious <code>update.rdf</code> file, enabling malware to infiltrate the user's computer. <strong>Alternatively, you could host your extension on </strong><a class="external" href="http://addons.mozilla.org"><strong>AMO</strong></a><strong> and leave out the <code>updateURL</code> completely.</strong> This provides secure updates automatically.</div> -<p>{{ Fx_minversion_inline(3) }} For security reasons, Gecko 1.9 applications <strong>require</strong> that if you specify an <code>updateURL</code>, it must be an https URL, or you must include an <code><a href="#updateKey">updateKey</a></code>.</p> -<p>Your server must send this file as <code>text/rdf</code>, <code>text/xml</code> or <code>application/xml+rdf</code> or the update checker may not work.</p> -<p>The addon manager will substitute the following values into this URL in case you wish to generate the response RDF dynamically, such as using PHP or CGI:</p> -<table> - <tbody> - <tr> - <td><code>%REQ_VERSION%</code></td> - <td>The version of the request. Currently 1</td> - </tr> - <tr> - <td><code>%ITEM_ID%</code></td> - <td>The <code>id</code> of the addon being updated</td> - </tr> - <tr> - <td><code>%ITEM_VERSION%</code></td> - <td>The <code>version</code> of the addon being updated</td> - </tr> - <tr> - <td><code>%ITEM_MAXAPPVERSION%</code></td> - <td>The <code>maxVersion</code> of the <code>targetApplication</code> object corresponding to the current application for the addon being updated.</td> - </tr> - <tr> - <td><code>%ITEM_STATUS%</code></td> - <td>{{ Fx_minversion_inline(2) }} Comma separated list of the add-ons operating status in the application. Contains at the least either <code>userEnabled</code> or <code>userDisabled</code> plus any number of <code>incompatible</code>, <code>blockslisted</code> or <code>needsDependencies</code>.</td> - </tr> - <tr> - <td><code>%APP_ID%</code></td> - <td>The <code>id</code> of the current application</td> - </tr> - <tr> - <td><code>%APP_VERSION%</code></td> - <td>The <code>version</code> of the application to check for updates for</td> - </tr> - <tr> - <td><code>%CURRENT_APP_VERSION%</code></td> - <td>{{ Fx_minversion_inline(3.5) }} The <code>version</code> of the current application</td> - </tr> - <tr> - <td><code>%APP_OS%</code></td> - <td>{{ Fx_minversion_inline(1.5) }} The value of <code><a href="/en-US/docs/OS_TARGET" title="OS_TARGET">OS_TARGET</a></code> from the Firefox build system, identifying the operating system being used.</td> - </tr> - <tr> - <td><code>%APP_ABI%</code></td> - <td>{{ Fx_minversion_inline(1.5) }} The value of the <code><a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">TARGET_XPCOM_ABI</a></code> value from the Firefox build system, identifying the compiler/architecture combination used to compile the current application.</td> - </tr> - <tr> - <td><code>%APP_LOCALE%</code></td> - <td>{{ Fx_minversion_inline(3) }} The current application's locale.</td> - </tr> - <tr> - <td><code>%UPDATE_TYPE%</code></td> - <td>{{ Fx_minversion_inline(4) }} <code>UPDATE_TYPE_COMPATIBILITY(32)</code>, <code>UPDATE_TYPE_NEWVERSION(64)</code></td> - </tr> - <tr> - <td><code>%COMPATIBILITY_MODE%</code></td> - <td>{{ Fx_minversion_inline(10) }} related to <a href="/en-US/docs/Firefox/Updating_add-ons_for_Firefox_10#Compatible_by_default" title="https://developer.mozilla.org/en-US/docs/Firefox/Updating_add-ons_for_Firefox_10#Compatible_by_default">default to compatible</a>, values could be <code>normal</code>, <code>ignore</code> or <code>strict</code>.</td> - </tr> - </tbody> -</table> -<p><strong>Examples</strong></p> -<pre class="brush:xml;auto-links:false"><em:updateURL>http://www.foo.com/update.cgi?id=%ITEM_ID%&amp;version=%ITEM_VERSION%</em:updateURL> -<em:updateURL>http://www.foo.com/extension/windows.rdf</em:updateURL> -</pre> -<p><strong>For add-ons hosted on addons.mozilla.org:</strong> You may not specify an <code>updateURL</code> property. By default, Mozilla applications using the Add-on Manager (such as Firefox and Thunderbird) will send update requests to <code>addons.mozilla.org</code> using the default web service. Every time you upload a new version of your add-on or change its compatibility parameters through the author interface, your update manifest will be generated automatically. Add-ons currently marked as <a class="link-https" href="https://addons.mozilla.org/firefox/pages/experimentalAddons">experimental</a> will not be updated due to security concerns.</p> -<p><strong>Format of the Update Manifest:</strong> The Update Manifest is a RDF/XML datasource. For examples of an update manifest, see <a href="/en-US/docs/Extension_Versioning,_Update_and_Compatibility#Update_RDF_Format" title="Extension_Versioning,_Update_and_Compatibility#Update_RDF_Format">Extension Versioning, Update and Compatibility</a> and <a href="/en-US/docs/Enabling_Extension_Updates_(external)" title="Enabling_Extension_Updates_(external)">Enabling Extension Updates (external)</a>.</p> -<h3 id="updateKey">updateKey</h3> -<div> - {{ Gecko_minversion_header(1.9) }} {{ Fx_minversion_header(3) }}</div> -<p>To ensure the security of update rdf data that is retrieved over plain http you must use a digital signature to verify the contents of the data. In order to do so you must include the public part of the cryptographic key in an updateKey entry in the install.rdf of the add-on. This can be generated using the <a href="/en-US/docs/McCoy" title="McCoy">McCoy</a> tool. Any line breaks and whitespace as part of this entry are ignored.</p> -<pre class="brush:xml"><em:updateKey>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj - Zc9EDI5OCJS8R3FIObJ9ZHJK1TXeaE7JWqt9WUmBWTEFvwS+FI9vWu8058N9CHhD - NyeP6i4LuUYjTURnn7Yw/IgzyIJ2oKsYa32RuxAyteqAWqPT/J63wBixIeCxmysf - awB/zH4KaPiY3vnrzQIDAQAB</em:updateKey> -</pre> -<h3 id="optionsURL">optionsURL</h3> -<p>The <code>chrome://</code> URL of the extension's options dialog box. This is only useful to extensions. If this property is specified, when the extension is selected in the Extensions list, the Options button is enabled and will show this.</p> -<pre class="brush:xml"><em:optionsURL>chrome://myext/content/options.xul</em:optionsURL></pre> -<p>{{ gecko_minversion_note("7", "In Firefox 7 you can also simply include your options XUL as a file named <code>options.xul</code>, in the base directory of the add-on.") }}</p> -<p>{{ h3_gecko_minversion("optionsType", 7) }}</p> -<p>The type of user-interface used for displaying the options. Accepted values are:</p> -<table style=""> - <tbody> - <tr> - <td>1</td> - <td>Opens optionsURL in a dialog box</td> - </tr> - <tr> - <td>2</td> - <td><a href="/en-US/docs/Extensions/Inline_Options" title="Extensions/Inline Options">Options are displayed inside the Add-on Manager</a></td> - </tr> - <tr> - <td>3</td> - <td>Opens optionsURL in a new tab (if the application supports that), or a dialog box</td> - </tr> - </tbody> -</table> -<p>optionsType defaults to 1 if there is an optionsURL included in install.rdf or 2 if there is no optionsURL and the file <code>options.xul</code> exists in the root of the add-on.</p> -<pre class="brush:xml"><em:optionsType>2</em:optionsType> -</pre> -<h3 id="aboutURL">aboutURL</h3> -<p>The<code> chrome://</code> URL of the extension's about dialog box. This is only useful to extensions. If this property is specified, when the extension is selected in the Extensions list, the About... link in the extension's context menu will show this dialog, rather than the default.</p> -<div class="geckoVersionNote"> - <p>{{ gecko_callout_heading("2.0") }}</p> - <p>The dialog receives the <code>Addon</code> object representing your add-on as a parameter.</p> -</div> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:aboutURL><a class="external" rel="freelink">chrome://myext/content/about.xul</a></em:aboutURL> -</pre> -<h3 id="iconURL">iconURL</h3> -<p>A <code>chrome://</code> URL to an icon to display in the add-ons list. The icon will be displayed at 32x32 in Firefox 3.6 and lower. In Firefox 4.0 and later the icon can be up to 48x48 pixels in size. If this property is not specified, a default icon is used.</p> -<pre class="brush:xml"><em:iconURL><a class="external" rel="freelink">chrome://myext/skin/icon.png</a></em:iconURL> -</pre> -<div class="note"> - <strong>Note:</strong> For the above example to work you will also have to add a <code>skin package</code> line to your <code>chrome.manifest</code> file. See <a href="/en-US/docs/Chrome_Registration#skin" title="Chrome_Registration#skin">Chrome Registration#skin</a>. Alternatively you can place your icon in the directory specified in your <code>content package</code> line.</div> -<p>{{ gecko_minversion_note("1.9.2", "Starting in Gecko 1.9.2 (Firefox 3.6), you can also simply include your icon, named <code>icon.png</code>, in the base directory of the add-on. This allows your add-on's icon to be displayed even when the add-on is disabled, or if the manifest is missing an <code>iconURL</code> entry.") }}</p> -<p>{{ h3_gecko_minversion("icon64URL", "2.0") }}</p> -<p>A <code>chrome://</code> URL to a 64x64 pixel icon to display in the add-on's details view . If this property is not specified, the smaller icon above will be used.</p> -<pre class="brush:xml"><em:icon64URL><a class="external" rel="freelink">chrome://myext/skin/icon64.png</a></em:icon64URL> -</pre> -<div class="note"> - <strong>Note:</strong> For the above example to work you will also have to add a <code>skin package</code> line to your <code>chrome.manifest</code> file. See <a href="/en-US/docs/Chrome_Registration#skin" title="Chrome_Registration#skin">Chrome Registration#skin</a>. Alternatively you can place your icon in the directory specified in your <code>content package</code> line.</div> -<p>{{ h3_gecko_minversion("targetPlatform", "1.8") }}</p> -<p>A string specifying a platform that the add-on supports. It contains either the value of <code><a href="/en-US/docs/OS_TARGET" title="OS_TARGET">OS_TARGET</a></code> alone or combined with <code><a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">TARGET_XPCOM_ABI</a></code>, separated by an underscore (_).</p> -<p>You can specify multiple <code>targetPlatform</code> properties per manifest. If any value matches the application's build parameters, it will be installed; if not, the user will get an appropriate error message.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:targetPlatform>WINNT_x86-msvc</em:targetPlatform> - -<em:targetPlatform>Linux</em:targetPlatform> - -<em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform> - -<em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform></pre> -<p>Usually, you would use only the OS part for themes or for extensions that are not fully cross-platform. For extensions including binary (compiled) components, you should never use the OS alone, but include the <a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">ABI (s)</a> that you compiled the components with. If you want to include multiple versions of the components, you should also use <a href="/en-US/docs/Bundles#Platform-specific_Subdirectories" title="Bundles#Platform-specific_Subdirectories">Platform-specific Subdirectories</a>.</p> -<p><strong>Notes</strong></p> -<ul> - <li>In the same manifest file, you could even mix values with and without ABI. If a value for the application's OS is encountered that requires any specific ABI, the ABI is considered important for that OS and the application will refuse to install the add-on if it does not find a matching OS/ABI combination. This means that if all of the above examples would occur in one manifest, the add-on will install on any Linux build of the application, regardless of its ABI, but not on a Windows Cygwin build.</li> - <li>There may be builds of Firefox and Thunderbird which do not "know" their ABI (most likely ports to rare platforms, or non-official builds). These builds will refuse to install any addon that requires a specific ABI for their platform.</li> -</ul> -<p>This property was added for Firefox/Thunderbird 1.5. Previous versions of these applications will ignore the restrictions and install the add-on regardless of the platform.</p> -<p>{{ h3_gecko_minversion("strictCompatibility", "10.0") }}</p> -<p>A Boolean value indicating if the add-on should be enabled when the version of the application is greater than its max version. By default, the value of this property is <code>false</code> meaning that the compatibility checking will not be performed against the max version.</p> -<pre class="brush:xml"><em:strictCompatibility>true</em:strictCompatibility></pre> -<p>Usually, there is no need to restrict the compatibility: not all new releases will break your extension and, if it is hosted on AMO, you'll get notice several weeks in advance if a potential risk has been detected. Moreover, an extension being disabled, even for a short period, leads to a bad experience for the user. About the only time you should need to set this if your add-on does things that are likely to be broken by Firefox updates. You <strong>do not</strong> need to set this flag if your add-on has a binary component, since add-ons with binary components are always subject to strict compatibility checking (because binary components need to be rebuilt for every major application release anyway).</p> -<div class="note"> - <strong>Note:</strong> If you want to restore the old behavior of strict compatibility checking of all add-ons, regardless of the value of this setting in their manifests, you can set the <code>extensions.strictCompatibility</code> preference to <code>true</code>.</div> -<div class="geckoVersionNote" style=""> - <p class="note">{{ gecko_callout_heading("11.0") }}</p> - <p class="note">Starting in Gecko 11.0 {{ geckoRelease("11.0") }}, applications such as Firefox will assume add-ons that have not been updated in a very long time are no longer compatible by default.</p> -</div> -<h2 id="Obsolete_Property_Reference">Obsolete Property Reference</h2> -<p>These properties were required in older versions of the Add-on Manager, but have been replaced with newer and better mechanisms.</p> -<h3 id="file">file</h3> -<p><strong>Firefox 1.0</strong> This property pointed to a chrome <code>.jar</code> file that contains chrome packages that require registration with the Chrome Registry.</p> -<p>The <code><em:file></code> property has a complex object value. The uri of the value is <code>urn:mozilla:extension:file:jarFile.jar</code> where <code>jarFile.jar</code> is the name of the jar file that contains the chrome package's files. This could also be the name of a directory that contains the chrome package's files, un-jarred (e.g. <code>urn:mozilla:extension:file:directory</code>). In either case, the referenced chrome package file(s) must be placed in the <code>chrome</code> subdirectory of the XPI's top level.</p> -<p>This object has a <code>package</code> property (with a path within the jar file or directory that leads to the location where the <code>contents.rdf</code> file responsible for registering that package is located), a <code>locale</code> property (ditto, but to register the locale) and a <code>skin</code> property (ditto, but to register the theme material).</p> -<p>In extensions for Firefox 1.5, this property is no longer necessary: the <code><a href="/en-US/docs/Chrome_Registration" title="Chrome_Registration">chrome.manifest</a></code> at the top level of the XPI is used to locate chrome to register. If there is no chrome.manifest, this property is still read by the Add-on Manager and a chrome.manifest is generated from old-style contents.rdf.</p> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:file> - <Description about="urn:mozilla:extension:file:myext.jar"> - <em:package>content/myext/</em:package> - <em:locale>locale/en-US/myext/</em:locale> - <em:skin>skin/classic/myext/<em:skin> - </Description> -</em:file> -</pre> -<p>An Install Manifest may specify multiple <code>file</code> properties, one for each jar file or subdirectory that contains chrome to register.</p> -<h3 id="hidden">hidden</h3> -<p><strong>Firefox 1.0</strong><strong> - 3.5</strong> A boolean value that when <code>true</code> makes the add-on not show up in the add-ons list, provided the add-on is installed in a {{ Anch("restricted access area") }} (so it does not work for add-ons installed in the profile). This is for bundling integration hooks to larger applications where having an entry in the Extensions list does not make sense.</p> -<div class="note"> - <strong>Note:</strong> This property is no longer supported under Gecko 1.9.2 (Firefox 3.6) or later, to prevent extensions from being installed in such a way that the user might not be able to tell they're installed.</div> -<p><strong>Examples</strong></p> -<pre class="brush:xml"><em:hidden>true</em:hidden> -</pre> -<h3 id="requires">requires</h3> -<p><strong>Firefox 2.0 - 3.6.x</strong>. Other versions will ignore the restrictions and install the add-on regardless of the requirements.</p> -<p>See <a class="link-https" href="https://groups.google.com/forum/#!topic/mozilla.dev.platform/u9QT2ZucV-c" title="https://groups.google.com/forum/#!topic/mozilla.dev.platform/u9QT2ZucV-c">Replacement for install.rdf property "requires"</a> discussion for rationale behind removing this feature and the suggested workaround.</p> -<p><code><em:requires</code>> has a similar syntax to the <code><em:targetApplication></code> tag (i.e. you must specify <code><em:id></code>, <code><em:minVersion></code>, <code><em:maxVersion></code> when using it). If the add-on specified by the <code><em:id></code> tag is not installed or has an incompatible version, the extension manager will disable your extension and show the message "Requires additional items". You can add as many <code><em:requires></code> tags as you like. Your extension will be disabled if any of the specified requirements fail. It is not possible to add dependencies that are specific to a <code><em:targetApplication></code>. See <a href="https://wiki.mozilla.org/Extension_Dependencies" title="https://wiki.mozilla.org/Extension_Dependencies">Extension Dependencies</a> for more details.</p> -<h2 id="Glossary">Glossary</h2> -<h2 id="restricted_access_area">restricted access area</h2> -<p>A <em>restricted access area</em> is an install location that could be restricted on a restricted-access account, regardless of whether or not the location is restricted with the current user privileges (see {{ Source("toolkit/mozapps/extensions/public/nsIExtensionManager.idl#80", "nsIInstallLocation::restricted") }}). Currently, the <code>($APPDIR)/extensions</code> folder and the registry install location under <code>HKEY_LOCAL_MACHINE</code> (see <a href="/en-US/docs/Adding_Extensions_using_the_Windows_Registry" title="Adding_Extensions_using_the_Windows_Registry">Adding Extensions using the Windows Registry</a> for details) are restricted.</p> -<p>The <code>($PROFILE)/extensions</code> and <code>HKEY_CURRENT_USER</code> install locations, on the other hand, are not restricted.</p> diff --git a/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html b/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html deleted file mode 100644 index 9200ccb0f6..0000000000 --- a/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: 旧式附件组件 -slug: Mozilla/Add-ons/Legacy_add_ons -translation_of: Archive/Add-ons/Legacy_add_ons ---- -<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p> - -<p>本节包含附件组件开发的旧式技术文档链接,包括:</p> - -<ul> - <li><a href="/zh-CN/docs/Mozilla/Add-ons/SDK">附件组件 SDK</a></li> - <li><a href="/zh-CN/docs/Mozilla/Add-ons/Legacy_Firefox_for_Android">Firefox for Android旧式扩展</a></li> - <li>早期技术 - <ul> - <li><a href="/zh-CN/docs/Mozilla/Add-ons/Bootstrapped_extensions">Bootstrapped 扩展</a></li> - <li><a href="/zh-CN/docs/Mozilla/Add-ons/Overlay_Extensions">Overlay 扩展</a></li> - </ul> - </li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html b/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html deleted file mode 100644 index 6504a2ef16..0000000000 --- a/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Overlay扩展 -slug: Mozilla/Add-ons/Overlay_Extensions -tags: - - Add-ons - - Extensions - - Landing - - NeedsTranslation - - TopicStub -translation_of: Archive/Add-ons/Overlay_Extensions ---- -<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p> - -<p>本页面为那些基于 Gecko 的应用开发扩展插件的开发者们提供了可用的参考文献链接。</p> - -<ul> - <li>XUL 覆盖指定的接口</li> - <li>对应用与内容的之间交互的特定代码提供了可用的APIs, 比如 <a href="/zh-CN/docs/XUL/tabbrowser">页签浏览</a> 和<a href="/zh-CN/docs/Mozilla/JavaScript_code_modules">JavaScript模组</a>。</li> -</ul> - -<p>唯一可行的方法是开发扩展在 Gecko 2.0 发布之前. 但是现在有两种可以选择的技术:免重启扩展和基于 SDK 的扩展插件. 这些特定的 JavaScript APIs 仍旧可以被这些较新的技术使用。</p> - -<p>Prior to Firefox 4, and the Gecko 2 engine that powers it, this was the only way to develop extensions. This methodology has largely been superseded by <a href="/en-US/docs/Extensions/Bootstrapped_extensions">restartless extensions</a>, and the <a href="/en-US/Add-ons/SDK">Add-on SDK</a>, which is built on top of them. The privileged JavaScript APIs described here can still be used in these newer types of add-ons.</p> - -<h2 id="XUL_学校">XUL 学校</h2> - -<p><a href="/zh-CN/Add-ons/Overlay_Extensions/XUL_School">XUL 学校</a> 是一个综合性的拓展开发指南,主要针对 Firefox 的扩展开发,但是绝大多数可应用于其他基于 Gecko 的应用。</p> - -<h2 id="更多资源">更多资源</h2> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/en-US/Mozilla/Add-ons/Setting_up_extension_development_environment">设置环境</a></dt> - <dd>设置扩展开发需要的应用.</dd> - <dt><a href="/en-US/docs/XUL">XUL</a></dt> - <dd>相关的指南介绍XUL 扩展的接口.</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Code_snippets">代码片段</a></dt> - <dd>提供了很多的简单示例代码片段.</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Installing_extensions">安装扩展</a></dt> - <dd>如何通过把扩展的文件拷贝进应用的安装目录来安装扩展.</dd> - <dt><a href="/en-US/Add-ons/Overlay_extensions/Firefox_addons_developer_guide">Firefox 插件的开发者指南</a></dt> - <dd>开发扩展的指南.</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/en-US/docs/Mozilla/JavaScript_code_modules">JavaScript 模块代码</a></dt> - <dd>适用于扩展开发者的 JavaScript 模块。</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Inline_Options">扩展偏好</a></dt> - <dd>如何在你的扩展出现在附加组件管理界面的时候指定偏好设置。</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Extension_Frequently_Asked_Questions">常见问题</a></dt> - <dd>常见的扩展开发中的错误。</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Extension_Packaging">扩展打包</a></dt> - <dd>看看扩展是如何被打包和安装的。</dd> - <dt><a href="/en-US/Mozilla/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System">Firefox 的二进制扩展</a></dt> - <dd>为 Firefox 创建二进制扩展。</dd> -</dl> -</div> -</div> diff --git a/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html b/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html deleted file mode 100644 index d6a6f7515b..0000000000 --- a/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: 扩展中的性能最佳实践 -slug: Mozilla/Add-ons/Performance_best_practices_in_extensions -translation_of: Archive/Add-ons/Performance_best_practices_in_extensions ---- -<p>Firefox 的一个巨大优势就是可扩展性非常强。扩展组件几乎可以做任何事情。但这也带来了一个劣势: 扩展组件如果写的不好,将会大大的影响浏览器性能,包括 firefox 的整体体验。 本文则提供了一些最佳实践方式,他们不仅能够提升你的组件的性能和速度,也会对 firefox 带来同样的影响。</p> -<h2 id="提升启动性能">提升启动性能</h2> -<p>Extensions are loaded and run whenever a new browser window opens. That means every time a window opens, your extension can have an impact on how long it takes the user to see the content they're trying to view. There are several things you can do to reduce the amount of time your extension delays the appearance of the user's desired content.</p> -<h3 id="只在需要的时候装载需要的东西">只在需要的时候装载需要的东西</h3> -<p>Don't load things during startup that are only needed if the user clicks a button, or if a given preference is enabled when it's not. If your extension has features that only work when the user has logged into a service, don't load the resources for those features until the user actually logs in.</p> -<h3 id="使用_JavaScript_code_modules">使用 JavaScript code modules</h3> -<p>You can create your own <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Using" title="/en-US/docs/Mozilla/JavaScript_code_modules/Using">JavaScript code modules</a> incorporating sets of features that are only needed under specific circumstances. This makes it easy to load chunks of your extension on the fly as needed, instead of loading everything all at once.</p> -<p>This has an advantage over XPCOM modules, which are always loaded when your extension starts up.</p> -<p>Of course, for extremely simple extensions it may not make sense to modularize your code.</p> -<h3 id="Defer_everything_that_you_can">Defer everything that you can</h3> -<p>Most extensions have a load event listener in the main overlay that runs their startup functions. Do as little as possible here. The browser window is blocked while your add-on's load handler runs, so the more it does, the slower Firefox will appear to the user.</p> -<p>If there is <em>anything</em> that can be done even a fraction of a second later, you can use an {{ interface("nsITimer") }} or the {{ domxref("window.setTimeout()") }} method to schedule that work for later. Even a short delay can have a big impact.</p> -<h2 id="通用性能提示">通用性能提示</h2> -<h3 id="避免产生内存泄漏">避免产生内存泄漏</h3> -<p>Memory leaks require the garbage collector and the cycle collector to work harder, which can significantly degrade performance.</p> -<p>Zombie compartments are a particular kind of memory leak that you can detect with minimal effort. See the<a href="/en/Zombie_compartments" title="en/Zombie_compartments"> </a><a href="/en/Zombie_compartments" title="en/Zombie_compartments">Zombie compartments page</a>, especially the <a href="/en/Zombie_compartments#Proactive_checking_of_add-ons" title="en/Zombie_compartments#Proactive_checking_of_add-ons">Proactive checking of add-ons</a> section.</p> -<p>See <a href="/en/Extensions/Common_causes_of_memory_leaks_in_extensions" title="en/Extensions/Common_causes_of_zombie_compartments_in_extensions">Common causes of memory leaks in extensions</a> for ways to avoid zombie compartments and other kinds of leaks.</p> -<p>As well as looking for these specific kinds of leaks, it's worth exercising your extension's functionality and checking the contents of about:memory for any excessive memory usage. For example, <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=719601" title="https://bugzilla.mozilla.org/show_bug.cgi?id=719601">bug 719601</a> featured a "System Principal" JavaScript compartment containing 100s of MBs of memory, which is <em>much</em> larger than usual.</p> -<h3 id="Use_JavaScript_Modules">Use JavaScript Modules</h3> -<p>JavaScript modules are just like any other JavaScript, with the exception that they are singletons and Firefox can cache the compiled code for faster use the next time the browser is started. Any time your add-on loads JavaScript from an {{ HTMLElement("script") }} element you should consider using a JavaScript Module instead. For more on how JavaScript modules work, see the <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Using" title="/en-US/docs/Mozilla/JavaScript_code_modules/Using">Using JavaScript Code Modules page</a>.</p> -<h3 id="Avoid_Writing_Slow_CSS">Avoid Writing Slow CSS</h3> -<ul> - <li>Read the <a href="/en/CSS/Writing_Efficient_CSS" title="en/CSS/Writing_Efficient_CSS">"writing efficient CSS"</a> guide.</li> - <li>Remember that any selector in your rule which might match many different nodes is a source of inefficiency during either selector matching or dynamic update processing. This is especially bad for the latter if the selector can dynamically start or stop matching. Avoid unqualified ":hover" like the plague.</li> -</ul> -<h3 id="Avoid_DOM_mutation_event_listeners">Avoid DOM mutation event listeners</h3> -<p>Adding DOM mutation listeners to a document disables most DOM modification optimizations and <a class="external" href="http://groups.google.com/group/mozilla.dev.platform/browse_thread/thread/2f42f1d75bb906fb?pli=1">profoundly degrades the performance</a> of further DOM modifications to that document. Moreover, removing the listeners does not reverse the damage. For these reasons, the following events should be avoided wherever possible: <code>DOMAttrModified</code>, <code>DOMAttributeNameChanged</code>, <code>DOMCharacterDataModified</code>, <code>DOMElementNameChanged</code>, <code>DOMNodeInserted</code>, <code>DOMNodeInsertedIntoDocument</code>, <code>DOMNodeRemoved</code>, <code>DOMNodeRemovedFromDocument</code>, <code>DOMSubtreeModified</code></p> -<p>For more on these events and their deprecation, see <a href="/en-US/docs/Web/Guide/DOM/Events/Mutation_events" title="en-US/docs/Web/Guide/DOM/Events/Mutation_events">Mutation events</a>. Use <a href="/en-US/docs/Web/API/MutationObserver" title="en-US/docs/Web/API/MutationObserver">Mutation Observers</a> instead if possible.</p> -<h3 id="延迟加载服务_services">延迟加载服务 services</h3> -<p>The <a href="/en/JavaScript_code_modules/XPCOMUtils.jsm#Methods" title="en/JavaScript_code_modules/XPCOMUtils.jsm#Methods">XPCOMUtils JavaScript module</a> provides two methods for lazily loading things:</p> -<ul> - <li><code>defineLazyGetter()</code> defines a function on a specified object that acts as a getter which will be created the first time it's used. <a class="external" href="http://mxr.mozilla.org/mozilla-central/search?string=defineLazyGetter">See examples</a>.</li> - <li><code>defineLazyServiceGetter()</code> defines a function on a specified object which acts as a getter for a service. The service isn't obtained until the first time it's used. {{ LXRSearch("ident", "string", "defineLazyServiceGetter", "Look through the source") }} for examples.</li> -</ul> -<p>As of Firefox 4.0, many common services are already cached for you in <a href="/en/JavaScript_code_modules/Services.jsm" title="en/JavaScript_code_modules/Services.jsm">Services.jsm</a>.</p> -<h3 id="Reduce_file_IO">Reduce file I/O</h3> -<p>TODO: Give examples below, link to code, bugs, docs.</p> -<ul> - <li>If you're targeting Firefox 3.6 and earlier, or if you're specifying <code>em:unpack</code> then use chrome JARs!</li> - <li>Combine CSS</li> - <li>Combine pref files</li> - <li>Combine interfaces into a single .idl to reduce xpt files</li> - <li>Combine toolbar icons in a single file.</li> -</ul> -<h3 id="Use_the_right_compression_level_for_JAR_and_XPI_files">Use the right compression level for JAR and XPI files</h3> -<p>Reading data from compressed archives costs time. The higher the compression level of the archive, the higher also the performance cost of reading the data from it. So any JAR files in your extension should always be packed with compression level 0 (no compression) for better performance. It may seem counter-intuitive, but doing this will increase the JAR file size and actually <em>decrease</em> the XPI file size as it allows for compression between files inside the JAR to be done when compressing the XPI (essentially a poor-man's <a class="external" href="http://en.wikipedia.org/wiki/Solid_archive" title="http://en.wikipedia.org/wiki/Solid_archive">solid archive</a> effect).</p> -<p>If your extension doesn't specify <code>em:unpack</code> then its XPI file will not be unpacked in Firefox 4 and used directly instead. This makes choosing a low compression level preferable; we recommend using compression level 1. It will increase the download size only a small amount, even compared to maximum compression.</p> -<h3 id="使用异步_IO">使用异步 I/O</h3> -<p>This cannot be stressed enough: never do synchronous I/O on the GUI thread.</p> -<ul> - <li>Never use synchronous XMLHttpRequests (XHR). Use asynchronous requests instead and show a throbber image or message in case you need the user to wait.</li> - <li><a href="/en/JavaScript_code_modules/NetUtil.jsm" title="en/JavaScript_code_modules/NetUtil.jsm">NetUtils.jsm</a> provides helpers for asynchronous reading and copying of files.</li> - <li>Never access a SQLite database synchronously. Use the <a href="/en/Storage#Asynchronously" title="en/Storage#Asynchronously">asynchronous API</a> instead.</li> -</ul> -<h3 id="Unnecessary_onreadystatechange_in_XHR">Unnecessary onreadystatechange in XHR</h3> -<p><code>addEventListener</code>(load/error) and/or xhr.onload/.onerror are usually sufficient for most uses and will only be called once, contrary to <code>onreadystatechange</code>. When using XHR in websites people tend to use <code>onreadystatechange</code> (for compatiblity reasons). Often it is enough to just load the resource or handle errors. load/error event listener are far less often called than <code>onreadystatechange</code>, i.e. only once, and you don't need to check <code>readyState</code> or figure out if it is an error or not. Only use <code>onreadystatechange</code> if you want to process the response while it is still arriving.</p> -<h3 id="Removing_Event_Listeners">Removing Event Listeners</h3> -<p>Remove event listener if they are not needed any more. It is better to actually remove event listener instead of just having some flag to check if the listener is active which is checked every time when an event is propagated. Abandon schemes like: <code>function onMouseOver(evt) { if (is_active) { /* doSomeThing */ } }</code> Also, remove "fire-once" listeners again:</p> -<pre class="brush: js"> function init() { - var largeArray; - addEventListener('load', function onLoad() { - removeEventListener('load', onLoad, true); - largeArray.forEach(); - }, true); -</pre> -<p>Else a lot of closure stuff might be still referenced (<code>largeArray</code> in this example). And the listener will sit idle in some internal table.</p> -<h3 id="Populate_menus_as_needed">Populate menus as needed</h3> -<p>Populate "context" menus (page, tabs, tools) as needed and keep computation to a minimum (UI responsiveness). There is no need to populate the context menu every time something changes. It is enough to populate it once the user actually needs it. Add a listener to the "popupshowing" event and compute there.</p> -<h3 id="Avoid_mouse_movement_events">Avoid mouse movement events</h3> -<p>Avoid mouse movement events (enter/over/exit) or at least keep computation to a minimum. Mouse movement events, especially the <code>mouseover</code> event, usually happen at high frequency. Best would be to only store the new information and compute "stuff" once the user actually requests it (e.g. in a <code>popupshowing</code> event). Also don't forget to remove the event listeners when no longer needed (see above).</p> -<h3 id="Avoid_polling">Avoid polling</h3> -<p>Use {{ interface("nsIObserverService") }} functionality instead. Everybody is free to post "custom" notifications via {{ interface("nsIObserverService") }}, but few extensions actually use this. However, a lot of other services also provide observer functionality, such as nsIPrefBranch2.</p> -<h3 id="aPNGaGIF_inappropriate_in_a_lot_of_cases">aPNG/aGIF inappropriate in a lot of cases</h3> -<p>Animations require a lot of time to set up, as a lot of images are decoded (the frames). Animated images may have their cached representations evicted quite often, causing the frames of your animated images to be reloaded lots of times, not just once. {{ interface("nsITree") }} / {{ XULElem("tree") }} seems to be extra special in this regard, as it doesn't seem to cache animations at all under certain circumstances.</p> -<h3 id="base64md5sha1_implementations">base64/md5/sha1 implementations</h3> -<p>Do not ship your own base64/md5/sha1 implementations. Regarding base64 there are the built-in <code>atob</code>/<code>btoa</code> functions that do the job just well and are available in overlay script as well as in in JavaScript modules and components. Hashes can be computed using {{ interface("nsICryptoHash") }}, which accepts either a string or an {{ interface("nsIInputStream") }}.</p> -<h3 id="Image_sprites">Image sprites</h3> -<p>You may combine multiple images into one (sprites). See {{ cssxref("-moz-image-region") }}. Most XUL widgets that are used to display some image (incl. {{ XULElem("button") }} and {{ XULElem("toolbarbutton") }}) allow to use {{ cssxref("list-style-image") }}. Avoid the <code>imagesrc</code>/<code>src</code> attributes to define images where possible.</p> -<h3 id="Consider_using_Chrome_Workers">Consider using Chrome Workers</h3> -<p>You can use a {{ domxref("ChromeWorker") }} to execute long running tasks or do data processing.</p> -<h2 id="参考">参考</h2> -<ul> - <li><a href="/en/Performance/Measuring_add-on_startup_performance" title="en/Measuring Add-on Startup Performance">Measuring Add-on Startup Performance</a></li> - <li><a class="external" href="http://blog.mozilla.com/addons/2010/06/14/improve-extension-startup-performance/" title="http://blog.mozilla.com/addons/2010/06/14/improve-extension-startup-performance/">How to Improve Extension Startup Performance</a></li> - <li><a href="/en-US/docs/Performance">General information about measuring and improving performance in Mozilla code</a></li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/plugins/index.html b/files/zh-cn/mozilla/add-ons/plugins/index.html deleted file mode 100644 index f35791a3bf..0000000000 --- a/files/zh-cn/mozilla/add-ons/plugins/index.html +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Plugins -slug: Mozilla/Add-ons/Plugins -tags: - - Add-ons - - NPAPI - - NeedsTranslation - - Plugins - - TopicStub -translation_of: Archive/Plugins ---- -<div class="blockIndicator warning"> -<p><strong>Important</strong>: Since <a href="/en-US/docs/Mozilla/Firefox/Releases/52">Firefox 52</a>, all plugin support except Flash has been dropped (see <span><a href="https://www.fxsitecompat.com/en-CA/docs/2016/plug-in-support-has-been-dropped-other-than-flash/">Plug-in support has been dropped other than Flash</a> for more details</span>). Flash usage is also set to be phased out in the future.</p> -</div> - -<div class="blockIndicator note"> -<p><strong>Note</strong>: Plugins are now a legacy technology. They are not available on most mobile devices. Mozilla encourages website developers to avoid using plugins wherever possible and use standard Web APIs instead. If there are plugin features which are not available in the web platform, we encourage developers to post their use cases to mozilla.dev.platform project list, so that Mozilla can prioritize web platform work to make those use cases possible.</p> -</div> - -<p>For more information about plugin roadmap, see <a href="/en-US/docs/Plugins">non-archived plugin information</a>.</p> - -<p>Plugins are shared libraries that users can install to display content that the browser can't display natively. For example, the Adobe Reader plugin lets the user open PDF files directly inside the browser, and the QuickTime and RealPlayer plugins are used to play special format videos in a web page.</p> - -<p>Plugins are written using <strong>NPAPI</strong>, the cross-browser API for plugins. The main source of documentation for NPAPI is the <a href="/en/Gecko_Plugin_API_Reference" title="en/Gecko_Plugin_API_Reference">Gecko Plugin API Reference</a>. To make your plugin scriptable from web pages, use <a href="/en/Gecko_Plugin_API_Reference/Scripting_plugins" title="en/Gecko_Plugin_API_Reference/Scripting_plugins">npruntime</a>.</p> - -<p>Plugins can be written completely from scratch using C APIs (usually in C or C++) or they may be built on a plugin framework such as <a class="external" href="http://www.firebreath.org" title="http://www.firebreath.org/">Firebreath</a>, <a class="external" href="http://www.juce.com/" title="http://www.rawmaterialsoftware.com/juce.php">JUCE</a>, or <a class="external" href="http://doc.qt.nokia.com/solutions/4/qtbrowserplugin/developingplugins.html" title="http://doc.qt.nokia.com/solutions/4/qtbrowserplugin/developingplugins.html">QtBrowserPlugin</a>. There are also some code generation tools that may be helpful. More information about these tools can be found on the <a href="/en/Plugins/External_resources_for_plugin_creation" title="en/Plugins/External resources for plugin creation">External Resources</a> page.</p> - -<p>Plugins are different from <a href="/en/Extensions" title="en/Extensions">extensions</a>, which modify or enhance the functionality of the browser itself. Plugins are also different from <a href="/en/Creating_OpenSearch_plugins_for_Firefox" title="en/Creating_OpenSearch_plugins_for_Firefox">search plugins</a>, which plug additional search engines in the search bar.</p> - -<hr> -<div class="topicpage-table"> -<div class="section"> -<dl> - <dt><a href="/en/Gecko_Plugin_API_Reference" title="en/Gecko_Plugin_API_Reference">Gecko Plugin API Reference</a> (NPAPI)</dt> - <dd>This reference describes the application programming interfaces for NPAPI plugins and provides information about how to use these interfaces.</dd> - <dt><a href="/en-US/docs/Site_Author_Guide_for_Click-To-Activate_Plugins">Site Author Guide For Click-To-Activate Plugins</a></dt> - <dd>These guidelines will help website authors use plugins when they are blocked by default with the Firefox click-to-activate feature.</dd> -</dl> - -<dl> - <dt><a href="/en/Gecko_Plugin_API_Reference/Scripting_plugins" title="en/Gecko_Plugin_API_Reference/Scripting_plugins">Scripting plugins</a> (npruntime)</dt> - <dd>This reference describes the new cross-browser NPAPI extensions that let plugins be scriptable and also let them access the script objects in the browser.</dd> -</dl> - -<dl> - <dt><a href="/en/Shipping_a_plugin_as_a_Toolkit_bundle" title="en/Shipping_a_plugin_as_a_Toolkit_bundle">Shipping a plugin as a Toolkit bundle</a></dt> - <dd>Plugins can be shipped as a Toolkit <a href="/en/Bundles" title="Bundles">bundle</a>, allowing a user to easily install, uninstall and manage their personal plugins.</dd> -</dl> - -<dl> - <dt><a class="internal" href="/En/Supporting_private_browsing_in_plugins" title="en/Supporting private browsing in plugins">Supporting private browsing in plugins</a></dt> - <dd>Firefox 3.5 introduced support for private browsing; learn how to make your plugin respect the user's privacy wishes.</dd> - <dt><a href="/en/Plugins/Multi-Process_Plugin_Architecture" title="en/Plugins/Multi-Process Plugin Architecture">Multi-Process Plugin Architecture</a></dt> - <dd>How Firefox loads plugins into a separate process. Firefox 3.6.4 introduced out-of-process plugins which execute in a separate process so that a crashing plugin does not crash the browser.</dd> - <dt><a href="/en/Plugins/Logging" title="en/Plugins/Logging">Logging and Debugging for Multi-Process Plugins</a></dt> - <dd>How to create a plugin log to aid in debugging problems with multi-process plugins.</dd> -</dl> -</div> - -<div class="section"> -<dl> - <dt><a class="internal" href="/En/Writing_a_plugin_for_Mac_OS_X" title="en/Writing a plugin for Mac OS X">Writing a plugin for Mac OS X</a></dt> - <dd>Learn how to write a plugin for Mac OS X; a template Xcode project is provided.</dd> -</dl> - -<dl> - <dt><a href="/en/Monitoring_plugins" title="en/Monitoring_plugins">Monitoring Plugins</a></dt> - <dd>Use an observer service notification to monitor the amount of time spent executing calls in plugins. This can be useful when trying to determine if a plug-in is consuming too many resources.</dd> -</dl> - -<dl> - <dt><a href="/en/Scripting_Plugins/Adobe_Flash" title="en/Scripting_Plugins/Macromedia_Flash">Scripting Plugins: Macromedia Flash</a></dt> - <dd>This article explains how JavaScript can be used to access methods from within the Flash plugin, as well as how a feature called FSCommands can be used to access JavaScript functions from within the Flash animation.</dd> -</dl> - -<dl> - <dt><a href="/en/Gecko_Plugin_API_Reference/Plug-in_Development_Overview" title="en/Plugins/The_First_Install_Problem">Plugins: The First Install Problem</a></dt> - <dd>The First Install Problem is the name given to the conditions arising when a plugin or embeddable software installs itself on a system first, before any other Gecko-based browser.</dd> -</dl> - -<dl> - <dt><a href="/en/Plugins/Samples_and_Test_Cases" title="en/Plugins/Samples_and_Test_Cases">Plugins: Samples and Test Cases</a></dt> - <dd>NPAPI plugin samples and test cases.</dd> - <dt><a href="/en/Plugins/External_resources_for_plugin_creation" title="https://developer.mozilla.org/en/Plugins/External_resources_for_plugin_creation">External Resources for Plugin Creation</a></dt> - <dd>External projects, frameworks, and blog posts that may be useful.</dd> -</dl> - -<dl> - <dt><a href="/en/XEmbed_Extension_for_Mozilla_Plugins" title="en/XEmbed_Extension_for_Mozilla_Plugins">XEmbed Extension for Mozilla Plugins</a></dt> - <dd>Recent versions of Mozilla on *nix-based systems include an extension for writing plugins that use XEmbed instead of using the old Xt-based main loop that most plugins have been using since the Netscape 3.x days.</dd> -</dl> -</div> -</div> - -<hr> -<p><span class="comment">Categories</span></p> - -<p><span class="comment">Interwiki Language Links</span></p> - -<div class="blockIndicator communitybox" dir="ltr"> -<div class="column-container"> -<h2 id="Join_the_plugin_development_community">Join the plugin development community</h2> - -<div class="column-half"> -<div class="communitysubhead">Choose your preferred method for joining the discussion:</div> - -<ul class="communitymailinglist"> - <li><a href="https://lists.mozilla.org/listinfo/dev-tech-plugins">Mailing list</a></li> - <li><a href="http://groups.google.com/group/mozilla.dev.tech.plugins">Newsgroup</a></li> - <li><a href="http://groups.google.com/group/mozilla.dev.tech.plugins/feeds">RSS feed</a></li> -</ul> -</div> - -<div class="column-half"> </div> -</div> -</div> diff --git a/files/zh-cn/mozilla/add-ons/plugins/reference/index.html b/files/zh-cn/mozilla/add-ons/plugins/reference/index.html deleted file mode 100644 index fcb2ba7232..0000000000 --- a/files/zh-cn/mozilla/add-ons/plugins/reference/index.html +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: NPAPI plugin reference -slug: Mozilla/Add-ons/Plugins/Reference -tags: - - Deprecated - - Landing - - NPAPI - - NeedsTranslation - - Plugins - - Reference - - TopicStub -translation_of: Archive/Plugins/Reference ---- -<p>{{deprecated_header}}</p> -<p>The articles below describe each of the APIs related to NPAPI plugins.</p> -<p>{{LandingPageListSubpages}}</p> diff --git a/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html b/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html deleted file mode 100644 index 4d0ac34085..0000000000 --- a/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Samples and Test Cases -slug: Mozilla/Add-ons/Plugins/Samples_and_Test_Cases -translation_of: Archive/Plugins/Samples_and_Test_Cases ---- -<h2 id="NPAPI_Plugin_Samples">NPAPI Plugin Samples</h2> -<p>Collections of NPAPI plugin samples can be found in the Seamonkey source code at <a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/samples/" title="http://mxr.mozilla.org/seamonkey/source/modules/plugin/samples/">/modules/plugin/sdk/samples</a>.</p> -<p>The samples may not build any more on all platforms. There are plans to clean up the sample plugin situation - better organization, updated build systems, get them building on all platforms. However, even if one cannot build the samples they can still be very valuable as code references.</p> -<p>There is a <a href="/en/Compiling_The_npruntime_Sample_Plugin_in_Visual_Studio" title="en/Compiling_The_npruntime_Sample_Plugin_in_Visual_Studio">guide to compiling the npruntime sample in Visual Studio</a>.</p> -<p>In addition to those samples, there are 2 more plugins in the tree that might be helpful.</p> -<ul> - <li><a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/tools/spy/">Spy</a></li> - <li><a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/tools/tester/">Tester</a></li> -</ul> -<h2 id="NPAPI_Plugin_Test_Cases">NPAPI Plugin Test Cases</h2> -<ul> - <li>mozilla.org QA <a class="external" href="http://www.mozilla.org/quality/browser/front-end/testcases/plugins/">Plugins testcases</a></li> - <li>mozilla.org QA <a class="external" href="http://www.mozilla.org/quality/browser/front-end/testcases/oji/">OJI testcases</a></li> - <li><a class="external" href="http://www.mozilla.org/projects/plugins/plugins_testing_checklist.html">Plugins Verification Testing Checklist</a> (including <a class="external" href="http://www.mozilla.org/quality/smoketests/">SmokeTesting</a>)</li> -</ul> -<p>{{ languages( { "de": "de/Plugins/Beispiele_und_Testfälle" } ) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html b/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html deleted file mode 100644 index 30aae2d422..0000000000 --- a/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Shipping a plugin as an extension -slug: Mozilla/Add-ons/Plugins/Shipping_a_plugin_as_a_Toolkit_bundle -tags: - - Extensions - - Plugins -translation_of: Archive/Plugins/Shipping_a_plugin_as_a_Toolkit_bundle ---- -<p>One of the new features that is available in Firefox 1.5 is the ability to place browser plug-ins in a Firefox extension.</p> -<p>Historically, most people have chosen to use an install.js script to install a plug-in. When this method is used, you can choose to either place the plug-in into the plugins directory, or place it into your own directory and modify the Windows registry to let Firefox know where to find the plug-in. The downside to this method is that once the plug-in is installed, it might be difficult for users to upgrade, uninstall, or disable the plug-in. As of Firefox 3 (and any Gecko 1.9 based application) the use of install.js scripts is no longer possible and plugins must either be shipped as an executable installer or as an extension as described here.</p> -<h2 id="Bundle_structure" name="Bundle_structure">Bundle structure</h2> -<p><a href="cn/Bundles">Toolkit bundles</a> can be used for all add-ons including extensions, themes and plugins. Plugin packages should only need to package a small set of files in the follow structure in the xpi file:</p> -<pre>install.rdf -plugins/ - pluginlib.dll - plugintypes.xpt -</pre> -<p>The install.rdf file contains an <a href="#Install_Manifest">install manifest</a> that describes the plugin to the user. The library and scripting interfaces are held in the <tt>plugins</tt> directory.</p> -<h3 id="Platform-specific_files" name="Platform-specific_files">Platform-specific files</h3> -<p>It is possible to package multiple plugin libraries for different operating systems into a single xpi bundle. In the xpi you can use the following structure:</p> -<pre>platform/ - Linux_x86-gcc3/ - plugins/ - libplugin.so - Darwin_ppc-gcc3/ - plugins/ - libplugin.dylib -</pre> -<p>More specific information can be found in the <a href="cn/Bundles#Platform-specific_Subdirectories">platform-specific subdirectories</a> documentation.</p> -<h2 id="Install_Manifest" name="Install_Manifest">Install Manifest</h2> -<p>The <a href="cn/Install.rdf">install manifest</a> describes the plugin to the user. For a plugin the manifest only needs to be very simple:</p> -<pre><RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:install-manifest"> - <em:id>mypluginid@myplugin.com</em:id> - <em:name>My Plugin</em:name> - <em:version>1.0</em:version> - <em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> - <em:minVersion>1.5</em:minVersion> - <em:maxVersion>3.0.*</em:maxVersion> - </Description> - </em:targetApplication> - </Description> -</RDF> -</pre> -<p>This contains 4 required pieces of information.</p> -<ol> - <li>Every add-on must have a unique id. This can be in a guid form but the simpler email form is preferred now. You should aim to use a domain-name that you own and then your own unique short-name for the plugin before the @.</li> - <li>The plugin must have a name to identify the plugin to the user in the list of add-ons.</li> - <li>The version is fairly self-descriptive, it must be a <a href="cn/Toolkit_version_format">toolkit version format</a>.</li> - <li>The target application block says which versions of an application the plugin is compatible with. It includes the application ID and the minimum and maximum version of the application that the plugin works with. There can be multiple targetApplication blocks listed.</li> -</ol> -<h2 id="Providing_updates" name="Providing_updates">Providing updates</h2> -<p>When plugins are packaged in this way they can make use of the built in add-on update system. This allows a remote update file to be read periodically and an updated version of the plugin offered to the user or to mark the plugin as compatible with a wider range of applications.</p> -<p>This is performed by including an <a href="cn/Install.rdf#updateURL">updateURL</a> in the install manifest. This should point to an <a href="cn/Extension_Versioning%2c_Update_and_Compatibility#Update_RDF_Format">update.rdf</a> file on the internet which will include the updated versions and version information for the plugin.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/builder/index.html b/files/zh-cn/mozilla/add-ons/sdk/builder/index.html deleted file mode 100644 index 1baa282d43..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/builder/index.html +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Builder -slug: Mozilla/Add-ons/SDK/Builder -translation_of: Archive/Add-ons/Add-on_SDK/Builder ---- -<p>The Add-on Builder was a web-based development environment that allowed developers to create add-ons using the SDK APIs, but without needing to use the <code>cfx</code> command line tool. It was retired on April 1, 2014, and the "builder.addons.mozilla.org" domain now redirects to this page.<br> - <br> - If you have only used the SDK through the Builder, you already know most of what you need to know to develop using just the SDK. The <a href="/en-US/Add-ons/SDK/High-Level_APIs">high-level</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs">low-level</a> APIs used for Builder add-ons are exactly the same for Builder and SDK. To switch to the SDK:</p> -<ul> - <li><a href="/en-US/Add-ons/SDK/Tutorials/Installation">install the SDK locally</a></li> - <li>get to know the cfx command line tool, with this <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started">introductory walkthrough</a> and the <a href="/en-US/Add-ons/SDK/Tools/cfx">detailed <code>cfx</code> reference</a></li> - <li>get to know the <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> file used to configure attributes of your add-on</li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html deleted file mode 100644 index fa95b15db3..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html +++ /dev/null @@ -1,486 +0,0 @@ ---- -title: Content Scripts(内容脚本) -slug: Mozilla/Add-ons/SDK/Guides/Content_Scripts -translation_of: Archive/Add-ons/Add-on_SDK/Guides/Content_Scripts ---- -<article id="wikiArticle">{{AddonSidebar}} -<p><span class="seoSummary">很多 add-ons 需要访问和修改 web 页面的内容。但是 add-on 的主代码不能直接访问 web 内容。替代方案是, SDK add-ons 需要使用一些分散的脚本代理访问 web 内容,这些脚本被称作<em>内容脚本(content scripts)</em>。本页面描述如何开发和部署内容脚本。 </span></p> - -<p>内容脚本是在使用SDK时很令人疑惑的点,但你很有可能不得不使用它们。下面有五个基本原则:</p> - -<ul> - <li>add-on 的主代码,包括"main.js"和其他"lib"下的模块,可以使用 SDK <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/High-Level_APIs">高层次</a>和<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Low-Level_APIs">低层次</a> APIs,但不能直接访问 web 内容</li> - <li>内容脚本 <a href="/en-US/Add-ons/SDK/Guides/Two_Types_of_Scripts#API_Access_for_Add-on_Code_and_Content_Scripts">不能使用 SDK 的 API</a>(访问不了 globals 的 <code>exports</code>、<code>require</code>),但你可以访问 web 内容</li> - <li>SDK API 可以使用,内容脚本,比如 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a> 和 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>,提供了一些函数,使得 add-on 的主代码可以将内容脚本载入web页面中。</li> - <li>内容脚本可以作为字符串加载,但是更常见的是分离存储为 add-on 的"data"目录下文件。 jpm 不会默认创建"data"目录,所以你必须添加该目录并把脚本放进去。</li> - <li>一个消息传递 API 允许主代码和内容脚本间相互通信。</li> -</ul> - -<p>这个完整的 add-on 表现出所有的这些原则。它的"main.js"使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a> 模块附加了一个内容脚本到当前标签页。本例中内容脚本作为字符串传递,内容脚本简单地替换了页面的内容:</p> - -<pre class="brush: js">// main.js -var tabs = require("sdk/tabs"); -var contentScriptString = 'document.body.innerHTML = "<h1>this page has been eaten</h1>";' - -tabs.activeTab.attach({ - contentScript: contentScriptString -});</pre> - -<p>下面的高层次 SDK 模块能使用内容脚本来修改 web 页面:</p> - -<ul> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>:使你能附加一个内容脚本到匹配上特定 URL 模式的web页面。</li> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>:导出一个 <code>Tab</code> 对象来处理浏览器标签页。<code>Tab</code> 对象包括了一个 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>attach()</code></a> 函数来附加内容脚本到标签页。</li> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/page-worker">page-worker</a>:让你能够恢复一个 web 页面,但不显示它。你可以附加内容脚本到该页面,来访问和操作该页面的 DOM。</li> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu</a>:使用内容脚本来和按钮所在的页面交互。</li> -</ul> - -<p>另外,还能使用 HTML 定义了一些 SDK 用户接口组件,并且使用分类的脚本来和这些内容交互。从很多方面来讲,这些脚本就像内容脚本一样,但它们并不是本文的关注点。要学习如何和用户接口模块的内容交互,请参看模块定义文档:<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a>、<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_sidebar">sidebar</a>、<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_frame">frame</a>。</p> - -<p>这篇指南中列出的几乎所有的示例都是完整并且且最小的,可以在 Github 的 <a href="https://github.com/mdn/addon-sdk-content-scripts">addon-sdk-content-scripts repository</a> 页面上获得。</p> - -<h2 id="加载用户脚本">加载用户脚本</h2> - -<article id="wikiArticle"> -<p>你可以声明一个字符串或者指定 <code>contentScript</code> 或 <code>contentScriptFile</code> 选项加载一个单独的脚本。<code>contentScript</code> 选项接受一个作为脚本的字符串:</p> - -<pre class="brush: js">// main.js - -var pageMod = require("sdk/page-mod"); -var contentScriptValue = 'document.body.innerHTML = ' + - ' "<h1>Page matches ruleset</h1>";'; - -pageMod.PageMod({ - include: "*.mozilla.org", - contentScript: contentScriptValue -});</pre> - -<p><code>contentScriptFile</code> 选项接受一个作为 resource:// URL 的字符串,指向一个存储在你的 add-on 的 <code>data</code> 目录中的脚本文件。jpm不会默认创建"data"目录,所以你必须创建该目录并将你的用户脚本放进去。</p> - -<p>本 add-on 提供一个 URL ,指向"content-script.js"文件,存储在 add-on 根目录下的 <code>data</code> 子目录:</p> - -<pre class="brush: js">// main.js - -var data = require("sdk/self").data; -var pageMod = require("sdk/page-mod"); - -pageMod.PageMod({ - include: "*.mozilla.org", - contentScriptFile: data.url("content-script.js") -});</pre> - -<pre class="brush: js">// content-script.js - -document.body.innerHTML = "<h1>Page matches ruleset</h1>";</pre> - -<div class="note"> -<p>从 Firefox 34 开始,你可以使用"./content-script.js"替代 self.data.url("content-script.js")。所以你可以像这样重写:</p> - -<pre class="brush: js">var pageMod = require("sdk/page-mod"); - -pageMod.PageMod({ - include: "*.mozilla.org", - contentScriptFile: "./content-script.js" -}); -</pre> -</div> - -<div class="warning"> -<p>除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 <code>contentScript</code>:否则,你会在从 AMO 获取你的add-on上遇到问题。</p> - -<p>相反,把脚本放到一个单独的文件并用 <code>contentScriptFile</code> 加载它。这回事你的代码更易维护、安全、调试和审核。</p> -</div> - -<p>你可以给 <code>contentScript</code> 或 <code>contentScriptFile</code> 传递字符串数组来加载多个脚本:</p> - -<pre class="brush: js">// main.js - -var tabs = require("sdk/tabs"); - -tabs.on('ready', function(tab) { - tab.attach({ - contentScript: ['document.body.style.border = "5px solid red";', 'window.alert("hi");'] - }); -}); -</pre> - -<pre class="brush: js">// main.js - -var data = require("sdk/self").data; -var pageMod = require("sdk/page-mod"); - -pageMod.PageMod({ - include: "*.mozilla.org", - contentScriptFile: [data.url("jquery.min.js"), data.url("my-content-script.js")] -});</pre> - -<p>如果你这么做,这些脚本之间可以直接交互,就像他们被同一个 web 页面加载一样。</p> - -<p>你也可以把 <code>contentScript</code> 和 <code>contentScriptFile</code> 一起用。如果你这么做,使用 <code>contentScriptFile</code> 定义的脚本会在使用 <code>contentScript</code> 定义的脚本之前加载。这使你能够用 URL 加载比如 jQuery 这样的 JavaScript 库,然后传递一个简单的能够使用jQuery脚本:</p> - -<pre class="brush: js">// main.js - -var data = require("sdk/self").data; -var pageMod = require("sdk/page-mod"); - -var contentScriptString = '$("body").html("<h1>Page matches ruleset</h1>");'; - -pageMod.PageMod({ - include: "*.mozilla.org", - contentScript: contentScriptString, - contentScriptFile: data.url("jquery.js") -});</pre> - -<div class="warning"> -<p>除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 <code>contentScript</code>:否则,在从 AMO 获取你的 add-on 上,你会遇到问题。</p> - -<p>相反,把脚本放到一个单独的文件并用 <code>contentScriptFile</code> 加载它。这回事你的代码更易维护、安全、调试和审核。</p> -</div> - -<h3 id="控制附加脚本的时间">控制附加脚本的时间</h3> - -<p><code>contentScriptWhen</code> 选项指定了什么时候加载内容脚本。从这里选一个:</p> - -<ul> - <li><code>"start"</code>:页面 document 元素插入 DOM 之后,立即加载脚本。这时 DOM 的内容仍未加载,所以脚本不能与其交互。</li> - <li><code>"ready"</code>:页面 DOM 加载完后加载脚本:也就是说,在那个时间点 <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> 事件触发。这时,内容脚本可以和DOM内容交互,但外部引用的样式表和图片可能还没有完成加载。</li> - <li><code>"end"</code>:页面上所有内容(DOM、JS、CSS、images)加载完后,加载脚本,就是在 <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload 事件</a>触发的时候</li> -</ul> - -<p>默认值为 <code>"end"</code>。</p> - -<p>注意 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>tab.attach()</code></a> 不支持 contentScriptWhen,因为它原来就是在页面加载页面的时候被调用的。</p> - -<h3 id="传递配置选项">传递配置选项</h3> - -<p><code>contentScriptOptions</code> 是一个作为只读对象暴露给内容脚本的JSON对象,在 <code><a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self">self</a>.options</code> 的属性里:</p> - -<pre class="brush: js">// main.js - -var tabs = require("sdk/tabs"); - -tabs.on('ready', function(tab) { - tab.attach({ - contentScript: 'window.alert(self.options.message);', - contentScriptOptions: {"message" : "hello world"} - }); -});</pre> - -<p>这里可以使用任何可以转成json的值(object、array、string等等)。</p> - -<h2 id="访问_DOM">访问 DOM</h2> - -<p>内容脚本可以访问页面的 DOM,就像任何页面中加载的脚本(页面脚本)一样。但是内容脚本和页面脚本之间是隔离的:</p> - -<ul> - <li>内容脚本不能看到任何由页面脚本添加到页面的 JavaScript 对象</li> - <li>如果页面脚本重定义了某个 DOM 对象的行为,但内容脚本只会看到原来的那个行为。</li> -</ul> - -<p>相反也是如此:页面脚本不能看到内容脚本添加的 JavaScript 对象。</p> - -<p>例如,假想一个页面用页面脚本添加变量 <code>foo</code> 到 <code>window</code> 对象:</p> - -<pre class="brush: html"><!DOCTYPE html"> -<html> - <head> - <script> - window.foo = "hello from page script" - </script> - </head> -</html></pre> - -<p>在这个脚本后面加载到页面的其他脚本也可以访问 <code>foo</code>。但是内容脚本不能:</p> - -<pre class="brush: js">// main.js - -var tabs = require("sdk/tabs"); -var mod = require("sdk/page-mod"); -var self = require("sdk/self"); - -var pageUrl = self.data.url("page.html") - -var pageMod = mod.PageMod({ - include: pageUrl, - contentScript: "console.log(window.foo);" -}) - -tabs.open(pageUrl);</pre> - -<pre>console.log: my-addon: null -</pre> - -<p>这种隔离策略有着很合理的理由。首先,这意味着内容脚本不会泄露对象给 web 页面,这样可能会打开安全漏洞。第二,这意味着,在内容脚本创建对象的时候,可以不用担心是否会和页面脚本添加的对象相冲突。</p> - -<p>这种隔离意味着,例如,如果一个 web 页面加载了 jQuery 库,那么内容脚本不能够看到由该库添加的 <code>jQuery</code> 对象——但是可以看到内容脚本添加的自己的 <code>jQuery</code> 对象,并且它不会和页面脚本的 jQuery 版本冲突。</p> - -<h3 id="和页面脚本交互">和页面脚本交互</h3> - -<p>一般来说,这种内容脚本和页面脚本的隔离正是你所希望的。但是有时候你也许会希望和页面脚本交互:你想在内容脚本和页面脚本之间共享对象来,来在它们之间发送消息。如果你需要这么做,请阅读<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Interacting_with_page_scripts">和页面脚本交互</a>。</p> - -<h3 id="事件监听器">事件监听器</h3> - -<p>你可以监听 DOM 的事件,就像在页面脚本中一样,但是有两个重要的区别:</p> - -<p>第一,如果你向 <a href="https://developer.mozilla.org/en/DOM/element.setAttribute"><code>setAttribute()</code></a> 传递字符串,来定义了事件监听器,那么此监听器被当做是在页面上下文中的,所以它不能访问任何内容脚本中的变量。</p> - -<p>如下,内容脚本会失败报错"theMessage is not defined":</p> - -<pre class="brush: js">var theMessage = "Hello from content script!"; -anElement.setAttribute("onclick", "alert(theMessage);");</pre> - -<p>Second, if you define an event listener by direct assignment to a <a href="/en-US/docs/Web/API/GlobalEventHandlers">global event handler</a> like <code>onclick</code>, then the assignment might be overridden by the page. For example, here's an add-on that tries to add a click handler by assignment to <code>window.onclick</code>:</p> - -<pre class="brush: js">var myScript = "window.onclick = function() {" + - " console.log('unsafewindow.onclick: ' + window.document.title);" + - "}"; - -require("sdk/page-mod").PageMod({ - include: "*", - contentScript: myScript, - contentScriptWhen: "start" -});</pre> - -<p>这个示例会在大多数页面上正常工作,但是会在定义 <code>onclick</code> 的页面上失败:</p> - -<pre class="brush: html"><html> - <head> - </head> - <body> - <script> - window.onclick = function() { - window.alert("it's my click now!"); - } - </script> - </body> -</html></pre> - -<p>由于这些原因,最好还是用 <a href="https://developer.mozilla.org/en/DOM/element.addEventListener"><code>addEventListener()</code> 添加一个事件监听器</a>,定义监听器为一个函数:</p> - -<pre class="brush: js">var theMessage = "Hello from content script!"; - -anElement.onclick = function() { - alert(theMessage); -}; - -anotherElement.addEventListener("click", function() { - alert(theMessage); -});</pre> - -<h2 id="和_add-on_通信">和 add-on 通信</h2> - -<p>为了使 add-on 脚本和内容脚本相互通信,任何一通信端都要访问 <code>port</code> 对象。</p> - -<ul> - <li>要从一头发送消息到另一头,使用 <code>port.emit()</code></li> - <li>要从另一头接收消息,使用 <code>port.on()</code></li> -</ul> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7873/content-scripting-overview.png" style="display: block; margin-left: auto; margin-right: auto;">消息是异步的:也就是说,发送方不会等待接收方的回应,而仅仅是发送消息完后继续处理别的事情。</p> - -<p>这里有一个简单的 add-on 使用 <code>port</code> 发送一个消息到内容脚本:</p> - -<pre class="brush: js">// main.js - -var tabs = require("sdk/tabs"); -var self = require("sdk/self"); - -tabs.on("ready", function(tab) { - var worker = tab.attach({ - contentScriptFile: self.data.url("content-script.js") - }); - worker.port.emit("alert", "Message from the add-on"); -}); - -tabs.open("http://www.mozilla.org");</pre> - -<pre class="brush: js">// content-script.js - -self.port.on("alert", function(message) { - window.alert(message); -});</pre> - -<div class="note"> -<p>context-menu 模块没有使用这里描述的通信模型。了解更多关于使用 context-menu 和内容脚本通信的事情,参看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu documentation</a>。</p> -</div> - -<h3 id="在内容脚本中访问_port"><code>在内容脚本中访问 port</code></h3> - -<p>内容脚本中,<code>port</code> 对象是作为global下 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self"><code>self</code></a> 对象的属性。所以要从内容脚本中发送消息的话:</p> - -<pre class="brush: js">self.port.emit("myContentScriptMessage", myContentScriptMessagePayload);</pre> - -<p>要从 add-on 代码接收消息</p> - -<pre class="brush: js">self.port.on("myAddonMessage", function(myAddonMessagePayload) { - // Handle the message -});</pre> - -<div class="note"> -<p>注意 global下 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self"><code>self</code></a> 对象和 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code> 模块</a>完全不一样,后者提供一个API给 add-on,用来访问它的数据文件和ID。</p> -</div> - -<h3 id="在内容脚本中访问_port_2">在内容脚本中访问 port</h3> - -<p>在 add-on 代码中,联通 add-on 和某一特定内容脚本上下文的通道被封装入 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker"><code>worker</code></a> 对象。所以和内容脚本通信的 <code>port</code> 对象其实是其相对应的 <code>worker</code> 对象的一个属性。</p> - -<p>但是,这个 worker 没有暴露给 add-on 代码,以及同样所有的模块。</p> - -<h4 id="从_page-worker">从 <code>page-worker</code></h4> - -<p><code>page-worker</code> 对象直接整合了 work API。所以要从一个由 <code>page-worker</code> 关联的内容脚本接收消息的话,你可以使用 <code>pageWorker.port.on()</code>:</p> - -<pre class="brush: js">// main.js - -var self = require("sdk/self"); - -var pageWorker = require("sdk/page-worker").Page({ - contentScriptFile: self.data.url("content-script.js"), - contentURL: "http://en.wikipedia.org/wiki/Internet" -}); - -pageWorker.port.on("first-para", function(firstPara) { - console.log(firstPara); -});</pre> - -<p>要从你的 add-on 发送用户定义的消息,你可以只调用 <code>pageWorker.port.emit()</code>:</p> - -<pre class="brush: js">// main.js - -var self = require("sdk/self"); - -var pageWorker = require("sdk/page-worker").Page({ - contentScriptFile: self.data.url("content-script.js"), - contentURL: "http://en.wikipedia.org/wiki/Internet" -}); - -pageWorker.port.on("first-para", function(firstPara) { - console.log(firstPara); -}); - -pageWorker.port.emit("get-first-para");</pre> - -<pre class="brush: js">// content-script.js - -self.port.on("get-first-para", getFirstPara); - -function getFirstPara() { - var paras = document.getElementsByTagName("p"); - if (paras.length > 0) { - var firstPara = paras[0].textContent; - self.port.emit("first-para", firstPara); - } -}</pre> - -<h4 id="从_page-mod">从<code> page-mod</code></h4> - -<p>单个 <code>page-mod</code> 对象可以附加它的脚本到多个页面,每个页面有它自己的上下文来运行内容脚本,所以每个页面都需要相互隔离的通道(worker)。</p> - -<p>所以 <code>page-mod</code> 没有直接整合 worker 的 API。而是在每次内容脚本被附加到页面时,page-mod 发送一个 <code>attach</code> 事件,它的监听器会给对应的上下文传递一个 worker。通过为 <code>attach</code> 提供一个监听器,你可以访问被一个 page-mod 附加到页面上的内容脚本的 <code>port</code> 对象:</p> - -<pre class="brush: js">// main.js - -var pageMods = require("sdk/page-mod"); -var self = require("sdk/self"); - -var pageMod = pageMods.PageMod({ - include: ['*'], - contentScriptFile: self.data.url("content-script.js"), - onAttach: startListening -}); - -function startListening(worker) { - worker.port.on('click', function(html) { - worker.port.emit('warning', 'Do not click this again'); - }); -}</pre> - -<pre class="brush: js">// content-script.js - -window.addEventListener('click', function(event) { - self.port.emit('click', event.target.toString()); - event.stopPropagation(); - event.preventDefault(); -}, false); - -self.port.on('warning', function(message) { - window.alert(message); -}); -</pre> - -<p>上面的 add-on 里有两条消息:</p> - -<ul> - <li>当用户点击页面元素时,<code>click</code> 从 page-mod 被发送到当前 add-on。</li> - <li><code>warning</code> 发送一条傻气的字符串回给page-mod</li> -</ul> - -<h4 id="从_Tab.attach()">从 <code>Tab.attach()</code></h4> - -<p><code>Tab.attach()</code> 方法返回一个 worker,你可以用来和附加的内容脚本通信。</p> - -<p>这个 add-on 添加了一个按钮到Firefox:等用户点击按钮是,这个 add-on 附加一个内容脚本到当前的标签页,发送给内容脚本一条名为 "my-addon-message"的消息,并且监听名为"my-script-response"的响应:</p> - -<pre class="brush: js">//main.js - -var tabs = require("sdk/tabs"); -var buttons = require("sdk/ui/button/action"); -var self = require("sdk/self"); - -buttons.ActionButton({ - id: "attach-script", - label: "Attach the script", - icon: "./icon-16.png", - onClick: attachScript -}); - -function attachScript() { - var worker = tabs.activeTab.attach({ - contentScriptFile: self.data.url("content-script.js") - }); - worker.port.on("my-script-response", function(response) { - console.log(response); - }); - worker.port.emit("my-addon-message", "Message from the add-on"); -} -</pre> - -<pre class="brush: js">// content-script.js - -self.port.on("my-addon-message", handleMessage); - -function handleMessage(message) { - alert(message); - self.port.emit("my-script-response", "Response from content script"); -}</pre> - -<h3 id="port的API">port的API</h3> - -<p>参看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/port"><code>port</code> 对象的参考文档</a>.</p> -</article> - -<h3 id="postMessage的API">postMessage的API</h3> - -<p>在 <code>port</code> 对象加载之前,add-on 代码和内容脚本可以使用另一个 API 通信:</p> - -<ul> - <li>内容脚本调用 <code>self.postMessage()</code> 来发送,并用 <code>self.on()</code> 来接收</li> - <li>内容脚本调用 <code>worker.postMessage()</code> 来发送,并用 <code>worker.on()</code> 来接收</li> -</ul> - -<p>这个API依然可用,并且还有<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_postMessage">文档</a>,但是没有理由替代前文描述的 <code>port</code> API。 例外是 <a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu</a> 模块,它还是使用 postMessage。</p> - -<h3 id="内容脚本的内容脚本">内容脚本的内容脚本</h3> - -<p>内容脚本可用直接和其他同一个上下文中的内容脚本通信。举个例子,如果一次 <code>Tab.attach()</code> 的调用附加了两个脚本,那么他们可用直接相互查看,就像加载在同一页面内的页面脚本一样。但是如果你调用 <code>Tab.attach()</code> 两次,每次附加一个内容脚本,那么这些内容脚本之间不能通信。你必须使用port API 通过 add-on 的主代码来传递消息。</p> - -<h2 id="跨域的内容脚本">跨域的内容脚本</h2> - -<p>默认情况下,内容脚本没有跨域的权限。特别是,它们不能访问在不同 <code>iframe</code> 中的在另外的域名上的内容,也不能发起跨域的 XMLHttpRequests。</p> - -<p>但是,你可以把需要的域名添加到 <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 中<code>"permissions"</code>键下的 <code>"cross-domain-content"</code>键下,为这些域名打开这些特性。参阅文章<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts">跨域内容脚本</a>。</p> -</article> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/index.html deleted file mode 100644 index 51fbdef445..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/guides/index.html +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: 教程 -slug: Mozilla/Add-ons/SDK/Guides -tags: - - NeedsTranslation - - TopicStub -translation_of: Archive/Add-ons/Add-on_SDK/Guides ---- -<p>下面列出了一些文章可以加深你对SDK的理解</p> -<hr> -<h3 id="投稿者的教程"><a name="contributors-guide">投稿者的教程</a></h3> -<div class="column-container"> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Getting_Started">起步</a></dt> - <dd> - 学会如何使用SDK : 编写代码, 调试bug, 提交补丁, 审核项目, 获得帮助.</dd> - <dt> - <a href="Guides/Modules">模块</a></dt> - <dd> - 通过SDK学会模块的使用 (以CommonJS为规范), 懂得如何使用 sandboxes 和compartments 提高安全性, 并且了解内置的 SDK module loader (被称为Cuddlefish).</dd> - <dt> - <a href="Guides/Classes_and_Inheritance">类 和 继承</a></dt> - <dd> - 学会<strong> 类</strong>和<strong>继承</strong>在JavaScript中的运行机制, 使用<strong>构造(constructors)</strong>和<strong>原型(prototypes)</strong>, 并知道如何使用SDK提供的函数帮助器简化它.</dd> - </dl> - </div> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Private_Properties">私有成员</a></dt> - <dd> - 通过 前缀, 闭包, 和WeakMaps 学会私有成员如何在JavaScript中的实现, 使用 命名空间(通常指WeakMaps) 学会SDK如何支持私有成员.</dd> - <dt> - <a href="Guides/Content_Processes">脚本运行流程</a></dt> - <dd> - SDK的设计目的是为了使控制网页内容的扩展脚本可以在不同进程的环境中运行. 这篇文章强调了这一设计的特点.</dd> - </dl> - </div> -</div> -<hr> -<h3 id="SDK的基础结构"><a name="sdk-infrastructure">SDK的基础结构</a></h3> -<div class="column-container"> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Module_structure_of_the_SDK">SDK 模块结构</a></dt> - <dd> - SDK是可重复使用的 JavaScript 模块. 这里解释了什么是模块, 怎样加载模块, 和SDK模块树的构造.</dd> - <dt> - <a href="Guides/SDK_API_Lifecycle">SDK API 生存周期</a></dt> - <dd> - 为SDK的API定义生命周期, 包括API稳定性的排名</dd> - </dl> - </div> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Program_ID">程序 ID</a></dt> - <dd> - 程序ID 是扩展独一无二的标识符. 教程解释了如何定义你自己的程序 ID.</dd> - <dt> - <a href="Guides/Firefox_Compatibility">Firefox 兼容</a></dt> - <dd> - 解决不同版本SDK生成的扩展与不同版本Firefox的兼容问题</dd> - </dl> - </div> -</div> -<hr> -<h3 id="SDK_常用技巧"><a name="sdk-idioms">SDK 常用技巧</a></h3> -<div class="column-container"> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Working_with_Events">善用 事件触发</a></dt> - <dd> - 通过SDK的事件触发框架 写出以事件驱动为基础的代码</dd> - </dl> - </div> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Two_Types_of_Scripts">脚本的两种类型</a></dt> - <dd> - 这篇文章可以帮助你理解扩展中的API和普通脚本的区别</dd> - </dl> - </div> -</div> -<p> </p> -<hr> -<h3 id="XUL_迁移"><a name="xul-migration">XUL 迁移</a></h3> -<div class="column-container"> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/XUL_Migration_Guide">XUL 迁移教程</a></dt> - <dd> - 把XUL扩展迁移到SDK的技巧</dd> - <dt> - <a href="Guides/XUL_vs_SDK">XUL 与 SDK 不同</a></dt> - <dd> - 比较 传统的以XUL为基础的扩展 和 SDK 两者优点和缺点</dd> - </dl> - </div> - <div class="column-half"> - <dl> - <dt> - <a href="Guides/Porting_the_Library_Detector">移植例子</a></dt> - <dd> - 一个简单地教你如何让 基于XUL的扩展 迁移到 SDK中的实例</dd> - </dl> - </div> -</div> -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html deleted file mode 100644 index c22dd0181e..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: 多进程 Firefox 与 SDK -slug: Mozilla/Add-ons/SDK/Guides/Multiprocess_Firefox_and_the_SDK -translation_of: Archive/Add-ons/Add-on_SDK/Guides/Multiprocess_Firefox_and_the_SDK ---- -<p>我们目前正在使 Firefox 变为多进程,它为浏览器界面使用一个操作系统进程,为运行的网页使用另一个进程来执行代码,这个项目被称为 "electrolysis" 或者 "e10s"。更多信息请参考<a href="/en-US/Firefox/Multiprocess_Firefox">多进程 Firefox 相关页面</a>。</p> - -<p>本文章介绍了开发者如何测试基于 SDK 的附加组件是否与多进程的 Firefox 兼容,以及如何解决出现的问题。</p> - -<h2 id="SDK_的合约">SDK 的合约</h2> - -<p>SDK 为附加组件的开发者承诺了:</p> - -<ul> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs">顶层 API</a> 对多进程 Firefox 完全工作。如果并没有,请报告为 SDK 中的 bug。</li> - <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs">底层 API</a> 也许不工作。如果你在使用底层 API,考虑检查、测试和重构某些代码。</li> -</ul> - -<p>在实践中,大多数底层 API 将正常工作,但可以直接访问网页内容的底层 API 无法正常工作。</p> - -<h2 id="兼容性垫片">兼容性垫片</h2> - -<p>举例来说,你可能认为这是行不通的:</p> - -<pre class="brush: js">var contentDocument = require("sdk/window/utils") - .getMostRecentBrowserWindow().content.document;</pre> - -<p>但是,Firefox 为附加组件提供了许多 API 的兼容性垫片。这意味着许多 API,包括上述例子的那个,仍然工作。虽然有两条警示需注意:</p> - -<ul> - <li>这些垫片不完美:某些附加组件在有垫片的情况下仍然不工作。举例来说,许多垫片通过为内容对象返回跨进称对象包装器来工作,并且这<a href="/en-US/Firefox/Multiprocess_Firefox/Cross_Process_Object_Wrappers#Limitations_of_CPOWs">并非始终以同样的方式</a>作为内容对象。</li> - <li>这些垫片可能对性能有不良影响,我们希望人们最终去除它们。</li> -</ul> - -<p>We don't yet have a complete list of low-level APIs that are not multiprocess compatible: that is, will not work without the shims. Where we know that a low-level API is not multiprocess compatible, we've indicated that in the documentation page for it.</p> - -<h2 id="测试">测试</h2> - -<p>To test whether an add-on works without the shims, use the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>.</p> - -<div class="note"> -<p><strong>Note</strong> that you can only do this if you are using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>. You can't use the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a> if you are using <a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a>.</p> -</div> - -<p>Setting this permission will disable the shims for your add-on, so you can test to see if it's really multiprocess compatible or not.</p> - -<p>However, there's a catch: some of the SDK's APIs themselves still depend on the shims. So by setting the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>, your add-on might not work, even if you are only using high-level APIs. For example:</p> - -<pre class="brush: js">var selection = require("sdk/selection"); - -function myListener() { - console.log(selection.text); -} - -selection.on('select', myListener); -</pre> - -<p>This add-on will not work if you've set the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>, because <code><a href="/en-US/Add-ons/SDK/High-Level_APIs/selection">sdk/selection</a></code> depends on the shims. We're working on fixing these problems: see <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1004745">bug 1004745</a> and its dependencies.</p> - -<h2 id="使用框架脚本">使用框架脚本</h2> - -<p>If the shims don't enable your add-on to work properly, or you're trying to remove your dependency on the shims, then the solution is the same as it is for all add-ons:</p> - -<ul> - <li>factor the code that needs access to content objects into frame scripts</li> - <li>use the message manager to load the frame scripts into the content process</li> - <li>use the message manager to exchange messages with the frame scripts</li> -</ul> - -<p>In the rest of this section we'll outline some SDK-specific details of using the message manager. However, you'll also need to read the main <a href="/en-US/Firefox/Multiprocess_Firefox/The_message_manager">message manager documentation</a> for the details on working with frame scripts.</p> - -<div class="note"> -<p>If you're used to working with content scripts in the SDK, then frame scripts might feel similar, but they're actually very different. Frame scripts are more like a part of the main add-on code that just happens to be running in the content process.</p> - -<p>Differences between frame scripts and content scripts include:</p> - -<ul> - <li>the <a href="/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment">environment for frame scripts</a> and the <a href="/en-US/Add-ons/SDK/Guides/Two_Types_of_Scripts#API_Access_for_Add-on_Code_and_Content_Scripts">environment for content scripts</a> are totally different: - - <ul> - <li>content scripts have a very similar environment to scripts loaded by web pages, plus the <code><a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self">self</a></code> global.</li> - <li>frame scripts also have access to web content, but have a different set of APIs for communicating with the chrome process, and access to the <a href="/en-US/docs/Components_object">Components object</a>, which enables them to use privileged <a href="/en-US/docs/Mozilla/Tech/XPCOM">XPCOM</a> APIs and load <a href="/en-US/docs/Mozilla/JavaScript_code_modules">JSMs</a>.</li> - </ul> - </li> - <li>content scripts are reloaded when a new document is loaded. Frame scripts aren't: once a frame script is loaded into a tab it remains loaded until the tab is closed. For more details, see the article on <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime">frame script lifetime</a>.</li> -</ul> -</div> - -<h3 id="访问消息管理器">访问消息管理器</h3> - -<h4 id="全局消息管理器">全局消息管理器</h4> - -<p>To access the <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Global_frame_message_manager">global message manager</a>, you load the <a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager">nsIMessageListenerManager</a> service. Before you can do this in an SDK add-on, you have to <code>require("chrome")</code> to get access to the <code><a href="/en-US/docs/Components_object">Components</a></code> object:</p> - -<pre class="brush: js">const {Cc, Ci} = require("chrome"); - -var globalMM = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager);</pre> - -<h4 id="窗口消息管理器">窗口消息管理器</h4> - -<p>The <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Window_message_manager">window message manager</a> is available as the <code>messageManager</code> property of a chrome window. To understand what a chrome window is, you need to distinguish three sorts of windows:</p> - -<ul> - <li>a content window is the <a href="/en-US/docs/Web/API/Window">Window</a> object familiar to Web developers as the global object for JavaScript loaded from an HTML document. This is the same window that content scripts in the SDK access.</li> - <li>a chrome window, also called a browser window. This is a Firefox application window, hosting the Firefox UI as well as a collection of tabs, each of which can in turn host a DOM window to display web content. This is the global for traditional overlay-based add-ons. In the SDK, the low-level <a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> module works with these sorts of windows.</li> - <li>an SDK window, as made available by the high level <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows">windows</a> module. Each SDK window maps to a chrome window, but omits most of the chrome window's properties, including <code>messageManager</code>. If you have an SDK window you can convert it to a chrome window using <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#Converting_to_chrome_windows">viewFor</a>.</li> -</ul> - -<p>So to get a window message manager from the SDK, you have a couple of options:</p> - -<p>(1) Use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> module:</p> - -<pre class="brush: js">// Note that although this code uses window/utils, -// it's safe to run in the chrome process because -// it only accesses chrome objects. - -// get the active chrome window -var browserWindow = require("sdk/window/utils").getMostRecentBrowserWindow(); - -var windowMM = browserWindow.messageManager;</pre> - -<p>(2) Use <code>viewFor</code> to convert an SDK window to a chrome window:</p> - -<pre class="brush: js">// get the active SDK window -var windows = require("sdk/windows").browserWindows; -var activeWindow = windows.activeWindow; - -// convert it to a chrome window -var browserWindow = require("sdk/view/core").viewFor(activeWindow); - -var windowMM = browserWindow.messageManager;</pre> - -<h4 id="浏览器消息管理器">浏览器消息管理器</h4> - -<p>The <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Browser_message_manager">browser message manager</a> is available as the <code>messageManager</code> property of an XUL <code><a href="/en-US/docs/XUL/browser">browser</a></code>.</p> - -<p>In the SDK, to get a <code>browser</code> for a given tab, you can use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils">tabs/utils</a> module's <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils#getBrowserForTab%28tab%29">getBrowserForTab</a></code> function. <code>getBrowserForTab</code> expects an XUL tab as an argument, so if you have an <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">SDK tab</a> object, you'll need to convert it to an XUL tab using <code><a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Converting_to_XUL_tabs">viewFor</a></code>:</p> - -<pre class="brush: js">// get the active SDK tab -var tab = require("sdk/tabs").activeTab; -// convert it to an XUL tab -var xulTab = require("sdk/view/core").viewFor(tab); -// get the XUL browser for this tab -var xulBrowser = require("sdk/tabs/utils").getBrowserForTab(xulTab); - -var browserMM = xulBrowser.messageManager;</pre> - -<p>Again, although this code uses tabs/utils, it's safe to run in the chrome process because it only accesses chrome objects.</p> - -<h3 id="载入框架脚本">载入框架脚本</h3> - -<p>You can load frame scripts using the message manager, passing in a chrome:// or resource:// URL pointing to the script. With the SDK, the simplest approach is to keep frame scripts under your add-on's data directory, and pass in a resource:// URL created using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)">self.data.url</a>:</p> - -<pre class="brush: js">const self = require("sdk/self"); - -messageManager.loadFrameScript(self.data.url("frame-script.js"), false);</pre> - -<p>Note that unlike the APIs to load content scripts, you can only load a single frame script here.</p> - -<h3 id="例子">例子</h3> - -<p>For example, this add-on trivially accesses content directly using a low-level API:</p> - -<pre class="brush: js">function logContent() { - var contentDocument = require("sdk/window/utils") - .getMostRecentBrowserWindow().content.document; - console.log(contentDocument.body.innerHTML); -} - -require("sdk/ui/button/action").ActionButton({ - id: "log-content", - label: "Log Content", - icon: "./icon-16.png", - onClick: logContent -});</pre> - -<p>This add-on will work by default due to the shims, but will break if you set multiprocessCompatible. So you could rewrite the add-on to use frame scripts:</p> - -<pre class="brush: js">/* -frame-script.js is in the "data" directory, and has this content: - -sendAsyncMessage("sdk-low-level-apis-e10s@jetpack:got-content", - content.document.body.innerHTML); - -*/ - -const self = require("sdk/self"); - -function logContentAsync() { - var tab = require("sdk/tabs").activeTab; - var xulTab = require("sdk/view/core").viewFor(tab); - var xulBrowser = require("sdk/tabs/utils").getBrowserForTab(xulTab); - - var browserMM = xulBrowser.messageManager; - browserMM.loadFrameScript(self.data.url("frame-script.js"), false); - browserMM.addMessageListener("sdk-low-level-apis-e10s@jetpack:got-content", - logContent); -} - -function logContent(message) { - console.log(message.data); -} - -require("sdk/ui/button/action").ActionButton({ - id: "log-content", - label: "Log Content", - icon: "./icon-16.png", - onClick: logContentAsync -});</pre> - -<p>现在附加组件能正常工作了,即使你设置了 multiprocessCompatible。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html deleted file mode 100644 index 4c24b84e13..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Working with Events -slug: Mozilla/Add-ons/SDK/Guides/Working_with_Events -translation_of: Archive/Add-ons/Add-on_SDK/Guides/Working_with_Events ---- -<p>The Add-on SDK supports event-driven programming.</p> -<p>Objects emit events on state changes that might be of interest to add-on code, such as browser windows opening, pages loading, network requests completing, and mouse clicks. By registering a listener function to an event emitter an add-on can receive notifications of these events.</p> -<p><span>We talk about content scripts in more detail in the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</span></p> -<p>Additionally, if you're using content scripts to interact with web content, you can define your own events and use them to communicate between the main add-on code and the content scripts. In this case one end of the conversation emits the events, and the other end listens to them.</p> -<p>So there are two main ways you will interact with the EventEmitter framework:</p> -<ul> - <li> - <p><strong>listening to built-in events</strong> emitted by objects in the SDK, such as tabs opening, pages loading, mouse clicks</p> - </li> - <li> - <p><strong>sending and receiving user-defined events</strong> between content scripts and add-on code</p> - </li> -</ul> -<p>This guide only covers the first of these; the second is explained in the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p> -<h2 id="Adding_Listeners">Adding Listeners</h2> -<p>You can add a listener to an event emitter by calling its <code>on(type, listener)</code> method.</p> -<p>It takes two parameters:</p> -<ul> - <li> - <p><strong><code>type</code></strong>: the type of event we are interested in, identified by a string. Many event emitters may emit more than one type of event: for example, a browser window might emit both <code>open</code> and <code>close</code> events. The list of valid event types is specific to an event emitter and is included with its documentation.</p> - </li> - <li> - <p><strong><code>listener</code></strong>: the listener itself. This is a function which will be called whenever the event occurs. The arguments that will be passed to the listener are specific to an event type and are documented with the event emitter.</p> - </li> -</ul> -<p>For example, the following add-on registers a listener with the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> module to listen for the <code>ready</code> event, and logs a string to the console reporting the event:</p> -<pre class="brush: js">var tabs = require("sdk/tabs"); - -tabs.on("ready", function () { - console.log("tab loaded"); -}); -</pre> -<p>It is not possible to enumerate the set of listeners for a given event.</p> -<p>The value of <code>this</code> in the listener function is the object that emitted the event.</p> -<h3 id="Listening_to_all_events">Listening to all events</h3> -<div class="note"> - <p>This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p> -</div> -<p>From Firefox 28 onwards, you can pass the wildcard "*" as the <code>type</code> argument. If you do this, the listener will be called for any event emitted by that object, and its argument will be the name of the event:</p> -<pre class="brush: js">var ui = require('sdk/ui'); -var panels = require("sdk/panel"); -var self = require("sdk/self"); - -var panel = panels.Panel({ - contentURL: self.data.url("panel.html") -}); - -panel.on("*", function(e) { - console.log("event " + e + " was emitted"); -}); - -var button = ui.ActionButton({ - id: "my-button", - label: "my button", - icon: "./icon-16.png", - onClick: handleClick -}); - -function handleClick(state) { - panel.show({ - position: button - }); -}</pre> -<p>This wildcard feature does not yet work for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>windows</code></a> modules.</p> -<h3 id="Adding_Listeners_in_Constructors">Adding Listeners in Constructors</h3> -<p>Event emitters may be modules, as is the case for the <code>ready</code> event above, or they may be objects returned by constructors.</p> -<p>In the latter case the <code>options</code> object passed to the constructor typically defines properties whose names are the names of supported event types prefixed with "on": for example, "onOpen", "onReady" and so on. Then in the constructor you can assign a listener function to this property as an alternative to calling the object's <code>on()</code> method.</p> -<p>For example: the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action"><code>ActionButton</code></a> object emits an event when the button is clicked.</p> -<p>The following add-on creates a button and assigns a listener to the <code>onClick</code> property of the <code>options</code> object supplied to the button's constructor. The listener loads https://developer.mozilla.org/:</p> -<pre class="brush: js">require("sdk/ui/button/action").ActionButton({ - id: "visit-mozilla", - label: "Visit Mozilla", - icon: "./icon-16.png", - onClick: function() { - require("sdk/tabs").open("https://developer.mozilla.org/"); - } -}); -</pre> -<p>This is exactly equivalent to constructing the button and then calling the button's <code>on()</code> method:</p> -<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({ - id: "visit-mozilla", - label: "Visit Mozilla", - icon: "./icon-16.png" -}); - -button.on("click", function() { - require("sdk/tabs").open("https://developer.mozilla.org/"); -}); -</pre> -<h2 id="Removing_Event_Listeners">Removing Event Listeners</h2> -<p>Event listeners can be removed by calling <code>removeListener(type, listener)</code>, supplying the type of event and the listener to remove.</p> -<p>The listener must have been previously been added using one of the methods described above.</p> -<p>In the following add-on, we add two listeners to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready"><code>tabs</code> module's <code>ready</code> event</a>. One of the handler functions removes the listener again.</p> -<p>Then we open two tabs.</p> -<pre class="brush: js">var tabs = require("sdk/tabs"); - -function listener1() { - console.log("Listener 1"); - tabs.removeListener("ready", listener1); -} - -function listener2() { - console.log("Listener 2"); -} - -tabs.on("ready", listener1); -tabs.on("ready", listener2); - -tabs.open("https://www.mozilla.org"); -tabs.open("https://www.mozilla.org"); -</pre> -<p>We should see output like this:</p> -<pre>info: tabevents: Listener 1 -info: tabevents: Listener 2 -info: tabevents: Listener 2 -</pre> -<p>Listeners will be removed automatically when the add-on is unloaded.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html deleted file mode 100644 index bbde3e418f..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: base64 -slug: Mozilla/Add-ons/SDK/High-Level_APIs/base64 -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/base64 ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>不稳定</p> -</div> - -<p>使用Base64算法编码和解码数据</p> - -<pre class="brush: js">var base64 = require("sdk/base64"); - -var encodedData = base64.encode("Hello, World");//"SGVsbG8sIFdvcmxk" -var decodedData = base64.decode(encodedData);//"Hello, World"</pre> - -<h2 id="Globals">Globals</h2> - -<h3 id="函数">函数</h3> - -<h4 class="addon-sdk-api-name" id="encode(data_charset)"><code>encode(data, charset)</code></h4> - -<p>将数据编码成ASCII的Base64字符串。</p> - -<h5 id="参数">参数</h5> - -<p><strong>data : string</strong><br> - 需要被编码的字符串</p> - -<p><strong>charset : string</strong><br> - 字符串的编码字符集(可选)。唯一能接受的值<code>“UTF-8”</code>。为了进行编码和解码Unicode字符串,需要设置字符集参数:</p> - -<pre class="brush: js">var base64 = require("sdk/base64"); - -var encodedData = base64.encode(unicodeString, "utf-8"); -</pre> - -<h5 id="返回">返回</h5> - -<p><strong>string</strong> : 编码后的Base64字符串。</p> - -<h4 class="addon-sdk-api-name" id="decode(data_charset)"><code>decode(data, charset)</code></h4> - -<p>解码一个已使用base-64编码的数据字符串</p> - -<h5 id="参数_2">参数</h5> - -<p><strong>data : string</strong><br> - 需要被解码的字符串</p> - -<p><strong>charset : string</strong><br> - 字符串的编码字符集(可选)。唯一能接受的值<code>“UTF-8”</code>。为了进行编码和解码Unicode字符串,需要设置字符集参数:</p> - -<pre class="brush: js">var base64 = require("sdk/base64"); - -var decodedData = base64.decode(encodedData, "utf-8"); -</pre> - -<h5 id="返回_2">返回</h5> - -<p><strong>string</strong> : 解码后的字符串</p> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html deleted file mode 100644 index e56a9223cd..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: clipboard(剪贴板) -slug: Mozilla/Add-ons/SDK/High-Level_APIs/clipboard -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/clipboard ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>稳定版</p> -</div> - -<p><span class="seoSummary">操作系统剪贴板,设置或获取其内容</span></p> - -<h2 id="用法">用法</h2> - -<p>你可以选择性地设置将要获取或设置的内容的格式. 支持一下格式:</p> - -<ul> - <li><code>text</code> (纯文本)</li> - <li><code>html</code> (HTML标记语言)</li> - <li><code>image</code> (经过base-64编码过的png图片)</li> -</ul> - -<p>如果没有提供格式参数的话,剪贴板模块会自动检测。</p> - -<p>现在在Windows操作系统下,"image"格式并不支持透明度。</p> - -<h3 id="示例">示例</h3> - -<p>设置和获取剪贴板内容。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); -clipboard.set("Lorem ipsum dolor sit amet"); -var contents = clipboard.get();</pre> - -<p>将剪贴板内容设置为某些html。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); -clipboard.set("<blink>Lorem ipsum dolor sit amet</blink>", "html");</pre> - -<p>如果剪贴板内容中包含有html,则将其在新标签页中打开。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); -if (clipboard.currentFlavors.indexOf("html") != -1) - require("sdk/tabs").open("data:text/html;charset=utf-8," + clipboard.get("html"));</pre> - -<p>将剪贴板内容设置为一幅图片。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); -clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" + - "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" + - "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" + - "bWRR9AAAAABJRU5ErkJggg%3D%3D");</pre> - -<p>如果剪贴板内容中包含图片,则将其在新标签页中打开。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); -if (clipboard.currentFlavors.indexOf("image") != -1) - require("sdk/tabs").open(clipboard.get());</pre> - -<p>如前所述,图片的参数类型很容易被忽略,例如在网页中选中复制一张图片,得到的格式会是html而不是所预期的image。如果你是想将剪贴板的内容设置成像data URL这样的文本字符串而不是图片的话,可以通过将格式设置为text实现。</p> - -<pre class="brush: js">var clipboard = require("sdk/clipboard"); - -clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" + - "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" + - "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" + - "bWRR9AAAAABJRU5ErkJggg%3D%3D", "text");</pre> - -<h2 id="Globals">Globals</h2> - -<h3 id="函数">函数</h3> - -<h4 class="addon-sdk-api-name" id="set(data_datatype)"><code>set(data, datatype)</code></h4> - -<p>将用户剪贴板上的内容用data替换。</p> - -<h5 id="参数">参数</h5> - -<p><strong>data : string</strong><br> - 要放入剪贴板的内容。</p> - -<p><strong>datatype : string</strong><br> - 内容的格式 ,为"text"或"html" 或 "image"。可选参数.</p> - -<h4 class="addon-sdk-api-name" id="get(datatype)"><code>get(datatype)</code></h4> - -<p>获取用户当前剪贴板的内容。</p> - -<h5 id="参数_2">参数</h5> - -<p><strong>datatype : string</strong><br> - 只有当剪贴板中的内容格式为datatype指定的格式时才获取 (可选).。当剪贴板中的内容非所提供的datatype指定的格式时,函数回返回null。</p> - -<h3 id="属性">属性</h3> - -<h4 class="addon-sdk-api-name" id="currentFlavors"><code>currentFlavors</code></h4> - -<p>剪贴板上的内容有时会是多种格式。例如,HTML内容即能匹配HTML格式(html),又能匹配纯文本格式(text)。这个属性为一个数组,数组中的元素是剪贴板内容所匹配的所有格式,如["text","html"]。</p> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html deleted file mode 100644 index d0d7bd569a..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: High-Level APIs -slug: Mozilla/Add-ons/SDK/High-Level_APIs -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs ---- -<p>{{AddonSidebar}}</p> - -<p>此页面列出的模块使用的是高级的API:创建用户界面,与网络进行交互并与浏览器交互。</p> - -<p>除非文件明确说明,否则这些API是稳定的,我们避免做出不兼容的改变。 - -{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/High-Level_APIs", 5) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html deleted file mode 100644 index 415450dca7..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: notifications(通知) -slug: Mozilla/Add-ons/SDK/High-Level_APIs/notifications -tags: - - Add-on SDK - - 通知 -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/notifications ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>Stable</p> -</div> - -<p><span class="seoSummary">向用户展示短暂的 <a href="http://en.wikipedia.org/wiki/Toast_%28computing%29">toaster</a> 风格的桌面消息。</span></p> - -<h2 id="用法">用法</h2> - -<p>本 API 支持Windows、使用<a href="http://growl.info/">Growl</a>(或者像OS X 10.9 Mavericks那样的通知中心)的 OS X 的桌面通知,以及使用 libnotify 的Linux系统</p> - -<p>这儿有个典型的例子。当消息被点击,控制台上回记录一个字符串。</p> - -<pre class="brush: js">var notifications = require("sdk/notifications"); -notifications.notify({ - title: "Jabberwocky", - text: "'Twas brillig, and the slithy toves", - data: "did gyre and gimble in the wabe", - onClick: function (data) { - console.log(data); - // console.log(this.data) would produce the same result. - } -}); -</pre> - -<p>下面这个示例用来展示一个保存在 add-on 的 <code>data</code> 目录下的图标。参看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> 模块文档以获取更多信息。</p> - -<pre class="brush: js">var notifications = require("sdk/notifications"); -var self = require("sdk/self"); -var myIconURL = self.data.url("myIcon.png"); - -notifications.notify({ - text: "I have an icon!", - iconURL: myIconURL -});</pre> - -<div class="note"> -<p>从 Firefox 34 起,你能使用 <code>"./myIcon.png"</code> 作为 <code>self.data.url("myIcon.png")</code> 的别名。所以你也可以把上面的代码重写成这样:</p> - -<pre class="brush: js">var notifications = require("sdk/notifications"); -var myIconURL = "./myIcon.png"; - -notifications.notify({ - text: "I have an icon!", - iconURL: myIconURL -});</pre> -</div> - -<p>本模块依赖于底层系统的通知服务。如果用户的系统不支持桌面通知或者通知服务没有运行:</p> - -<ul> - <li>如果 Firefox 正常运行,通知会记录在 Firefox 的错误控制台</li> - <li>如果用户从命令行启动 Firefox,通知会记录到终端。</li> -</ul> - -<h2 id="Globals">Globals</h2> - -<h3 id="函数">函数</h3> - -<h4 class="addon-sdk-api-name" id="notify(options)"><code>notify(options)</code></h4> - -<p>向用户展示一个短暂的通知</p> - -<h5 id="参数">参数</h5> - -<p><strong>options : object</strong><br> - 可选项:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>title</td> - <td>string</td> - <td> - <p>作为消息标题的字符串。</p> - </td> - </tr> - <tr> - <td>text</td> - <td>作为消息体的字符串。</td> - <td> - <p> </p> - </td> - </tr> - <tr> - <td>iconURL</td> - <td>string</td> - <td> - <p>消息里的图标的 URL 。可以是个远程的、本地的或者使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> 模块的 URL。</p> - </td> - </tr> - <tr> - <td>onClick</td> - <td>function</td> - <td> - <p>用户点击消息是调用的函数。它会传递一个 <code>data</code> 值。</p> - </td> - </tr> - <tr> - <td>data</td> - <td>string</td> - <td> - <p>传递给 <code>onClick</code> 的字符串。</p> - </td> - </tr> - </tbody> -</table> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html deleted file mode 100644 index 3a86fb0c61..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html +++ /dev/null @@ -1,899 +0,0 @@ ---- -title: panel -slug: Mozilla/Add-ons/SDK/High-Level_APIs/panel -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/panel ---- -<div class="note"> -<p>稳定版本</p> -</div> - -<p><span class="seoSummary">创建临时的 add-on's 用户界面对话框.</span></p> - -<h2 id="用法">用法</h2> - -<p>该模块导出了一个单独的构造函数函数 <code>Panel()</code> 构建一个Panel对话框 .</p> - -<p>面板是一个对话框。其内容是指定的HTML,你可以在它执行脚本,所以面板的外观和行为是有限的只有你可以使用HTML,CSS,JavaScript。</p> - -<p>下面的截图显示了一个面板,其内容是从当前打开的选项卡的列表中构建的:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6595/panel-tabs-osx.png" style="display: block; height: 238px; margin-left: auto; margin-right: auto; width: 307px;"></p> - -<p>面板是呈现临时用户界面中容易忽视和解聘的用户比模态对话框的方式,是有用的,因为面板隐藏瞬间用户交互部分的应用程序接口外。</p> - -<p><br> - 面板的内容加载快作为它是创建,面板显示之前,和内容仍然加载时面板是隐藏的,所以它是可能保持面板周围的背景,更新其内容适当地准备下一次显示。</p> - -<p><br> - 您的插件可以接收通知,当面板显示或隐藏通过听其显示和隐藏事件。<br> - 打开面板将关闭已打开的面板。</p> - -<h3 id="Panel_内容">Panel 内容</h3> - -<p>该面板的内容指定为HTML,它是在contenturl选项面板的构造函数提供的URL加载。</p> - -<p><br> - 你可以加载远程HTML到面板:</p> - -<pre class="brush: js">var panel = require("sdk/panel").Panel({ - width: 180, - height: 180, - contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile" -}); - -panel.show();</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6597/wikipedia-jetpack-panel.png" style="display: block; height: 411px; margin-left: auto; margin-right: auto; width: 494px;"></p> - -<p>你也可以加载HTML已经打包你的 add-on,这可能是你将如何创建对话框。要做到这一点,在你的 add-on 的 <em><strong>data </strong></em>目录中保存的HTML 和加载使用 <strong><em><code>data.url()</code></em></strong>方法,由 <em><strong><a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a></strong></em> 模块导出, 像下面:</p> - -<pre class="brush: js">var panel = require("sdk/panel").Panel({ - contentURL: require("sdk/self").data.url("myFile.html") -}); - -panel.show();</pre> - -<div class="note"> -<p>从Firefox 34以后, 你可以使用 <code>"./myFile.html" 作为</code><code>self.data.url("myFile.html")</code> 的<code>别名</code>. 所以你可以重写成下面的示例:</p> - -<pre class="brush: js">var panel = require("sdk/panel").Panel({ - contentURL: "./myFile.html" -}); - -panel.show(); -</pre> -</div> - -<h3 id="Panel_positioning">Panel positioning</h3> - -<p>By default the panel appears in the center of the currently active browser window. You can position the panel by passing a <code>position</code> to the panel's <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)">constructor</a> or to its <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a> method.</p> - -<h3 id="Attaching_panels_to_buttons">Attaching panels to buttons</h3> - -<p>You can attach a panel to a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">toggle button</a> by passing the button itself as the <code>position</code> option to the panel's <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a> method or to its constructor:</p> - -<pre class="brush: js">var { ToggleButton } = require('sdk/ui/button/toggle'); -var panels = require("sdk/panel"); -var self = require("sdk/self"); - -var button = ToggleButton({ - id: "my-button", - label: "my button", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onChange: handleChange -}); - -var panel = panels.Panel({ - contentURL: self.data.url("panel.html"), - onHide: handleHide -}); - -function handleChange(state) { - if (state.checked) { - panel.show({ - position: button - }); - } -} - -function handleHide() { - button.state('window', {checked: false}); -}</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7615/panel-button.png" style="display: block; height: 332px; margin-left: auto; margin-right: auto; width: 397px;"></p> - -<h3 id="Updating_panel_content">Updating panel content</h3> - -<p>You can update the panel's content by:</p> - -<ul> - <li>sending a message to a content script that updates the DOM in the same document. This is usually the best approach.</li> - <li>embedding an <a href="/en-US/docs/Web/HTML/Element/iframe">iframe</a> in the panel, and changing its document</li> - <li>setting the panel's <code>contentURL</code> property. However, doing this will cause any content scripts to be unloaded and then reloaded, so it may be less efficient, and you'll lose any state associated with the scripts.</li> -</ul> - -<h3 id="Scripting_panel_content">Scripting panel content</h3> - -<p>You can't directly access your panel's content from your main add-on code. To access the panel's content, you need to load a script into the panel. In the SDK these scripts are called "content scripts" because they're explicitly used for interacting with web content.</p> - -<p>While content scripts can access the content they're attached to, they can't use the SDK's APIs. So implementing a complete solution usually means you have to send messages between the content script and the main add-on code.</p> - -<ul> - <li> - <p>You can specify one or more content scripts to load into a panel using the <code>contentScript</code> or <code>contentScriptFile</code> options to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)"><code>Panel()</code> constructor</a>.</p> - </li> - <li> - <p>You can communicate with the script using either the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or (preferably, usually) the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API.</p> - </li> -</ul> - -<p>For example, here's an add-on whose content script intercepts mouse clicks on links inside the panel, and sends the target URL to the main add-on code. The content script sends messages using <code>self.port.emit()</code> and the add-on script receives them using <code>panel.port.on()</code>.</p> - -<pre class="brush: js">var myScript = "window.addEventListener('click', function(event) {" + - " var t = event.target;" + - " if (t.nodeName == 'A')" + - " self.port.emit('click-link', t.toString());" + - "}, false);" - -var panel = require("sdk/panel").Panel({ - contentURL: "http://www.bbc.co.uk/mobile/index.html", - contentScript: myScript -}); - -panel.port.on("click-link", function(url) { - console.log(url); -}); - -panel.show();</pre> - -<p>This example uses <code>contentScript</code> to supply the script as a string. It's usually better practice to use <code>contentScriptFile</code>, which is a URL pointing to a script file saved under your add-on's <code>data</code> directory.</p> - -<div class="warning"> -<p><strong>Warning:</strong> Unless your content script is extremely simple and consists only of a static string, don't use <code>contentScript</code>: if you do, you may have problems getting your add-on approved on AMO.</p> - -<p>Instead, keep the script in a separate file and load it using <code>contentScriptFile</code>. This makes your code easier to maintain, secure, debug and review.</p> -</div> - -<h3 id="Getting_user_input">Getting user input</h3> - -<div class="note"> -<p><strong>Note:</strong> This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p> -</div> - -<p>The following add-on adds a button which displays a panel when clicked. The panel just contains a {{HTMLElement("textarea")}} element: when the user presses the <code>return</code> key, the contents of the <code><textarea></code> is sent to the main add-on code.</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7647/panel.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<p>The add-on consists of six files:</p> - -<ul> - <li><code>main.js</code>: the main add-on code, that creates the button and panel</li> - <li><code>get-text.js</code>: the content script that interacts with the panel content</li> - <li><code>text-entry.html</code>: the panel content itself, specified as HTML</li> - <li><code>icon-16.png</code>, <code>icon-32.png</code>, and <code>icon-64.png</code>: icons for the button in three different sizes</li> -</ul> - -<p>"main.js" is saved in your add-on's <code>lib</code> directory, and the other files go in your add-on's <code>data</code> directory:</p> - -<pre>my-addon/ - data/ - get-text.js - icon-16.png - icon-32.png - icon-64.png - text-entry.html - lib/ - main.js -</pre> - -<p>The "main.js" looks like this:</p> - -<pre class="brush: js">var data = require("sdk/self").data; -// Construct a panel, loading its content from the "text-entry.html" -// file in the "data" directory, and loading the "get-text.js" script -// into it. -var text_entry = require("sdk/panel").Panel({ - contentURL: data.url("text-entry.html"), - contentScriptFile: data.url("get-text.js") -}); - -// Create a button -require("sdk/ui/button/action").ActionButton({ - id: "show-panel", - label: "Show Panel", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -// Show the panel when the user clicks the button. -function handleClick(state) { - text_entry.show(); -} - -// When the panel is displayed it generated an event called -// "show": we will listen for that event and when it happens, -// send our own "show" event to the panel's script, so the -// script can prepare the panel for display. -text_entry.on("show", function() { - text_entry.port.emit("show"); -}); - -// Listen for messages called "text-entered" coming from -// the content script. The message payload is the text the user -// entered. -// In this implementation we'll just log the text to the console. -text_entry.port.on("text-entered", function (text) { - console.log(text); - text_entry.hide(); -});</pre> - -<p>The content script "get-text.js" looks like this:</p> - -<pre class="brush: js">// When the user hits return, send the "text-entered" -// message to main.js. -// The message payload is the contents of the edit box. -var textArea = document.getElementById("edit-box"); -textArea.addEventListener('keyup', function onkeyup(event) { - if (event.keyCode == 13) { - // Remove the newline. - text = textArea.value.replace(/(\r\n|\n|\r)/gm,""); - self.port.emit("text-entered", text); - textArea.value = ''; - } -}, false); -// Listen for the "show" event being sent from the -// main add-on code. It means that the panel's about -// to be shown. -// -// Set the focus to the text area so the user can -// just start typing. -self.port.on("show", function onShow() { - textArea.focus(); -});</pre> - -<p>Finally, the "text-entry.html" file defines the <code><textarea></code> element:<code> </code></p> - -<pre class="brush: html"><html> -<head> - <style type="text/css" media="all"> - textarea { - margin: 10px; - } - body { - background-color: gray; - } - </style> - </head> -<body> - <textarea rows="13" cols="33" id="edit-box"></textarea> - </body> -</html></pre> - -<p>Finally, save these three icon files to the "data" directory:</p> - -<table class="standard-table"> - <tbody> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td> - <td>icon-16.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td> - <td>icon-32.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td> - <td>icon-64.png</td> - </tr> - </tbody> -</table> - -<p>To learn much more about content scripts, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p> - -<h3 id="Scripting_trusted_panel_content">Scripting trusted panel content</h3> - -<div class="note"> -<p><strong>Note:</strong> This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p> -</div> - -<p>We've already seen that you can package HTML files in your add-on's <code>data</code> directory and use them to define the panel's content. We can call this "trusted" content, because unlike content loaded from a source outside the add-on, the add-on author knows exactly what it's doing. To interact with trusted content you don't need to use content scripts: you can just include a script from the HTML file in the normal way, using <code>script</code> tags.</p> - -<p>Like a content script, these scripts can communicate with the add-on code using the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API. The crucial difference is that these scripts access the <code>postMessage</code> and <code>port</code> objects through the <code>addon</code> object, whereas content scripts access them through the <code>self</code> object.</p> - -<p>To show the difference, we can easily convert the <code>text-entry</code> add-on above to use normal page scripts instead of content scripts.</p> - -<p>The main add-on code is exactly the same as the main add-on code in the previous example, except that we don't attach a content script:</p> - -<pre class="brush: js">var data = require("sdk/self").data; -// Construct a panel, loading its content from the "text-entry.html" -// file in the "data" directory, and loading the "get-text.js" script -// into it. -var text_entry = require("sdk/panel").Panel({ - contentURL: data.url("text-entry.html") -}); - -// Create a button -require("sdk/ui/button/action").ActionButton({ - id: "show-panel", - label: "Show Panel", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -// Show the panel when the user clicks the button. -function handleClick(state) { - text_entry.show(); -} - -// When the panel is displayed it generated an event called -// "show": we will listen for that event and when it happens, -// send our own "show" event to the panel's script, so the -// script can prepare the panel for display. -text_entry.on("show", function() { - text_entry.port.emit("show"); -}); - -// Listen for messages called "text-entered" coming from -// the content script. The message payload is the text the user -// entered. -// In this implementation we'll just log the text to the console. -text_entry.port.on("text-entered", function (text) { - console.log(text); - text_entry.hide(); -});</pre> - -<p>The page script is exactly the same as the content script above, except that instead of <code>self</code>, we use <code>addon</code> to access the messaging APIs:</p> - -<pre class="brush: js">// When the user hits return, send the "text-entered" -// message to main.js. -// The message payload is the contents of the edit box. -var textArea = document.getElementById("edit-box"); -textArea.addEventListener('keyup', function onkeyup(event) { - if (event.keyCode == 13) { - // Remove the newline. - text = textArea.value.replace(/(\r\n|\n|\r)/gm,""); - addon.port.emit("text-entered", text); - textArea.value = ''; - } -}, false); -// Listen for the "show" event being sent from the -// main add-on code. It means that the panel's about -// to be shown. -// -// Set the focus to the text area so the user can -// just start typing. -addon.port.on("show", function onShow() { - textArea.focus(); -});</pre> - -<p>Finally, the HTML file now references "get-text.js" inside a {{HTMLElement("script")}} tag:</p> - -<pre class="brush: html"><html> -<head> - <style type="text/css" media="all"> - textarea { - margin: 10px; - } - body { - background-color: gray; - } - </style> - </head> - <body> - <script src="get-text.js"></script> - <textarea rows="13" cols="33" id="edit-box"></textarea> - </body> -</html> -</pre> - -<h3 id="Styling_panel_content">Styling panel content</h3> - -<p>The panel's default style is different for each operating system:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/8001/panel-styles-os.png" style="display: block; margin-left: auto; margin-right: auto;">This helps to ensure that the panel's style is consistent with the dialogs displayed by Firefox and other applications, but means you need to take care when applying your own styles.</p> - -<p>If the panel's content is packaged along with your add-on and specified using an HTML file in your <code>data</code> directory, you can style it by embedding CSS directly in the HTML file or by referencing a CSS file stored under <code>data</code>:</p> - -<pre class="brush: html"><!DOCTYPE HTML> -<html> - <head> - <link href="panel-style.css" type="text/css" rel="stylesheet"> - </head> - <body> - My panel content - </body> -</html></pre> - -<p>From Firefox 31 onwards, you can style panel content using the <code>contentStyle</code> or <code>contentStyleFile</code> options. You can use these options even if the panel content is not packaged along with the add-on:</p> - -<pre class="brush: js">var panel = require("sdk/panel").Panel({ - contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile", - contentStyle: "body { border: 3px solid blue; }" -}); - -panel.show();</pre> - -<pre class="brush: js">var self = require("sdk/self"); - -var panel = require("sdk/panel").Panel({ - contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile", - contentStyleFile: self.data.url("panel-style.css") -}); - -panel.show();</pre> - -<h3 id="Private_browsing">Private browsing</h3> - -<p>If your add-on has not <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">opted into private browsing</a>, and it calls <code>panel.show()</code> when the currently active window is a <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing#Per-window_private_browsing">private window</a>, then the panel will not be shown.</p> - -<h3 id="Panel_limitations">Panel limitations</h3> - -<p>Although panels can host HTML documents, they are not implemented as browser tabs, so many things that work in normal web pages do not work inside panels:</p> - -<ul> - <li>Prior to Firefox 33, you don't get a context menu. From Firefox 33 you can enable a context menu by passing <code>contextMenu: true</code> to the panel's constructor.</li> - <li>The HTML {{HTMLElement("select")}} element doesn't work.</li> - <li>The HTML {{HTMLElement("datalist")}} element doesn't give you autocomplete suggestions (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=918600">bug 918600</a>).</li> - <li>You can't embed Flash (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=952578">bug 952578</a>).</li> - <li>You can't provide tooltips using <a href="/en-US/docs/Web/HTML/Global_attributes#attr-title"><code>title</code> attributes</a> (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=918600">bug 918600</a>).</li> - <li>Security warning pages (the <a href="https://support.mozilla.org/en-US/kb/connection-untrusted-error-message">"This Connection is Untrusted" warning</a>) does not work, so panels which trigger it will be broken (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1031554">bug 1031554</a>).</li> - <li>Mouse button shortcuts, such as using the middle button to open a link in a new page, don't work.</li> - <li>Scrolling using keyboard doesn't work properly (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1001914">bug 1001914</a>)</li> -</ul> - -<h2 id="Globals">Globals</h2> - -<h3 id="Constructors">Constructors</h3> - -<h4 class="addon-sdk-api-name" id="Panel(options)"><code>Panel(options)</code></h4> - -<p>Creates a panel.</p> - -<h5 id="Parameters">Parameters</h5> - -<p><strong>options : object</strong><br> - Optional options:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td><code>width</code></td> - <td>number</td> - <td> - <p>The width of the panel in pixels. Optional.</p> - </td> - </tr> - <tr> - <td><code>height</code></td> - <td>number</td> - <td> - <p>The height of the panel in pixels. Optional.</p> - </td> - </tr> - <tr> - <td><code>position</code></td> - <td> - <p>object, button, widget</p> - </td> - <td> - <p>The position of the panel. Ignored if the panel is opened by a widget.</p> - - <p>This may be one of three things:</p> - - <ul> - <li>a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">toggle button</a>. If this is supplied the panel will be shown attached to the button. See the section on <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Attaching_panels_to_buttons">attaching panels to buttons</a>.</li> - <li>a <a href="/en-US/Add-ons/SDK/High-Level_APIs/widget">widget</a> object. If this is supplied the panel will be shown attached to the widget.</li> - <li>an object which specifies where in the window the panel should be shown. The rest of this section describes this object.</li> - </ul> - - <p>The position object has one or more of the following properties: <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code>. Their values are expressed in pixels. Any other properties will be ignored.</p> - - <p>The default alignment along each axis is centered: so to display a panel centred along the vertical or horizontal axis, just omit that axis:</p> - - <pre class="brush: js"> -// Show the panel centered horizontally and -// aligned to the bottom of the content area -require("sdk/panel").Panel({ - position: { - bottom: 0 - } -}).show(); - -// Show the panel centered vertically and -// aligned to the left of the content area -require("sdk/panel").Panel({ - position: { - left: 0 - } -}).show(); - -// Centered panel, default behavior -require("sdk/panel").Panel({}).show();</pre> - - <p>As with the CSS <code>top</code>, <code>bottom</code>, <code>left</code>, and <code>right</code> properties, setting both <code>top</code> and <code>bottom</code> or both <code>left</code> and <code>right</code> will implicitly set the panel's <code>height</code> or <code>width</code> relative to the content window:</p> - - <pre class="brush: js"> -// Show the panel centered horizontally, with: -// - the top edge 40px from the top -// of the content window -// - the bottom edge 100px from the bottom -// of the content window -require("sdk/panel").Panel({ - position: { - top: 40, - bottom: 100 - } -}).show();</pre> - - <p>If you set both <code>top</code> and <code>bottom</code>, but also set the panel's height explicitly using the <code>height</code> property, then the panel will ignore <code>bottom</code>, just as CSS does for its properties with the same name:</p> - - <pre class="brush: js"> -// Show the panel centered horizontally, with: -// - the top edge 40px from the top -// of the content window -// - a height of 400px -require("sdk/panel").Panel({ - position: { - top: 40, - bottom: 100, - }, - height: 400 -}).show(); - -// This is equivalent to: - -require("panel").Panel({ - position { - top: 40 - }, - height: 400 -}).show();</pre> - - <p>The same principle is applied in the horizontal axis with <code>width</code>, <code>left</code> and <code>right</code>.</p> - </td> - </tr> - <tr> - <td><code>focus</code></td> - <td>boolean</td> - <td> - <p>Set to <code>false</code> to prevent taking the focus away when the panel is shown. Only turn this off if necessary, to prevent accessibility issue. Optional, default to <code>true</code>.</p> - </td> - </tr> - <tr> - <td><code>contentURL</code></td> - <td>string,URL</td> - <td> - <p>The URL of the content to load in the panel. That is, they can't refer to remote scripts. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p> - - <div class="note"> - <p>From Firefox 34, you can use <code>"./my-file.html"</code> as an alias for <code>self.data.url("my-<code>file.html</code>")</code>.</p> - </div> - </td> - </tr> - <tr> - <td><code>allow</code></td> - <td>object</td> - <td> - <p>An optional object describing permissions for the content. It should contain a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content. <code>script</code> defaults to true.</p> - </td> - </tr> - <tr> - <td><code>contentScriptFile</code></td> - <td>string,array</td> - <td> - <p>A URL or an array of URLs. The URLs point to scripts to load into the panel.</p> - - <p>The scripts must be packaged with the add-on under the add-on's <code>data</code> directory. That is, they can't refer to remote scripts. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p> - - <div class="note"> - <p>From Firefox 34, you can use <code>"./my-script.js"</code> as an alias for <code>self.data.url("my-script.js")</code>.</p> - </div> - - <p>Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p> - </td> - </tr> - <tr> - <td><code>contentScript</code></td> - <td>string,array</td> - <td> - <p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p> - </td> - </tr> - <tr> - <td><code>contentStyleFile</code></td> - <td>string, array</td> - <td> - <p>A URL or an array of URLs. The URLs point to CSS stylesheets to load into the panel.</p> - - <p>The stylesheets must be packaged with the add-on under the add-on's <code>data</code> directory. That is, they can't refer to remote stylesheets. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p> - - <p>Stylesheets specified by this property are loaded <em>before</em> those specified by the <code>contentStyle</code> property.</p> - </td> - </tr> - <tr> - <td><code>contentStyle</code></td> - <td>string, array</td> - <td> - <p>A string or an array of strings containing the texts of stylesheets to load. Stylesheets specified by this property are loaded <em>after</em> those specified by the <code>contentStyleFile</code> property.</p> - </td> - </tr> - <tr> - <td><code>contentScriptWhen</code></td> - <td>string</td> - <td> - <p>When to load the content scripts. This may take one of the following values:</p> - - <ul> - <li>"start": load content scripts immediately after the document element for the panel is inserted into the DOM, but before the DOM content itself has been loaded</li> - <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li> - <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the panel has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li> - </ul> - - <p>This property is optional and defaults to "end".</p> - </td> - </tr> - <tr> - <td><code>contentScriptOptions</code></td> - <td>object</td> - <td> - <p>Read-only value exposed to content scripts under <code>addon.options</code> property.</p> - - <p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p> - </td> - </tr> - <tr> - <td><code>contextMenu</code></td> - <td>boolean</td> - <td> - <div class="geckoVersionNote"> - <p>New in Firefox 33</p> - </div> - - <p>Whether to show a context menu when the user context-clicks in the panel. The context menu will be the same one that's displayed in web pages. Optional, defaults to <code>false</code>.</p> - </td> - </tr> - <tr> - <td><code>onMessage</code></td> - <td>function</td> - <td> - <p>Include this to listen to the panel's <code>message</code> event.</p> - </td> - </tr> - <tr> - <td><code>onShow</code></td> - <td>function</td> - <td> - <p>Include this to listen to the panel's <code>show</code> event.</p> - </td> - </tr> - <tr> - <td><code>onHide</code></td> - <td>function</td> - <td> - <p>Include this to listen to the panel's <code>hide</code> event.</p> - </td> - </tr> - </tbody> -</table> - -<h2 id="Panel">Panel</h2> - -<p>The Panel object represents a floating modal dialog that can by an add-on to present user interface content.</p> - -<p>Once a panel object has been created it can be shown and hidden using its <code>show()</code> and <code>hide()</code> methods. Once a panel is no longer needed it can be deactivated using <code>destroy()</code>.</p> - -<p>The content of a panel is specified using the <code>contentURL</code> option. An add-on can interact with the content of a panel using content scripts which it supplies in the <code>contentScript</code> and/or <code>contentScriptFile</code> options. For example, a content script could create a menu and send the user's selection to the add-on.</p> - -<h3 id="Methods">Methods</h3> - -<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4> - -<p>Destroys the panel, unloading any content that was loaded in it. Once destroyed, the panel can no longer be used. If you just want to hide the panel and might show it later, use <code>hide</code> instead.</p> - -<h4 class="addon-sdk-api-name" id="postMessage(message)"><code>postMessage(message)</code></h4> - -<p>Sends a message to the content scripts.</p> - -<h5 id="Parameters_2">Parameters</h5> - -<p><strong>message : value</strong><br> - The message to send. Must be stringifiable to JSON.</p> - -<h4 class="addon-sdk-api-name" id="show(options)"><code>show(options)</code></h4> - -<p>Displays the panel.</p> - -<p>If the <code>options</code> argument is given, it will be shallow merged with the options provided in the constructor: the <code>options</code> passed in the <code>show</code> method takes precedence.</p> - -<p>Passing options here is useful for making temporary changes without touching the default values.</p> - -<h5 id="Parameters_3">Parameters</h5> - -<p><strong>options : object</strong><br> - Optional options:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>width</td> - <td>number</td> - <td> - <p>The width of the panel in pixels. Optional.</p> - </td> - </tr> - <tr> - <td>height</td> - <td>number</td> - <td> - <p>The height of the panel in pixels. Optional.</p> - </td> - </tr> - <tr> - <td>position</td> - <td>object</td> - <td> - <p>The position of the panel. Optional. See <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)">Panel's options</a> for further details.</p> - </td> - </tr> - <tr> - <td>focus</td> - <td>boolean</td> - <td> - <p>Set to <code>false</code> to prevent taking the focus away when the panel is shown.</p> - </td> - </tr> - </tbody> -</table> - -<h4 class="addon-sdk-api-name" id="hide()"><code>hide()</code></h4> - -<p>Stops displaying the panel.</p> - -<h4 class="addon-sdk-api-name" id="resize(width_height)"><code>resize(width, height)</code></h4> - -<p>Resizes the panel.</p> - -<h5 id="Parameters_4">Parameters</h5> - -<p><strong>width : number</strong><br> - The new width of the panel in pixels.</p> - -<p><strong>height : number</strong><br> - The new height of the panel in pixels.</p> - -<h4 class="addon-sdk-api-name" id="on(type_listener)"><code>on(type, listener)</code></h4> - -<p>Registers an event listener with the panel.</p> - -<h5 id="Parameters_5">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event to listen for.</p> - -<p><strong>listener : function</strong><br> - The listener function that handles the event.</p> - -<h4 class="addon-sdk-api-name" id="removeListener(type_listener)"><code>removeListener(type, listener)</code></h4> - -<p>Unregisters an event listener from the panel.</p> - -<h5 id="Parameters_6">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event for which <code>listener</code> was registered.</p> - -<p><strong>listener : function</strong><br> - The listener function that was registered.</p> - -<h3 id="Properties">Properties</h3> - -<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4> - -<p>EventEmitter object that allows you to:</p> - -<ul> - <li>send events to the content script using the <code>port.emit</code> function</li> - <li>receive events from the content script using the <code>port.on</code> function</li> -</ul> - -<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p> - -<h4 class="addon-sdk-api-name" id="isShowing"><code>isShowing</code></h4> - -<p>Tells if the panel is currently shown or not. This property is read-only.</p> - -<h4 class="addon-sdk-api-name" id="height"><code>height</code></h4> - -<p>The height of the panel in pixels.</p> - -<h4 class="addon-sdk-api-name" id="width"><code>width</code></h4> - -<p>The width of the panel in pixels.</p> - -<h4 class="addon-sdk-api-name" id="focus"><code>focus</code></h4> - -<p>Whether or not focus will be taken away when the panel is shown. This property is read-only.</p> - -<h4 class="addon-sdk-api-name" id="contentURL"><code>contentURL</code></h4> - -<p>The URL of content loaded into the panel. This can point to local content loaded from your add-on's "data" directory or remote content. Setting it updates the panel's content immediately.</p> - -<h4 class="addon-sdk-api-name" id="allow"><code>allow</code></h4> - -<p>An object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptFile"><code>contentScriptFile</code></h4> - -<p>A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p> - -<h4 class="addon-sdk-api-name" id="contentScript"><code>contentScript</code></h4> - -<p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptWhen"><code>contentScriptWhen</code></h4> - -<p>When to load the content scripts. This may have one of the following values:</p> - -<ul> - <li>"start": load content scripts immediately after the document element for the panel is inserted into the DOM, but before the DOM content itself has been loaded</li> - <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li> - <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the panel has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li> -</ul> - -<h4 class="addon-sdk-api-name" id="contentScriptOptions"><code>contentScriptOptions</code></h4> - -<p>Read-only value exposed to content scripts under <code>addon.options</code> property.</p> - -<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p> - -<h3 id="Events">Events</h3> - -<h4 class="addon-sdk-api-name" id="show"><code>show</code></h4> - -<p>This event is emitted when the panel is shown.</p> - -<h4 class="addon-sdk-api-name" id="hide"><code>hide</code></h4> - -<p>This event is emitted when the panel is hidden.</p> - -<h4 class="addon-sdk-api-name" id="message"><code>message</code></h4> - -<p>If you listen to this event you can receive message events from content scripts associated with this panel. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the panel's <code>message</code> event.</p> - -<h5 id="Arguments">Arguments</h5> - -<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p> - -<h4 class="addon-sdk-api-name" id="error"><code>error</code></h4> - -<p>This event is emitted when an uncaught runtime error occurs in one of the panel's content scripts.</p> - -<h5 id="Arguments_2">Arguments</h5> - -<p><strong>Error</strong> : Listeners are passed a single argument, the <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error">Error</a> object.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html deleted file mode 100644 index b85bb94ab3..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html +++ /dev/null @@ -1,669 +0,0 @@ ---- -title: tabs -slug: Mozilla/Add-ons/SDK/High-Level_APIs/tabs -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/tabs ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>Stable</p> -</div> - -<p><span class="seoSummary">打开、操作和访问标签页,以及接收标签页事件</span></p> - -<h2 id="用法">用法</h2> - -<h3 id="打开标签页">打开标签页</h3> - -<p>你可以注册事件监听器,以便在标签打开、关闭、完成DOM内容加载、被激活或被闲置时接收通知:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.open("http://www.example.com");</pre> - -<h3 id="跟踪标签页">跟踪标签页</h3> - -<p>You can register event listeners to be notified when tabs open, close, finish loading DOM content, or are made active or inactive:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); - -// Listen for tab openings. -tabs.on('open', function onOpen(tab) { - myOpenTabs.push(tab); -}); - -// Listen for tab content loads. -tabs.on('ready', function(tab) { - console.log('tab is loaded', tab.title, tab.url); -});</pre> - -<h3 id="访问标签页">访问标签页</h3> - -<p>The module itself can be used as a list of all opened tabs across all windows. In particular, you can enumerate it:</p> - -<pre class="brush: js">var tabs = require('sdk/tabs'); -for (let tab of tabs) - console.log(tab.title);</pre> - -<p>You can also access individual tabs by index:</p> - -<pre class="brush: js">var tabs = require('sdk/tabs'); - -tabs.on('ready', function () { - console.log('first: ' + tabs[0].title); - console.log('last: ' + tabs[tabs.length-1].title); -});</pre> - -<p>You can access the currently active tab:</p> - -<pre class="brush: js">var tabs = require('sdk/tabs'); - -tabs.on('activate', function () { - console.log('active: ' + tabs.activeTab.url); -});</pre> - -<h3 id="跟踪单个标签页">跟踪单个标签页</h3> - -<p>Given a tab, you can register event listeners to be notified when the tab is closed, activated or deactivated, or when the page hosted by the tab is loaded or retrieved from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">"back-forward cache"</a>:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); - -function onOpen(tab) { - console.log(tab.url + " is open"); - tab.on("pageshow", logShow); - tab.on("activate", logActivate); - tab.on("deactivate", logDeactivate); - tab.on("close", logClose); -} - -function logShow(tab) { - console.log(tab.url + " is loaded"); -} - -function logActivate(tab) { - console.log(tab.url + " is activated"); -} - -function logDeactivate(tab) { - console.log(tab.url + " is deactivated"); -} - -function logClose(tab) { - console.log(tab.url + " is closed"); -} - -tabs.on('open', onOpen);</pre> - -<h3 id="操作标签页">操作标签页</h3> - -<p>You can get and set various properties of tabs (but note that properties relating to the tab's content, such as the URL, will not contain valid values until after the tab's <code>ready</code> event fires). By setting the <code>url</code> property you can load a new page in the tab:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.on('activate', function(tab) { - tab.url = "http://www.example.com"; -});</pre> - -<h3 id="在标签页中运行脚本">在标签页中运行脚本</h3> - -<p>You can attach a <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content script</a> to the page hosted in a tab, and use that to access and manipulate the page's content (see the <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">Modifying the Page Hosted by a Tab</a> tutorial):</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); - -tabs.on('activate', function(tab) { - var worker = tab.attach({ - contentScript: 'self.port.emit("html", document.body.innerHTML);' - }); - worker.port.on("html", function(message) { - console.log(message) - }) -});</pre> - -<p>Note that <code>tab.attach</code> is tab-centric: if the user navigates to a new page in the same tab, then the worker and content scripts will be reattached to the new page.</p> - -<h3 id="附加样式表">附加样式表</h3> - -<div class="geckoVersionNote"> -<p>Firefox 34 新增。</p> -</div> - -<p>You can't attach style sheets to a tab using <code>tab.attach()</code>, but from Firefox 34 onwards you can attach and detach them using the low-level <a href="/en-US/Add-ons/SDK/Low-Level_APIs/stylesheet_style">stylesheet/style</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_mod">content/mod</a> APIs. Here's an add-on that uses a toggle button to attach a stylesheet to the active tab, and detach it again. The stylesheet is called "style.css" and is located in the add-on's "data" directory:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -var { attach, detach } = require('sdk/content/mod'); -var { Style } = require('sdk/stylesheet/style'); -var { ToggleButton } = require("sdk/ui/button/toggle"); - -var style = Style({ - uri: './style.css' -}); - -var button = ToggleButton({ - id: "stylist", - label: "stylist", - icon: "./icon-16.png", - onChange: function(state) { - if (state.checked) { - attach(style, tabs.activeTab); - } - else { - detach(style, tabs.activeTab); - } - } -});</pre> - -<h3 id="隐私窗口">隐私窗口</h3> - -<p>If your add-on has not opted into private browsing, then you won't see any tabs that are hosted by private browser windows.</p> - -<p>Tabs hosted by private browser windows won't be seen if you enumerate the <code>tabs</code> module itself, and you won't receive any events for them.</p> - -<p>To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">documentation for the <code>private-browsing</code> module</a>.</p> - -<h3 id="转为XUL标签页">转为XUL标签页</h3> - -<p>To convert from the high-level <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Tab"><code>Tab</code></a> objects used in this API to the low-level <a href="/en-US/docs/Mozilla/Tech/XUL/tab">XUL <code>tab</code></a> objects used in the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils"><code>tabs/utils</code></a> API and by traditional add-ons, use the <code>viewFor()</code> function exported by the <code>viewFor</code> module.</p> - -<p>To convert back the other way, from a XUL <code>tab</code> to a high-level <code>Tab</code> object, use the <code>modelFor()</code> function, exported by the <code>modelFor</code> module.</p> - -<p>Here's an example converting from a high-level <code>Tab</code> to a XUL <code>tab</code> and then back the other way:</p> - -<pre class="brush: js">var { modelFor } = require("sdk/model/core"); -var { viewFor } = require("sdk/view/core"); - -var tabs = require("sdk/tabs"); -var tab_utils = require("sdk/tabs/utils"); - -function mapHighLevelToLowLevel(tab) { - // get the XUL tab that corresponds to this high-level tab - var lowLevelTab = viewFor(tab); - // now we can, for example, access the tab's content directly - var browser = tab_utils.getBrowserForTab(lowLevelTab); - console.log(browser.contentDocument.body.innerHTML); - // get the high-level tab back from the XUL tab - var highLevelTab = modelFor(lowLevelTab); - console.log(highLevelTab.url); -} - -tabs.on("ready", mapHighLevelToLowLevel); -</pre> - -<p>Note that directly accessing XUL objects and web content like this means you're no longer protected by the compatibility guarantees made by the SDK's high-level APIs. In particular, your code might not work with <a href="http://billmccloskey.wordpress.com/2013/12/05/multiprocess-firefox/">multiprocess Firefox</a>.</p> - -<h2 id="全局变量">全局变量</h2> - -<h3 id="函数">函数</h3> - -<h4 class="addon-sdk-api-name" id="open(options)"><code>open(options)</code></h4> - -<p>Opens a new tab. The new tab will open in the active window or in a new window, depending on the <code>inNewWindow</code> option.</p> - -<p><strong>示例</strong></p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); - -// Open a new tab on active window and make tab active. -tabs.open("http://www.mysite.com"); - -// Open a new tab in a new window and make it active. -tabs.open({ - url: "http://www.mysite.com", - inNewWindow: true -}); - -// Open a new tab on active window in the background. -tabs.open({ - url: "http://www.mysite.com", - inBackground: true -}); - -// Open a new tab as an app tab and do something once it's open. -tabs.open({ - url: "http://www.mysite.com", - isPinned: true, - onOpen: function onOpen(tab) { - // do stuff like listen for content - // loading. - } -});</pre> - -<h5 id="参数">参数</h5> - -<p><strong>options : object</strong><br> - 必选项:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>url</td> - <td>string</td> - <td> - <p>String URL to be opened in the new tab. This is a required property.</p> - </td> - </tr> - </tbody> -</table> - -<p>可选项:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>isPrivate</td> - <td>boolean</td> - <td> - <p>Boolean which will determine whether the new tab should be private or not. If your add-on does not support private browsing this will have no effect. See the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">private-browsing</a> documentation for more information. Defaults to <code>false</code>.</p> - </td> - </tr> - <tr> - <td>inNewWindow</td> - <td>boolean</td> - <td> - <p>If present and true, a new browser window will be opened and the URL will be opened in the first tab in that window. This is an optional property.</p> - </td> - </tr> - <tr> - <td>inBackground</td> - <td>boolean</td> - <td> - <p>If present and true, the new tab will be opened to the right of the active tab and will not be active. This is an optional property.</p> - </td> - </tr> - <tr> - <td>isPinned</td> - <td>boolean</td> - <td> - <p>If present and true, then the new tab will be pinned as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>.</p> - </td> - </tr> - <tr> - <td>onOpen</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'open' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onClose</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'close' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onReady</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'ready' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onLoad</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'load' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onPageShow</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'pageshow' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onActivate</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'activate' event. This is an optional property.</p> - </td> - </tr> - <tr> - <td>onDeactivate</td> - <td>function</td> - <td> - <p>A callback function that will be registered for the 'deactivate' event. This is an optional property.</p> - </td> - </tr> - </tbody> -</table> - -<h3 id="属性">属性</h3> - -<h4 class="addon-sdk-api-name" id="activeTab"><code>activeTab</code></h4> - -<p>The currently active tab in the active window. This property is read-only. To activate a <code>Tab</code> object, call its <code>activate</code> method.</p> - -<p><strong>示例</strong></p> - -<pre class="brush: js">// Get the active tab's title. -var tabs = require("sdk/tabs"); -console.log("title of active tab is " + tabs.activeTab.title);</pre> - -<h4 class="addon-sdk-api-name" id="length"><code>length</code></h4> - -<p>The number of open tabs across all windows.</p> - -<h3 id="事件">事件</h3> - -<h4 class="addon-sdk-api-name" id="open"><code>open</code></h4> - -<p>This event is emitted when a new tab is opened. This does not mean that the content has loaded, only that the browser tab itself is fully visible to the user.</p> - -<p>Properties relating to the tab's content (for example: <code>title</code>, <code>favicon</code>, and <code>url</code>) will not be correct at this point. If you need to access these properties, listen for the <code>ready</code> event:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.on('open', function(tab){ - tab.on('ready', function(tab){ - console.log(tab.url); - }); -});</pre> - -<h5 id="参数_2">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object that just opened.</p> - -<h4 class="addon-sdk-api-name" id="close"><code>close</code></h4> - -<p>This event is emitted when a tab is closed. When a window is closed this event will be emitted for each of the open tabs in that window.</p> - -<h5 id="参数_3">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object that has closed.</p> - -<h4 class="addon-sdk-api-name" id="ready"><code>ready</code></h4> - -<p>This event is emitted when the DOM for a tab's content is ready. It is equivalent to the <code>DOMContentLoaded</code> event for the given content page.</p> - -<p>A single tab will emit this event every time the DOM is loaded: so it will be emitted again if the tab's location changes or the content is reloaded.</p> - -<p>After this event has been emitted, all properties relating to the tab's content can be used.</p> - -<h5 id="参数_4">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object that has loaded.</p> - -<h4 class="addon-sdk-api-name" id="activate"><code>activate</code></h4> - -<p>This event is emitted when an inactive tab is made active.</p> - -<h5 id="参数_5">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object that has become active.</p> - -<h4 class="addon-sdk-api-name" id="deactivate"><code>deactivate</code></h4> - -<p>This event is emitted when the active tab is made inactive.</p> - -<h5 id="参数_6">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object that has become inactive.</p> - -<h2 id="Tab">Tab</h2> - -<p>A <code>Tab</code> instance represents a single open tab. It contains various tab properties, several methods for manipulation, as well as per-tab event registration.</p> - -<p>Tabs emit all the events described in the Events section. Listeners are passed the <code>Tab</code> object that triggered the event.</p> - -<h3 id="方法">方法</h3> - -<h4 class="addon-sdk-api-name" id="pin()"><code>pin()</code></h4> - -<p>Pins this tab as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>.</p> - -<h4 class="addon-sdk-api-name" id="unpin()"><code>unpin()</code></h4> - -<p>Unpins this tab.</p> - -<h4 class="addon-sdk-api-name" id="close(callback)"><code>close(callback)</code></h4> - -<p>Closes this tab.</p> - -<h5 id="参数_7">参数</h5> - -<p><strong>callback : function</strong><br> - A function to be called when the tab finishes its closing process. This is an optional argument.</p> - -<h4 class="addon-sdk-api-name" id="reload()"><code>reload()</code></h4> - -<p>Reloads this tab.</p> - -<h4 class="addon-sdk-api-name" id="activate()"><code>activate()</code></h4> - -<p>Makes this tab active, which will bring this tab to the foreground.</p> - -<h4 class="addon-sdk-api-name" id="getThumbnail()"><code>getThumbnail()</code></h4> - -<p>Returns thumbnail data URI of the page currently loaded in this tab.</p> - -<h4 class="addon-sdk-api-name" id="attach(options)"><code>attach(options)</code></h4> - -<p>Attach one or more scripts to the document loaded in the tab. Note that by attaching inside <em>ready</em> event, this becomes tab-centric: if the user navigates to a new page in the same tab, then the content scripts will be reattached to the new page.</p> - -<p><strong>示例</strong></p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); - -tabs.on('ready', function(tab) { - var worker = tab.attach({ - contentScript: - 'document.body.style.border = "5px solid red";' - }); -});</pre> - -<h5 id="参数_8">参数</h5> - -<p><strong>options : object</strong><br> - 可选项:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>contentScriptFile</td> - <td>string,array</td> - <td> - <p>The local file URLs of content scripts to load. Content scripts specified by this option are loaded <em>before</em> those specified by the <code>contentScript</code> option. Optional.</p> - </td> - </tr> - <tr> - <td>contentScript</td> - <td>string,array</td> - <td> - <p>A string or an array of strings of code to be evaluated in the context. Content scripts specified by this option are loaded <em>after</em> those specified by the <code>contentScriptFile</code> option. Optional.</p> - </td> - </tr> - <tr> - <td>contentScriptOptions</td> - <td>object</td> - <td> - <p>You can use this option to define read-only values for your content scripts.</p> - - <p>The option consists of an object literal listing <code>name:value</code> pairs for the values you want to provide to the content script. For example:</p> - - <pre class="brush: js"> -// main.js - -const tabs = require("sdk/tabs"); - -tabs.open({ - url: "./page.html", - onReady: function(tab) { - tab.attach({ - contentScriptFile: "./content-script.js", - contentScriptOptions: { - a: "blah" - } - }); - } -});</pre> - - <p>The values are accessible to content scripts via the <code>self.options</code> property:</p> - - <pre class="brush: js"> -// content-script.js - -alert(self.options.a);</pre> - </td> - </tr> - <tr> - <td>onMessage</td> - <td>function</td> - <td> - <p>A function called when the content worker receives a message from content scripts. Listeners are passed a single argument, the message posted from the content script. Optional.</p> - </td> - </tr> - <tr> - <td>onError</td> - <td>function</td> - <td>A function called when the content worker receives an error from content scripts. Listeners are passed a single argument, <code>error</code>, which is the error posted from the content script and an object of type <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error">Error</a>. Optional</td> - </tr> - </tbody> -</table> - -<h5 id="返回">返回</h5> - -<p><strong>Worker</strong> : <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">Worker</a> 对象能够用来和内容脚本通信。查看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Content Scripts guide</a> 了解详细信息。</p> - -<h3 id="属性_2">属性</h3> - -<h4 class="addon-sdk-api-name" id="id"><code>id</code></h4> - -<p>The unique id for the tab. This property is read-only.</p> - -<h4 class="addon-sdk-api-name" id="title"><code>title</code></h4> - -<p>The title of the tab (usually the title of the page currently loaded in the tab) This property can be set to change the tab title.</p> - -<h4 class="addon-sdk-api-name" id="url"><code>url</code></h4> - -<p>The URL of the page currently loaded in the tab. This property can be set to load a different URL in the tab.</p> - -<h4 class="addon-sdk-api-name" id="favicon"><code>favicon</code></h4> - -<p>The URL of the favicon for the page currently loaded in the tab. This property is read-only.</p> - -<div class="warning">This property is deprecated. From version 1.15, use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/places_favicon">favicon module's <code>getFavicon()</code></a> function instead.</div> - -<h4 class="addon-sdk-api-name" id="contentType"><code>contentType</code></h4> - -<div class="note"> -<p><strong>This is currently an experimental API, so we might change it in future releases.</strong></p> - -<p>Returns the MIME type that the document currently loaded in the tab is being rendered as. This may come from HTTP headers or other sources of MIME information, and might be affected by automatic type conversions performed by either the browser or extensions. This property is read-only.</p> -</div> - -<h4 class="addon-sdk-api-name" id="index"><code>index</code></h4> - -<p>The index of the tab relative to other tabs in the application window. This property can be set to change its relative position.</p> - -<h4 class="addon-sdk-api-name" id="isPinned"><code>isPinned</code></h4> - -<p>Whether or not this tab is pinned as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>. This property is read-only.</p> - -<h4 class="addon-sdk-api-name" id="window"><code>window</code></h4> - -<p><code>标签页的</code><a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#BrowserWindow"><code>window</code></a>对象.</p> - -<h4 class="addon-sdk-api-name" id="readyState"><code>readyState</code></h4> - -<div class="geckoVersionNote"> -<p>Firefox 33 新增。</p> -</div> - -<p>A string telling you the load state of the document hosted by this tab. This corresponds directly to <a href="/en-US/docs/Web/API/document.readyState"><code>Document.readyState</code></a>. It has one of four possible values:</p> - -<ul> - <li>"uninitialized": the tab's document is not yet loading</li> - <li>"loading": the tab's document is still in the process of loading</li> - <li>"interactive": the tab's document has loaded and is parsed, but resources such as images and stylesheets may still be loading</li> - <li>"complete": the tab's document and all resources are fully loaded</li> -</ul> - -<p>Once a tab's <code>readyState</code> has entered "interactive", you can retrieve properties such as the document's URL.</p> - -<h3 id="事件_2">事件</h3> - -<h4 class="addon-sdk-api-name" id="close_2"><code>close</code></h4> - -<p>This event is emitted when the tab is closed. It's also emitted when the tab's window is closed.</p> - -<h5 id="参数_9">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> - -<h4 class="addon-sdk-api-name" id="ready_2"><code>ready</code></h4> - -<p>This event is emitted when the DOM for the tab's content is ready. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded"><code>DOMContentLoaded</code></a> event for the given content page. At this point the document itself is fully loaded and parsed, but resources such as stylesheets and images may still be loading.</p> - -<p>A single tab will emit this event every time the DOM is loaded: so it will be emitted again if the tab's location changes or the content is reloaded. After this event has been emitted, all properties relating to the tab's content can be used.</p> - -<h5 id="参数_10">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> - -<h4 class="addon-sdk-api-name" id="load"><code>load</code></h4> - -<p>This event is emitted when the page for the tab's content is loaded. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/load"><code>load</code></a> event for the given content page. At this point the document and its resources, such as images and stylesheets, have finished loading.</p> - -<p>This event can be used for pages that do not have a <code>DOMContentLoaded</code> event, like images. For pages that have a <code>DOMContentLoaded</code> event, <code>load</code> is fired after <code>ready</code>.</p> - -<p>A single tab will emit this event every time the page is loaded: so it will be emitted again if the tab's location changes or the content is reloaded. After this event has been emitted, all properties relating to the tab's content can be used.</p> - -<h5 id="参数_11">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> - -<h4 class="addon-sdk-api-name" id="pageshow"><code>pageshow</code></h4> - -<p>The <code>pageshow</code> event is emitted when the page for a tab's content is loaded. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/pageshow"><code>pageshow</code></a> event for the given content page.</p> - -<p>This event is similar to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#load"><code>load</code></a> and <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready"><code>ready</code></a> events, except unlike <code>load</code> and <code>ready</code>, <code>pageshow</code> is triggered if the page was retrieved from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">bfcache</a>. This means that if the user loads a page, loads a new page, then moves back to the previous page using the "Back" button, the <code>pageshow</code> event is emitted when the user moves back to the previous page, while the <code>load</code> and <code>ready</code> events are not.</p> - -<p>This event is <em>not</em> emitted when the tab is made the active tab: to get notified about that, you need to listen to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#activate"><code>activate</code></a> event.</p> - -<p>After this event has been emitted, all properties relating to the tab's content can be used. It is emitted after <code>load</code> and <code>ready</code>.</p> - -<h5 id="参数_12">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> - -<p><strong>persisted</strong> : Listeners are passed a boolean value indicating whether or not the page was loaded from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">bfcache</a>.</p> - -<h4 class="addon-sdk-api-name" id="activate_2"><code>activate</code></h4> - -<p>This event is emitted when the tab is made active.</p> - -<p>Note that you cannot guarantee that a tab's content, or even its <code>url</code>, are initialized at the time <code>activate</code> is emitted. This is because when a new tab is opened, its <code>activate</code> event may be emitted before the content is loaded.</p> - -<p>You can use the tab's <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#readyState"><code>readyState</code></a> property to determine whether the tab's content and <code>url</code> will be available: if <code>readyState</code> is <code>uninitialized</code> or <code>loading</code>, then you can't access the tab's properties and must wait for the tab's <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready_2"><code>ready</code></a> event.</p> - -<h5 id="参数_13">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> - -<h4 class="addon-sdk-api-name" id="deactivate_2"><code>deactivate</code></h4> - -<p>This event is emitted when the tab is made inactive.</p> - -<h5 id="参数_14">参数</h5> - -<p><strong>Tab</strong> : Listeners are passed the tab object.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html deleted file mode 100644 index f98da9baf9..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: url -slug: Mozilla/Add-ons/SDK/High-Level_APIs/url -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/url ---- -<div class="note"> -<p>实验性的</p> -</div> - -<p><span class="seoSummary">构建,验证,解析URL</span></p> - -<h2 id="Globals">Globals</h2> - -<h3 id="构造函数">构造函数</h3> - -<h4 class="addon-sdk-api-name" id="URL(source_base)"><code>URL(source, base)</code></h4> - -<p>URL构造函数可以创建一个URL对象,并验证提供的字符串是否是有效的URL。SDK中,任何接受URL参数的API,除非特殊说明,均接受的是此对象而不是字符串。</p> - -<h5 id="参数">参数</h5> - -<p><strong>source : string</strong><br> - 一个表示URL的字符串,如果接受的参数不是有效的URL字符串,此构造函数会抛出一个异常。</p> - -<p><strong>base : string</strong><br> - 一个设置的字符串,用来表示一个相对路径的源。</p> - -<h4 class="addon-sdk-api-name" id="DataURL(uri)"><code>DataURL(uri)</code></h4> - -<p>DataURL构造函数创建一个data: URL对象, 并验证提供的字符串是否是一个有效的data: URL。</p> - -<h5 id="参数_2">参数</h5> - -<p><strong>uri : string</strong><br> - 一个表示Data URL的字符串。如果它不是一个合法的URL字符串,此构造函数会抛出一个错误。</p> - -<h3 id="函数">函数</h3> - -<h4 class="addon-sdk-api-name" id="toFilename(url)"><code>toFilename(url)</code></h4> - -<p>尝试将给定的URL转换成本地文件路径。这个方法会自动尝试解决非文件协议, such as the <code>resource:</code> protocol, to their place on the file system. 除非URL无法转换,否则,本方法会将本地路径作为字符串返回。</p> - -<h5 id="参数_3">参数</h5> - -<p><strong>url : string</strong><br> - 字符串格式的URL。</p> - -<h5 id="返回">返回</h5> - -<p><strong>string</strong> : 转换后的本地路径字符串</p> - -<h4 class="addon-sdk-api-name" id="fromFilename(path)"><code>fromFilename(path)</code></h4> - -<p>讲一个给定的路径转换成 <code>file:</code> URL.</p> - -<h5 id="参数_4">参数</h5> - -<p><strong>path : string</strong><br> - 需要被转换的本地文件路径字符串。</p> - -<h5 id="Returns">Returns</h5> - -<p><strong>string</strong> : 转换后的字符串。</p> - -<h4 class="addon-sdk-api-name" id="isValidURI(uri)"><code>isValidURI(uri)</code></h4> - -<p>检查一个URL字符串是合法。 <code>isValidURI("http://mozilla.org")</code> 将返回 <code>true</code>, 而 <code>isValidURI("mozilla.org")</code> 将返回 <code>false</code>。</p> - -<h5 id="参数_5">参数</h5> - -<p><strong>uri : string</strong><br> - 需要被测试的URL。</p> - -<h5 id="Returns_2">Returns</h5> - -<p><strong>boolean</strong> : 代表字符串是否有效的布尔值。</p> - -<h4 class="addon-sdk-api-name" id="getTLD(url)"><code>getTLD(url)</code></h4> - -<p>返回给定域名的顶级域名: 内部使用的是 <a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIEffectiveTLDService#getPublicSuffix()"><code>getPublicSuffix()</code></a> 。</p> - -<pre class="brush: js">var urls = require("sdk/url"); -console.log(urls.getTLD("http://www.bbc.co.uk/")); // "co.uk" -console.log(urls.getTLD("https://developer.mozilla.org/")); // "org"</pre> - -<h5 id="参数_6">参数</h5> - -<p><strong>url : string</strong><br> - 给定的URL字符串</p> - -<h5 id="返回_2">返回</h5> - -<p><strong>string</strong> : 对应的顶级域名。</p> - -<h2 id="URL">URL</h2> - -<h3 id="方法">方法</h3> - -<h4 class="addon-sdk-api-name" id="toString()"><code>toString()</code></h4> - -<p>返回URL的字符表示形式。</p> - -<h5 id="返回_3">返回</h5> - -<p><strong>string</strong> : 字符串格式的URL。</p> - -<h3 id="属性">属性</h3> - -<h4 class="addon-sdk-api-name" id="scheme"><code>scheme</code></h4> - -<p>URL使用的协议</p> - -<h4 class="addon-sdk-api-name" id="userPass"><code>userPass</code></h4> - -<p>URL中的username:password 部分,<code>null</code> 表示不存在。</p> - -<h4 class="addon-sdk-api-name" id="host"><code>host</code></h4> - -<p>URL的主机部分。 <code>null</code> 表示无此部分。例子:</p> - -<pre class="brush: js">var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons"); -console.log(url.host); // developer.mozilla.org</pre> - -<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4> - -<p>URL使用的端口。 <code>null</code> 表示不存在。</p> - -<h4 class="addon-sdk-api-name" id="path"><code>path</code></h4> - -<p>URL的路径部分,例子:</p> - -<pre class="brush: js">var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons"); -console.log(url.path); // /en-US/Add-ons</pre> - -<h4 class="addon-sdk-api-name" id="hostname"><code>hostname</code></h4> - -<p>表示URL的域的字符串。参见 <a href="/en-US/docs/Web/API/URLUtils.hostname"><code>window.location.hostname</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="pathname"><code>pathname</code></h4> - -<p>从 <code>'/'</code>开始的路径字符串。参见 <a href="/en-US/docs/Web/API/URLUtils.pathname"><code>window.location.pathname</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="hash"><code>hash</code></h4> - -<p>从 <code>'#'</code> 开始的hash字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.hash"><code>window.location.hash</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="href"><code>href</code></h4> - -<p>整个URL字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.href"><code>window.location.href</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="origin"><code>origin</code></h4> - -<p>该URL的源的字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.origin"><code>window.location.origin</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="protocol"><code>protocol</code></h4> - -<p>该URL使用的协议字符串,包括最后的<code>':',参见</code> <a href="/en-US/docs/Web/API/URLUtils.protocol"><code>window.location.protocol</code></a>。</p> - -<h4 class="addon-sdk-api-name" id="search"><code>search</code></h4> - -<p>以'?'开始的URL的参数段,包括最开始的<code>'?'</code>。 <code>参见</code><a href="/en-US/docs/Web/API/URLUtils.search"><code>window.location.search</code></a>.</p> - -<h2 id="DataURL">DataURL</h2> - -<h3 id="方法_2">方法</h3> - -<h4 class="addon-sdk-api-name" id="toString()_2"><code>toString()</code></h4> - -<p>返回数据的URL字符串形式。如果是 <code>base64</code> 的URL,数据会以base64编码方式编码。</p> - -<h5 id="返回_4">返回</h5> - -<p><strong>string</strong> : URL字符串</p> - -<h3 id="属性_2">属性</h3> - -<h4 class="addon-sdk-api-name" id="mimeType"><code>mimeType</code></h4> - -<p>数据的MIME类型,默认为空字符串。</p> - -<h4 class="addon-sdk-api-name" id="parameters"><code>parameters</code></h4> - -<p>一个HashMap的数据包含URL参数。默认情况下是一个空对象。</p> - -<h4 class="addon-sdk-api-name" id="base64"><code>base64</code></h4> - -<p><span>定义了</span><span>数据</span><span>属性</span><span>值</span><span>的编码。</span></p> - -<h4 class="addon-sdk-api-name" id="data"><code>data</code></h4> - -<p>包含数据的URL字符串。如果<code>URI</code>给构造函数包含<code>Base64</code>参数,这个字符串会被解码。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html deleted file mode 100644 index 3d374a0752..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html +++ /dev/null @@ -1,839 +0,0 @@ ---- -title: widget -slug: Mozilla/Add-ons/SDK/High-Level_APIs/widget -tags: - - ZH -translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/widget ---- -<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p> - -<div class="warning"> -<p>Deprecated in Firefox 29 and removed in Firefox 38.</p> - -<p>The widget API is deprecated from Firefox 29 onwards. Please see the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui">ui module</a> for replacements. In particular, for a simple button, try the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#ActionButton">action button</a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#ToggleButton">toggle button</a> APIs, and for a more complex widget try the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#Toolbar">toolbar</a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#Sidebar">sidebar</a> APIs.</p> -</div> - -<p><span class="seoSummary">Create a simple user interface for an add-on in Firefox's add-on bar.</span></p> - -<h2 id="Usage">Usage</h2> - -<p>"Widgets" are small pieces of content that live in the Firefox 4 <a href="https://developer.mozilla.org/en/The_add-on_bar">add-on bar</a>. They can be simple icons or complex web pages. You can attach <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panels</a> to them that open when they're clicked, or you can define a custom click handler to perform some other action, like opening a web page in a tab.</p> - -<p>There are a few advantages to using widgets over an ad hoc user interface. First, your users will be accustomed to interacting with add-ons via widgets and the add-on bar. Second, it allows Firefox to treat your interface as a first-class citizen. For example, in the future Firefox may allow the user to drag widgets from the add-on bar to other toolbars. By exposing your interface as a widget, your add-on would automatically inherit such functionality.</p> - -<h3 id="Creation_and_content">Creation and content</h3> - -<p>Widgets can contain images or arbitrary web content. You can include this content inline as a string by using the <code>content</code> property, or point to content using a URL with the <code>contentURL</code> property.</p> - -<p>Upon creation, the widget is automatically added to the add-on bar. You can set the width of a widget, but the height is fixed so as to fit in the add-on bar. If the content is an image, it is automatically scaled to be 16x16 pixels.</p> - -<p>For example, this widget contains an image, so it looks like a simple icon:</p> - -<pre class="brush: js">require("sdk/widget").Widget({ - id: "mozilla-icon", - label: "My Mozilla Widget", - contentURL: "http://www.mozilla.org/favicon.ico" -});</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6695/widget-mozilla.png" style="display: block; height: 184px; margin-left: auto; margin-right: auto; width: 464px;">You can make <code>contentURL</code> point to an HTML or icon file which you have packaged inside your add-on. Just save the file in your add-on's <code>data</code> directory, and reference it using the <code>data.url()</code> method of the <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> module:</p> - -<pre class="brush: js">var data = require("sdk/self").data; - -require("sdk/widget").Widget({ - id: "my-widget", - label: "My Widget", - contentURL: data.url("my-content.html") -});</pre> - -<p>This widget contains an entire web page:</p> - -<pre class="brush: js">require("sdk/widget").Widget({ - id: "hello-display", - label: "My Hello Widget", - content: "Hello!", - width: 50 -});</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6605/widget-hello-text.png" style="display: block; height: 132px; margin-left: auto; margin-right: auto; width: 282px;">Widgets are quite small by default, so this example used the <code>width</code> property to grow it in order to show all the text.</p> - -<h3 id="Scripting_widget_content">Scripting widget content</h3> - -<p>To interact with the widget's content you need to load a separate script into the panel. In the SDK these scripts are called "content scripts" because they're explicitly used for interacting with web content.</p> - -<p>While content scripts can access the content they're attached to, they can't use the SDK's APIs. So implementing a complete solution usually means you have to send messages between the content script and the main add-on code.</p> - -<ul> - <li> - <p>You can specify one or more content scripts to load into the widget using the <code>contentScript</code> or <code>contentScriptFile</code> options to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/widget#Widget(options)"><code>Widget()</code> constructor</a>.</p> - </li> - <li> - <p>You can communicate with the script using either the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or (preferably, usually) the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API.</p> - </li> -</ul> - -<div class="warning"> -<p>Unless your content script is extremely simple and consists only of a static string, don't use <code>contentScript</code>: if you do, you may have problems getting your add-on approved on AMO.</p> - -<p>Instead, keep the script in a separate file and load it using <code>contentScriptFile</code>. This makes your code easier to maintain, secure, debug and review.</p> -</div> - - -<p><img alt="" src="https://mdn.mozillademos.org/files/6607/widget-player-buttons.png" style="float: right; height: 132px; width: 282px;">For example, suppose we want to implement a media player as an add-on. We could implement the main user interface as a widget hosting an array of buttons to control play/pause/stop functions.</p> - -<p>We can then use a content script to listen for clicks on those buttons. But because content scripts can't use the SDK's APIs, we'll want the content script to send messages to the main add-on code, which can then implement the media player functions using the SDK.</p> - -<p>The widget's content is specified using HTML like this:</p> - -<pre class="brush: html"><code class="brush: js"><html> - <body> - <img src="play.png" id="play-button"> - <img src="pause.png" id="pause-button"> - <img src="stop.png" id="stop-button"> - </body> -</html></code></pre> - -<p>We just include three icons, and assign an ID to each one. This HTML file, and the icon files it references, are saved in the add-on's <code>data</code> directory.</p> - -<p>Next, we write a content script that listens for click events on each icon and sends the corresponding message to the main add-on code:</p> - -<pre class="brush: js">var play_button = document.getElementById("play-button"); -play_button.onclick = function() { - self.port.emit("play"); -} - -var pause_button = document.getElementById("pause-button"); -pause_button.onclick = function() { - self.port.emit("pause"); -} - -var stop_button = document.getElementById("stop-button"); -stop_button.onclick = function() { - self.port.emit("stop"); -}</pre> - -<p>We save this file in the add-on's <code>data</code> directory as "button-script.js". Finally. in the add-on's "main.js" file, we create the widget, assign it the HTML file and the content script, and listen for events from the content script:</p> - -<pre class="brush: js">const widgets = require("sdk/widget"); -const data = require("sdk/self").data; - -var player = widgets.Widget({ - id: "player", - width: 72, - label: "Player", - contentURL: data.url("buttons.html"), - contentScriptFile: data.url("button-script.js") -}); - -player.port.on("play", function() { - console.log("playing"); -}); - -player.port.on("pause", function() { - console.log("pausing"); -}); - -player.port.on("stop", function() { - console.log("stopping"); -});</pre> - -<p>To learn much more about content scripts, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p> - -<h3 id="Scripting_trusted_widget_content">Scripting trusted widget content</h3> - -<p>We've already seen that you can package HTML files in your add-on's <code>data</code> directory and use them to define the widget's content. We can call this "trusted" content, because unlike content loaded from a source outside the add-on, the add-on author knows exactly what it's doing. To interact with trusted content you don't need to use content scripts: you can just include a script from the HTML file in the normal way, using <code>script</code> tags.</p> - -<p>Like a content script, these scripts can communicate with the add-on code using the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API. The crucial difference is that these scripts access the <code>postMessage</code> and <code>port</code> objects through the <code>addon</code> object, whereas content scripts access them through the <code>self</code> object.</p> - -<p>To show the difference, convert the <code>player</code> add-on above to use normal page scripts instead of content scripts.</p> - -<p>First, in the content script, change <code>self</code> to <code>addon</code>, and wrap it in a function:</p> - -<pre class="brush: js">function init() { - var play_button = document.getElementById("play-button"); - play_button.onclick = function() { - addon.port.emit("play"); - } - - var pause_button = document.getElementById("pause-button"); - pause_button.onclick = function() { - addon.port.emit("pause"); - } - - var stop_button = document.getElementById("stop-button"); - stop_button.onclick = function() { - addon.port.emit("stop"); - } -}</pre> - -<p>Next, add a <code>script</code> tag to reference "button-script.js", and call its <code>init()</code> function on load:</p> - -<pre class="brush: html"><html> - <head> - <script src="button-script.js"></script> - </head> - <body onLoad="init()"> - <img src="play.png" id="play-button"> - <img src="pause.png" id="pause-button"> - <img src="stop.png" id="stop-button"> - </body> -</html> -</pre> - -<p>Finally, remove the line attaching the content script from "main.js":</p> - -<pre class="brush: js">const widgets = require("sdk/widget"); -const data = require("sdk/self").data; - -var player = widgets.Widget({ - id: "player", - width: 72, - label: "Player", - contentURL: data.url("buttons.html") -}); - -player.port.emit("init"); - -player.port.on("play", function() { - console.log("playing"); -}); - -player.port.on("pause", function() { - console.log("pausing"); -}); - -player.port.on("stop", function() { - console.log("stopping"); -});</pre> - -<h3 id="Attaching_panels_to_widgets">Attaching panels to widgets</h3> - -<p>You can supply a <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to the widget's constructor: if you do this, the panel is automatically displayed when the user clicks the widget.</p> - - -<p><img alt="" src="https://mdn.mozillademos.org/files/6609/widget-panel-clock.png" style="float: right; height: 222px; width: 214px;"></p> - -<pre class="brush: js">data = require("sdk/self").data - -var clockPanel = require("sdk/panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") -}); - -require("sdk/widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png"), - panel: clockPanel -});</pre> - -<p>Note that this is, at the moment, the only way you can attach a panel to a widget.</p> - -<p>You must supply the panel in the widget's constructor for it to work. If you assign the panel to the widget after construction, the panel can still be shown but will not be anchored to the widget:</p> - -<pre class="brush: js">data = require("sdk/self").data - -var clockPanel = require("sdk/panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") -}); - -widget = require("sdk/widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png") -}); - -widget.panel = clockPanel; - -// Will not be anchored -widget.panel.show();</pre> - -<p>Also, if you try to call <code>panel.show()</code> inside your widget's <code>click</code> event listener, the panel will not be anchored:</p> - -<pre class="brush: js">data = require("sdk/self").data - -var clockPanel = require("sdk/panel").Panel({ - width:215, - height:160, - contentURL: data.url("clock.html") -}); - -require("sdk/widget").Widget({ - id: "open-clock-btn", - label: "Clock", - contentURL: data.url("History.png"), - panel: clockPanel, - onClick: function() { - // Will not be anchored - this.panel.show(); - } -});</pre> - -<p>See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=638142">bug 638142</a>.</p> - -<h3 id="Private_windows">Private windows</h3> - -<p>If your add-on has not opted into private browsing, then your widget will not appear in any private browser windows.</p> - -<p>To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">documentation for the <code>private-browsing</code> module</a>.</p> - -<h3 id="Examples">Examples</h3> - -<p>For conciseness, these examples create their content scripts as strings and use the <code>contentScript</code> property. In your own add-ons, you will probably want to create your content scripts in separate files and pass their URLs using the <code>contentScriptFile</code> property. See <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> for more information.</p> - -<pre class="brush: js">var widgets = require("sdk/widget"); - -// A basic click-able image widget. -widgets.Widget({ - id: "google-link", - label: "Widget with an image and a click handler", - contentURL: "http://www.google.com/favicon.ico", - onClick: function() { - require("sdk/tabs").activeTab.url = "http://www.google.com/"; - } -});</pre> - -<pre class="brush: js">// A widget that changes display on mouseover. -widgets.Widget({ - id: "mouseover-effect", - label: "Widget with changing image on mouseover", - contentURL: "http://www.yahoo.com/favicon.ico", - onMouseover: function() { - this.contentURL = "http://www.bing.com/favicon.ico"; - }, - onMouseout: function() { - this.contentURL = "http://www.yahoo.com/favicon.ico"; - } -});</pre> - -<pre class="brush: js">// A widget that updates content on a timer. -widgets.Widget({ - id: "auto-update-widget", - label: "Widget that updates content on a timer", - content: "0", - contentScript: 'setTimeout(function() {' + - ' document.body.innerHTML++;' + - '}, 2000)', - contentScriptWhen: "ready" -});</pre> - -<pre class="brush: js">// A widget created with a specified width, that grows. -var myWidget = widgets.Widget({ - id: "widget-effect", - label: "Wide widget that grows wider on a timer", - content: "I'm getting longer.", - width: 50, -}); -require("sdk/timers").setInterval(function() { - myWidget.width += 10; -}, 1000);</pre> - -<pre class="brush: js">// A widget communicating bi-directionally with a content script. -var widget = widgets.Widget({ - id: "message-test", - label: "Bi-directional communication!", - content: "<foo>bar</foo>", - contentScriptWhen: "ready", - contentScript: 'self.on("message", function(message) {' + - ' alert("Got message: " + message);' + - '});' + - 'self.postMessage("ready");', - onMessage: function(message) { - if (message == "ready") - widget.postMessage("me too"); - } -});</pre> - -<h2 id="Globals">Globals</h2> - -<h3 id="Constructors">Constructors</h3> - -<h4 class="addon-sdk-api-name" id="Widget(options)"><code>Widget(options)</code></h4> - -<p>Creates a new widget. The widget is immediately added to the add-on bar.</p> - -<h5 id="Parameters">Parameters</h5> - -<p><strong>options : object</strong><br> - Required options:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>label</td> - <td>string</td> - <td> - <p>A string description of the widget used for accessibility, title bars, and error reporting.</p> - </td> - </tr> - <tr> - <td>id</td> - <td>string</td> - <td> - <p>A string used to identify your widget in order to save its location when the user moves it in the browser. This string has to be unique and must not be changed over time.</p> - </td> - </tr> - </tbody> -</table> - -<p>Optional options:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>content</td> - <td>string</td> - <td> - <p>An optional string value containing the displayed content of the widget. It may contain HTML. Widgets must have either the <code>content</code> property or the <code>contentURL</code> property set.</p> - - <p>If the content is an image, it is automatically scaled to be 16x16 pixels.</p> - </td> - </tr> - <tr> - <td>contentURL</td> - <td>string</td> - <td> - <p>An optional string URL to content to load into the widget. This can be local content or remote content, an image or web content. Widgets must have either the <code>content</code> property or the <code>contentURL</code> property set.</p> - - <p>If the content is an image, it is automatically scaled to be 16x16 pixels.</p> - </td> - </tr> - <tr> - <td>panel</td> - <td>Panel</td> - <td> - <p>An optional <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget. Note: If you also register a "click" listener, it will be called instead of the panel being opened. However, you can show the panel from the listener by calling <code>this.panel.show()</code>.</p> - </td> - </tr> - <tr> - <td>width</td> - <td>integer</td> - <td> - <p>Optional width in pixels of the widget. If not given, a default width is used.</p> - </td> - </tr> - <tr> - <td>onClick</td> - <td>function</td> - <td> - <p>Include this to listen to the widget's <code>click</code> event.</p> - </td> - </tr> - <tr> - <td>onMessage</td> - <td>function</td> - <td> - <p>Include this to listen to the widget's <code>message</code> event.</p> - </td> - </tr> - <tr> - <td>onMouseover</td> - <td>function</td> - <td> - <p>Include this to listen to the widget's <code>mouseover</code> event.</p> - </td> - </tr> - <tr> - <td>onMouseout</td> - <td>function</td> - <td> - <p>Include this to listen to the widget's <code>mouseout</code> event.</p> - </td> - </tr> - <tr> - <td>onAttach</td> - <td>function</td> - <td> - <p>Include this to listen to the widget's <code>attach</code> event.</p> - </td> - </tr> - <tr> - <td>tooltip</td> - <td>string</td> - <td> - <p>Optional text to show when the user's mouse hovers over the widget. If not given, the <code>label</code> is used.</p> - </td> - </tr> - <tr> - <td>allow</td> - <td>object</td> - <td> - <p>An optional object describing permissions for the content. It should contain a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content. <code>script</code> defaults to true.</p> - </td> - </tr> - <tr> - <td>contentScriptFile</td> - <td>string,array</td> - <td> - <p>A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p> - </td> - </tr> - <tr> - <td>contentScript</td> - <td>string,array</td> - <td> - <p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p> - </td> - </tr> - <tr> - <td>contentScriptWhen</td> - <td>string</td> - <td> - <p>When to load the content scripts. This may take one of the following values:</p> - - <ul> - <li>"start": load content scripts immediately after the document element for the widget is inserted into the DOM, but before the DOM content itself has been loaded</li> - <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li> - <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li> - </ul> - - <p>This property is optional and defaults to "end".</p> - </td> - </tr> - <tr> - <td>contentScriptOptions</td> - <td>object</td> - <td> - <p>Read-only value exposed to content scripts under <code>self.options</code> property.</p> - - <p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p> - </td> - </tr> - </tbody> -</table> - -<h2 id="Widget">Widget</h2> - -<p>Represents a widget object.</p> - -<h3 id="Methods">Methods</h3> - -<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4> - -<p>Removes the widget from the add-on bar.</p> - -<h4 class="addon-sdk-api-name" id="postMessage(data)"><code>postMessage(data)</code></h4> - -<p>Sends a message to the widget's content scripts.</p> - -<h5 id="Parameters_2">Parameters</h5> - -<p><strong>data : value</strong><br> - The message to send. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p> - -<h4 class="addon-sdk-api-name" id="on(type_listener)"><code>on(type, listener)</code></h4> - -<p>Registers an event listener with the widget.</p> - -<h5 id="Parameters_3">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event to listen for.</p> - -<p><strong>listener : function</strong><br> - The listener function that handles the event.</p> - -<h4 class="addon-sdk-api-name" id="removeListener(type_listener)"><code>removeListener(type, listener)</code></h4> - -<p>Unregisters an event listener from the widget.</p> - -<h5 id="Parameters_4">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event for which <code>listener</code> was registered.</p> - -<p><strong>listener : function</strong><br> - The listener function that was registered.</p> - -<h4 class="addon-sdk-api-name" id="getView(window)"><code>getView(window)</code></h4> - -<p>Retrieve a <code>WidgetView</code> instance of this widget relative to a browser window.</p> - -<h5 id="Parameters_5">Parameters</h5> - -<p><strong>window : BrowserWindow</strong><br> - The <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#BrowserWindow">BrowserWindow</a> instance to match.</p> - -<h5 id="Returns">Returns</h5> - -<p><strong>WidgetView</strong> : A <code>WidgetView</code> instance associated with the browser window. Any changes subsequently applied to this object will only be applied to the widget attached to that window.</p> - -<h3 id="Properties">Properties</h3> - -<h4 class="addon-sdk-api-name" id="label"><code>label</code></h4> - -<p>The widget's label. Read-only.</p> - -<h4 class="addon-sdk-api-name" id="content"><code>content</code></h4> - -<p>A string containing the widget's content. It can contain HTML. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>contentURL</code>, then this property is meaningless, and setting it has no effect.</p> - -<h4 class="addon-sdk-api-name" id="contentURL"><code>contentURL</code></h4> - -<p>The URL of content to load into the widget. This can point to local content loaded from your add-on's "data" directory or remote content, an image or web content. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>content</code>, then this property is meaningless, and setting it has no effect.</p> - -<p>Setting the <code>contentURL</code> property will break the channel of communication between this widget and any content scripts it contains. Messages sent from the content script will no longer be received by the main add-on code, and vice versa. This issue is currently tracked as <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=825434">bug 825434</a>.</p> - -<h4 class="addon-sdk-api-name" id="panel"><code>panel</code></h4> - -<p>A <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget.</p> - -<h4 class="addon-sdk-api-name" id="width"><code>width</code></h4> - -<p>The widget's width in pixels. Setting it updates the widget's appearance immediately.</p> - -<h4 class="addon-sdk-api-name" id="tooltip"><code>tooltip</code></h4> - -<p>The text of the tooltip that appears when the user hovers over the widget.</p> - -<h4 class="addon-sdk-api-name" id="allow"><code>allow</code></h4> - -<p>A object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptFile"><code>contentScriptFile</code></h4> - -<p>A local file URL or an array of local file URLs of content scripts to load.</p> - -<h4 class="addon-sdk-api-name" id="contentScript"><code>contentScript</code></h4> - -<p>A string or an array of strings containing the texts of content scripts to load.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptWhen"><code>contentScriptWhen</code></h4> - -<p>When to load the content scripts. This may have one of the following values:</p> - -<ul> - <li>"start": load content scripts immediately after the document element for the widget is inserted into the DOM, but before the DOM content itself has been loaded</li> - <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li> - <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li> -</ul> - -<h4 class="addon-sdk-api-name" id="contentScriptOptions"><code>contentScriptOptions</code></h4> - -<p>Read-only value exposed to content scripts under <code>self.options</code> property.</p> - -<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p> - -<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4> - -<p>Object that allows you to:</p> - -<ul> - <li>send events to the content script using the <code>port.emit</code> function</li> - <li>receive events from the content script using the <code>port.on</code> function</li> -</ul> - -<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p> - -<h3 id="Events">Events</h3> - -<h4 class="addon-sdk-api-name" id="attach"><code>attach</code></h4> - -<p>This event is emitted when a browser window is opened and a new <code>WidgetView</code> object is created. If the widget has a content script, this event is fired only when the content script is applied according to the <code>contentScriptWhen</code> attribute.</p> - -<h5 id="Arguments">Arguments</h5> - -<p><strong>WidgetView</strong> : The related <code>WidgetView</code> object.</p> - -<h4 class="addon-sdk-api-name" id="click"><code>click</code></h4> - -<p>This event is emitted when the widget is clicked.</p> - -<h5 id="Arguments_2">Arguments</h5> - -<p><strong>WidgetView</strong> : Listeners are passed a single argument which is the <code>WidgetView</code> that triggered the click event.</p> - -<h4 class="addon-sdk-api-name" id="message"><code>message</code></h4> - -<p>If you listen to this event you can receive message events from content scripts associated with this widget. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the widget's <code>message</code> event.</p> - -<h5 id="Arguments_3">Arguments</h5> - -<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p> - -<h4 class="addon-sdk-api-name" id="mouseover"><code>mouseover</code></h4> - -<p>This event is emitted when the user moves the mouse over the widget.</p> - -<h4 class="addon-sdk-api-name" id="mouseout"><code>mouseout</code></h4> - -<p>This event is emitted when the user moves the mouse away from the widget.</p> - -<h2 id="WidgetView">WidgetView</h2> - -<p>Represents a widget instance specific to one browser window.</p> - -<p>Anything you do to an instance of this object will only be applied to the instance attached to its browser window: widget instances attached to other browser windows will be unaffected.</p> - -<p>By contrast, any changes you make to an instance of the normal <code>Widget</code> class will be applied across all browser windows.</p> - -<p>This class has all the same methods, attributes and events as the <code>Widget</code> class except for the <code>getView</code> method and the <code>attach</code> event.</p> - -<p>In this example <code>WidgetView</code> is used to display different content for <code>http</code> and <code>https</code> schemes:</p> - -<pre class="brush: js">// A widget that update its content specifically to each window. -var tabs = require("sdk/tabs"); -var windows = require("sdk/windows").browserWindows; -var widget = require("sdk/widget").Widget({ - id: "window-specific-test", - label: "Widget with content specific to each window", - content: " ", - width: 50 -}); -// Observe tab switch or document changes in each existing tab: -function updateWidgetState(tab) { - var view = widget.getView(tab.window); - if (!view) return; - // Update widget displayed text: - view.content = tab.url.match(/^https/) ? "Secured" : "Unsafe"; -} -tabs.on('ready', updateWidgetState); -tabs.on('activate', updateWidgetState);</pre> - -<h3 id="Methods_2">Methods</h3> - -<h4 class="addon-sdk-api-name" id="destroy()_2"><code>destroy()</code></h4> - -<p>Removes the widget view from the add-on bar.</p> - -<h4 class="addon-sdk-api-name" id="postMessage(data)_2"><code>postMessage(data)</code></h4> - -<p>Sends a message to the widget view's content scripts.</p> - -<h5 id="Parameters_6">Parameters</h5> - -<p><strong>data : value</strong><br> - The message to send. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p> - -<h4 class="addon-sdk-api-name" id="on(type_listener)_2"><code>on(type, listener)</code></h4> - -<p>Registers an event listener with the widget view.</p> - -<h5 id="Parameters_7">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event to listen for.</p> - -<p><strong>listener : function</strong><br> - The listener function that handles the event.</p> - -<h4 class="addon-sdk-api-name" id="removeListener(type_listener)_2"><code>removeListener(type, listener)</code></h4> - -<p>Unregisters an event listener from the widget view.</p> - -<h5 id="Parameters_8">Parameters</h5> - -<p><strong>type : string</strong><br> - The type of event for which <code>listener</code> was registered.</p> - -<p><strong>listener : function</strong><br> - The listener function that was registered.</p> - -<h3 id="Properties_2">Properties</h3> - -<h4 class="addon-sdk-api-name" id="label_2"><code>label</code></h4> - -<p>The widget view's label. Read-only.</p> - -<h4 class="addon-sdk-api-name" id="content_2"><code>content</code></h4> - -<p>A string containing the widget view's content. It can contain HTML. Setting it updates the widget view's appearance immediately. However, if the widget view was created using <code>contentURL</code>, then this property is meaningless, and setting it has no effect.</p> - -<h4 class="addon-sdk-api-name" id="contentURL_2"><code>contentURL</code></h4> - -<p>The URL of content to load into the widget. This can point to local content loaded from your add-on's "data" directory or remote content, an image or web content. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>content</code>, then this property is meaningless, and setting it has no effect.</p> - -<p>Setting the <code>contentURL</code> property will break the channel of communication between this widget and any content scripts it contains. Messages sent from the content script will no longer be received by the main add-on code, and vice versa. This issue is currently tracked as <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=825434">bug 825434</a>.</p> - -<h4 class="addon-sdk-api-name" id="panel_2"><code>panel</code></h4> - -<p>A <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget view.</p> - -<h4 class="addon-sdk-api-name" id="width_2"><code>width</code></h4> - -<p>The widget view's width in pixels. Setting it updates the widget view's appearance immediately.</p> - -<h4 class="addon-sdk-api-name" id="tooltip_2"><code>tooltip</code></h4> - -<p>The text of the tooltip that appears when the user hovers over the widget view.</p> - -<h4 class="addon-sdk-api-name" id="allow_2"><code>allow</code></h4> - -<p>A object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptFile_2"><code>contentScriptFile</code></h4> - -<p>A local file URL or an array of local file URLs of content scripts to load.</p> - -<h4 class="addon-sdk-api-name" id="contentScript_2"><code>contentScript</code></h4> - -<p>A string or an array of strings containing the texts of content scripts to load.</p> - -<h4 class="addon-sdk-api-name" id="contentScriptWhen_2"><code>contentScriptWhen</code></h4> - -<p>When to load the content scripts. This may have one of the following values:</p> - -<ul> - <li>"start": load content scripts immediately after the document element for the widget view is inserted into the DOM, but before the DOM content itself has been loaded</li> - <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li> - <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget view has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li> -</ul> - -<h4 class="addon-sdk-api-name" id="contentScriptOptions_2"><code>contentScriptOptions</code></h4> - -<p>Read-only value exposed to content scripts under <code>self.options</code> property.</p> - -<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p> - -<h4 class="addon-sdk-api-name" id="port_2"><code>port</code></h4> - -<p>Object that allows you to:</p> - -<ul> - <li>send events to the content script using the <code>port.emit</code> function</li> - <li>receive events from the content script using the <code>port.on</code></li> -</ul> - -<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p> - -<h3 id="Events_2">Events</h3> - -<h4 class="addon-sdk-api-name" id="detach"><code>detach</code></h4> - -<p>The <code>detach</code> event is fired when the widget view is removed from its related window. This can occur if the window is closed, Firefox exits, or the add-on is disabled.</p> - -<h4 class="addon-sdk-api-name" id="click_2"><code>click</code></h4> - -<p>This event is emitted when the widget view is clicked.</p> - -<h4 class="addon-sdk-api-name" id="message_2"><code>message</code></h4> - -<p>If you listen to this event you can receive message events from content scripts associated with this widget view. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the widget view's <code>message</code> event.</p> - -<h5 id="Arguments_4">Arguments</h5> - -<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p> - -<h4 class="addon-sdk-api-name" id="mouseover_2"><code>mouseover</code></h4> - -<p>This event is emitted when the user moves the mouse over the widget view.</p> - -<h4 class="addon-sdk-api-name" id="mouseout_2"><code>mouseout</code></h4> - -<p>This event is emitted when the user moves the mouse away from the widget view.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/index.html b/files/zh-cn/mozilla/add-ons/sdk/index.html deleted file mode 100644 index 3c6398ed48..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/index.html +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: 附加组件 SDK -slug: Mozilla/Add-ons/SDK -tags: - - More Example - - Need Tanslate - - TopicStub -translation_of: Archive/Add-ons/Add-on_SDK ---- -<div class="warning"> -<p>Support for extensions using XUL/XPCOM or the Add-on SDK was removed in Firefox 57, released November 2017. As there is no supported version of Firefox enabling these technologies, this page will be removed by December 2020.</p> - -<p>Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use <a href="/en-US/Add-ons/WebExtensions">WebExtensions</a> instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.</p> - -<p><strong>Starting from <a href="https://wiki.mozilla.org/RapidRelease/Calendar">Firefox 53</a>, no new legacy add-ons will be accepted on addons.mozilla.org (AMO) for desktop Firefox and Firefox for Android.</strong></p> - -<p><strong>Starting from <a href="https://wiki.mozilla.org/RapidRelease/Calendar">Firefox 57</a>, only extensions developed using WebExtensions APIs will be supported on Desktop Firefox and Firefox for Android. </strong></p> - -<p>Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to use WebExtensions APIs if they can. See the <a href="https://blog.mozilla.org/addons/2017/02/16/the-road-to-firefox-57-compatibility-milestones/">"Compatibility Milestones" document</a> for more information.</p> - -<p>A wiki page containing <a href="https://wiki.mozilla.org/Add-ons/developer/communication">resources, migration paths, office hours, and more</a>, is available to help developers transition to the new technologies.</p> -</div> - -<p>你可以使用Add-on SDK来开发Firefox的附加组件。你可以使用各种各样的标准Web技术:JavaScript, HTML和CSS。该SDK不仅包括一些用来创建附加组件的 JavaScript API,还提供了开发、运行、测试、打包附加组件的一些工具。</p> - -<hr> -<h3 id="教程">教程</h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><code><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials#getting-started">快速入门</a></code></dt> - <dd>如何<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/jpm">安装SDK</a>并<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_started">使用jpm工具</a>开发、测试、打包附加组件</dd> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials#interact-with-the-browser">与浏览器交互</a></dt> - <dd><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开网页</a>,<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load">监听页面加载</a>,<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs">列出打开的标签页</a>。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#development-techniques">开发技术</a></dt> - <dd>学习常用开发技术,如<a href="/zh-CN/Add-ons/SDK/Tutorials/Unit_testing">单元测试</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Logging">日志</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_Reusable_Modules">创建可复用模块</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/l10n">本地化</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Mobile_development">移动开发</a></dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#create-user-interfaces">创建用户界面组件</a></dt> - <dd>创建用户界面组件如<a href="/zh-CN/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar">工具条按钮</a>, <a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Context_Menu_Item">上下文菜单</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">菜单项</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Display_a_Popup">对话框</a>。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#modify-web-pages">修改网页</a></dt> - <dd> - <p>通过<a href="/zh-CN/docs//zh-CN/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL">URL匹配</a>修改页面或者动态<a href="/zh-CN/docs//zh-CN/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">修改某个tab选项卡</a>。</p> - </dd> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator">将其组合在一起</a></dt> - <dd>关于注释器的附加组件的例子演示.</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="指南">指南</h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Guides#contributors-guide"><span class="short_text" id="result_box" lang="zh-CN"><span class="op_dict_text2">贡献者</span><span>指南</span></span></a></dt> - <dd>学习<a href="/zh-CN/Add-ons/SDK/Guides/Getting_Started">如何开始构建</a> SDK和关于SDK最重要的术语, 如 <a href="/zh-CN/Add-ons/SDK/Guides/Modules">模块</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Classes_and_Inheritance"> 类和继承</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Private_Properties">私有属性</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Content_Processes">内容处理</a>.</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Guides#sdk-infrastructure">SDK的基础构建</a></dt> - <dd>SDK的底层技术方面: <a href="/zh-CN/Add-ons/SDK/Guides/Module_structure_of_the_SDK">模块</a>,<a href="/zh-CN/Add-ons/SDK/Guides/Program_ID">程序ID</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Firefox_Compatibility">Firefox 兼容</a>的规则定义.</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Guides/Content_Scripts"><span class="short_text" id="result_box" lang="zh-CN"><span>内容</span><span>脚本</span></span></a></dt> - <dd> - <div class="output-bd" dir="ltr"> - <p class="ordinary-output target-output"><span>一个详细的</span><span>指南</span><span>内容脚本</span></p> - </div> - </dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Guides#sdk-idioms">SDK语法</a></dt> - <dd>SDK的事件框架和插件的脚本和内容脚本之间的区别。</dd> - <dd>SDK的 <a href="/zh-CN/Add-ons/SDK/Guides/Working_with_Events">事件框架</a> 和 <a href="/zh-CN/Add-ons/SDK/Guides/Two_Types_of_Scripts">add-on scripts 和 content scripts 的</a>区别.</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Guides/XUL_Migration_Guide">XUL 迁移</a></dt> - <dd>指导 <a href="/zh-CN/Add-ons/SDK/Guides/XUL_Migration_Guide">移植 XUL add-ons 到 SDK</a>. 本指南包括 <a href="/zh-CN/Add-ons/SDK/Guides/XUL_vs_SDK">两工具</a> 和 一个 <a href="/zh-CN/Add-ons/SDK/Guides/Porting_the_Library_Detector">工作实例</a> 比较 XUL 和 add-on.</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="参考"><span class="short_text" id="result_box" lang="zh-CN"><span>参考</span></span></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/High-Level_APIs">高级API</a></dt> - <dd>高级SDK API的参考文档.</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tools">工具参考</a></dt> - <dd>用于 <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/jpm">jpm工具</a> 开发的参考文档, 测试, 打包add-ons, 全局 <a href="/zh-CN/Add-ons/SDK/Tools/console">控制台</a>记录, 和<a href="/zh-CN/Add-ons/SDK/Tools/package_json">package.json</a> 文件.</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Low-Level_APIs">低级API</a></dt> - <dd>低级SDK API的参考文档.</dd> -</dl> -</div> -</div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html deleted file mode 100644 index 673c369430..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: 低层 API -slug: Mozilla/Add-ons/SDK/Low-Level_APIs -translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs ---- -<p>{{AddonSidebar}}</p> - -<p>本节的模块实现了低层的 API,这些模块大至分为三类:</p> - -<ul> - <li> - <p>基础工具,比如 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/util_collection">collection</a>。很多 add-ons 都有可能使用这个类别的模块。</p> - </li> - <li> - <p>为高层模块构建分块,比如 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/event_core">events</a> 和 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a>。你更有可能使用它们构建你自己德尔模块,来扩展 SDK 本身。</p> - </li> - <li> - <p>权限模块,露出强大的低层功能,比如<a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> 和 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/net_xhr">net/xhr</a>。你可以使用这些模块,但是应该意识到获取访问权限的代价是必须采取更加详尽的预防措施。大部分情况下这些模块在"高层API中"有着简单的更加严格的同类模块。(例如,<a href="/en-US/Add-ons/SDK/High-Level_APIs/windows">windows</a> 或 <a href="/en-US/Add-ons/SDK/High-Level_APIs/request">request</a>)。</p> - </li> -</ul> - -<p>这些模块仍在开发中,我们预期在将来发布的版本中会做出不兼容的变更。</p> - -<p>{{ LandingPageListSubpages ("/zh-CN/Add-ons/SDK/Low-Level_APIs", 5) }}</p> - -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html deleted file mode 100644 index 5f7537ec42..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html +++ /dev/null @@ -1,283 +0,0 @@ ---- -title: test/assert -slug: Mozilla/Add-ons/SDK/Low-Level_APIs/test_assert -translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs/test_assert ---- -<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p> - -<div class="note"> -<p>Unstable</p> -</div> - -<p>实现在 <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification version 1.1</a> 其中定义的断言接口。</p> - -<h2 id="Usage">Usage</h2> - -<p>To use the <code>assert</code> module, write a set of unit tests following the instructions in the <a href="/en-US/Add-ons/SDK/Tutorials/Unit_testing">unit testing tutorial</a>. Each test will be passed an <code>Assert</code> object when you run the tests using <a href="/en-US/Add-ons/SDK/Tools/jpm"><code>jpm test</code></a>. You can use this object to make assertions about your program's state.</p> - -<p>For example:</p> - -<pre class="brush: js">var a = 1; - -exports["test value of a"] = function(assert) { - assert.ok(a == 1, "test that a is 1"); -} - -require("sdk/test").run(exports);</pre> - -<h2 id="Globals">Globals</h2> - -<h3 id="Constructors">Constructors</h3> - -<h4 class="addon-sdk-api-name" id="Assert(logger)"><code>Assert(logger)</code></h4> - -<p>Create a new Assert object. This function is only called by the unit test framework, and not by unit tests themselves.</p> - -<h5 id="Parameters">Parameters</h5> - -<p><strong>logger : object</strong><br> - Object used to log the results of assertions.</p> - -<h2 id="Assert">Assert</h2> - -<p>An object used to make assertions about a program's state in order to implement unit tests.</p> - -<p>The <code>Assert</code> object's interface is defined by the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification, version 1.1</a>.</p> - -<h3 id="Methods">Methods</h3> - -<h4 class="addon-sdk-api-name" id="ok(guard_message)"><code>ok(guard, message)</code></h4> - -<p>Tests whether an expression evaluates to true.</p> - -<pre class="brush: js">assert.ok(a == 1, "test that a is equal to one");</pre> - -<p>This is equivalent to:</p> - -<pre class="brush: js">assert.equal(a == 1, true, "test that a is equal to one");</pre> - -<h5 id="Parameters_2">Parameters</h5> - -<p><strong>guard : expression</strong><br> - The expression to evaluate.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="equal(actual_expected_message)"><code>equal(actual, expected, message)</code></h4> - -<p>Tests shallow, coercive equality with <code>==</code>:</p> - -<pre class="brush: js">assert.equal(1, 1, "test that one is one");</pre> - -<h5 id="Parameters_3">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="notEqual(actual_expected_message)"><code>notEqual(actual, expected, message)</code></h4> - -<p>Tests that two objects are not equal, using <code>!=</code>:</p> - -<pre class="brush: js">assert.notEqual(1, 2, "test that one is not two");</pre> - -<h5 id="Parameters_4">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="deepEqual(actual_expected_message)"><code>deepEqual(actual, expected, message)</code></h4> - -<p>Tests that two objects have a deep equality relation. Deep equality is defined in the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.0#Assert">CommonJS specification for Assert</a>, item 7, which is quoted here:</p> - -<div class="quote"> -<ol> - <li>All identical values are equivalent, as determined by ===.</li> - <li>If the expected value is a Date object, the actual value is equivalent if it is also a Date object that refers to the same time.</li> - <li>Other pairs that do not both pass typeof value == "object", equivalence is determined by ==.</li> - <li>For all other Object pairs, including Array objects, equivalence is determined by having the same number of owned properties (as verified with Object.prototype.hasOwnProperty.call), the same set of keys (although not necessarily the same order), equivalent values for every corresponding key, and an identical "prototype" property. Note: this accounts for both named and indexed properties on Arrays.</li> -</ol> -</div> - -<pre class="brush: js">assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects");</pre> - -<h5 id="Parameters_5">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="notDeepEqual(actual_expected_message)"><code>notDeepEqual(actual, expected, message)</code></h4> - -<p>Tests that two objects do not have a deep equality relation, using the negation of the test for deep equality:</p> - -<pre class="brush: js">assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }), - "object's inherit from different prototypes");</pre> - -<h5 id="Parameters_6">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="strictEqual(actual_expected_message)"><code>strictEqual(actual, expected, message)</code></h4> - -<p>Tests that two objects are equal, using the strict equality operator <code>===</code>:</p> - -<pre class="brush: js">// This test will pass, because "==" will perform type conversion -exports["test coercive equality"] = function(assert) { - assert.equal(1, "1", "test coercive equality between 1 and '1'"); -} - -// This test will fail, because the types are different -exports["test strict equality"] = function(assert) { - assert.strictEqual(1, "1", "test strict equality between 1 and '1'"); -}</pre> - -<h5 id="Parameters_7">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="notStrictEqual(actual_expected_message)"><code>notStrictEqual(actual, expected, message)</code></h4> - -<p>Tests that two objects are not equal, using the negation of the strict equality operator <code>===</code>:</p> - -<pre class="brush: js">// This test will fail, because "==" will perform type conversion -exports["test coercive equality"] = function(assert) { - assert.notEqual(1, "1", "test coercive equality between 1 and '1'"); -} - -// This test will pass, because the types are different -exports["test strict equality"] = function(assert) { - assert.notStrictEqual(1, "1", "test strict equality between 1 and '1'"); -}</pre> - -<h5 id="Parameters_8">Parameters</h5> - -<p><strong>actual : object</strong><br> - The actual result.</p> - -<p><strong>expected : object</strong><br> - The expected result.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> - -<h4 class="addon-sdk-api-name" id="throws(block_error_message)"><code>throws(block, error, message)</code></h4> - -<p>Assert that a block of code throws the expected exception.</p> - -<p>This method takes an optional <code>Error</code> argument:</p> - -<ul> - <li> - <p>to check that the exception thrown is of the expected type, pass a constructor function: the exception thrown must be an instance of the object returned by that function.</p> - </li> - <li> - <p>to check that the exception thrown contains a specific message, pass a regular expression here: the <code>message</code> property of the exception thrown must match the regular expression</p> - </li> -</ul> - - -<p>For example, suppose we define two different custom exceptions:</p> - -<pre class="brush: js">function MyError(message) { - this.name = "MyError"; - this.message = message || "Default Message"; -} - -MyError.prototype = new Error(); -MyError.prototype.constructor = MyError; - -function AnotherError(message) { - this.name = "AnotherError"; - this.message = message || "Default Message"; - console.log(this.message); -} - -AnotherError.prototype = new Error(); -AnotherError.prototype.constructor = AnotherError;</pre> - -<p>We can check the type of exception by passing a function as the <code>Error</code> argument:</p> - -<pre class="brush: js">exports["test exception type 1 expected to pass"] = function(assert) { - assert.throws(function() { - throw new MyError("custom message"); - }, - MyError, - "test throwing a specific exception"); -} - -exports["test exception type 2 expected to fail"] = function(assert) { - assert.throws(function() { - throw new MyError("custom message"); - }, - AnotherError, - "test throwing a specific exception"); -}</pre> - -<p>We can check the message by passing a regular expression:</p> - -<pre class="brush: js">exports["test exception message 1 expected to pass"] = function(assert) { - assert.throws(function() { - throw new MyError("custom message"); - }, - /custom message/, - "test throwing a specific message"); -} - -exports["test exception message 2 expected to pass"] = function(assert) { - assert.throws(function() { - throw new AnotherError("custom message"); - }, - /custom message/, - "test throwing a specific exception"); -} - -exports["test exception message 3 expected to fail"] = function(assert) { - assert.throws(function() { - throw new MyError("another message"); - }, - /custom message/, - "test throwing a specific message"); -}</pre> - -<h5 id="Parameters_9">Parameters</h5> - -<p><strong>block : block</strong><br> - The block of code to test.</p> - -<p><strong>error : function|RegExp</strong><br> - Either a constructor function returning the type of exception expected, or a regular expression expected to match the exception's <code>message</code> property.</p> - -<p><strong>message : string</strong><br> - Optional message to log, providing extra information about the test.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html deleted file mode 100644 index d826b15d7f..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html +++ /dev/null @@ -1,526 +0,0 @@ ---- -title: ui/button/action -slug: Mozilla/Add-ons/SDK/Low-Level_APIs/ui_button_action -translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs/ui_button_action ---- -<div class="note"> - <p>实验性的(译者备注:暂不翻译,可能会废弃)</p> -</div> -<p><span class="seoSummary">Add a button to the Firefox user interface.</span> With this module you can create buttons that display icons and can respond to click events.</p> -<h2 id="Usage">Usage</h2> -<h3 id="Creating_buttons"><br> - Creating buttons</h3> -<p>To create a button you must give it an ID, an icon, and a label:</p> -<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action"); - -var button = ActionButton({ - id: "my-button", - label: "my button", - icon: { - "16": "./firefox-16.png", - "32": "./firefox-32.png" - }, - onClick: function(state) { - console.log("button '" + state.label + "' was clicked"); - } - });</pre> -<p>By default, the button appears in the Firefox toolbar:</p> -<p><img alt="" src="https://mdn.mozillademos.org/files/6803/action-button-toolbar.png" style="width: 381px; height: 201px; display: block; margin-left: auto; margin-right: auto;">However, users can move it to the Firefox menu panel using the <a href="https://support.mozilla.org/en-US/kb/customize-firefox-controls-buttons-and-toolbars">toolbar customization feature</a>:</p> -<p><img alt="" src="https://mdn.mozillademos.org/files/6809/action-button-menu.png" style="width: 381px; height: 573px; display: block; margin-left: auto; margin-right: auto;"></p> -<h3 id="Badged_buttons">Badged buttons</h3> -<div class="geckoVersionNote"> - <p>New in Firefox 36.</p> -</div> -<p>You can add a "badge" to a button using its <code>badge</code> property. This can be a number or a string, and you can update it at any time. By default the badge's color is red, but you can set your own color using the <code>badgeColor</code> property, specified as a CSS <a href="/en-US/docs/Web/CSS/color_value"><code><color></code></a> value:</p> -<pre class="brush: js">var { ToggleButton } = require("sdk/ui/button/toggle"); - -var button = ToggleButton({ - id: "my-button1", - label: "my button1", - icon: "./icon-16.png", - onChange: changed, - badge: 0, - badgeColor: "#00AAAA" - }); - -function changed(state) { - button.badge = state.badge + 1; - if (state.checked) { - button.badgeColor = "#AA00AA"; - } - else { - button.badgeColor = "#00AAAA"; - } -}</pre> -<p><img alt="" src="https://mdn.mozillademos.org/files/9067/badge.png" style="width: 383px; height: 202px; display: block; margin-left: auto; margin-right: auto;"></p> -<h3 id="Specifying_multiple_icons">Specifying multiple icons</h3> -<p>You can specify just one icon, or multiple icons in different sizes.</p> -<p>If you specify multiple icons, Firefox will select the best-fitting icon based on the device screen resolution and the place the icon appears. For example, in the screenshots above, Firefox uses the small icon when the button is in the toolbar and the large icon when the button is in the menu panel. Read more about specifying icons in the reference documentation for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#ActionButton(options)"><code>ActionButton</code> constructor</a>.</p> -<h3 id="Responding_to_click_events">Responding to click events</h3> -<p>You can respond to click events by assigning a listener to the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a> event. You can do this in the button's constructor, by assigning the listener to the <code>onClick</code> option. You can also add, or change, the listener afterwards:</p> -<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action"); - -var button = ActionButton({ - id: "my-button", - label: "my button", - icon: { - "16": "./firefox-16.png", - "32": "./firefox-32.png" - }, - onClick: firstClick - }); - -function firstClick(state) { - console.log("You clicked '" + state.label + "'"); - button.removeListener("click", firstClick); - button.on("click", subsequentClicks); -} - -function subsequentClicks(state) { - console.log("You clicked '" + state.label + "' again"); -}</pre> -<p>The listener is passed a <code>state</code> object that contains all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a>.</p> -<p>You can generate click events programmatically with the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click()"><code>click()</code></a> method.</p> -<h3 id="Disabling_buttons">Disabling buttons</h3> -<p>You can disable a button by setting its <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#disabled"><code>disabled</code></a> property to <code>true</code>. A disabled button will not generate click events and its icon will appear disabled:</p> -<p><img alt="" src="https://mdn.mozillademos.org/files/6805/action-button-toolbar-disabled.png" style="width: 381px; height: 201px; display: block; margin-left: auto; margin-right: auto;"></p> -<h3 id="Updating_state">Updating state</h3> -<p>You can update all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a> except for its <code>id</code>.</p> -<p>By default, the button has global state: that is, its properties are the same across all open windows and tabs, and updating them updates the button's state across all open windows and tabs.</p> -<p>You can set state to be specific to a window or tab using the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#state()"><code>state()</code></a> method. To set state like this, call <code>state()</code> with 2 parameters:</p> -<ul> - <li>the first parameter is a <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Tab"><code>tab</code></a> object or as a shorthand, the string "window" for the currently active window, or the string "tab" for the currently active tab</li> - <li>the second parameter is an object containing the state properties you wish to update.</li> -</ul> -<p>Here's an add-on with a button that disables itself when you click it, but only for the currently active window:</p> -<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action"); - -var button = ActionButton({ - id: "my-button", - label: "my button", - icon: { - "16": "./firefox-16.png", - "32": "./firefox-32.png" - }, - onClick: disableForThisWindow - }); - -function disableForThisWindow(state) { - button.state("window", { - disabled: true - }); -}</pre> -<p>To fetch the state for a specific window or tab, call <code>state()</code>, passing in the window or tab you are interested in, and it will return the state:</p> -<pre class="brush: js">var labelForActiveTab = button.state("tab").label;</pre> -<p>To learn more about this, see the API documentation for <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#state()"><code>state()</code></a>.</p> -<h3 id="Destroying_buttons">Destroying buttons</h3> -<p>When you've finished with a button, destroy it by calling its <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#destroy()"><code>destroy()</code></a> method. After that, any attempts to access any of its properties or to call any of its methods will throw exceptions.</p> -<h2 id="Globals">Globals</h2> -<h3 id="Constructors">Constructors</h3> -<h4 class="addon-sdk-api-name" id="ActionButton(options)"><code>ActionButton(options)</code></h4> -<p>Creates an action button.</p> -<h5 id="Parameters">Parameters</h5> -<p><strong>options : object</strong><br> - Required options:</p> -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>id</td> - <td>string</td> - <td> - <p>The button's ID. This is used internally to keep track of this button. The ID must be unique within your add-on.</p> - </td> - </tr> - <tr> - <td>label</td> - <td>string</td> - <td> - <p>The button's human-readable label. When the button is in the toolbar, this appears in a tooltip, and when the button is in the menu, it appears underneath the button as a legend.</p> - </td> - </tr> - <tr> - <td>icon</td> - <td>url, string, object</td> - <td> - <p>One or more icons for the button. You can specify this in one of three ways: </p> - <ul> - <li><strong>as a resource:// URL</strong> pointing at an icon file in your add-on's "data" directory, typically constructed using <em><code>self.data.url(iconfile)</code></em></li> - <li><strong>as a relative path</strong>: a string in the form "./iconfile", where "iconfile" is a relative path to the icon file beginning in your add-on's "data" directory</li> - <li><strong>as an object, or dictionary of key-value pairs</strong>. Here you can specify a range of sizes for your button's icon. Each key-value pair specifies an icon: - <ul> - <li>each value specifies an image file as a resource:// URL or relative path.</li> - <li>each key must be a numeric string such as "16", or "32", which represents the size in pixels of the corresponding image.</li> - </ul> - </li> - </ul> - <pre class="brush: js"> -var { ActionButton } = require('sdk/ui/button/action'); -var self = require("sdk/self"); - -var button1 = ActionButton({ - id: "my-button1", - label: "my button1", - icon: self.data.url("firefox-16.png") - }); - -var button2 = ActionButton({ - id: "my-button2", - label: "my button2", - icon: "./firefox-16.png" - }); - -var button3 = ActionButton({ - id: "my-button3", - label: "my button3", - icon: { - "16" : "./firefox-16.png", - "32" : "./firefox-32.png", - "64" : "./firefox-64.png" - } - });</pre> - <p>If you use the final form, Firefox will automatically choose the best-fit icon for your button, depending on the device screen resolution and where the button is in the UI. On a device with a "normal" screen resolution, the toolbar has space for 18 x 18 pixels and the menu panel has space for 32 x 32 pixels. On a high resolution screen (such as a <a href="https://en.wikipedia.org/wiki/Retina_Display">HiDPI</a> display), these are doubled to 36 x 36 and 64 x 64 pixels, respectively. So you can supply three icon files:</p> - <pre class="brush: js"> -icon: { - "16": "./addon16.png", - "32": "./addon32.png", - "64": "./addon64.png" -}</pre> - <p>This will look fine in both toolbar and menu panel, and for both screen resolutions. However, the icons in the toolbar will not quite fill the space available, so you can instead supply four icons:</p> - <pre class="brush: js"> -icon: { - "18": "./addon18.png", // toolbar icon non HiDPI - "32": "./addon32.png", // menu panel icon non HiDPI - "36": "./addon36.png", // toolbar icon HiDPI - "64": "./addon64.png" // menu panel icon HiDPI -} -</pre> - </td> - </tr> - </tbody> -</table> -<p>Optional options:</p> -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Name</th> - <th scope="col">Type</th> - <th scope="col"> </th> - </tr> - </thead> - <tbody> - <tr> - <td>disabled</td> - <td>boolean</td> - <td> - <p>Determines whether the button is disabled. Disabled buttons appear disabled in the UI, and do not respond to clicks. Defaults to false.</p> - </td> - </tr> - <tr> - <td>onClick</td> - <td>function</td> - <td> - <p>Click handler for the button.</p> - </td> - </tr> - <tr> - <td>badge</td> - <td>Number or String</td> - <td> - <div class="geckoVersionNote"> - <p>New in Firefox 36.</p> - </div> - <p><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">Badge</a> to attach to the button.</p> - </td> - </tr> - <tr> - <td>badgeColor</td> - <td>CSS <a href="/en-US/docs/Web/CSS/color_value"><color></a> value</td> - <td> - <div class="geckoVersionNote"> - <p>New in Firefox 36.</p> - </div> - <p>Color for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>. If <code>badgeColor</code> is omitted and <code>badge</code> is specified, then the badge is red.</p> - </td> - </tr> - </tbody> -</table> -<h2 id="ActionButton">ActionButton</h2> -<h3 id="Methods">Methods</h3> -<h4 class="addon-sdk-api-name" id="click()"><code>click()</code></h4> -<p>Click the button. This will cause the button to generate the <code>click</code> event:</p> -<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action'); - -var button = ActionButton({ - id: "my-button", - label: "my button", - icon: { - "16": "./firefox-16.png", - "32": "./firefox-32.png" - }, - onClick: function(state) { - console.log("You clicked '" + state.label + "'"); - } -}); - -button.click(); -</pre> -<h4 class="addon-sdk-api-name" id="state()"><code>state()</code></h4> -<p>Get or set the button's state for a specific window or tab.</p> -<p>By default, a button's properties are global, meaning that they are the same across all open windows and tabs, and that if you update these properties, then they are updated across all windows and tabs. But sometimes you want a button attached to one window (or tab) to have a different state to a button attached to a different window (or tab). That's what <code>state()</code> is for.</p> -<p>To set a button's properties for a specific window or tab, call <code>state()</code>, passing it the <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tab</code></a> you want the property to apply to, and the property value to set. A special shortcut allows you to pass the string "window" or "tab" to select the currently active window or tab.</p> -<p>For example, if you have a button like this:</p> -<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action'); - -var button = ActionButton({ - id: "my-button", - label: "default", - icon: "./firefox-16.png" -});</pre> -<p>You can change its label for only the currently active window like this:</p> -<pre class="brush: js">button.state("window", { - "label" : "window-specific label" -});</pre> -<p>You can change its label for only the currently active tab like this:</p> -<pre class="brush: js">button.state("tab", { - "label" : "tab-specific label" -}); -</pre> -<p>To fetch the button state for a specific window or tab, call <code>state()</code>, passing it the window or tab you're interested in, and it will return a state object containing all the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a> for the button associated with that window or tab. Again. you can use the strings "window" or "tab" as shortcuts. For example, this add-on:</p> -<ul> - <li>creates a button with a default label</li> - <li>opens a new tab</li> - <li>sets a new label only for the new tab</li> - <li>logs the result of accessing the global label, the window-specific label, and each of the 2 tab-specific labels</li> -</ul> -<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = ActionButton({ - id: "my-button", - label: "default label", - icon: "./firefox-16.png" -}); - -tabs.open({ - url: "https://mozilla.org/", - onOpen: onNewTab -}); - -function onNewTab(tab) { - // Modify the label only for the new tab - button.state(tab, { - "label" : "tab-specific label" - }); - - // access the global label -> "default label" - console.log(button.label); - - // access the window's label -> "default label" - console.log(button.state("window").label); - - // access the first tab's label -> "default label" - console.log(button.state(tabs[0]).label); - - // access the second tab's label -> "tab-specific label" - console.log(button.state(tabs[1]).label); -}</pre> -<p>Setting a property won't affect a more-specific property setting. For example, if you have a window with two tabs, and you set a tab-specific label, then set the window-specific label, this will not overwrite the tab-specific label:</p> -<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = ActionButton({ - id: "my-button", - label: "default label", - icon: "./firefox-16.png" -}); - -tabs.open({ - url: "https://mozilla.org/", - onOpen: onNewTab -}); - -function onNewTab(tab) { - // Modify the label only for the new tab - button.state(tab, { - "label" : "tab-specific label" - }); - - // Modify the label for the window - button.state("window", { - "label" : "window-specific label" - }); - - // access the global label -> "default label" - console.log(button.label); - - // access the window's label -> "window-specific label" - console.log(button.state("window").label); - - // access the first tab's label -> "window-specific label" - console.log(button.state(tabs[0]).label); - - // access the second tab's label -> "tab-specific label" - console.log(button.state(tabs[1]).label); -}</pre> -<p>The best way to think of this is as a tree: the global state is the root, followed by the state for each window, followed by the state for each tab in a window. If a property value for a node in the tree has not been set explicitly using <code>state()</code>, then it inherits its value from the next level up. So if you have one window containing two tabs, and have set the button's <code>label</code> only for tab A, then tab B will inherit <code>label</code>'s value from the window, and changing the value for the window will implicitly change the value for tab B.</p> -<p>To delete a tab- or window-specific state, assign <code>null</code> to the property. After that, the property will inherit its value from the less-specific state as before:</p> -<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = ActionButton({ - id: "my-button", - label: "default label", - icon: "./firefox-16.png" -}); - -tabs.open({ - url: "https://mozilla.org/", - onOpen: onNewTab -}); - -function onNewTab(tab) { - // Modify the label only for the new tab - button.state(tab, { - "label" : "tab-specific label" - }); - - // Modify the label for the window - button.state("window", { - "label" : "window-specific label" - }); - - // access the global label -> "default label" - console.log(button.label); - - // access the window's label -> "window-specific label" - console.log(button.state("window").label); - - // access the first tab's label -> "window-specific label" - console.log(button.state(tabs[0]).label); - - // access the second tab's label -> "tab-specific label" - console.log(button.state(tabs[1]).label); - - // Reset the tab-specific state - button.state(tab, null); - - // access the second tab's label -> "window-specific label" - console.log(button.state(tabs[1]).label); -}</pre> -<p>Finally, you can pass the button itself into <code>state()</code>. This is an alternative way to set or get the global state. The reason for using this, rather than setting properties individually, is that you can define an object with the properties to set in one place, then apply it to the global state with a single line:</p> -<pre class="brush: js">const defaultState = { - "label": "default label", - "icon": "./default.png", -} - -const differentState = { - "label": "different label", - "icon": "./different.png", -} - -var { ActionButton } = require("sdk/ui/button/action"); - -var button = ActionButton({ - id: "default-label", - label: "default label", - icon: "./default.png", - onClick: function(state) { - if (button.label == "default label") { - button.state(button, differentState); - } - else { - button.state(button, defaultState); - } - console.log(button.state(button).label); - console.log(button.state(button).icon); - } - }); -</pre> -<h5 id="Parameters_2">Parameters</h5> -<p><strong>target : button, tab, window, string</strong></p> -<ul> - <li>To set or get the global state, this needs to be the <code>button</code> instance.</li> - <li>To get or set window-specific state, this needs to be the <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> object for which you wish to set a specific state, or the string "window" to select the currently active window.</li> - <li>To get or set tab-specific state this needs to be the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tab</code></a> object for which you wish to set a specific state, or the string "tab" to select the currently active tab.</li> -</ul> -<p><strong>state : object, null</strong><br> - Include this parameter only if you are setting state. It is an object containing all the properties you wish to set. For example:</p> -<pre class="brush: js">button.state("tab", { - "label" : "tab-specific label", - "icon": "./tab-specific-icon.ico" -});</pre> -<p>To reset state, pass null:</p> -<pre class="brush: js">button.state("tab", null);</pre> -<h5 id="Returns">Returns</h5> -<p><strong>state</strong> : if you have passed the second <code>state</code> argument to make this function a setter, it returns <code>undefined</code>. Otherwise, it functions as a getter and returns the button's state for the specified object. This logs the state for the button associated with the currently active tab:</p> -<pre class="brush: js">console.log(button.state("tab"));</pre> -<p>This object represents a snapshot of the state at the time <code>state()</code> is called. It is not kept up to date with changes made to the button:</p> -<pre class="brush: js">button.label = "foo"; -var state = button.state(button); -button.label = "bar"; -console.log(state.label) // foo</pre> -<h4 class="addon-sdk-api-name" id="on()"><code>on()</code></h4> -<p>Add a listener to an event emitted by the button. The button only emits one type of event, <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click">click</a></code>:</p> -<pre class="brush: js">button.on("click", handleClick) - -function handleClick(state) { - console.log("button '" + state.label + "' was clicked"); -}</pre> -<h5 id="Parameters_3">Parameters</h5> -<p><strong>event : string</strong><br> - The event to listen for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p> -<p><strong>listener : function</strong><br> - Function that will be called on click.</p> -<h4 class="addon-sdk-api-name" id="once()"><code>once()</code></h4> -<p>Assign a listener to the first occurrence only of an event emitted by the button. The button only emits one type of event, <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click">click</a></code>. The listener is automatically removed after the first time the event is emitted.</p> -<h5 id="Parameters_4">Parameters</h5> -<p><strong>event : string</strong><br> - The event to listen for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p> -<p><strong>listener : function</strong><br> - Function that will be called on click.</p> -<h4 class="addon-sdk-api-name" id="removeListener()"><code>removeListener()</code></h4> -<p>Removes an event listener. For example, this code is equivalent to <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#once()"><code>once()</code></a>:</p> -<pre class="brush: js">button.on("click", handleClick) - -function handleClick(state) { - console.log("button '" + state.label + "' was clicked"); - button.removeListener("click", handleClick); -} </pre> -<h5 id="Parameters_5">Parameters</h5> -<p><strong>event : string</strong><br> - The event to listener is listening for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p> -<p><strong>listener : function</strong><br> - The listener to remove.</p> -<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4> -<p>Destroy the button. After calling this function, the button will no longer appear in the UI, and accessing any of its properties or methods will throw an error.</p> -<h3 id="Properties">Properties</h3> -<h4 class="addon-sdk-api-name" id="id"><code>id</code></h4> -<p>The button's unique ID. This is read-only.</p> -<h4 class="addon-sdk-api-name" id="label"><code>label</code></h4> -<p>The button's label.</p> -<h4 class="addon-sdk-api-name" id="icon"><code>icon</code></h4> -<p>The button's icon or icons, as a URL, relative path, or object containing a set of key-value pairs.</p> -<h4 class="addon-sdk-api-name" id="disabled"><code>disabled</code></h4> -<p>Boolean property indicating whether or not the button is disabled.</p> -<h4 class="addon-sdk-api-name" id="badge"><code>badge</code></h4> -<div class="geckoVersionNote"> - <p>New in Firefox 36.</p> -</div> -<p>Value to attach to the button as a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>. May be a number or a string.</p> -<h4 class="addon-sdk-api-name" id="badgeColor"><code>badgeColor</code></h4> -<div class="geckoVersionNote"> - <p>New in Firefox 36.</p> -</div> -<p>Color for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>, specified as a CSS <a href="/en-US/docs/Web/CSS/color_value"><color></a> value.</p> -<h3 id="Events">Events</h3> -<h4 class="addon-sdk-api-name" id="click"><code>click</code></h4> -<p>This event is emitted when a user clicks the button or your add-on calls the button's <code>click()</code> method.</p> -<h5 id="Arguments">Arguments</h5> -<p><strong>state</strong> : The button's state. This contains all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a>.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/index.html deleted file mode 100644 index 8c67b4644e..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tools/index.html +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Tools -slug: Mozilla/Add-ons/SDK/Tools -tags: - - Add-on SDK - - CFX - - JPM - - NeedsTranslation - - TopicStub -translation_of: Archive/Add-ons/Add-on_SDK/Tools ---- -<p>Articles listed here provide a reference for the SDK's tools:</p> - -<p>{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/Tools", 7) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html deleted file mode 100644 index db429ef078..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html +++ /dev/null @@ -1,652 +0,0 @@ ---- -title: jpm -slug: Mozilla/Add-ons/SDK/Tools/jpm -tags: - - Add-on SDK - - JPM -translation_of: Archive/Add-ons/Add-on_SDK/Tools/jpm ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>你能在Firefox 38或更高的版本中使用jpm。</p> - -<p>本文为jpm参考。</p> -</div> - -<p><span class="seoSummary"><a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a> 的Node版本允许你测试、运行以及打包扩展。</span></p> - -<p>你也可以阅读 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29">jpm教程</a> 开始学习。</p> - -<p>jpm 用法:</p> - -<pre class="brush: bash">jpm [command] [options] -</pre> - -<p>jpm支持以下全局参数:</p> - -<pre class="brush: bash">-h, --help - 显示帮助信息并退出 --V, --version - 打印出jpm版本号 ---addon-dir - 源代码目录,默认为当前目录 -</pre> - -<h2 id="安装">安装</h2> - -<p>jpm发布在node包管理器 <a class="external external-icon" href="https://www.npmjs.org/package/jpm">npm</a> 上。</p> - -<h3 id="安装npm">安装npm</h3> - -<p>有两种方法来获取npm。</p> - -<ul> - <li>访问 <a href="http://nodejs.org/">nodejs.org</a> 下载并安装Node.js。Node.js 包含npm。</li> - <li>或者,如果你的系统有像 APT 这种包管理器,就用它来安装。例如,在 Ubuntu 或者 Debian 的终端窗口里,输入<code>sudo apt-get install nodejs nodejs-legacy npm</code></li> -</ul> - -<p>要测试安装是否成功,运行:</p> - -<pre class="brush: bash">/usr/bin/env node -v</pre> - -<p>如果出现错误提示 <em>/usr/bin/env: node: No such file or directory</em> 并且你的 nodejs 是通过包管理的方式安装的,那你的 nodejs 很有可能安装为其它的名字。为了保证jpm的兼容,PATH之中必须是以node为可执行文件名的。在Debian和Ubuntu系统上,你可以通过安装兼容包nodejs-legacy来解决这个问题:</p> - -<pre class="brush: bash"><code>sudo apt-get install nodejs-legacy</code></pre> - -<p><font face="Consolas, Liberation Mono, Courier, monospace">在其它的发行版中,你或许必须手动创建一共本地符号链接:</font></p> - -<pre><code>sudo ln -s "$(which nodejs)" /usr/local/bin/node</code></pre> - -<h3 id="安装jpm"><code>安装jpm</code></h3> - -<p>在你安装好npm并且将其加入你的PATH中后,你可以像安装其他npm包一样来安装jpm。</p> - -<h4 id="全局安装jpm">全局安装jpm</h4> - -<pre><code>npm install jpm --global</code></pre> - -<p>取决于你的安装,你可能需要管理员权限执行:</p> - -<pre class="brush: bash"><code>sudo npm install jpm --global</code></pre> - -<h4 id="局部安装jpm"><code>局部安装jpm</code></h4> - -<p><code>如果你不想,或者不能够全局安装jpm,你或许可以只为你安装它:</code></p> - -<pre><code>npm install jpm</code></pre> - -<p><code>在局部安装的情况下,为了在终端中运行jpm,你必须首先将目录</code>"$HOME/node_modules/.bin/"添加到你的终端PATH中。将下行中的命令添加到$HOME/.profile的末尾来实现永久添加(.profile将在每次运行一个新终端时被执行):</p> - -<pre><code>export PATH="$HOME/node_modules/.bin/:$PATH"</code></pre> - -<h4 id="通过git来安装jpm">通过git来安装jpm</h4> - -<p>另外,你也可以通过git安装jpm的最新版本</p> - -<pre>git clone https://github.com/mozilla-jetpack/jpm.git -cd jpm -npm install -npm link -</pre> - -<h3 id="jpm安装完毕后">jpm安装完毕后</h3> - -<p><span style="line-height: 1.5;">在全部搞定后,在命令行窗口中输入:</span></p> - -<pre class="brush: bash"><code>jpm</code></pre> - -<p>屏幕上显示了一系列可用的 jpm 命令。不同于 cfx,当在安装时使用了 --global 参数,你能在任何路径下启动的命令提示符中使用 jpm 命令。</p> - -<h3 id="还有问题?">还有问题?</h3> - -<p>如果你看不懂本文,要寻求帮助。SDK 用户和项目团队成员在<a class="external external-icon" href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目邮件列表</a>中讨论问题和建议。其他人也许会和你有一样的问题,所以试着搜索一下列表。也欢迎你发表一个新问题。你也可以在 <a class="external external-icon" href="http://irc.mozilla.org/">Mozilla 的 IRC 网络</a> 的 <a class="external external-icon" href="http://mibbit.com/?channel=%23jetpack&server=irc.mozilla.org">#jetpack</a> 房间里和其他SDK的用户聊天。</p> - -<h2 id="命令参考">命令参考</h2> - -<p>有六个命令:</p> - -<table> - <tbody> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_init"><code>jpm init</code></a></td> - <td>创建一个基本的 add-on 作为你 add-on 的开端。</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_run"><code>jpm run</code></a></td> - <td>运行一个带有你的 add-on 的 Firefox 实例。</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_test"><code>jpm test</code></a></td> - <td>运行你插件的单元测试</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_xpi"><code>jpm xpi</code></a></td> - <td>将你的插件打包为 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件(火狐的插件扩展文件名)</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_post"><code>jpm post</code></a></td> - <td>把你的 add-on 打包成 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件,然后发送到某一个URL。</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_watchpost"><code>jpm watchpost</code></a></td> - <td>无论是否有文件变更,把你的 add-on 打包成 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件发送到某一个URL。</td> - </tr> - <tr> - <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign"><code>jpm sign</code></a></td> - <td>将你的插件打包为 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件并且取回一个由Mozilla签名的新XPI文件。</td> - </tr> - </tbody> -</table> - -<h3 id="jpm_init">jpm init</h3> - -<p>这个命令从头开始初始化一个新的 add-on。</p> - -<p>新建一个目录,转到该目录下,然后运行 <code>jpm init</code>。</p> - -<pre><code>mkdir my-addon -cd my-addon -jpm init</code></pre> - -<p>然后你会被要求提供关于你的 add-on 的一些信息:这会用来创建 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件。</p> - -<ul> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#title">title</a></li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#name">name</a>: 默认是你运行 <code>jpm init 的目录名。除非</code>package.json里有 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#id"><code>id</code></a> 字段, jpm 在name前面加个<code>"@"</code>用作 <a href="https://developer.mozilla.org/en-US/Add-ons/Install_Manifests#id">add-on 安装清单的 <code>id</code> 字段</a>.</li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#version">version</a></li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#description">description</a></li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#main">entry point</a> (映射向package.json中的 "main")</li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#author">author</a></li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#engines">engines</a> (支持哪些应用程序)</li> - <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#license">license</a></li> -</ul> - -<p>大部分字段都有一个默认值,显示在那些问题的后面的括号里。如果你按了回车,那么你的 add-on 就用那个默认值。</p> - -<p>一旦你提供了一个值或者接受了默认值,你会看到"package.json"的完整内容,并被询问是否接受。</p> - -<p>然后 jpm 创建一个基本的 add-on,作为你开发的起点,文件结构如下:</p> - -<ul> - <li>my-addon - <ul> - <li>index.js</li> - <li>package.json</li> - <li>test - <ul> - <li>test-index.js</li> - </ul> - </li> - </ul> - </li> -</ul> - -<h3 id="jpm_run">jpm run</h3> - -<p>此命令运行一个新的装有你的 add-on 的 Firefox实例:</p> - -<pre><code>jpm run</code></pre> - -<p><code>jpm run</code> 有以下选项:</p> - -<table> - <tbody> - <tr> - <td><code>-b --binary BINARY</code></td> - <td> - <p>指定二进制文件,使用该版本的火狐。可以用全路径,也可以用相对路径。</p> - - <pre> -<code>jpm run -b /path/to/Firefox/Nightly</code></pre> - 参看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Selecting_a_browser_version">选择浏览器版本</a>。</td> - </tr> - <tr> - <td><code>--binary-args CMDARGS</code></td> - <td> - <p>传递<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options">附件参数</a>到 Firefox。</p> - - <p>例如,为了传递 <code>-jsconsole</code>参数给 Firefox 并打开<a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">浏览器</a>,试试下面命令:</p> - - <pre> -<code>jpm run --binary-args -jsconsole</code></pre> - - <p>要传递多个参数,或者参数中间有空格,就把他们用引号括起来:</p> - - <pre> -<code>jpm run --binary-args '-url mzl.la -jsconsole'</code></pre> - </td> - </tr> - <tr> - <td><code>--debug</code></td> - <td>运行这个 add-on 的<a href="https://developer.mozilla.org/en-US/Add-ons/Add-on_Debugger">Add-on 调试器</a>。</td> - </tr> - <tr> - <td><code>-o --overload PATH</code></td> - <td> - <p>不再使用 Firefox 内建的 SDK 模块,使用指定 PATH 路径下的模块。如果加了 <code>-o</code> 但 PATH 没有指定,jpm 会寻找 JETPACK_ROOT 环境变量用作路径</p> - - <p>参看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Overloading_the_built-in_modules">重载内建模块</a>以获取更多信息</p> - </td> - </tr> - <tr> - <td><code>-p --profile=<code> PROFILE</code></code></td> - <td> - <p>在你每次调用jpm run时,jpm 默认使用一个干净的临时的 Firefox <a href="http://support.mozilla.com/en-US/kb/profiles">配置文件(profile)</a>。使用<code>--profile</code> 选项以使得 jpm 使用已有的配置文件来打开 Firefox。</p> - - <p>PROFILE的值可以是一个profile的名字或路径。</p> - - <p>参看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Using_profiles">使用 profile</a> 以获取更多信息。</p> - </td> - </tr> - <tr> - <td><code>-v --verbose</code></td> - <td>(查看)详细操作</td> - </tr> - <tr> - <td><code>--no-copy</code></td> - <td> - <div class="warning">小心使用,因为 <code>jpm run|test</code> 会改变很多配置,不要和你的主配置文件一起使用。</div> - - <div class="note">只有使用 <code>--profile</code> 的时候回生效</div> - 禁止配置文件的拷贝,允许重用配置。</td> - <td> </td> - </tr> - </tbody> -</table> - -<h3 id="jpm_test">jpm test</h3> - -<p>这个命令用来运行 add-on 的单元测试。命令:</p> - -<ul> - <li>查找在当前目录(或者 <code>--addon-dir</code> 目录)下的test文件夹。</li> - <li>打开所有名字以 "test-" 开头的文件。注意文件名中"test"后面的连字符号。<code>jpm test</code> 包含一个 "test-myCode.js" 文件,但会排除"test_myCode.js"或"test_myCode.js"。</li> - <li>调用文件中所有export的、以"test"开头的函数。</li> -</ul> - -<pre><code>jpm test</code></pre> - -<p>查看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing">单元测试教程</a> 和 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert"> <code>assert</code> 模块参考文档</a>获取更多具体内容。</p> - -<p><code>jpm test</code> 接受一下选项:</p> - -<table> - <tbody> - <tr> - <td><code>-b --binary BINARY</code></td> - <td> - <p>指定所用 Firefox 的版本。BINARY 可被指定为绝对路径或者基于当前路径的相对路径。</p> - - <pre> -<code>jpm test -b /path/to/Firefox/Nightly</code></pre> - - <p>请查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Selecting_a_browser_version">选择一个浏览器版本</a>。</p> - </td> - </tr> - <tr> - <td><code>--binary-args CMDARGS</code></td> - <td> - <p>传递<a href="http://kb.mozillazine.org/Command_line_arguments">附件参数</a>给 Firefox。</p> - - <p>例如,传递 <code>-jsconsole</code> 参数,它会打开<a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">浏览器控制台</a>,试试下面的命令:</p> - - <pre> -<code>jpm test --binary-args -jsconsole</code></pre> - - <p>传递多个参数,或者参数间有空格,请将它们用引号括起来:</p> - - <pre> -<code>jpm test --binary-args '-url mzl.la -jsconsole'</code></pre> - </td> - </tr> - <tr> - <td><code>--debug</code></td> - <td>运行 <a href="https://developer.mozilla.org/en-US/Add-ons/Add-on_Debugger">add-on debugger</a> 附件到当前 add-on 上。</td> - </tr> - <tr> - <td><code>-f --filter FILE[:TEST]</code></td> - <td> - <p>只运行名字和 FILE 匹配的测试文件,且名字匹配 TEST(可选)的测试函数。</p> - - <pre> -<code>jpm test --filter base64:btoa</code></pre> - - <p>上面的命令值会运行名字中含有"base64"的文件,在这些文件中只会运行名字中含有"btoa"的测试函数。</p> - </td> - </tr> - <tr> - <td><code>-o --overload PATH</code></td> - <td> - <p>不使用 Firefox 内建的模块,而使用 PATH 路径下的模块。如果 <code>-o</code> 指定而 PATH 被忽略,jpm会查找 JETPACK_ROOT 环境变量并将其用作路径。</p> - - <p>查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Overloading_the_built-in_modules">重载内建模块</a>以获取更多信息。</p> - </td> - </tr> - <tr> - <td><code>-p --profile<code> PROFILE</code></code></td> - <td> - <p>你每次运行jpm call时,默认地,jpm使用一个干净的临时 Firefox <a href="http://support.mozilla.com/en-US/kb/profiles">配置文件</a>。使用<code>--profile</code> 选项来让 jpm 使用一个现有配置文件来打开火狐。</p> - - <p>PROFILE 的值可以是配置文件的名称或者指向配置文件的路径。</p> - - <p>查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Using_profiles">使用配置文件</a>来获取更多信息。</p> - </td> - </tr> - <tr> - <td><code>--stop-on-error</code></td> - <td> - <p>即使测试失败,jpm test 默认还会继续运行测试。指定 <code>--stop-on-error</code> 的话,会在第一次失败后停止运行测试</p> - - <pre> -<code>jpm test --stop-on-error</code></pre> - </td> - </tr> - <tr> - <td><code>--tbpl</code></td> - <td>用<a href="https://treeherder.mozilla.org/">Treeherder</a> 格式打印 test 的输出</td> - </tr> - <tr> - <td><code>--times NUMBER</code></td> - <td> - <p>运行几遍 test:</p> - - <pre> -<code>jpm test --times 2</code></pre> - </td> - </tr> - <tr> - <td><code>-v --verbose</code></td> - <td>详细操作。</td> - </tr> - <tr> - <td><code>--no-copy</code></td> - <td> - <p>小心使用,因为 <code>jpm run|test</code> 会修改许多首选项,这些首选项在你的主配置文件中从未用过。</p> - - <p>这仅仅在使用 <code>--profile</code> 时生效。</p> - 禁用配置未经的拷贝,允许用户重用配置文件。</td> - </tr> - </tbody> -</table> - -<h3 id="jpm_xpi">jpm xpi</h3> - -<p>这个命令将 add-on 打包为一个 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 文件,这是 Mozilla 附加组件的安装文件的格式。</p> - -<pre><code>jpm xpi</code></pre> - -<p>它会在当前目录(或者 <code>--addon-dir</code> 指定的目录)查找 <code>package.json</code> 文件,并创建相关的 XPI 文件。它忽略任何 ZIP 或 XPI文件(译者注:OSX 上测试下来不会默认忽略这些文件,若要忽略请编辑.jpmignore文件),以及任何测试文件。它会包含其他所有文件。如果你想排除其他文件,查看 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/en-US/Add-ons/SDK/Tools/jpmignore">.jpmignore 文件</a>。</p> - -<p>一旦你构建了一个 XPI 文件,你可以通过提交到 <a href="http://addons.mozilla.org/">addons.mozilla.org</a> 来分发你的附加组件。</p> - -<p><code>jpm xpi</code> 接受下列选项:</p> - -<table> - <tbody> - <tr> - <td><code>-v --verbose</code></td> - <td> - <p>打印详细操作:</p> - - <pre> -<code>jpm xpi -v</code></pre> - </td> - </tr> - </tbody> -</table> - -<h3 id="jpm_post">jpm post</h3> - -<p>这个命令把附加组件打包为 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 后 post 到某个URL。</p> - -<pre><code>jpm post</code></pre> - -<p>查找当前目录(或 <code>--addon-dir</code>)下的<code>package.json</code> 文件,创建 XPI 文件,post 到 <code>--post-url</code>。</p> - -<p><code>jpm post</code> 接受以下选项:</p> - -<table> - <tbody> - <tr> - <td><code>--post-url URL</code></td> - <td> - <p>创建 XPI 文件后,将扩展 post 到这个URL。</p> - - <pre> -<code>jpm post --post-url http://localhost:8888/</code></pre> - - <p>查看<a href="https://www.npmjs.com/package/jpm#using-post-and-watchpost">使用 Post 和 Watchpost</a> 获取更多信息。</p> - </td> - </tr> - <tr> - <td><code>-v --verbose</code></td> - <td> - <p>打印详细操作:</p> - - <pre> -<code>jpm post --post-url http://localhost:8888/ -v</code></pre> - </td> - </tr> - </tbody> -</table> - -<h3 id="jpm_watchpost">jpm watchpost</h3> - -<p>这个命令在打包附件组件为 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 文件后,无论文件是否改变都将其 post 到某个URL。</p> - -<pre><code>jpm watchpost</code></pre> - -<p>无论文件是否改变,在当前目录(或 <code>--addon-dir</code>)下创建一个 XPI并将其post到 <code>--post-url</code>。</p> - -<p><code>jpm watchpost</code> 接受以下选项:</p> - -<table> - <tbody> - <tr> - <td><code>--post-url URL</code></td> - <td> - <p>创建 XPI 文件后,将扩展 post 到这个URL。</p> - - <pre> -<code>jpm watchpost --post-url http://localhost:8888/</code></pre> - - <p>查看 <a href="https://www.npmjs.com/package/jpm#using-post-and-watchpost">Using Post 和 Watchpost</a> 获取更多信息。</p> - </td> - </tr> - <tr> - <td><code>-v --verbose</code></td> - <td> - <p>打印详细信息:</p> - - <pre> -<code>jpm watchpost --post-url http://localhost:8888/ -v</code></pre> - </td> - </tr> - </tbody> -</table> - -<h3 id="jpm_sign">jpm sign</h3> - -<p>此特性仅从 jpm 1.0.4 起被支持。</p> - -<p>此命令为你的附加组件重新生成一个新的被Mozilla签名的 <a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a> 文件。这就允许你<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">自己托管你的 add-on</a>,这样用户可以在安装时避免 <a href="https://wiki.mozilla.org/Add-ons/Extension_Signing">signed add-ons are required</a> 错误。在用这个命令之前,你需要<a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">在 addons.mozilla.org 创建 API 证书</a>。</p> - -<p>你可以为你已经生成的 XPI 文件签名,就像如下,通过传递 XPI 文件给 <code>--xpi</code>参数:</p> - -<pre id="comment_text_2"><code>jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET} --xpi <xpi file></code></pre> - -<p>或者,你可以省略 <code>--xpi</code> 参数,这样 <code>jpm sign</code> 会从当前目录(或者 <code>--addon-dir</code>)生成一个XPI文件。</p> - -<pre><code>jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET}</code></pre> - -<p>上面提交了一个 <a href="https://developer.mozilla.org/en-US/docs/XPI/">XPI</a> 到 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> <a href="http://olympia.readthedocs.org/en/latest/topics/api/signing.html">签名g API</a>,如果通过验证,然后下载一个签名后的 XPI 文件到工作目录。</p> - -<p>下面是一些运行 <code>sign</code> 命令的结果:</p> - -<ul> - <li>你的 add-on 通过验证,被 Mozilla 签名,并且一个新的签名后的 <a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a> 文件被下载到你的工作目录。</li> - <li>你的 add-on 没有通过验证,没有签名,你获取到一个详细报告的链接。修复验证错误以后,你可以再次运行这个命令。</li> - <li>你的 add-on 公公验证,但是它不能自动签名,因为你的 add-on 是<a href="https://developer.mozilla.org/en-US/Add-ons/Distribution">列表上的</a>。列表上的 add-ons 需要人工复核才能被签名。</li> - <li>你的 add-on 已经存在某个版本号了,所以它没有被签名。增加 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件中的版本号并且再次运行命令。</li> -</ul> - -<p>在底层,<code>jpm sign</code> 在<a href="https://addons.mozilla.org/">addons.mozilla.org</a>里创建了一个不会被列出的附加组件,这就意味着你必须自己把XPI文件分发给你的用户来安装。如果你需要创建一个在列表中的附加组件,只要<a href="https://addons.mozilla.org/en-US/developers/addon/submit/2">直接将它提交到 addons.mozilla.org</a>,在那里它自动会被签名。如果你在安装一个已签名的附加组件时遇到困难,参看<a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Debugging_and_solving_problems">调试</a>一节。</p> - -<p><code>jpm sign</code> 接收以下参数:</p> - -<table> - <tbody> - <tr> - <td><code>--api-key=API_KEY</code></td> - <td> - <p><a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">addons.mozilla.org key管理页面</a>生成的API访问key(字符串)。</p> - </td> - </tr> - <tr> - <td><code>--api-secret=API_SECRET</code></td> - <td> - <p><a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">addons.mozilla.org key 管理页面</a>生成的API访问密钥(字符串)。这个值应该被小心保密并且永远不要记录到版本控制中。如果你的密钥被破解,另一个开发者就能上传附加组件到你的账号上。你应该立即撤销泄露的API证书并且重新生成一份。</p> - </td> - </tr> - <tr> - <td><code>--api-url-prefix=http://.../api</code></td> - <td> - <p>可选的API URL前缀,如果你想使用一个试用签名的API。</p> - - <p>例如,你可以通过<code>https://addons-dev.allizom.org/api/v3</code>的认证来使用<a href="https://addons.mozilla.org/">addons.mozilla.org</a>的开发者版本。</p> - </td> - </tr> - <tr> - <td><code>--xpi=/path/to/file.xpi</code></td> - <td> - <p>需要签名的<a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a>文件。如果没指定文件,一个新的XPI会在当前目录(或者<code>--addon-dir</code>)中生成。</p> - </td> - </tr> - </tbody> -</table> - -<h2 id="一些技巧">一些技巧</h2> - -<h3 id="选择浏览器版本">选择浏览器版本</h3> - -<p>默认地,<code>jpm run</code> 和 <code>jpm test</code> 运行 release 版本的 FireFox。你可以有一两种办法来告诉 jpm 使用一个不同的版本:</p> - -<ul> - <li> - <p>你可以使用 <code>-b</code> 或者 <code>--binary</code> 选项来告诉 jpm 去使用一个不同版本的 Firefox。你可以提供一个指定二进制文件的路径:</p> - - <pre><code>jpm run -b /path/to/Firefox/Nightly</code></pre> - - <p>有个简化的方法,你可以传递"nightly"、"aurora"、"beta"或者"firefox"然后jpm会在默认位置寻找这些 Firefox 的版本:</p> - - <pre><code>jpm run -b nightly</code></pre> - </li> - <li> - <p>你可以设置 <code>JPM_FIREFOX_BINARY</code> 环境变量为你想运行的 Firefox 版本的路径。在你调用 <code>jpm run</code> 或 <code>jpm test</code> 而不带 <code>-b</code> 选项时,jpm 首先检查 <code>JPM_FIREFOX_BINARY</code>,并且将其当做已设置的路径来用。</p> - </li> -</ul> - -<h3 id="使用_.jpmignore_来忽略文件">使用 <code>.jpmignore</code> 来忽略文件</h3> - -<p>使用 <code>.jpmignore</code> 就像使用 <code>git</code> 的<code>.gitignore</code>,Mercurial 的 <code>.hgignore</code>,或者 npm 的 <code>.npmignore</code>。通过使用这个文件,你可以在使用 <code>jpm xpi</code> 编译 <code>.xpi</code> 文件时,让 <code>jpm</code> 知道你想要忽略哪些文件。</p> - -<p>这是个例子:</p> - -<pre><code># Ignore .DS_Store files created by mac -.DS_Store - -# Ignore any zip or xpi files -*.zip -*.xpi</code></pre> - -<p>有着以上内容的 <code>.jpmignore</code> 文件会忽略所有的 zip 文件和 <code>.DS_Store</code> 文件,这些文件不会包括在 <code>jpm xpi</code> 所生成的 xpi 文件中。</p> - -<h3 id="使用配置"><a name="Using_profiles">使用配置</a></h3> - -<p>默认地,<code>jpm run</code> 每次都会使用一个新的配置。这就意味着前一次运行 <code>jpm</code> 时的任何配置,默认都不会在下一次中使用。</p> - -<p>这其中包括,比如你安装的任何附加组件,或者你的历史记录,或者任何使用 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/simple-storage">simple-storage</a> API 存储的数据。</p> - -<p>为了让 <code>jpm</code> 使用一个特定的配置,传递 <code>--profile</code> 选项,设定你想使用的配置文件的名字,或者是配置文件的路径。</p> - -<pre><code>jpm run --profile boogaloo</code></pre> - -<pre><code>jpm run --profile path/to/boogaloo</code></pre> - -<p>如果你提供了 <code>--profile</code> 但是它的参数不是一个已有配置文件的名字或路径,jpm 会打开 <a href="https://support.mozilla.org/en-US/kb/profile-manager-create-and-remove-firefox-profiles">配置文件管理器</a> 让你选择一个已有的配置文件或者创建一个新的配置文件:</p> - -<pre><code>jpm run --profile i-dont-exist</code></pre> - -<h3 id="开发时不用重启浏览器">开发时不用重启浏览器</h3> - -<p>因为每次调用 <code>jpm run</code> 时都会重启浏览,如果你十分频繁地修改附加组件,这就可能有点笨重了。一个替代的开发模型是使用 <a href="https://addons.mozilla.org/en-US/firefox/addon/autoinstaller/" rel="noreferrer">扩展自动安装器</a>附加组件:它会在特定端口监听新 XPI 文件并且自动安装它们。这样,你就能测试新的改动,而不用重启浏览器:</p> - -<ul> - <li>修改附件组件</li> - <li>运行 <code>jpm post --post-url http://localhost:8888/</code>,来创建 XPI 文件并提交。</li> -</ul> - -<p>你甚至可以用一个简单的脚本来自动化这一工作流程。例如:</p> - -<pre><code>jpm watchpost --post-url http://localhost:8888/</code></pre> - -<p>注意,比起使用 <code>jpm run</code> 运行附加组件时的日志级别,你在使用这个方法时控制台定义的日志级别是不一样的。这意味着,如果你想看到 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Logging" rel="noreferrer"><code>console.log()</code></a> 消息的输出,你必须微调一下配置。查看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/console#Logging_Levels" rel="noreferrer">logging levels</a> 文档以获取这方面的详细信息。</p> - -<h3 id="重载内建模块">重载内建模块</h3> - -<p>你用来实现你的附加组件的SDK模快是 Firefox 内建的。当你使用 <code>jpm run</code> 或 <code>jpm xpi</code> 来运行或者打包附加组件时,附加组件使用其所在的 Firefox 版本中的模块版本。</p> - -<p>作为附件组件开发者,这一般就是你想要的。但是如果你在开发 SDK 模块本身,这就不合适了。这时你需要:</p> - -<ul> - <li>获取你想要的 SDK 模块的本地拷贝:一般来说就是从 <a href="https://github.com/mozilla/addon-sdk" rel="noreferrer">GitHub 仓库</a>中检出SDK。</li> - <li>设置 <code>JETPACK_ROOT</code> 环境变量,指向你的本地拷贝</li> - <li>传递 <code>-o</code> 选项到 <code>jpm run</code> 或 <code>jpm xpi</code>:</li> -</ul> - -<pre><code>jpm run -o</code></pre> - -<p>这会通知 jpm 去使用 SDK 模块的本地拷贝,而不是 Firefox 内部的模块。如果你不想设置 <code>JETPACK_ROOT</code> 环境变量,你可以使用 <code>-o</code> 传递SDK模块本地拷贝的位置:</p> - -<pre><code>jpm run -o "/path/to/addon-sdk/"</code></pre> - -<p>路径必须是一个绝对路径并且指向 SDK 的根目录(不是 addon-sdk/sdk 或 addon-sdk/sdk/lib)。</p> - -<h3 id="支持自托管附加组件的更新">支持自托管附加组件的更新</h3> - -<p>此特性仅被 jpm 1.0.3 及之后版本支持,</p> - -<p>当你给你的附加组件来添加特性或者修复 bug 时,你想让之前安装好的附加组件将自己从老版本更新到新版本。</p> - -<p>如果你在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上列出你的附加组件,那么你要做的只是提交一个新的版本;附加组件默认会检查它们在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上的新版本。好了,你不用继续往下看这一节了。</p> - -<p>如果你没有在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上列出你的附加组件,你需要生成一个 Mozilla 签名的 XPI 文件并告诉 Firefox 哪里可以找到这个附加组件的新版本。方法就是:</p> - -<ul> - <li>每次你想要创建一个新版本时,你运行 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign">jpm sign</a></li> - <li>当你需要更新时,更新由你托管的签名好的附加组件</li> - <li>你维护一个“更新清单”,包含了指向那个 XPI 的URL</li> - <li>你的附加组件告诉 Firefox 哪里可以找到更新清单</li> -</ul> - -<p>为了达到这个目的,package.json中需要包含两个额外的key :</p> - -<ul> - <li><code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateURL">updateURL</a></code>:这个 URL 包含在 <code>jpm xpi</code> 所编译的 XPI 文件的<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/Install_Manifests">安装清单</a>中。他指向了你的更新清单。<code>updateURL</code> 值<em>可以</em>是HTTPS的。如果不是,那么你也可以签名的更新清单,并且使用 package.json 文件中的 <code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateKey">updateKey</a></code> 字段来包含其公钥。参看 <a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Securing_Updates">安全地更新</a> 以获取这方面更多信息</li> - <li><code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateLink">updateLink</a></code>:这个 URL 包含在那个更新清单文件中。它指向了 XPI,并且<em>必须</em>是一个 HTTPS URL。</li> -</ul> - -<p><img alt="" src="https://mdn.mozillademos.org/files/11847/addons-update.svg" title="[https://mdn.mozillademos.org]"></p> - -<p>如果你设置了 <code>updateURL</code> 和 <code>updateLink</code>(如果 <code>updateKey</code> 不是 HTTPS 的,那也要包括 <code>updateKey</code>),那么 <code>jpm xpi</code> 会:</p> - -<ul> - <li>生成 XPI 文件时将 <code>updateURL</code> 设置为你提供的值。</li> - <li>和 XPI 文件一起,生成更新清单,并将清单中的 <code>updateURL</code> 设置为你提供的值。</li> -</ul> - -<p>然后你将更新清单托管到 <code>updateURL</code>,并且将新版 XPI 托管到 <code>updateLink</code>。</p> - -<p>获取更多这方面的详细信息,参看<a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning,_Update_and_Compatibility#Automatic_Add-on_Update_Checking">自动检查附件组件更新</a>。</p> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html deleted file mode 100644 index cd08ff2b64..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html +++ /dev/null @@ -1,312 +0,0 @@ ---- -title: package.json -slug: Mozilla/Add-ons/SDK/Tools/package_json -translation_of: Archive/Add-ons/Add-on_SDK/Tools/package_json ---- -<p>{{AddonSidebar}}</p> - -<p><span class="seoSummary">The <code>package.json</code> file contains manifest data for your add-on, providing not only descriptive information about the add-on for presentation in the Add-ons Manager, but other metadata required of add-ons.</span></p> - -<p>一些条目, 比如<a href="/en-US/Add-ons/SDK/Tools/package_json#icon"><code>icon</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#name"><code>name</code></a>和<a href="/en-US/Add-ons/SDK/Tools/package_json#description"><code>description</code></a>, 有类似<a href="https://developer.mozilla.org/en-US/docs/Install_Manifests">install manifest</a>的格式, 并且<code>package.json会写入</code>install manifest, 当使用<a href="/en-US/Add-ons/SDK/Tools/jpm#jpm_xpi"><code>jpm xpi</code></a><code>的时候.</code></p> - -<p>Others, such as <a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions"><code>permissions</code></a>, and <a href="/en-US/Add-ons/SDK/Tools/package_json#preferences"><code>preferences</code></a>, represent instructions to the <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> tool itself to generate and include particular code and data structures in your add-on.</p> - -<p>其他如<a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions"><code>permissions</code></a>和<a href="/en-US/Add-ons/SDK/Tools/package_json#preferences"><code>preferences</code></a>表示使用<a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>工具的步骤, 生成你扩展包含的特殊代码和数据结构.</p> - -<h2 id="创建manifest">创建manifest</h2> - -<p><code>package.json起初是通过运行</code><a href="/en-US/Add-ons/SDK/Tools/jpm#jpm_init"><code>jpm init</code></a>生成的<code>,通常在扩展的根目录.比如下面(假设扩展目录是</code>"my-addon"<code>)</code></p> - -<pre class="brush: json">{ - "name": "my-addon", - "title": "my-addon", - "id": "jid1-1FERGV45e4f4f", - "description": "a basic add-on", - "author": "", - "license": "MPL-2.0", - "version": "0.1" -}</pre> - -<p>如果你使用新的<a href="/en-US/Add-ons/SDK/Tools/jpm">jpm tool</a>话,可以方便的从package.json获取manifest数据, 通过require其他模块的方式:</p> - -<pre class="brush: js" id="comment_text_1">var title = require("./package.json").title;</pre> - -<h2 id="Key_reference">Key reference</h2> - -<p><code>package.json</code> may contain the following keys:</p> - -<table class="standard-table"> - <tbody> - <tr> - <td id="author"><code>author</code></td> - <td> - <p>The name of the package's original author; this could be the name of a person or a company. Defaults to an empty string. It may include a optional URL in parentheses and an email address in angle brackets.</p> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#creator"><code>em:creator</code></a> element in the <code>install.rdf</code> file generated by <code>cfx</code>.</p> - - <div class="note"><strong>Note:</strong> <a href="https://developer.mozilla.org/Add-ons/SDK/Tools/jpm">jpm</a> supports <a href="https://docs.npmjs.com/files/package.json#people-fields-author-contributors">NodeJS people fields</a>.</div> - </td> - </tr> - <tr> - <td id="contributors"><code>contributors</code></td> - <td> - <p>An array of additional <a href="/en-US/Add-ons/SDK/Tools/package_json#author"><code>author</code></a> strings, identifying other contributors to the add-on.</p> - - <p>These values will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#contributor"><code>em:contributor</code></a> elements in its <code>install.rdf</code>.</p> - - <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div> - </td> - </tr> - <tr> - <td id="dependencies"><code>dependencies</code></td> - <td> - <p>A string or an array of strings specifying the names of packages that this add-on requires in order to function properly.</p> - </td> - </tr> - <tr> - <td id="description"><code>description</code></td> - <td> - <p>The add-on's description; this is a human-readable message describing what the add-on does. This defaults to the text "a basic add-on".</p> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#description"><code>em:description</code></a> element in its <code>install.rdf</code>.</p> - </td> - </tr> - <tr> - <td id="engines"><code>engines</code></td> - <td> - <p>Object with supported applications (key) and required version numbers (value).</p> - - <ul> - <li><code>firefox</code>: Firefox Desktop</li> - <li><code>fennec</code>: Firefox for Android</li> - </ul> - - <p>Example:</p> - - <pre> -<code> "engines": { - "firefox": ">=38.0a1", - "fennec": ">=38.0a1" - }</code></pre> - </td> - </tr> - <tr> - <td id="fullName"><code>fullName</code> {{deprecated_inline}}</td> - <td> - <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div> - - <p>The full name of the package. It can contain spaces.</p> - - <p>If this key is present its value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p> - </td> - </tr> - <tr> - <td id="harnessClassID"><code>harnessClassID</code> {{deprecated_inline}}</td> - <td> - <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div> - - <p>String in the <a href="https://developer.mozilla.org/en-US/docs/Generating_GUIDs">GUID format</a>.</p> - - <p>This is used as a <a href="https://developer.mozilla.org/en-US/docs/Creating_XPCOM_Components/An_Overview_of_XPCOM#CID"><code>classID</code></a> of the "harness service" XPCOM component. Defaults to a random GUID generated by <code>cfx</code>.</p> - </td> - </tr> - <tr> - <td id="homepage"><code>homepage</code></td> - <td> - <p>The URL of the add-on's website.</p> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#homepageURL"><code>em:homepageURL</code></a> element in its <code>install.rdf</code>.</p> - </td> - </tr> - <tr> - <td id="icon"><code>icon</code></td> - <td> - <p>The path to an image file containing the icon for the add-on. Defaults to <code>icon.png</code>. If no icon is specified, the standard add-on icon will be used by default.</p> - - <div class="warning"> - <p>When using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>, relative path to the data directory (to make it re-usable for add-on HTML content) does not currently work. Instead you have to use following syntax:</p> - - <p>resource://ID/data/icon-name.png</p> - - <p>ID is the value from the <code>id </code>field. If it does <strong>not</strong> begin with the <code>@</code>-character, then <code>@</code> has to be escaped as <code>-at-</code> and <code>.</code> as <code>-dot-</code>. If the ID is a GUID, the curly braces used in the <code>id</code> field are <strong>not</strong> included.</p> - </div> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#iconURL"><code>em:iconURL</code></a> element in its <code>install.rdf</code>.</p> - - <p>The icon may be up to 48x48 pixels in size (although a bigger icon is tolerated here too)</p> - </td> - </tr> - <tr> - <td id="icon64"><code>icon64</code> {{deprecated_inline}}</td> - <td> - <div class="note"> - <p><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - - <p><span style="background-color: rgba(212, 221, 228, 0.14902);">The path to an image</span> containing the large icon for the add-on. Defaults to <code>icon64.png</code>. If you don't provide an icon here, the same icon as specified by <code>icon</code> will be used.</p> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#icon64URL"><code>em:icon64URL</code></a> element in its <code>install.rdf</code>.</p> - - <p>The icon may be up to 64x64 pixels in size.</p> - </td> - </tr> - <tr> - <td id="id"><code>id</code></td> - <td> - <p>A globally unique identifier for the add-on.</p> - - <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#id"><code>em:id</code></a> element in its <code>install.rdf</code>.</p> - - <p>See the <a href="/en-US/Add-ons/SDK/Guides/Program_ID">Program ID documentation</a>.</p> - </td> - </tr> - <tr> - <td><code>lib</code></td> - <td> - <p>String representing the top-level module directory provided in this add-on. Defaults to "lib".</p> - - <div class="note"> - <p><strong>Note:</strong> This is deprecated along with <code>cfx</code> and is not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="license"><code>license</code></td> - <td> - <p>The name of the license under which the add-on is distributed, with an optional URL in parentheses. Defaults to <code>"MPL-2.0"</code>.</p> - - <div class="note"> - <p><strong>Note</strong>: It is recommend that you use an <a href="https://spdx.org/licenses/">SPDX license ID</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="main"><code>main</code></td> - <td> - <p>A string representing the name of a program module that is located in one of the top-level module directories specified by <a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>. Defaults to <code>"main"</code>.</p> - </td> - </tr> - <tr> - <td id="name"><code>name</code></td> - <td> - <p>The add-on's name. This name cannot contain spaces or periods, and defaults to the name of the parent directory.</p> - - <p>When the add-on is built as an XPI, if the <a href="/en-US/Add-ons/SDK/Tools/package_json#fullName"><code>fullName</code></a> and <a href="/en-US/Add-ons/SDK/Tools/package_json#title"><code>title</code></a> keys are not present, <code>name</code> is used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p> - </td> - </tr> - <tr> - <td id="packages"><code>packages</code></td> - <td> - <div class="note"> - <p><strong>Note:</strong> This is deprecated along with <code>cfx</code> and is not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - - <p>A string pointing to a directory containing additional packages. Defaults to <code>"packages"</code>.</p> - </td> - </tr> - <tr> - <td id="permissions"><code>permissions</code></td> - <td> - <p>A set of permissions that the add-on needs.</p> - - <p><strong><code>private-browsing</code></strong>: a boolean indicating whether or not the add-on supports private browsing. If this value is not <code>true</code> or is omitted, then the add-on will not see any private windows or objects, such as tabs, that are associated with private windows. See the documentation for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing"><code>private-browsing</code> module</a>.</p> - - <p><strong><code>cross-domain-content</code></strong>: a list of domains for which content scripts are given cross-domain privileges to access content in iframes or to make XMLHTTPRequests. See the documentation for <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts">enabling cross-domain content scripts</a>.</p> - - <p><strong><code>multiprocess</code></strong>: a Boolean value declaring whether this add-on is, or is not, compatible with <a href="/en-US/Add-ons/Working_with_multiprocess_Firefox">multiprocess Firefox</a>.</p> - - <div class="note"> - <p><strong>Note</strong> the <code>multiprocess</code> permission is not supported by <a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="preferences"><code>preferences</code></td> - <td> - <p>An array of <a href="/en-US/docs/Glossary/JSON">JSON</a> objects that use the following keys: <code>name</code>,<code>type</code>, <code>value</code>, <code>title</code>, and <code>description</code>. These JSON objects will be used to create a preferences interface for the add-on in the Add-ons Manager.</p> - - <p>See the documentation for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs"><code>simple-prefs</code> module</a>.</p> - </td> - </tr> - <tr> - <td id="preferences-branch"><code>preferences-branch</code></td> - <td>Use this to specify an alternative branch for your add-on's simple-prefs. See <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs#Simple-prefs_in_the_preferences_system">"Simple-prefs in the preferences system"</a> for more details.</td> - </tr> - <tr> - <td id="title"><code>title</code></td> - <td> - <p>The human-readable title of the package; this can contain spaces.</p> - - <p>If this key is present its value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p> - </td> - </tr> - <tr> - <td id="translators"><code>translators</code></td> - <td> - <p>An array of strings listing the people who contributed to the localization of this add-on.</p> - - <p>These values will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#translator"><code>em:translator</code></a> elements in its <code>install.rdf</code>.</p> - - <div class="note"><strong>Note:</strong> <a href="https://developer.mozilla.org/Add-ons/SDK/Tools/jpm">jpm</a> supports <a href="https://docs.npmjs.com/files/package.json#people-fields-author-contributors">NodeJS people fields</a>.</div> - </td> - </tr> - <tr> - <td id="unpack"><code>unpack</code></td> - <td> - <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#unpack">unpack</a></code> in an <code>install.rdf</code> file.</p> - - <p>Useful when the extension contains binaries.</p> - </td> - </tr> - <tr> - <td id="updateKey"><code>updateKey</code></td> - <td> - <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#updateKey">updateKey</a></code> in an <code>install.rdf</code> file.</p> - - <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p> - - <div class="note"> - <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="updateLink"><code>updateLink</code></td> - <td> - <p>Same as the <code><a href="/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Securing_Updates">updateLink</a></code> for an <code>update.rdf</code> file. Previously was <code><a href="/en-US/Add-ons/SDK/Tools/cfx#updateURL_and_updateLink">--update-link in cfx</a></code>.</p> - - <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p> - - <div class="note"> - <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="updateURL"><code>updateURL</code></td> - <td> - <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#updateURL">updateURL</a></code> for an <code>install.rdf</code> file.</p> - - <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p> - - <div class="note"> - <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p> - </div> - </td> - </tr> - <tr> - <td id="version"><code>version</code></td> - <td> - <p>String representing the version of the add-on. Defaults to "0.0.1".</p> - - <p>This value is used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#version"><code>em:version</code></a> element in its <code>install.rdf</code>.</p> - - <div class="note"> - <p><strong>Note:</strong> For <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> the version must be a valid <a href="http://semver.org/">semver</a>.</p> - </div> - </td> - </tr> - </tbody> -</table> - -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html deleted file mode 100644 index 29348bbabb..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Add a Menu Item to Firefox -slug: Mozilla/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Add_a_Menu_Item_to_Firefox ---- -<div class="note"> - <p>学习本模块你需要 <a href="/en-US/Add-ons/SDK/Installation">安装SDK</a> 学习基础工具<a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code></a>.</p> -</div> -<div class="note"> - <p>如果你使用 <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> 替代cfx, 使用第三方模块的方式是不同的, 你应该阅读 <a href="/en-US/Add-ons/SDK/Tutorials/Using_third-party_modules_%28jpm%29">jpm</a>的相应版本替代本教程.</p> - <p>给予Python可能未来废弃,使用JPM基于nodejs(译者备注).</p> -</div> -<p class="ordinary-output target-output"><span>SDK还不能为<span>火狐浏览器</span>提供一个API添加新的菜单项。</span><span>但它是可扩展的设计,所以任何人都可以建立和发布模块,使用插件开发者。</span><span>幸运的是</span><span>,</span><span>埃里克</span><span>沃尔德</span><span>写的</span><a href="https://github.com/mykmelez/menuitems-jplib"><span>MenuItems</span></a><span>模块,</span><span>能够使我们</span><span>添加菜单项</span><span>。</span></p> -<p class="ordinary-output target-output"><span>本教程有双重的责任。</span><span>它描述的一般</span><span>方法,</span><span>使用一个外部的</span><span>,</span><span>在你的</span><span>插件</span><span>的第三方</span><span>模块</span><span>,</span><span>并</span><span>描述了如何</span><span>使用</span><span>特别的</span><span>MenuItems</span><span>模块</span><span>添加一个菜单项</span><span>。</span></p> -<p class="ordinary-output target-output"><span>首先,创建一个新的扩展程序。</span><span>创建一个</span><span>目录名称为</span><span>“</span><span>clickme</span><span>”</span><span>(名称随意)</span><span>,</span><span>找到它并运行</span><code>cfx init</code><span>初始化</span><span>。</span></p> -<pre>mkdir clickme -cd clickme -cfx init -</pre> -<p>通常将创建目录结构:</p> -<ul> - <li>clickme - <ul> - <li>data</li> - <li>docs - <ul> - <li>main.md</li> - </ul> - </li> - <li>lib - <ul> - <li>main.js</li> - </ul> - </li> - <li>package.json</li> - <li>README.md</li> - <li>tests - <ul> - <li>test-main.js</li> - </ul> - </li> - </ul> - </li> -</ul> -<div> - </div> -<h2 id="安装_menuitems"><code>安装 menuitems</code></h2> -<p>在 "clickme"下创建一个名称为"packages"的目录. 从 <a href="https://github.com/mykmelez/menuitems-jplib/zipball/4d6ae5b410d79cc16c9c76920fbaa8a367e44ca7">https://github.com/mykmelez/menuitems-jplib</a> 下载 <code>menuitems 并展开到刚才创建的</code>"packages" 目录下:</p> -<pre>mkdir packages -cd packages -tar -xf ../erikvold-menuitems-jplib-d80630c.zip -</pre> -<h2 id="模块依赖">模块依赖</h2> -<p class="ordinary-output target-output"><span>如果</span><span>第三方模块</span><span>只</span><span>取决于</span><span>SDK</span><span>模块</span><span>,</span><span>你</span><span>可以马上</span><span>使用它们</span><span>,</span><span>但如果</span><span>他们依赖于其他</span><span>第三方模块</span><span>,</span><span>你需要安装</span><span>的</span><span>依赖</span><span>以及</span><span>。</span></p> -<p><span class="high-light-bg">在软件包的主目录,你会发现一个叫做</span> "package.json"的文件. <span>打开它,看看一个</span>名称"dependencies"的入口. <code>menuitems</code> 包的入口:</p> -<pre>"dependencies": ["vold-utils"] -</pre> -<p>这告诉我们需要安装 <code>vold-utils</code> 包, 我们可以从<a href="https://github.com/mykmelez/vold-utils-jplib/zipball/a321447dc5d613df33023165854957c181dc3174">https://github.com/mykmelez/vold-utils-jplib</a> 下载,并添加到 <code>packages</code> 目录<code>下的旁边的menuitems</code>.</p> -<h2 id="使用menuitems"><code>使用menuitems</code></h2> -<p> <a href="https://github.com/mykmelez/menuitems-jplib/blob/master/docs/menuitems.md"><code>Menuitems</code>模块文档</a> <code>告诉使用MenuItem()创建一个新的菜单项</code>. <code>MenuItem()可接受的附加选项</code>, 我们将使用最迷你的配置:</p> -<ul> - <li><code>id</code>: 菜单项标示符</li> - <li><code>label</code>:菜单项线上的文本</li> - <li><code>command</code>: 用户选择菜单项的响应函数</li> - <li><code>menuid</code>: 菜单项的父类标示符</li> - <li><code>insertbefore</code>: 我们希望出现的标示符之前的位置</li> -</ul> -<div> - <div> - <pre class="brush: js">var menuitem = require("menuitems").Menuitem({ - id: "clickme", - menuid: "menu_ToolsPopup", - label: "Click Me!", - onCommand: function() { - console.log("clicked"); - }, - insertbefore: "menu_pageInfo" -});</pre> - <div> - </div> - </div> -</div> -<p>接下来, 我们将<code>声明menuitems</code>的依赖包. 在你的add-on's <code>package.json文件添加一行</code>:</p> -<pre>"dependencies": "menuitems" -</pre> -<p>Note that due to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=663480">bug 663480</a>, if you add a <code>dependencies</code> line to <code>package.json</code>, and you use any modules from the SDK, then you must also declare your dependency on that built-in package, like this:</p> -<pre>"dependencies": ["menuitems", "addon-sdk"] -</pre> -<p class="ordinary-output target-output"><span>现在我们要做的。</span><span>运行</span><span>插件</span><span>,</span><span>你会</span><span>看到新的项目</span><span>出现在工具</span><span>菜单:</span><span>选择它,</span><span>你会看到</span><code>info: clicked </code><span>出现在</span><span>控制台</span><span>。</span></p> -<h2 id="Caveats">Caveats</h2> -<p class="ordinary-output target-output"><span>第三方</span><span>模块</span><span>使用</span><span>不直接支持的</span><span>SDK功能</span><span>的好方法,</span><span>但由于</span><span>第三方模块</span><span>通常使用</span><span>低级别的</span><span>API</span><span>,</span><span>它们可以通过</span><span>Firefox的</span><span>新版本</span><span>了</span><span>。</span></p> -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html deleted file mode 100644 index 8e4438f818..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: 在工具栏上添加按钮 -slug: Mozilla/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Adding_a_Button_to_the_Toolbar ---- -<div class="note"> -<p>动手之前,必须先<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/安装">安装SDK</a>并学习<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_With_cfx"><code>cfx</code>基础</a>.</p> - -<p>这篇教程使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API,需要Firefox 29或更新版本。</p> -</div> - -<p>如果要给工具栏添加一个按钮,需要使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>或<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>模块。</p> - -<p>新建一个目录,打开它,执行<code>cfx init</code>。</p> - -<p>然后,把这三个图标保存到data文件夹:</p> - -<table class="standard-table"> - <tbody> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td> - <td>icon-16.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td> - <td>icon-32.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td> - <td>icon-64.png</td> - </tr> - </tbody> -</table> - -<p>随后打开lib目录下的main.js文件,添加如下代码:</p> - -<pre class="brush: js">var buttons = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = buttons.ActionButton({ - id: "mozilla-link", - label: "Visit Mozilla", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -function handleClick(state) { - tabs.open("https://www.mozilla.org/"); -}</pre> - -<p>现在输入<code>cfx run</code>来执行附加组件。按钮添加到了浏览器顶部的工具栏上:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7641/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">你无法设置按钮的初始位置,但是用回可以使用浏览器的自定义功能移动它。其中的<code>id</code>属性是必需的,用来记录按钮的位置,因此,你最好不要在后续版本中修改它。</p> - -<p>单击按钮,<a href="https://www.mozilla.org/en-US/">https://www.mozilla.org/</a>将会在新的标签页中加载。</p> - -<h2 id="设定图标">设定图标</h2> - -<p>icon属性可以设定单个或是一组不同大小图标。如果你用的是一组不同大小的图标,浏览器将会自动选择最适合当前屏幕分辨率的,然后显示在浏览器界面的按钮上。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#ActionButton(options)">更多内容,参考设定多个图标</a>。</p> - -<p>图标文件必须打包在附加组件内:它不可以指向一个远程文件。</p> - -<p>你只要正确地设置了按钮的<code>icon</code>属性,它就会立刻生效。你可以改变全局的,在特定窗口的或者是特定标签页中显示的图标或者是其他状态属性。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Updating_state">更多内容,参考更新状态</a>。</p> - -<h2 id="附加一个面板">附加一个面板</h2> - -<p>如果你想把一个面板附加到按钮上,使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>API。这就和动作按钮API类似,只不过多了一个boolean值属性,表示按钮是否被<code>checked</code>。附加面板,要把按钮传递给面板的<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a>方法。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle#Attaching_panels_to_buttons">更多细节,参考切换按钮文档</a>。</p> - -<h2 id="显示更多样的内容">显示更多样的内容</h2> - -<p>添加按钮做不到的复杂界面功能,需要使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_toolbar">工具栏</a>API。 使用工具栏API你可以得到一个用户界面内容的水平条。可以添加按钮或者是可以包含HTML,CSS,javaScript的<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_frame">frame</a>到工具栏上。</p> - -<h2 id="进一步学习">进一步学习</h2> - -<ul> - <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮参考</a></li> - <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮参考</a></li> - <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_toolbar">工具栏参考</a></li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html deleted file mode 100644 index 04e4a75d23..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: 实现控件 -slug: Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget -tags: - - 附加组件 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator/Implementing_the_widget ---- -<p>我们想要控件做两件事:</p> - -<ul> - <li>点击鼠标左键,控件应当启用或禁用注释器。</li> - <li>点击鼠标右键,控件应当显示用户创建注释的清单。</li> -</ul> - -<p>因为控件无法区分鼠标左右键的点击,我们应当使用内容脚本来捕获单击事件并发送相应的消息到附加组件。</p> - -<p>控件将有两个图标:一个在注释器启用时显示,一个在禁用时显示。</p> - -<p>因此,我们需要创建三个文件:控件的内容脚本和两个图标。</p> - -<p>在data子目录创建一个widget子目录,我们将把控件的文件保存在这里(注意,这个不是强制性的:你可以仅仅把它们放在data里,但分类放置会更加整洁)。</p> - -<h2 id="控件的内容脚本">控件的内容脚本</h2> - -<p>控件的内容脚本仅仅监听鼠标的左右单击并发送相应的消息到附加组件代码:</p> - -<pre class="brush: js">this.addEventListener('click', function(event) { - if(event.button == 0 && event.shiftKey == false) - self.port.emit('left-click'); - - if(event.button == 2 || (event.button == 0 && event.shiftKey == true)) - self.port.emit('right-click'); - event.preventDefault(); -}, true);</pre> - -<p>把它保存在data/widget并命名为widget.js。</p> - -<h2 id="控件图标">控件图标</h2> - -<p>你可以从这里复制图标:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6673/pencil-off.png"><img alt="" src="https://mdn.mozillademos.org/files/6675/pencil-on.png" style="width: 32px; height: 32px;"></p> - -<p>或者自己动手做你觉得有创造性的图标。把它们保存在data/widget目录。</p> - -<h2 id="main.js">main.js</h2> - -<p>现在在lib目录创建main.js并添加下列内容:</p> - -<pre class="brush: js">var widgets = require('sdk/widget'); -var data = require('sdk/self').data; - -var annotatorIsOn = false; - -function toggleActivation() { - annotatorIsOn = !annotatorIsOn; - return annotatorIsOn; -} - -exports.main = function() { - - var widget = widgets.Widget({ - id: 'toggle-switch', - label: 'Annotator', - contentURL: data.url('widget/pencil-off.png'), - contentScriptWhen: 'ready', - contentScriptFile: data.url('widget/widget.js') - }); - - widget.port.on('left-click', function() { - console.log('activate/deactivate'); - widget.contentURL = toggleActivation() ? - data.url('widget/pencil-on.png') : - data.url('widget/pencil-off.png'); - }); - - widget.port.on('right-click', function() { - console.log('show annotation list'); - }); -}</pre> - -<p>注释器默认禁用。它创建控件并通过切换注释器的活动状态来回应来自控件内容脚本的消息。注意,由于<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=626326">bug 626326</a>,附加组件状态栏的环境菜单会显示,尽管在控件的内容脚本中调用了event.preventDefault()。由于我们没有任何代码来显示注释,所以我们们仅仅记录右击事件到控制台。</p> - -<p>现在在注释器目录输入cfx run,你应该看见在附加组件状态栏的控件:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6679/widget-icon.png" style="width: 405px; height: 166px; display: block; margin-left: auto; margin-right: auto;"></p> - -<p>左击和右击应当产生合适的调试输出,同时左击应当改变控件的图标为启用状态。</p> - -<p> </p> - -<p>下一步,我们将添加代码来<a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Creating_annotations">创建注释器</a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html deleted file mode 100644 index 4f76d67802..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: 注释器(Annotator) -slug: Mozilla/Add-ons/SDK/Tutorials/Annotator -tags: - - 附加组件 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator ---- -<div class="warning"> -<p>请注意教程中Widget API适合的浏览器版本。(译者注)</p> -</div> - -<p>在这个教程中,我们将构建一个使用许多SDK高级API的附加组件.</p> - -<p>这个附加组件是一个注释器:它可以让用户选择网页的元素并输入有关的笔记(注释).注释器储存笔记.无论用户何时载入包含被注释元素的页面,这些元素都将会高亮显示,并且用户若把鼠标移动到被注释元素的上面,将会显示它的注释.</p> - -<p>接着我们将给出这个注释器设计的快速简介,然后一步步的讨论如何实现.</p> - -<p>如果你想参阅完整的附加组件,你可以在<a href="https://github.com/mozilla/addon-sdk/tree/master/examples/annotator">SDK例子目录</a>找到它.</p> - -<ul> - <li> - <p><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Overview">设计概述</a></p> - </li> - <li> - <p><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget">实现控件</a></p> - </li> - <li> - <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Creating_annotations">创建注释</a></p> - </li> - <li> - <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Storing_annotations">保存注释</a></p> - </li> - <li> - <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Displaying_annotations">显示注释</a></p> - </li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html deleted file mode 100644 index da94f8142a..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: 概述 -slug: Mozilla/Add-ons/SDK/Tutorials/Annotator/Overview -tags: - - addon sdk example - - annotator example - - 附加组件 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator/Overview ---- -<p>注释器使用内容脚本(content scripts)来构建用户界面,得到用户输入,并检查用户载入页面的DOM。</p> - -<p>同时,主要模块包括程序逻辑和调节不同SDK对象的交互。</p> - -<p>我们可以描述在主要模块和不同内容脚本的交互,像这样:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6671/annotator-design.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h2 id="用户界面">用户界面</h2> - -<p>注释器的主要用户界面由一个控件和三个面板组成。</p> - -<ul> - <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/widget">控件(widget)</a>用来选择打开或关闭注释器,显示所有已经储存的注释列表。</li> - <li><strong>注释编辑器(annotation-editor)</strong><a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">面板</a>用来让用户输入注释。</li> - <li><strong>注释列表(annotation-list)</strong>面板用来显示保存的注释清单。</li> - <li><strong>注释(annotation)</strong>面板显示单条注释。</li> -</ul> - -<p>除此之外,我们使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/notifications">notifications</a> 模块来告知用户附加组件的储存限额已满。</p> - -<h2 id="用DOM工作">用DOM工作</h2> - -<p>我们将使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mods</a> 来和用户打开的网页的DOM进行交互。</p> - -<ul> - <li> - <p><strong>选择器(selector)</strong>让用户选择一个元素来注释。它识别符合注释条件的页面元素,当鼠标在他们上方时高亮显示,并在用户点击高亮元素时通知主要的附加组件代码。</p> - </li> - <li> - <p><strong>匹配器(matcher)</strong>用来寻找被注释的元素:它初始化注释列表并网页中和注释相关连的元素。高亮网页上找到的关联元素,并高亮显示。当鼠标移动到已注释元素的上面,匹配器将通知显示注释面板的主要附加组件代码。</p> - </li> -</ul> - -<h2 id="处理数据">处理数据</h2> - -<p>我们将使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-storage">simple-storage</a>模块来储存数据。</p> - -<p>由于我们将记录潜在的敏感信息,我们想阻止用户在隐私浏览模式下创建注释,最简单的方式是删除附加组件中“package.json“文件的<a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">”private-browsing"键</a>。这样,附加组件就不能看见任何隐私浏览窗口,同时注释器的控件也将不再出现。</p> - -<h2 id="开始行动">开始行动</h2> - -<p>现在让我们来创建叫“注释器”的目录。Navigate to it and type <code>cfx init</code>.</p> - -<p>下一步,我们将<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget">实现控件</a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html deleted file mode 100644 index 9bec4966d4..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: 显示弹出对话框 -slug: Mozilla/Add-ons/SDK/Tutorials/Display_a_Popup -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Display_a_Popup ---- -<div class="note"> - <p>动手之前,必须先<a href="/en-US/Add-ons/SDK/Installation">安装SDK</a>并学习<a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code>基础知识</a>.</p> - <p>T这篇教程使用<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API需要Firefox 29或更新版本。</p> -</div> -<p>可以使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel"><code>面板(panel)</code></a>模块来显示弹出对话框。面板的内容通过HTML编写。你可以在面板上运行content script:尽管在面板里的脚本无法直接访问插件代码,但是你可以在面板脚本和插件代码间交换信息。</p> -<p>这里,我们做了一个会在单击时显示面板的<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>。面板上有一个<code><textarea></code>元素:用户按下<code>return</code>键时,<code><textarea></code>的内容会被发送给插件代码主程序。插件代码主程序会<a href="/en-US/Add-ons/SDK/Tutorials/Logging">在控制台输出日志</a>。.</p> -<p><img alt="" src="https://mdn.mozillademos.org/files/7647/panel.png" style="display: block; margin-left: auto; margin-right: auto;">The add-o插件由六个文件组成n consists of six files:</p> -<ul> - <li><code>main.js</code>:插件主程序,在这里创建按钮和面板</li> - <li><code>get-text.js</code>:与面板内容交互的content脚本</li> - <li><code>text-entry.html</code>:面板的内容,由HTML编写</li> - <li><code>icon-16.png</code>,<code>icon-32.png</code>和<code>icon-64.png</code>:三种不同大小的图标</li> -</ul> -<p>"main.js"像这样:</p> -<pre class="brush: js">var data = require("sdk/self").data; -// 构造面板,从"data"目录的"text-entry.html"加载 -// 内容,然后加载"get-text.js"脚本。 -var text_entry = require("sdk/panel").Panel({ - contentURL: data.url("text-entry.html"), - contentScriptFile: data.url("get-text.js") -}); - -// 创建按钮 -require("sdk/ui/button/action").ActionButton({ - id: "show-panel", - label: "Show Panel", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -// 在用户点击按钮时显示面板。 -function handleClick(state) { - text_entry.show(); -} - -<code class="language-js"><span class="token comment">// When the panel is displayed it generated an event called -</span><span class="token comment">// "show": we will listen for that event and when it happens, -</span><span class="token comment">// send our own "show" event to the panel's script, so the -</span><span class="token comment">// script can prepare the panel for display.</span></code> -text_entry.on("show", function() { - text_entry.port.emit("show"); -}); - -// 监听来自content脚本的text-entered消息。消息主体L是用户输入的文本。 -// 此实现,我们只在控制台显示日志。 -text_entry.port.on("text-entered", function (text) { - console.log(text); - text_entry.hide(); -});</pre> -<p>content脚本"get-text.js"像这样:</p> -<div> - <pre class="brush: js">// 用户按下回车,发送text-entered消息给main.js。 -// 消息主体是编辑框的内容。 -var textArea = document.getElementById("edit-box"); -textArea.addEventListener('keyup', function onkeyup(event) { - if (event.keyCode == 13) { - // Remove the newline. - text = textArea.value.replace(/(\r\n|\n|\r)/gm,""); - self.port.emit("text-entered", text); - textArea.value = ''; - } -}, false); -// 监听由插件主程序发送的show事件。表示面板将要显示。 -// -// 焦点放在textarea上,这样用户可以直接开始输入。 -self.port.on("show", function onShow() { - textArea.focus(); -});</pre> - <div> - </div> -</div> -<p>最后,"text-entry.html"文件定义了<code><textarea></code>元素:</p> -<div> - <div> - <pre class="brush: html"><html> -<head> - <style type="text/css" media="all"> - textarea { - margin: 10px; - } - body { - background-color: gray; - } - </style> - </head> -<body> - <textarea rows="13" cols="33" id="edit-box"></textarea> - </body> -</html></pre> - <div> - </div> - </div> -</div> -<p>最后,把这三个图标文件保存在"data"目录:</p> -<table class="standard-table"> - <tbody> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="width: 16px; height: 16px;"></td> - <td>icon-16.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="width: 32px; height: 32px;"></td> - <td>icon-32.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="width: 64px; height: 64px;"></td> - <td>icon-64.png</td> - </tr> - </tbody> -</table> -<p>试用以下:保存在<code>lib</code>目录,其他五个文件存放在插件的<code>data</code>目录:</p> -<pre>my-addon/ - data/ - get-text.js - icon-16.png - icon-32.png - icon-64.png - text-entry.html - lib/ - main.js -</pre> -<p>运行插件,点击按钮,你就会看见一个面板。输入几行文本,然后按下回车,你就会看见控制台里的输出。</p> -<p>自Firefox 30起,如果你使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>,就可以<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle#Attaching_panels_to_buttons">给它附加一个面板</a>。</p> -<h2 id="进一步学习">进一步学习</h2> -<p>学习<code>panel</code>模块的更多内容,见<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel"><code>panel</code> API参考</a>。</p> -<p>学习关于按钮的更多内容,见<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>和<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>API参考。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html deleted file mode 100644 index 225739de76..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: 快速入门 -slug: Mozilla/Add-ons/SDK/Tutorials/Getting_started -tags: - - add-on sdk开发 - - cfx工具基础使用教程 - - 火狐扩展程序 -translation_of: Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29 ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p>Add-on SDK 里包含了一个命令行工具,你可以用此工具来初始化、运行、测试以及打包 add on。 这个工具称为 jpm,基于 <a href="http://nodejs.org/">Node.js</a> 。它替代了以前的cfx工具。</p> - -<p>你可以在 Firefox 38或之后的版本中使用。</p> - -<p>本文阐述如何使用 jpm 开发。</p> -</div> - -<p>本教程会过一遍使用 SDK 创建一个简单 add-on 的过程。</p> - -<h2 id="准备">准备</h2> - -<p>要使用 SDK 创建 add-on,你需要:</p> - -<ul> - <li>Firefox 38或以后版本。如果你需要在早期版本的 Firefox 上开发,你就要使用老的 cfx 工具。参看 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started_(cfx)">cfx 快速入门</a>的说明。</li> - <li>命令行 jpm 工具。参看 <a href="/en-US/Add-ons/SDK/Tools/jpm#Installation">jpm 安装</a>的说明。一旦你已经完成这些工作,你就会在一个命令行提示符下。</li> -</ul> - -<h2 id="初始化空的_add-on">初始化空的 add-on</h2> - -<p>在命令行提示符下,创建一个新目录。进入新文件夹,键入 <code>jpm init</code>,然后敲回车</p> - -<pre>mkdir my-addon -cd my-addon -jpm init -</pre> - -<p>接着你会被要求提供一些关于你的 add-on 的信息:这会用来创建 <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件。如果光按回车的话,就表示接受属性的默认值。关于 <code>jpm init</code> 的更多信息,参看 <a href="/en-US/Add-ons/SDK/Tools/jpm#Command_reference">jpm command reference</a>.</p> - -<p>一旦你设置了这些属性的值或者接受默认值,你会看到 "package.json" 的完整内容并被询问是否接受这些设置。</p> - -<h2 id="实现_add-on">实现 add-on</h2> - -<p>现在你可以写 add-on 的代码了。除非你修改了"entry point"的值(package.json 中的 "<a href="/en-US/Add-ons/SDK/Tools/package_json#main">main</a>"),一般情况将从你的 add-on 的根目录下的"index.js"文件开始。这个文件就是在之前步骤中创建的。打开这个文件并且添加以下代码:</p> - -<pre class="brush: js">var buttons = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = buttons.ActionButton({ - id: "mozilla-link", - label: "Visit Mozilla", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -function handleClick(state) { - tabs.open("http://www.mozilla.org/"); -} -</pre> - -<div class="note"> -<p>注意在jpm中"entry point"的默认值为"index.js",意思是你的主文件是"index.js",且在你的 add-on的根目录下。</p> - -<p>cfx中,入口默认是"main.js",并且在"lib"目录下</p> -</div> - -<p>保存文件</p> - -<p>接下来,在根目录下创建目录<strong>"data"</strong>。</p> - -<pre>mkdir data -</pre> - -<p>并保存这三个图标文件到<strong>"data"</strong>目录:</p> - -<table class="standard-table"> - <tbody> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td> - <td>icon-16.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td> - <td>icon-32.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td> - <td>icon-64.png</td> - </tr> - </tbody> -</table> - -<p>返回命令行,键入:</p> - -<pre>jpm run</pre> - -<p>这个 jpm 命令会运行一个带有你的 add-on 的 Firefox 的新实例。</p> - -<p>如果找不到 Firefox,你可能要为它提供一个路径(如在Ubuntu中):</p> - - -<pre>jpm run -b /usr/bin/firefox</pre> - -<p>Firefox 启动以后,在浏览器右上角你能看到一个 Firefox logo 的图标。点击该图标,就会打开一个新标签页 <a href="http://www.mozilla.org/" rel="noreferrer">http://www.mozilla.org/</a>。</p> - -<p>这就是这个 add-on 的全部功能了。它用到了 SDK 的两个模块:<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 模块,使你能加个按钮到浏览器上,以及 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a> 模块,使你能完成对标签页的基本操作。本例中,我们以及创建了一个图标是Firefox图标的按钮,并添加一个点击处理程序,可以在新标签页中打开 Mozilla 页面。</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7643/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">试着编辑这个文件。例如,我们可以改变加载的页面:</p> - -<pre class="brush: js">var buttons = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = buttons.ActionButton({ - id: "mozilla-link", - label: "Visit Mozilla", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -function handleClick(state) { - tabs.open("https://developer.mozilla.org/"); -}</pre> - -<p>在命令行提示符下,再次执行 <code>jpm run</code>。这次点击按钮,它会带你到 <a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a> 页面。</p> - -<h2 id="打包_add-on">打包 add-on</h2> - -<p>当你完成了 add-on 并准备发布它,你会需要把它打包为 XPI 文件。你能自己分发 XPI 文件,也可以把它们发布到 <a href="https://addons.mozilla.org" rel="noreferrer">https://addons.mozilla.org</a>,这样其他用户就能下载并按照它们。</p> - -<p>要构建 XPI,只要在 add-on 的根目录下运行命令 <code>jpm xpi</code>:</p> - -<pre>jpm xpi -</pre> - -<p>你应该看到像这样的信息:</p> - -<pre>JPM info Successfully created xpi at /path/to/my-addon/@my-addon-0.0.1.xpi -</pre> - -<p>要测试附加组件是否能正常运行,可以尝试在你自己的火狐中安装 XPI 文件。你可以在 Firefox 中按 Ctrl+O 组合键(Mac 中是 Cmd+O),或者选择"文件"菜单里的“打开”。这样会弹出一个文件选择对话框:转到"@my-addon.xpi"文件,打开并按照提示安装 add-on。</p> - -<p>注意 Firefox 默认需要 add-on 有签名,即使是本地开发的 add-on。安装完后他们会在已安装的 add-on 列表中出现,只因没有签名而被禁用。开发的时候,又或者你不准备发布,你可以打开 <a>about:config</a> 设置 <em>xpinstall.signatures.required</em> 为 <em>false</em> 来运行未经签名的组件。这个设置会应用到所有的 add-on,所以要十分小心,不要一不当心从别的地方安装了恶意组件。</p> - -<p>要发布你的 add-on,请<a href="https://addons.mozilla.org/en-US/developers/addon/submit/2">提交 XPI 文件到 addons.mozilla.org</a> 或者如果你想在你自己的服务器上发布,运行 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign">jpm sign</a>。</p> - -<h2 id="总结">总结</h2> - -<p>本教程中我们使用了下面三个命令来构建和打包 add-on :</p> - -<ul> - <li><code>jpm init</code> 初始化一个空的 add-on 模板</li> - <li><code>jpm run</code> 运行一个装有 add-on 的新 Firefox 实例,所以我们可以试用它</li> - <li><code>jpm xpi</code> 打包 add-on 为 XPI 文件,用来发布</li> -</ul> - -<p>这是你在开发SDK add-on会用到的三个主要命令。完全的<a href="/en-US/Add-ons/SDK/Tools/jpm" rel="noreferrer">参考文档</a>包含了所以你能使用的命令,以及这些命令的可选项。</p> - -<p>这次开发的add-on 的代码用到了两个 SDK 模块,<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 和 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a>。这儿有参考文档,描述 SDK 中所有<a href="/en-US/Add-ons/SDK/High-Level_APIs" rel="noreferrer">高层次</a>和<a href="/en-US/Add-ons/SDK/Low-Level_APIs" rel="noreferrer">低层次</a>的 API。</p> - -<h2 id="下一步">下一步?</h2> - -<p>要了解你能用 SDK API 做些什么,试着继续阅读<a href="/en-US/Add-ons/SDK/Tutorials" rel="noreferrer">教程</a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html deleted file mode 100644 index e09d6d4e55..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: JPM 入门! -slug: Mozilla/Add-ons/SDK/Tutorials/Getting_Started_(jpm) -tags: - - JPM - - add-on -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Getting_Started_(jpm) ---- -<div class="note"> -<p>该附加SDK包含一个用于初始化,运行,测试和打包加载项的命令行工具。当前工具称为jpm,并且基于 <a href="http://nodejs.org/">Node.js</a> .它替代了旧的cfx工具。</p> - -<p>Firefox 38 以上的版本才可以使用jpm。</p> - -<p>本文介绍如何使用jpm开发。</p> -</div> - -<p>本教程将介绍使用SDK创建一个简单的附加组件。</p> - -<h2 id="先决条件">先决条件</h2> - -<p>要使用SDK为Firefox创建附加组件,您需要:</p> - -<ul> - <li>备好 Firefox 38 或更高版本浏览器,否则抱着你亲爱的cfx古董去死吧,出门左转 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started">getting started with cfx</a> 不谢。</li> - <li>命令行 JPM 工具,至 <a href="/en-US/Add-ons/SDK/Tools/jpm#Installation">installing jpm</a> 此处领取。// 后面这句是废话不翻译</li> -</ul> - -<h2 id="初始化一个空的附加组件">初始化一个空的附加组件</h2> - -<p>在命令提示符下,创建一个新目录。导航到它,键入 <code>jpm init, </code>然后按Enter键<code>:</code></p> - -<pre>mkdir my-addon -cd my-addon -jpm init -</pre> - -<p>You'll then be asked to supply some information about your add-on: this will be used to create your add-on's <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> file. For now, just press Enter to accept the default for each property. For more information on <code>jpm init</code>, see the <a href="/en-US/Add-ons/SDK/Tools/jpm#Command_reference">jpm command reference</a>.</p> - -<p>Once you've supplied a value or accepted the default for these properties, you'll be shown the complete contents of "package.json" and asked to accept it.</p> - -<h2 id="实现附加组件">实现附加组件</h2> - -<p>Now you can write the add-on's code. Unless you've changed the value of "entry point" ("<a href="/en-US/Add-ons/SDK/Tools/package_json#main">main</a>" in package.json), this goes in "index.js" file in the root of your add-on. This file was created for you in the previous step. Open it and add the following code:</p> - -<pre class="brush: js">var buttons = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = buttons.ActionButton({ - id: "mozilla-link", - label: "Visit Mozilla", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -function handleClick(state) { - tabs.open("http://www.mozilla.org/"); -} -</pre> - -<div class="note"> -<p>Note that "entry point" defaults to "index.js" in jpm, meaning that your main file is "index.js", and it is found directly in your add-on's root.</p> - -<p>In cfx, the entry point defaults to "main.js", and is located in the "lib" directory under the add-on's root.</p> -</div> - -<p>Save the file.</p> - -<p>Next, create a directory called "data" in your add-on's root, and save these three icon files to the "data" directory:</p> - -<table class="standard-table"> - <tbody> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td> - <td>icon-16.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td> - <td>icon-32.png</td> - </tr> - <tr> - <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td> - <td>icon-64.png</td> - </tr> - </tbody> -</table> - -<p>Back at the command prompt, type:</p> - -<pre>jpm run</pre> - -<p>This is the jpm command to run a new instance of Firefox with your add-on installed.</p> - -<p>If Firefox can not be located, you may need to provide the path to it (example in Ubuntu):</p> - - -<pre>jpm run -b /usr/bin/firefox</pre> - -<p>When Firefox launches, in the top-right corner of the browser you'll see an icon with the Firefox logo. Click the icon, and a new tab will open with <a href="http://www.mozilla.org/" rel="noreferrer">http://www.mozilla.org/</a> loaded into it.</p> - -<p>That's all this add-on does. It uses two SDK modules: the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> module, which enables you to add buttons to the browser, and the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a> module, which enables you to perform basic operations with tabs. In this case, we've created a button whose icon is the Firefox icon, and added a click handler that loads the Mozilla home page in a new tab.</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7643/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">Try editing this file. For example, we could change the page that gets loaded:</p> - -<pre class="brush: js">var buttons = require('sdk/ui/button/action'); -var tabs = require("sdk/tabs"); - -var button = buttons.ActionButton({ - id: "mozilla-link", - label: "Visit Mozilla", - icon: { - "16": "./icon-16.png", - "32": "./icon-32.png", - "64": "./icon-64.png" - }, - onClick: handleClick -}); - -function handleClick(state) { - tabs.open("https://developer.mozilla.org/"); -}</pre> - -<p>At the command prompt, execute <code>jpm run</code> again. This time clicking it takes you to <a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a>.</p> - -<h2 id="Packaging_the_add-on">Packaging the add-on</h2> - -<p>When you've finished the add-on and are ready to distribute it, you'll need to package it as an XPI file. This is the installable file format for Firefox add-ons. You can distribute XPI files yourself or publish them to <a href="https://addons.mozilla.org" rel="noreferrer">https://addons.mozilla.org</a> so other users can download and install them.</p> - -<p>To build an XPI, just execute the command <code>jpm xpi</code> from the add-on's directory:</p> - -<pre>jpm xpi -</pre> - -<p>You should see a message like:</p> - -<pre>JPM info Successfully created xpi at /path/to/getting-started/@getting-started.xpi -</pre> - -<p>To test that this worked, try installing the XPI file in your own Firefox installation. You can do this by pressing the Ctrl+O key combination (Cmd+O on Mac) from within Firefox, or selecting the "Open" item from Firefox's "File" menu. This will bring up a file selection dialog: navigate to the "@getting-started.xpi" file, open it and follow the prompts to install the add-on.</p> - -<h2 id="Summary">Summary</h2> - -<p>In this tutorial we've built and packaged an add-on using three commands:</p> - -<ul> - <li><code>jpm init</code> to initialize an empty add-on template</li> - <li><code>jpm run</code> to run a new instance of Firefox with the add-on installed, so we can try it out</li> - <li><code>jpm xpi</code> to package the add-on into an XPI file for distribution</li> -</ul> - -<p>These are the three main commands you'll use when developing SDK add-ons. There's comprehensive <a href="/en-US/Add-ons/SDK/Tools/jpm" rel="noreferrer">reference documentation</a> covering all the commands you can use and all the options they take.</p> - -<p>The add-on code itself uses two SDK modules, <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> and <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a>. There's reference documentation for all the <a href="/en-US/Add-ons/SDK/High-Level_APIs" rel="noreferrer">high-level</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs" rel="noreferrer">low-level</a> APIs in the SDK.</p> - -<h2 id="What's_next">What's next?</h2> - -<p>To get a feel for some of the things you can do with the SDK APIs, try working through some of the <a href="/en-US/Add-ons/SDK/Tutorials" rel="noreferrer">tutorials</a>.</p> - -<p> </p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html deleted file mode 100644 index 03173c3219..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: 教程 -slug: Mozilla/Add-ons/SDK/Tutorials -tags: - - 插件SDK -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials ---- -<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p> - -<p>本文列出了许多关于如何通过SDK完成特定任务要求的实际动手的文章。</p> - -<hr> -<h3 id="开发之旅"><a name="getting-started">开发之旅</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Installation">安装</a></dt> - <dd>在Windows, OS X和Linux上下载,安装,初始化SDK工具。</dd> -</dl> - -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Troubleshooting">常见问题</a></dt> - <dd>解决常见问题的建议和获取更多帮助。</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_started">快速开始</a></dt> - <dd>走马观花地使用SDK开发一个简单的扩展</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="创建用户交互界面"><a name="create-user-interfaces">创建用户交互界面</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar">添加一个工具按钮</a></dt> - <dd>添加一个按钮到火狐Add-on工具栏。</dd> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">添加一个菜单选项到火狐</a></dt> - <dd>添加多个菜单选项到火狐主菜单。</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Display_a_Popup">显示一个弹出对话框</a></dt> - <dd>通过HTML和JavaScript实现并显示一个弹窗对话框。</dd> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/添加一个菜单项">添加一个上下文菜单</a></dt> - <dd>添加一个上下文菜单(一般都是右键菜单)到火狐浏览器</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="与浏览器交互"><a name="interact-with-the-browser">与浏览器交互</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开Web页面</a></dt> - <dd>在一个新的浏览器选项卡里打开一个Web页面或窗口使用tabs模块并获取内容。</dd> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load">监听页面加载</a></dt> - <dd>当新页面载入时使用tabs模块得到通知并获取页面内容。</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs">获取打开的选项卡(Tab)列表</a></dt> - <dd>使用tabs模块遍历当前打开的tab,并获取其内容。</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="更改网页"><a name="modify-web-pages">更改网页</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL">更改网页通过URL</a></dt> - <dd>基于URL过滤网页:当载入的页面的URL与过滤器匹配时执行特定的脚本。</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">修改页面内容</a></dt> - <dd>动态加载脚本到当前页面。</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="开发技术"><a name="development-techniques">开发技术</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/日志">日志</a></dt> - <dd>在终端中记录日志以便调试。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_reusable_modules">创建可复用的模块</a></dt> - <dd>拆分扩展程序为多个分离的模块,可以使开发调试和维护更加简单。封装你的模块使其成为可复用的包,以便其他开发者可以再次使用。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Unit_testing">单元测试</a></dt> - <dd>使用SDK的测试框架书写和进行单元测试。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Chrome_authority">Chrome授权 </a></dt> - <dd>获得Components对象,使你的扩展程序能够加载和使用任何XPCOM对象。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_event_targets">创建事件目标</a></dt> - <dd>使你定义的对象能够响应相关事件。</dd> -</dl> -</div> - -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Listening_for_load_and_unload">监听载入和卸载</a></dt> - <dd>当你的扩展程序被加载和卸载时获得通知,并从终端传递参数给扩展程序。</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">使用第三方模块</a></dt> - <dd>安装和使用与SDK无关额外的模块</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/l10n">本地化</a></dt> - <dd>书写本地化代码.</dd> - <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Mobile_development">移动开发</a></dt> - <dd>为Andriod上的火狐浏览器开发扩展程序。</dd> - <dt><a href="/zh-CN/Add-ons/Add-on_Debugger">扩展调试</a></dt> - <dd>调试扩展应用的JavaScript。</dd> -</dl> -</div> -</div> - -<hr> -<h3 id="打包"><a name="putting-it-together">打包</a></h3> - -<div class="column-container"> -<div class="column-half"> -<dl> - <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator">扩展应用:Annotator</a></dt> - <dd>一起开发一个相对复杂的扩展应用。</dd> -</dl> -</div> -</div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html deleted file mode 100644 index 4313836979..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: 安装 -slug: Mozilla/Add-ons/SDK/Tutorials/Installation -tags: - - cfx安装 - - 配置cfx环境 -translation_of: Mozilla/Add-ons/SDK/Tools/jpm#Installation ---- -<h2 id="先决条件">先决条件</h2> - -<p><span style="color: #ff0000;">请不要把任何相关的开发工具和扩展程序(命名推荐小写英文和数字,不推荐特殊符号等),放到有空格的目录(如Progaram Files\Python),会导致意想不到的错误,无法进行后续操作。(最新开发SDK可能修复了该错误,参见https://github.com/mozilla/addon-sdk/pull/1738)</span></p> - -<p>开发 Add-on SDK,你需要:</p> - -<ul> - <li> - <p><a href="http://www.python.org/">Python</a> 2.5,2.6 或 2.7。 <span class="short_text" id="result_box" lang="zh-CN"><span>需要注意的是在任何平台<span class="short_text" id="result_box" lang="zh-CN"><span>都是不支持</span></span></span></span> <span class="short_text" id="result_box" lang="zh-CN"><span>Python</span><span>3.x版本的</span></span> 。确保你已经安装过Python。</p> - </li> - <li> - <p>Firefox火狐浏览器(本教程针对最新的浏览器)。</p> - </li> - <li> - <p><span class="short_text" id="result_box" lang="zh-CN"><span>SDK本身</span><span>:</span><span>可以获取</span><span>SDK的最新</span><span>稳定版本</span><span>为</span></span> <a href="https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.tar.gz">tarball压缩包</a> 或 <a href="https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.zip">zip 文件</a>。</p> - </li> -</ul> - -<p>另外,<span class="short_text" id="result_box" lang="zh-CN"><span>你</span><span>可以从它</span><span>的<a href="https://github.com/mozilla/addon-sdk">GitHub repository</a></span><span>库中</span><span>得到最新的</span><span>开发版本</span></span>。</p> - -<h2 id="为AMO开发扩展">为AMO开发扩展</h2> - -<p>如果提交到AMO只有最新发布或许使用。</p> - -<p class="ordinary-output target-output"><span>git</span><span> archive </span><span>需要扩展</span><span>一些Git</span><span>属性</span><span>占位符</span><span>。</span></p> - -<pre class="language-html">git checkout 1.16 - -git archive 1.16 python-lib/cuddlefish/_version.py | tar -xvf -</pre> - -<h2 id="通过Homebrew自动安装到Mac_OS_X">通过Homebrew自动安装到Mac OS X</h2> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>使用以下命令</span><span>通过</span></span> <a href="http://brew.sh/">homebrew</a><span class="short_text" id="result_box" lang="zh-CN"><span>来安装</span><span>SDK<span class="short_text" id="result_box" lang="zh-CN"><span><span class="short_text" id="result_box" lang="zh-CN"><span>插件</span></span></span></span>工具:</span></span></p> - -<pre>brew install mozilla-addon-sdk</pre> - -<h2 id="安装到Mac_OS_XLinux">安装到Mac OS X/Linux</h2> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span><span class="short_text" id="result_box" lang="zh-CN"><span>无论你</span><span>选择哪个方式都要</span></span>解压缩</span><span>文件的内容</span><span>作为根路径,</span><span>并通过</span><span>shell</span><span>/</span><span>命令提示符切换到</span><span>SDK的</span><span>根目录下</span><span>。</span><span>例如:</span></span></p> - -<pre>tar -xf addon-sdk.tar.gz -cd addon-sdk -</pre> - -<p>如果你是<span class="short_text" id="result_box" lang="zh-CN"><span>Bash的</span><span>用户,则继续运行</span></span>(大多数人都是的):</p> - -<pre>source bin/activate -</pre> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>如果你是</span><span>一个非</span><span>Bash的</span><span>用户</span><span>,</span><span>你应该运行</span><span>:</span></span></p> - -<pre>bash bin/activate -</pre> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>命令提示符</span><span>现在应该</span><span>有一个包含</span><span>SDK的</span><span>根</span><span>目录名称</span><span>的新的前缀</span><span>:</span></span></p> - -<pre>(addon-sdk)~/mozilla/addon-sdk > -</pre> - -<h2 id="安装到Windows">安装到Windows</h2> - -<p>同样解压缩文件,并通过命令符进入到SDK根目录下,例如:</p> - -<pre>7z.exe x addon-sdk.zip -cd addon-sdk -</pre> - -<p>接着运行激活命令:</p> - -<pre>bin\activate -</pre> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>同样可以看到命令提示符</span><span>现在应该</span><span>有一个包含</span><span>SDK的</span><span>根</span><span>目录名称</span><span>的<span class="short_text" id="result_box" lang="zh-CN"><span>新的</span></span>前缀</span><span>:</span></span></p> - -<pre>(C:\Users\mozilla\sdk\addon-sdk) C:\Users\Work\sdk\addon-sdk> -</pre> - -<h2 id="SDK_的虚拟环境">SDK 的虚拟环境</h2> - -<p><span id="result_box" lang="zh-CN"><span><span id="result_box" lang="zh-CN"><span>当命令</span><span>提示符</span></span>出现新的</span><span>前缀</span><span>表明</span><span>你的</span><span>已经搭建好了SDK的</span><span>运行环境</span><span>,那么你就可以使用</span><span>Add</span><span class="atn">-</span><span>on SDK来开发</span><span>的</span><span>命令行工具</span><span>。</span></span></p> - -<p>任何时候,你都可以通过运行 <code>deactivate 命令停用虚拟环境</code>.</p> - -<p class="ordinary-output target-output"><span>配置好的虚拟环境是特定于这个特定的命令提示符。</span><span>如果您关闭命令提示符, 它会关闭运行环境,你需要<code>source bin/activate</code>或<code> bin\activate 在</code>一个新的命令提示符重新激活它。</span><span>如果你</span><span>打开一个新命令提示符</span><span>,</span><span id="result_box" lang="zh-CN"><span>SDK将</span><span>不会被激活</span><span>在新的提示</span></span><span>。</span></p> - -<p><span id="result_box" lang="zh-CN"><span>可以</span><span>将SDK</span><span>的多个副本</span><span>拷贝在</span><span>磁盘上的</span><span>不同位置</span><span>,并</span><span>在它们之间切换</span><span>,甚至可以</span><span>让他们<span id="result_box" lang="zh-CN"><span>同时</span><span>激活</span></span>运行在</span><span>不同的命令</span><span>提示</span><span>符</span><span>。</span></span></p> - -<h3 id="制作启动项">制作启动项</h3> - -<p><span id="result_box" lang="zh-CN"><span>所有 </span><code>activate </code><span>的作用是通过设置环境变量,<span id="result_box" lang="zh-CN"><span>使位于</span><span>顶层</span><code> bin </code><span>目录下</span><span>的脚本</span></span></span><span> </span><span>位于当前命令符下</span><span>,制作的启动项 ,</span><span>通过永久</span><span>环境中的这些</span><span>变量</span><span>设置,以便</span><span>每一个新的</span><span>命令提示符下</span><span>都能读取它们</span><span>。</span><span>那么</span><span>就不需要每次都去打开新的命令提示符来激活</span><span><code> activate </code>。</span></span></p> - -<p class="ordinary-output target-output"><span>因为变量精确设置可能随SDK发布新版本的变化,所以最好是指激活脚本来确定哪些变量需要设置。</span><span>激活</span><span>使用不同的</span><span>脚本</span><span>设置</span><span>bash</span><span>环境</span><span>不同的变量</span><span>(</span><span>Linux</span><span>和</span><span>MAC</span><span> OS X</span><span>和Windows</span><span>环境</span><span>)</span><span>。</span></p> - -<h4 id="Windows">Windows</h4> - -<p><span id="result_box" lang="zh-CN"><span>在Windows上,</span><span>使用</span><span> <code>bin\activate\</code><code>activate.bat</code></span><span>批处理脚本,也可以</span><span>使用命令行</span><code>setx</code><span>工具或</span><span>控制面板</span><span>激活</span><span>永久</span><span>使用</span><span>。</span></span></p> - -<h4 id="LinuxMac_OS_X">Linux/Mac OS X</h4> - -<p>在 Linux 和 Mac OS X,<span id="result_box" lang="zh-CN"><span>使用</span></span><code>source bin/activate</code>/<code>activate</code> bash 脚本, 你可以 <code>~/.bashrc</code> ( Linux) <code>或~/.bashprofile</code> (Mac OS X) 来激活。</p> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>作为替代</span><span>,你</span><span>可以在</span><code> ~/bin </code><span class="hps">目录中</span><span>创建到</span><span>cfx </span><span>程序</span><span>的符号链接</span><span>:</span></span></p> - -<pre>ln -s PATH_TO_SDK/bin/cfx ~/bin/cfx -</pre> - -<h2 id="完整性检查"><span class="short_text" id="result_box" lang="zh-CN"><span>完整性检查</span></span></h2> - -<p><span class="short_text" id="result_box" lang="zh-CN"><span>在shell提示符</span></span>运行:</p> - -<pre>cfx -</pre> - -<p>它会产生下面信息,这里是第一行内容,后面<span>是</span><span>大量的</span><span>使用信息</span><span>:</span></p> - -<pre>Usage: cfx [options] [command] -</pre> - -<p><span id="result_box" lang="zh-CN"><span>这是</span></span> <a href="/en-US/Add-ons/SDK/Tools/cfx"><span id="result_box" lang="zh-CN"><span>CFX</span><span>命令行程序</span></span></a>, <span id="result_box" lang="zh-CN"><span>是</span><span>主</span><span>界面</span><span>加载项</span><span>的SDK</span></span>,<span id="result_box" lang="zh-CN"><span>可以使用</span><span>它来</span><span>启动Firefox</span><span>和测试</span><span>插件,</span><span>打包</span><span>附加</span><span>分发</span><span>,查看</span><span>文档和</span><span>运行单元测试</span><span>。</span></span></p> - -<h2 id="出现问题">出现问题?</h2> - -<p>尝试通过<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Troubleshooting">故障排除页面</a>来解决遇到的问题。</p> - -<h2 id="下一步">下一步</h2> - -<p>接下来, 开始学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">cfx</a> 教程, <span class="short_text" id="result_box" lang="zh-CN"><span>其中</span><span>介绍了如何</span><span>使用</span><span>CFX的</span><span>工具来创建</span><span>附加组件</span><span>。</span></span></p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html deleted file mode 100644 index 5083be5b5c..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html +++ /dev/null @@ -1,381 +0,0 @@ ---- -title: Localization -slug: Mozilla/Add-ons/SDK/Tutorials/l10n -tags: - - Add-on SDK - - 本地化 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/l10n ---- -<p>该SDK支持本地化字符串出现在:</p> - -<ul> - <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_JavaScript">你的主附加组件Add-on的 JavaScript代码</a></li> - <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_HTML">你的附加组件一起打包的HTML文件</a></li> - <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_Preferences">你的附加组件首选项中的 title 标题和 description 描述域</a></li> -</ul> - -<p>目前为止还不支持本地化CSS和content scripts。</p> - -<h2 id="本地化字符串">本地化字符串</h2> - -<p>翻译后的字符串都保存在你的add-on扩展目录下一个名为 "locale"的目录 ,每个本地化地域对应一个文件。这些文件:</p> - -<ul> - <li>使用文件<a href="http://en.wikipedia.org/wiki/.properties"><code>.properties</code> 格式</a></li> - <li>被命名为 "xx-YY.properties", 这里的 "xx-YY" 是 <a href="https://wiki.mozilla.org/L10n:Locale_Codes"> </a> <a href="https://wiki.mozilla.org/L10n:Locale_Codes">name of the locale(本地化区域的名称)</a></li> - <li>包含所有你想要本地化的字符串,其中由一个本地化字符串标识ID和对应的本地化翻译字符串以 <code>"标识ID=本地化翻译的字符串</code>" 的格式组成。(contain one entry for each string you want to localize, consisting of an identifier for the string and its translation in that locale, in the format <code>identifier=translation</code>.)</li> - <li>需要使用没有BOM的UTF-8格式来编码(need to use UTF-8 without BOM encoding)</li> -</ul> - -<p>假设你的附加组件包含一个单一的本地化字符串,用英语表示为“Hello!”,你想提供英语和法语的本地化支持。</p> - -<p>你需要添加两个文件到"locale"目录:</p> - -<pre>my-addon/ - data - lib - locale/ - en-US.properties - fr-FR.properties -</pre> - -<p>"en-US.properties" 文件中内容:</p> - -<pre>hello_id= Hello! -</pre> - -<p>"fr-FR.properties" 文件中内容:</p> - -<pre>hello_id= Bonjour ! -</pre> - -<p>现在,每当你的JavaScript或HTML向本地化系统请求hello_id标识的翻译,它将获得与当前区域语言一致的翻译。</p> - -<h2 id="在HTML中使用本地化字符串">在HTML中使用本地化字符串</h2> - -<div class="note"> -<p>本例使用的 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API需要 Firefox 29 或者更高版本。</p> -</div> - -<p>要从HTML中引用本地化字符串,需要添加一个 <code>data-l10n-id</code> 的属性,到你想本地化的字符串所属的HTML标签中,然后为该属性指定一个ID值(To reference localized strings from HTML, add a <code>data-l10n-id</code> attribute to the HTML tag where you want the localized string to appear, and assign the identifier to it):</p> - -<pre class="brush: html"><html> - <body> - <h1 data-l10n-id="hello_id"></h1> - </body> -</html> -</pre> - -<p>然后你就可以使用这个HTML文件来建立你的界面, 比如插入一个 panel 面板:</p> - -<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({ - id: "localized-hello", - label: "Localized hello", - icon: "./icon-16.png", - onClick: function() { - hello.show(); - } -}); - -var hello = require("sdk/panel").Panel({ - height: 75, - width: 150, - contentURL: require("sdk/self").data.url("my-panel.html") -});</pre> - -<p>“en-US”和“fr-FR”提供了翻译标识为hello_id字符串的本地化文件,面板将根据当前区域语言设置,显示“Hello!”或者“Bonjour!”:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/7663/bonjour.png" style="width: 255px; height: 160px;"><img alt="" src="https://mdn.mozillademos.org/files/7665/hello.png" style="width: 255px; height: 160px;"></p> - -<p>翻译文本会插入到具有data-l10n-id属性集的节点中。任何之前存在的内容只是被替换掉了。(The translation is inserted into the node which has the <code>data-l10n-id</code> attribute set. Any previously existing content is just replaced.)</p> - -<p>本地化字符串只能作为text文本插入, 所以你不能使用下面的语句插入HTML:</p> - -<pre>hello_id= <blink>Hello!</blink> -</pre> - -<h3 id="Localizing_Element_Attributes">Localizing Element Attributes</h3> - -<div class="geckoVersionNote">这是 Firefox 39 上的新功能</div> - -<p><br> - 你可以在properties文件中,通过设置 l10n-id.attributeName 的值,本地化某些具有 l10n-id属性的元素的属性值。像这样(You can localize certain attributes of elements with an l10n-id by setting its value with l10n-id.attributeName in the properties file like):<br> - </p> - -<pre>hello_id.accesskey= H</pre> - -<p>可以支持以下几个属性:</p> - -<ul> - <li><strong>accesskey</strong></li> - <li><strong>alt</strong></li> - <li><strong>label</strong></li> - <li><strong>title</strong></li> - <li><strong>placeholder</strong></li> -</ul> - -<p>更多的<a href="/en-US/docs/Web/Accessibility/ARIA"> ARIA</a> 属性<strong>aria-label</strong>, <strong>aria-valuetext</strong> 和 <strong>aria-moz-hint</strong> 的本地化将通过在Firefox OS上同样的别名被支持(Further the localization of the <a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a> attributes <strong>aria-label</strong>, <strong>aria-valuetext</strong> and <strong>aria-moz-hint</strong> are supported with the same aliases as on Firefox OS):</p> - -<ul> - <li><strong>ariaLabel</strong></li> - <li><strong>ariaValueText</strong></li> - <li><strong>ariaMozHint</strong></li> -</ul> - -<h2 id="在JavaScript代码中使用本地化字符串">在JavaScript代码中使用本地化字符串</h2> - -<p>为了在主附加组件代码中引用本地化字符串,你需要这样做:</p> - -<pre class="brush: js">var _ = require("sdk/l10n").get; -console.log(_("hello_id!"));</pre> - -<p><span>指定的 "_" 并不是必需的,但是作为<a href="https://www.gnu.org/software/gettext/gettext.html"> gettext </a>工具的默认约定,这能更好的配合其他默认使用 "_" 来表示本地化字符串的现有工具。</span></p> - -<ol> - <li>导入 <code>l10n</code> 模块,然后指定 "_" (下划线)为模块的 <code>get</code> 函数。</li> - <li>把所有涉及本地化的字符串放到 <code>_()</code> 函数中包括起来。</li> -</ol> - -<p>如果你运行它,你会看到输出为预期的当前设置的区域语言:</p> - -<pre>info: Hello! -</pre> - -<pre>info: Bonjour ! -</pre> - -<p>注意你不能在content scripts中 <code>require()</code> 一个模块,所以目前还不能在content script 中引用本地化字符串。</p> - -<h3 id="复数">复数</h3> - -<p> <code>l10n</code> 模快支持复数形式,不同的语言有不同的复数形态。例如,英语有两种形式:相对于"one"的单数形式,和对于"everything else, including zero"的复数形式:</p> - -<pre>one tomato -no tomatoes -two tomatoes -</pre> - -<p>但是俄罗斯语对于以 1 结尾(除了11)的数字、以 2-4 结尾(除了12-14)的数字和其他数字,有着不同的复数形态:</p> - -<pre>один помидор // one tomato -два помидора // two tomatoes -пять помидоров // five tomatoes -</pre> - -<p>SDK使用 <a href="http://cldr.unicode.org/index">Unicode CLDR</a> 数据描述由不同的语言使用的不同复数形式。</p> - -<h4 id="Unicode_CLDR_复数形式">Unicode CLDR 复数形式</h4> - -<p>Unicode CLDR项目定义了用于描述一个特定语言的多个规则的一种方案。在这个方案中一种语言对应最多有六种不同的范围的数字,有以下类别区分:<em>zero(零个),one(一个),two(两个),few(几个),many(很多),</em>和<em>other(其他)</em>。(The Unicode CLDR project defines a scheme for describing a particular language's plural rules. In this scheme a language maps each distinct range of numbers on to one of up to six forms, identified by the following categories: <em>zero</em>, <em>one</em>, <em>two</em>, <em>few</em>, <em>many</em>, and <em>other</em>.)</p> - -<p>英语有两种复数形式,可以表示为 "1" 映射到 "one" 和 "everything else" 映射到 "other"的形式(English has two forms, which can be described by mapping "1" to "one" and "everything else" to "other"):</p> - -<pre>one → n is 1; -other → everything else -</pre> - -<p>俄罗斯语有四种形式,可以使用以下方式表示:</p> - -<pre>one → n mod 10 is 1 and n mod 100 is not 11; -few → n mod 10 in 2..4 and n mod 100 not in 12..14; -many → n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14; -other → everything else -</pre> - -<p>所有语言的多个规则可以在CLDR的 <a href="http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html">语言复数规则</a> 页面查到 (即使这个规则表相对于 <a href="http://unicode.org/repos/cldr/trunk/common/supplemental/plurals.xml">CLDR XML source</a> 已经过时了).</p> - -<h4 id="SDK中的复数形式">SDK中的复数形式</h4> - -<p>代码中,在 <code>_()</code>函数中的本地化ID参数之后提供一个额外的参数,用来表示代表多少个项的本地化字符串(In the code, you supply an extra parameter alongside the identifier, describing how many items there are):</p> - -<pre class="brush: js">var _ = require("sdk/l10n").get; -console.log(_("tomato_id")); -console.log(_("tomato_id", 1)); -console.log(_("tomato_id", 2)); -console.log(_("tomato_id", 5)); -console.log(_("tomato_id", .5));</pre> - -<p>在 <code>.properties</code> 文件中通过使用 CLDR 关键字,对于每种语言可能的复数形式你可以自定义不同的本地化字符串。所以对于英语可以有两种本地化(注意"other" 分类不是 CDLR 关键字)。(In the <code>.properties</code> file for each language you can define a different localization for each plural form possible in that language, using the CLDR keywords. So in English we could have two plural localizations (note that the "other" category does <strong>not</strong> take the CLDR keyword))</p> - -<pre># en-US translations -tomato_id[one]= %d tomato -tomato_id= %d tomatoes -</pre> - -<p>俄罗斯语中可以定义四种本地化的复数形式:</p> - -<pre># ru-RU translations -tomato_id[one]= %d помидор -tomato_id[few]= %d помидора -tomato_id[many]= %d помидоров -tomato_id= %d помидоры -</pre> - -<p>The localization module itself understands the CLDR definitions for each language, enabling it to map between, for example, "2" in the code and "few" in the <code>ru-RU.properties</code> file. Then it retrieves and returns the localization appropriate for the count you supplied.</p> - -<h3 id="Placeholders">Placeholders</h3> - -<p>The <code>l10n</code> module supports placeholders, allowing you to insert a string which should not be localized into one which is. The following "en-US" and "fr-FR" ".properties" files include placeholders:</p> - -<pre># en-US translations -hello_id= Hello %s! -</pre> - -<pre># fr-FR translations -hello_id= Bonjour %s ! -</pre> - -<p>To use placeholders, supply the placeholder string after the identifier:</p> - -<pre class="brush: js">var _ = require("sdk/l10n").get; -console.log(_("hello_id", "Bob")); -console.log(_("hello_id", "Alice"));</pre> - -<p>In the "en-US" locale, this gives us:</p> - -<pre>info: Hello Bob! -info: Hello Alice! -</pre> - -<p>In "fr-FR" we get:</p> - -<pre>info: Bonjour Bob ! -info: Bonjour Alice ! -</pre> - -<h3 id="Ordering_Placeholders">Ordering Placeholders</h3> - -<p>When a localizable string can take two or more placeholders, translators can define the order in which placeholders are inserted, without affecting the code.</p> - -<p>Primarily, this is important because different languages have different rules for word order. Even within the same language, though, translators should have the freedom to define word order.</p> - -<p>For example, suppose we want to include a localized string naming a person's home town. There are two placeholders: the name of the person and the name of the home town:</p> - -<pre class="brush: js">var _ = require("sdk/l10n").get; -console.log(_("home_town_id", "Bob", "London"));</pre> - -<p>An English translator might want to choose between the following:</p> - -<pre>"<town_name> is <person_name>'s home town." -</pre> - -<pre>"<person_name>'s home town is <town_name>" -</pre> - -<p>To choose the first option, the <code>.properties</code> file can order the placeholders as follows:</p> - -<pre>home_town_id= %2s is %1s's home town. -</pre> - -<p>This gives us the following output:</p> - -<pre>info: London is Bob's home town. -</pre> - -<h2 id="在首选项设置中的本地化字符串">在首选项设置中的本地化字符串</h2> - -<p>通过加入一个 <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs">"preferences" 字段的结构到你的附加组件的 "package.json" 文件</a>中,你可以为你的附加组件定义首选项选项,用户可以在Firefox的 <a href="https://support.mozilla.org/en-US/kb/Using%20extensions%20with%20Firefox#w_how-to-change-extension-settings">Add-ons Manager</a> 看到和编辑它。</p> - -<p>Preferences (首选项)有一个必需的title标题项和一个可选的description描述项 这些字符串将出现在 Add-ons Manager中,来帮助向用户解释各个首选项设置的意义。</p> - -<ul> - <li> - <p>要对preferences中的title标题部分进行本地化,所有在"properties"文件中,形式为preferences中的name后面接着 <code>_title</code> 的本地化标识ID,其对应的值就是标题的本地化字符串。(To provide the localized form of the preference title, include an entry in your "properties" file whose identifier is the preference name followed by <code>_title</code>, and whose value is the localized title.)</p> - </li> - <li> - <p>要对preferences中的description描述部分进行本地化,所有在"properties"文件中,形式为preferences中的name后面接着 <code>_description</code> 的本地化标识ID,其对应的值就是描述的本地化字符串。(To provide the localized form of the preference description, include an entry in your "properties" file whose identifier is the preference name followed by <code>_description</code>, and whose value is the localized description.)</p> - </li> -</ul> - -<p>例如, 假设你的 "package.json" 中只定义了一个设置选项:</p> - -<pre>{ - "preferences": [ - { - "type": "string", - "name": "monster_name", - "value": "Gerald", - "title": "Name" - } - ], - "name": "monster-builder", - "license": "MPL 2.0", - "author": "me", - "version": "0.1", - "fullName": "Monster Builder", - "id": "monster-builder@me.org", - "description": "Build your own monster" -} -</pre> - -<p>在你的"en-US.properties"文件中, 应该包括下面两个项:</p> - -<pre>monster_name_title= Name -monster_name_description= What is the monster's name? -</pre> - -<p>在你的"fr-FR.properties"文件中, 应该包括下面两个法语的翻译项:</p> - -<pre>monster_name_title= Nom -monster_name_description= Quel est le nom du monstre ? -</pre> - -<p>现在,当浏览器的区域设置为 "en-US", 用户会在 Add-ons Manager看到这样:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6525/preference-us.png" style="width: 571px; height: 77px;"></p> - -<p>当浏览器区域设置为 "fr-FR", 用户会看到:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6523/preference-french.png"></p> - -<p>下拉菜单<code>menulist</code>和单选按钮<code>radio</code>的类型有多个选项,每一个选项的标签属性都会展示给用户。如果本地化文件中有一项是以前缀是"{name} _options" 为键的键值对,其中"{name}"是选项的标签名字,该键值对的值就是一个选项标签的本地化字符串。(The <code>menulist</code> and the <code>radio</code> preference types have options. The <code>label</code> attribute of each option is displayed to the user. If the locale file has a entry with the value of the <code>label</code> attribute prefixed with "{name}_options." as its key, where {name} is the name of the preference, its value is used as a localized label.)</p> - -<h2 id="Using_Identifiers">Using Identifiers</h2> - -<p>If the localization system can't find an entry for a particular identifier using the current locale, then it just returns the identifier itself.</p> - -<p>This has the nice property that you can write localizable, fully functional add-ons without having to write any locale files. You can just use the default language strings as your identifier, and subsequently supply <code>.properties</code> files for all the additional locales you want to support.</p> - -<p>For example, in the case above you could use "Hello!" as the identifier, and just have one <code>.properties</code> file for the "fr-FR" locale:</p> - -<pre>Hello!= Bonjour ! -</pre> - -<p>Then when the locale is "en-US", the system would fail to find a <code>.properties</code> file, and return "Hello!".</p> - -<p>However, this approach makes it difficult to maintain an add-on which has many localizations, because you're using the default language strings both as user interface strings and as keys to look up your translations. This means that if you want to change the wording of a string in the default language, or fix a typo, then you break all your locale files.</p> - -<h2 id="Locale_Updater">Locale Updater</h2> - -<p>The <a href="https://github.com/downloads/ochameau/locale-updater/locale-updater.xpi">locale updater</a> add-on makes it easier to update locale files. Once you've installed it, open the Add-on Manager, and you'll see a see a new button labeled "Update l10n" next to each add-on you've installed:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6515/locale-updater.png"></p> - -<p>Click the button and you'll be prompted for a new <code>.properties</code> file for that add-on. If you provide a new file, the add-on's locale data will be updated with the new file.</p> - -<h2 id="Limitations">Limitations</h2> - -<p>The current localization support is a first step towards full support, and contains a number of limitations.</p> - -<ul> - <li> - <p>There's no support for content scripts or CSS files: at the moment, you can only localize strings appearing in JavaScript files that can <code>require()</code> SDK modules and in HTML.</p> - </li> - <li> - <p>The set of locale files is global across an add-on. This means that a module isn't able to override a more general translation: so a module <code>informal.js</code> can't specify that "hello_id" occurring in its code should be localized to "Hi!".</p> - </li> - <li> - <p>The SDK tools compile the locale files into a JSON format when producing an XPI. This means that translators can't localize an add-on given the XPI alone, but must be given access to the add-on source.</p> - </li> - <li> - <p>The add-on developer must manually assemble the set of localizable strings that make up the locale files. In a future release we'll add a command to <code>cfx</code> that scans the add-on for localizable strings and builds a template <code>.properties</code> file listing all the strings that need to be translated.</p> - </li> -</ul> - -<h2 id="See_Also_-_for_developers_looking_to_localize_non-SDK_add-ons">See Also - for developers looking to localize non-SDK add-ons</h2> - -<ul> - <li>How to localize html pages, xul files, and js/jsm files from bootstrapped add-ons: <a href="/en-US/Add-ons/Bootstrapped_extensions#Localization_%28L10n%29">Bootstrapped Extensions :: Localization (L10n)</a></li> - <li>XUL School Localization Tutorial: <a href="/en-US/docs/Mozilla/Tech/XUL/Tutorial/Localization">DTD/Entities method</a> and <a href="/en-US/docs/Mozilla/Tech/XUL/Tutorial/Property_Files">Properties method</a></li> - <li><a href="/en-US/docs/Mozilla/Localization/Localizing_an_extension">Localizing an extension</a></li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html deleted file mode 100644 index 8a4985806e..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: 列出打开的标签页 -slug: Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs -tags: - - Add-on SDK -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/List_Open_Tabs ---- -<p>{{AddonSidebar}}</p> - -<div class="note"> -<p><span>学习本教程之前你需要学习 <a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></p> -</div> - -<p>列出打开的标签页,你可以遍历 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 对象本身。</p> - -<p>下面的 add-on 添加一个 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 当用户单击该按钮时,该日志将在打开的标签页中记录:</p> - -<pre class="brush: js">require("sdk/ui/button/action").ActionButton({ - id: "list-tabs", - label: "List Tabs", - icon: "./icon-16.png", - onClick: listTabs -}); - -function listTabs() { - var tabs = require("sdk/tabs"); - for (let tab of tabs) - console.log(tab.url); -} -</pre> - -<div class="note"> -<p>注意:为此你需要一个按钮图标,以"icon-16.png"的文件名保存到你的 add-on 的"data"目录下。你可以从这里下载图标:<img alt="" src="https://mdn.mozillademos.org/files/7649/icon-16.png" style="height: 16px; width: 16px;">。</p> -</div> - -<p>运行该 add-on,加载一对标签页,并点击按钮,你会看到在<a href="/en-US/Add-ons/SDK/Tutorials/Logging">控制台</a>输出如下的内容:</p> - -<pre>info: http://www.mozilla.org/en-US/about/ -info: http://www.bbc.co.uk/ -</pre> - -<div class="warning"> -<p>你不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:<span class="tcnt">JavaScript 本地对象、内置对象、宿主对象</span> )。</p> - -<p>为了访问标签页的内容,你需要使用 tab.attach() 添加一个脚本,此 add-on 加载加载一个页面,然后将一个脚本附加到所有打开的标签页,该脚本将向标签页的文档添加红色边框:</p> -</div> - -<pre class="brush: js">require("sdk/ui/button/action").ActionButton({ - id: "list-tabs", - label: "List Tabs", - icon: "./icon-16.png", - onClick: listTabs -}); - -function listTabs() { - var tabs = require("sdk/tabs"); - for (let tab of tabs) - runScript(tab); -} - -function runScript(tab) { - tab.attach({ - contentScript: "document.body.style.border = '5px solid red';" - }); -} -</pre> - -<h2 id="学习更多">学习更多</h2> - -<p>要了解更多关于SDK中标签如何工作, 查看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API reference</a>。</p> - -<p>要了解更多关于在标签中运行脚本, 查看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">tutorial on using <code>tab.attach()</code></a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html deleted file mode 100644 index 815cfd42c5..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: 监听页面加载 -slug: Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Listen_for_Page_Load ---- -<p>{{AddonSidebar}}</p> - -<div class="note"><span>学习本教程之前你需要了解 <a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></div> - -<p>你可以使用 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 模块来获取关于新页面加载的通知。下面的附加组件监听标签页内建的 <code>ready</code> 事件,并且记录下每一个标签加载时的URL:</p> - -<pre class="brush: js">require("sdk/tabs").on("ready", logURL); - -function logURL(tab) { - console.log(tab.url); -} -</pre> - -<div class="note"> -<p>你会在<a href="/zh-CN/docs/Tools/Browser_Console">浏览器控制台</a>,而非 <a href="/zh-CN/docs/Tools/Web_Console">Web 控制台</a>中,找到这些输出的内容。</p> -</div> - -<p>你不能直接访问标签页里面的内容。</p> - -<p>为了访问标签页内容,你需要使用 <code>tab.attach()</code> 把一个脚本附到标签页上。这个示例给每一个打开后的标签页附上了一个脚本。这个脚本给标签页的 document 加上了一个红色边框:</p> - -<pre class="brush: js">require("sdk/tabs").on("ready", runScript); - -function runScript(tab) { - tab.attach({ - contentScript: "if (document.body) document.body.style.border = '5px solid red';" - }); -} -</pre> - -<p>(本示例仅仅表示:可以像这样实现一些功能,而你应当使用 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/page-mod"><code>page-mod</code></a>,并且指定匹配模式为 "*"。)</p> - -<h2 id="了解更多">了解更多</h2> - -<p>想要了解更多关于如何在SDK中处理标签页的内容,请看 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API 参考</a>。你能够监听其他一些标签页事件,包括 <code>open</code>、<code>close</code>、和 <code>activate</code>。</p> - -<p>想要了解更多关于在标签页中运行脚本的事情,请看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab"><code>tab.attach() 使用教程</code></a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html deleted file mode 100644 index 5fd51fd8f7..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: 修改标签页中页面 -slug: Mozilla/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab -tags: - - Add-on SDK -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab ---- -<div class="note"> -<p>为了进一步学习本教程,你需要安装 <a href="/en-US/Add-ons/SDK/Tutorials/Installation">Add-on SDK</a> 和学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">cfx的基本使用</a></p> - -<p>这篇教程使用<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API,需要Firefox 29或更新版本。</p> -</div> - -<p>为了修改特定标签页中的页面, 可以使用<code> <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/tabs">tab</a></code>对象的<code>attach()</code> 方法加载一个script脚本到页面中。因为他们的工作是和Web内容进行交互,所以这些脚本被称为content scripts(内容脚本)。</p> - -<p>这是个简单的示例:</p> - -<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({ - id: "style-tab", - label: "Style Tab", - icon: "./icon-16.png", - onClick: function() { - require("sdk/tabs").activeTab.attach({ - contentScript: 'document.body.style.border = "5px solid red";' - }); - } -});</pre> - -<p>要运行这个示例你必须保存一个名为”icon-16.png“的图标文件在你的Add-on目录下的”data”目录下。你可以下载这个图标: <img alt="" src="https://mdn.mozillademos.org/files/7661/icon-16.png" style="width: 16px; height: 16px;">。</p> - -<p>这个插件创建一个按钮,其中包含Mozilla的图标作为一个图标。这个按钮产生一个点击事件处理程序,处理事件中将获取当前活动标签页和加载一个脚本到该标签页中的页面。使用<code>contentscript</code>选项指定加载的脚本,该脚本只绘制一个红色边框页。</p> - -<p>然后在浏览器窗口中打开任何网页,点击按钮 。你会看到一个红色的边界出现在页面中, 就像这样:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6531/tabattach-bbc.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h2 id="保持Content_Script在一个单独的文件中">保持Content Script在一个单独的文件中</h2> - -<p>在上面的例子中我们的<code>content script</code>作为一个字符串来直接使用.除非脚本非常简单,你应该保持脚本作为一个单独的文件。这使得代码更容易维护、调试和审查。</p> - -<p>比如,我们把上面的脚本代码保存在Add-on目录下的data目录中并取名为<code>my-script.js</code>,在代码中可以这样加载脚本:</p> - -<pre class="brush: js">var self = require("sdk/self"); - -var button = require("sdk/ui/button/action").ActionButton({ - id: "style-tab", - label: "Style Tab", - icon: "./icon-16.png", - onClick: function() { - require("sdk/tabs").activeTab.attach({ - contentScriptFile: self.data.url("my-script.js") - }); - } -}); -</pre> - -<p>你可以加载多个脚本,同时这些脚本可以直接相互作用。所以你可以加载 <a href="http://jquery.com/">jQuery</a>, 然后在你的其他 content script使用它。</p> - -<h2 id="与Content_Script传递信息">与Content Script传递信息</h2> - -<p>你的扩展插件脚本Add-on script和内容脚本content script 不能直接访问对方的变量和函数,但他们之间可以互相发送消息。</p> - -<p>从一方发送消息到另外一方, 发送方需要调用 <code>port.emit()发送消息,</code> 同时接收方使用<code>port.on()</code>接收消息。</p> - -<ul> - <li>在 content script 中, <code>port</code> 是全局对象 <code>self</code> 的属性之一.</li> - <li>在 content script 中, <code>tab.attach()</code> 返回一个其中包含 <code>port</code> 属性的 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a> 对象,你可以使用它来向 content script 发送消息</li> -</ul> - -<p>让我们重写上面的例子来从附加内容脚本 content script 传递一个消息。现在content script 需要像下面这样:</p> - -<pre class="brush: js">// "self" is a global object in content scripts -// Listen for a "drawBorder" -self.port.on("drawBorder", function(color) { - document.body.style.border = "5px solid " + color; -}); -</pre> - -<p>在 add-on script 扩展脚本中,我们使用 <code>attach()方法返回的对象向 content script</code> 中发送一个“drawBorder”消息:</p> - -<pre class="brush: js">var self = require("sdk/self"); -var tabs = require("sdk/tabs"); - -var button = require("sdk/ui/button/action").ActionButton({ - id: "style-tab", - label: "Style Tab", - icon: "./icon-16.png", - onClick: function() { - var worker = tabs.activeTab.attach({ - contentScriptFile: self.data.url("my-script.js") - }); - worker.port.emit("drawBorder", "red"); - } -}); -</pre> - -<p>名为 <code>drawBorder</code> 的消息并不是一个内置的消息, 而是通过 <code>port.emit()方法自定义的。</code></p> - -<h2 id="注入_CSS">注入 CSS</h2> - -<p>不像 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod"><code>page-mod</code></a> API, <code>tab.attach()</code> 不允许你直接注入CSS到页面中。</p> - -<p>你需要使用 JavaScript 来修改页面的样式,就像前面的示例那样。</p> - -<h2 id="学习更多">学习更多</h2> - -<p>要了解更多关于在SDK中标签页的使用, 可以查看<a href="/en-US/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开一个网页</a>教程, <a href="/en-US/Add-ons/SDK/Tutorials/List_Open_Tabs">列出打开的标签页</a>教程, 和<a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API 参考手册</a>.</p> - -<p>要学习更多关于content scripts, 查看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content scripts guide</a>.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html deleted file mode 100644 index 6e5e46c532..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Modifying Web Pages Based on URL -slug: Mozilla/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Modifying_Web_Pages_Based_on_URL ---- -<div class="note">开始本教程之前,您必须安装好 <em><strong>SDK</strong></em>,并且学习 <strong><em>cfx </em></strong>的基本的使用方法。</div> - -<p>要修改任何页面匹配特定的模式(比如,“http://example.org/”)当它们加载后,使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>模块。</p> - -<p>要创建 <strong><em>page-mod</em></strong>,您必须指定两件事:</p> - -<ul> - <li>一个或多个 <em><strong>content scripts</strong></em> 运行,它们的工作将和网站内容进行交互</li> - <li>一个或多个 <strong><em>patterns</em> </strong>去匹配您要修改的页面的 URLs</li> -</ul> - -<div class="note"> -<p>content scripts为内容脚本,只能使用普通浏览器支持的 JS,不能使用 add-on 的API</p> -</div> - -<p>这里有一个范例。内容脚本提供contentScript选项,地址样本提供include选项:</p> - -<pre class="brush: js">// Import the page-mod API -var pageMod = require("sdk/page-mod"); - -// Create a page mod -// It will run a script whenever a ".org" URL is loaded -// The script replaces the page contents with a message -pageMod.PageMod({ - include: "*.org", - contentScript: 'document.body.innerHTML = ' + - ' "<h1>Page matches ruleset</h1>";' -}); -</pre> - -<p>试试吧:</p> - -<ul> - <li>创建新的目录并转到该目录下</li> - <li>运行 <code>cfx init</code></li> - <li>打开 <code>lib/main.js</code> 文件,添加以上的代码</li> - <li>运行 <code>cfx run</code></li> - <li>在打开的浏览器窗口中打开 <a href="http://www.ietf.org">ietf.org</a></li> -</ul> - -<p>您将看到:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/6537/pagemod-ietf.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h2 id="指定匹配模式">指定匹配模式</h2> - -<p>匹配模式使用 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/util_match-pattern"><code>match-pattern</code></a> 语法。您可以通过单一的匹配字符串,或者数组。</p> - -<h2 id="把内容脚本放在独立的文件中">把内容脚本放在独立的文件中</h2> - -<p>在上面的范例中我们通过字符串来实现内容脚本。除非是用作简单的例子,通常情况下您应该将内容脚本放在独立文件中,这将使您的代码更易维护、调式和查看。</p> - -<p>要这样做,您需要:</p> - -<ul> - <li>将脚本文件保存在 data 目录下</li> - <li>使用 <code>contentScriptFile</code> 选项代替 <code>contentScript 选项,并且指定脚本的路径</code>。路径用 <code>self.data.url()</code> 取得</li> -</ul> - -<p>例如,如果我们将内容脚本保存在 data 目录下,命名为 my-script.js,在main.js中,我们应该这么写:</p> - -<pre class="brush: js">// Import the page-mod API -var pageMod = require("sdk/page-mod"); -// Import the self API -var self = require("sdk/self"); - -// Create a page mod -// It will run a script whenever a ".org" URL is loaded -// The script replaces the page contents with a message -pageMod.PageMod({ - include: "*.org", - contentScriptFile: self.data.url("my-script.js") -});</pre> - -<h2 id="加载多个Content_Scripts">加载多个Content Scripts</h2> - -<p>您可以加载更多脚本,且脚本可以相互交互。所以,您可以使用jQuery重写 my-script.js:</p> - -<pre class="brush: js">$("body").html("<h1>Page matches ruleset</h1>"); -</pre> - -<p>然后下载 jQuery 库到您的扩展开发目录的 data 目录下,并且将 jQuery 和 my-script 一起加载(确保先加载 jQuery 库):</p> - -<pre class="brush: js">// Import the page-mod API,加载 add-on 的 page-mod API -var pageMod = require("sdk/page-mod"); -// Import the self API, 加载 add-on 的 self API -var self = require("sdk/self"); - -// Create a page mod -// It will run a script whenever a ".org" URL is loaded -// The script replaces the page contents with a message -// 创建 page mod,匹配 “.org” URL -pageMod.PageMod({ - include: "*.org", - contentScriptFile: [self.data.url("jquery-1.7.min.js"), self.data.url("my-script.js")] -}); -</pre> - -<p>您也可以在同一 page-mod 中同时使用 <code>contentScript</code> 和 <code>contentScriptFile</code> 。如果您这么做的话,contentScript的脚本将会先加载。(应该是contentScriptFile的先加载吧?)</p> - -<pre class="brush: js">// Import the page-mod API -var pageMod = require("sdk/page-mod"); -// Import the self API -var self = require("sdk/self"); - -// Create a page mod -// It will run a script whenever a ".org" URL is loaded -// The script replaces the page contents with a message -pageMod.PageMod({ - include: "*.org", - contentScriptFile: self.data.url("jquery-1.7.min.js"), - contentScript: '$("body").html("<h1>Page matches ruleset</h1>");' -}); -</pre> - -<p>注意,您不能直接加载网站上的脚本。脚本必须从 data 目录中加载。</p> - -<h2 id="与_Content_Script_通信">与 Content Script 通信</h2> - -<p>Your add-on script and the content script can't directly access each other's variables or call each other's functions, but they can send each other messages.</p> - -<p>从 Content Script 与 main.js 通信,发送方使用 <code>port.emit()</code> ,接收方使用 <code>port.on()</code> 监听.</p> - -<ul> - <li>In the content script, <code>port</code> is a property of the global <code>self</code> object.</li> - <li>In the add-on script, you need to listen for the <code>onAttach</code> event to get passed a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a> object that contains <code>port</code>.</li> -</ul> - -<p>Let's rewrite the example above to pass a message from the add-on to the content script. The message will contain the new content to insert into the document. The content script now needs to look like this:</p> - -<pre class="brush: js">// "self" is a global object in content scripts -// Listen for a message, and replace the document's -// contents with the message payload. -self.port.on("replacePage", function(message) { - document.body.innerHTML = "<h1>" + message + "</h1>"; -}); -</pre> - -<p>In the add-on script, we'll send the content script a message inside <code>onAttach</code>:</p> - -<pre class="brush: js">// Import the page-mod API -var pageMod = require("sdk/page-mod"); -// Import the self API -var self = require("sdk/self"); - -// Create a page mod -// It will run a script whenever a ".org" URL is loaded -// The script replaces the page contents with a message -pageMod.PageMod({ - include: "*.org", - contentScriptFile: self.data.url("my-script.js"), - // Send the content script a message inside onAttach - onAttach: function(worker) { - worker.port.emit("replacePage", "Page matches ruleset"); - } -}); -</pre> - -<p>The <code>replacePage</code> message isn't a built-in message: it's a message defined by the add-on in the <code>port.emit()</code> call.</p> - -<h2 id="注入_CSS">注入 CSS</h2> - -<div class="warning"> -<p><strong>请注意,本节中描述的功能是实验性的:我们很可能继续支持的功能,但可能需要改变的细节。</strong></p> -</div> - -<p>Rather than injecting JavaScript into a page, you can inject CSS by setting the page-mod's <code>contentStyle</code> option:</p> - -<pre class="brush: js">var pageMod = require("sdk/page-mod").PageMod({ - include: "*", - contentStyle: "body {" + - " border: 5px solid green;" + - "}" -}); -</pre> - -<p>As with <code>contentScript</code>, there's a corresponding <code>contentStyleFile</code> option that's given the URL of a CSS file in your "data" directory, and it is good practice to use this option in preference to <code>contentStyle</code> if the CSS is at all complex:</p> - -<pre class="brush: js">var pageMod = require("sdk/page-mod").PageMod({ - include: "*", - contentStyleFile: require("sdk/self").data.url("my-style.css") -}); -</pre> - -<p>You can't currently use relative URLs in style sheets loaded with <code>contentStyle</code> or <code>contentStyleFile</code>. If you do, the files referenced by the relative URLs will not be found.</p> - -<p>To learn more about this, and read about a workaround, see the <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod#PageMod(options)">relevant section in the page-mod API documentation</a>.</p> - -<h2 id="Learning_More">Learning More</h2> - -<p>To learn more about <code>page-mod</code>, see its <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">API reference page</a>. In particular, the <code>PageMod</code> constructor takes several additional options to control its behavior:</p> - -<ul> - <li> - <p>By default, content scripts are not attached to any tabs that are already open when the page-mod is created, and are attached to iframes as well as top-level documents. To control this behavior use the <code>attachTo</code> option.</p> - </li> - <li> - <p>Define read-only values accessible to content scripts using the <code>contentScriptOptions</code> option.</p> - </li> - <li> - <p>By default, content scripts are attached after all the content (DOM, JS, CSS, images) for the page has been loaded, at the time the <a href="/en-US/docs/Web/API/GlobalEventHandlers.onload">window.onload event</a> fires. To control this behavior use the <code>contentScriptWhen</code> option.</p> - </li> -</ul> - -<p>To learn more about content scripts in general, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content scripts guide</a>.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html deleted file mode 100644 index 7ff9ba7883..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: 打开Web页面 -slug: Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Open_a_Web_Page ---- -{{AddonSidebar}} - -<div class="note"><span>学习本教程之前你需要学习 <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></div> - -<p>打开一个新的网页,你可以使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 模块:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.open({ -"http://www.example.com"); -</pre> - -<p>这个函数是异步的,所以你不能立即获取一个可以检查的标签对象。要做到这一点,通过一个回调函数为open()。将回调函数赋值给 onready 属性,并将通过标签作为参数:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.open({ - url: "http://www.example.com", - onReady: function onReady(tab) { - console.log(tab.title); - } -}); -</pre> - -<div class="warning"> -<p>尽管这样,你还是不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:<span class="tcnt">JavaScript 本地对象、内置对象、宿主对象</span> )。</p> -</div> - -<p> -要访问标签页的内容,你需要使用 tab.attach()把一个脚本添加到该标签页。此add-on加载加载一个页面,然后将一个脚本附加到该页,该将向页面添加红色边框:</p> - -<pre class="brush: js">var tabs = require("sdk/tabs"); -tabs.open({ - url: "http://www.example.com", - onReady: runScript -}); - -function runScript(tab) { - tab.attach({ - contentScript: "document.body.style.border = '5px solid red';" - }); -} -</pre> - -<h2 id="学习更多">学习更多</h2> - -<p>要了解更多关于SDK中标签如何工作, 查看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API reference</a>.</p> - -<p>要了解更多关于在标签中运行脚本, 查看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">tutorial on using <code>tab.attach()</code></a>.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html deleted file mode 100644 index afa3cc0cd3..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Troubleshooting -slug: Mozilla/Add-ons/SDK/Tutorials/Troubleshooting -tags: - - add-on sdk 安装指南 - - add-on sdk安装解惑 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Troubleshooting ---- -<p>{{AddonSidebar}}</p> - -<p>如果你的SDK安装和运行遇到了问题,不要慌!本页面列出了一些基本点,来帮助你追踪你的问题。</p> - -<h2 id="检查你的_Firefox">检查你的 Firefox</h2> - -<p><code>jpm</code> 会搜索你系统中 Firefox 常见的地址,<code>jpm</code> 也许不能找到火狐安装在哪,或者你有多个地方安装了火狐,<code>jpm</code> 也许找错了地方。这种情况下,你需要使用 <code>jpm</code> 的 <code>--binary</code> 选项。参看 <code><a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a></code> 指南以获取更多信息</p> - -<p>当你运行 <code>jpm</code> 来测试你的 add-on 或者运行单元测试时,它会打印出 Firefox 或 XULRunner 二进制文件的地址,所有你可以检查一下它的输出内容来做确认。</p> - -<h2 id="检查你的文本控制台">检查你的文本控制台</h2> - -<p>当你的代码代码和SKD的API产生错误时,他们会被记录到文本控制台。这应该和你运行 <code>jpm</code> 命令的是同一控制台或shell</p> - -<h2 id="搜索已知的问题">搜索已知的问题</h2> - -<p>也许有人已经遇到过和你一样的问题了。其他用户经常发布问题到 <a href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目邮件列表</a>。你也可以浏览<a href="https://bugzilla.mozilla.org/buglist.cgi?order=Bug%20Number&resolution=---&resolution=DUPLICATE&query_format=advanced&product=Add-on%20SDK">已知问题</a>列表或者<a href="https://bugzilla.mozilla.org/query.cgi?format=advanced&product=Add-on%20SDK">搜索</a>特定的关键词。</p> - -<h2 id="与项目团队和用户组交流">与项目团队和用户组交流</h2> - -<p>SDK的用户和项目团队成员对问题和建议在 <a href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目的邮件列表</a>. 别人可能有与你相同的问题,所以试着搜索列表。也欢迎你发表问题.</p> - -<p>你也可以与其他SDK用户在 <a href="http://irc.mozilla.org/">Mozilla的 IRC 网络</a> 的 <a href="http://mibbit.com/?channel=%23jetpack&server=irc.mozilla.org">#jetpack</a> 聊天室聊天.</p> - -<p>如果你想<a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=General">报告SDK的bug</a><span>,我们非常欢迎!您将需要创建一个 Bugzilla 的帐号,Bugzilla 是 Mozilla 的 bug 追踪系统。</span></p> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> - -<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html deleted file mode 100644 index 63cd86da13..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Unit Testing -slug: Mozilla/Add-ons/SDK/Tutorials/Unit_testing -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Unit_testing ---- -<div class="note"> - <p><span>学习本教程你将需要<a href="/en-US/Add-ons/SDK/Tutorials/Installation">安装SDK</a>, 学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">基本操作<code>cfx</code></a>,和学习过<a href="/en-US/Add-ons/SDK/Tutorials/Creating_reusable_modules">编写可重复模块(writing reusable modules)</a>.</span></p> -</div> -<div class="note"> - <p>如果你在使用 <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> 而不是 cfx, 请看关于cfx, 而且重点看<a href="/en-US/Add-ons/SDK/Tools/cfx_to_jpm#Requiring_modules_from_test_code">加载测试模块(loading modules from test code)</a>.</p> -</div> -<p>SDK提供了一个框架,为你的代码创建和运行单元测试.接下来我们将演示如何写一个关于<a href="http://en.wikipedia.org/wiki/Base64">Base64</a> 模块的单元测试.</p> -<h2 id="一个Base64模块例子">一个Base64模块例子</h2> -<p>在一个网页中, 你可以进行Base64的加密和解密,通过使用函数<code>btoa()</code> and <code>atob()</code> .不幸的是这些函数依附在<code>window</code>对象: 由于这个对象在你的add-on(插件) main 的代码里不是有效对象,所以 <code>atob()</code> and <code>btoa()</code> 也不是有效的. 因此我们将展示如何在这个平台上创建一个<code>base64</code>模块 .</p> -<p>To begin with, create a new directory, navigate to it, and run <code>cfx init</code>. Now create a new file in "lib" called "base64.js", and give it the following contents:</p> -<pre class="brush: js">const { atob, btoa } = require("chrome").Cu.import("resource://gre/modules/Services.jsm", {}); - -exports.atob = a => atob(a); -exports.btoa = b => btoa(b); -</pre> -<p>This code exports two functions, which just call the platform's <code>btoa()</code> and <code>atob()</code> functions. To show the module in use, edit the "main.js" file as follows:</p> -<pre class="brush: js">var base64 = require("./base64"); - -var button = require("sdk/ui/button/action").ActionButton({ - id: "base64", - label: "base64", - icon: "./icon-16.png", - onClick: function() { - encoded = base64.btoa("hello"); - console.log(encoded); - decoded = base64.atob(encoded); - console.log(decoded); - } -});</pre> -<p>To run this example you'll also have to have an icon file named "icon-16.png" saved in your add-ons "data" directory. You could download this icon: <img alt="" src="https://mdn.mozillademos.org/files/7661/icon-16.png" style="width: 16px; height: 16px;">.</p> -<p>Now "main.js" imports the base64 module and calls its two exported functions. If we run the add-on and click the button, we should see the following logging output:</p> -<pre>info: aGVsbG8= -info: hello -</pre> -<h2 id="Testing_the_Base64_Module">Testing the Base64 Module</h2> -<p>Navigate to the add-on's <code>test</code> directory and delete the <code>test-main.js</code> file. In its place create a file called <code>test-base64.js</code> with the following contents:</p> -<pre class="brush: js">var base64 = require("./base64"); - -exports["test atob"] = function(assert) { - assert.ok(base64.atob("aGVsbG8=") == "hello", "atob works"); -} - -exports["test btoa"] = function(assert) { - assert.ok(base64.btoa("hello") == "aGVsbG8=", "btoa works"); -} - -exports["test empty string"] = function(assert) { - assert.throws(function() { - base64.atob(); - }, - "empty string check works"); -} - -require("sdk/test").run(exports); -</pre> -<p>This file: exports three functions, each of which expects to receive a single argument which is an <code>assert</code> object. <code>assert</code> is supplied by the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert"><code>test/assert</code></a> module and implements the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification</a>.</p> -<ul> - <li> - <p>The first two functions call <code>atob()</code> and <code>btoa()</code> and use <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#ok(guard.2C_message)"><code>assert.ok()</code></a> to check that the output is as expected.</p> - </li> - <li> - <p>The second function tests the module's error-handling code by passing an empty string into <code>atob()</code> and using <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#throws(block.2C_error.2C_message)"><code>assert.throws()</code></a> to check that the expected exception is raised.</p> - </li> -</ul> -<p>At this point your add-on ought to look like this:</p> -<pre> /base64 - package.json - README.md - /doc - main.md - /lib - main.js - base64.js - /test - test-base64.js -</pre> -<p>Now execute <code>cfx --verbose test</code> from the add-on's root directory. You should see something like this:</p> -<pre>Running tests on Firefox 13.0/Gecko 13.0 ({ec8030f7-c20a-464f-9b0e-13a3a9e97384}) under darwin/x86. -info: executing 'test-base64.test atob' -info: pass: atob works -info: executing 'test-base64.test btoa' -info: pass: btoa works -info: executing 'test-base64.test empty string' -info: pass: empty string check works - -3 of 3 tests passed. -Total time: 5.172589 seconds -Program terminated successfully. -</pre> -<p>What happens here is that <code>cfx test</code>:</p> -<p><span>Note the hyphen after "test" in the module name. <code>cfx test</code> will include a module called "test-myCode.js", but will exclude modules called "test_myCode.js" or "testMyCode.js".</span></p> -<ul> - <li>looks in the <code>test</code> directory of your package</li> - <li>loads any modules whose names start with the word <code>test-</code></li> - <li>calls each exported function whose name starts with "test", passing it an <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#Assert"><code>assert</code></a> object as its only argument.</li> -</ul> -<p>Obviously, you don't have to pass the <code>--verbose</code> option to <code>cfx</code> if you don't want to; doing so just makes the output easier to read.</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html deleted file mode 100644 index e581a0811c..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 日志 -slug: Mozilla/Add-ons/SDK/Tutorials/日志 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Logging ---- -<p>{{AddonSidebar}}</p> - -<div class="note"><span>学习本教程之前你需要学习 </span><span><a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29">jpm 基础</a>. </span></div> - -<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><a href="https://developer.mozilla.org/en/DOM/console">DOM console</a> 对象对调试 Javascript 非常有帮助。但是由于扩展程序无法访问 DOM 对象,sdk 提供了一个拥有大部分 DOM console 对象方法的全局 console 对象,包括打印错误日车、警告和数据信息的方法。你无需 require() 任何模块,就可以直接使用 console 对象。</span></p> - -<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">使用 console.log() 方法来打印信息:</span></p> - -<pre class="brush: js">console.log("Hello World"); -</pre> - -<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span class="md-expand" style="">尝试:</span></span></p> - -<ul style="margin: -1em 0px 1.5em 1.5em; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"> - <li style="margin: 0px; position: relative; list-style-type: disc;"> - <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">新建一个目录,打开它</span></span></p> - </li> - <li style="margin: 0px; position: relative; list-style-type: disc;"> - <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm init</code></span><span style="">,接受所有默认设置</span></span></p> - </li> - <li style="margin: 0px; position: relative; list-style-type: disc;"> - <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">打开 "index.js",并在文件内添加上面的代码</span></span></p> - </li> - <li style="margin: 0px; position: relative; list-style-type: disc;"> - <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-focus md-line" style="display: block; width: 452px;"><span style="">执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span></span></p> - </li> -</ul> - -<p><span class="md-expand" style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Firefox 将会启动,并在你执行 </span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"> 的命令行窗口显示下面的信息:</span></p> - -<pre>console.log: console: Hello world -</pre> - -<h2 id="在内容脚本(conent_script)中使用_console"><code>在内容脚本(conent script)中使用 console</code></h2> - -<p><span class="md-expand" style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">与 addon 主代码一样,你可以在<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">内容脚本</a>中直接使用 console 对象。下面这个扩展在内容脚本中调用了 </span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">console.log()</code></span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"> 方法,作用是在控制台打印出每个打开的标签页内的 HTML 内容:</span></p> - -<pre class="brush: js">require("sdk/tabs").on("ready", function(tab) { - tab.attach({ - contentScript: "console.log(document.body.innerHTML);" - }); -}); -</pre> - -<h2 id="控制台输出"><span style="">控制台输出</span></h2> - -<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">如果你是在命令行启动你的扩展(例如:执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span><span style=""> 或 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm test</code></span><span style="">),那么控制台信息将在你使用的命令行界面中显示。</span></span></p> - -<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">如果你将扩展安装到了 Firefox 中,控制台信息将显示在 Firefox <a href="/en-US/docs/Tools/Browser_Console">浏览器控制台</a>中。</span></span></p> - -<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">但请注意,<strong>默认情况下,任何已经安装的扩展不会在错误控制台中输出任何信息</strong>,包括使用扩展构建程序安装的扩展或者使用其它工具例如:<a href="https://addons.mozilla.org/en-US/firefox/addon/autoinstaller/">Extension Auto-installer</a>。</span></span></p> - -<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-focus md-line" style="display: block; width: 516px;"><span style="">关于此项内容的更多信息请参阅控制台参考文档 “<a href="/en-US/Add-ons/SDK/Tools/console#Logging_Levels">日志等级</a>”。</span></span></p> - -<h2 id="更多">更多</h2> - -<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">完整的 console API,请看 </span> <a href="/en-US/Add-ons/SDK/Tools/console">API 参考文档</a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html deleted file mode 100644 index 77d743e806..0000000000 --- a/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: 添加菜单项 -slug: Mozilla/Add-ons/SDK/Tutorials/添加一个菜单项 -translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Add_a_Context_Menu_Item ---- -<div class="note"> - <p>学习本章前,您要先 <a href="/en-US/Add-ons/SDK/Installation">安装SDK</a> 和学习 <a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code>的基本用法 </a></p> -</div> -<p>用<a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu"><code>右键菜单</code></a>模块添加右键菜单项或子菜单</p> -<p>下面的例子是增加了一个新的上下文菜单项。当页面被选中时才会显示该菜单项,选择的部分会被发送到main.js的add-on代码中,它只是记录:</p> -<pre class="brush: js">var contextMenu = require("sdk/context-menu"); - var menuItem = contextMenu.Item({ - label: "Log Selection", - context: contextMenu.SelectionContext(), - contentScript: 'self.on("click", function () {' + - ' var text = window.getSelection().toString();' + - ' self.postMessage(text);' + - '});', - onMessage: function (selectionText) { - console.log(selectionText); - } -});</pre> -<p>Try it: run the add-on, load a web page, select some text and right-click. You should see the new item appear:</p> -<p>试一试:运行该扩展,加载一个网页,选中一些文本并右键单击。你应该能看到新的项目出现:</p> -<p><img src="https://mdn.mozillademos.org/files/6513/context-menu-selection.png" style="display: block; margin-left: auto; margin-right: auto;"></p> -<p>点击,选中的文本<a href="/en-US/Add-ons/SDK/Tutorials/Logging">记录到控制台</a>:</p> -<pre>info: elephantine lizard -</pre> -<h2 id="细节">细节</h2> -<p><br> - 这个add-on所有的操作是构建一个上下文菜单项。你不需要添加它:一旦你已经建立了项目,它会自动添加在正确的上下文。在这种情况下,构造函数接受四个选项:<code>label</code>,<code>context</code>,和contentscript,onMessage。</p> -<h3 id="label">label</h3> -<p><br> - 标签是字符串的显示。</p> -<h3 id="context">context</h3> -<p><br> - 上下文应该在不同的情境中显示它该做的显示。上下文菜单模块提供了一些简单的内置的上下文,包括selectioncontext(),这意味着:当页面被选中的时候将会显示菜单项。<br> - 如果这些简单的背景是不够的,你可以使用脚本定义更复杂的环境。</p> -<h3 id="contentScript">contentScript</h3> -<p>这将一个脚本项目。在这种情况下,脚本侦听用户点击该项目,然后选定文本用消息发送到add-on。</p> -<h3 id="onMessage">onMessage</h3> -<p>onMessage属性提供附加的代码来响应来自连接到上下文菜单项脚本报文的一种方法。在这种情况下,它只是记录选定的文本。</p> -<p>所以:<br> - 用户点击项目<br> - 内容脚本的点击事件触发,和内容脚本检索选定的文本和发送邮件的附件<br> - 附加的消息事件触发,并附加代码的处理函数是通过选定的文本,它的日志<br> - </p> -<h2 id="获取更多">获取更多</h2> -<p>如果想获取更多信息关于<code>context-menu</code>模块,查看<a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu"><code>context-menu</code> API reference</a>.</p> diff --git a/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html b/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html deleted file mode 100644 index 9790442e3c..0000000000 --- a/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 扩展开发环境设置 -slug: Mozilla/Add-ons/Setting_up_extension_development_environment -tags: - - Extensions -translation_of: Archive/Add-ons/Setting_up_extension_development_environment ---- -<p>本文给出了关于如何为扩展开发配置Mozilla应用程序的建议.</p> -<h2 id=".E5.BC.80.E5.8F.91.E9.85.8D.E7.BD.AE" name=".E5.BC.80.E5.8F.91.E9.85.8D.E7.BD.AE">开发配置</h2> -<p>为了避免由于设置了开发相关的预定义选项导致的性能上的问题,以及避免破坏你的个人数据,建议你可以创建一个新的Profile,而不是使用默认的进行开发工作.</p> -<p>如果你使用<code>-no-remote</code>参数启动Firefox,你可以用不同的Profile运行两个Firefox实例.例如,不管是否"正常"的Firefox是否运行,下面的命令将运行你的开发Profile(假设你的开发Profile命名为"dev").</p> -<pre class="eval">start "" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev -</pre> -<p>用默认的Profile允许Firefox通常仅仅是"firefox"或者"firefox -P default".</p> -<p>你可以使用Firefox稳定版本和开发版本来检查扩展的兼容性(<a class="external" href="http://forums.mozillazine.org/viewtopic.php?t=613873">Installing Firefox 3 or Minefield while keeping Firefox 2</a>).</p> -<h2 id=".E5.BC.80.E5.8F.91.E9.A2.84.E5.AE.9A.E4.B9.89.E9.80.89.E9.A1.B9" name=".E5.BC.80.E5.8F.91.E9.A2.84.E5.AE.9A.E4.B9.89.E9.80.89.E9.A1.B9">开发预定义选项</h2> -<p>这些已定义参数使在低性能的情况下使调试更容易.</p> -<p>查看<a class="external" href="http://www.mozilla.org/support/firefox/edit">编辑配置文件</a>关于设置预定义选项的信息.注意某些设置默认不存在与abount:config中.所以你需要创建一个新的(boolean)的项.</p> -<p>要这样做, 添加下面的代码行到你的Profile目录的 <code>user.js</code> 文件中,如果文件不存在,创建之:</p> -<pre class="eval">user_pref("nglayout.debug.disable_xul_cache",true); -user_pref("browser.dom.window.dump.enabled",true); -</pre> -<p>注意: 对于Firefox 版本 3.0"user.js" 已被 "prefs.js" 替换.</p> -<p>See below under "Development Profile" to setup a separate development profile before you make these changes.</p> -<ul> - <li><strong>javascript.options.showInConsole</strong> = <strong>true</strong>. Logs errors in chrome files to the <a href="/cn/Error_Console" title="cn/Error_Console">Error Console</a>.</li> - <li><strong>nglayout.debug.disable_xul_cache</strong> = <strong>true</strong>. Disables the XUL cache so that changes to windows and dialogs do not require a restart. This assumes you're <a href="#Using_directories_rather_than_JARs">using directories rather than JARs</a>. Changes to XUL overlays will still require reloading of the document overlaid.</li> - <li><strong>browser.dom.window.dump.enabled</strong> = <strong>true</strong>. Enables the use of the dump() statement to print to the standard console. See {{ Domxref("window.dump") }} for more info. You can also use {{ Interface("nsIConsoleService") }} from privileged script.</li> - <li><strong>javascript.options.strict</strong> = <strong>true</strong>. Enables strict JavaScript warnings in the Error Console. Note that since many people have this setting turned off when developing, you will see lots of warnings for problems with their code in addition to warnings for your own extension. You can filter those with <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/1815">Console<sup>2</sup></a>.</li> - <li><strong>extensions.logging.enabled</strong> = <strong>true</strong>. This will send more detailed information about installation and update problems to the Error Console.</li> -</ul> -<h2 id=".E5.BC.80.E5.8F.91.E6.89.A9.E5.B1.95" name=".E5.BC.80.E5.8F.91.E6.89.A9.E5.B1.95">开发扩展</h2> -<p>这些扩展可以帮组你进行扩展开发.</p> -<ul> - <li>DOM 检查器, 自定义安装的一个选项.</li> - <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/216">Venkman</a>, 一个JavaScript 调试器.</li> - <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/7434/">扩展开发者的扩展</a></li> - <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1815">Console<sup>2</sup></a></li> - <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/4453">Chrome 清单</a></li> - <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1843">Firebug</a></li> - <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1729">Execute JS</a></li> - <li><a class="external" href="http://xpcomviewer.mozdev.org">XPCOMViewer</a>, 一个XPCOM 检查器</li> -</ul> -<h2 id=".E8.87.AA.E5.AE.9A.E4.B9.89.E4.BB.A3.E7.A0.81.E4.BD.8D.E7.BD.AE" name=".E8.87.AA.E5.AE.9A.E4.B9.89.E4.BB.A3.E7.A0.81.E4.BD.8D.E7.BD.AE">扩展开发目录设定</h2> -<p>每次因遇到某些变更而不得不重新添加扩展部分的时候,以及,为了保护您的"扩展源文件"不受到卸载过程中被意外删除的风险,其实您可以把"扩展插件目录"从"标准用户配置目录"中移出到你自己想要的文件目录中进行开发。具体操作步骤如下:</p> -<ol> - <li>找到扩展ID:从install.rdf中找到你的扩展ID号,install.rdf就安装在扩展插件的根目录中;</li> - <li>建立文件:在“用户配置目录/extensions/”目录下,用你的扩展插件ID号作为文件名新建一个文件。 (比如: `用户配置目录/extensions/{46D1B3C0-DB7A-4b1a-863A-6EE6F77ECB58}`) (<a class="external" href="http://kb.mozillazine.org/Profile_folder">找到你的用户配置目录所在位置</a>),记得没有文件扩展名。(为了方便说明暂把这个文件称作“扩展外链定位文件” )</li> - <li>设定文件内容:“扩展外链定位文件”里要包含一个路径,这个路径是指向扩展程序的install.rdf所在目录的路径。(例如:`/full/path/to/yourExtension`. Windows用户注意,用大写书写驱动器名以及反斜杠而不是正斜杠,比如:`C:\full\path\to\yourExtension` Here is an example 'C:\sam\workspace\toolbar\helloWorldtoolbar\'). 在Firefox3中, 如果你是通过XPI包安装的扩展,`用户配置目录`下部分或者所有extensions.*的文件可能会被重新设置。虽然这些文件系统会自动重新生成的,还是备份一下先。</li> - <li>把“扩展外链定位文件”放在你的用户配置目录中的扩展目录(`用户配置目录/extension`)下,重启Firefox。</li> -</ol> -<h2 id=".E4.BD.BF.E7.94.A8.E7.9B.AE.E5.BD.95.E8.80.8C.E9.9D.9EJAR" name=".E4.BD.BF.E7.94.A8.E7.9B.AE.E5.BD.95.E8.80.8C.E9.9D.9EJAR">使用目录而非JAR</h2> -<p>无论你是否选择将你的扩展 chrome打包成JAR或是目录,在目录下开发会更简单。如果你选择了一个用于分发的JAR,你仍然可以通过编辑chrome.manifest工作在目录形式下。比如下面的例子</p> -<pre class="eval">content myExtension jar:chrome/myExtension.jar!/content/ -</pre> -<p>不如</p> -<pre class="eval">content myExtension chrome/content/ -</pre> diff --git a/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html b/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html deleted file mode 100644 index 5ffb14d889..0000000000 --- a/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: 向AMO提交一个附加组件 -slug: Mozilla/Add-ons/Submitting_an_add-on_to_AMO -translation_of: Mozilla/Add-ons/Distribution ---- -<p>当你为基于Mozilla的软件(如Firefox,Thunderbird等)制作出了一个全新的附加组件时,你一定希望其他人能够找,到下载并使用它。</p> -<p>Mozilla provides the <a class="external" href="http://addons.mozilla.org" rel="freelink">http://addons.mozilla.org</a> (AMO) web site to provide a repository for add-ons for Mozilla software. When users click the "Get Extensions" link in the <strong>Add-ons</strong> window in Firefox, for example, they are directed to this site.</p> -<p>That makes AMO a great way to get your add-ons to the public. This article provides details on how to submit your article to AMO for distribution.</p> -<div class="note"> - <strong>Not</strong><strong>e:</strong> Attaching your add-on to articles on the Mozilla Developer Center web site won't do you a lot of good, as we delete them. This is not the right place to post your add-ons; please follow the instructions here instead.</div> -<h2 id="Step_1:_Write_your_add-on" name="Step_1:_Write_your_add-on">第一步:编写你的附加组件</h2> -<p>This is important. It's hard to get an add-on accepted into AMO if you don't write it first. Really hard.</p> -<h2 id="Step_2:_Test_your_add-on" name="Step_2:_Test_your_add-on">第二步:测试你的附加组件</h2> -<p>Make sure it works before you submit it. You should try it out on every product you claim to support. In other words, you don't want to advertise that it works in both Firefox and Thunderbird if you haven't tested it in both. Make sure it works in every version you claim to support, too.</p> -<h2 id="Step_3:_Package_your_add-on" name="Step_3:_Package_your_add-on">第三步:打包你的附加组件</h2> -<p>Add-ons distributed by AMO need to be packaged properly as XPI files. See <a href="/en/Extension_Packaging" title="en/Extension_Packaging">Extension Packaging</a> for information on how to do this.</p> -<h2 id="Step_4:_Get_an_AMO_account" name="Step_4:_Get_an_AMO_account">第四部:注册一个AMO账户</h2> -<p>You'll need to have an AMO account so that you can make submissions. To get one, visit the <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/users/register">Register</a> link at the top of any page on the AMO website. Fill out the form and follow the instructions to activate your account.</p> -<p>Obviously, you can skip this step if you already have an AMO account.</p> -<h2 id="Step_5:_Submit_your_add-on" name="Step_5:_Submit_your_add-on">第五步:提交你的附加组件</h2> -<p>To submit an add-on, go to the <a class="link-https" href="https://addons.mozilla.org/developers" title="https://addons.mozilla.org/developers">Developer Control Panel</a>.</p> -<p>You will then be asked to supply a file, as well as information about the add-on.</p> -<p>Once the add-on has been reviewed, it will be made available for downloading. Reviews can take a varying amount of time depending on how many pending submissions there are and the availability of people to perform the reviews.</p> -<h2 id="languages(_fr_frSoumettre_un_module_sur_AMO_)">{{ languages( { "fr": "fr/Soumettre_un_module_sur_AMO" } ) }}</h2> diff --git a/files/zh-cn/mozilla/add-ons/themes/index.html b/files/zh-cn/mozilla/add-ons/themes/index.html deleted file mode 100644 index e7c28ba50c..0000000000 --- a/files/zh-cn/mozilla/add-ons/themes/index.html +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: 主题 -slug: Mozilla/Add-ons/Themes -tags: - - Themes -translation_of: Mozilla/Add-ons/Themes ---- -<p> -</p> -<div class="callout-box"><b><a href="cn/Creating_a_Skin_for_Firefox">Getting Started</a></b><br> -介绍如何为Firefox开发主题。</div> -<div><b>主题</b>指的是程序的皮肤,通过它可以改变程序的外观,满足不同人的不同需要。一个主题可以只改变界面的颜色,也可以改变界面相关的所有元素。</div> -<table class="topicpage-table"> -<tbody><tr> -<td> -<h4 id="Documentation" name="Documentation"> <a>Documentation</a> </h4> -<dl><dt> <a href="cn/%e5%88%9b%e5%bb%ba%e4%b8%80%e5%a5%97_Firefox_%e7%9a%ae%e8%82%a4">创建一套 Firefox 皮肤</a> -</dt><dd> <small>介绍如何为Firefox创建新的主题。</small> -</dd></dl> -<p><span class="comment">一般style翻译成样式</span> -</p> -<dl><dt> <a href="cn/%e4%b8%bb%e9%a2%98%e6%89%93%e5%8c%85">主题打包</a> -</dt><dd> <small>如何将Firefox和Thunderbird的主题打包。</small> -</dd></dl> -<dl><dt> <a href="cn/Theme_changes_in_Firefox_3"> Firefox 2.0 和 3.0 间的主题变更</a> -</dt></dl> -<dl><dt> <a href="cn/Theme_changes_in_Firefox_2"> Firefox 1.5 和 2.0 间的主题变更</a> -</dt><dd> <small> Firefox 发行版1.5和2.0之间的主题全部变更清单。</small> -</dd></dl> -<dl><dt> <a class="external" href="http://forums.mozillazine.org/viewtopic.php?t=197434">Firefox 1.5 和 2.0 间的主题变更 (forum post)</a> -</dt><dd> <small>A forum post at <a class="external" href="http://www.mozillazine.org">MozillaZine</a> outlining the basic theme-related changes between Firefox 1.0 and 1.5.</small> -</dd></dl> -<dl><dt> <a class="external" href="http://cheeaun.phoenity.com/weblog/2004/12/first-steps-in-theme-design.html">主题设计的第一步</a> -</dt><dd> <small>A somewhat aged article discussing theme design for Firefox.</small> -</dd></dl> -<p><span class="alllinks"><a>View All...</a></span> -</p> -</td><td> -<h4 id="Community" name="Community"> Community </h4> -<ul><li> View Mozilla forums... -</li></ul> -<p>{{ DiscussionList("dev-themes", "mozilla.dev.themes") }} -</p> -<ul><li> <a class="link-irc" href="irc://irc.mozilla.org/#themedev">#themedev IRC channel</a> -</li><li> <a class="external" href="http://forums.mozillazine.org/viewforum.php?f=18">MozillaZine Themes forum</a> -</li></ul> -<h4 id="Tools" name="Tools"> Tools </h4> -<ul><li> <a href="cn/DOM_Inspector">DOM Inspector</a> -</li><li> <a class="link-https" href="https://addons.mozilla.org/firefox/63/">InspectorWidget</a> -</li><li> <a class="external" href="http://www.extensionsmirror.nl/index.php?showtopic=21">ChromeEdit extension</a> -</li></ul> -<p><span class="alllinks"><a>View All...</a></span> -</p> -<h4 id="Related_Topics" name="Related_Topics"> Related Topics </h4> -<dl><dd> <a href="cn/CSS">CSS</a> -</dd></dl> -</td></tr></tbody></table> -<p><span class="comment">Categories</span> -</p><p><span class="comment">Interwiki Language Links</span> -</p><p><br> -</p><p><br> -</p> -<div class="noinclude"> -</div> -{{ languages( { "de": "de/Themes", "en": "en/Themes", "es": "es/Temas", "fr": "fr/Th\u00e8mes", "ja": "ja/Themes", "pl": "pl/Motywy", "zh-tw": "zh_tw/\u4f48\u666f\u4e3b\u984c" } ) }} diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html deleted file mode 100644 index 2301b757e7..0000000000 --- a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 创建一套_Firefox_皮肤 -slug: Mozilla/Add-ons/Themes/Obsolete/Creating_a_Skin_for_Firefox -tags: - - Themes -translation_of: Archive/Themes/Creating_a_Skin_for_Firefox ---- -<p> </p> -<h3 id=".E8.AF.B4.E6.98.8E" name=".E8.AF.B4.E6.98.8E">说明</h3> -<p>为了为 Firefox 创建一套皮肤, 你必须知道三件事:如何编辑图像、如何释放zip文件、以及如何更改CSS。Firefox 的按钮图标使用标准的gif、png、和 jpeg 图像并使用 CSS 来定义界面上的一切。</p> -<p><b>什么是皮肤?</b></p> -<p>皮肤不会改版总体的界面;相反的,它仅仅定义了界面看上去的样子。你无法改版用户右击一个图像时发生什么事情,但你可以改版右键菜单的外观(例如使其变为带有粉色圆点装饰)。如果你想更改Firefox的功能,你不得不去改变chrome,这不在本文讨论的范围之内。</p> -<h3 id=".E5.86.85.E5.AE.B9" name=".E5.86.85.E5.AE.B9">内容</h3> -<ul> - <li><a href="cn/%e5%88%9b%e5%bb%ba%e4%b8%80%e5%a5%97Firefox%e7%9a%ae%e8%82%a4/%e4%bb%8e%e8%bf%99%e9%87%8c%e5%bc%80%e5%a7%8b">从这里开始</a></li> -</ul> -<div class="originaldocinfo"> - <h3 id=".E6.96.87.E7.AB.A0.E5.8E.9F.E5.A7.8B.E4.BF.A1.E6.81.AF" name=".E6.96.87.E7.AB.A0.E5.8E.9F.E5.A7.8B.E4.BF.A1.E6.81.AF">文章原始信息</h3> - <ul> - <li>作者:Neil Marshall 和 Tucker Lee</li> - <li>其它贡献者 (建议/校正):Brent Marshall, CDN (<a class="external" href="http://themes.mozdev.org" rel="freelink">http://themes.mozdev.org</a>), JP Martin, Boris Zbarsky, Asa Dotzler, WeSaySo, David James, Dan Mauch, Anders Conbere, Tim Regula (<a class="external" href="http://www.igraphics.nn.cx" rel="freelink">http://www.igraphics.nn.cx</a>)</li> - <li>版权信息:Copyright 2002-2003 Neil Marshall, permission given to MDC to migrate into the wiki April 2005 via email.</li> - <li>原始链接:<a class="external" href="http://www.eightlines.com/neil/mozskin" rel="freelink">http://www.eightlines.com/neil/mozskin</a></li> - </ul> -</div> -<div class="noinclude"> - </div> -<p>{{ languages( { "de": "de/Theme_erstellen", "es": "es/Creando_un_tema_para_Firefox", "fr": "fr/Cr\u00e9er_un_th\u00e8me_pour_Firefox", "ja": "ja/Creating_a_Skin_for_Firefox", "pl": "pl/Tworzenie_sk\u00f3rek_dla_Firefoksa" } ) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html deleted file mode 100644 index 37280321a1..0000000000 --- a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: 创建一套Firefox皮肤 -slug: Mozilla/Add-ons/Themes/Obsolete/Creating_a_Skin_for_Firefox/UUID -translation_of: Archive/Themes/Creating_a_Skin_for_Firefox/UUID ---- -<p>{{wiki.localize('System.API.page-generated-for-subpage')}}</p> diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html deleted file mode 100644 index d420b6ebf0..0000000000 --- a/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Obsolete -slug: Mozilla/Add-ons/Themes/Obsolete -tags: - - NeedsTranslation - - TopicStub -translation_of: Mozilla/Add-ons/Themes/Obsolete ---- -<p>This page collects theme docs that we don't expect will ever be updated, but which we're keeping for the time being as potential source material for updated docs.</p> -<p>{{ ListSubPages ("/en-US/Add-ons/Themes/Obsolete", 5) }}</p> diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html deleted file mode 100644 index 595058f253..0000000000 --- a/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Firefox 3 的界面改动 -slug: Mozilla/Add-ons/Themes/Obsolete/Theme_changes_in_Firefox_3 -tags: - - Themes -translation_of: Archive/Themes/Theme_changes_in_Firefox_3 ---- -<p>{{ Fx_minversion_header(3) }} {{ Draft() }}</p> -<p>本文包含了更新FireFox主题以使其可以在<a href="cn/Firefox_3">Firefox 3</a>下良好表现所需进行的一些改动。</p> -<div class="note"> - <b>Note:</b> We could use an article called <a href="cn/Updating_themes_for_Firefox_3">Updating themes for Firefox 3</a> that would serve as a how-to guide for updating themes. If anyone with theming experience would like to write one, please do!</div> -<h2 id=".E9.BB.98.E8.AE.A4.E4.B8.BB.E9.A2.98.E7.9A.84.E6.94.B9.E5.8A.A8" name=".E9.BB.98.E8.AE.A4.E4.B8.BB.E9.A2.98.E7.9A.84.E6.94.B9.E5.8A.A8">默认主题的改动</h2> -<p>下表列出了Firefox 3默认主题的一些改动。你可以对照此表,确认你所需要做出的改动。</p> -<h3 id=".E6.89.80.E6.9C.89.E6.96.87.E4.BB.B6" name=".E6.89.80.E6.9C.89.E6.96.87.E4.BB.B6">所有文件</h3> -<h4 id=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0" name=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0">所有平台</h4> -<table class="standard-table"> - <tbody> - <tr> - <td class="header">文件</td> - <td class="header">变更</td> - </tr> - <tr> - <td><tt>browser/themes/*/browser/browser.css</tt></td> - <td>The width of the drag and drop indicator is no longer calculated during the drag (tabbrowser.xml). Instead a '-moz-margin-start' property must be added to .tab-drop-indicator-bar, with a value that is half of the width of the indicator image. Also, the visibility of the indicator is now controlled by setting collapsed in tabbrowser.xml. As a result, the 'display' property should be removed from .tab-drop-indicator-bar (including for dragging="true").</td> - </tr> - </tbody> -</table> -<h4 id="Mac_OS_X" name="Mac_OS_X">Mac OS X</h4> -<table class="standard-table"> - <tbody> - <tr> - <td class="header">文件</td> - <td class="header">变动信息</td> - </tr> - <tr> - <td><tt>browser/themes/pinstripe/browser/tabbrowser/tabDragIndicator.png</tt></td> - <td>删除了图片边缘多余的空白,现在图片尺寸变小。也许会对其他使用此图片的Mac平台下的主题产生影响。</td> - </tr> - <tr> - <td><tt>browser/themes/pinstripe/browser/browser.css</tt></td> - <td>.tabbrowser-tab{{ mediawiki.external('first-tab=\"true\"') }} > .tab-image-left不再具有margin-left属性,现在使用定义了相同宽度的.tabs-left元素来替代。在FireFox 2的默认皮肤Winstripe中已经作此处理。</td> - </tr> - </tbody> -</table> -<h3 id="browser.E7.9A.84.E6.94.B9.E5.8A.A8" name="browser.E7.9A.84.E6.94.B9.E5.8A.A8"><tt>browser</tt>的改动</h3> -<h3 id="global.E7.9A.84.E6.94.B9.E5.8A.A8" name="global.E7.9A.84.E6.94.B9.E5.8A.A8"><tt>global</tt>的改动</h3> -<h4 id=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0_2" name=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0_2">所有平台</h4> -<p>“跳转到”按钮现在被放置在地址栏内部,所以此按钮所用的图片(<tt><a class="external" rel="freelink">chrome://browser/skin/Go-arrow.png</a></tt>)需要设计的小一些。控制“跳转到”及其他地址栏中所用到的按钮的显示及隐藏的CSS规则为:</p> -<pre class="eval">#urlbar[pageproxystate="invalid"] > #urlbar-icons > :not(#go-button) , -#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button { - visibility: collapse; -} -</pre> -<h5 id=".E5.A2.9E.E5.8A.A0.E7.9A.84.E5.9B.BE.E7.89.87" name=".E5.A2.9E.E5.8A.A0.E7.9A.84.E5.9B.BE.E7.89.87">增加的图片</h5> -<p>增加了以下图片:</p> -<dl> - <dt> - <tt><a class="external" rel="freelink">chrome://global/skin/icons/information-16.png</a></tt></dt> - <dd> - Used when presenting information notices。</dd> - <dt> - <tt><a class="external" rel="freelink">chrome://global/skin/icons/warning-16.png</a></tt></dt> - <dd> - 用作显示警告窗口。</dd> -</dl> -<h5 id=".E7.A7.BB.E9.99.A4.E7.9A.84.E5.9B.BE.E7.89.87" name=".E7.A7.BB.E9.99.A4.E7.9A.84.E5.9B.BE.E7.89.87">移除的图片</h5> -<p>以下图片被移除:</p> -<dl> - <dt> - <tt><a class="external" rel="freelink">chrome://mozapps/skin/extensions/question.png</a></tt></dt> - <dd> - 不再使用。</dd> -</dl> -<h4 id="Mac_OS_X_2" name="Mac_OS_X_2">Mac OS X</h4> -<p>为Mac OS X平台上的Firefox 3制作的皮肤需要在<tt><a class="external" rel="freelink">chrome://global/skin/wizard.css</a></tt>末尾增加两条CSS规则:</p> -<pre class="eval">.wizard-buttons-btm { - padding:<i>X</i>px; -} - -.wizard-label-box { - display: none; -} -</pre> -<p>此处的数字 - <i> - X</i> - ,即<tt>.wizard-buttons-btm</tt>中的padding值,需要和<tt>.wizard-buttons-box-2</tt>中的margin值相同。</p> -<h5 id=".E5.9B.BE.E7.89.87.E5.8F.98.E5.8A.A8" name=".E5.9B.BE.E7.89.87.E5.8F.98.E5.8A.A8">图片变动</h5> -<p><a class="external" rel="freelink">chrome://global/skin/icons/loading_16.gif</a> 被chrome://global/skin/icons/loading_16.png 替代。</p> -<h3 id="mozapps.E7.9A.84.E6.94.B9.E5.8A.A8" name="mozapps.E7.9A.84.E6.94.B9.E5.8A.A8"><tt>mozapps</tt>的改动</h3> -<h2 id=".E5.8F.82.E8.80.83.E6.96.87.E7.AB.A0" name=".E5.8F.82.E8.80.83.E6.96.87.E7.AB.A0">参考文章</h2> -<p><a href="cn/Theme_changes_in_Firefox_2">Theme changes in Firefox 2</a></p> diff --git a/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html deleted file mode 100644 index 834125bb32..0000000000 --- a/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Embedded WebExtensions -slug: Mozilla/Add-ons/WebExtensions/Embedded_WebExtensions -translation_of: Archive/Add-ons/Embedded_WebExtensions ---- -<div>{{AddonSidebar}}</div> - -<div class="note"> -<p>嵌入一个 WebExtension 需要使用 Firefox 51 或更高版本。在 SDK 附加组件中嵌入一个 WebExtension 还需要 <a href="https://www.npmjs.com/package/jpm">jpm 1.2.0</a>。</p> -</div> - -<p>从 Firefox 51 开始,你可以在传统附加组件类型中嵌入一个 WebExtension。</p> - -<p>传统附加组件可以是经典的<a href="/en-US/docs/Mozilla/Add-ons/Bootstrapped_extensions">自举扩展</a>或者<a href="/en-US/docs/Mozilla/Add-ons/SDK">Add-on SDK</a> 附加组件。嵌入式 WebExtension 的文件打包在传统附加组件中。嵌入式 WebExtension 并不直接与嵌入的附加组件共享范围,但可以使用 {{WebExtAPIRef("runtime")}} API 中定义的消息函数交换消息。</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/13895/embedded-we.png" style="display: block; height: 522px; margin-left: auto; margin-right: auto; width: 429px;"></p> - -<p>这意味着您可以一次性迁移传统附加组件到 WebExtensions,并且在此期间附加组件的功能完全保留。尤其是它可以让您从旧版附加组件<a href="/en-US/Add-ons/WebExtensions/Embedded_WebExtensions#Migrating_data_from_legacy_add-ons">迁移存储数据</a>到 WebExtension,通过撰写一个中间的混合式附加组件,使用旧版 API 读取数据(例如 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> 或 preferences <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Services.jsm">服务</a>)并使用 WebExtension API 写入它(例如 {{WebExtAPIRef("storage")}})。</p> - -<p>连同本指南,我们撰写了两个例子展示如何使用嵌入式 WebExtensions 来帮助从传统附加组件迁移。<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-bootstrapped">如何从自举式附加组件迁移</a>以及<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">如何从 SDK 附加组件迁移</a>。</p> - -<h2 id="嵌入_WebExtension">嵌入 WebExtension</h2> - -<p>如果传统附加组件是一个带有<a href="/en-US/Add-ons/Install_Manifests">install.rdf</a> 的自举式扩展,在该 RDF 中加入 "hasEmbeddedWebExtension" 并设为 "true":</p> - -<pre><<span class="pl-ent">em</span><span class="pl-ent">:</span><span class="pl-ent">hasEmbeddedWebExtension</span>>true</<span class="pl-ent">em</span><span class="pl-ent">:</span><span class="pl-ent">hasEmbeddedWebExtension</span>></pre> - -<div>如果旧式附加组件是一个 SDK 附加组件,在 package.json 中包含 "hasEmbeddedWebExtension" 并设为 <code>true</code>:</div> - -<div> </div> - -<pre class="brush: json"><span class="pl-s"><span class="pl-pds">"</span>hasEmbeddedWebExtension<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span> -</pre> - -<div>WebExtension 本身放在附加组件中的 "webextension" 顶层目录。例如:</div> - -<div> </div> - -<pre>my-boostrapped-addon/ - chrome/ - webextension/ - manifest.json - background.js - ... - bootstrap.js - chrome.manifest - install.rdf</pre> - -<div> </div> - -<div> -<pre>my-sdk-addon/ - index.js - package.json - webextension/ - manifest.json - background.js - ...</pre> -</div> - -<p>Firefox 不将嵌入式 WebExtension 视为一个独立的附加组件。因此,您不应该为它指定一个<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">附加组件 ID</a>。如果你这样做,那只会被忽略。</p> - -<p>但是,在您完成附加组件的迁移并移除旧式嵌入代码后,您必须添加一个 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> 键,设置 ID 为旧式附加组件的 ID。通过此方式,<a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> 可以识别 WebExtension 是旧式附加组件的一个更新。</p> - -<h2 id="启动_WebExtension">启动 WebExtension</h2> - -<p>嵌入式 WebExtension 必须由被嵌入的附加组件明确启动。</p> - -<p>如果被嵌入的附加组件是一个自举式附加组件,那么传递到自举式扩展的 <code><a href="/en-US/Add-ons/Bootstrapped_extensions#startup">startup()</a></code> 函数的 <code>data</code> 将获得一个明确的 <code>webExtension</code>:</p> - -<pre class="brush: js">// bootstrapped add-on - -<span class="pl-k">function</span> <span class="pl-en">startup</span>({webExtension}) { - -...</pre> - -<p>如果被嵌入的附加组件是一个 SDK 附加组件,它可以使用 <code>sdk/webextension</code> 模块访问一个 WebExtension 对象:</p> - -<pre class="brush: js"><span class="pl-k">// SDK add-on - -const</span> <span class="pl-c1">webExtension</span> <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>sdk/webextension<span class="pl-pds">"</span></span>);</pre> - -<p>无论哪种方式,此对象都有一个 <code>startup()</code> 函数,它返回一个 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>。该 promise 使用一个 <code>browser</code> 属性解决一个对象:这包括 {{WebExtAPIRef("runtime")}} API,被嵌入的附加组件可以用它来与嵌入式 WebExtension 交换消息:</p> - -<ul> - <li>{{WebExtAPIRef("runtime.onConnect")}}</li> - <li>{{WebExtAPIRef("runtime.onMessage")}}</li> -</ul> - -<p>例如:</p> - -<pre class="brush: js">// bootstrapped add-on - -function startup({webExtension}) { - webExtension.startup().then(api => { - const {browser} = api; - browser.runtime.onMessage.addListener(handleMessage); - }); -}</pre> - -<pre class="brush: js"><span class="pl-k">// SDK add-on</span> - -const webExtension = require("sdk/webextension"); - -webExtension.startup().then(api => { - const {browser} = api; - browser.runtime.onMessage.addListener(handleMessage); -}); -</pre> - -<p>应注意的是,嵌入的附加组件不能启动通信,它可以使用 <code>onMessage</code> 接收(并可选响应)一次性消息,并可以使用 <code>onConnect</code> 接受连接请求。</p> - -<p>如果嵌入式 WebExtension 缺少一个 manifest,或者如果 manifest 无效,该 promise 会被拒绝。这种情况下,您可以在<a href="/en-US/Add-ons/WebExtensions/Debugging#Viewing_log_output">浏览器工具箱的控制台</a>中看到更多细节。</p> - -<h2 id="交换消息">交换消息</h2> - -<p>一旦嵌入式 WebExtension 处在运行,它可以使用 {{WebExtAPIRef("runtime")}} API 的子集与旧式附加组件交换消息:</p> - -<ul> - <li>它可以使用 {{WebExtAPIRef("runtime.sendMessage()")}} 发送一次性消息。</li> - <li>它可以使用 {{WebExtAPIRef("runtime.connect()")}} 建立一个连接。</li> -</ul> - -<h3 id="无需连接的消息">无需连接的消息</h3> - -<p>要发送一条消息,WebExtension 可以使用 {{WebExtAPIRef("runtime.sendMessage()")}}。您可以省略 <code>extensionId</code> 参数,因为浏览器认为嵌入式 WebExtension 是被嵌入附加组件的一部分:</p> - -<pre class="brush: js">browser.runtime.sendMessage("message-from-webextension").then(reply => { - if (reply) { - console.log("response from legacy add-on: " + reply.content); - } -});</pre> - -<p>被嵌入的附加组件可以使用 {{WebExtAPIRef("runtime.onMessage")}} 对象接收消息(并可选响应):</p> - -<pre class="brush: js">// bootstrapped add-on - -function startup({webExtension}) { - // Start the embedded webextension. - webExtension.startup().then(api => { - const {browser} = api; - browser.runtime.onMessage.addListener((msg, sender, sendReply) => { - if (msg == "message-from-webextension") { - sendReply({ - content: "reply from legacy add-on" - }); - } - }); - }); -}</pre> - -<h3 id="基于连接的消息">基于连接的消息</h3> - -<p>要在 WebExtension 与传统附加组件间设置一个长寿命连接,WebExtension 可以使用 {{WebExtAPIRef("runtime.connect()")}}。</p> - -<pre class="brush: js">var port = browser.runtime.connect({name: "connection-to-legacy"}); - -port.onMessage.addListener(function(message) { - console.log("Message from legacy add-on: " + message.content); -}); -</pre> - -<p>旧式附加组件可以使用 {{WebExtAPIRef("runtime.onConnect")}} 监听连接尝试,双方可以使用得到的 {{webExtAPIRef("runtime.Port")}} 来交换消息:</p> - -<pre class="brush: js">function startup({webExtension}) { - // Start the embedded webextension. - webExtension.startup().then(api => { - const {browser} = api; - browser.runtime.onConnect.addListener((port) => { - port.postMessage({ - content: "content from legacy add-on" - }); - }); - }); -}</pre> - -<h2 id="从传统附加组件迁移数据">从传统附加组件迁移数据</h2> - -<p>嵌入式 WebExtensions 的一项主要用途是迁移附加组件的存储数据。</p> - -<p>人们从旧式附加组件类型迁移的一个主要问题是存储数据,因为旧式附加组件不能使用 WebExtension 存储 API,WebExtensions 也不能使用旧式存储 API。例如,如果一个 SDK 附加组件使用了 SDK 的 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> API 来存储首选项,WebExtension 版本不可能访问这项数据。</p> - -<p>使用嵌入式 WebExtensions,您可以创建一个嵌入了 WebExtension 的附加组件中间版本来迁移数据。中间版本使用旧式 API 读取存储的数据,然后使用 WebExtension API 写入数据。</p> - -<ul> - <li>在初始版本中,基于 SDK 的附加组件使用 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> API 读取和写入附加组件首选项。</li> - <li> - <p>在中间版本中,SDK 附加组件启动嵌入式 WebExtension。WebExtension 要求 SDK 附加组件用 simple-prefs 检索存储的数据。WebExtension 然后使用 {{WebExtAPIRef("storage")}} API 存储数据。</p> - - <div class="note"> - <p>在某些情况下,中间版本必须在初始导入后保持数据同步。例如,<a href="/en-US/Add-ons/WebExtensions/Embedded_WebExtensions#Add-on_preferences_UI">附加组件的首选项界面仍然使用旧系统</a>,所以如果用户在这里修改了设置,它修改的是旧数据。中间的附加组件必须监听这些更改并将新数据发送到嵌入式 WebExtension。</p> - - <p>有个 <a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">"embedded-webextension-sdk"</a> 示例说明了这一点。</p> - </div> - </li> - <li>在最终版本中,附加组件只是一个 WebExtension,并且只使用存储 API。</li> -</ul> - -<p>我们提供了两个例子说明此模式:<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-bootstrapped">"embedded-webextension-bootstrapped"</a> 展示了从一个自举式附加组件迁移,而 <a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">"embedded-webextension-sdk"</a> 展示了从一个 SDK 附加组件迁移。</p> - -<h2 id="限制">限制</h2> - -<h3 id="调试">调试</h3> - -<p>如果您有一个嵌入了 WebExtension 的旧式附加组件,您不能使用新的附加组件调试器来调试它。您必须使用基于浏览器工具箱的<a href="/en-US/Add-ons/WebExtensions/Debugging_(before_Firefox_50)">旧版调试工具</a>。</p> diff --git a/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html b/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html deleted file mode 100644 index 152a15de20..0000000000 --- a/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html +++ /dev/null @@ -1,296 +0,0 @@ ---- -title: 编写适合多进程 Firefox 的扩展 -slug: Mozilla/Add-ons/Working_with_multiprocess_Firefox -translation_of: Archive/Add-ons/Working_with_multiprocess_Firefox ---- -<div class="summary"> -<p>致 Firefox 开发者:本文描述如何使你开发的扩展能在多进程 Firefox 中运行。</p> -</div> - -<p>目前,在桌面版 Firefox 中,Chrome 代码(Chrome Code)和内容(Content)运行在同一个进程里。因此扩展可以直接访问网页内容:</p> - -<pre class="brush: js">gBrowser.selectedBrowser.contentDocument.body.innerHTML = "replaced by chrome code";</pre> - -<p>不过呢,在多进程 Firefox(又称 Electrolysis 或 E10S)中,扩展代码(Add-on Code)和内容则在不同的进程中运行,所以上述直接访问就不一定可行了。</p> - -<p>在多进程 Firefox 中,扩展需要将触及内容的代码分解成单独分离的脚本,也就是所谓的框架脚本(Frame Scripts)。框架脚本在内容进程中运行,可以直接访问内容。框架脚本通过消息传递接口(Message-passing API)与扩展的剩余部分进行通讯。</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/8437/e10s-overview.png" style="display: block; margin-left: auto; margin-right: auto;">运行在 Chrome 进程中的扩展代码必须向框架脚本发送异步消息。这样做可以确保 Firefox 的用户界面不会被内容进程卡死。</p> - -<p>内容进程则可以向 Chrome 进程发送同步或异步消息,不过使用异步消息是再好不过了。</p> - -<p>关于使用消息管理器的更多细节,请参阅:<a href="/zh-CN/docs/The_message_manager">消息管理器指南</a>。接下来,本文将告诉你如何判断你开发的扩展是否会受到这方面的影响,同时简要说明需要如何进行修改。最后,通过对一些简单的样板扩展进行修改,让它们能在多进程 Firefox 中运行。</p> - -<h2 id="检查你的扩展是否受到影响">检查你的扩展是否受到影响</h2> - -<p>总体规则如下:</p> - -<ul> - <li>如果你只是使用附加组件开发工具包的<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/High-Level_APIs">高级接口</a>,你的扩展不会受到影响(附加组件开发工具包尚未完全兼容多进程Firefox,但很快就会完全兼容)。</li> - <li>如果你的扩展完全不访问网络内容,它们也不会受到影响。</li> - <li>如果你通过直接使用<a href="https://developer.mozilla.org/zh-CN/Add-ons/Overlay_Extensions">表层扩展</a>、<a href="https://developer.mozilla.org/zh-CN/Add-ons/Bootstrapped_extensions">启动扩展</a>或<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs">底层开发工具包接口</a>(例如<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs/window_utils">窗口/工具</a>或<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs/tabs_utils">标签页/工具</a>)来访问网络内容,那么你的扩展有可能受到影响。</li> - <li>如果你在标签页中加载可扩展用户界面语言(xul),你的扩展会受到影响。</li> -</ul> - -<p>为了证实是否受到影响,你还需要进一步测试,这个测试过程由两步过程构成:</p> - -<ul> - <li><strong>开启 Firefox 的多进程支持</strong>:<a href="https://nightly.mozilla.org/">Firefox 每夜版</a>(Nightly Build)支持多进程,但是默认是关闭的,而且并没有出现在选项窗口中。启用多进程的方法是访问 about:config 页面,找到名为 browser.tabs.remote.autostart 的项目,将其值设置为true,重启火狐浏览器。启用多进程功能后,标签页的标题会出现下划线以提示用户。</li> - <li><strong>声明你的扩展兼容多进程模式</strong>:为了便于迁移至多进程 Firefox,我们提供<a href="https://developer.mozilla.org/zh-CN/Firefox/Multiprocess_Firefox/Compatibility_shims">兼容性管理工具</a>帮助不兼容多进程的扩展工作。故此,你需要禁用兼容性管理工具以检测你的扩展是否真正兼容。禁用兼容性管理工具的方法是向你的扩展的 install.rdf 文件添加一个名为 multiprocessCompatible 的属性,值为 true。</li> -</ul> - -<p>现在,你可以在多进程 Firefox 中禁用兼容性管理工具来测试你的扩展的兼容性了。可惜你还不能在开启多进程功能的时候安装新扩展,因此你必须先安装好扩展再开启多进程功能。关于这个问题,详见 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1055808">bug 1055808</a>。</p> - -<h2 id="更新你的代码">更新你的代码</h2> - -<p>更新代码的一般方法是:</p> - -<ul> - <li>将你的扩展中需要访问网络内容的部分分解为一个或数个单独的脚本。在多进程Firefox中,这被称为框架脚本。</li> - <li>为你的框架脚本注册 chrome:// 地址。</li> - <li>用<a href="https://developer.mozilla.org/zh-CN/docs/The_message_manager">消息管理器</a>来将脚本加载进 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XUL/browser"><code>browser </code></a>对象。</li> - <li>如果你的扩展需要在主扩展代码和框架脚本之间通信,可以使用消息管理器接口来实现。</li> - <li>如果你需要在标签页中加载可扩展用户界面语言,可以将它们注册为 about: 地址,然后通过 about: 地址加载它们。</li> -</ul> - -<p>更多细节,请参见<a href="/zh-CN/docs/The_message_manager"> message manager</a> 文档。</p> - -<h3 id="新应用程序接口的向前兼容能力">新应用程序接口的向前兼容能力</h3> - -<p>新的多进程 Firefox 的消息接口在多进程模式没有开启的情况下仍然可用。实际上它们从 Firefox 4开始就在某种程度上可用了。不过呢,最初的应用程序接口和现在的并不相同。一些已知的差异如下:</p> - -<ul> - <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=776825">Firefox 17 的界面发生了变化</a>。</li> - <li>在Firefox 19 之前的版本中,类似<code>new content.document.defaultView.XMLHttpRequest()</code>的代码会得到<code>NS_ERROR_FAILURE: Failure</code>的错误值。</li> -</ul> - -<p>你不仅应该在开启了多进程支持的每夜版Firefox上测试你的扩展的变化,而且应该在你打算支持的没有开启多进程支持的发行版(Release Build)中测试。</p> - -<h2 id="举几个例子">举几个例子</h2> - -<p>这部分将演示修改几种不同的扩展的过程。这些扩展都是很简易的,意在展示基础的扩展模式在多进程Firefox中需要的不同处理方式。</p> - -<p>你可以在 <a href="https://github.com/mdn/e10s-example-addons">e10s-example-addons GitHub repository</a> 中找到这些例子的所有源代码。</p> - -<h3 id="在所有页面运行一个脚本">在所有页面运行一个脚本</h3> - -<div class="note"> -<p><a href="https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages">查看这个例子的源代码</a></p> -</div> - -<p>第一个扩展在每一个页面加载的时候运行一些代码。这些代码不和扩展的其他部分交互,它们只是对页面进行一些预设的修改。在这个例子中,扩展向文档的主体(<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/body"><code>body</code></a>)添加了一个边界。</p> - -<p>这个扩展通过将一种“页面加载中”代码碎片(<a href="https://developer.mozilla.org/zh-CN/docs/Code_snippets/On_page_load#Basic_onPageLoad_for_a_browser_window">"On page load" code snippet</a>)附加于可扩展用户界面语言层来实现此修改。</p> - -<pre class="brush: js">var myExtension = { - init: function() { - // The event can be DOMContentLoaded, pageshow, pagehide, load or unload. - if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false); - }, - onPageLoad: function(aEvent) { - var doc = aEvent.originalTarget; // doc is document that triggered the event - if (doc.nodeName != "#document") return; // only documents - // make whatever modifications you want to doc - doc.body.style.border = "5px solid blue"; - } -} - -window.addEventListener("load", function load(event){ - window.removeEventListener("load", load, false); //remove listener, no longer needed - myExtension.init(); -},false);</pre> - -<p>因为这段代码直接访问网络内容,所以它不能在多进程 Firefox 中运行。<br> - <img alt="" src="https://mdn.mozillademos.org/files/8431/all-pages-original.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h4 id="移植到消息管理器">移植到消息管理器</h4> - -<p>为了使用消息管理器移植这个例子,我们可将这个扩展全部的主体部分放入一个框架脚本:</p> - -<pre class="brush: js">// frame-script.js -// will run in the content process - -addEventListener("DOMContentLoaded", function(event) { - var doc = event.originalTarget; - if (doc.nodeName != "#document") return; // only documents - doc.body.style.border = "5px solid red"; -}); -</pre> - -<p>我们将为这个框架脚本注册一个 chrome:// URL :</p> - -<pre>// chrome.manifest - -content modify-all-pages chrome/content/ -</pre> - -<p>我们附加到XUL overlay的主体脚本,只是一个使用全局消息管理器来在每个标签页中加载框架脚本的 stub。</p> - -<pre class="brush: js">// chrome script -// will run in the chrome process - -var globalMM = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager); - -globalMM.loadFrameScript("chrome://modify-all-pages/content/frame-script.js", true);</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/8415/all-pages-ported.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h4 id="移植到_Add-on_SDK">移植到 Add-on SDK</h4> - -<p>一个好的替代这样的一个扩展的思路是将其移植到 Add-on SDK。Add-on SDK 包括一个名为 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a> 的设计为在网页中加载脚本的模块。Add-on SDK 称这些脚本为内容脚本。</p> - -<p>这种情况下扩展的主要代码创建一个 page-mod 来加载内容脚本到用户载入的每个页面:</p> - -<pre class="brush: js">// main.js - -var pageMod = require("sdk/page-mod"); -var self = require("sdk/self"); - -pageMod.PageMod({ - include: "*", - contentScriptFile: self.data.url("modify-all-pages.js") -});</pre> - -<p>内容脚本可以直接修改页面:</p> - -<pre class="brush: js">// modify-all-pages.js - content script - -document.body.style.border = "5px solid green";</pre> - -<h3 id="在活动标签中运行一个脚本">在活动标签中运行一个脚本</h3> - -<div class="note"> -<p><a href="https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-active-page">查看这个例子的代码。</a></p> -</div> - -<p>这个例子说明了一个扩展如何:</p> - -<ul> - <li><a href="/zh-CN/docs/The_message_manager#Types_of_message_manager">向一个特定的XUL <browser> 元素中加载框架脚本</a></li> - <li><a href="/zh-CN/docs/The_message_manager#Synchronous_messaging">从框架脚本向扩展主体发出一个同步的请求</a></li> -</ul> - -<p>这个例子是一个无需重启的扩展,它使用 CustomizableUI 模块添加了一个按钮。当用户点击这个按钮,这个扩展运行一些代码来改变当前标签。其基础构造取自 <a href="https://github.com/jvillalobos/Australis-Hello-World">Jorge Villalobos 的 Australis "Hello World" 扩展</a> .<br> - <br> - 代码实际做的事是:找到任意 <code><a href="/zh-CN/docs/Web/HTML/Element/Img"><img></a></code> 元素并将其 <code>src</code> 替换为从硬编码于扩展中的列表中随机抽取的无意义的 GIF 图像。 无意义的 gifs 从<a href="https://github.com/bwinton/whimsy">Whimsy extension </a>获取。</p> - -<p>第一个版本直接访问页面,因此其不是多进程兼容的:</p> - -<pre class="brush: js">// bootstrap.js - -let Gifinate = { - init : function() { - let io = - Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - - // the 'style' directive isn't supported in chrome.manifest for bootstrapped - // extensions, so this is the manual way of doing the same. - this._ss = - Cc["@mozilla.org/content/style-sheet-service;1"]. - getService(Ci.nsIStyleSheetService); - this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null); - this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET); - - // create widget and add it to the main toolbar. - CustomizableUI.createWidget( - { id : "gifinate-button", - defaultArea : CustomizableUI.AREA_NAVBAR, - label : "Gifinate", - tooltiptext : "Gifinate!", - onCommand : function(aEvent) { - Gifinate.replaceImages(aEvent.target.ownerDocument.defaultView.content.document); - } - }); - }, - - replaceImages : function(contentDocument) { - let images = contentDocument.getElementsByTagName("img"); - for (var i = 0; i < images.length; ++i) { - let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)]; - images[i].src = gif; - } - },</pre> - -<p><img alt="" src="https://mdn.mozillademos.org/files/8433/gifinate-original.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h4 id="移植到消息管理器_2">移植到消息管理器</h4> - -<p>为了移植这个例子到消息管理器,我们将使 <code>onCommand</code> 加载一个框架脚本到当前的 <code><browser></code>,然后监听来自框架脚本的 "request-gifs" 信息。这些 "request-gifs" 信息应当包含我们在此页面上需要的 GIFs :信息监听器取回并返回这个数量的 GIFs。</p> - -<pre class="brush: js">// bootstrap.js -// will run in the chrome process - -let Gifinate = { - init : function() { - let io = - Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - - // the 'style' directive isn't supported in chrome.manifest for bootstrapped - // extensions, so this is the manual way of doing the same. - this._ss = - Cc["@mozilla.org/content/style-sheet-service;1"]. - getService(Ci.nsIStyleSheetService); - this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null); - this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET); - - // create widget and add it to the main toolbar. - CustomizableUI.createWidget( - { id : "gifinate-button", - defaultArea : CustomizableUI.AREA_NAVBAR, - label : "Gifinate Button", - tooltiptext : "Gifinate!", - onCommand : function(aEvent) { - Gifinate.replaceImages(aEvent.target.ownerDocument); - } - }); - }, - - replaceImages : function(xulDocument) { - var browserMM = xulDocument.defaultView.gBrowser.selectedBrowser.messageManager; - browserMM.loadFrameScript("chrome://gifinate/content/frame-script.js", false); - browserMM.addMessageListener("request-gifs", Gifinate.getGifs); - }, - - getGifs : function(message) { - var gifsToReturn = new Array(message.data); - for (var i = 0; i < gifsToReturn.length; i++) { - let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)]; - gifsToReturn[i] = gif; - } - return gifsToReturn; - }, -</pre> - -<p>再次地,我们需要为这个框架脚本注册一个 chrome:// URL:</p> - -<pre>// chrome.manifest - -content gifinate frame-script.js</pre> - -<p>在框架脚本中,我们获取所有的 <code><img></code> 元素并发送 "request-gifs" 信息给扩展主体代码。 由于这是框架脚本我们可以将其变为一个同步信息,并使用其返回值更新 <code>src</code> 属性:</p> - -<pre class="brush: js">// frame-script.js -// will run in the content process - -var images = content.document.getElementsByTagName("img"); -var response = sendSyncMessage("request-gifs", images.length); -var gifs = response[0]; - -for (var i = 0; i < images.length; ++i) { - images[i].src = gifs[i]; -}</pre> - -<p>整个扩展的流程现在像这样:<br> - <img alt="" src="https://mdn.mozillademos.org/files/8411/gifinate-ported.png" style="display: block; margin-left: auto; margin-right: auto;"></p> - -<h2 id="已知问题">已知问题</h2> - -<p>这里是可能影响扩展开发者移植到多进程firefox的开放的bug列表:</p> - -<ul> - <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1051238"><strong>Bug 1051238</strong></a> -<span id="summary_alias_container"> 框架脚本被永久缓存,因此扩展不能在不重启浏览器的情况下正确更新</span></li> - <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017320"><strong>Bug 1017320</strong></a> -<span id="summary_alias_container"> 实施兼容shims的跟踪<span id="short_desc_nonedit_display"> bug</span></span></li> -</ul> diff --git a/files/zh-cn/mozilla/add-ons/雷鸟/index.html b/files/zh-cn/mozilla/add-ons/雷鸟/index.html deleted file mode 100644 index c46b242f7e..0000000000 --- a/files/zh-cn/mozilla/add-ons/雷鸟/index.html +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: 雷鸟扩展 -slug: Mozilla/Add-ons/雷鸟 -translation_of: Mozilla/Thunderbird/Thunderbird_extensions ---- -<div class="callout-box"><strong><a href="/en/Extensions/Thunderbird/Building_a_Thunderbird_extension" title="en/Building_a_Thunderbird_extension">Building a Thunderbird extension</a></strong><br> -Step-by-step explanation on how to build an extension for Thunderbird.</div> - -<div> -<p>{{AddonSidebar}}</p> -本文档是为Mozilla公司的雷鸟邮件客户端开发扩展的教程。Although there are many similarities with <a href="/en/Extensions" title="en/Extensions">Firefox extensions</a> there are also some differences that may confound the starting developer.</div> - -<div><br> -<strong>Please help!</strong> You can <a class="internal" href="/en/Extensions/Thunderbird/HowTos" title="en/Extensions/Thunderbird/HowTos">add a how-to</a> (a question or an answer or a code snippet), <a class="internal" href="/en/Extensions/Thunderbird/Useful_newsgroups_discussions" title="En/Extensions/Thunderbird/Useful newsgroups discussions">summarize and link to a relevant newsgroup discussion</a>, or create a tutorial. Need help? Contact <a class="internal" href="/User:jenzed" title="User:jenzed">jenzed</a>.</div> - -<table class="topicpage-table"> - <tbody> - <tr> - <td> - <h2 id="Documentation" name="Documentation"><a href="/Special:Tags?tag=Extensions&language=en" title="Special:Tags?tag=Extensions&language=en">Documentation</a></h2> - - <h3 id="Getting_started_with_Thunderbird">Getting started with Thunderbird</h3> - - <p>A brave, young developer wants to develop an add-on for Thunderbird. Here's a few links to help them through this journey.</p> - - <ul> - <li>Start by reading the tutorial and learn how to<a class="internal" href="/en/Extensions/Thunderbird/Building_a_Thunderbird_extension" title="En/Building a Thunderbird extension"> build a Thunderbird extension</a> (Outdated, still talks about overlays and the add-on builder is no longer available but the tutorial has not been updated.)</li> - <li>Read about the <a href="/en/Thunderbird/Main_Windows" title="Main Windows">main windows</a> so that you know what one means when they say « thread pane », « preview pane », and « folder pane ».</li> - <li>Read an <a class="external" href="http://blog.xulforum.org/index.php?post/2011/01/03/An-overview-of-Thunderbird-Conversations" title="http://blog.xulforum.org/index.php?post/2011/01/03/An-overview-of-Thunderbird-Conversations">overview</a> of how the various parts of Thunderbird fit together, this really helps get a better understanding of Thunderbird.</li> - <li>Want to do some real stuff? See <a class="external" href="http://blog.xulforum.org/index.php?post/2011/03/14/Basic-MimeMessage-demo" title="http://blog.xulforum.org/index.php?post/2011/03/14/Basic-MimeMessage-demo">how to inspect a message</a> (demo add-on included!)</li> - <li>Play with our other <a href="/en/Extensions/Thunderbird/Demo_Addon" title="Demo Addon">demo add-on</a> that exercises some more advanced Thunderbird-specific features</li> - <li>Want to do even more stuff? Don't reinvent the wheel: steal functions from the <a class="link-https" href="https://github.com/protz/thunderbird-stdlib" title="https://github.com/protz/thunderbird-stdlib">thunderbird-stdlib</a> project (doc <a class="external" href="http://protz.github.com/thunderbird-stdlib/doc/symbols/_global_.html" title="http://protz.github.com/thunderbird-stdlib/doc/symbols/_global_.html">here</a>). Functions for dealing with messages (delete them, archive them, change their tags, etc.) are included.</li> - <li>Haven't found what you're looking for? Read the <a class="internal" href="/en/Extensions/Thunderbird/HowTos" rel="internal" title="en/Extensions/Thunderbird/HowTos">Thunderbird how-tos</a>; they contain a lot of recipes for things extensions want to do.</li> - <li>Still haven't managed to do what you wanted? See the list of all <a class="external" href="http://wiki.mozilla.org/Thunderbird/CommunicationChannels" title="http://wiki.mozilla.org/Thunderbird/CommunicationChannels">Thunderbird communication channels </a>so that you know where to ask when you get stuck :-).</li> - <li>Feeling really brave? Read the source using a <a class="external" href="http://doxygen.db48x.net/comm-central/html/" title="http://doxygen.db48x.net/comm-central/html/">fancy interface</a>; you can often find tests that demonstrate how to do what you're trying to achieve.</li> - </ul> - - <h3 id="The_Gloda_database">The Gloda database</h3> - - <p>Thunderbird has a subsystem called Gloda. Gloda stands for « Global Database », and creates Thunderbird-wide relations between objects. Gloda provides concepts such as Conversations, Messages, Identities, Contacts. All these concepts are related together: a Conversation contains Messages which are linked to Identities (<strong>from</strong> field, <strong>to</strong> field) which are themselves part of a Contact: indeed, a contact has multiple identities.</p> - - <p>Typical use cases for Gloda: find all messages whose subject matches [search term], find all messages from [person], find all messages in the same thread as [a given message], find all messages involving [person], etc. etc.</p> - - <p>Gloda is extremely powerful and is used heavily by add-ons such as <a class="link-https" href="https://addons.mozilla.org/en-US/thunderbird/addon/gmail-conversation-view/" title="https://addons.mozilla.org/en-US/thunderbird/addon/gmail-conversation-view/">Thunderbird Conversations</a>. Learn more about Gloda:</p> - - <ul> - <li>an overview of <a href="/en/Thunderbird/gloda" title="Gloda">Gloda</a></li> - <li>learn how to create <a href="/en/Thunderbird/Creating_a_Gloda_message_query" title="Creating a gloda message query">your first message query</a> and read the <a href="/en/Thunderbird/Gloda_examples" title="Gloda examples">gloda examples</a></li> - <li>learn about the Gloda internals: <a href="/en/Thunderbird/Gloda_debugging" title="Gloda debugging">Gloda debugging</a>, <a href="/en/Thunderbird/Gloda_indexing" title="Gloda indexing">Gloda indexing</a></li> - </ul> - - <h3 id="More_Thunderbird-specific_links">More Thunderbird-specific links</h3> - - <p>Some of these links may be wildly out of date, but they still provide valuable information on the codebase.</p> - - <ul> - <li><a class="internal" href="/en/Extensions/Thunderbird/An_overview_of_the_Thunderbird_interface" title="En/Extensions/Thunderbird/An overview of the Thunderbird interface">An overview of Thunderbird components</a></li> - <li><a class="internal" href="/en/Extensions/Thunderbird/Thunderbird_developer_reference_docs" title="en/Extensions/Thunderbird/Thunderbird developer reference docs">Developer reference docs</a>: - <ul> - <li><a class="internal" href="/en/Folders" title="En/Folders">Folder classes</a></li> - <li><a class="internal" href="/en/DB_Views_(message_lists)" title="En/DB Views (message lists)">DB views (message list)</a></li> - <li><a class="internal" href="/en/Message_Summary_Database" title="En/Message Summary Database">Message summary database</a></li> - <li><a class="internal" href="/en/MailNews_Protocols" title="En/MailNews Protocols">MailNews protocols</a></li> - <li><a class="internal" href="/En/MailNews_Filters" rel="internal" title="En/MailNews Filters">MailNews filters</a></li> - <li><a class="internal" href="/en/Extensions/Thunderbird/Error_reporting_tools" title="en/Extension Library/Extensions/Thunderbird/Error reporting tools">Error reporting tools</a></li> - <li><a href="/en/Toolkit_API/STEEL" title="en/Toolkit API/STEEL">STEEL library</a> (not actively developed anymore, use <a class="link-https" href="https://github.com/protz/thunderbird-stdlib" title="https://github.com/protz/thunderbird-stdlib">https://github.com/protz/thunderbird-stdlib</a>)</li> - <li><a class="external" href="http://quetzalcoatal.blogspot.com/2010/01/developing-new-account-types-part-0.html" title="http://quetzalcoatal.blogspot.com/2010/01/developing-new-account-types-part-0.html">Developing new account types</a> <strong>NEW!</strong></li> - </ul> - </li> - <li><a class="internal" href="/en/Extensions/Thunderbird/Useful_newsgroups_discussions" title="En/Extensions/Thunderbird/Useful newsgroups discussions">Useful newsgroup discussions</a> (watch out, anything that's too old should be regarded suspiciously; there's been significant API rewrite over the past years, and most of these techniques are considerably easier now) </li> - <li><a href="/en/Thunderbird/Thunderbird_API_documentation" title="en/Thunderbird/Thunderbird API documentation">Thunderbird API docs</a> (mostly a collection of out-of-date pages, relevance is rather dubious) </li> - <li><a href="/En/Thunderbird_3_for_developers" title="En/Thunderbird 3 for developers">Thunderbird 3 for developers</a> and <a href="/en/Thunderbird_3.1_for_developers" title="en/Thunderbird 3.1 for developers">Thunderbird 3.1 for developers</a> - changes in the recent Thunderbird updates affecting add-on developers. <a href="/Thunderbird_5_for_developers" title="Thunderbird 5 for developers">Thunderbird 5 for developers</a> has important information on MsgHdrToMimeMessage which is a central piece of code.</li> - </ul> - - <h3 id="General_links">General links</h3> - - <ul> - <li><a class="internal" href="/en/Extensions" title="en/Extensions">General information on developing extensions for Mozilla applications</a></li> - <li><a href="/en/Extensions/Thunderbird/Finding_the_code_for_a_feature" title="en/Extensions/Thunderbird/Finding the code for a feature">Finding the code for a feature</a></li> - <li><a class="external" href="http://kb.mozillazine.org/Category:Thunderbird" title="http://kb.mozillazine.org/Category:Thunderbird">Mozillazine articles on Thunderbird</a></li> - <li><a href="/Special:Tags?tag=Thunderbird" title="https://developer.mozilla.org/Special:Tags?tag=Thunderbird">All pages tagged with Thunderbird</a></li> - <li><a href="/Special:Tags?tag=MailNews" title="https://developer.mozilla.org/Special:Tags?tag=MailNews">All pages tagged with MailNews</a></li> - </ul> - </td> - <td> - <h2 id="Community" name="Community">Community</h2> - - <ul> - <li>See the list of all <a class="external" href="http://wiki.mozilla.org/Thunderbird/CommunicationChannels" title="http://wiki.mozilla.org/Thunderbird/CommunicationChannels">Thunderbird communication channels </a>first</li> - <li>Among these are:</li> - </ul> - - <p>{{ DiscussionList("dev-extensions", "mozilla.dev.extensions") }}</p> - - <ul> - <li><a class="link-irc" href="irc://moznet/#extdev">#extdev IRC channel</a> / <a class="link-irc" href="irc://moznet/#maildev">#maildev IRC channel</a></li> - <li><a class="external" href="http://forums.mozillazine.org/viewforum.php?f=19">MozillaZine forum</a></li> - <li><a class="external" href="http://mozdev.org/mailman/listinfo/project_owners">mozdev project owners</a></li> - <li><a href="/en/Extensions/Community" title="en/Extensions/Community">Other community links...</a></li> - </ul> - - <h2 id="Tools" name="Tools">Tools</h2> - - <ul> - <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/6622" rel="external nofollow" title="https://addons.mozilla.org/en-US/firefox/addon/6622">DOM Inspector</a> edit the live DOM (Firefox and Thunderbird)</li> - <li><a class="link-https" href="https://addons.mozilla.org/thunderbird/addon/workspace-for-thunderbird/" title="https://addons.mozilla.org/thunderbird/addon/workspace-for-thunderbird/">Workspace for Thunderbird</a>, allows running code snippets in Thunderbird and inspecting variable structure and content</li> - <li><a class="external" href="http://www.hacksrus.com/~ginda/venkman/" rel="external nofollow" title="http://www.hacksrus.com/~ginda/venkman/">Venkman</a>, a JavaScript debugger (<a class="external" href="http://addons.mozilla.org/en-US/firefox/addon/216" rel="external nofollow" title="http://addons.mozilla.org/en-US/firefox/addon/216">Firefox</a>, <a class="external" href="http://addons.mozilla.org/en-US/thunderbird/addon/216" rel="external nofollow" title="http://addons.mozilla.org/en-US/thunderbird/addon/216">Thunderbird</a>)</li> - <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/7434/" rel="external nofollow" title="https://addons.mozilla.org/en-US/firefox/addon/7434/">Extension Developer's Extension</a> a suite of development tools</li> - <li><a class="external" href="http://www.gijsk.com/" rel="external nofollow" title="http://www.gijsk.com/">Chrome List</a> view files in chrome:// (<a class="external" href="http://addons.mozilla.org/en-US/firefox/addon/4453" rel="external nofollow" title="http://addons.mozilla.org/en-US/firefox/addon/4453">Firefox</a>, <a class="external" href="http://addons.mozilla.org/en-US/thunderbird/addon/4453" rel="external nofollow" title="http://addons.mozilla.org/en-US/thunderbird/addon/4453">Thunderbird</a>)</li> - <li><a class="external" href="http://addons.mozilla.org/en-US/developers/tools/builder" rel="external nofollow" title="http://addons.mozilla.org/en-US/developers/tools/builder">Add-on Builder</a> a web-based extension skeleton generator (Firefox and Thunderbird)</li> - <li><a href="/en/Mozmill" title="en/Mozmill">Mozmill</a> test tool and framework</li> - <li><a class="external" href="http://xpcomviewer.mozdev.org/" rel="external nofollow" title="http://xpcomviewer.mozdev.org">XPCOMViewer</a> an XPCOM inspector (Firefox and Thunderbird)</li> - </ul> - - <p>... <a class="internal" href="/en/Setting_up_extension_development_environment#Development_extensions" title="en/Setting up extension development environment#Development extensions">more tools</a> ...</p> - - <p><span class="alllinks"><a href="/Special:Tags?tag=Extensions:Tools&language=en" title="Special:Tags?tag=Extensions:Tools&language=en">View All...</a></span></p> - - <h2 id="Related_Topics" name="Related_Topics">Related Topics</h2> - - <dl> - <dd><a href="/en/XUL" title="en/XUL">XUL</a>, <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a>, <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a>, <a href="/en/Themes" title="en/Themes">Themes</a>, <a href="/En/Developer_Guide" title="en/Developing_Mozilla">Developing Mozilla</a></dd> - </dl> - </td> - </tr> - </tbody> -</table> - -<p><span class="comment">Categories</span></p> - -<p>{{ languages( { "ja": "ja/Extensions/Thunderbird" } ) }}</p> |