├── locales ├── zh │ ├── manifest.properties │ └── app.properties ├── ja │ ├── manifest.properties │ └── app.properties ├── es │ ├── manifest.properties │ └── app.properties ├── he │ ├── manifest.properties │ └── app.properties ├── nl │ ├── manifest.properties │ └── app.properties ├── pt_BR │ ├── manifest.properties │ └── app.properties ├── ro │ ├── manifest.properties │ └── app.properties ├── ru │ ├── manifest.properties │ └── app.properties ├── en-US │ ├── manifest.properties │ └── app.properties ├── sk_SK │ ├── manifest.properties │ └── app.properties ├── sv │ ├── manifest.properties │ └── app.properties ├── bn_IN │ ├── manifest.properties │ └── app.properties ├── de │ ├── manifest.properties │ └── app.properties ├── el │ └── manifest.properties ├── hu │ ├── manifest.properties │ └── app.properties ├── it_IT │ ├── manifest.properties │ └── app.properties ├── bn_BD │ ├── manifest.properties │ └── app.properties ├── fa │ ├── manifest.properties │ └── app.properties ├── id │ ├── manifest.properties │ └── app.properties ├── tr │ ├── manifest.properties │ └── app.properties ├── ar │ ├── manifest.properties │ └── app.properties ├── cs │ ├── manifest.properties │ └── app.properties ├── hi │ ├── manifest.properties │ └── app.properties ├── ta │ ├── manifest.properties │ └── app.properties ├── tl │ ├── manifest.properties │ └── app.properties ├── fr │ ├── manifest.properties │ └── app.properties └── locales.ini ├── images ├── logo120.png ├── logo128.png ├── logo16.png ├── logo32.png ├── logo48.png ├── logo60.png ├── logo64.png ├── logo90.png ├── buttons │ ├── ui │ │ ├── danger.png │ │ ├── shadow.png │ │ ├── default.png │ │ ├── disabled.png │ │ ├── recommend.png │ │ ├── shadow@2x.png │ │ ├── shadow@1.5x.png │ │ ├── danger-press.png │ │ └── danger-disabled.png │ └── icons │ │ ├── dialog.png │ │ ├── view.png │ │ ├── view@2x.png │ │ ├── view_rtl.png │ │ ├── dialog@1.5x.png │ │ ├── dialog@2x.png │ │ ├── dialog_rtl.png │ │ ├── view@1.5x.png │ │ ├── view_rtl@2x.png │ │ ├── dialog_rtl@2x.png │ │ ├── view_rtl@1.5x.png │ │ └── dialog_rtl@1.5x.png ├── headers │ ├── icons │ │ ├── add.png │ │ ├── up.png │ │ ├── add@2x.png │ │ ├── back.png │ │ ├── clear.png │ │ ├── close.png │ │ ├── down.png │ │ ├── edit.png │ │ ├── menu.png │ │ ├── reply.png │ │ ├── send.png │ │ ├── update.png │ │ ├── user.png │ │ ├── add@1.5x.png │ │ ├── back-rtl.png │ │ ├── back@2x.png │ │ ├── back_rtl.png │ │ ├── clear@2x.png │ │ ├── close@2x.png │ │ ├── compose.png │ │ ├── edit@2x.png │ │ ├── menu@2x.png │ │ ├── options.png │ │ ├── reply@2x.png │ │ ├── send@2x.png │ │ ├── user@2x.png │ │ ├── back-rtl@2x.png │ │ ├── back@1.5x.png │ │ ├── clear@1.5x.png │ │ ├── close@1.5x.png │ │ ├── compose@2x.png │ │ ├── edit@1.5x.png │ │ ├── menu@1.5x.png │ │ ├── organic │ │ │ ├── add.png │ │ │ ├── back.png │ │ │ ├── close.png │ │ │ ├── edit.png │ │ │ ├── add@1.5.png │ │ │ ├── back@2x.png │ │ │ ├── back_rtl.png │ │ │ ├── close@2x.png │ │ │ ├── back@1.5x.png │ │ │ ├── close@1.5x.png │ │ │ ├── edit@1.5x.png │ │ │ └── back_rtl@1.5x.png │ │ ├── reply-all.png │ │ ├── reply@1.5x.png │ │ ├── reply_all.png │ │ ├── send@1.5x.png │ │ ├── user@1.5x.png │ │ ├── back-rtl@1.5x.png │ │ ├── back_rtl@1.5x.png │ │ ├── compose@1.5x.png │ │ ├── options@1.5x.png │ │ ├── reply-all@2x.png │ │ ├── reply-all@1.5x.png │ │ └── reply_all@1.5x.png │ └── ui │ │ ├── header.png │ │ ├── shadow.png │ │ ├── negative.png │ │ ├── separator.png │ │ ├── shadow@2x.png │ │ ├── subheader.png │ │ ├── dark │ │ ├── header.png │ │ ├── negative.png │ │ ├── separator.png │ │ ├── subheader.png │ │ ├── separator@1.5x.png │ │ └── separator-large.png │ │ ├── shadow@1.5x.png │ │ ├── noise-pattern.png │ │ ├── organic │ │ ├── header.png │ │ ├── negative.png │ │ ├── pattern.png │ │ ├── separator.png │ │ ├── subheader.png │ │ └── separator-large.png │ │ ├── overlay │ │ ├── header.png │ │ └── separator.png │ │ └── separator-large.png └── toolbars │ ├── icons │ └── update.png │ └── ui │ └── background.png ├── fonts ├── FiraSans-Bold.woff ├── FiraSans-Light.woff ├── FiraSans-Medium.woff └── FiraSans-Regular.woff ├── manifest.appcache ├── .htaccess ├── .tx └── config ├── js ├── offline.js ├── base.js ├── webapp.js └── l10n.js ├── css ├── toolbars.css ├── base.css ├── buttons.css └── headers.css ├── fallback.html ├── humans.txt ├── README.md ├── manifest.webapp ├── manifest-hosted.webapp └── index.html /locales/zh/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS 模板程序 2 | description=从Firefox OS模板应用内置的用户示例开始 3 | -------------------------------------------------------------------------------- /locales/ja/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OSボイラプレートアプリ 2 | description=初心者の為のFirefox OS向けサンプルアプリ 3 | -------------------------------------------------------------------------------- /images/logo120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo120.png -------------------------------------------------------------------------------- /images/logo128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo128.png -------------------------------------------------------------------------------- /images/logo16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo16.png -------------------------------------------------------------------------------- /images/logo32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo32.png -------------------------------------------------------------------------------- /images/logo48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo48.png -------------------------------------------------------------------------------- /images/logo60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo60.png -------------------------------------------------------------------------------- /images/logo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo64.png -------------------------------------------------------------------------------- /images/logo90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/logo90.png -------------------------------------------------------------------------------- /fonts/FiraSans-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/fonts/FiraSans-Bold.woff -------------------------------------------------------------------------------- /fonts/FiraSans-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/fonts/FiraSans-Light.woff -------------------------------------------------------------------------------- /fonts/FiraSans-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/fonts/FiraSans-Medium.woff -------------------------------------------------------------------------------- /fonts/FiraSans-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/fonts/FiraSans-Regular.woff -------------------------------------------------------------------------------- /images/buttons/ui/danger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/danger.png -------------------------------------------------------------------------------- /images/buttons/ui/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/shadow.png -------------------------------------------------------------------------------- /images/headers/icons/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/add.png -------------------------------------------------------------------------------- /images/headers/icons/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/up.png -------------------------------------------------------------------------------- /images/headers/ui/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/header.png -------------------------------------------------------------------------------- /images/headers/ui/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/shadow.png -------------------------------------------------------------------------------- /images/buttons/icons/dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog.png -------------------------------------------------------------------------------- /images/buttons/icons/view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view.png -------------------------------------------------------------------------------- /images/buttons/ui/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/default.png -------------------------------------------------------------------------------- /images/buttons/ui/disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/disabled.png -------------------------------------------------------------------------------- /images/buttons/ui/recommend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/recommend.png -------------------------------------------------------------------------------- /images/buttons/ui/shadow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/shadow@2x.png -------------------------------------------------------------------------------- /images/headers/icons/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/add@2x.png -------------------------------------------------------------------------------- /images/headers/icons/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back.png -------------------------------------------------------------------------------- /images/headers/icons/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/clear.png -------------------------------------------------------------------------------- /images/headers/icons/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/close.png -------------------------------------------------------------------------------- /images/headers/icons/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/down.png -------------------------------------------------------------------------------- /images/headers/icons/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/edit.png -------------------------------------------------------------------------------- /images/headers/icons/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/menu.png -------------------------------------------------------------------------------- /images/headers/icons/reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply.png -------------------------------------------------------------------------------- /images/headers/icons/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/send.png -------------------------------------------------------------------------------- /images/headers/icons/update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/update.png -------------------------------------------------------------------------------- /images/headers/icons/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/user.png -------------------------------------------------------------------------------- /images/headers/ui/negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/negative.png -------------------------------------------------------------------------------- /images/headers/ui/separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/separator.png -------------------------------------------------------------------------------- /images/headers/ui/shadow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/shadow@2x.png -------------------------------------------------------------------------------- /images/headers/ui/subheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/subheader.png -------------------------------------------------------------------------------- /images/buttons/icons/view@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view@2x.png -------------------------------------------------------------------------------- /images/buttons/icons/view_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view_rtl.png -------------------------------------------------------------------------------- /images/buttons/ui/shadow@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/shadow@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/add@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/add@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/back-rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back-rtl.png -------------------------------------------------------------------------------- /images/headers/icons/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back@2x.png -------------------------------------------------------------------------------- /images/headers/icons/back_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back_rtl.png -------------------------------------------------------------------------------- /images/headers/icons/clear@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/clear@2x.png -------------------------------------------------------------------------------- /images/headers/icons/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/close@2x.png -------------------------------------------------------------------------------- /images/headers/icons/compose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/compose.png -------------------------------------------------------------------------------- /images/headers/icons/edit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/edit@2x.png -------------------------------------------------------------------------------- /images/headers/icons/menu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/menu@2x.png -------------------------------------------------------------------------------- /images/headers/icons/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/options.png -------------------------------------------------------------------------------- /images/headers/icons/reply@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply@2x.png -------------------------------------------------------------------------------- /images/headers/icons/send@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/send@2x.png -------------------------------------------------------------------------------- /images/headers/icons/user@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/user@2x.png -------------------------------------------------------------------------------- /images/headers/ui/dark/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/header.png -------------------------------------------------------------------------------- /images/headers/ui/shadow@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/shadow@1.5x.png -------------------------------------------------------------------------------- /images/toolbars/icons/update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/toolbars/icons/update.png -------------------------------------------------------------------------------- /images/toolbars/ui/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/toolbars/ui/background.png -------------------------------------------------------------------------------- /images/buttons/icons/dialog@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog@1.5x.png -------------------------------------------------------------------------------- /images/buttons/icons/dialog@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog@2x.png -------------------------------------------------------------------------------- /images/buttons/icons/dialog_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog_rtl.png -------------------------------------------------------------------------------- /images/buttons/icons/view@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view@1.5x.png -------------------------------------------------------------------------------- /images/buttons/icons/view_rtl@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view_rtl@2x.png -------------------------------------------------------------------------------- /images/buttons/ui/danger-press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/danger-press.png -------------------------------------------------------------------------------- /images/headers/icons/back-rtl@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back-rtl@2x.png -------------------------------------------------------------------------------- /images/headers/icons/back@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/clear@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/clear@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/close@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/close@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/compose@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/compose@2x.png -------------------------------------------------------------------------------- /images/headers/icons/edit@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/edit@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/menu@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/menu@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/add.png -------------------------------------------------------------------------------- /images/headers/icons/reply-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply-all.png -------------------------------------------------------------------------------- /images/headers/icons/reply@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/reply_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply_all.png -------------------------------------------------------------------------------- /images/headers/icons/send@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/send@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/user@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/user@1.5x.png -------------------------------------------------------------------------------- /images/headers/ui/dark/negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/negative.png -------------------------------------------------------------------------------- /images/headers/ui/dark/separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/separator.png -------------------------------------------------------------------------------- /images/headers/ui/dark/subheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/subheader.png -------------------------------------------------------------------------------- /images/headers/ui/noise-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/noise-pattern.png -------------------------------------------------------------------------------- /images/headers/ui/organic/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/header.png -------------------------------------------------------------------------------- /images/headers/ui/overlay/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/overlay/header.png -------------------------------------------------------------------------------- /locales/es/manifest.properties: -------------------------------------------------------------------------------- 1 | name=App base para Firefox OS 2 | description=App base para Firefox OS con ejemplos de usos para empezar 3 | -------------------------------------------------------------------------------- /images/buttons/icons/dialog_rtl@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog_rtl@2x.png -------------------------------------------------------------------------------- /images/buttons/icons/view_rtl@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/view_rtl@1.5x.png -------------------------------------------------------------------------------- /images/buttons/ui/danger-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/ui/danger-disabled.png -------------------------------------------------------------------------------- /images/headers/icons/back-rtl@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back-rtl@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/back_rtl@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/back_rtl@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/compose@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/compose@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/options@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/options@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/back.png -------------------------------------------------------------------------------- /images/headers/icons/organic/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/close.png -------------------------------------------------------------------------------- /images/headers/icons/organic/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/edit.png -------------------------------------------------------------------------------- /images/headers/icons/reply-all@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply-all@2x.png -------------------------------------------------------------------------------- /images/headers/ui/organic/negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/negative.png -------------------------------------------------------------------------------- /images/headers/ui/organic/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/pattern.png -------------------------------------------------------------------------------- /images/headers/ui/separator-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/separator-large.png -------------------------------------------------------------------------------- /locales/he/manifest.properties: -------------------------------------------------------------------------------- 1 | name=אפליקציית Firefox OS Boilerplate 2 | description=אפליקציית Firefox OS Boilerplate עם דוגמאות שימוש להתחלה 3 | -------------------------------------------------------------------------------- /locales/nl/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app met voorbeeld use cases om te beginnen 3 | -------------------------------------------------------------------------------- /locales/pt_BR/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app com exemplos de uso para começar 3 | -------------------------------------------------------------------------------- /locales/ro/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app cu exemple de utilizare pentru început 3 | -------------------------------------------------------------------------------- /locales/ru/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app with example use cases to get started 3 | -------------------------------------------------------------------------------- /images/buttons/icons/dialog_rtl@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/buttons/icons/dialog_rtl@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/add@1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/add@1.5.png -------------------------------------------------------------------------------- /images/headers/icons/organic/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/back@2x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/back_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/back_rtl.png -------------------------------------------------------------------------------- /images/headers/icons/organic/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/close@2x.png -------------------------------------------------------------------------------- /images/headers/icons/reply-all@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply-all@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/reply_all@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/reply_all@1.5x.png -------------------------------------------------------------------------------- /images/headers/ui/dark/separator@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/separator@1.5x.png -------------------------------------------------------------------------------- /images/headers/ui/organic/separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/separator.png -------------------------------------------------------------------------------- /images/headers/ui/organic/subheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/subheader.png -------------------------------------------------------------------------------- /images/headers/ui/overlay/separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/overlay/separator.png -------------------------------------------------------------------------------- /locales/en-US/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app with example use cases to get started 3 | -------------------------------------------------------------------------------- /images/headers/icons/organic/back@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/back@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/close@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/close@1.5x.png -------------------------------------------------------------------------------- /images/headers/icons/organic/edit@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/edit@1.5x.png -------------------------------------------------------------------------------- /images/headers/ui/dark/separator-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/dark/separator-large.png -------------------------------------------------------------------------------- /locales/sk_SK/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate Aplikácia 2 | description=Boilerplate Firefox OS aplikácia s príkladmi použitia pre začiatok 3 | -------------------------------------------------------------------------------- /locales/sv/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate-appen 2 | description=Boilerplate Firefox OS-appen med exempel använder cases för att startas 3 | -------------------------------------------------------------------------------- /images/headers/icons/organic/back_rtl@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/icons/organic/back_rtl@1.5x.png -------------------------------------------------------------------------------- /images/headers/ui/organic/separator-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robnyman/Firefox-OS-Boilerplate-App/HEAD/images/headers/ui/organic/separator-large.png -------------------------------------------------------------------------------- /locales/bn_IN/manifest.properties: -------------------------------------------------------------------------------- 1 | name=ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ 2 | description=শুরু করার জন্য ব্যবহারিক উদাহরণ সহ ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ 3 | -------------------------------------------------------------------------------- /locales/de/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Boilerplate App für Firefox OS 2 | description=Boilerplate-App für Firefox OS mit Beispielanwendungsfällen für den Anfang 3 | -------------------------------------------------------------------------------- /locales/el/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate Εφαρμογή 2 | description=Boilerplate Firefox OS εφαρμογή με παραδείγματα χρήσης για να ξεκινήσετε 3 | -------------------------------------------------------------------------------- /locales/hu/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate Firefox OS app használati mintaesetekkel a kezdés megkönnyítéséért 3 | -------------------------------------------------------------------------------- /locales/it_IT/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate App 2 | description=Boilerplate per FirefoxOS con esempi e casi d'uso per iniziare lo sviluppo 3 | -------------------------------------------------------------------------------- /locales/bn_BD/manifest.properties: -------------------------------------------------------------------------------- 1 | name=ফায়ারফক্স ওএস বয়লারপ্লেট অ্যাপ 2 | description=ব্যবহারিক ক্ষেত্রের উদাহরণসহ ফায়ারফক্স ওএস বয়লারপ্লেট অ্যাপ নিয়ে শুরু করুন 3 | -------------------------------------------------------------------------------- /locales/fa/manifest.properties: -------------------------------------------------------------------------------- 1 | name=برنامه ساز ابتدایی سیستم عامل فایرفاکس 2 | description=برنامه ساز ابتدایی سیستم عامل فایرفاکس با مثال کاربردی برای شروع به کار 3 | -------------------------------------------------------------------------------- /locales/id/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate Aplikasi 2 | description=Aplikasi boilerplate Firefox OS dengan contoh kasus penggunaan untuk memulai 3 | -------------------------------------------------------------------------------- /locales/tr/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Firefox OS Boilerplate Uygulaması 2 | description=Başlamak için örnek kullanım durumları ile Boilerplate Firefox OS uygulaması 3 | -------------------------------------------------------------------------------- /locales/ar/manifest.properties: -------------------------------------------------------------------------------- 1 | name=التطبيق المساعد لبدء التطوير لـFirefox OS 2 | description=تطبيق يُساعدك على بدء التطوير لنظام Firefox مُرفق بأمثلة عن حالات الاستخدام 3 | -------------------------------------------------------------------------------- /locales/cs/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Aplikace Firefox OS Boilerplate 2 | description=Aplikace Boilerplate Firefox OS s ukázkovými příklady použití, které vám umožní začít 3 | -------------------------------------------------------------------------------- /locales/hi/manifest.properties: -------------------------------------------------------------------------------- 1 | name=फायर फॉक्स OS BoilerPlate App 2 | description=बॉयलरप्लेट फायरफॉक्स OS एप्प उदहारण के साथ। शुरू करने के लिए cases का इस्तेमाल करें 3 | -------------------------------------------------------------------------------- /locales/ta/manifest.properties: -------------------------------------------------------------------------------- 1 | name=பையர்பாக்ஸ் ஓ.எஸ் பாயீலர்பிலேட் ஆப் 2 | description=பாயீலர்பிலேட் பையர்பாக்ஸ் ஓ.எஸ் ஆப் உடன் யூஸ்கேஸ்சின் தொடக்கத்திற்காண எடுத்து காட்டு 3 | -------------------------------------------------------------------------------- /locales/tl/manifest.properties: -------------------------------------------------------------------------------- 1 | name=App ng Firefox OS Boilerplate 2 | description=Boilerplate Firefox OS app na may halimbawa ay gumagamit ng mga kaso upang makapagsimula 3 | -------------------------------------------------------------------------------- /locales/fr/manifest.properties: -------------------------------------------------------------------------------- 1 | name=Modèle d’application pour Firefox OS 2 | description=Modèle d’application pour Firefox OS avec des exemples de cas d’utilisation pour bien commencer 3 | -------------------------------------------------------------------------------- /manifest.appcache: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # Version 0.6799999 3 | 4 | index.html 5 | css/base.css 6 | js/base.js 7 | js/webapp.js 8 | js/offline.js 9 | 10 | NETWORK: 11 | * 12 | 13 | FALLBACK: 14 | / fallback.html 15 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | FileETag None 3 | 4 | Header unset ETag 5 | Header set Cache-Control "max-age=0, no-cache, must-revalidate" 6 | Header set Pragma "no-cache" 7 | Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT" 8 | 9 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [firefox-os-boilerplate.app_properties] 5 | file_filter = locales//app.properties 6 | source_file = locales/en-US/app.properties 7 | source_lang = en 8 | type = MOZILLAPROPERTIES 9 | minimum_perc = 50 10 | 11 | [firefox-os-boilerplate.manifest_properties] 12 | file_filter = locales//manifest.properties 13 | source_file = locales/en-US/manifest.properties 14 | source_lang = en 15 | type = MOZILLAPROPERTIES 16 | minimum_perc = 50 17 | 18 | -------------------------------------------------------------------------------- /js/offline.js: -------------------------------------------------------------------------------- 1 | /* global confirm */ 2 | "use strict"; 3 | (function () { 4 | var appCache = window.applicationCache; 5 | if (appCache) { 6 | appCache.onupdateready = function () { 7 | if (confirm("The app has been updated. Do you want to download the latest files? \nOtherwise they will be updated at the next reload.")) { 8 | location.reload(true); 9 | } 10 | }; 11 | 12 | var displayStatus = document.querySelector("#online-status"); 13 | if (displayStatus) { 14 | // Using this, since navigator.onLine is very inconcistent and unreliable 15 | appCache.onerror = function() { 16 | displayStatus.className = "offline"; 17 | displayStatus.title = "Offline"; 18 | }; 19 | 20 | } 21 | } 22 | })(); -------------------------------------------------------------------------------- /css/toolbars.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- 2 | * Toolbars 3 | * ---------------------------------- */ 4 | 5 | [role="toolbar"] { 6 | height: 4rem; 7 | width: 100%; 8 | position: fixed; 9 | bottom: 0; 10 | left: 0; 11 | z-index: 100; 12 | background: rgba(0,0,0, 0.85); 13 | } 14 | 15 | [role="toolbar"] ul { 16 | float: left; 17 | list-style: none; 18 | padding: 0; 19 | margin: 0; 20 | } 21 | 22 | [role="toolbar"] ul:last-child { 23 | float: right; 24 | } 25 | 26 | [role="toolbar"] li { 27 | float: left; 28 | } 29 | 30 | [role="toolbar"] button { 31 | width: 5.5rem; 32 | height: 4rem; 33 | border: none; 34 | font-size: 0; 35 | background: transparent no-repeat 50% 50% / 3rem auto; 36 | padding: 0; 37 | border-radius: 0; 38 | } 39 | 40 | [role="toolbar"] button:active { 41 | background-color: #008aaa; 42 | } 43 | -------------------------------------------------------------------------------- /fallback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Offline - Firefox OS Boilerplate App 8 | 9 | 10 | 11 | 12 |
13 |

Firefox OS Boilerplate

14 |
15 | 16 |
17 |

You are currently offline. You came here through the manifest.appcache file.

18 |
19 | 20 |
21 |
    22 |
  • 23 |
  • 24 |
25 |
26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /humans.txt: -------------------------------------------------------------------------------- 1 | Firefox OS Boilerplate App 2 | --------------------------- 3 | Author: Robert Nyman 4 | Site: http://robnyman.github.io/Firefox-OS-Boilerplate-App/ 5 | Github: https://github.com/robnyman/Firefox-OS-Boilerplate-App 6 | Transifex: https://www.transifex.com/projects/p/firefox-os-boilerplate/ 7 | 8 | Contributors on Github 9 | ----------------------- 10 | amirouche 11 | christi3k 12 | fharper 13 | jor3l 14 | mpous 15 | Mte90 16 | ossreleasefeed 17 | potch 18 | taboca 19 | zalun 20 | zenorocha 21 | 22 | Localizers on Transifex 23 | ------------------------ 24 | ariestiyansyah 25 | dbcomp 26 | C7DB 27 | cuneytoktay 28 | davidbourguignon 29 | Dominick 30 | dsecsuresh 31 | FabioMagnoni 32 | ffee_machine 33 | gorjuce 34 | Imrizalp 35 | Mte90 36 | Martin1982 37 | nclm 38 | pj.pradeepjha 39 | sayak 40 | sourav26721062 41 | stelistcristi 42 | sweb 43 | ThomasTursics 44 | ravmn 45 | vahagnbn 46 | yourfrienddhruv 47 | 48 | Last updated: 10 December 2013 49 | -------------------------------------------------------------------------------- /locales/zh/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = FireFox OS 示例程序 2 | web-activities = 网络应用 3 | pick-image = 选择图像 4 | pick-anything = 选择文件 5 | take-picture = 照相 6 | dial-number = 拨号 7 | dial-sms = 发送短信 8 | add-contact = 添加联系人 9 | share-url = 分享链接 10 | share-image = 分享图片 11 | view-url = 查看链接 12 | compose-email = 写邮件 13 | save-bookmark = 保存书签 14 | web-apis = 网络应用接口 15 | add-notification = 添加到通知项 16 | orientation-lock = 屏幕方向锁定 17 | vibrate = 震动2秒 18 | add-alarm = 添加闹钟 19 | check-connection = 查看连接状态 20 | connection-values = 在这里显示连接信息 21 | check-battery = 查看电池状态 22 | battery-values = 在这里显示电池电量 23 | geolocation = 地理位置信息 24 | golocation-values = 在这里显示地理位置坐标 25 | ambient-light = 环境光状况 26 | ambient-light-values = 在这里显示环境光状态 27 | proximity = 接近状态 28 | proximity-values = 在这里显示接近状态 29 | user-proximity = 用户接近程度 30 | user-proximity-values = 在这里显示用户接近程度 31 | device-orientation = 设备旋转状态 32 | device-orientation-values = 在这里显示设备旋转状态 33 | priv-apis = 私有接口 34 | cross-domain-xhr = 跨域XHR 35 | device-storage-pictures = 设备存储器 - 图像 36 | get-all-contacts = 获取所有联系人信息 37 | update-button = 更新 38 | log-visibility = 应用可见度 39 | setup-permissions = 当前使用的这些程序接口需要在manifest.webapp文件中设置相应权限: 40 | open-video = 打开视频 41 | -------------------------------------------------------------------------------- /locales/locales.ini: -------------------------------------------------------------------------------- 1 | @import url(en-US/app.properties) 2 | [ar] 3 | @import url(ar/app.properties) 4 | [bn-IN] 5 | @import url(bn_IN/app.properties) 6 | [cs] 7 | @import url(cs/app.properties) 8 | [de] 9 | @import url(de/app.properties) 10 | [en-US] 11 | @import url(en-US/app.properties) 12 | [el] 13 | @import url(el/app.properties) 14 | [es] 15 | @import url(es/app.properties) 16 | [fa] 17 | @import url(fa/app.properties) 18 | [fr] 19 | @import url(fr/app.properties) 20 | [id] 21 | @import url(id/app.properties) 22 | [he] 23 | @import url(he/app.properties) 24 | [hi] 25 | @import url(hi/app.properties) 26 | [hu] 27 | @import url(hu/app.properties) 28 | [id] 29 | @import url(id/app.properties) 30 | [it] 31 | @import url(it_IT/app.properties) 32 | [ja] 33 | @import url(ja/app.properties) 34 | [nl] 35 | @import url(nl/app.properties) 36 | [pt-BR] 37 | @import url(pt_BR/app.properties) 38 | [ro] 39 | @import url(ro/app.properties) 40 | [ru] 41 | @import url(ru/app.properties) 42 | [sk-SK] 43 | @import url(sk_SK/app.properties) 44 | [sv] 45 | @import url(sv/app.properties) 46 | [ta] 47 | @import url(ta/app.properties) 48 | [tl] 49 | @import url(tl/app.properties) 50 | [tr] 51 | @import url(tr/app.properties) 52 | [zh] 53 | @import url(zh/app.properties) 54 | -------------------------------------------------------------------------------- /locales/ja/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OSボイラプレートアプリ 2 | web-activities = Webアクティビティ 3 | pick-image = 画像を選択 4 | pick-anything = 何かを選択 5 | take-picture = 写真を撮る 6 | dial-number = 電話の発信 7 | dial-sms = SMSを送信 8 | add-contact = 連絡先の追加 9 | share-url = URLの共有 10 | share-image = 画像の共有 11 | view-url = URLを閲覧 12 | compose-email = メールを作成 13 | save-bookmark = ブックマークを保存 14 | web-apis = ウェブAPI 15 | add-notification = 通知を設定 16 | orientation-lock = 画面の向きをロック 17 | vibrate = 2秒間振動 18 | add-alarm = アラームを追加 19 | check-connection = 接続を確認 20 | connection-values = 接続の数値はここに表示されるはず 21 | check-battery = 電池を確認 22 | battery-values = 電池の数値はここに表示されるはず 23 | geolocation = 位置情報 24 | golocation-values = 位置情報の座標はここに表示されるはず 25 | ambient-light = 周辺光量 26 | ambient-light-values = 周辺光量の数値はここに表示されるはず 27 | proximity = 近接 28 | proximity-values = 近接の数値はここに表示されるはず 29 | user-proximity = ユーザー近接 30 | user-proximity-values = ユーザー近接の数値はここに表示されるはず 31 | device-orientation = 端末の向き 32 | device-orientation-values = 端末の向きはここに表示されるはず 33 | priv-apis = 特権API 34 | cross-domain-xhr = クロスドメインXHR 35 | device-storage-pictures = 内蔵ストレージ/画像 36 | get-all-contacts = 全ての連絡先を収得 37 | update-button = 更新 38 | log-visibility = アプリの不透明度 39 | setup-permissions = 以下のAPIに関する許可設定はmanifest.webappというファイルに記されてるべき 40 | open-video = 動画を開く 41 | -------------------------------------------------------------------------------- /js/base.js: -------------------------------------------------------------------------------- 1 | /* global alert, console */ 2 | "use strict"; 3 | // Install app 4 | if (navigator.mozApps) { 5 | var checkIfInstalled = navigator.mozApps.getSelf(); 6 | checkIfInstalled.onsuccess = function () { 7 | if (checkIfInstalled.result) { 8 | // Already installed 9 | var installationInstructions = document.querySelector("#installation-instructions"); 10 | if (installationInstructions) { 11 | installationInstructions.style.display = "none"; 12 | } 13 | } 14 | else { 15 | var install = document.querySelector("#install"), 16 | manifestURL = location.href.substring(0, location.href.lastIndexOf("/")) + "/manifest-hosted.webapp"; 17 | install.className = "show-install"; 18 | install.onclick = function () { 19 | var installApp = navigator.mozApps.install(manifestURL); 20 | installApp.onsuccess = function() { 21 | install.style.display = "none"; 22 | }; 23 | installApp.onerror = function() { 24 | alert("Install failed\n\n:" + installApp.error.name); 25 | }; 26 | }; 27 | } 28 | }; 29 | } 30 | else { 31 | console.log("Open Web Apps not supported"); 32 | } 33 | 34 | // Reload content 35 | var reload = document.querySelector("#reload"); 36 | if (reload) { 37 | reload.onclick = function () { 38 | location.reload(true); 39 | }; 40 | } -------------------------------------------------------------------------------- /locales/he/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = אפליקציית Firefox OS Boilerplate 2 | web-activities = פעילויות אינטרנט 3 | pick-image = בחר תמונה 4 | pick-anything = בחר הכל 5 | take-picture = צלם 6 | dial-number = חייג מספר 7 | dial-sms = שלח SMS 8 | add-contact = הוסף איש קשר 9 | share-url = שתף קישור 10 | share-image = שתף תמונה 11 | view-url = הראה קישור 12 | compose-email = דואר אלקטרוני חדש 13 | save-bookmark = שמור סימניה 14 | web-apis = אינטרנט API 15 | add-notification = הוסף התראה 16 | orientation-lock = נעילת כיוון 17 | vibrate = רטוט 2 שניות 18 | add-alarm = הוסף אזעקה 19 | check-connection = בדוק חיבור 20 | connection-values = ערכי החיבור צריכים להופיע כאן 21 | check-battery = בדוק סוללה 22 | battery-values = ערכי הסוללה צריכים להופיע כאן 23 | geolocation = מיקום גיאוגרפי 24 | golocation-values = נקודות ציון המיקום הגיאוגרפי צריכים להופיע כאן 25 | ambient-light = אור הסביבה 26 | ambient-light-values = אור הסביבה צריך להופיע כאן 27 | proximity = קירבה 28 | proximity-values = הקירבה צריכה להופיעה כאן 29 | user-proximity = קירבת המשתמש 30 | user-proximity-values = קירבת המשתמש צריכה להופיעה כאן 31 | device-orientation = כיוון המכשיר 32 | device-orientation-values = כיוון המכשיר צריך להופיע כאן 33 | priv-apis = API מיוחסים 34 | cross-domain-xhr = XHR בין-תחומי 35 | device-storage-pictures = deviceStorage - תמונות 36 | get-all-contacts = קבל את כל אנשי הקשר 37 | update-button = עדכן 38 | log-visibility = נראות האפליקציה 39 | setup-permissions = הרשאות נכונות צריכות להיות מוגדרות בקובץ manifest.webapp ל-API אלו: 40 | open-video = פתח וידאו 41 | -------------------------------------------------------------------------------- /locales/ar/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = التطبيق المساعد لبدء التطوير لـFirefox OS 2 | web-activities = WebActivities 3 | pick-image = انتقِ صورة 4 | pick-anything = انتقِ أي شيء 5 | take-picture = التقط صورة 6 | dial-number = اطلب رقماً 7 | dial-sms = أرسل رسالة قصيرة 8 | add-contact = أضف جهة اتصال 9 | share-url = شارك رابطاً 10 | share-image = شارك صورةً 11 | view-url = اعرض رابطاً 12 | compose-email = اكتب رسالة بريد 13 | save-bookmark = احفظ علامة 14 | web-apis = WebAPIs 15 | add-notification = أضف إشعاراً 16 | orientation-lock = أقفل دوران الجهاز 17 | vibrate = اهتزّ ثانيتين 18 | add-alarm = أضف منبّهاً 19 | check-connection = تفقد الاتصال 20 | connection-values = ينبغي أن تظهر قيم الاتصال هنا 21 | check-battery = تفقد البطارية 22 | battery-values = ينبغي أن تظهر قيم البطارية هنا 23 | geolocation = الموقع الجغرافي 24 | golocation-values = ينبغي أن تظهر إحداثيات الموقع الجغرافي هنا 25 | ambient-light = الضوء المحيط 26 | ambient-light-values = ينبغي أن تظهر قيمة الضوء المحيط هنا 27 | proximity = القُرب 28 | proximity-values = يجب أن تظهر قيمة القرب هنا 29 | user-proximity = قُرب المستخدم 30 | user-proximity-values = ينبغي أن تظهر قيمة قرب المستخدم هنا 31 | device-orientation = اتجاه الجهاز 32 | device-orientation-values = ينبغي أن يظهر اتجاه الجهاز هنا 33 | priv-apis = الواجهات البرمجية المُمتازة 34 | cross-domain-xhr = XHR العابرة للمواقع 35 | device-storage-pictures = deviceStorage - الصور 36 | get-all-contacts = اجلب كل جهات الاتصال 37 | update-button = حدّث 38 | log-visibility = ظهور التطبيق 39 | setup-permissions = يجب أن تُعين الأذونات الصحيحة في ملف manifest.webapp للوصول إلى الواجهات البرمجية التالية: 40 | open-video = افتح الفيديو 41 | -------------------------------------------------------------------------------- /locales/hi/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = फायर फॉक्स OS BoilerPlate App 2 | web-activities = वेब गतिविधियाँ 3 | pick-image = चित्र चुनें 4 | pick-anything = कुछ भी चुनें 5 | take-picture = चित्र लें 6 | dial-number = नंबर डायल करें 7 | dial-sms = sms भेजें 8 | add-contact = संपर्क जोडें 9 | share-url = URL साझा करें 10 | share-image = चित्र साझा करें 11 | view-url = URL देखें 12 | compose-email = मेल लिखें 13 | save-bookmark = बुकमार्क सहेजे 14 | web-apis = वेबAPIs 15 | add-notification = नोटीफीकेसन जोडें 16 | orientation-lock = अनुस्थापन ताला 17 | vibrate = 2 सेकंड के लिए कंपाएं 18 | add-alarm = अलार्म जोडें 19 | check-connection = कनेक्सन जांचें 20 | connection-values = कनेक्सन के मान यहाँ दिखाई देने चाहिए 21 | check-battery = बैटरी जांचें 22 | battery-values = बैटरी के मान यहाँ दिखाई देने चाहिए 23 | geolocation = भोगोलिक स्थिति 24 | golocation-values = भोगोलिक स्थिति के को-ओरडीनेट यहाँ दिकाई देने चाहिए 25 | ambient-light = व्यापक रोशिनी 26 | ambient-light-values = व्यापक रोशिनी यहाँ दिखाई देनी चाहिए 27 | proximity = निकटता 28 | proximity-values = निकटता यहाँ दिखाई देनी चाहिए 29 | user-proximity = यूजर की निकटता 30 | user-proximity-values = यूजर की निकटता यहाँ दिखाई देनी चाहिए 31 | device-orientation = उपकरण अनुस्थापन 32 | device-orientation-values = उपकरण अनुस्थापन यहाँ दिखाई देनी चाहिए 33 | priv-apis = विशेषाधिकार प्राप्त APIs 34 | cross-domain-xhr = क्रॉस डोमेन XHR 35 | device-storage-pictures = उपकरण स्टोरेज - तसवीरें 36 | get-all-contacts = सभी संपर्क पायें 37 | update-button = अपडेट 38 | log-visibility = एप्प की दर्शनीयता 39 | setup-permissions = यह APIs के लिए उचित अनुमति manifest.webapp file में स्थापित किये होने चाहिए: 40 | open-video = वीडियो खोले 41 | -------------------------------------------------------------------------------- /locales/id/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate Aplikasi 2 | web-activities = WebActivities 3 | pick-image = Pilih gambar 4 | pick-anything = Pilih apapun 5 | take-picture = Ambil gambar 6 | dial-number = Memanggil nomor 7 | dial-sms = Kirim SMS 8 | add-contact = Tambah kontak 9 | share-url = Bagi URL 10 | share-image = Bagi gambar 11 | view-url = Lihat URL 12 | compose-email = Menulis surat 13 | save-bookmark = Simpan penanda 14 | web-apis = WebAPIs 15 | add-notification = Tambah notifikasi 16 | orientation-lock = Orientasi kunci 17 | vibrate = Getar 2 detik 18 | add-alarm = Tambah alaram 19 | check-connection = Cek koneksi 20 | connection-values = Nilai koneksi seharusnya muncul di sini 21 | check-battery = Cek baterai 22 | battery-values = Nilai baterai seharusnya muncul di sini 23 | geolocation = Geolokasi 24 | golocation-values = Coords geolokasi harus muncul di sini 25 | ambient-light = Cahaya ambient 26 | ambient-light-values = Cahaya ambient harus muncul di sini 27 | proximity = Kedekatan 28 | proximity-values = Kedekatan seharusnya muncul di sini 29 | user-proximity = Kedekatan pengguna 30 | user-proximity-values = Kedekatan pengguna seharusnya muncul di sini 31 | device-orientation = Orientasi perangkat 32 | device-orientation-values = Orientasi perangkat seharusnya muncul di sini 33 | priv-apis = API istimewa 34 | cross-domain-xhr = Cross-domain HXR 35 | device-storage-pictures = deviceStorage - gambar 36 | get-all-contacts = Dapatkan semua kontak 37 | update-button = Perbarui 38 | log-visibility = Visibiltas aplikasi 39 | setup-permissions = Izin yang benar harus telah dibentuk dalam file manifest.webapp untuk API ini: 40 | open-video = Buka video 41 | -------------------------------------------------------------------------------- /locales/en-US/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivities 3 | pick-image = Pick image 4 | pick-anything = Pick anything 5 | take-picture = Take picture 6 | dial-number = Dial number 7 | dial-sms = Send SMS 8 | add-contact = Add contact 9 | share-url = Share URL 10 | share-image = Share Image 11 | view-url = View URL 12 | compose-email = Compose mail 13 | save-bookmark = Save bookmark 14 | web-apis = WebAPIs 15 | add-notification = Add notification 16 | orientation-lock = Orientation lock 17 | vibrate = Vibrate 2 sec 18 | add-alarm = Add alarm 19 | remove-all-alarms = Remove all alarms 20 | check-connection = Check connection 21 | connection-values = Connection values should show up here 22 | check-battery = Check battery 23 | battery-values = Battery values should show up here 24 | geolocation = Geolocation 25 | golocation-values = Geolocation coords should show up here 26 | ambient-light = Ambient light 27 | ambient-light-values = Ambient light should show up here 28 | proximity = Proximity 29 | proximity-values = Proximity should show up here 30 | user-proximity = User proximity 31 | user-proximity-values = User proximity should show up here 32 | device-orientation = Device orientation 33 | device-orientation-values = Device orientation should show up here 34 | priv-apis = Privileged APIs 35 | cross-domain-xhr = Cross-domain XHR 36 | device-storage-pictures = deviceStorage - pictures 37 | get-all-contacts = Get all contacts 38 | update-button = Update 39 | log-visibility = App visibility 40 | setup-permissions = Correct permissions need to have been set up in the manifest.webapp file for these APIs: 41 | open-video = Open video 42 | open-settings = Open Settings -------------------------------------------------------------------------------- /locales/bn_IN/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ 2 | web-activities = ওয়েব এক্টিভিটি 3 | pick-image = ছবি বেছে নিন 4 | pick-anything = যে কোনটি বেছে নিন 5 | take-picture = ছবি তুলুন 6 | dial-number = নম্বর ডায়াল করুন 7 | dial-sms = বার্তা পাঠাও 8 | add-contact = পরিচিতি যুক্ত করুন 9 | share-url = URL শেয়ার করুন 10 | share-image = ছবি শেয়ার করুন 11 | view-url = URL দেখুন 12 | compose-email = মেল লিখুন 13 | save-bookmark = বুকমার্ক সংরক্ষন করুন 14 | web-apis = ওয়েব APIs 15 | add-notification = নোটিফিকেশন যুক্ত করুন 16 | orientation-lock = ওরিয়েন্টেশন লক 17 | vibrate = 2 সেকেন্ড যাবৎ ভাইব্রেট করুন 18 | add-alarm = এলার্ম যুক্ত করুন 19 | check-connection = সংযোগ পরীক্ষা করুন 20 | connection-values = সংযোগের মানসমূহ এখানে দেখাবে 21 | check-battery = ব্যাটারি পরীক্ষা করুন 22 | battery-values = ব্যাটারির মানসমূহ এখানে দেখাবে 23 | geolocation = ভৌগলিক অবস্থান 24 | golocation-values = ভৌগলিক স্থানাংকসমূহ এখানে দেখাবে 25 | ambient-light = চারপাশের আলো 26 | ambient-light-values = চারপাশের আলোর তথ্য এখানে দেখাবে 27 | proximity = প্রক্সিমিটি 28 | proximity-values = প্রক্সিমিটি এর তথ্য এখানে দেখাবে 29 | user-proximity = ব্যবহারকারীর প্রক্সিমিটি 30 | user-proximity-values = ব্যবহারকারীর প্রক্সিমিটি তথ্য এখানে দেখাবে 31 | device-orientation = ডিভাইস ওরিয়েন্টেশন 32 | device-orientation-values = ডিভাইস ওরিয়েন্টেশন এর তথ্য এখানে দেখাবে 33 | priv-apis = প্রিভিলেজড APIs 34 | cross-domain-xhr = Cross-domain XHR 35 | device-storage-pictures = deviceStorage - pictures 36 | get-all-contacts = সব পরিচিতিগুলি নিন 37 | update-button = হালনাগাদ করা 38 | log-visibility = অ্যাপ দৃশ্য 39 | setup-permissions = এই এপিআইগুলোর জন্য manifest.webapp নথিটিতে সঠিকভাবে অনুমতি নির্ধারন করতে হবে 40 | open-video = চলমান দৃশ্য খুলুন 41 | -------------------------------------------------------------------------------- /locales/bn_BD/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = ফায়ারফক্স ওএস বয়লারপ্লেট অ্যাপ 2 | web-activities = ওয়েব এক্টিভিটি 3 | pick-image = ছবি বেছে নিন 4 | pick-anything = যে কোনটি বেছে নিন 5 | take-picture = ছবি তুলুন 6 | dial-number = নম্বর ডায়াল করুন 7 | dial-sms = বার্তা পাঠাও 8 | add-contact = পরিচিতি যুক্ত করুন 9 | share-url = ইউআরএল শেয়ার করুন 10 | share-image = ছবি শেয়ার করুন 11 | view-url = ইউআরএল দেখুন 12 | compose-email = মেইল লিখুন 13 | save-bookmark = বুকমার্ক সংরক্ষন করুন 14 | web-apis = ওয়েব এপআই 15 | add-notification = নোটিফিকেশন যুক্ত করুন 16 | orientation-lock = ওরিয়েন্টেশন লক 17 | vibrate = ২ সেকেন্ড যাবৎ ভাইব্রেট করুন 18 | add-alarm = এলার্ম যুক্ত করুন 19 | check-connection = সংযোগ পরীক্ষা করুন 20 | connection-values = সংযোগের মানসমূহ এখানে দেখাবে 21 | check-battery = ব্যাটারি পরীক্ষা করুন 22 | battery-values = ব্যাটারির মানসমূহ এখানে দেখাবে 23 | geolocation = ভৌগলিক অবস্থান 24 | golocation-values = ভৌগলিক স্থানাংকসমূহ এখানে দেখাবে 25 | ambient-light = চারপাশের আলো 26 | ambient-light-values = চারপাশের আলোর তথ্য এখানে দেখাবে 27 | proximity = প্রক্সিমিটি 28 | proximity-values = প্রক্সিমিটি এর তথ্য এখানে দেখাবে 29 | user-proximity = ব্যবহারকারীর প্রক্সিমিটি 30 | user-proximity-values = ব্যবহারকারীর প্রক্সিমিটি তথ্য এখানে দেখাবে 31 | device-orientation = ডিভাইস ওরিয়েন্টেশন 32 | device-orientation-values = ডিভাইস ওরিয়েন্টেশন এর তথ্য এখানে দেখাবে 33 | priv-apis = প্রিভিলেজড এপিআই 34 | cross-domain-xhr = Cross-domain XHR 35 | device-storage-pictures = deviceStorage - pictures 36 | get-all-contacts = সব পরিচিতিগুলি নিন 37 | update-button = হালনাগাদ করা 38 | log-visibility = অ্যাপ দৃশ্য 39 | setup-permissions = এই এপিআইগুলোর জন্য manifest.webapp নথিটিতে সঠিকভাবে অনুমতি নির্ধারন করতে হবে 40 | open-video = চলমান দৃশ্য খুলুন 41 | -------------------------------------------------------------------------------- /locales/sv/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate-app 2 | web-activities = Webb-aktiviteter 3 | pick-image = Välj bild 4 | pick-anything = Välj vad som helst 5 | take-picture = Ta foto 6 | dial-number = Slå nummer 7 | dial-sms = Skicka SMS 8 | add-contact = Lägg till kontakt 9 | share-url = Dela URL 10 | share-image = Dela bild 11 | view-url = Visa URL 12 | compose-email = Skriv e-post 13 | save-bookmark = Spara bokmärke 14 | web-apis = Webb-API:er 15 | add-notification = Lägg till meddelande 16 | orientation-lock = Lås orienteringen 17 | vibrate = Vibrera 2 sekunder 18 | add-alarm = Lägg till alarm 19 | remove-all-alarms = Ta bort alla alarm 20 | check-connection = Kontrollera uppkopplingen 21 | connection-values = Uppkopplingsvärden ska visas här 22 | check-battery = Kontrollera batteriet 23 | battery-values = Batterivärdena ska visas här 24 | geolocation = Geografiskt läge 25 | golocation-values = Geolocation-koordinater ska visas här 26 | ambient-light = Omgivande ljus 27 | ambient-light-values = Omgivande ljus ska visas här 28 | proximity = Närhet 29 | proximity-values = Närhet ska visas här 30 | user-proximity = Användarnärhet 31 | user-proximity-values = Användarnärhet ska visas här 32 | device-orientation = Enhetens orientering 33 | device-orientation-values = Enhetens riktning ska visas här 34 | priv-apis = Privilegierade API:er 35 | cross-domain-xhr = Cross-domain XHR 36 | device-storage-pictures = deviceStorage - bilder 37 | get-all-contacts = Få alla kontakter 38 | update-button = Uppdatera 39 | log-visibility = App-synlighet 40 | setup-permissions = Korrekta tillstånd måste ha ställts in i manifest.webapp-filen för dessa API:er: 41 | open-video = Öppna video 42 | open-settings = Öppna Inställningar -------------------------------------------------------------------------------- /locales/tr/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate Uygulaması 2 | web-activities = AğEtkinlikleri 3 | pick-image = Görüntü seç 4 | pick-anything = Herhangi bir şey seç 5 | take-picture = Fotoğraf çek 6 | dial-number = Numara çevir 7 | dial-sms = SMS Gönder 8 | add-contact = Kişi ekle 9 | share-url = Bağlantı Paylaş 10 | share-image = Görüntü Paylaş 11 | view-url = Bağlantıyı Gör 12 | compose-email = Posta oluştur 13 | save-bookmark = Yer imi kaydet 14 | web-apis = AğAPI'leri 15 | add-notification = Bildirim ekle 16 | orientation-lock = Oryantasyon kilidi 17 | vibrate = 2 saniye titret 18 | add-alarm = Alarm ekle 19 | check-connection = Bağlantıyı kontrol et 20 | connection-values = Bağlantı değerleri burada gösterilmelidir 21 | check-battery = Pili kontrol et 22 | battery-values = Pil değerleri burada gösterilmelidir 23 | geolocation = Coğrafi Konum 24 | golocation-values = Coğrafi konum koordinatları burada gösterilmelidir 25 | ambient-light = Ortam ışığı 26 | ambient-light-values = Ortam ışığı burada gösterilmelidir 27 | proximity = Yakınlık 28 | proximity-values = Yakınlık burada gösterilmelidir 29 | user-proximity = Kullanıcı yakınlığı 30 | user-proximity-values = Kullanıcı yakınlığı burada gösterilmelidir 31 | device-orientation = Aygıt oryantasyonu 32 | device-orientation-values = Aygıt oryantasyonu burada gösterilmelidir 33 | priv-apis = Ayrıcalıklı API'ler 34 | cross-domain-xhr = Etki alanları arası XHR 35 | device-storage-pictures = aygıtBelleği - resimler 36 | get-all-contacts = Tüm bağlantıları al 37 | update-button = Güncelle 38 | log-visibility = Uygulama görünürlüğü 39 | setup-permissions = Şu API'ler için doğru izinlerin manifest.webapp dosyasında ayarlanması gerekli: 40 | open-video = Videoyu aç 41 | -------------------------------------------------------------------------------- /locales/sk_SK/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate Aplikácia 2 | web-activities = WebAktivity 3 | pick-image = Vyberte obrázok 4 | pick-anything = Vyberte čokoľvek 5 | take-picture = Vyfotiť 6 | dial-number = Vytočiť číslo 7 | dial-sms = Poslať SMS 8 | add-contact = Pridať kontakt 9 | share-url = Zdielať URL 10 | share-image = Zdielať obrázok 11 | view-url = Pozrieť URL 12 | compose-email = Napísať mail 13 | save-bookmark = Uložiť záložku 14 | web-apis = WebAPI 15 | add-notification = Pridať upozornenie 16 | orientation-lock = Zámok orientácie 17 | vibrate = Vibrovať 2 sekundy 18 | add-alarm = Pridať alarm 19 | check-connection = Skontrolovať pripojenie 20 | connection-values = Hodnoty pripojenia by sa mali zobraziť tu 21 | check-battery = Skontrolovať batériu 22 | battery-values = Hodnoty batérie by sa mali zobraziť tu 23 | geolocation = Geolokácia 24 | golocation-values = Geolokačné súradnice by sa mali zobraziť tu 25 | ambient-light = Okolité svetlo 26 | ambient-light-values = Úroveň okolitého svetla by sa mala zobraziť tu 27 | proximity = Vzdialenosť 28 | proximity-values = Vzdialenosť by sa mala zobraziť tu 29 | user-proximity = Užívateľská vzdialenosť 30 | user-proximity-values = Užívateľská vzdialenosť by sa mala zobraziť tu 31 | device-orientation = Poloha zariadenia 32 | device-orientation-values = Poloha zariadenia by sa mala zobraziť tu 33 | priv-apis = Privilegované API 34 | cross-domain-xhr = Naprieč-doménový XHR 35 | device-storage-pictures = Pamäť zariadenia - obrázky 36 | get-all-contacts = Získať všetky kontakty 37 | update-button = Aktualizácia 38 | log-visibility = Viditeľnosť aplikácie 39 | setup-permissions = Správne poverenia musia byť nastavené v manifest.webapp súbore pre tieto API: 40 | open-video = Otvoriť video 41 | -------------------------------------------------------------------------------- /locales/de/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Boilerplate-App für Firefox OS 2 | web-activities = Web-Aktivitäten 3 | pick-image = Grafik auswählen 4 | pick-anything = Irgendetwas auswählen 5 | take-picture = Bild aufnehmen 6 | dial-number = Nummer anrufen 7 | dial-sms = SMS senden 8 | add-contact = Kontakt hinzufügen 9 | share-url = Adresse teilen 10 | share-image = Grafik teilen 11 | view-url = Adresse anzeigen 12 | compose-email = E-Mail verfassen 13 | save-bookmark = Lesezeichen erstellen 14 | web-apis = Web-APIs 15 | add-notification = Benachrichtigung hinzufügen 16 | orientation-lock = Ausrichtung sperren 17 | vibrate = 2 Sek. vibrieren 18 | add-alarm = Alarm erstellen 19 | check-connection = Verbindung überprüfen 20 | connection-values = Verbindungsstatus 21 | check-battery = Batteriestatus 22 | battery-values = Batteriedaten sollten hier erscheinen 23 | geolocation = Standort 24 | golocation-values = Standortdaten sollten hier erscheinen 25 | ambient-light = Umgebungslicht 26 | ambient-light-values = Umgebungslichtdaten sollten hier erscheinen 27 | proximity = Entfernungssensor 28 | proximity-values = Daten vom Entfernungssensor sollten hier erscheinen 29 | user-proximity = Nutzer-Entfernung 30 | user-proximity-values = Die Entfernung des Benutzer sollte hier erscheinen 31 | device-orientation = Geräteausrichtung 32 | device-orientation-values = Die Geräteausrichtung sollte hier erscheinen 33 | priv-apis = Privilegierte API 34 | cross-domain-xhr = Cross-Domain-XHR 35 | device-storage-pictures = deviceStorage - Bilder 36 | get-all-contacts = Alle Kontakte 37 | update-button = Aktualisieren 38 | log-visibility = App-Sichtbarkeit 39 | setup-permissions = Die Berechtigungen für folgende APIs müssen in der Datei manifest.webapp gesetzt werden: 40 | open-video = Video öffnen 41 | -------------------------------------------------------------------------------- /locales/nl/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivities 3 | pick-image = Kies afbeelding 4 | pick-anything = Kies alles 5 | take-picture = Neem een foto 6 | dial-number = Bel nummer 7 | dial-sms = Verstuur SMS 8 | add-contact = Voeg contactpersoon toe 9 | share-url = Deel URL 10 | share-image = Deel afbeelding 11 | view-url = Bekijk URL 12 | compose-email = E-mail opstellen 13 | save-bookmark = Favoriet opslaan 14 | web-apis = WebAPIs 15 | add-notification = Notificatie toevoegen 16 | orientation-lock = Oriëntatie slot 17 | vibrate = Vibreer 2 sec 18 | add-alarm = Alarm toevoegen 19 | check-connection = Connectie controleren 20 | connection-values = Connectie waarden moeten hier verschijnen 21 | check-battery = Controleer de accu 22 | battery-values = Accu waarden moeten hier getoond worden 23 | geolocation = Geolocatie 24 | golocation-values = Geolocatie coordinaten moeten hier getoond worden 25 | ambient-light = Omgevingslicht 26 | ambient-light-values = De omgevingsbelichting moet hier getoond worden 27 | proximity = Nabijheid 28 | proximity-values = De nabijheid moet hier getoond worden 29 | user-proximity = Gebruikers nabijheid 30 | user-proximity-values = De gebruikers-nabijheid moet hier getoond worden 31 | device-orientation = Apparaat oriëntatie 32 | device-orientation-values = De apparaat oriëntatie moet hier getoond worden 33 | priv-apis = Bevoorrechte API's 34 | cross-domain-xhr = Cross-domain XHR 35 | device-storage-pictures = deviceStorage - afbeeldingen 36 | get-all-contacts = Haal alle contactpersonen op 37 | update-button = Update 38 | log-visibility = App visibiliteit 39 | setup-permissions = De juiste toegangen moeten opgezet worden in de manifest.webapp voor de volgende APIs: 40 | open-video = Open video 41 | -------------------------------------------------------------------------------- /locales/ta/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = பையர்பாக்ஸ் ஓ.எஸ் பாயீலர்பிலேட் ஆப் 2 | web-activities = இணைய நடவடிக்கைள் 3 | pick-image = படத்தை எடு 4 | pick-anything = எதையாவது எடு 5 | take-picture = புகைப்படம் எடு 6 | dial-number = எண்ணை டயல் செய் 7 | dial-sms = குறுஞ்ச்செய்தி அனுப்பு 8 | add-contact = தொடர்பை சேர் 9 | share-url = யூ.ஆர்.ல் ஐ பகிரு 10 | share-image = படத்தை பகிரு 11 | view-url = யூ.ஆர்.ல் ஐ நோக்கு 12 | compose-email = மின்னஞ்சல் எழுது 13 | save-bookmark = புத்தகக்குறியை சேமி 14 | web-apis = இணைய ஏ.பி.ஐ 15 | add-notification = அறிவிப்பை சேர் 16 | orientation-lock = நோக்குநிலையை பூட்டு 17 | vibrate = 2 நொடிகள் அதிர்க 18 | add-alarm = எச்சரிக்கை மணியை சேர் 19 | check-connection = இணைப்பை சோதனை செய் 20 | connection-values = இணைப்பின் மதிப்புகள் இங்கே காட்டப்படும் 21 | check-battery = பேட்டரியை சோதனை செய் 22 | battery-values = பேட்டரி மதிப்பு இங்கே காட்டப்படும் 23 | geolocation = \t\nபூகோள இருப்பிடம் 24 | golocation-values = பூகோள இருப்பிட ரேகைகள் இங்கே காட்டப்படும் 25 | ambient-light = சுற்றுப்புற வெளிச்சம் 26 | ambient-light-values = சுற்றுப்புற வெளிச்சம் இங்கே காட்டப்படும் 27 | proximity = அண்மை பொருள் 28 | proximity-values = அண்மை பொருள் இங்கே காட்டப்படும் 29 | user-proximity = பயனர் தொலைவு 30 | user-proximity-values = பயனர் தொலைவு இங்கே காட்டப்படும் 31 | device-orientation = சாதனத்தின் நோக்குநிலை 32 | device-orientation-values = சாதனத்தின் நோக்குநிலை இங்கே காட்டப்படும் 33 | priv-apis = சலுகை ஏ.பி.ஐ 34 | cross-domain-xhr = குறுக்கு டொமைன் XHR 35 | device-storage-pictures = சாதனசேமிப்பு-படங்கள் 36 | get-all-contacts = அனைத்து தொடர்பையும் எடு 37 | update-button = மேம்படுத்து 38 | log-visibility = பயன்பாட்டின் காணும்தன்மை 39 | setup-permissions = இந்த ஏபீஐக்காண மேனீஃபெஸ்ட். வெப்ஆப்பை இயக்க சரியான அனுமதி தேவைப்படுகிறது 40 | open-video = வீடியோவை திற 41 | -------------------------------------------------------------------------------- /locales/es/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = App base para Firefox OS 2 | web-activities = Actividades Web 3 | pick-image = Escoger imagen 4 | pick-anything = Escoger algo 5 | take-picture = Tomar foto 6 | dial-number = Llamar al número 7 | dial-sms = Enviar SMS 8 | add-contact = Añadir contacto 9 | share-url = Compartir URL 10 | share-image = Compartir imagen 11 | view-url = Ver URL 12 | compose-email = Escribir correo 13 | save-bookmark = Guardar marcador 14 | web-apis = APIs Web 15 | add-notification = Añadir notificación 16 | orientation-lock = Bloqueo orientación 17 | vibrate = Vibrar 2 segundos 18 | add-alarm = Añadir alarma 19 | check-connection = Revisar conexión 20 | connection-values = Los valores de la conexión debieran ser mostrados aquí 21 | check-battery = Revisar batería 22 | battery-values = Los valores de la batería debieran ser mostrados aquí 23 | geolocation = Ubicación 24 | golocation-values = Las coordenadas de la ubicación debieran ser mostradas aquí 25 | ambient-light = Luz ambiental 26 | ambient-light-values = La luz ambiente debiera ser mostrada aquí 27 | proximity = Proximidad 28 | proximity-values = La proximidad debiera ser mostrada aquí 29 | user-proximity = Cercanía usuario 30 | user-proximity-values = La cercanía del usuario debiera ser mostrada aquí 31 | device-orientation = Orientación 32 | device-orientation-values = La orientación del dispositivo debiera ser mostrada aquí 33 | priv-apis = APIs privilegiadas 34 | cross-domain-xhr = XHR inter-dominio 35 | device-storage-pictures = Guardado local 36 | get-all-contacts = Obtener contactos 37 | update-button = Actualizar 38 | log-visibility = Visibilidad App 39 | setup-permissions = Los permisos adecuados deben haber sido otorgados en el archivo manifest.webapp para estas APIs: 40 | open-video = Abrir video 41 | -------------------------------------------------------------------------------- /locales/it_IT/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivity 3 | pick-image = Cerca una immagine 4 | pick-anything = Cerca qualcosa 5 | take-picture = Scatta una foto 6 | dial-number = Telefona 7 | dial-sms = Invia un SMS 8 | add-contact = Aggiungi un contatto 9 | share-url = Condividi una URL 10 | share-image = Condividi una foto 11 | view-url = Vedi URL 12 | compose-email = Scrivi una mail 13 | save-bookmark = Salva il segnalibro 14 | web-apis = WebAPI 15 | add-notification = Aggiungi una notifica 16 | orientation-lock = Blocca rotazione 17 | vibrate = Vibra per 2 sec 18 | add-alarm = Aggiungi un'allarme 19 | check-connection = Verifica connessione 20 | connection-values = Il valore della connessione verrà mostrato qui 21 | check-battery = Verifica batteria 22 | battery-values = Il valore della batteria verrà mostrato qui 23 | geolocation = Geolocazione 24 | golocation-values = Le coordinate della geolocazione verranno mostrate qui 25 | ambient-light = Luce ambiente 26 | ambient-light-values = La luce dell'ambiente verrà mostrata qui 27 | proximity = Prossimità 28 | proximity-values = La prossimità verrà mostrata qui 29 | user-proximity = Prossimità dall'utente 30 | user-proximity-values = La prossimità dall'utente verrà mostrata qui 31 | device-orientation = Orientamento del dispositivo 32 | device-orientation-values = L'orientamento del dispositivo verrà mostrato qui 33 | priv-apis = API Privilegiate 34 | cross-domain-xhr = Cross-domain XHR 35 | device-storage-pictures = deviceStorage - immagini 36 | get-all-contacts = Seleziona tutti i contatti 37 | update-button = Aggiorna 38 | log-visibility = Visibilità APP 39 | setup-permissions = I permessi corretti devono essere settati nel file manifest.webapp per queste API: 40 | open-video = Apri un video 41 | -------------------------------------------------------------------------------- /locales/ru/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivities 3 | pick-image = Выбирать изображение 4 | pick-anything = Выбирать 5 | take-picture = Сделать снимок 6 | dial-number = Наберите номер 7 | dial-sms = Отправить SMS 8 | add-contact = Добавить контакт 9 | share-url = Поделиться URL 10 | share-image = Поделиться изображением 11 | view-url = Посмотреть URL 12 | compose-email = Написать письмо 13 | save-bookmark = Сохранить в закладках 14 | web-apis = WebAPIs 15 | add-notification = Добавить уведомления 16 | orientation-lock = Блокировка ориентации 17 | vibrate = Вибрация 2 сек 18 | add-alarm = Добавить будильник 19 | check-connection = Проверить подключение 20 | connection-values = Значения соединения должны отображаться здесь 21 | check-battery = Проверить аккумулятор 22 | battery-values = Значения аккумулятора будет отображаться здесь 23 | geolocation = Геолокация 24 | golocation-values = Координаты геолокации должны отображаться здесь 25 | ambient-light = Окружающий свет 26 | ambient-light-values = Ambient light should show up here 27 | proximity = Расстояние 28 | proximity-values = Расстояние должна отображаться здесь 29 | user-proximity = Расстояние пользователей 30 | user-proximity-values = Расстояние пользователей должна отображаться здесь 31 | device-orientation = Device orientation 32 | device-orientation-values = Device orientation should show up here 33 | priv-apis = Привилегированные APIs 34 | cross-domain-xhr = Кросс-доменные XHR 35 | device-storage-pictures = deviceStorage - фотографий 36 | get-all-contacts = Получить все контакты 37 | update-button = Обновить 38 | log-visibility = Видимость App 39 | setup-permissions = Correct permissions need to have been set up in the manifest.webapp file for these APIs: 40 | open-video = Open video 41 | -------------------------------------------------------------------------------- /locales/ro/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivities 3 | pick-image = Alege imagine 4 | pick-anything = Alege orice 5 | take-picture = Fă o poză 6 | dial-number = Apelează număr 7 | dial-sms = Trimite SMS 8 | add-contact = Adaugă contact 9 | share-url = Distribuie URL 10 | share-image = Distribuie Imaginea 11 | view-url = Vizualizează URL 12 | compose-email = Compune mail 13 | save-bookmark = Salvează bookmark 14 | web-apis = API-uri web 15 | add-notification = Adaugă notificare 16 | orientation-lock = Blocare orientare 17 | vibrate = Vibrează 2 secunde 18 | add-alarm = Adaugă alarmă 19 | check-connection = Verifică conexiunea 20 | connection-values = Valorile conexiunii ar trebui să apară aici 21 | check-battery = Verifică bateria 22 | battery-values = Valorile bateriei ar trebui să apară aici 23 | geolocation = Geolocație 24 | golocation-values = Coordonatele geolocației ar trebui să apară aici 25 | ambient-light = Lumină ambientală 26 | ambient-light-values = Lumina ambientală ar trebui să apară aici 27 | proximity = Proximitate 28 | proximity-values = Proximitatea ar trebui să apară aici 29 | user-proximity = Proximitatea utilizatorului 30 | user-proximity-values = Proximitatea utilizatorului ar trebui să apară aici 31 | device-orientation = Orientare dispozitiv 32 | device-orientation-values = Orientarea dispozitivului ar trebui să apară aici 33 | priv-apis = API-uri privilegiate 34 | cross-domain-xhr = XHR între domenii 35 | device-storage-pictures = memorieDispozitiv - imagini 36 | get-all-contacts = Obține toate contactele 37 | update-button = Actualizează 38 | log-visibility = Vizibilitate aplicație 39 | setup-permissions = Permisiuni corecte trebuie să fie setate în fișierul manifest.webapp pentru aceste API-uri: 40 | open-video = Deschide video 41 | -------------------------------------------------------------------------------- /locales/fa/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = برنامه ساز ابتدایی سیستم عامل فایرفاکس 2 | web-activities = فعالیت های تحت وب 3 | pick-image = انتخاب تصویر 4 | pick-anything = انتخاب هرچیزی 5 | take-picture = عکس گرفتن 6 | dial-number = گرفتن شماره 7 | dial-sms = ارسال پیامک 8 | add-contact = مخاطب جدید 9 | share-url = به اشتراک گذاری پیوند 10 | share-image = به اشتراک گذاری تصویر 11 | view-url = مشاهده پیوند 12 | compose-email = درج نامه جدید 13 | save-bookmark = ذخیره نشانه 14 | web-apis = پروتکل های برنامه نویسی وب 15 | add-notification = درج اعلان 16 | orientation-lock = قفل جهت 17 | vibrate = لرزاننده ۲ ثانیه 18 | add-alarm = درج هشدار 19 | check-connection = بررسی اتصال شبکه 20 | connection-values = اطلاعات مربوط به اتصال شبکه در بالا نمایش داده می‌شود 21 | check-battery = بررسی باطری 22 | battery-values = اطلاعات مربوط به باطری در بالا نمایش داده می‌شود 23 | geolocation = موقعیت یابی جغرافیایی 24 | golocation-values = اطلاعات مربوط به موقعیت یابی جغرافیایی در بالا نمایش داده می‌شود 25 | ambient-light = نور محیط 26 | ambient-light-values = اطلاعات مربوط به نور محیط در بالا نمایش داده می‌شود 27 | proximity = مجاورت 28 | proximity-values = اطلاعات مربوط به مجاورت در بالا نمایش داده می‌شود 29 | user-proximity = مجاورت کاربر 30 | user-proximity-values = اطلاعات مربوط به مجاورت کاربر در بالا نمایش داده می‌شود 31 | device-orientation = جهت دستگاه 32 | device-orientation-values = اطلاعات مربوط به جهت دستگاه در بالا نمایش داده می‌شود 33 | priv-apis = پروتکل های سطح بندی 34 | cross-domain-xhr = درخواست XHR بین دامنه‌ها 35 | device-storage-pictures = ذخیره سازی دستگاه - تصاویر 36 | get-all-contacts = دریافت تمامی مخاطبین 37 | update-button = بروزرسانی 38 | log-visibility = سطوح نمایش برنامه 39 | setup-permissions = دسترسی صحیح نیاز به راه اندازی مانیفست دارد. فایل برنامه تحت وب برای این پروتکل‌ها: 40 | open-video = باز کردن ویدئو 41 | -------------------------------------------------------------------------------- /locales/pt_BR/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = WebActivities 3 | pick-image = Selecionar imagem 4 | pick-anything = Selecionar a partir de qualquer atividade 5 | take-picture = Tirar foto 6 | dial-number = Discar um número 7 | dial-sms = Enviar SMS 8 | add-contact = Adicionar contato 9 | share-url = Compartilhar URL 10 | share-image = Compartilhar imagem 11 | view-url = Ver URL 12 | compose-email = Escrever email 13 | save-bookmark = Salvar favoritos 14 | web-apis = WebAPIs 15 | add-notification = Adicionar notificação 16 | orientation-lock = Bloquear orientação 17 | vibrate = Vibrar por 2s 18 | add-alarm = Adicionar alarme 19 | check-connection = Verificar conexão 20 | connection-values = Valores da conexão devem aparecer aqui em cima 21 | check-battery = Verificar bateria 22 | battery-values = Valores da bateria devem aparecer aqui em cima 23 | geolocation = Geolocalização 24 | golocation-values = Coordenadas da geolocalização deve aparecer aqui em cima 25 | ambient-light = Luz do ambiente 26 | ambient-light-values = Luz do ambiente deve aparecer aqui em cima 27 | proximity = Proximidade 28 | proximity-values = Proximidade deve aparecer aqui em cima 29 | user-proximity = Proximidade do usuário 30 | user-proximity-values = Proximidade do usuário deve aparecer aqui em cima 31 | device-orientation = Orientação do aparelho 32 | device-orientation-values = Orientação do aparelho deve aparecer aqui em cima 33 | priv-apis = APIs Privilegiadas 34 | cross-domain-xhr = Cross-domain XHR 35 | device-storage-pictures = deviceStorage - pictures 36 | get-all-contacts = Pegar todos os contatos 37 | update-button = Atualizar 38 | log-visibility = Visibilidade do App 39 | setup-permissions = As permissões corretas precisam ser configuradas no arquivo manifest.webapp para as seguintes APIs: 40 | open-video = Abrir video 41 | -------------------------------------------------------------------------------- /locales/hu/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Firefox OS Boilerplate App 2 | web-activities = Webtevékenységek 3 | pick-image = Kép kiválasztása 4 | pick-anything = Bármi kiválasztása 5 | take-picture = Fénykép csinálása 6 | dial-number = Szám beütése 7 | dial-sms = SMS küldése 8 | add-contact = Elérhetőség hozzáadása 9 | share-url = URL megosztása 10 | share-image = Kép megosztása 11 | view-url = URL megtekintése 12 | compose-email = Levél írása 13 | save-bookmark = Könyvjelző elmentése 14 | web-apis = WebAPIk 15 | add-notification = Emlékeztető hozzáadása 16 | orientation-lock = Orientációs zár 17 | vibrate = Két másodperces vibrálás 18 | add-alarm = Riasztás hozzáadása 19 | check-connection = Csatlakozás ellenőrzése 20 | connection-values = A csatlakozási értékeknek itt kellene megjelenniük 21 | check-battery = Akkumulátor ellenőrzése 22 | battery-values = Az akkumulátor értékeknek itt kellene megjelenniük 23 | geolocation = Geolokáció 24 | golocation-values = A geolokációs koordinátáknak itt kellene megjelenniük 25 | ambient-light = Környező fény 26 | ambient-light-values = A környező fénynek itt kellene megjelennie 27 | proximity = Proximitás 28 | proximity-values = A proximitásnak itt kellene megjelennie 29 | user-proximity = Felhasználói proximitás 30 | user-proximity-values = Itt kellene megjelennie a felhasználói proximitásnak 31 | device-orientation = Eszköz orientáció 32 | device-orientation-values = Itt kellene megjelennie az eszköz orientációnak 33 | priv-apis = Kiváltságos APIk 34 | cross-domain-xhr = Domének közti XHR 35 | device-storage-pictures = eszközreMentés - képek 36 | get-all-contacts = Összes névjegy megszerzése 37 | update-button = Frissítés 38 | log-visibility = App láthatóság 39 | setup-permissions = A megfelelő engedélyeknek a manifest.webapp fájlban kellett volna beállítani ezekhez az API-khoz: 40 | open-video = Videó megnyitása 41 | -------------------------------------------------------------------------------- /locales/cs/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Aplikace Firefox OS Boilerplate 2 | web-activities = Rozhraní WebActivities 3 | pick-image = Výběr obrázku 4 | pick-anything = Libovolný výběr 5 | take-picture = Pořízení fotografie 6 | dial-number = Vytočení čísla 7 | dial-sms = Odeslání zprávy SMS 8 | add-contact = Přidání kontaktu 9 | share-url = Sdílení adresy URL 10 | share-image = Sdílení obrázku 11 | view-url = Zobrazení adresy URL 12 | compose-email = Vytvoření e-mailu 13 | save-bookmark = Uložení záložky 14 | web-apis = Rozhraní WebAPI 15 | add-notification = Přidání oznámení 16 | orientation-lock = Zámek orientace 17 | vibrate = Vibrování po dobu 2 sekundy 18 | add-alarm = Přidání budíku 19 | check-connection = Kontrola připojení 20 | connection-values = Zde by se měly zobrazovat hodnoty připojení. 21 | check-battery = Kontrola baterie 22 | battery-values = Zde by se měly zobrazovat hodnoty baterie. 23 | geolocation = Geografické umístění 24 | golocation-values = Zde by se měly zobrazovat souřadnice geografického umístění. 25 | ambient-light = Okolní osvětlení 26 | ambient-light-values = Zde by se měly zobrazovat informace o okolním osvětlení. 27 | proximity = Přiblížení 28 | proximity-values = Zde by se měly zobrazovat informace o přiblížení. 29 | user-proximity = Přiblížení uživatele 30 | user-proximity-values = Zde by se měly zobrazovat informace o přiblížení uživatele. 31 | device-orientation = Orientace zařízení 32 | device-orientation-values = Zde by se měly zobrazovat informace o orientaci zařízení. 33 | priv-apis = Vybraná rozhraní API 34 | cross-domain-xhr = Požadavek XHR napříč doménami 35 | device-storage-pictures = Rozhraní deviceStorage – obrázky 36 | get-all-contacts = Získání všech kontaktů 37 | update-button = Aktualizace 38 | log-visibility = Viditelnost aplikace 39 | setup-permissions = V případě následujících rozhraní API je nutné nastavit správná oprávnění v souboru manifest.webapp: 40 | open-video = Otevření videa 41 | -------------------------------------------------------------------------------- /locales/tl/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = App na Firefox OS Boilerplate 2 | web-activities = Mga Aktibidad sa Web 3 | pick-image = Pumili ng imahe 4 | pick-anything = Pumili ng kahit ano 5 | take-picture = Kumuha ng larawan 6 | dial-number = I-dial ang numero 7 | dial-sms = Magpadala ng SMS 8 | add-contact = Magdagdag ng ugnayan 9 | share-url = Ibahagi ang URL 10 | share-image = Ibahagi ang Imahe 11 | view-url = Tignan ang URL 12 | compose-email = Gumawa ng mail 13 | save-bookmark = I-save ang bookmark 14 | web-apis = Mga WebAPI 15 | add-notification = Magdagdag ng notipikasyon 16 | orientation-lock = I-lock ang oryentasyon 17 | vibrate = Mag-vibrate ng 2 seg 18 | add-alarm = Magdagdag ng alarma 19 | check-connection = Suriin ang koneksyon 20 | connection-values = Ang mga halaga ng koneksyon ay dapat makikita dito 21 | check-battery = Suriin ang baterya 22 | battery-values = Ang mga halaga ng baterya ay dapat makikita dito 23 | geolocation = Heograpikal na lokasyon 24 | golocation-values = Ang mga coord ng Heograpikal na lokasyon ay dapat makikita dito 25 | ambient-light = Nakapaligid na ilaw 26 | ambient-light-values = Ang nakapaligid na ilaw ay dapat makikita dito 27 | proximity = Kalapitan 28 | proximity-values = Ang kalapitan ay dapat makikita dito 29 | user-proximity = Gamitin ang kalapitan 30 | user-proximity-values = Ang kalapitan ng gumagamit ay dapat makikita dito 31 | device-orientation = Oryentasyon ng device. 32 | device-orientation-values = Ang oryentasyon ng device ay dapat makikita dito 33 | priv-apis = Mga may pribilehiyong app 34 | cross-domain-xhr = Tumatawid sa domain na XHR 35 | device-storage-pictures = Imbakan ng device - mga larawan 36 | get-all-contacts = Kunin ang lahat ng mga kaugnayan 37 | update-button = I-update 38 | log-visibility = Pagkakakita sa app 39 | setup-permissions = Ang tamang mga pahintulot ay kailangang naka-set up sa manipesto. mga webapp na file para sa mga API na ito: 40 | open-video = Buksan ang video 41 | -------------------------------------------------------------------------------- /locales/fr/app.properties: -------------------------------------------------------------------------------- 1 | app-heading = Modèle d’application pour Firefox OS 2 | web-activities = WebActivities 3 | pick-image = Choisir une image 4 | pick-anything = Choisir quoi que ce soit 5 | take-picture = Prendre une photo 6 | dial-number = Composer un numéro 7 | dial-sms = Envoyer un SMS 8 | add-contact = Ajouter un contact 9 | share-url = Partager l’adresse URL 10 | share-image = Partager l’image 11 | view-url = Voir l’adresse URL 12 | compose-email = Composer un courriel 13 | save-bookmark = Enregistrer un marque-page 14 | web-apis = WebAPIs 15 | add-notification = Ajouter une notification 16 | orientation-lock = Verrouiller l’orientation 17 | vibrate = Vibrer 2 secondes 18 | add-alarm = Ajouter une alarme 19 | check-connection = Vérifier la connexion 20 | connection-values = Les valeurs pour la connexion devraient s’afficher ici 21 | check-battery = Vérifier la batterie 22 | battery-values = Les valeurs pour la batterie devraient s’afficher ici 23 | geolocation = Géolocalisation 24 | golocation-values = Les coordonnées de géolocalisation devraient s’afficher ici 25 | ambient-light = Lumière ambiante 26 | ambient-light-values = La lumière ambiante devrait s’afficher ici 27 | proximity = Proximité 28 | proximity-values = La proximité devrait s’afficher ici 29 | user-proximity = Proximité de l’utilisateur 30 | user-proximity-values = La proximité de l’utilisateur devrait s’afficher ici 31 | device-orientation = Orientation de l’appareil 32 | device-orientation-values = L’orientation de l’appareil devrait s’afficher ici 33 | priv-apis = APIs privilégiées 34 | cross-domain-xhr = XHR inter-domaine 35 | device-storage-pictures = deviceStorage - pictures 36 | get-all-contacts = Obtenir tous les contacts 37 | update-button = Mise à jour 38 | log-visibility = Visibilité de l’application 39 | setup-permissions = Les autorisations appropriées doivent avoir été mises en place dans le fichier manifest.webapp pour ces APIs : 40 | open-video = Ouvrir une vidéo 41 | -------------------------------------------------------------------------------- /css/base.css: -------------------------------------------------------------------------------- 1 | * { font-family: 'FiraSans'; } 2 | 3 | @font-face { 4 | font-family: 'FiraSans'; 5 | src: url('../fonts/FiraSans-Regular.woff') format('woff'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | @font-face { 10 | font-family: 'FiraSans'; 11 | src: url('../fonts/FiraSans-Light.woff') format('woff'); 12 | font-weight: 300; 13 | font-style: normal; 14 | } 15 | @font-face { 16 | font-family: 'FiraSans'; 17 | src: url('../fonts/FiraSans-Medium.woff') format('woff'); 18 | font-weight: 500; 19 | font-style: normal; 20 | } 21 | @font-face { 22 | font-family: 'FiraSans'; 23 | src: url('../fonts/FiraSans-Bold.woff') format('woff'); 24 | font-weight: bold; 25 | font-style: normal; 26 | } 27 | 28 | html, body { 29 | height: 100%; 30 | padding: 0; 31 | margin: 0; 32 | font-size:10px; 33 | background: #fff; 34 | } 35 | 36 | body { 37 | position: relative; 38 | } 39 | 40 | ul { 41 | margin: 0; 42 | padding: 0; 43 | list-style: none; 44 | } 45 | 46 | h2 { 47 | font-size: 16px; 48 | } 49 | 50 | h3 { 51 | font-size: 14px; 52 | } 53 | 54 | h4 { 55 | font-size: 12px; 56 | } 57 | 58 | #install { 59 | display: none; 60 | } 61 | 62 | #install.show-install { 63 | display: inline-block; 64 | } 65 | 66 | header.show-install h1 { 67 | display: inline-block; 68 | width: 55%; 69 | white-space: nowrap; 70 | overflow: hidden; 71 | text-overflow: ellipsis; 72 | } 73 | 74 | #online-status { 75 | position: absolute; 76 | left: 10px; 77 | top: 2rem; 78 | width: 10px; 79 | height: 10px; 80 | color: #fff; 81 | background: #008000; 82 | border-radius: 5px; 83 | } 84 | 85 | #online-status.offline { 86 | background: #ff0000; 87 | } 88 | 89 | #main { 90 | padding: 1rem 1rem 6rem 1rem; 91 | } 92 | 93 | #main h2 { 94 | margin: 0 0 1rem; 95 | } 96 | 97 | #main img { 98 | max-width: 100%; 99 | } 100 | 101 | #log-visibility-display, 102 | #image-presenter, 103 | #connection-display, 104 | #geolocation-display, 105 | #battery-display, 106 | #ambient-light-display, 107 | #proximity-display, 108 | #user-proximity-display, 109 | #device-orientation-display { 110 | display: none; 111 | margin-bottom: 10px; 112 | } 113 | 114 | #cross-domain-xhr-display, 115 | #device-storage-pictures-display, 116 | #get-all-contacts-display { 117 | display: none; 118 | margin-bottom: 10px; 119 | } 120 | 121 | #main button { 122 | display: inline-block; 123 | width: 49%; 124 | vertical-align: top; 125 | margin: 0 auto 2rem; 126 | } 127 | 128 | #image-to-share { 129 | display: none; 130 | } 131 | 132 | footer { 133 | position: fixed; 134 | width: 100%; 135 | height: 5rem; 136 | bottom: 0; 137 | } 138 | 139 | [role="toolbar"] li button.update { 140 | background-image: url("../images/toolbars/icons/update.png"); 141 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firefox OS Boilerplate App 2 | 3 | This is a demo app for Firefox OS, loosely based on [fxosstub](https://github.com/Jaxo/fxosstub), meant to act as a simple boilerplate for getting started with apps for Firefox OS. 4 | 5 | It will give you a button to install it in Firefox OS - on a device, in the [App Manager](https://developer.mozilla.org/en-US/Firefox_OS/Using_the_App_Manager) and in certain [Nightly versions of Firefox](http://nightly.mozilla.org/). 6 | 7 | It is a showcase of: 8 | 9 | * [Web Activities](https://hacks.mozilla.org/2013/01/introducing-web-activities/) 10 | * [WebAPI usage](https://hacks.mozilla.org/2013/02/using-webapis-to-make-the-web-layer-more-capable/) 11 | * Adding offline support and more in Firefox OS! 12 | 13 | To add your own icon, I recommend using the [Firefox OS app icons style guide](http://www.mozilla.org/en-US/styleguide/products/firefox-os/icons/). 14 | 15 | The Firefox OS Boilerplate App apply the Gaia style of Firefox OS, but note that there is no obligation to add the same look, and feel to your application: Firefox OS applications are web applications, so no need to follow a UI guideline. 16 | 17 | For up-to-date information on building Open Web Apps, visit the [App Center on MDN](https://developer.mozilla.org/en-US/Apps). 18 | 19 | 20 | ## Preview 21 | 22 | To test/install this app, the recommended way is to download it or clone/fork this repository and run it in the [App Manager](https://developer.mozilla.org/en-US/Firefox_OS/Using_the_App_Manager) (`Tools > Web Developer > App Manager` or go to the URL `about:app-manager` in Firefox) by clicking Add Packaged App and browse to where your local repository is. 23 | 24 | Alternatively, you can test-run it from GitHub by installing it in the App Manager Dashboard - click Add Hosted App - by providing this URL: 25 | 26 | * [http://robnyman.github.io/Firefox-OS-Boilerplate-App/manifest-hosted.webapp](http://robnyman.github.io/Firefox-OS-Boilerplate-App/manifest-hosted.webapp) 27 | 28 | ## For Packaged Apps 29 | 30 | You can test packaged apps in version 2 and higher of the App Manager, by using the Add Directory button. If you want to access privileged APIs - such as deviceStorage, cross-domain XMLHttpRequest etc - you need to set type and permissions in the manifest file. E.g. 31 | 32 | { 33 | "version": "1", 34 | "name": "Firefox OS Boilerplate App", 35 | "type" : "privileged" 36 | … 37 | 38 | And: 39 | 40 | "permissions": { 41 | "device-storage:pictures": { 42 | "access": "readcreate" 43 | }, 44 | "systemXHR":{}, 45 | "contacts": { 46 | "description" : "Reading out contacts", 47 | "access": "readcreate" 48 | } 49 | } 50 | 51 | 52 | All options to test packaged apps are outlined in the [How to install packaged apps in Firefox OS – options and tools](https://hacks.mozilla.org/2013/03/how-to-install-packaged-apps-in-firefox-os-options-and-tools/) article 53 | 54 | ## Contribute 55 | 56 | ### Localization (L10n) 57 | 58 | #### Get a Transifex account 59 | 60 | Transifex is the platform that we use to manage the localization workflow. 61 | 62 | [Sign up](https://www.transifex.com/signup/) for a Transifex account and visit the [Firefox OS Boilerplate project](https://www.transifex.com/projects/p/firefox-os-boilerplate/). 63 | 64 | ![](https://support.cdn.mozilla.net/media/uploads/gallery/images/2013-09-27-08-46-21-087973.png) 65 | 66 | #### Find your language 67 | 68 | Click on the language that you want to localize and click the ![](https://support.cdn.mozilla.net/media/uploads/gallery/images/2013-09-27-08-57-01-bc2228.png) button 69 | 70 | If your language is not listed, click the ![](https://support.cdn.mozilla.net/media/uploads/gallery/images/2013-09-27-08-58-27-05ceb1.png) button. 71 | 72 | #### Start translating! 73 | 74 | Select the project you want to translate and hit the ![](https://support.cdn.mozilla.net/media/uploads/gallery/images/2013-09-27-09-13-50-99ae4f.png) button. 75 | 76 | When your translation is complete, we'll pull it into this repository. -------------------------------------------------------------------------------- /manifest.webapp: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "Firefox OS Boilerplate App", 4 | "launch_path": "/index.html", 5 | "description": "Boilerplate Firefox OS app with example use cases to get started", 6 | "icons": { 7 | "16": "/images/logo16.png", 8 | "32": "/images/logo32.png", 9 | "48": "/images/logo48.png", 10 | "60": "/images/logo60.png", 11 | "64": "/images/logo64.png", 12 | "90": "/images/logo90.png", 13 | "120": "/images/logo120.png", 14 | "128": "/images/logo128.png" 15 | }, 16 | "developer": { 17 | "name": "Robert Nyman", 18 | "url": "http://robertnyman.com" 19 | }, 20 | "installs_allowed_from": [ 21 | "*" 22 | ], 23 | "default_locale": "en", 24 | "permissions": { 25 | "desktop-notification": { 26 | "description": "To show notifications" 27 | }, 28 | "geolocation": { 29 | "description": "Marking out user location" 30 | }, 31 | "alarms": { 32 | "description": "Scheduling alarms" 33 | } 34 | }, 35 | "locales": { 36 | "ar": { 37 | "name": "التطبيق المساعد لبدء التطوير لـFirefox OS", 38 | "description": "تطبيق يُساعدك على بدء التطوير لنظام Firefox مُرفق بأمثلة عن حالات الاستخدام" 39 | }, 40 | "bn-IN": { 41 | "name": "ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ", 42 | "description": "শুরু করার জন্য ব্যবহারিক উদাহরণ সহ ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ" 43 | }, 44 | "cs": { 45 | "name": "Aplikace Firefox OS Boilerplate", 46 | "description": "Aplikace Boilerplate Firefox OS s ukázkovými příklady použití, které vám umožní začít" 47 | }, 48 | "de": { 49 | "name": "Firefox OS Boilerplate App", 50 | "description": "Boilerplate Firefox OS App mit Beispiel Anwendungsfälle, um loszulegen" 51 | }, 52 | "el": { 53 | "name": "Firefox OS Boilerplate Εφαρμογή", 54 | "description": "Boilerplate Firefox OS εφαρμογή με παραδείγματα χρήσης για να ξεκινήσετε" 55 | }, 56 | "en": { 57 | "name": "Firefox OS Boilerplate App", 58 | "description": "Boilerplate Firefox OS app with example use cases to get started" 59 | }, 60 | "en-US": { 61 | "name": "Firefox OS Boilerplate App", 62 | "description": "Boilerplate Firefox OS app with example use cases to get started" 63 | }, 64 | "es": { 65 | "name": "App base para Firefox OS", 66 | "description": "App base para Firefox OS con ejemplos de usos para empezar" 67 | }, 68 | "fa": { 69 | "name": "برنامه ساز ابتدایی سیستم عامل فایرفاکس", 70 | "description": "برنامه ساز ابتدایی سیستم عامل فایرفاکس با مثال کاربردی برای شروع به کار" 71 | }, 72 | "fr": { 73 | "name": "Modèle d’application pour Firefox OS", 74 | "description": "Modèle d’application pour Firefox OS avec des exemples de cas d’utilisation pour bien commencer" 75 | }, 76 | "he": { 77 | "name": "אפליקציית Firefox OS Boilerplate", 78 | "description": "אפליקציית Firefox OS Boilerplate עם דוגמאות שימוש להתחלה" 79 | }, 80 | "hi": { 81 | "name": "फायर फॉक्स OS BoilerPlate App" 82 | }, 83 | "hu": { 84 | "name": "Firefox OS Boilerplate App", 85 | "description": "Boilerplate Firefox OS app használati mintaesetekkel a kezdés megkönnyítéséért" 86 | }, 87 | "id": { 88 | "name": "Firefox OS Boilerplate Aplikasi", 89 | "description": "Aplikasi boilerplate Firefox OS dengan contoh kasus penggunaan untuk memulai" 90 | }, 91 | "it-IT": { 92 | "name": "Firefox OS Boilerplate App", 93 | "description": "Boilerplate per FirefoxOS con esempi e casi d'uso per iniziare lo sviluppo" 94 | }, 95 | "ja": { 96 | "name": "Firefox OSボイラプレートアプリ", 97 | "description": "いくつかの用例を含めた、Firefox OS用アプリの入門用見本" 98 | }, 99 | "nl": { 100 | "name": "Firefox OS Boilerplate App", 101 | "description": "Boilerplate Firefox OS app met voorbeeld use cases om te beginnen" 102 | }, 103 | "pt_BR": { 104 | "name": "Firefox OS Boilerplate App", 105 | "description": "Boilerplate Firefox OS app com exemplos de uso para começar" 106 | }, 107 | "ro": { 108 | "name": "Firefox OS Boilerplate App", 109 | "description": "Boilerplate Firefox OS app cu exemple de utilizare pentru început" 110 | }, 111 | "sk-SK": { 112 | "name": "Firefox OS Boilerplate Aplikácia", 113 | "description": "Boilerplate Firefox OS aplikácia s príkladmi použitia pre začiatok" 114 | }, 115 | "sv": { 116 | "name": "Firefox OS Boilerplate-appen", 117 | "description": "Boilerplate Firefox OS-appen med exempel använder cases för att startas" 118 | }, 119 | "ta": { 120 | "name": "பையர்பாக்ஸ் ஓ.எஸ் பாயீலர்பிலேட் ஆப்", 121 | "description": "பாயீலர்பிலேட் பையர்பாக்ஸ் ஓ.எஸ் ஆப் உடன் யூஸ்கேஸ்சின் தொடக்கத்திற்காண எடுத்து காட்டு" 122 | }, 123 | "tl": { 124 | "name": "App ng Firefox OS Boilerplate", 125 | "description": "Boilerplate Firefox OS app na may halimbawa ay gumagamit ng mga kaso upang makapagsimula" 126 | }, 127 | "tr": { 128 | "name": "Firefox OS Boilerplate Uygulaması", 129 | "description": "Başlamak için örnek kullanım durumları ile Boilerplate Firefox OS uygulaması" 130 | }, 131 | "zh": { 132 | "name": "Firefox OS 模板程序", 133 | "description": "从Firefox OS模板应用内置的用户示例开始" 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /manifest-hosted.webapp: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "Firefox OS Boilerplate App", 4 | "launch_path": "/Firefox-OS-Boilerplate-App/index.html", 5 | "description": "Boilerplate Firefox OS app with example use cases to get started", 6 | "icons": { 7 | "16": "/Firefox-OS-Boilerplate-App/images/logo16.png", 8 | "32": "/Firefox-OS-Boilerplate-App/images/logo32.png", 9 | "48": "/Firefox-OS-Boilerplate-App/images/logo48.png", 10 | "60": "/Firefox-OS-Boilerplate-App/images/logo60.png", 11 | "64": "/Firefox-OS-Boilerplate-App/images/logo64.png", 12 | "90": "/Firefox-OS-Boilerplate-App/images/logo90.png", 13 | "120": "/Firefox-OS-Boilerplate-App/images/logo120.png", 14 | "128": "/Firefox-OS-Boilerplate-App/images/logo128.png" 15 | }, 16 | "developer": { 17 | "name": "Robert Nyman", 18 | "url": "http://robertnyman.com" 19 | }, 20 | "installs_allowed_from": [ 21 | "*" 22 | ], 23 | "default_locale": "en", 24 | "permissions": { 25 | "desktop-notification": { 26 | "description": "To show notifications" 27 | }, 28 | "geolocation": { 29 | "description": "Marking out user location" 30 | }, 31 | "alarms": { 32 | "description": "Scheduling alarms" 33 | } 34 | }, 35 | "locales": { 36 | "ar": { 37 | "name": "التطبيق المساعد لبدء التطوير لـFirefox OS", 38 | "description": "تطبيق يُساعدك على بدء التطوير لنظام Firefox مُرفق بأمثلة عن حالات الاستخدام" 39 | }, 40 | "bn-IN": { 41 | "name": "ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ", 42 | "description": "শুরু করার জন্য ব্যবহারিক উদাহরণ সহ ফায়ারফক্স ওএস বয়েলারপ্লেট অ্যাপ" 43 | }, 44 | "cs": { 45 | "name": "Aplikace Firefox OS Boilerplate", 46 | "description": "Aplikace Boilerplate Firefox OS s ukázkovými příklady použití, které vám umožní začít" 47 | }, 48 | "de": { 49 | "name": "Firefox OS Boilerplate App", 50 | "description": "Boilerplate Firefox OS App mit Beispiel Anwendungsfälle, um loszulegen" 51 | }, 52 | "el": { 53 | "name": "Firefox OS Boilerplate Εφαρμογή", 54 | "description": "Boilerplate Firefox OS εφαρμογή με παραδείγματα χρήσης για να ξεκινήσετε" 55 | }, 56 | "en": { 57 | "name": "Firefox OS Boilerplate App", 58 | "description": "Boilerplate Firefox OS app with example use cases to get started" 59 | }, 60 | "en-US": { 61 | "name": "Firefox OS Boilerplate App", 62 | "description": "Boilerplate Firefox OS app with example use cases to get started" 63 | }, 64 | "es": { 65 | "name": "App base para Firefox OS", 66 | "description": "App base para Firefox OS con ejemplos de usos para empezar" 67 | }, 68 | "fa": { 69 | "name": "برنامه ساز ابتدایی سیستم عامل فایرفاکس", 70 | "description": "برنامه ساز ابتدایی سیستم عامل فایرفاکس با مثال کاربردی برای شروع به کار" 71 | }, 72 | "fr": { 73 | "name": "Modèle d’application pour Firefox OS", 74 | "description": "Modèle d’application pour Firefox OS avec des exemples de cas d’utilisation pour bien commencer" 75 | }, 76 | "he": { 77 | "name": "אפליקציית Firefox OS Boilerplate", 78 | "description": "אפליקציית Firefox OS Boilerplate עם דוגמאות שימוש להתחלה" 79 | }, 80 | "hi": { 81 | "name": "फायर फॉक्स OS BoilerPlate App" 82 | }, 83 | "hu": { 84 | "name": "Firefox OS Boilerplate App", 85 | "description": "Boilerplate Firefox OS app használati mintaesetekkel a kezdés megkönnyítéséért" 86 | }, 87 | "id": { 88 | "name": "Firefox OS Boilerplate Aplikasi", 89 | "description": "Aplikasi boilerplate Firefox OS dengan contoh kasus penggunaan untuk memulai" 90 | }, 91 | "it-IT": { 92 | "name": "Firefox OS Boilerplate App", 93 | "description": "Boilerplate per FirefoxOS con esempi e casi d'uso per iniziare lo sviluppo" 94 | }, 95 | "ja": { 96 | "name": "Firefox OSボイラプレートアプリ", 97 | "description": "いくつかの用例を含めた、Firefox OS用アプリの入門用見本" 98 | }, 99 | "nl": { 100 | "name": "Firefox OS Boilerplate App", 101 | "description": "Boilerplate Firefox OS app met voorbeeld use cases om te beginnen" 102 | }, 103 | "pt_BR": { 104 | "name": "Firefox OS Boilerplate App", 105 | "description": "Boilerplate Firefox OS app com exemplos de uso para começar" 106 | }, 107 | "ro": { 108 | "name": "Firefox OS Boilerplate App", 109 | "description": "Boilerplate Firefox OS app cu exemple de utilizare pentru început" 110 | }, 111 | "sk-SK": { 112 | "name": "Firefox OS Boilerplate Aplikácia", 113 | "description": "Boilerplate Firefox OS aplikácia s príkladmi použitia pre začiatok" 114 | }, 115 | "sv": { 116 | "name": "Firefox OS Boilerplate-appen", 117 | "description": "Boilerplate Firefox OS-appen med exempel använder cases för att startas" 118 | }, 119 | "ta": { 120 | "name": "பையர்பாக்ஸ் ஓ.எஸ் பாயீலர்பிலேட் ஆப்", 121 | "description": "பாயீலர்பிலேட் பையர்பாக்ஸ் ஓ.எஸ் ஆப் உடன் யூஸ்கேஸ்சின் தொடக்கத்திற்காண எடுத்து காட்டு" 122 | }, 123 | "tl": { 124 | "name": "App ng Firefox OS Boilerplate", 125 | "description": "Boilerplate Firefox OS app na may halimbawa ay gumagamit ng mga kaso upang makapagsimula" 126 | }, 127 | "tr": { 128 | "name": "Firefox OS Boilerplate Uygulaması", 129 | "description": "Başlamak için örnek kullanım durumları ile Boilerplate Firefox OS uygulaması" 130 | }, 131 | "zh": { 132 | "name": "Firefox OS 模板程序", 133 | "description": "从Firefox OS模板应用内置的用户示例开始" 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Firefox OS Boilerplate App 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 | 34 |
35 | 36 | 37 | 38 |

39 | Firefox OS Boilerplate App 40 |

41 |
42 |
43 | 44 | 45 |
46 | 47 |

Press the + button in the top right corner to install this app.

48 | 49 |

WebActivities

50 | 51 | 52 |
53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |

WebAPIs

81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
Connection values should show up here
90 | 91 | 92 |
Battery values should show up here
93 | 94 | 95 |
Geolocation coords should show up here
96 | 97 | 98 |
Ambient light should show up here
99 | 100 | 101 |
Proximity should show up here
102 | 103 | 104 |
User proximity should show up here
105 | 106 | 107 |
Device orientation should show up here
108 | 109 | 110 | 111 | 112 |
113 | 114 | 115 |
116 | 117 | 118 |

Privileged APIs

119 |

README.md

120 | 121 | 122 |
123 | 124 | 125 |
126 | 127 | 128 |
129 | 130 | 131 |
132 |
133 | 134 |
135 |
136 |
    137 |
  • 138 |
139 |
140 |
141 | 142 | 143 | 144 | 145 | 146 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /css/buttons.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- 2 | * Buttons 3 | * ---------------------------------- */ 4 | 5 | .button::-moz-focus-inner, 6 | a[role="button"]::-moz-focus-inner, 7 | button::-moz-focus-inner { 8 | border: none; 9 | outline: none; 10 | margin-top: -0.2rem; /* To fix line-height bug (697451) */ 11 | } 12 | 13 | button, 14 | a[role="button"], 15 | .button { 16 | width: 100%; 17 | height: 3.8rem; 18 | margin: 0 0 1rem; 19 | padding: 0 1.5rem; 20 | -moz-box-sizing: border-box; 21 | display: inline-block; 22 | vertical-align: middle; 23 | text-overflow: ellipsis; 24 | white-space: nowrap; 25 | overflow: hidden; 26 | background: #fafafa url(../images/buttons/ui/default.png) repeat-x left bottom / auto 100%; 27 | border: 0.1rem solid #a6a6a6; 28 | border-radius: 0.2rem; 29 | font-weight: 500; 30 | font-size: 1.6rem; 31 | line-height: 3.8rem; 32 | color: #333; 33 | text-align: center; 34 | text-shadow: 0.1rem 0.1rem 0 rgba(255,255,255,0.3); 35 | text-decoration: none; 36 | outline: none; 37 | } 38 | 39 | /* Press (default & recommend) */ 40 | button:active, 41 | a[role="button"]:active, 42 | button.recommend:active, 43 | a.recommend[role="button"]:active { 44 | border-color: #008aaa; 45 | background: #008aaa; 46 | background-size: auto 100%; 47 | color: #333; 48 | } 49 | 50 | /* Recommend */ 51 | button.recommend, 52 | a[role="button"].recommend { 53 | background-image: url(../images/buttons/ui/recommend.png); 54 | background-color: #00caf2; 55 | border-color: #008eab; 56 | } 57 | 58 | /* Danger */ 59 | button.danger, 60 | a.danger[role="button"], 61 | span.danger[role="button"] { 62 | background-image: url(../images/buttons/ui/danger.png); 63 | background-color: #b70404; 64 | color: #fff; 65 | text-shadow: none; 66 | border-color: #820000; 67 | } 68 | 69 | /* Danger Press */ 70 | button.danger:active, 71 | a[role="button"].danger:active, 72 | .button.danger:active { 73 | background-image: url(../images/buttons/ui/danger-press.png); 74 | background-color: #890707; 75 | } 76 | 77 | /* Disabled (default & recommend) */ 78 | button[disabled], 79 | a[role="button"][aria-disabled="true"], 80 | .button[aria-disabled="true"], 81 | button[disabled].recommend, 82 | a[role="button"][aria-disabled="true"].recommend, 83 | .button[aria-disabled="true"].recommend { 84 | background: #e7e7e7; 85 | border-color: #c7c7c7; 86 | color: #c7c7c7; 87 | text-shadow: none; 88 | pointer-events: none; 89 | } 90 | 91 | /* Danger disabled */ 92 | button[disabled].danger, 93 | .button[aria-disabled="true"].danger, 94 | a[role="button"][aria-disabled="true"].danger { 95 | background: #c68484; 96 | border-color: #a56464; 97 | color: #a56464; 98 | text-shadow: none; 99 | pointer-events: none; 100 | } 101 | 102 | /* Disabled with dark background */ 103 | .dark button[disabled], 104 | .dark .button[aria-disabled="true"], 105 | .dark a[role="button"][aria-disabled="true"] { 106 | background: #5f5f5f; 107 | color: #4d4d4d; 108 | border-color: #4d4d4d; 109 | text-shadow: none; 110 | pointer-events: none; 111 | } 112 | 113 | 114 | /* ---------------------------------- 115 | * Buttons inside lists 116 | * ---------------------------------- */ 117 | 118 | li button, 119 | li a[role="button"], 120 | li .button { 121 | position: relative; 122 | background: #e7e7e7; 123 | text-align: left; 124 | /* For hacking box-shadows we need overflow:visible; so we lose text-overflows...*/ 125 | white-space: normal; 126 | overflow: visible; 127 | } 128 | 129 | /* Hacking box-shadow */ 130 | li button:after, 131 | li a[role="button"]:after, 132 | li .button:after { 133 | content: ""; 134 | position: absolute; 135 | top: 100%; 136 | left: 0; 137 | right: 0; 138 | height: 0.2rem; 139 | background: url(../images/buttons/ui/shadow.png) repeat-x left bottom / auto 100%; 140 | } 141 | 142 | /* Press */ 143 | li a[role="button"]:active:after, 144 | li .button:active:after, 145 | li button:active:after { 146 | opacity: 0; 147 | } 148 | 149 | /* Disabled */ 150 | li button[disabled]:after, 151 | li a[role="button"][aria-disabled="true"]:after, 152 | li .button[aria-disabled="true"]:after { 153 | background: none; 154 | } 155 | 156 | /* Icons */ 157 | li button.icon, 158 | li a[role="button"].icon, 159 | li .button.icon { 160 | padding-right: 3rem; 161 | } 162 | 163 | li button.icon:before, 164 | li a[role="button"].icon:before, 165 | li .button.icon:before { 166 | content: ""; 167 | width: 3rem; 168 | height: 3rem; 169 | position: absolute; 170 | top: 50%; 171 | right: 0; 172 | margin-top: -1.5rem; 173 | background: transparent no-repeat center center / 100% auto; 174 | pointer-events: none; 175 | } 176 | 177 | li button.icon-view:before, 178 | li a[role="button"].icon-view:before { 179 | background: url(../images/buttons/icons/view.png) no-repeat 1.6rem 0 / 1rem 9rem; 180 | } 181 | 182 | li button.icon-view:active:before, 183 | li a[role="button"].icon-view:active:before { 184 | background-position: 1.6rem -3rem; 185 | } 186 | 187 | li button.icon-view:disabled:before, 188 | li a[role="button"][aria-disabled="true"].icon-view:before { 189 | background-position: 1.6rem -6rem; 190 | } 191 | 192 | li button.icon-dialog, 193 | li a[role="button"].icon-dialog, 194 | li .button.icon-dialog { 195 | font-size: 1.7rem; 196 | } 197 | 198 | li button.icon-dialog:before, 199 | li a[role="button"].icon-dialog:before, 200 | li .button.icon-dialog:before { 201 | background: url(../images/buttons/icons/dialog.png) no-repeat 1.6rem 0 / 1rem 9rem; 202 | top: 100%; 203 | margin-top: -2.4rem; 204 | } 205 | 206 | li button.icon-dialog:active:before, 207 | li a[role="button"].icon-dialog:active:before, 208 | li .button.icon-dialog:active:before { 209 | background-position: 1.6rem -3rem; 210 | } 211 | 212 | li button.icon-dialog:disabled:before, 213 | li a[role="button"][aria-disabled="true"].icon-dialog:before, 214 | li .button[aria-disabled="true"].icon-dialog:before { 215 | background-position: 1.6rem -6rem; 216 | } 217 | 218 | 219 | /* ---------------------------------- 220 | * Buttons inside lists, compact mode 221 | * ---------------------------------- */ 222 | 223 | ul.compact, 224 | ol.compact { 225 | padding: 0 1.5rem 1.5rem 1.5rem; 226 | } 227 | 228 | ul.compact li, 229 | ol.compact li { 230 | padding: 1.5rem 0 0.5rem 0; 231 | border-bottom: solid #bdbdbd 0.1rem; 232 | display: block; 233 | overflow: hidden; 234 | } 235 | 236 | ul.compact li label, 237 | ol.compact li label { 238 | padding: 0 1.5rem 1rem 1.5rem; 239 | color: #333; 240 | font-weight: normal; 241 | font-size: 1.6rem; 242 | line-height: 1.8rem; 243 | display: block; 244 | text-overflow: ellipsis; 245 | white-space: nowrap; 246 | overflow: hidden; 247 | } 248 | 249 | /* Inputs inside of .button */ 250 | .button input, 251 | body[role="application"] .button input { 252 | border: 0; 253 | background: none; 254 | } 255 | 256 | /* Hides dropdown arrow until bug #649849 is fixed */ 257 | .button.icon select { 258 | width: 130%; 259 | } 260 | 261 | /****************************************************************************** 262 | * Right-To-Left layout 263 | */ 264 | 265 | html[dir="rtl"] li button, 266 | html[dir="rtl"] li a[role="button"], 267 | html[dir="rtl"] li .button { 268 | text-align: right; 269 | } 270 | 271 | html[dir="rtl"] li button:after, 272 | html[dir="rtl"] li a[role="button"]:after, 273 | html[dir="rtl"] li .button:after { 274 | background-position: right bottom; 275 | } 276 | 277 | html[dir="rtl"] li button.icon, 278 | html[dir="rtl"] li a[role="button"].icon, 279 | html[dir="rtl"] li .button.icon { 280 | padding-left: 3rem; 281 | padding-right: 1rem; 282 | } 283 | 284 | html[dir="rtl"] li button.icon:before, 285 | html[dir="rtl"] li a[role="button"].icon:before, 286 | html[dir="rtl"] li .button.icon:before { 287 | left: -1rem; 288 | right: inherit; 289 | } 290 | 291 | html[dir="rtl"] li button.icon-view:before, 292 | html[dir="rtl"] li a[role="button"].icon-view:before { 293 | background-image: url(../images/buttons/icons/view_rtl.png); 294 | background-position: 1.6rem 0; 295 | } 296 | 297 | html[dir="rtl"] li button.icon-dialog:before, 298 | html[dir="rtl"] li a[role="button"].icon-dialog:before, 299 | html[dir="rtl"] li .button.icon-dialog:before { 300 | background-image: url(../images/buttons/icons/dialog_rtl.png); 301 | background-position: 1.6rem 0; 302 | } 303 | 304 | -------------------------------------------------------------------------------- /css/headers.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- 2 | * HEADERS: default 3 | * ---------------------------------- */ 4 | section[role="region"] > header:first-child { 5 | position: relative; 6 | z-index: 10; 7 | padding: 0; 8 | height: 5rem; 9 | color: #fff; 10 | background-color: #F97C17; 11 | border: none; 12 | } 13 | 14 | section[role="region"] > header:first-child h1 { 15 | font-size: 2.5rem; 16 | line-height: 5rem; 17 | text-align: left; 18 | color: #fff; 19 | white-space: nowrap; 20 | text-overflow: ellipsis; 21 | display: block; 22 | overflow: hidden; 23 | margin: 0; 24 | padding: 0 1rem 0 3rem; 25 | height: 100%; 26 | font-weight: lighter; 27 | } 28 | 29 | section[role="region"] > header:first-child h1 em { 30 | font-weight: 400; 31 | font-size: 1.5rem; 32 | line-height: 1em; 33 | font-style: normal; 34 | } 35 | 36 | section[role="region"] > header:first-child form { 37 | display: block; 38 | overflow: hidden; 39 | position: relative; 40 | padding: 1rem 1rem 0 0.5rem ; 41 | margin-left: 3.5rem; 42 | } 43 | 44 | section[role="region"] > header:first-child input[type="text"] { 45 | width: 100%; 46 | height: 3rem; 47 | -moz-box-sizing: border-box; 48 | padding: 0 0.8rem; 49 | border: solid 0.1rem #9d4123; 50 | border-top-color: #a6501e; 51 | border-radius: 0.3rem; 52 | background: #fff url(../images/headers/ui/shadow.png) repeat-x left -0.1rem; 53 | font-size: 1.5rem; 54 | line-height: 3em; 55 | box-shadow: none; 56 | } 57 | 58 | section[role="region"] > header:first-child form button[type="reset"] { 59 | font-size: 0; 60 | overflow: hidden; 61 | position: absolute; 62 | right: 1rem; 63 | top: 1rem; 64 | bottom: 0; 65 | width: 3rem; 66 | height: auto; 67 | margin: 0; 68 | display: none; 69 | border: none; 70 | background: url(../images/headers/icons/clear.png) no-repeat center center / 1.7rem auto; 71 | } 72 | 73 | section[role="region"] > header:first-child input[type="text"]:valid + button[type="reset"] { 74 | display: block; 75 | } 76 | 77 | /* Generic set of actions in toolbar */ 78 | section[role="region"] > header:first-child menu[type="toolbar"] { 79 | height: 100%; 80 | float: right; 81 | } 82 | 83 | section[role="region"] > header:first-child menu[type="toolbar"] a, 84 | section[role="region"] > header:first-child menu[type="toolbar"] button { 85 | -moz-box-sizing: border-box; 86 | position: relative; 87 | float: left; 88 | width: auto; 89 | min-width: 5rem; 90 | height: 5rem; 91 | margin-bottom: 0; 92 | padding: 0 1rem; 93 | border-radius: 0; 94 | line-height: 5rem; 95 | background: none; 96 | text-align: center; 97 | text-shadow: none; 98 | z-index: 5; 99 | } 100 | 101 | 102 | section[role="region"] > header:first-child menu[type="toolbar"] { 103 | padding: 0; 104 | margin: 0; 105 | } 106 | 107 | section[role="region"] > header:first-child a, 108 | section[role="region"] > header:first-child button { 109 | border: none; 110 | padding: 0; 111 | overflow: hidden; 112 | font-weight: 400; 113 | font-size: 1.5rem; 114 | line-height: 1.1em; 115 | color: #fff; 116 | border-radius: 0; 117 | text-decoration: none; 118 | } 119 | 120 | /* Pressed state */ 121 | section[role="region"] > header:first-child a:focus { 122 | outline: none; 123 | } 124 | 125 | section[role="region"] > header:first-child button::-moz-focus-inner { 126 | outline: none; 127 | border: none; 128 | margin-top: -0.2rem; /* To fix line-height bug (697451) */ 129 | padding: 0; 130 | } 131 | 132 | section[role="region"] > header:first-child > a:not([aria-disabled="true"]):active:after, 133 | section[role="region"] > header:first-child > button:not(:disabled):active:after, 134 | section[role="region"] > header:first-child > a:not([aria-disabled="true"]):hover:after, 135 | section[role="region"] > header:first-child > button:not(:disabled):hover:after, 136 | section[role="region"] > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):hover, 137 | section[role="region"] > header:first-child menu[type="toolbar"] button:not(:disabled):hover, 138 | section[role="region"] > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):active, 139 | section[role="region"] > header:first-child menu[type="toolbar"] button:not(:disabled):active { 140 | background-color: #dc6a0e !important; 141 | } 142 | 143 | /* Disabled state */ 144 | section[role="region"] > header:first-child menu[type="toolbar"] a[aria-disabled="true"], 145 | section[role="region"] > header:first-child menu[type="toolbar"] button[disabled] { 146 | opacity: 0.5; 147 | } 148 | 149 | /* Icon definitions */ 150 | section[role="region"] > header:first-child .icon { 151 | position: relative; 152 | float: none; 153 | display: inline-block; 154 | vertical-align: middle; 155 | width: 3rem; 156 | height: 5rem; 157 | margin: 0 -1rem; 158 | background: transparent no-repeat center center / 3rem auto; 159 | font-size: 0; 160 | overflow: hidden; 161 | } 162 | 163 | section[role="region"] > header:first-child .icon.icon-add { 164 | background-image: url(../images/headers/icons/add.png); 165 | } 166 | 167 | section[role="region"] > header:first-child .icon.icon-compose { 168 | background-image: url(../images/headers/icons/compose.png); 169 | } 170 | 171 | section[role="region"] > header:first-child .icon.icon-edit { 172 | background-image: url(../images/headers/icons/edit.png); 173 | } 174 | 175 | section[role="region"] > header:first-child .icon.icon-send { 176 | background-image: url(../images/headers/icons/send.png); 177 | } 178 | 179 | section[role="region"] > header:first-child .icon.icon-close { 180 | background-image: url(../images/headers/icons/close.png); 181 | } 182 | 183 | section[role="region"] > header:first-child .icon.icon-back { 184 | background-image: url(../images/headers/icons/back.png); 185 | } 186 | 187 | section[role="region"] > header:first-child .icon.icon-menu { 188 | background-image: url(../images/headers/icons/menu.png); 189 | } 190 | 191 | section[role="region"] > header:first-child .icon.icon-user { 192 | background-image: url(../images/headers/icons/user.png); 193 | } 194 | 195 | section[role="region"] > header:first-child .icon.icon-up { 196 | background-image: url(../images/headers/icons/up.png); 197 | } 198 | 199 | section[role="region"] > header:first-child .icon.icon-down { 200 | background-image: url(../images/headers/icons/down.png); 201 | } 202 | 203 | section[role="region"] > header:first-child .icon.icon-disabled { 204 | opacity: 0.5; 205 | } 206 | 207 | /* We need to opt out of the header separator */ 208 | section[role="region"] > header:first-child menu[type="toolbar"] a.msg-down-btn { 209 | background: no-repeat left center / auto 4.8rem !important; 210 | } 211 | 212 | section[role="region"] > header:first-child .icon.icon-options { 213 | background-image: url(headers/icons/options.png); 214 | } 215 | 216 | /* Navigation links (back, cancel, etc) */ 217 | section[role="region"] > header:first-child > button, 218 | section[role="region"] > header:first-child > a { 219 | position: relative; 220 | width: 5rem; 221 | height: 5rem; 222 | background: none; 223 | float: left; 224 | overflow: visible; 225 | margin: 0 -5rem 0 0; 226 | } 227 | 228 | section[role="region"] > header:first-child > button:after, 229 | section[role="region"] > header:first-child > a:after { 230 | content: ""; 231 | position: absolute; 232 | left: 0; 233 | top: 0; 234 | z-index: -1; 235 | width: 2.6rem; 236 | height: 5rem; 237 | } 238 | 239 | section[role="region"] > header:first-child > button .icon, 240 | section[role="region"] > header:first-child > a .icon { 241 | display: block; 242 | margin: 0; 243 | font-size: 0; 244 | } 245 | 246 | /* ---------------------------------- 247 | * HEADERS: subheader 248 | * ---------------------------------- */ 249 | 250 | section[role="region"] > header { 251 | z-index: 0; 252 | height: auto; 253 | } 254 | 255 | section[role="region"] > header:after { 256 | display: none; 257 | } 258 | 259 | section[role="region"] header h2 { 260 | margin: 0; 261 | padding: 0.8rem 3rem; 262 | color: #424242; 263 | font-weight: 400; 264 | font-size: 1.5rem; 265 | line-height: 1.8rem; 266 | border-bottom: solid 0.1rem #e6e6e6; 267 | } 268 | 269 | /* ---------------------------------- 270 | * HEADERS: dark 271 | * ---------------------------------- */ 272 | section[role="region"].skin-dark > header:first-child, 273 | .skin-dark > section[role="region"] > header:first-child { 274 | background-color: #242D33; 275 | } 276 | 277 | 278 | /* Navigation links (back, cancel, etc) */ 279 | /* the `organic' blue arrows work fine with the dark theme, let's reuse them */ 280 | section[role="region"].skin-dark > header:first-child .icon.icon-back { 281 | background-image: url(../images/headers/icons/organic/back.png); 282 | } 283 | 284 | section[role="region"].skin-dark > header:first-child .icon.icon-close { 285 | background-image: url(../images/headers/icons/organic/close.png); 286 | } 287 | 288 | 289 | section[role="region"].skin-dark > header:first-child > a:not([aria-disabled="true"]):active:after, 290 | section[role="region"].skin-dark > header:first-child > button:not(:disabled):active:after, 291 | section[role="region"].skin-dark > header:first-child > a:not([aria-disabled="true"]):hover:after, 292 | section[role="region"].skin-dark > header:first-child > button:not(:disabled):hover:after, 293 | section[role="region"].skin-dark > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):hover, 294 | section[role="region"].skin-dark > header:first-child menu[type="toolbar"] button:not(:disabled):hover, 295 | section[role="region"].skin-dark > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):active, 296 | section[role="region"].skin-dark > header:first-child menu[type="toolbar"] button:not(:disabled):active { 297 | background-color: #1d525e !important; 298 | } 299 | 300 | section[role="region"].skin-dark header h2, 301 | .skin-dark > section[role="region"] header h2 { 302 | background-color: #2c353b; 303 | color: #fff; 304 | border: none; 305 | } 306 | 307 | 308 | 309 | /* ---------------------------------- 310 | * HEADERS: organic 311 | * ---------------------------------- */ 312 | 313 | section[role="region"].skin-organic > header:first-child, 314 | .skin-organic section[role="region"] > header:first-child { 315 | background-color: #F4F4F4; 316 | } 317 | 318 | section[role="region"].skin-organic > header:first-child h1, 319 | .skin-organic section[role="region"] > header:first-child h1 { 320 | color: #868692; 321 | } 322 | 323 | /* clear background => specific dark icons */ 324 | 325 | section[role="region"].skin-organic > header:first-child .icon.icon-back, 326 | .skin-organic section[role="region"] > header:first-child .icon.icon-back { 327 | background-image: url(../images/headers/icons/organic/back.png); 328 | } 329 | 330 | section[role="region"].skin-organic > header:first-child .icon.icon-close, 331 | .skin-organic section[role="region"] > header:first-child .icon.icon-close { 332 | background-image: url(../images/headers/icons/organic/close.png); 333 | } 334 | 335 | section[role="region"].skin-organic > header:first-child .icon.icon-add, 336 | .skin-organic section[role="region"] > header:first-child .icon.icon-add { 337 | background-image: url(../images/headers/icons/organic/add.png); 338 | } 339 | 340 | section[role="region"].skin-organic > header:first-child .icon.icon-edit, 341 | .skin-organic section[role="region"] > header:first-child .icon.icon-edit { 342 | background-image: url(../images/headers/icons/organic/edit.png); 343 | } 344 | 345 | section[role="region"].skin-organic > header:first-child > a:not([aria-disabled="true"]):active:after, 346 | .skin-organic section[role="region"] > header:first-child > a:not([aria-disabled="true"]):active:after, 347 | section[role="region"].skin-organic > header:first-child > button:not(:disabled):active:after, 348 | .skin-organic section[role="region"] > header:first-child > button:not(:disabled):active:after, 349 | section[role="region"].skin-organic > header:first-child > a:not([aria-disabled="true"]):hover:after, 350 | .skin-organic section[role="region"] > header:first-child > a:not([aria-disabled="true"]):hover:after, 351 | section[role="region"].skin-organic > header:first-child > button:not(:disabled):hover:after, 352 | .skin-organic section[role="region"] > header:first-child > button:not(:disabled):hover:after, 353 | section[role="region"].skin-organic > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):hover, 354 | .skin-organic section[role="region"] > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):hover, 355 | section[role="region"].skin-organic > header:first-child menu[type="toolbar"] button:not(:disabled):hover, 356 | .skin-organic section[role="region"] > header:first-child menu[type="toolbar"] button:not(:disabled):hover, 357 | section[role="region"].skin-organic > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):active, 358 | .skin-organic section[role="region"] > header:first-child menu[type="toolbar"] a:not([aria-disabled="true"]):active, 359 | section[role="region"].skin-organic > header:first-child menu[type="toolbar"] button:not(:disabled):active, 360 | .skin-organic section[role="region"] > header:first-child menu[type="toolbar"] button:not(:disabled):active { 361 | background-color: #aae1e9 !important; 362 | } 363 | 364 | section[role="region"].skin-organic header h2, 365 | .skin-organic section[role="region"] header h2 { 366 | background-color: #e7e7e7; 367 | color: #4D4D4D; 368 | border: none; 369 | } 370 | 371 | section[role="region"].skin-organic > header:first-child a, 372 | .skin-organic section[role="region"] > header:first-child a, 373 | section[role="region"].skin-organic > header:first-child button, 374 | .skin-organic section[role="region"] > header:first-child button { 375 | color: #858585; 376 | } 377 | 378 | 379 | /* ---------------------------------- 380 | * HEADERS: right-to-left tweaks 381 | * ---------------------------------- */ 382 | 383 | html[dir="rtl"] section[role="region"] > header:first-child h1 { 384 | text-align: right; 385 | padding: 0 3rem 0 1rem; 386 | } 387 | html[dir="rtl"] section[role="region"] > header:first-child form { 388 | padding: 1rem .5rem 0 1rem ; 389 | margin-right: 3.5rem; 390 | margin-left:0; 391 | } 392 | html[dir="rtl"] section[role="region"] > header:first-child input[type="text"] { 393 | background: #fff url(headers/ui/shadow.png) repeat-x right -0.1rem; 394 | } 395 | 396 | html[dir="rtl"] section[role="region"] > header:first-child form button[type="reset"] { 397 | left: 1rem; 398 | right:inherit; 399 | } 400 | html[dir="rtl"] section[role="region"] > header:first-child menu[type="toolbar"] { 401 | float: left; 402 | } 403 | html[dir="rtl"] section[role="region"] > header:first-child menu[type="toolbar"] a, 404 | html[dir="rtl"] section[role="region"] > header:first-child menu[type="toolbar"] button { 405 | float: right; 406 | } 407 | html[dir="rtl"] section[role="region"] > header:first-child > button, 408 | html[dir="rtl"] section[role="region"] > header:first-child > a { 409 | float: right; 410 | margin: 0 0 0 -5rem; 411 | } 412 | html[dir="rtl"] section[role="region"] > header:first-child > button:after, 413 | html[dir="rtl"] section[role="region"] > header:first-child > a:after { 414 | right: 0; 415 | } 416 | html[dir="rtl"] section[role="region"] > header:first-child .icon.icon-back { 417 | background-image: url(../images/headers/icons/back_rtl.png); 418 | } 419 | html[dir="rtl"] section[role="region"].skin-organic > header:first-child .icon.icon-back, 420 | html[dir="rtl"] .skin-organic section[role="region"] > header:first-child .icon.icon-back, 421 | html[dir="rtl"] section[role="region"].skin-dark > header:first-child .icon.icon-back { 422 | background-image: url(../images/headers/icons/organic/back_rtl.png); 423 | } 424 | 425 | -------------------------------------------------------------------------------- /js/webapp.js: -------------------------------------------------------------------------------- 1 | /* global MozActivity, alert, console, Notification */ 2 | "use strict"; 3 | (function () { 4 | /* 5 | WebActivities: 6 | 7 | configure 8 | costcontrol/balance 9 | costcontrol/data_usage 10 | costcontrol/telephony 11 | dial 12 | new (type: "websms/sms", "webcontacts/contact") (add-contact, compose-mail?) 13 | open 14 | pick (type: "image/png" etc) 15 | record (capture?) 16 | save-bookmark 17 | share 18 | test 19 | view (type: "url" etc. "text/html"?) 20 | */ 21 | 22 | // WebActivities 23 | var pickImage = document.querySelector("#pick-image"); 24 | if (pickImage) { 25 | pickImage.onclick = function () { 26 | var pick = new MozActivity({ 27 | name: "pick", 28 | data: { 29 | type: ["image/png", "image/jpg", "image/jpeg"], 30 | // In FxOS 1.3 and before the user is allowed to crop the 31 | // image by default, but this can cause out-of-memory issues 32 | // so we explicitly disable it. 33 | nocrop: true // don't allow the user to crop the image 34 | } 35 | }); 36 | 37 | pick.onsuccess = function () { 38 | var img = document.createElement("img"); 39 | img.src = window.URL.createObjectURL(this.result.blob); 40 | var imagePresenter = document.querySelector("#image-presenter"); 41 | imagePresenter.appendChild(img); 42 | imagePresenter.style.display = "block"; 43 | }; 44 | 45 | pick.onerror = function () { 46 | console.log("Can't view the image"); 47 | }; 48 | }; 49 | } 50 | 51 | var pickAnything = document.querySelector("#pick-anything"); 52 | if (pickAnything) { 53 | pickAnything.onclick = function () { 54 | var pickAny = new MozActivity({ 55 | name: "pick" 56 | }); 57 | 58 | pickAny.onsuccess = function () { 59 | var img = document.createElement("img"); 60 | if (this.result.blob.type.indexOf("image") != -1) { 61 | img.src = window.URL.createObjectURL(this.result.blob); 62 | var imagePresenter = document.querySelector("#image-presenter"); 63 | imagePresenter.appendChild(img); 64 | imagePresenter.style.display = "block"; 65 | } 66 | }; 67 | 68 | pickAny.onerror = function () { 69 | console.log("An error occurred"); 70 | }; 71 | }; 72 | } 73 | 74 | var record = document.querySelector("#record"); 75 | if (record) { 76 | record.onclick = function () { 77 | var rec = new MozActivity({ 78 | name: "record" // Possibly capture in future versions 79 | }); 80 | 81 | rec.onsuccess = function () { 82 | var img = document.createElement("img"); 83 | img.src = window.URL.createObjectURL(this.result.blob); 84 | var imagePresenter = document.querySelector("#image-presenter"); 85 | imagePresenter.appendChild(img); 86 | imagePresenter.style.display = "block"; 87 | }; 88 | 89 | rec.onerror = function () { 90 | alert("No taken picture returned"); 91 | }; 92 | }; 93 | } 94 | 95 | var dial = document.querySelector("#dial"); 96 | if (dial) { 97 | dial.onclick = function () { 98 | new MozActivity({ 99 | name: "dial", 100 | data: { 101 | number: "+46777888999" 102 | } 103 | }); 104 | }; 105 | } 106 | 107 | var sendSMS = document.querySelector("#send-sms"); 108 | if (sendSMS) { 109 | sendSMS.onclick = function () { 110 | new MozActivity({ 111 | name: "new", // Possible compose-sms in future versions 112 | data: { 113 | type: "websms/sms", 114 | number: "+46777888999" 115 | } 116 | }); 117 | }; 118 | } 119 | 120 | var addContact = document.querySelector("#add-contact"); 121 | if (addContact) { 122 | addContact.onclick = function () { 123 | new MozActivity({ 124 | name: "new", // Possibly add-contact in future versions 125 | data: { 126 | type: "webcontacts/contact", 127 | params: { // Will possibly move to be direct properties under "data" 128 | givenName: "Robert", 129 | lastName: "Nyman", 130 | tel: "+44789", 131 | email: "robert@mozilla.com", 132 | address: "San Francisco", 133 | note: "This is a note", 134 | company: "Mozilla" 135 | } 136 | } 137 | }); 138 | }; 139 | } 140 | 141 | var share = document.querySelector("#share"); 142 | if (share) { 143 | share.onclick = function () { 144 | new MozActivity({ 145 | name: "share", 146 | data: { 147 | //type: "url", // Possibly text/html in future versions, 148 | number: 1, 149 | url: "http://robertnyman.com" 150 | } 151 | }); 152 | }; 153 | } 154 | 155 | var shareImage = document.querySelector("#share-image"), 156 | imgToShare = document.querySelector("#image-to-share"); 157 | if (shareImage && imgToShare) { 158 | shareImage.onclick = function () { 159 | if(imgToShare.naturalWidth > 0) { 160 | // Create dummy canvas 161 | var blobCanvas = document.createElement("canvas"); 162 | blobCanvas.width = imgToShare.width; 163 | blobCanvas.height = imgToShare.height; 164 | 165 | // Get context and draw image 166 | var blobCanvasContext = blobCanvas.getContext("2d"); 167 | blobCanvasContext.drawImage(imgToShare, 0, 0); 168 | 169 | // Export to blob and share through a Web Activitiy 170 | blobCanvas.toBlob(function (blob) { 171 | new MozActivity({ 172 | name: "share", 173 | data: { 174 | type: "image/*", 175 | number: 1, 176 | blobs: [blob] 177 | } 178 | }); 179 | }); 180 | } 181 | else { 182 | alert("Image failed to load, can't be shared"); 183 | } 184 | }; 185 | } 186 | 187 | var viewURL = document.querySelector("#view-url"); 188 | if (viewURL) { 189 | viewURL.onclick = function () { 190 | new MozActivity({ 191 | name: "view", 192 | data: { 193 | type: "url", // Possibly text/html in future versions 194 | url: "http://robertnyman.com" 195 | } 196 | }); 197 | }; 198 | } 199 | 200 | var composeEmail = document.querySelector("#compose-email"); 201 | if (composeEmail) { 202 | composeEmail.onclick = function () { 203 | new MozActivity({ 204 | name: "new", // Possibly compose-mail in future versions 205 | data: { 206 | type : "mail", 207 | url: "mailto:example@example.org" 208 | } 209 | }); 210 | }; 211 | } 212 | 213 | var saveBookmark = document.querySelector("#save-bookmark"); 214 | if (saveBookmark) { 215 | saveBookmark.onclick = function () { 216 | new MozActivity({ 217 | name: "save-bookmark", 218 | data: { 219 | type: "url", 220 | url: "http://robertnyman.com", 221 | name: "Robert's talk", 222 | icon: "http://robertnyman.com/favicon.png" 223 | } 224 | }); 225 | }; 226 | } 227 | 228 | var openVideo = document.querySelector("#open-video"); 229 | if (openVideo) { 230 | openVideo.onclick = function () { 231 | new MozActivity({ 232 | name: "open", 233 | data: { 234 | type: [ 235 | "video/webm", 236 | "video/mp4", 237 | "video/3gpp", 238 | "video/youtube" 239 | ], 240 | url: "http://v2v.cc/~j/theora_testsuite/320x240.ogg" 241 | } 242 | }); 243 | }; 244 | } 245 | 246 | var openSettings = document.querySelector("#open-settings"); 247 | if (openSettings) { 248 | openSettings.onclick = function () { 249 | new MozActivity({ 250 | name: "configure", 251 | target: "device" 252 | }); 253 | }; 254 | } 255 | 256 | 257 | 258 | // Notifications 259 | var addNotification = document.querySelector("#add-notification"); 260 | if (addNotification) { 261 | addNotification.onclick = function () { 262 | if ("Notification" in window) { 263 | // Firefox OS 1.1 and higher 264 | if (Notification.permission !== "denied") { 265 | Notification.requestPermission(function (permission) { 266 | if(!("permission" in Notification)) { 267 | Notification.permission = permission; 268 | } 269 | }); 270 | } 271 | 272 | if (Notification.permission === "granted") { 273 | new Notification("See this", { 274 | body : "This is a notification" 275 | }); 276 | } 277 | } 278 | else { 279 | // Firefox OS 1.0 280 | var notify = navigator.mozNotification.createNotification( 281 | "See this", 282 | "This is a notification" 283 | ); 284 | notify.show(); 285 | } 286 | }; 287 | } 288 | 289 | // Lock orientation 290 | var lockOrientation = document.querySelector("#lock-orientation"); 291 | if (lockOrientation) { 292 | lockOrientation.onclick = function () { 293 | /* 294 | Possible values: 295 | "landscape", 296 | "portrait" 297 | "landscape-primary" 298 | "landscape-secondary" 299 | "portrait-primary" 300 | "portrait-secondary" 301 | */ 302 | var portraitLock = screen.mozLockOrientation("portrait"); 303 | if (portraitLock) { 304 | alert("Orientation locked to portrait"); 305 | } 306 | }; 307 | } 308 | 309 | // Vibration 310 | var vibrate = document.querySelector("#vibrate"); 311 | if (vibrate) { 312 | vibrate.onclick = function () { 313 | navigator.vibrate(2000); 314 | /* 315 | Possible values: 316 | On/off pattern: 317 | navigator.vibrate([200, 100, 200, 100]); 318 | 319 | Turn off vibration 320 | navigator.vibrate(0); 321 | */ 322 | }; 323 | } 324 | 325 | // Check connection 326 | var checkConnection = document.querySelector("#check-connection"), 327 | connectionDisplay = document.querySelector("#connection-display"); 328 | 329 | if (checkConnection && connectionDisplay) { 330 | checkConnection.onclick = function () { 331 | var connection = window.navigator.mozConnection, 332 | online = "Connected: " + (connection.bandwidth), 333 | metered = "Metered: " + connection.metered; 334 | 335 | connectionDisplay.innerHTML = "

Result from Check connection

" + online + "
" + metered; 336 | connectionDisplay.style.display = "block"; 337 | }; 338 | } 339 | 340 | // Check battery 341 | var checkBattery = document.querySelector("#check-battery"), 342 | batteryDisplay = document.querySelector("#battery-display"); 343 | if (checkBattery && batteryDisplay) { 344 | checkBattery.onclick = function () { 345 | var battery = navigator.battery, 346 | batteryLevel = Math.round(battery.level * 100) + "%", 347 | charging = battery.charging, 348 | chargingTime = parseInt(battery.chargingTime / 60, 10), 349 | dischargingTime = parseInt(battery.dischargingTime / 60, 10), 350 | batteryInfo; 351 | 352 | batteryInfo = "

Result from Check battery

Battery level: " + batteryLevel + "
"; 353 | batteryInfo += "Battery charging: " + charging + "
"; 354 | batteryInfo += "Battery charging time: " + chargingTime + "
"; 355 | batteryInfo += "Battery discharging time: " + dischargingTime; 356 | 357 | batteryDisplay.innerHTML = batteryInfo; 358 | batteryDisplay.style.display = "block"; 359 | }; 360 | } 361 | 362 | // Geolocation 363 | var geolocation = document.querySelector("#geolocation"), 364 | geolocationDisplay = document.querySelector("#geolocation-display"); 365 | if (geolocation && geolocationDisplay) { 366 | geolocation.onclick = function () { 367 | navigator.geolocation.getCurrentPosition(function (position) { 368 | geolocationDisplay.innerHTML = "Latitude: " + position.coords.latitude + ", Longitude: " + position.coords.longitude; 369 | geolocationDisplay.style.display = "block"; 370 | }, 371 | function () { 372 | geolocationDisplay.innerHTML = "Failed to get your current location"; 373 | geolocationDisplay.style.display = "block"; 374 | }); 375 | }; 376 | } 377 | 378 | // Ambient light 379 | var ambientLight = document.querySelector("#ambient-light"), 380 | ambientLightDisplay = document.querySelector("#ambient-light-display"); 381 | if (ambientLight && ambientLightDisplay) { 382 | ambientLight.onclick = function () { 383 | ambientLightDisplay.style.display = "block"; 384 | window.ondevicelight = function (event) { 385 | // Read out the lux value 386 | var lux = "Ambient light: " + event.value + " lux"; 387 | ambientLightDisplay.innerHTML = lux; 388 | }; 389 | }; 390 | } 391 | 392 | // Proximity 393 | var proximity = document.querySelector("#proximity"), 394 | proximityDisplay = document.querySelector("#proximity-display"); 395 | if (proximity && proximityDisplay) { 396 | proximity.onclick = function () { 397 | proximityDisplay.style.display = "block"; 398 | window.ondeviceproximity = function (event) { 399 | // Check proximity, in centimeters 400 | var prox = "Proximity: " + event.value + " cm
"; 401 | prox += "Min value supported: " + event.min + " cm
"; 402 | prox += "Max value supported: " + event.max + " cm"; 403 | proximityDisplay.innerHTML = prox; 404 | }; 405 | }; 406 | } 407 | 408 | // User proximity 409 | var userProximity = document.querySelector("#user-proximity"), 410 | userProximityDisplay = document.querySelector("#user-proximity-display"); 411 | if (userProximity && userProximityDisplay) { 412 | userProximity.onclick = function () { 413 | userProximityDisplay.style.display = "block"; 414 | window.onuserproximity = function (event) { 415 | // Check user proximity 416 | var userProx = "User proximity - near: " + event.near + "
"; 417 | userProximityDisplay.innerHTML = userProx; 418 | }; 419 | }; 420 | } 421 | 422 | // Device Orientation 423 | var deviceOrientation = document.querySelector("#device-orientation"), 424 | deviceOrientationDisplay = document.querySelector("#device-orientation-display"); 425 | 426 | if (deviceOrientation && deviceOrientationDisplay) { 427 | deviceOrientation.onclick = function() { 428 | deviceOrientationDisplay.style.display = "block"; 429 | window.ondeviceorientation = function (event) { 430 | var orientedTo = (event.beta > 45 && event.beta < 135) ? "top" : (event.beta < -45 && event.beta > -135) ? "bottom" : (event.gamma > 45) ? "right" : (event.gamma < -45) ? "left" : "flat"; 431 | var orientation = "Absolute: " + event.absolute + "
" + 432 | "Alpha: " + event.alpha + "
" + 433 | "Beta: " + event.beta + "
" + 434 | "Gamma: " + event.gamma + "
" + 435 | "Device orientation: " + orientedTo; 436 | 437 | deviceOrientationDisplay.innerHTML = orientation; 438 | }; 439 | }; 440 | } 441 | 442 | // Log visibility of the app 443 | var logVisibility = document.querySelector("#log-visibility"), 444 | logVisibilityDisplay = document.querySelector("#log-visibility-display"); 445 | if (logVisibility && logVisibilityDisplay) { 446 | logVisibility.onclick = function () { 447 | logVisibilityDisplay.style.display = "block"; 448 | logVisibilityDisplay.innerHTML = "I have focus!
"; 449 | document.addEventListener("visibilitychange", function () { 450 | if (document.hidden) { 451 | console.log("Firefox OS Boilerplate App is hidden"); 452 | logVisibilityDisplay.innerHTML += "Now I'm in the background
"; 453 | } 454 | else { 455 | console.log("Firefox OS Boilerplate App has focus"); 456 | logVisibilityDisplay.innerHTML += "I have focus!
"; 457 | } 458 | }); 459 | }; 460 | } 461 | 462 | // Cross domain XHR 463 | var crossDomainXHR = document.querySelector("#cross-domain-xhr"), 464 | crossDomainXHRDisplay = document.querySelector("#cross-domain-xhr-display"); 465 | if (crossDomainXHR && crossDomainXHRDisplay) { 466 | crossDomainXHR.onclick = function () { 467 | var xhr = new XMLHttpRequest({mozSystem: true}); 468 | xhr.open("GET", "http://robnyman.github.io/Firefox-OS-Boilerplate-App/README.md", true); 469 | xhr.onreadystatechange = function () { 470 | if (xhr.status === 200 && xhr.readyState === 4) { 471 | crossDomainXHRDisplay.innerHTML = "

Result from Cross-domain XHR

" + xhr.response; 472 | crossDomainXHRDisplay.style.display = "block"; 473 | } 474 | }; 475 | 476 | xhr.onerror = function () { 477 | crossDomainXHRDisplay.innerHTML = "

Result from Cross-domain XHR

Cross-domain XHR failed

"; 478 | crossDomainXHRDisplay.style.display = "block"; 479 | }; 480 | xhr.send(); 481 | }; 482 | } 483 | 484 | // deviceStorage, pictures 485 | var deviceStoragePictures = document.querySelector("#device-storage-pictures"), 486 | deviceStoragePicturesDisplay = document.querySelector("#device-storage-pictures-display"); 487 | if (deviceStoragePictures && deviceStoragePicturesDisplay) { 488 | deviceStoragePictures.onclick = function () { 489 | var deviceStorage = navigator.getDeviceStorage("pictures"), 490 | cursor = deviceStorage.enumerate(); 491 | deviceStoragePicturesDisplay.innerHTML = "

Result from deviceStorage - pictures

"; 492 | 493 | cursor.onsuccess = function () { 494 | if (!cursor.result) { 495 | deviceStoragePicturesDisplay.innerHTML = "No files"; 496 | } 497 | 498 | var file = cursor.result, 499 | filePresentation; 500 | filePresentation = "" + file.name + ": " + parseInt(file.size / 1024, 10) + "kb
"; 501 | filePresentation += "

"; 502 | deviceStoragePicturesDisplay.innerHTML += filePresentation; 503 | 504 | deviceStoragePicturesDisplay.style.display = "block"; 505 | }; 506 | 507 | cursor.onerror = function () { 508 | console.log(this.error); 509 | deviceStoragePicturesDisplay.innerHTML = "

Result from deviceStorage - pictures

deviceStorage failed

" + 510 | (this.error.message || this.error.name || this.error.toString()) + "

"; 511 | deviceStoragePicturesDisplay.style.display = "block"; 512 | }; 513 | }; 514 | } 515 | 516 | // List contacts 517 | var getAllContacts = document.querySelector("#get-all-contacts"), 518 | getAllContactsDisplay = document.querySelector("#get-all-contacts-display"); 519 | if (getAllContacts && getAllContactsDisplay) { 520 | getAllContacts.onclick = function () { 521 | var getContacts = window.navigator.mozContacts.getAll({}); 522 | getAllContactsDisplay.style.display = "block"; 523 | 524 | getContacts.onsuccess = function () { 525 | var result = getContacts.result; 526 | if (result) { 527 | getAllContactsDisplay.innerHTML += result.givenName + " " + result.familyName + "
"; 528 | getContacts.continue(); 529 | } 530 | }; 531 | 532 | getContacts.onerror = function () { 533 | getAllContactsDisplay.innerHTML += "Error"; 534 | }; 535 | }; 536 | } 537 | 538 | // Keep screen on 539 | var lock = null, 540 | keepscreen = document.querySelector("#keep-screen-on"); 541 | if (keepscreen) { 542 | keepscreen.onclick = function () { 543 | if (!lock) { 544 | lock = window.navigator.requestWakeLock("screen"); 545 | keepscreen.innerHTML = "Remove the lock"; 546 | } 547 | else { 548 | lock.unlock(); 549 | lock = null; 550 | keepscreen.innerHTML = "Keep screen on"; 551 | } 552 | }; 553 | } 554 | 555 | // Alarm API 556 | var alarmDate = new Date("Aug 31, 2014 15:20:00"), 557 | addAlarm = document.querySelector("#add-alarm"), 558 | alarmDisplay = document.querySelector("#alarm-display"); 559 | if (addAlarm) { 560 | addAlarm.onclick = function () { 561 | var alarm = navigator.mozAlarms.add(alarmDate, "honorTimezone", { 562 | "optionalData" : "I am data" 563 | }); 564 | 565 | alarm.onsuccess = function () { 566 | alarmDisplay.innerHTML = "Alarm scheduled for " + alarmDate; 567 | }; 568 | 569 | alarm.onerror = function () { 570 | alarmDisplay.innerHTML = "Failed to set the alarm
" + this.error.name; 571 | }; 572 | 573 | var getAllAlarms = navigator.mozAlarms.getAll(); 574 | getAllAlarms.onsuccess = function () { 575 | alarmDisplay.innerHTML += "

All alarms

"; 576 | this.result.forEach(function (alarm) { 577 | alarmDisplay.innerHTML += "

Id: " + alarm.id + 578 | ", date: " + alarm.date + 579 | ", respectTimezone: " + alarm.respectTimezone + 580 | ", data: " + JSON.stringify(alarm.data) + "

"; 581 | }); 582 | }; 583 | 584 | getAllAlarms.onerror = function () { 585 | alarmDisplay.innerHTML = "

Failed to get all alarms

" + this.error.name; 586 | }; 587 | }; 588 | } 589 | 590 | var removeAllAlarms = document.querySelector("#remove-all-alarms"), 591 | removeAlarmsDisplay = document.querySelector("#remove-alarms-display"); 592 | if(removeAllAlarms) { 593 | removeAllAlarms.onclick = function () { 594 | var getAddedAlarms = navigator.mozAlarms.getAll(); 595 | getAddedAlarms.onsuccess = function () { 596 | this.result.forEach(function (alarm) { 597 | navigator.mozAlarms.remove(alarm.id); 598 | }); 599 | removeAlarmsDisplay.innerHTML = "All alarms removed"; 600 | if (alarmDisplay) { 601 | alarmDisplay.innerHTML = ""; 602 | } 603 | }; 604 | 605 | getAddedAlarms.onerror = function () { 606 | removeAlarmsDisplay.innerHTML = "

Failed to remove all alarms

" + this.error.name; 607 | }; 608 | }; 609 | } 610 | })(); 611 | -------------------------------------------------------------------------------- /js/l10n.js: -------------------------------------------------------------------------------- 1 | (function(window, undefined) { 2 | 'use strict'; 3 | 4 | /* jshint validthis:true */ 5 | function L10nError(message, id, loc) { 6 | this.name = 'L10nError'; 7 | this.message = message; 8 | this.id = id; 9 | this.loc = loc; 10 | } 11 | L10nError.prototype = Object.create(Error.prototype); 12 | L10nError.prototype.constructor = L10nError; 13 | 14 | 15 | /* jshint browser:true */ 16 | 17 | var io = { 18 | load: function load(url, callback, sync) { 19 | var xhr = new XMLHttpRequest(); 20 | 21 | if (xhr.overrideMimeType) { 22 | xhr.overrideMimeType('text/plain'); 23 | } 24 | 25 | xhr.open('GET', url, !sync); 26 | 27 | xhr.addEventListener('load', function io_load(e) { 28 | if (e.target.status === 200 || e.target.status === 0) { 29 | callback(null, e.target.responseText); 30 | } else { 31 | callback(new L10nError('Not found: ' + url)); 32 | } 33 | }); 34 | xhr.addEventListener('error', callback); 35 | xhr.addEventListener('timeout', callback); 36 | 37 | // the app: protocol throws on 404, see https://bugzil.la/827243 38 | try { 39 | xhr.send(null); 40 | } catch (e) { 41 | callback(new L10nError('Not found: ' + url)); 42 | } 43 | }, 44 | 45 | loadJSON: function loadJSON(url, callback) { 46 | var xhr = new XMLHttpRequest(); 47 | 48 | if (xhr.overrideMimeType) { 49 | xhr.overrideMimeType('application/json'); 50 | } 51 | 52 | xhr.open('GET', url); 53 | 54 | xhr.responseType = 'json'; 55 | xhr.addEventListener('load', function io_loadjson(e) { 56 | if (e.target.status === 200 || e.target.status === 0) { 57 | callback(null, e.target.response); 58 | } else { 59 | callback(new L10nError('Not found: ' + url)); 60 | } 61 | }); 62 | xhr.addEventListener('error', callback); 63 | xhr.addEventListener('timeout', callback); 64 | 65 | // the app: protocol throws on 404, see https://bugzil.la/827243 66 | try { 67 | xhr.send(null); 68 | } catch (e) { 69 | callback(new L10nError('Not found: ' + url)); 70 | } 71 | } 72 | }; 73 | 74 | function EventEmitter() {} 75 | 76 | EventEmitter.prototype.emit = function ee_emit() { 77 | if (!this._listeners) { 78 | return; 79 | } 80 | 81 | var args = Array.prototype.slice.call(arguments); 82 | var type = args.shift(); 83 | if (!this._listeners[type]) { 84 | return; 85 | } 86 | 87 | var typeListeners = this._listeners[type].slice(); 88 | for (var i = 0; i < typeListeners.length; i++) { 89 | typeListeners[i].apply(this, args); 90 | } 91 | }; 92 | 93 | EventEmitter.prototype.addEventListener = function ee_add(type, listener) { 94 | if (!this._listeners) { 95 | this._listeners = {}; 96 | } 97 | if (!(type in this._listeners)) { 98 | this._listeners[type] = []; 99 | } 100 | this._listeners[type].push(listener); 101 | }; 102 | 103 | EventEmitter.prototype.removeEventListener = function ee_rm(type, listener) { 104 | if (!this._listeners) { 105 | return; 106 | } 107 | 108 | var typeListeners = this._listeners[type]; 109 | var pos = typeListeners.indexOf(listener); 110 | if (pos === -1) { 111 | return; 112 | } 113 | 114 | typeListeners.splice(pos, 1); 115 | }; 116 | 117 | 118 | function getPluralRule(lang) { 119 | var locales2rules = { 120 | 'af': 3, 121 | 'ak': 4, 122 | 'am': 4, 123 | 'ar': 1, 124 | 'asa': 3, 125 | 'az': 0, 126 | 'be': 11, 127 | 'bem': 3, 128 | 'bez': 3, 129 | 'bg': 3, 130 | 'bh': 4, 131 | 'bm': 0, 132 | 'bn': 3, 133 | 'bo': 0, 134 | 'br': 20, 135 | 'brx': 3, 136 | 'bs': 11, 137 | 'ca': 3, 138 | 'cgg': 3, 139 | 'chr': 3, 140 | 'cs': 12, 141 | 'cy': 17, 142 | 'da': 3, 143 | 'de': 3, 144 | 'dv': 3, 145 | 'dz': 0, 146 | 'ee': 3, 147 | 'el': 3, 148 | 'en': 3, 149 | 'eo': 3, 150 | 'es': 3, 151 | 'et': 3, 152 | 'eu': 3, 153 | 'fa': 0, 154 | 'ff': 5, 155 | 'fi': 3, 156 | 'fil': 4, 157 | 'fo': 3, 158 | 'fr': 5, 159 | 'fur': 3, 160 | 'fy': 3, 161 | 'ga': 8, 162 | 'gd': 24, 163 | 'gl': 3, 164 | 'gsw': 3, 165 | 'gu': 3, 166 | 'guw': 4, 167 | 'gv': 23, 168 | 'ha': 3, 169 | 'haw': 3, 170 | 'he': 2, 171 | 'hi': 4, 172 | 'hr': 11, 173 | 'hu': 0, 174 | 'id': 0, 175 | 'ig': 0, 176 | 'ii': 0, 177 | 'is': 3, 178 | 'it': 3, 179 | 'iu': 7, 180 | 'ja': 0, 181 | 'jmc': 3, 182 | 'jv': 0, 183 | 'ka': 0, 184 | 'kab': 5, 185 | 'kaj': 3, 186 | 'kcg': 3, 187 | 'kde': 0, 188 | 'kea': 0, 189 | 'kk': 3, 190 | 'kl': 3, 191 | 'km': 0, 192 | 'kn': 0, 193 | 'ko': 0, 194 | 'ksb': 3, 195 | 'ksh': 21, 196 | 'ku': 3, 197 | 'kw': 7, 198 | 'lag': 18, 199 | 'lb': 3, 200 | 'lg': 3, 201 | 'ln': 4, 202 | 'lo': 0, 203 | 'lt': 10, 204 | 'lv': 6, 205 | 'mas': 3, 206 | 'mg': 4, 207 | 'mk': 16, 208 | 'ml': 3, 209 | 'mn': 3, 210 | 'mo': 9, 211 | 'mr': 3, 212 | 'ms': 0, 213 | 'mt': 15, 214 | 'my': 0, 215 | 'nah': 3, 216 | 'naq': 7, 217 | 'nb': 3, 218 | 'nd': 3, 219 | 'ne': 3, 220 | 'nl': 3, 221 | 'nn': 3, 222 | 'no': 3, 223 | 'nr': 3, 224 | 'nso': 4, 225 | 'ny': 3, 226 | 'nyn': 3, 227 | 'om': 3, 228 | 'or': 3, 229 | 'pa': 3, 230 | 'pap': 3, 231 | 'pl': 13, 232 | 'ps': 3, 233 | 'pt': 3, 234 | 'rm': 3, 235 | 'ro': 9, 236 | 'rof': 3, 237 | 'ru': 11, 238 | 'rwk': 3, 239 | 'sah': 0, 240 | 'saq': 3, 241 | 'se': 7, 242 | 'seh': 3, 243 | 'ses': 0, 244 | 'sg': 0, 245 | 'sh': 11, 246 | 'shi': 19, 247 | 'sk': 12, 248 | 'sl': 14, 249 | 'sma': 7, 250 | 'smi': 7, 251 | 'smj': 7, 252 | 'smn': 7, 253 | 'sms': 7, 254 | 'sn': 3, 255 | 'so': 3, 256 | 'sq': 3, 257 | 'sr': 11, 258 | 'ss': 3, 259 | 'ssy': 3, 260 | 'st': 3, 261 | 'sv': 3, 262 | 'sw': 3, 263 | 'syr': 3, 264 | 'ta': 3, 265 | 'te': 3, 266 | 'teo': 3, 267 | 'th': 0, 268 | 'ti': 4, 269 | 'tig': 3, 270 | 'tk': 3, 271 | 'tl': 4, 272 | 'tn': 3, 273 | 'to': 0, 274 | 'tr': 0, 275 | 'ts': 3, 276 | 'tzm': 22, 277 | 'uk': 11, 278 | 'ur': 3, 279 | 've': 3, 280 | 'vi': 0, 281 | 'vun': 3, 282 | 'wa': 4, 283 | 'wae': 3, 284 | 'wo': 0, 285 | 'xh': 3, 286 | 'xog': 3, 287 | 'yo': 0, 288 | 'zh': 0, 289 | 'zu': 3 290 | }; 291 | 292 | // utility functions for plural rules methods 293 | function isIn(n, list) { 294 | return list.indexOf(n) !== -1; 295 | } 296 | function isBetween(n, start, end) { 297 | return typeof n === typeof start && start <= n && n <= end; 298 | } 299 | 300 | // list of all plural rules methods: 301 | // map an integer to the plural form name to use 302 | var pluralRules = { 303 | '0': function() { 304 | return 'other'; 305 | }, 306 | '1': function(n) { 307 | if ((isBetween((n % 100), 3, 10))) { 308 | return 'few'; 309 | } 310 | if (n === 0) { 311 | return 'zero'; 312 | } 313 | if ((isBetween((n % 100), 11, 99))) { 314 | return 'many'; 315 | } 316 | if (n === 2) { 317 | return 'two'; 318 | } 319 | if (n === 1) { 320 | return 'one'; 321 | } 322 | return 'other'; 323 | }, 324 | '2': function(n) { 325 | if (n !== 0 && (n % 10) === 0) { 326 | return 'many'; 327 | } 328 | if (n === 2) { 329 | return 'two'; 330 | } 331 | if (n === 1) { 332 | return 'one'; 333 | } 334 | return 'other'; 335 | }, 336 | '3': function(n) { 337 | if (n === 1) { 338 | return 'one'; 339 | } 340 | return 'other'; 341 | }, 342 | '4': function(n) { 343 | if ((isBetween(n, 0, 1))) { 344 | return 'one'; 345 | } 346 | return 'other'; 347 | }, 348 | '5': function(n) { 349 | if ((isBetween(n, 0, 2)) && n !== 2) { 350 | return 'one'; 351 | } 352 | return 'other'; 353 | }, 354 | '6': function(n) { 355 | if (n === 0) { 356 | return 'zero'; 357 | } 358 | if ((n % 10) === 1 && (n % 100) !== 11) { 359 | return 'one'; 360 | } 361 | return 'other'; 362 | }, 363 | '7': function(n) { 364 | if (n === 2) { 365 | return 'two'; 366 | } 367 | if (n === 1) { 368 | return 'one'; 369 | } 370 | return 'other'; 371 | }, 372 | '8': function(n) { 373 | if ((isBetween(n, 3, 6))) { 374 | return 'few'; 375 | } 376 | if ((isBetween(n, 7, 10))) { 377 | return 'many'; 378 | } 379 | if (n === 2) { 380 | return 'two'; 381 | } 382 | if (n === 1) { 383 | return 'one'; 384 | } 385 | return 'other'; 386 | }, 387 | '9': function(n) { 388 | if (n === 0 || n !== 1 && (isBetween((n % 100), 1, 19))) { 389 | return 'few'; 390 | } 391 | if (n === 1) { 392 | return 'one'; 393 | } 394 | return 'other'; 395 | }, 396 | '10': function(n) { 397 | if ((isBetween((n % 10), 2, 9)) && !(isBetween((n % 100), 11, 19))) { 398 | return 'few'; 399 | } 400 | if ((n % 10) === 1 && !(isBetween((n % 100), 11, 19))) { 401 | return 'one'; 402 | } 403 | return 'other'; 404 | }, 405 | '11': function(n) { 406 | if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) { 407 | return 'few'; 408 | } 409 | if ((n % 10) === 0 || 410 | (isBetween((n % 10), 5, 9)) || 411 | (isBetween((n % 100), 11, 14))) { 412 | return 'many'; 413 | } 414 | if ((n % 10) === 1 && (n % 100) !== 11) { 415 | return 'one'; 416 | } 417 | return 'other'; 418 | }, 419 | '12': function(n) { 420 | if ((isBetween(n, 2, 4))) { 421 | return 'few'; 422 | } 423 | if (n === 1) { 424 | return 'one'; 425 | } 426 | return 'other'; 427 | }, 428 | '13': function(n) { 429 | if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) { 430 | return 'few'; 431 | } 432 | if (n !== 1 && (isBetween((n % 10), 0, 1)) || 433 | (isBetween((n % 10), 5, 9)) || 434 | (isBetween((n % 100), 12, 14))) { 435 | return 'many'; 436 | } 437 | if (n === 1) { 438 | return 'one'; 439 | } 440 | return 'other'; 441 | }, 442 | '14': function(n) { 443 | if ((isBetween((n % 100), 3, 4))) { 444 | return 'few'; 445 | } 446 | if ((n % 100) === 2) { 447 | return 'two'; 448 | } 449 | if ((n % 100) === 1) { 450 | return 'one'; 451 | } 452 | return 'other'; 453 | }, 454 | '15': function(n) { 455 | if (n === 0 || (isBetween((n % 100), 2, 10))) { 456 | return 'few'; 457 | } 458 | if ((isBetween((n % 100), 11, 19))) { 459 | return 'many'; 460 | } 461 | if (n === 1) { 462 | return 'one'; 463 | } 464 | return 'other'; 465 | }, 466 | '16': function(n) { 467 | if ((n % 10) === 1 && n !== 11) { 468 | return 'one'; 469 | } 470 | return 'other'; 471 | }, 472 | '17': function(n) { 473 | if (n === 3) { 474 | return 'few'; 475 | } 476 | if (n === 0) { 477 | return 'zero'; 478 | } 479 | if (n === 6) { 480 | return 'many'; 481 | } 482 | if (n === 2) { 483 | return 'two'; 484 | } 485 | if (n === 1) { 486 | return 'one'; 487 | } 488 | return 'other'; 489 | }, 490 | '18': function(n) { 491 | if (n === 0) { 492 | return 'zero'; 493 | } 494 | if ((isBetween(n, 0, 2)) && n !== 0 && n !== 2) { 495 | return 'one'; 496 | } 497 | return 'other'; 498 | }, 499 | '19': function(n) { 500 | if ((isBetween(n, 2, 10))) { 501 | return 'few'; 502 | } 503 | if ((isBetween(n, 0, 1))) { 504 | return 'one'; 505 | } 506 | return 'other'; 507 | }, 508 | '20': function(n) { 509 | if ((isBetween((n % 10), 3, 4) || ((n % 10) === 9)) && !( 510 | isBetween((n % 100), 10, 19) || 511 | isBetween((n % 100), 70, 79) || 512 | isBetween((n % 100), 90, 99) 513 | )) { 514 | return 'few'; 515 | } 516 | if ((n % 1000000) === 0 && n !== 0) { 517 | return 'many'; 518 | } 519 | if ((n % 10) === 2 && !isIn((n % 100), [12, 72, 92])) { 520 | return 'two'; 521 | } 522 | if ((n % 10) === 1 && !isIn((n % 100), [11, 71, 91])) { 523 | return 'one'; 524 | } 525 | return 'other'; 526 | }, 527 | '21': function(n) { 528 | if (n === 0) { 529 | return 'zero'; 530 | } 531 | if (n === 1) { 532 | return 'one'; 533 | } 534 | return 'other'; 535 | }, 536 | '22': function(n) { 537 | if ((isBetween(n, 0, 1)) || (isBetween(n, 11, 99))) { 538 | return 'one'; 539 | } 540 | return 'other'; 541 | }, 542 | '23': function(n) { 543 | if ((isBetween((n % 10), 1, 2)) || (n % 20) === 0) { 544 | return 'one'; 545 | } 546 | return 'other'; 547 | }, 548 | '24': function(n) { 549 | if ((isBetween(n, 3, 10) || isBetween(n, 13, 19))) { 550 | return 'few'; 551 | } 552 | if (isIn(n, [2, 12])) { 553 | return 'two'; 554 | } 555 | if (isIn(n, [1, 11])) { 556 | return 'one'; 557 | } 558 | return 'other'; 559 | } 560 | }; 561 | 562 | // return a function that gives the plural form name for a given integer 563 | var index = locales2rules[lang.replace(/-.*$/, '')]; 564 | if (!(index in pluralRules)) { 565 | return function() { return 'other'; }; 566 | } 567 | return pluralRules[index]; 568 | } 569 | 570 | 571 | 572 | 573 | function PropertiesParser() { 574 | var parsePatterns = { 575 | comment: /^\s*#|^\s*$/, 576 | entity: /^([^=\s]+)\s*=\s*(.+)$/, 577 | multiline: /[^\\]\\$/, 578 | macro: /\{\[\s*(\w+)\(([^\)]*)\)\s*\]\}/i, 579 | unicode: /\\u([0-9a-fA-F]{1,4})/g, 580 | entries: /[\r\n]+/, 581 | controlChars: /\\([\\\n\r\t\b\f\{\}\"\'])/g 582 | }; 583 | 584 | this.parse = function (ctx, source) { 585 | var ast = Object.create(null); 586 | 587 | var entries = source.split(parsePatterns.entries); 588 | for (var i = 0; i < entries.length; i++) { 589 | var line = entries[i]; 590 | 591 | if (parsePatterns.comment.test(line)) { 592 | continue; 593 | } 594 | 595 | while (parsePatterns.multiline.test(line) && i < entries.length) { 596 | line = line.slice(0, -1) + entries[++i].trim(); 597 | } 598 | 599 | var entityMatch = line.match(parsePatterns.entity); 600 | if (entityMatch) { 601 | try { 602 | parseEntity(entityMatch[1], entityMatch[2], ast); 603 | } catch (e) { 604 | if (ctx) { 605 | ctx._emitter.emit('error', e); 606 | } else { 607 | throw e; 608 | } 609 | } 610 | } 611 | } 612 | return ast; 613 | }; 614 | 615 | function setEntityValue(id, attr, key, value, ast) { 616 | var obj = ast; 617 | var prop = id; 618 | 619 | if (attr) { 620 | if (!(id in obj)) { 621 | obj[id] = {}; 622 | } 623 | if (typeof(obj[id]) === 'string') { 624 | obj[id] = {'_': obj[id]}; 625 | } 626 | obj = obj[id]; 627 | prop = attr; 628 | } 629 | 630 | if (!key) { 631 | obj[prop] = value; 632 | return; 633 | } 634 | 635 | if (!(prop in obj)) { 636 | obj[prop] = {'_': {}}; 637 | } else if (typeof(obj[prop]) === 'string') { 638 | obj[prop] = {'_index': parseMacro(obj[prop]), '_': {}}; 639 | } 640 | obj[prop]._[key] = value; 641 | } 642 | 643 | function parseEntity(id, value, ast) { 644 | var name, key; 645 | 646 | var pos = id.indexOf('['); 647 | if (pos !== -1) { 648 | name = id.substr(0, pos); 649 | key = id.substring(pos + 1, id.length - 1); 650 | } else { 651 | name = id; 652 | key = null; 653 | } 654 | 655 | var nameElements = name.split('.'); 656 | 657 | if (nameElements.length > 2) { 658 | throw new Error('Error in ID: "' + name + '".' + 659 | ' Nested attributes are not supported.'); 660 | } 661 | 662 | var attr; 663 | if (nameElements.length > 1) { 664 | name = nameElements[0]; 665 | attr = nameElements[1]; 666 | } else { 667 | attr = null; 668 | } 669 | 670 | setEntityValue(name, attr, key, unescapeString(value), ast); 671 | } 672 | 673 | function unescapeControlCharacters(str) { 674 | return str.replace(parsePatterns.controlChars, '$1'); 675 | } 676 | 677 | function unescapeUnicode(str) { 678 | return str.replace(parsePatterns.unicode, function(match, token) { 679 | return unescape('%u' + '0000'.slice(token.length) + token); 680 | }); 681 | } 682 | 683 | function unescapeString(str) { 684 | if (str.lastIndexOf('\\') !== -1) { 685 | str = unescapeControlCharacters(str); 686 | } 687 | return unescapeUnicode(str); 688 | } 689 | 690 | function parseMacro(str) { 691 | var match = str.match(parsePatterns.macro); 692 | if (!match) { 693 | throw new L10nError('Malformed macro'); 694 | } 695 | return [match[1], match[2]]; 696 | } 697 | } 698 | 699 | 700 | 701 | var MAX_PLACEABLE_LENGTH = 2500; 702 | var MAX_PLACEABLES = 100; 703 | var rePlaceables = /\{\{\s*(.+?)\s*\}\}/g; 704 | 705 | function Entity(id, node, env) { 706 | this.id = id; 707 | this.env = env; 708 | // the dirty guard prevents cyclic or recursive references from other 709 | // Entities; see Entity.prototype.resolve 710 | this.dirty = false; 711 | if (typeof node === 'string') { 712 | this.value = node; 713 | } else { 714 | // it's either a hash or it has attrs, or both 715 | for (var key in node) { 716 | if (key[0] !== '_') { 717 | if (!this.attributes) { 718 | this.attributes = Object.create(null); 719 | } 720 | this.attributes[key] = new Entity(this.id + '.' + key, node[key], 721 | env); 722 | } 723 | } 724 | this.value = node._ || null; 725 | this.index = node._index; 726 | } 727 | } 728 | 729 | Entity.prototype.resolve = function E_resolve(ctxdata) { 730 | if (this.dirty) { 731 | return undefined; 732 | } 733 | 734 | this.dirty = true; 735 | var val; 736 | // if resolve fails, we want the exception to bubble up and stop the whole 737 | // resolving process; however, we still need to clean up the dirty flag 738 | try { 739 | val = resolve(ctxdata, this.env, this.value, this.index); 740 | } finally { 741 | this.dirty = false; 742 | } 743 | return val; 744 | }; 745 | 746 | Entity.prototype.toString = function E_toString(ctxdata) { 747 | try { 748 | return this.resolve(ctxdata); 749 | } catch (e) { 750 | return undefined; 751 | } 752 | }; 753 | 754 | Entity.prototype.valueOf = function E_valueOf(ctxdata) { 755 | if (!this.attributes) { 756 | return this.toString(ctxdata); 757 | } 758 | 759 | var entity = { 760 | value: this.toString(ctxdata), 761 | attributes: Object.create(null) 762 | }; 763 | 764 | for (var key in this.attributes) { 765 | /* jshint -W089 */ 766 | entity.attributes[key] = this.attributes[key].toString(ctxdata); 767 | } 768 | 769 | return entity; 770 | }; 771 | 772 | function subPlaceable(ctxdata, env, match, id) { 773 | if (ctxdata && ctxdata.hasOwnProperty(id) && 774 | (typeof ctxdata[id] === 'string' || 775 | (typeof ctxdata[id] === 'number' && !isNaN(ctxdata[id])))) { 776 | return ctxdata[id]; 777 | } 778 | 779 | // XXX: special case for Node.js where still: 780 | // '__proto__' in Object.create(null) => true 781 | if (id in env && id !== '__proto__') { 782 | if (!(env[id] instanceof Entity)) { 783 | env[id] = new Entity(id, env[id], env); 784 | } 785 | var value = env[id].resolve(ctxdata); 786 | if (typeof value === 'string') { 787 | // prevent Billion Laughs attacks 788 | if (value.length >= MAX_PLACEABLE_LENGTH) { 789 | throw new L10nError('Too many characters in placeable (' + 790 | value.length + ', max allowed is ' + 791 | MAX_PLACEABLE_LENGTH + ')'); 792 | } 793 | return value; 794 | } 795 | } 796 | return match; 797 | } 798 | 799 | function interpolate(ctxdata, env, str) { 800 | var placeablesCount = 0; 801 | var value = str.replace(rePlaceables, function(match, id) { 802 | // prevent Quadratic Blowup attacks 803 | if (placeablesCount++ >= MAX_PLACEABLES) { 804 | throw new L10nError('Too many placeables (' + placeablesCount + 805 | ', max allowed is ' + MAX_PLACEABLES + ')'); 806 | } 807 | return subPlaceable(ctxdata, env, match, id); 808 | }); 809 | placeablesCount = 0; 810 | return value; 811 | } 812 | 813 | function resolve(ctxdata, env, expr, index) { 814 | if (typeof expr === 'string') { 815 | return interpolate(ctxdata, env, expr); 816 | } 817 | 818 | if (typeof expr === 'boolean' || 819 | typeof expr === 'number' || 820 | !expr) { 821 | return expr; 822 | } 823 | 824 | // otherwise, it's a dict 825 | 826 | if (index && ctxdata && ctxdata.hasOwnProperty(index[1])) { 827 | var argValue = ctxdata[index[1]]; 828 | 829 | // special cases for zero, one, two if they are defined on the hash 830 | if (argValue === 0 && 'zero' in expr) { 831 | return resolve(ctxdata, env, expr.zero); 832 | } 833 | if (argValue === 1 && 'one' in expr) { 834 | return resolve(ctxdata, env, expr.one); 835 | } 836 | if (argValue === 2 && 'two' in expr) { 837 | return resolve(ctxdata, env, expr.two); 838 | } 839 | 840 | var selector = env.__plural(argValue); 841 | if (expr.hasOwnProperty(selector)) { 842 | return resolve(ctxdata, env, expr[selector]); 843 | } 844 | } 845 | 846 | // if there was no index or no selector was found, try 'other' 847 | if ('other' in expr) { 848 | return resolve(ctxdata, env, expr.other); 849 | } 850 | 851 | return undefined; 852 | } 853 | 854 | function compile(env, ast) { 855 | /* jshint -W089 */ 856 | env = env || Object.create(null); 857 | for (var id in ast) { 858 | env[id] = new Entity(id, ast[id], env); 859 | } 860 | return env; 861 | } 862 | 863 | 864 | 865 | var propertiesParser = null; 866 | 867 | function Locale(id, ctx) { 868 | this.id = id; 869 | this.ctx = ctx; 870 | this.isReady = false; 871 | this.entries = Object.create(null); 872 | this.entries.__plural = getPluralRule(id); 873 | } 874 | 875 | Locale.prototype.getEntry = function L_getEntry(id) { 876 | /* jshint -W093 */ 877 | 878 | var entries = this.entries; 879 | 880 | if (!(id in entries)) { 881 | return undefined; 882 | } 883 | 884 | if (entries[id] instanceof Entity) { 885 | return entries[id]; 886 | } 887 | 888 | return entries[id] = new Entity(id, entries[id], entries); 889 | }; 890 | 891 | Locale.prototype.build = function L_build(callback) { 892 | var sync = !callback; 893 | var ctx = this.ctx; 894 | var self = this; 895 | 896 | var l10nLoads = ctx.resLinks.length; 897 | 898 | function onL10nLoaded(err) { 899 | if (err) { 900 | ctx._emitter.emit('error', err); 901 | } 902 | if (--l10nLoads <= 0) { 903 | self.isReady = true; 904 | if (callback) { 905 | callback(); 906 | } 907 | } 908 | } 909 | 910 | if (l10nLoads === 0) { 911 | onL10nLoaded(); 912 | return; 913 | } 914 | 915 | function onJSONLoaded(err, json) { 916 | if (!err && json) { 917 | self.addAST(json); 918 | } 919 | onL10nLoaded(err); 920 | } 921 | 922 | function onPropLoaded(err, source) { 923 | if (!err && source) { 924 | if (!propertiesParser) { 925 | propertiesParser = new PropertiesParser(); 926 | } 927 | var ast = propertiesParser.parse(ctx, source); 928 | self.addAST(ast); 929 | } 930 | onL10nLoaded(err); 931 | } 932 | 933 | 934 | for (var i = 0; i < ctx.resLinks.length; i++) { 935 | var path = ctx.resLinks[i].replace('{{locale}}', this.id); 936 | var type = path.substr(path.lastIndexOf('.') + 1); 937 | 938 | switch (type) { 939 | case 'json': 940 | io.loadJSON(path, onJSONLoaded, sync); 941 | break; 942 | case 'properties': 943 | io.load(path, onPropLoaded, sync); 944 | break; 945 | } 946 | } 947 | }; 948 | 949 | Locale.prototype.addAST = function(ast) { 950 | /* jshint -W089 */ 951 | for (var id in ast) { 952 | this.entries[id] = ast[id]; 953 | } 954 | }; 955 | 956 | Locale.prototype.getEntity = function(id, ctxdata) { 957 | var entry = this.getEntry(id); 958 | 959 | if (!entry) { 960 | return null; 961 | } 962 | return entry.valueOf(ctxdata); 963 | }; 964 | 965 | 966 | 967 | function Context(id) { 968 | 969 | this.id = id; 970 | this.isReady = false; 971 | this.isLoading = false; 972 | 973 | this.supportedLocales = []; 974 | this.resLinks = []; 975 | this.locales = {}; 976 | 977 | this._emitter = new EventEmitter(); 978 | 979 | 980 | // Getting translations 981 | 982 | function getWithFallback(id) { 983 | /* jshint -W084 */ 984 | 985 | if (!this.isReady) { 986 | throw new L10nError('Context not ready'); 987 | } 988 | 989 | var cur = 0; 990 | var loc; 991 | var locale; 992 | while (loc = this.supportedLocales[cur]) { 993 | locale = this.getLocale(loc); 994 | if (!locale.isReady) { 995 | // build without callback, synchronously 996 | locale.build(null); 997 | } 998 | var entry = locale.getEntry(id); 999 | if (entry === undefined) { 1000 | cur++; 1001 | warning.call(this, new L10nError(id + ' not found in ' + loc, id, 1002 | loc)); 1003 | continue; 1004 | } 1005 | return entry; 1006 | } 1007 | 1008 | error.call(this, new L10nError(id + ' not found', id)); 1009 | return null; 1010 | } 1011 | 1012 | this.get = function get(id, ctxdata) { 1013 | var entry = getWithFallback.call(this, id); 1014 | if (entry === null) { 1015 | return ''; 1016 | } 1017 | 1018 | return entry.toString(ctxdata) || ''; 1019 | }; 1020 | 1021 | this.getEntity = function getEntity(id, ctxdata) { 1022 | var entry = getWithFallback.call(this, id); 1023 | if (entry === null) { 1024 | return null; 1025 | } 1026 | 1027 | return entry.valueOf(ctxdata); 1028 | }; 1029 | 1030 | 1031 | // Helpers 1032 | 1033 | this.getLocale = function getLocale(code) { 1034 | /* jshint -W093 */ 1035 | 1036 | var locales = this.locales; 1037 | if (locales[code]) { 1038 | return locales[code]; 1039 | } 1040 | 1041 | return locales[code] = new Locale(code, this); 1042 | }; 1043 | 1044 | 1045 | // Getting ready 1046 | 1047 | function negotiate(available, requested, defaultLocale) { 1048 | if (available.indexOf(requested[0]) === -1 || 1049 | requested[0] === defaultLocale) { 1050 | return [defaultLocale]; 1051 | } else { 1052 | return [requested[0], defaultLocale]; 1053 | } 1054 | } 1055 | 1056 | function freeze(supported) { 1057 | var locale = this.getLocale(supported[0]); 1058 | if (locale.isReady) { 1059 | setReady.call(this, supported); 1060 | } else { 1061 | locale.build(setReady.bind(this, supported)); 1062 | } 1063 | } 1064 | 1065 | function setReady(supported) { 1066 | this.supportedLocales = supported; 1067 | this.isReady = true; 1068 | this._emitter.emit('ready'); 1069 | } 1070 | 1071 | this.requestLocales = function requestLocales() { 1072 | if (this.isLoading && !this.isReady) { 1073 | throw new L10nError('Context not ready'); 1074 | } 1075 | 1076 | this.isLoading = true; 1077 | var requested = Array.prototype.slice.call(arguments); 1078 | 1079 | var supported = negotiate(requested.concat('en-US'), requested, 'en-US'); 1080 | freeze.call(this, supported); 1081 | }; 1082 | 1083 | 1084 | // Events 1085 | 1086 | this.addEventListener = function addEventListener(type, listener) { 1087 | this._emitter.addEventListener(type, listener); 1088 | }; 1089 | 1090 | this.removeEventListener = function removeEventListener(type, listener) { 1091 | this._emitter.removeEventListener(type, listener); 1092 | }; 1093 | 1094 | this.ready = function ready(callback) { 1095 | if (this.isReady) { 1096 | setTimeout(callback); 1097 | } 1098 | this.addEventListener('ready', callback); 1099 | }; 1100 | 1101 | this.once = function once(callback) { 1102 | /* jshint -W068 */ 1103 | if (this.isReady) { 1104 | setTimeout(callback); 1105 | return; 1106 | } 1107 | 1108 | var callAndRemove = (function() { 1109 | this.removeEventListener('ready', callAndRemove); 1110 | callback(); 1111 | }).bind(this); 1112 | this.addEventListener('ready', callAndRemove); 1113 | }; 1114 | 1115 | 1116 | // Errors 1117 | 1118 | function warning(e) { 1119 | this._emitter.emit('warning', e); 1120 | return e; 1121 | } 1122 | 1123 | function error(e) { 1124 | this._emitter.emit('error', e); 1125 | return e; 1126 | } 1127 | } 1128 | 1129 | 1130 | 1131 | var DEBUG = false; 1132 | var isPretranslated = false; 1133 | var rtlList = ['ar', 'he', 'fa', 'ps', 'qps-plocm', 'ur']; 1134 | var nodeObserver = false; 1135 | 1136 | var moConfig = { 1137 | attributes: true, 1138 | characterData: false, 1139 | childList: true, 1140 | subtree: true, 1141 | attributeFilter: ['data-l10n-id', 'data-l10n-args'] 1142 | }; 1143 | 1144 | // Public API 1145 | 1146 | navigator.mozL10n = { 1147 | ctx: new Context(), 1148 | get: function get(id, ctxdata) { 1149 | return navigator.mozL10n.ctx.get(id, ctxdata); 1150 | }, 1151 | localize: function localize(element, id, args) { 1152 | return localizeElement.call(navigator.mozL10n, element, id, args); 1153 | }, 1154 | translate: function () { 1155 | // XXX: Remove after removing obsolete calls. Bugs 992473 and 1020136 1156 | }, 1157 | translateFragment: function (fragment) { 1158 | return translateFragment.call(navigator.mozL10n, fragment); 1159 | }, 1160 | setAttributes: setL10nAttributes, 1161 | getAttributes: getL10nAttributes, 1162 | ready: function ready(callback) { 1163 | return navigator.mozL10n.ctx.ready(callback); 1164 | }, 1165 | once: function once(callback) { 1166 | return navigator.mozL10n.ctx.once(callback); 1167 | }, 1168 | get readyState() { 1169 | return navigator.mozL10n.ctx.isReady ? 'complete' : 'loading'; 1170 | }, 1171 | language: { 1172 | set code(lang) { 1173 | navigator.mozL10n.ctx.requestLocales(lang); 1174 | }, 1175 | get code() { 1176 | return navigator.mozL10n.ctx.supportedLocales[0]; 1177 | }, 1178 | get direction() { 1179 | return getDirection(navigator.mozL10n.ctx.supportedLocales[0]); 1180 | } 1181 | }, 1182 | _getInternalAPI: function() { 1183 | return { 1184 | Error: L10nError, 1185 | Context: Context, 1186 | Locale: Locale, 1187 | Entity: Entity, 1188 | getPluralRule: getPluralRule, 1189 | rePlaceables: rePlaceables, 1190 | getTranslatableChildren: getTranslatableChildren, 1191 | translateDocument: translateDocument, 1192 | loadINI: loadINI, 1193 | fireLocalizedEvent: fireLocalizedEvent, 1194 | PropertiesParser: PropertiesParser, 1195 | compile: compile 1196 | }; 1197 | } 1198 | }; 1199 | 1200 | navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n)); 1201 | 1202 | if (DEBUG) { 1203 | navigator.mozL10n.ctx.addEventListener('error', console.error); 1204 | navigator.mozL10n.ctx.addEventListener('warning', console.warn); 1205 | } 1206 | 1207 | function getDirection(lang) { 1208 | return (rtlList.indexOf(lang) >= 0) ? 'rtl' : 'ltr'; 1209 | } 1210 | 1211 | var readyStates = { 1212 | 'loading': 0, 1213 | 'interactive': 1, 1214 | 'complete': 2 1215 | }; 1216 | 1217 | function waitFor(state, callback) { 1218 | state = readyStates[state]; 1219 | if (readyStates[document.readyState] >= state) { 1220 | callback(); 1221 | return; 1222 | } 1223 | 1224 | document.addEventListener('readystatechange', function l10n_onrsc() { 1225 | if (readyStates[document.readyState] >= state) { 1226 | document.removeEventListener('readystatechange', l10n_onrsc); 1227 | callback(); 1228 | } 1229 | }); 1230 | } 1231 | 1232 | if (window.document) { 1233 | isPretranslated = (document.documentElement.lang === navigator.language); 1234 | 1235 | // this is a special case for netError bug; see https://bugzil.la/444165 1236 | if (document.documentElement.dataset.noCompleteBug) { 1237 | pretranslate.call(navigator.mozL10n); 1238 | return; 1239 | } 1240 | 1241 | 1242 | if (isPretranslated) { 1243 | waitFor('interactive', function() { 1244 | window.setTimeout(initResources.bind(navigator.mozL10n)); 1245 | }); 1246 | } else { 1247 | if (document.readyState === 'complete') { 1248 | window.setTimeout(initResources.bind(navigator.mozL10n)); 1249 | } else { 1250 | waitFor('interactive', pretranslate.bind(navigator.mozL10n)); 1251 | } 1252 | } 1253 | 1254 | } 1255 | 1256 | function pretranslate() { 1257 | /* jshint -W068 */ 1258 | if (inlineLocalization.call(this)) { 1259 | waitFor('interactive', (function() { 1260 | window.setTimeout(initResources.bind(this)); 1261 | }).bind(this)); 1262 | } else { 1263 | initResources.call(this); 1264 | } 1265 | } 1266 | 1267 | function inlineLocalization() { 1268 | var script = document.documentElement 1269 | .querySelector('script[type="application/l10n"]' + 1270 | '[lang="' + navigator.language + '"]'); 1271 | if (!script) { 1272 | return false; 1273 | } 1274 | 1275 | var locale = this.ctx.getLocale(navigator.language); 1276 | // the inline localization is happenning very early, when the ctx is not 1277 | // yet ready and when the resources haven't been downloaded yet; add the 1278 | // inlined JSON directly to the current locale 1279 | locale.addAST(JSON.parse(script.innerHTML)); 1280 | // localize the visible DOM 1281 | var l10n = { 1282 | ctx: locale, 1283 | language: { 1284 | code: locale.id, 1285 | direction: getDirection(locale.id) 1286 | } 1287 | }; 1288 | translateDocument.call(l10n); 1289 | 1290 | // the visible DOM is now pretranslated 1291 | isPretranslated = true; 1292 | return true; 1293 | } 1294 | 1295 | function initResources() { 1296 | var resLinks = document.head 1297 | .querySelectorAll('link[type="application/l10n"]'); 1298 | var iniLinks = []; 1299 | 1300 | for (var i = 0; i < resLinks.length; i++) { 1301 | var link = resLinks[i]; 1302 | var url = link.getAttribute('href'); 1303 | var type = url.substr(url.lastIndexOf('.') + 1); 1304 | if (type === 'ini') { 1305 | iniLinks.push(url); 1306 | } 1307 | this.ctx.resLinks.push(url); 1308 | } 1309 | 1310 | var iniLoads = iniLinks.length; 1311 | if (iniLoads === 0) { 1312 | initLocale.call(this); 1313 | return; 1314 | } 1315 | 1316 | function onIniLoaded(err) { 1317 | if (err) { 1318 | this.ctx._emitter.emit('error', err); 1319 | } 1320 | if (--iniLoads === 0) { 1321 | initLocale.call(this); 1322 | } 1323 | } 1324 | 1325 | for (i = 0; i < iniLinks.length; i++) { 1326 | loadINI.call(this, iniLinks[i], onIniLoaded.bind(this)); 1327 | } 1328 | } 1329 | 1330 | function initLocale() { 1331 | this.ctx.requestLocales(navigator.language); 1332 | window.addEventListener('languagechange', function l10n_langchange() { 1333 | navigator.mozL10n.language.code = navigator.language; 1334 | }); 1335 | } 1336 | 1337 | function localizeMutations(mutations) { 1338 | var mutation; 1339 | 1340 | for (var i = 0; i < mutations.length; i++) { 1341 | mutation = mutations[i]; 1342 | if (mutation.type === 'childList') { 1343 | var addedNode; 1344 | 1345 | for (var j = 0; j < mutation.addedNodes.length; j++) { 1346 | addedNode = mutation.addedNodes[j]; 1347 | 1348 | if (addedNode.nodeType !== Node.ELEMENT_NODE) { 1349 | continue; 1350 | } 1351 | 1352 | if (addedNode.childElementCount) { 1353 | translateFragment.call(this, addedNode); 1354 | } else if (addedNode.hasAttribute('data-l10n-id')) { 1355 | translateElement.call(this, addedNode); 1356 | } 1357 | } 1358 | } 1359 | 1360 | if (mutation.type === 'attributes') { 1361 | translateElement.call(this, mutation.target); 1362 | } 1363 | } 1364 | } 1365 | 1366 | function onMutations(mutations, self) { 1367 | self.disconnect(); 1368 | localizeMutations.call(this, mutations); 1369 | self.observe(document, moConfig); 1370 | } 1371 | 1372 | function onReady() { 1373 | if (!isPretranslated) { 1374 | translateDocument.call(this); 1375 | } 1376 | isPretranslated = false; 1377 | 1378 | if (!nodeObserver) { 1379 | nodeObserver = new MutationObserver(onMutations.bind(this)); 1380 | nodeObserver.observe(document, moConfig); 1381 | } 1382 | 1383 | fireLocalizedEvent.call(this); 1384 | } 1385 | 1386 | function fireLocalizedEvent() { 1387 | var event = new CustomEvent('localized', { 1388 | 'bubbles': false, 1389 | 'cancelable': false, 1390 | 'detail': { 1391 | 'language': this.ctx.supportedLocales[0] 1392 | } 1393 | }); 1394 | window.dispatchEvent(event); 1395 | } 1396 | 1397 | /* jshint -W104 */ 1398 | 1399 | function loadINI(url, callback) { 1400 | var ctx = this.ctx; 1401 | io.load(url, function(err, source) { 1402 | var pos = ctx.resLinks.indexOf(url); 1403 | 1404 | if (err) { 1405 | // remove the ini link from resLinks 1406 | ctx.resLinks.splice(pos, 1); 1407 | return callback(err); 1408 | } 1409 | 1410 | if (!source) { 1411 | ctx.resLinks.splice(pos, 1); 1412 | return callback(new Error('Empty file: ' + url)); 1413 | } 1414 | 1415 | var patterns = parseINI(source, url).resources.map(function(x) { 1416 | return x.replace('en-US', '{{locale}}'); 1417 | }); 1418 | ctx.resLinks.splice.apply(ctx.resLinks, [pos, 1].concat(patterns)); 1419 | callback(); 1420 | }); 1421 | } 1422 | 1423 | function relativePath(baseUrl, url) { 1424 | if (url[0] === '/') { 1425 | return url; 1426 | } 1427 | 1428 | var dirs = baseUrl.split('/') 1429 | .slice(0, -1) 1430 | .concat(url.split('/')) 1431 | .filter(function(path) { 1432 | return path !== '.'; 1433 | }); 1434 | 1435 | return dirs.join('/'); 1436 | } 1437 | 1438 | var iniPatterns = { 1439 | 'section': /^\s*\[(.*)\]\s*$/, 1440 | 'import': /^\s*@import\s+url\((.*)\)\s*$/i, 1441 | 'entry': /[\r\n]+/ 1442 | }; 1443 | 1444 | function parseINI(source, iniPath) { 1445 | var entries = source.split(iniPatterns.entry); 1446 | var locales = ['en-US']; 1447 | var genericSection = true; 1448 | var uris = []; 1449 | var match; 1450 | 1451 | for (var i = 0; i < entries.length; i++) { 1452 | var line = entries[i]; 1453 | // we only care about en-US resources 1454 | if (genericSection && iniPatterns['import'].test(line)) { 1455 | match = iniPatterns['import'].exec(line); 1456 | var uri = relativePath(iniPath, match[1]); 1457 | uris.push(uri); 1458 | continue; 1459 | } 1460 | 1461 | // but we need the list of all locales in the ini, too 1462 | if (iniPatterns.section.test(line)) { 1463 | genericSection = false; 1464 | match = iniPatterns.section.exec(line); 1465 | locales.push(match[1]); 1466 | } 1467 | } 1468 | return { 1469 | locales: locales, 1470 | resources: uris 1471 | }; 1472 | } 1473 | 1474 | /* jshint -W104 */ 1475 | 1476 | function translateDocument() { 1477 | document.documentElement.lang = this.language.code; 1478 | document.documentElement.dir = this.language.direction; 1479 | translateFragment.call(this, document.documentElement); 1480 | } 1481 | 1482 | function translateFragment(element) { 1483 | if (element.hasAttribute('data-l10n-id')) { 1484 | translateElement.call(this, element); 1485 | } 1486 | 1487 | var nodes = getTranslatableChildren(element); 1488 | for (var i = 0; i < nodes.length; i++ ) { 1489 | translateElement.call(this, nodes[i]); 1490 | } 1491 | } 1492 | 1493 | function setL10nAttributes(element, id, args) { 1494 | element.setAttribute('data-l10n-id', id); 1495 | if (args) { 1496 | element.setAttribute('data-l10n-args', JSON.stringify(args)); 1497 | } 1498 | } 1499 | 1500 | function getL10nAttributes(element) { 1501 | return { 1502 | id: element.getAttribute('data-l10n-id'), 1503 | args: JSON.parse(element.getAttribute('data-l10n-args')) 1504 | }; 1505 | } 1506 | 1507 | function getTranslatableChildren(element) { 1508 | return element ? element.querySelectorAll('*[data-l10n-id]') : []; 1509 | } 1510 | 1511 | function localizeElement(element, id, args) { 1512 | if (!id) { 1513 | element.removeAttribute('data-l10n-id'); 1514 | element.removeAttribute('data-l10n-args'); 1515 | setTextContent(element, ''); 1516 | return; 1517 | } 1518 | 1519 | element.setAttribute('data-l10n-id', id); 1520 | if (args && typeof args === 'object') { 1521 | element.setAttribute('data-l10n-args', JSON.stringify(args)); 1522 | } else { 1523 | element.removeAttribute('data-l10n-args'); 1524 | } 1525 | } 1526 | 1527 | function translateElement(element) { 1528 | var l10n = getL10nAttributes(element); 1529 | 1530 | if (!l10n.id) { 1531 | return false; 1532 | } 1533 | 1534 | var entity = this.ctx.getEntity(l10n.id, l10n.args); 1535 | 1536 | if (!entity) { 1537 | return false; 1538 | } 1539 | 1540 | if (typeof entity === 'string') { 1541 | setTextContent(element, entity); 1542 | return true; 1543 | } 1544 | 1545 | if (entity.value) { 1546 | setTextContent(element, entity.value); 1547 | } 1548 | 1549 | for (var key in entity.attributes) { 1550 | var attr = entity.attributes[key]; 1551 | if (key === 'ariaLabel') { 1552 | element.setAttribute('aria-label', attr); 1553 | } else if (key === 'innerHTML') { 1554 | // XXX: to be removed once bug 994357 lands 1555 | element.innerHTML = attr; 1556 | } else { 1557 | element.setAttribute(key, attr); 1558 | } 1559 | } 1560 | 1561 | return true; 1562 | } 1563 | 1564 | function setTextContent(element, text) { 1565 | // standard case: no element children 1566 | if (!element.firstElementChild) { 1567 | element.textContent = text; 1568 | return; 1569 | } 1570 | 1571 | // this element has element children: replace the content of the first 1572 | // (non-blank) child textNode and clear other child textNodes 1573 | var found = false; 1574 | var reNotBlank = /\S/; 1575 | for (var child = element.firstChild; child; child = child.nextSibling) { 1576 | if (child.nodeType === Node.TEXT_NODE && 1577 | reNotBlank.test(child.nodeValue)) { 1578 | if (found) { 1579 | child.nodeValue = ''; 1580 | } else { 1581 | child.nodeValue = text; 1582 | found = true; 1583 | } 1584 | } 1585 | } 1586 | // if no (non-empty) textNode is found, insert a textNode before the 1587 | // element's first child. 1588 | if (!found) { 1589 | element.insertBefore(document.createTextNode(text), element.firstChild); 1590 | } 1591 | } 1592 | 1593 | })(this); --------------------------------------------------------------------------------