├── .bowerrc ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── bower_modules ├── backbone │ └── backbone.js ├── jquery │ └── jquery.js ├── requirejs-text │ └── text.js ├── requirejs │ └── require.js ├── sinonjs │ └── sinon.js └── underscore │ └── underscore.js ├── build ├── config.gypi └── tasks │ └── build.js ├── docs ├── app.js ├── basics.html ├── building_your_xf_app_for_testing_and_production.html ├── buttons.html ├── collection.html ├── component.html ├── component_creation.html ├── creation_of_custom_xframework_build.html ├── data │ ├── basics.html │ ├── building_your_xf_app_for_testing_and_production.html │ ├── buttons.html │ ├── collection.html │ ├── component.html │ ├── component_creation.html │ ├── creation_of_custom_xframework_build.html │ ├── footer.html │ ├── form_elements.html │ ├── header.html │ ├── installing_xframework_generator.html │ ├── list_of_built-in_events.html │ ├── listview.html │ ├── model.html │ ├── supported_platforms_and_browsers.html │ ├── tabs.html │ ├── the_idea_behind.html │ ├── updating_xf_and_dependencies.html │ ├── view.html │ ├── what_is_xframework_.html │ ├── xf_app.html │ ├── xf_device.html │ ├── xf_pages.html │ ├── xf_router.html │ ├── xf_settings.html │ ├── xf_source_modules.html │ ├── xf_storage.html │ ├── xf_touch.html │ ├── xf_utils.html │ ├── xf_zepto_support_js.html │ └── your_first_xf_web_app.html ├── docs.css ├── footer.html ├── form_elements.html ├── header.html ├── installing_xframework_generator.html ├── js │ └── components │ │ ├── home.js │ │ └── menu.js ├── list_of_built-in_events.html ├── listview.html ├── mocks │ └── menu.json ├── model.html ├── supported_platforms_and_browsers.html ├── tabs.html ├── the_idea_behind.html ├── tmpl │ ├── mobile │ │ ├── header.tmpl │ │ ├── home.tmpl │ │ └── menu.tmpl │ └── tablet │ │ ├── header.tmpl │ │ ├── home.tmpl │ │ └── menu.tmpl ├── updating_xf_and_dependencies.html ├── view.html ├── what_is_xframework_.html ├── xf_app.html ├── xf_device.html ├── xf_pages.html ├── xf_router.html ├── xf_settings.html ├── xf_source_modules.html ├── xf_storage.html ├── xf_touch.html ├── xf_utils.html ├── xf_zepto_support_js.html └── your_first_xf_web_app.html ├── files ├── js ├── xf.js └── xf.min.js ├── mocks └── menu.json ├── package.json ├── styles ├── fonts │ ├── entypo-social.eot │ ├── entypo-social.svg │ ├── entypo-social.ttf │ ├── entypo-social.woff │ ├── entypo.eot │ ├── entypo.svg │ ├── entypo.ttf │ └── entypo.woff ├── lesshat.less ├── xf.animations.less ├── xf.buttons.less ├── xf.css ├── xf.dialog.less ├── xf.footer.less ├── xf.forms.less ├── xf.header.less ├── xf.icons.less ├── xf.layout.less ├── xf.less ├── xf.list.less ├── xf.loader.less ├── xf.min.css ├── xf.mixins.less ├── xf.pages.less ├── xf.reset.less ├── xf.tabs.less ├── xf.theme.dark.less ├── xf.theme.less ├── xf.type.less ├── xf.utilities.less ├── xf.variables.less └── xf.variables.theme.dark.less ├── test ├── components │ └── test.js ├── index.html ├── lib │ ├── qunit-1.12.0.css │ ├── qunit-1.12.0.js │ └── run-qunit.js ├── main.js ├── sample-feed.xml ├── src │ ├── app │ │ └── start.js │ ├── dom │ │ ├── data.html │ │ └── dom.js │ ├── xf.app.js │ ├── xf.collection.js │ ├── xf.component.js │ ├── xf.core.js │ ├── xf.device.js │ ├── xf.model.js │ ├── xf.pages.js │ ├── xf.router.js │ ├── xf.settings.js │ ├── xf.storage.js │ ├── xf.touch.js │ └── xf.ui.js ├── test-files.js ├── test.html ├── test.json ├── test.tmpl └── ui │ ├── xf.ui.button.js │ ├── xf.ui.dialog.js │ ├── xf.ui.fieldset.js │ └── xf.ui.list.js └── xf ├── src ├── app │ └── start.js ├── dom │ └── dom.js ├── xf.app.js ├── xf.collection.js ├── xf.component.js ├── xf.core.js ├── xf.device.js ├── xf.framework.js ├── xf.log.js ├── xf.model.js ├── xf.pages.js ├── xf.router.js ├── xf.settings.js ├── xf.storage.js ├── xf.touch.js ├── xf.ui.js ├── xf.utils.js ├── xf.view.js └── xf.zepto.support.js └── ui ├── xf.ui.button.js ├── xf.ui.checkboxradio.js ├── xf.ui.core.js ├── xf.ui.fieldset.js ├── xf.ui.footer.js ├── xf.ui.header.js ├── xf.ui.list.js ├── xf.ui.loader.js ├── xf.ui.popup.js ├── xf.ui.scrollable.js ├── xf.ui.slidemenu.js ├── xf.ui.tabs.js └── xf.ui.textinput.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "js/lib/" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea/.name 3 | 4 | .idea/codeStyleSettings.xml 5 | 6 | *.xml 7 | 8 | *.iml 9 | 10 | data.json 11 | 12 | docs.js 13 | 14 | index.html 15 | 16 | js/app.js 17 | 18 | js/appx.js 19 | 20 | js/collections/customCollection.js 21 | 22 | js/components/component1.js 23 | 24 | js/components/root.js 25 | 26 | js/index.js 27 | 28 | js/models/customModel.js 29 | 30 | styles/sec.css 31 | 32 | tmpl/desktop/comments.tmpl 33 | 34 | tmpl/desktop/favourites.tmpl 35 | 36 | tmpl/desktop/feedback.tmpl 37 | 38 | tmpl/desktop/home.tmpl 39 | 40 | tmpl/desktop/root.tmpl 41 | 42 | tmpl/desktop/presentation.tmpl 43 | 44 | tmpl/desktop/speaker.tmpl 45 | 46 | tmpl/desktop/speakers.tmpl 47 | 48 | tmpl/mobile/comments.tmpl 49 | 50 | tmpl/mobile/favourites.tmpl 51 | 52 | tmpl/mobile/feedback.tmpl 53 | 54 | tmpl/mobile/presentation.tmpl 55 | 56 | tmpl/mobile/home.tmpl 57 | 58 | tmpl/mobile/speaker.tmpl 59 | 60 | tmpl/mobile/speakers.tmpl 61 | 62 | tmpl/phone/root.tmpl 63 | 64 | tmpl/tablet/root.tmpl 65 | .DS_Store 66 | npm-debug.log 67 | 68 | js/lib 69 | 70 | index2.html 71 | 72 | xf/src/xf.storage-w-collections.js 73 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "jasmine": false, 4 | "spyOn": false, 5 | "it": false, 6 | "console": false, 7 | "describe": false, 8 | "expect": false, 9 | "beforeEach": false, 10 | "waits": false, 11 | "waitsFor": false, 12 | "runs": false 13 | }, 14 | 15 | "node" : true, 16 | "es5" : false, 17 | "expr" : false, 18 | "browser" : true, 19 | "boss" : false, 20 | "curly": false, 21 | "debug": true, 22 | "devel": true, 23 | "eqeqeq": false, 24 | "evil": true, 25 | "forin": false, 26 | "immed": true, 27 | "laxbreak": false, 28 | "newcap": false, 29 | "noarg": true, 30 | "noempty": false, 31 | "nonew": false, 32 | "nomen": false, 33 | "onevar": false, 34 | "plusplus": false, 35 | "regexp": false, 36 | "undef": false, 37 | "sub": true, 38 | "strict": false, 39 | "white": false, 40 | "unused": false 41 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | 5 | before_script: 6 | - "export DISPLAY=:99.0" 7 | - "sh -e /etc/init.d/xvfb start" 8 | - npm install nws -g 9 | - nws -p 9292 & 10 | - sleep 5 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013–2014, EPAM Systems, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the EPAM Systems, Inc. nor the names of its contributors 13 | may be used to endorse or promote products derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 19 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xframework", 3 | "version": "0.9.1", 4 | "devDependencies": { 5 | "jquery": "latest", 6 | "backbone": "latest", 7 | "underscore": "latest", 8 | "requirejs": "latest", 9 | "requirejs-text": "latest", 10 | "sinonjs": "latest", 11 | "xframework": "https://github.com/epam/xframework.git" 12 | }, 13 | "homepage": "http://xframeworkjs.org", 14 | "authors": [ 15 | "EPAM" 16 | ], 17 | "main": "js/xf.js", 18 | "license": "BSD", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_modules", 23 | ".", 24 | "test" 25 | ], 26 | "exportsOverride": { 27 | "backbone": { 28 | ".": "backbone.js" 29 | }, 30 | "jquery": { 31 | ".": "jquery.js" 32 | }, 33 | "underscore": { 34 | ".": "underscore.js" 35 | }, 36 | "requirejs": { 37 | ".": "require.js" 38 | }, 39 | "requirejs-text": { 40 | ".": "text.js" 41 | }, 42 | "sinonjs": { 43 | ".": "sinon.js" 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /build/config.gypi: -------------------------------------------------------------------------------- 1 | # Do not edit. File was generated by node-gyp's "configure" step 2 | { 3 | "target_defaults": { 4 | "cflags": [], 5 | "default_configuration": "Release", 6 | "defines": [], 7 | "include_dirs": [], 8 | "libraries": [] 9 | }, 10 | "variables": { 11 | "clang": 1, 12 | "host_arch": "x64", 13 | "node_install_npm": "true", 14 | "node_prefix": "/", 15 | "node_shared_cares": "false", 16 | "node_shared_http_parser": "false", 17 | "node_shared_libuv": "false", 18 | "node_shared_openssl": "false", 19 | "node_shared_v8": "false", 20 | "node_shared_zlib": "false", 21 | "node_tag": "", 22 | "node_unsafe_optimizations": 0, 23 | "node_use_dtrace": "true", 24 | "node_use_etw": "false", 25 | "node_use_openssl": "true", 26 | "node_use_perfctr": "false", 27 | "python": "/usr/bin/python", 28 | "target_arch": "x64", 29 | "v8_enable_gdbjit": 0, 30 | "v8_no_strict_aliasing": 1, 31 | "v8_use_snapshot": "false", 32 | "nodedir": "/Users/larchanka/.node-gyp/0.10.15", 33 | "copy_dev_lib": "true", 34 | "standalone_static_library": 1 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/app.js: -------------------------------------------------------------------------------- 1 | define(['../xf/src/xf.framework'], function (XF) { 2 | 3 | return XF.App.extend({ 4 | initialize: function () { 5 | XF.ui.loader.show(); 6 | XF.once('component:menu:constructed', XF.ui.loader.hide); 7 | } 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /docs/basics.html: -------------------------------------------------------------------------------- 1 |
XFramework UI element is 'an extended version of Document Object' or the another parallel could be done with jQuery Plugin. It fills the gap with Rich UI Elements for all the browsers. It means that XFramework will parse your HTML and add some markup to make UI controls user- and developer-friendly.
4 | 5 |Each UI element has a simple markup that will be enhanced into the rich element.
6 | 7 |<ul data-role="listview">
8 | <li data-role="divider">A</li>
9 | <li>
10 | <h2>Header</h2>
11 | <p>No link</p>
12 | </li>
13 | <li><a href="#">Simple link</a></li>
14 | <li data-role="divider">Divider</li>
15 | <li><a href="#">
16 | <h2>Header</h2>
17 | <p>Header and description</p>
18 | </a></li>
19 | </ul>
20 |
Will be converted to:
23 | 24 |<ul data-role="listview" data-skip-enhance="true" id="xf-8293" class="xf-listview">
25 | <li class=" xf-li xf-li-divider">A</li>
26 | <li class="xf-li-static xf-li">
27 | <div class="xf-li-wrap">
28 | <h2 class="xf-li-header">Header</h2>
29 | <p class="xf-li-desc">No link</p>
30 | </div>
31 | </li>
32 | <li class=" xf-li">
33 | <a href="#" class="xf-li-btn">
34 | Simple link
35 | <div class="xf-btn-text"></div>
36 | </a>
37 | </li>
38 | <li class=" xf-li xf-li-divider">Divider</li>
39 | <li class=" xf-li">
40 | <a href="#" class="xf-li-btn">
41 | <div class="xf-btn-text">
42 | <h2 class="xf-li-header">Header</h2>
43 | <p class="xf-li-desc">Header and description</p>
44 | </div>
45 | </a>
46 | </li>
47 | </ul>
48 |
The look of form inputs, buttons will be enhanced automatically, but you can use certain attributes to customize some of them. See full list of the data- attributes below.
-------------------------------------------------------------------------------- /docs/building_your_xf_app_for_testing_and_production.html: -------------------------------------------------------------------------------- 1 |yo xf:application build [appName]
Inputs of types submit, reset, button, <button>
s, and links with attribute [data-role=button]
will be styled as buttons. For example a usual input[type=submit]
will look like this:
<a data-role="button">A button</a>
6 |
Buttons can be of several types: normal, special and alert. They differ only in appearance.
11 | 12 |A special button is displayed in an accented color, blue by default, generally needed to highlight the most important button among several. To make a button special add data-special=true attribute to it.
13 | 14 |The following code:
15 | 16 |<a data-special="true"
17 | data-appearance="button" href="#">
18 | A special button
19 | </a>
20 |
Will produce the following button:
23 | 24 | data-appearance="button" href="#">
A special button
An alert button is red by default and is recommended to be used for actions that may cause data loss, e.g. for a delete button. Add data-alert=true attribute to get such a button:
27 | 28 |<button data-alert="true">An alert button</button>
29 |
Will produce the following button:
32 | 33 | 34 | 35 |You may need to use smaller buttons in your app. To make them, add a [data-small=true] attribute to the necessary controls.
36 | 37 |To make a common back button use a [data-back=true] attribute. It will go back in browser history by default.
38 | 39 |<a data-appearance="button" data-small="true" href="#">A small button</a>
40 | <a data-appearance="backbtn" href="#"> Back button</a>
41 |
XF.Collection
is an extended version of Backbone.Collection to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:collection [name]
.
XF.Collection
properties:
status
: status of the data in the collection. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this collection.ajaxSettings
: settings for ajax requests to the server for this collection. If not set global ajaxSettings
will be used. The format is the same as for $.ajax
method.XF.Collection
methods:
url
: the url to the data. Could be a function or a property.refresh
: refreshes the data and triggers the view refreshing.XF.Collection
hooks:
construct
: overwrite it for your own needs. Called on the construction of collection.initialize
: overwrite it for your own needs. Called on the initialization of collection.For other methods, properties and hooks available see Backbone.Collection.
-------------------------------------------------------------------------------- /docs/component.html: -------------------------------------------------------------------------------- 1 |Components are the building blocks of XFramework. A component is a part of an application that can be abstracted as an independent unit and can be reused throughout the application. Components can be nested in one another, can have customized presentations depending on the device it is used on. You can create as many device profiles as you need and customize whole application in any way for each of them.
4 | 5 |A component separates logic from presentation, which are stored as separate files and are loaded only when the component needs to be rendered, which helps to save on load times and device resources. Though component caching mechanism allows to prefetch component parts when developer deems it necessary.
6 | 7 |To use a component a developer places a marker where the component will be rendered. The marker is a
See an example of two nested components declared in the page markup:
10 | 11 |<div data-component="categoryList" data-id="categoryListBooks">
12 | This content will be shown while component is loading...
13 | </div>
14 |
Such an approach lets a developer build asynchronuous UIs and avoid loading extraneous resources.
17 | 18 |There's a way to customize the component with the starting options from outside:
19 | 20 | <div data-component="categoryList" data-id="categoryListBooks">
21 | This content will be shown while component is loading...
22 | <script>
23 | XF.setOptionsByID('categoryListBooks',
24 | {
25 | currentPage: 2
26 | }
27 | );
28 | </script>
29 | </div>
30 |
You can use XF.setOptionsByID
method in the place you decided but before component instance was created.
There are two ways to create a component:
4 | 5 |yo xf:component [name]
that will scaffold a javascript file together with templates for all device typesEvery component should extend XF.Component
that allows general functionality, loading and rendering processes work without your input.
First of all, you will need a JavaScript file which defines component's logic and may override some XF.Component properties to achieve specific behavior.
13 | 14 |XF.define(
15 | 'MyApp.components.categoryList', // just 'categoryList' is fine as well
16 | XF.Component.extend({
17 | construct: function () {
18 | // will be called on the start of construction
19 | },
20 |
21 | initialize: function () {
22 | // this method will be called after component construction
23 | },
24 |
25 | // for more flexibility you can define Views in separate files
26 | View: XF.View.extend({
27 | initialize: function () {
28 |
29 | }
30 | }),
31 |
32 | // for more flexibility you can define Collections in separate files
33 | Collection: XF.Collection.extend({
34 | url: 'books.json',
35 | initialize: function () {
36 |
37 | }
38 | })
39 | })
40 |
41 |
42 | );
43 |
This call defines a new component via two arguments: component name and component class.
46 | 47 |Component name: used to setup a placeholder (-s) for instance (-s) of the component and should be unique within the application.
48 | 49 |Component class: definition is created via XF.[some_base_component].extend() call. Here you should pass properties and methods you want to add to the base class functionality as non-static and static part of a class respectively.
50 | 51 |You may add/override properties of the component model, collection and view. Basically you are able to modify everything you see.
52 | 53 |Be aware of proper usage Collections and Models. By default XF.Component
has XF.View
and XF.Collection
classes (XF.Component.Model
is not defined). If the component has linkage to Collection and Model classes the collection will be created.
XF.Component
properties:
id
: component idname
: component nameoptions
: component options (defaults merged with passed options for component). Default: {autoload: true, autorender: true, updateOnShow: false}
. autoload
and autorender
will load the data for collection or model with creation of component and then render the template with fetched data.selector
: component selector, e.g. [data-id="componentId"]
Model
: model class for this component. Default: null
.model
: instance of Model
that will be created on the constructing of the component.Collection
: collection class for this component. Default: XF.Collection
.collection
: instance of Model
that will be created on the constructing of the component.View
: view class for this component. Default: XF.View
.view
: instance of View
that will be created on the constructing of the component.XF.Component
methods:
refresh
: refreshes the data (model or collection) and then refreshes the view. Triggers refresh
method for view and collection/model.XF.Component
hooks:
construct
: overwrite it for your own needs. Called on the construction of component.initialize
: overwrite it for your own needs. Called on the initialization of component.Custom xf.js and xf.min js build:
4 | 5 |yo xf:build
— create build with all UI elements and source modulesyo xf:build [srcModule1:srcModule2]
— create build with all UI elements and source modulesFull list of available elements can be found at xf/ui
and xf/src
directory of XFramework repository.
XFramework UI element is 'an extended version of Document Object' or the another parallel could be done with jQuery Plugin. It fills the gap with Rich UI Elements for all the browsers. It means that XFramework will parse your HTML and add some markup to make UI controls user- and developer-friendly.
4 | 5 |Each UI element has a simple markup that will be enhanced into the rich element.
6 | 7 |<ul data-role="listview">
8 | <li data-role="divider">A</li>
9 | <li>
10 | <h2>Header</h2>
11 | <p>No link</p>
12 | </li>
13 | <li><a href="#">Simple link</a></li>
14 | <li data-role="divider">Divider</li>
15 | <li><a href="#">
16 | <h2>Header</h2>
17 | <p>Header and description</p>
18 | </a></li>
19 | </ul>
20 |
Will be converted to:
23 | 24 |<ul data-role="listview" data-skip-enhance="true" id="xf-8293" class="xf-listview">
25 | <li class=" xf-li xf-li-divider">A</li>
26 | <li class="xf-li-static xf-li">
27 | <div class="xf-li-wrap">
28 | <h2 class="xf-li-header">Header</h2>
29 | <p class="xf-li-desc">No link</p>
30 | </div>
31 | </li>
32 | <li class=" xf-li">
33 | <a href="#" class="xf-li-btn">
34 | Simple link
35 | <div class="xf-btn-text"></div>
36 | </a>
37 | </li>
38 | <li class=" xf-li xf-li-divider">Divider</li>
39 | <li class=" xf-li">
40 | <a href="#" class="xf-li-btn">
41 | <div class="xf-btn-text">
42 | <h2 class="xf-li-header">Header</h2>
43 | <p class="xf-li-desc">Header and description</p>
44 | </div>
45 | </a>
46 | </li>
47 | </ul>
48 |
The look of form inputs, buttons will be enhanced automatically, but you can use certain attributes to customize some of them. See full list of the data- attributes below.
-------------------------------------------------------------------------------- /docs/data/building_your_xf_app_for_testing_and_production.html: -------------------------------------------------------------------------------- 1 |yo xf:application build [appName]
Inputs of types submit, reset, button, <button>
s, and links with attribute [data-role=button]
will be styled as buttons. For example a usual input[type=submit]
will look like this:
<a data-role="button">A button</a>
6 |
Buttons can be of several types: normal, special and alert. They differ only in appearance.
11 | 12 |A special button is displayed in an accented color, blue by default, generally needed to highlight the most important button among several. To make a button special add data-special=true attribute to it.
13 | 14 |The following code:
15 | 16 |<a data-special="true"
17 | data-appearance="button" href="#">
18 | A special button
19 | </a>
20 |
Will produce the following button:
23 | 24 | data-appearance="button" href="#">
A special button
An alert button is red by default and is recommended to be used for actions that may cause data loss, e.g. for a delete button. Add data-alert=true attribute to get such a button:
27 | 28 |<button data-alert="true">An alert button</button>
29 |
Will produce the following button:
32 | 33 | 34 | 35 |You may need to use smaller buttons in your app. To make them, add a [data-small=true] attribute to the necessary controls.
36 | 37 |To make a common back button use a [data-back=true] attribute. It will go back in browser history by default.
38 | 39 |<a data-appearance="button" data-small="true" href="#">A small button</a>
40 | <a data-appearance="backbtn" href="#"> Back button</a>
41 |
XF.Collection
is an extended version of Backbone.Collection to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:collection [name]
.
XF.Collection
properties:
status
: status of the data in the collection. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this collection.ajaxSettings
: settings for ajax requests to the server for this collection. If not set global ajaxSettings
will be used. The format is the same as for $.ajax
method.XF.Collection
methods:
url
: the url to the data. Could be a function or a property.refresh
: refreshes the data and triggers the view refreshing.XF.Collection
hooks:
construct
: overwrite it for your own needs. Called on the construction of collection.initialize
: overwrite it for your own needs. Called on the initialization of collection.For other methods, properties and hooks available see Backbone.Collection.
-------------------------------------------------------------------------------- /docs/data/component.html: -------------------------------------------------------------------------------- 1 |Components are the building blocks of XFramework. A component is a part of an application that can be abstracted as an independent unit and can be reused throughout the application. Components can be nested in one another, can have customized presentations depending on the device it is used on. You can create as many device profiles as you need and customize whole application in any way for each of them.
4 | 5 |A component separates logic from presentation, which are stored as separate files and are loaded only when the component needs to be rendered, which helps to save on load times and device resources. Though component caching mechanism allows to prefetch component parts when developer deems it necessary.
6 | 7 |To use a component a developer places a marker where the component will be rendered. The marker is a
See an example of two nested components declared in the page markup:
10 | 11 |<div data-component="categoryList" data-id="categoryListBooks">
12 | This content will be shown while component is loading...
13 | </div>
14 |
Such an approach lets a developer build asynchronuous UIs and avoid loading extraneous resources.
17 | 18 |There's a way to customize the component with the starting options from outside:
19 | 20 | <div data-component="categoryList" data-id="categoryListBooks">
21 | This content will be shown while component is loading...
22 | <script>
23 | XF.setOptionsByID('categoryListBooks',
24 | {
25 | currentPage: 2
26 | }
27 | );
28 | </script>
29 | </div>
30 |
You can use XF.setOptionsByID
method in the place you decided but before component instance was created.
There are two ways to create a component:
4 | 5 |yo xf:component [name]
that will scaffold a javascript file together with templates for all device typesEvery component should extend XF.Component
that allows general functionality, loading and rendering processes work without your input.
First of all, you will need a JavaScript file which defines component's logic and may override some XF.Component properties to achieve specific behavior.
13 | 14 |XF.define(
15 | 'MyApp.components.categoryList', // just 'categoryList' is fine as well
16 | XF.Component.extend({
17 | construct: function () {
18 | // will be called on the start of construction
19 | },
20 |
21 | initialize: function () {
22 | // this method will be called after component construction
23 | },
24 |
25 | // for more flexibility you can define Views in separate files
26 | View: XF.View.extend({
27 | initialize: function () {
28 |
29 | }
30 | }),
31 |
32 | // for more flexibility you can define Collections in separate files
33 | Collection: XF.Collection.extend({
34 | url: 'books.json',
35 | initialize: function () {
36 |
37 | }
38 | })
39 | })
40 |
41 |
42 | );
43 |
This call defines a new component via two arguments: component name and component class.
46 | 47 |Component name: used to setup a placeholder (-s) for instance (-s) of the component and should be unique within the application.
48 | 49 |Component class: definition is created via XF.[some_base_component].extend() call. Here you should pass properties and methods you want to add to the base class functionality as non-static and static part of a class respectively.
50 | 51 |You may add/override properties of the component model, collection and view. Basically you are able to modify everything you see.
52 | 53 |Be aware of proper usage Collections and Models. By default XF.Component
has XF.View
and XF.Collection
classes (XF.Component.Model
is not defined). If the component has linkage to Collection and Model classes the collection will be created.
XF.Component
properties:
id
: component idname
: component nameoptions
: component options (defaults merged with passed options for component). Default: {autoload: true, autorender: true, updateOnShow: false}
. autoload
and autorender
will load the data for collection or model with creation of component and then render the template with fetched data.selector
: component selector, e.g. [data-id="componentId"]
Model
: model class for this component. Default: null
.model
: instance of Model
that will be created on the constructing of the component.Collection
: collection class for this component. Default: XF.Collection
.collection
: instance of Model
that will be created on the constructing of the component.View
: view class for this component. Default: XF.View
.view
: instance of View
that will be created on the constructing of the component.XF.Component
methods:
refresh
: refreshes the data (model or collection) and then refreshes the view. Triggers refresh
method for view and collection/model. XF.Component
hooks:
construct
: overwrite it for your own needs. Called on the construction of component.initialize
: overwrite it for your own needs. Called on the initialization of component.Custom xf.js and xf.min js build:
4 | 5 |yo xf:build
— create build with all UI elements and source modulesyo xf:build [srcModule1:srcModule2]
— create build with all UI elements and source modulesFull list of available elements can be found at xf/ui
and xf/src
directory of XFramework repository.
Below you can find an example of footer UI element:
4 | 5 |<div data-role="footer" data-fixed="true">
6 | <button data-icon="star">Link 1</button>
7 | <button data-icon="help">Link 2</button>
8 | <button data-icon="heart">Link 3</button>
9 | <button data-icon="print">Link 4</button>
10 | </div>
11 |
Such code will be transformed into:
14 | 15 |<div data-role="footer" data-fixed="true" data-id="xf-29339" id="xf-29339" data-skip-enhance="true">
16 | <div class="xf-footer xf-footer-fixed ">
17 | <ul class="xf-nav">
18 | <li class="xf-grid-unit xf-grid-unit-1of4">
19 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item0">
20 | <div class="xf-icon xf-icon-big xf-icon-star"></div>
21 | <div class="xf-nav-item-text ">Link 1</div>
22 | </a>
23 | </li>
24 | <li class="xf-grid-unit xf-grid-unit-1of4">
25 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item1">
26 | <div class="xf-icon xf-icon-big xf-icon-help"></div>
27 | <div class="xf-nav-item-text ">Link 2</div>
28 | </a>
29 | </li>
30 | <li class="xf-grid-unit xf-grid-unit-1of4">
31 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item2">
32 | <div class="xf-icon xf-icon-big xf-icon-heart"></div>
33 | <div class="xf-nav-item-text ">Link 3</div>
34 | </a>
35 | </li>
36 | <li class="xf-grid-unit xf-grid-unit-1of4">
37 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item3">
38 | <div class="xf-icon xf-icon-big xf-icon-print"></div>
39 | <div class="xf-nav-item-text ">Link 4</div>
40 | </a>
41 | </li>
42 | </ul>
43 | </div>
44 | </div>
45 |
Below you can find an example of header UI element:
4 | 5 |<div data-role="header" data-fixed="true">
6 | <button data-small="true" data-icon="backbtn" data-position="left"></button>
7 | <h1>Title</h1>
8 | </div>
9 |
Such code will be transformed into:
12 | 13 |<div data-role="header" data-id="xf-18586" id="xf-18586" data-skip-enhance="true">
14 | <header class="xf-header ">
15 | <button data-small="true" data-icon="backbtn" id="backbtn" data-position="left" data-animation="slideright" data-skip-enhance="true" class="xf-button-float-left xf-button-header-left xf-button-small xf-iconpos-left xf-button-small-icon-only">
16 | <span class="xf-icon xf-icon-backbtn xf-icon-small"></span>
17 | </button>
18 | <h1 class="xf-header-title">Title</h1>
19 | </header>
20 | </div>
21 |
You don't need to download the source code from the repo, create all the necessary files for the web app, writing two thousands line of code just to create a Hello world!
app. XFramework Generator can make everything for you.
XF Generator has a number of dependencies such as:
6 | 7 | 12 | 13 |To install first two of them on Mac OS X or Windows computers you just need to download a package from nodejs.org/download/. For other platforms see the readme.
14 | 15 |After installing node.js and npm go to terminal and install Yeoman writing npm install -g yo
(with sudo
if necessary).
Almost there! After these steps you need to install XF Generator with npm install -g generator-xf
.
XF.on
, XF.off
, XF.trigger
, etc.)app:started
: when the app has startedcomponent:componentID:constructed
: when the component with id componentID
has been constructed
pages:show
: command to switch the page to another one. XF.trigger('pages:show', 'books')
pages:animation:next
: command to set the type of the next animation. XF.trigger('pages:animation:next', 'fade')
pages:animation:default
: command to set the default type of the animations. XF.trigger('pages:animation:default', 'fade')
ui:enhance
: command to enhance all inside the DOM element. Selector or jQuery object can be passed. XF.trigger('ui:enhance', '.cart')
navigate
: command to change the url, triggers the router that could trigger page switching. XF.trigger('navigate', 'books/fiction')
component:componentID:refresh
: command to refresh the component with id componentID
You can fire any event to the desired component in format component:componentID:eventName
. Even if there is no component with such id these events will be delayed until it will be rendered.
refresh
: command to refresh the componentfetched
: when the data has been loaded from the backendrefresh
: command to refresh the data of modelKeep in mind that all Backbone.js built-in events are available.
32 | 33 |fetched
: when the data has been loaded from the backendrefresh
: command to refresh the data of collectionKeep in mind that all Backbone.js built-in events are available.
41 | 42 |rendered
: when the view has been renderedloaded
: when the template has been loadedrefresh
: command to rerender the viewKeep in mind that all Backbone.js built-in events are available.
-------------------------------------------------------------------------------- /docs/data/listview.html: -------------------------------------------------------------------------------- 1 |To make a data list add a [data-role="listview"]
attribute to a UL or OL element.
If list elements must be clickable wrap all the contents of the list items in A elements: UL[data-role=listview] > LI > A > whatever
.
To make a divider between list items make another LI with a data-role="divider"
attribute.
See code and result lower in this section.
10 | 11 |Just like with buttons icons can be added to list items using data-icon
and data-iconpos
attributes. Note that [data-iconpos=top]
and [data-iconpos=bottom]
values are not supported on list items.
List elements can have a count bubble. Just add a SPAN.xf-count-bubble
inside them
If you need to have thumbnails inside list items, you don't need to do anything special, just put the image inside the list item, and it will be displayed on the left hand side. The image can be moved to the right side by adding [data-thumbpos="right"]
attribute to the corresponding LI
element.
Sample listview markup:
22 | 23 |<ul data-role="listview">
24 | <li data-role="divider">A</li>
25 | <li>
26 | <h2>Header</h2>
27 | <p>No link</p>
28 | </li>
29 | <li><a href="#">Simple link</a></li>
30 | <li data-role="divider">Divider</li>
31 | <li><a href="#">
32 | <h2>Header</h2>
33 | <p>Header and description</p>
34 | </a></li>
35 | <li data-icon="chevron-thin-right" data-iconpos="right"><a href="#">
36 | <h2>With Icon</h2>
37 | <p>List item with icon on the right</p>
38 | </a></li>
39 | <li data-icon="chevron-thin-right" data-iconpos="right"><a href="#">
40 | <h2>With Icon and Count</h2>
41 | <p>List item with icon on the right and count</p>
42 | <span class="xf-count-bubble">32</span>
43 | </a></li>
44 | <li data-thumbpos="right"><a href="#">
45 | <img src="../img/_thumb1.jpg" alt="">
46 | <h2>With Thumbnail on the right</h2>
47 | <p>List item with a thumbnail on the right</p>
48 | </a></li>
49 | </ul>
50 |
The above code will result in:
53 | 54 |No link
59 |Header and description
65 |List item with icon on the right
69 |List item with icon on the right and count
73 | 32 74 |List item with a thumbnail on the right
79 |XF.Model
is an extended version of Backbone.Model to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:model [name]
.
XF.Model
properties:
status
: status of the data in the model. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this model.ajaxSettings
: settings for ajax requests to the server for this model. If not set global ajaxSettings
will be used. The format is the same as for $.ajax
method.XF.Model
methods:
url
: the url to the data. Could be a function or a property.refresh
: refreshes the data and triggers the view refreshing.XF.Model
hooks:
construct
: overwrite it for your own needs. Called on the construction of model.initialize
: overwrite it for your own needs. Called on the initialization of model.For other methods, properties and hooks available see Backbone.Model.
-------------------------------------------------------------------------------- /docs/data/supported_platforms_and_browsers.html: -------------------------------------------------------------------------------- 1 |Mobile phones and tablets:
4 | 5 |Desktop:
12 | 13 |It doesn't mean that another browsers or platforms are not supported. We just don't have a possibility to test XF across all existing platforms and browsers.
22 | 23 |The roadmap for the next versions can be found on GitHub.
-------------------------------------------------------------------------------- /docs/data/tabs.html: -------------------------------------------------------------------------------- 1 |Below you can find an example of tabs UI element:
4 | 5 |<div data-role="tabs">
6 | <button data-active="true">Link 1</button>
7 | <button>Link 2</button>
8 | <button>Link 3</button>
9 | <button>Link 4</button>
10 | </div>
11 |
Such code will be transformed into:
14 | 15 |<div data-role="tabs" data-id="xf-37715" id="xf-37715" data-skip-enhance="true">
16 | <ul class="xf-tabs">
17 | <li class="xf-grid-unit xf-grid-unit-1of4">
18 | <a class="xf-tabs-button xf-corner-tl xf-corner-bl" id="xf-71177">
19 | <span class="xf-tabs-button-text">Link 1</span>
20 | </a>
21 | </li>
22 | <li class="xf-grid-unit xf-grid-unit-1of4">
23 | <a class="xf-tabs-button" id="xf-7896">
24 | <span class="xf-tabs-button-text">Link 2</span>
25 | </a>
26 | </li>
27 | <li class="xf-grid-unit xf-grid-unit-1of4">
28 | <a class="xf-tabs-button" id="xf-62398">
29 | <span class="xf-tabs-button-text">Link 3</span>
30 | </a>
31 | </li>
32 | <li class="xf-grid-unit xf-grid-unit-1of4">
33 | <a class="xf-tabs-button xf-corner-tr xf-corner-br xf-tabs-button-active" id="xf-83850">
34 | <span class="xf-tabs-button-text">Link 4</span>
35 | </a>
36 | </li>
37 | </ul>
38 | </div>
39 |
There are some rules behind the XFramework:
4 | 5 |XF Generator allows you to update sources and dependencies:
4 | 5 |yo xf:update [all]
— update less and js files of XFramework, check latest versions of jQuery, Backbone, Underscoreyo xf:update scripts
— update js files (inluding thirdparty libraries) of XFramework, check latest versions of jQuery, Backbone, Underscoreyo xf:update styles
— update less files of XFrameworkXF.View
is an extended version of Backbone.View to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:view [name]
.
XF.View
properties:
template
: contains source of the loaded template and the compiled version of it. Default: {src: null, compiled: null, cache: true }
.status
: status of the data in the view. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this view.XF.View
methods:
load
: loads the template from the cache or remotely.render
: renders the view. Please use refresh
instead to use it together with hooks available.refresh
: refreshes the view.getMarkup
: returns the markup using the current data.XF.View
hooks:
url
: the url to the template file. Could be a function or a property.construct
: overwrite it for your own needs. Called on the construction of view.initialize
: overwrite it for your own needs. Called on the initialization of view.beforeLoadTemplate
: called before loading of the template started.afterLoadTemplate
: called after loading of the template completed.afterLoadTemplateFailed
: called after loading of the template completed and failed.beforeRender
: called before rendering of the template.afterRender
: called after rendering of the template.Note that data from collection
or model
of the component is available in the template via localized variable data
.
For other methods, properties and hooks available see Backbone.View.
-------------------------------------------------------------------------------- /docs/data/what_is_xframework_.html: -------------------------------------------------------------------------------- 1 |Version 0.9.1
4 | 5 |XFramework (next XF) is a small yet powerful Javascript framework for quick development of cross-device web applications. Honestly saying, XF is a high-level framework based on Backbone.js that implements its own architecture paradigm, based on MV* on the component level.
6 | 7 |XFramework makes it easy to reuse the application logic and provide various layouts or widgets for different devices based on the criteria that you define.
8 | 9 |XFramework is designed to be extremely modular, flexible, fast, and easy to use. To develop an app in X-Framework a developer should be familiar with common web technologies such as HTML/CSS/JS, LESS for editing styles, Handlebars-style templating and have an understanding of how MV* architecture works. Experience using Backbone.js, Angular.js, Ember.js, jQuery Mobile or other framework will be helpful.
10 | 11 |XFramework currently features:
12 | 13 |XF.App
is a 'class' that you able to extend with your own methods and properties needed in the application. In this case an instance of this class is something like a main controller of the whole app.
// if the app boilerplate was created via XF Generator
6 | // these lines can be found in `app.js` file
7 | var MyApp = XF.App.extend({
8 | initialize: function () {
9 | // this code will be executed before XF will be started
10 | // but you can put the preparation code here
11 | // …
12 | this.myAwesomeMethod();
13 | },
14 | myAwesomeMethod: function () {
15 |
16 | }
17 |
18 |
19 | });
20 |
XF.device
contains the information about current user device app was launched:
XF.device.supports.touchEvents
XF.device.supports.pointerEvents
XF.device.supports.cssAnimations
XF.device.isMobile
. It was a necessary trick to detect mobile OS's using navigator.userAgent
.XF.device.type
is a selected type of devices from specified in options passed on the start of application. Based on this selected device type the necessary template for the component will be loaded.var app = new MyApp({
14 | // …
15 | // other settings for the application
16 | device: {
17 | types : [{
18 | name : 'tablet',
19 | range : {
20 | max : 1024,
21 | min : 569
22 | },
23 | templatePath : 'tablet/' // template path for tablet devices (by default it will be tmpl/tablet/componentName.tmpl)
24 | }, {
25 | name : 'phone',
26 | range : {
27 | max : 568,
28 | min : null
29 | },
30 | templatePath : 'phone/' // path to templates for phones (by default it will be tmpl/phone/componentName.tmpl)
31 | }]
32 | }
33 | });
34 |
XF.Router
is an extended [Backbone.Router]. XF cares about creation of router instance, its starting, binding handlers and so on. Everything you just need to do is to pass your routes and handlers with starting options for the application:
// if the app boilerplate was created via XF Generator
6 | // these lines cab be found in `index.js` file
7 | var app = new MyApp({
8 | // …
9 | // other settings for the application
10 | router: {
11 | routes: {
12 | '': 'home',
13 | 'search/:q': 'searchByQuery',
14 | 'item:id': 'showItemById',
15 | 'books/:cat(/:subcat)': 'showBooksCategory',
16 | 'news/*any': 'showNews'
17 | },
18 |
19 | home: function () {
20 |
21 | },
22 |
23 | searchByQuery: function (query) {
24 |
25 | },
26 |
27 | showItemById: function (id) {
28 |
29 | },
30 |
31 | showBooksCategory: function (cat, subcat) {
32 |
33 | },
34 |
35 | showNews: function (param) {
36 |
37 | }
38 | }
39 |
40 |
41 | });
42 |
In the example above the handler home
for empty route was created. In case you want to define the starting route for the application or turn off HTML5 pushState (using pushState
support is turned on by default) you should pass the necessary starting parameters to XF.history
which actually is a link to Backbone.history.
var app = new MyApp({
47 | // …
48 | // other settings for the application
49 | history: {
50 | pushState: false,
51 | root: 'books/fiction'
52 | }
53 | });
54 |
To force navigation to another url fragment a number of ways is available:
57 | 58 |XF.router.navigate('books/fiction', {trigger: true})
XF.navigate('books/fiction')
is the syntax sugar for the first approach. {trigger: true}
set by defaultXF.trigger('navigate', 'books/fiction')
is much more preferable for consistency and integrity of the applicationAll elements with the attribute data-href
or href
will work on changing url fragment.
<a data-href="books/fiction">Books</a>
67 |
This simple object contains the settings for the application, that could be overridden on the start:
4 | 5 |1.0.0
)true
)js/components/
).js
)componentUrlPrefix + compName + componentUrlPostfix
)tmpl/
).tmpl
)''
){}
)var app = new MyApp({
18 | // …
19 | // other settings for the application
20 | settings: {
21 | appVersion: '2.0.1',
22 |
23 | dataUrlPrefix: 'http://api.example.com/',
24 |
25 | ajaxSettings: {
26 | // settings that are provided to collections and models to fetch and sync the data
27 | // see $.ajax options
28 | crossDomain: true
29 | }
30 | }
31 |
32 |
33 | });
34 |
XFramework has its own building blocks that drive it on. Some blocks are mandatory to include in the build of XFramework, other ones are not required.
4 | 5 |Mandatory XF src modules are:
6 | 7 |xf.jquery.hooks.js
xf.core.js
xf.settings.js
xf.app.js
xf.router.js
xf.pages.js
xf.model.js
xf.collection.js
xf.view.js
xf.component.js
Optional XF src modules are:
21 | 22 |xf.ui.js
xf.ui.*.js
xf.touch.js
xf.utils.js
xf.storage.js
xf.zepto.support.js
XF.storage
is just a wrapper for localStorage that allows you easily to interact with it: set, get, clear.
XF.storage.set('booksCategory', 12);
6 |
7 | XF.storage.get('booksCategory');
8 |
9 | XF.storage.clear();
10 |
XF.touch
makes the life in such a multidevice world easier — it is an adapter for all types of user contexts: touch screens, mouse, pointers.
For now it contains the following user interaction events:
6 | 7 |tap
: it doesn't matter if it is a click or a touch to the screen. Just bind on tap events for all types of devices and that's it!
9 | <<<<<<< HEADXF.touch
fixes the 300ms gap between click and touch events as well*XF.touch
fixes the 300ms gap between click and touch events as well
15 |
16 | 17 |18 |19 |20 |21 |22 |23 |4da00e27f941b8e09cee59a7e8cd8d6fd27b4d8a
swipe
, swipeUp
, swipeDown
, swipeLeft
, swipeRight
This source module will contain all the helpers will needed to make the work with XF much more easier. Right now it contains only address bar hiding helper for iOS and Android mobile phones.
-------------------------------------------------------------------------------- /docs/data/xf_zepto_support_js.html: -------------------------------------------------------------------------------- 1 |This piece enables the support of zepto.js instead of jQuery extending it with all missing methods and properties.
4 | 5 |Attention! Include this module on your own fear and risk. It is in experimental status right away.
-------------------------------------------------------------------------------- /docs/data/your_first_xf_web_app.html: -------------------------------------------------------------------------------- 1 |To create the first XF application the simplest way is to use XF Generator through yo xf:application init [appName]
.
For now it scaffolds an app in the way you can see by example: XF Hello World App.
-------------------------------------------------------------------------------- /docs/docs.css: -------------------------------------------------------------------------------- 1 | html { 2 | font: 15px/1.5 sans-serif; 3 | } 4 | a { 5 | cursor: pointer; 6 | } 7 | ul, ol, dl { 8 | padding: 0 0 0 2em; 9 | } 10 | .example { 11 | margin: 1em 0; 12 | } 13 | code { 14 | color: #000070; 15 | -o-tab-size: 4; 16 | tab-size: 4; 17 | } 18 | .sublist { 19 | margin-left: 40px; 20 | } 21 | .data-table { 22 | margin: 1em 0; 23 | width: 100%; 24 | } 25 | .data-table td, 26 | .data-table th { 27 | padding: .5em; 28 | } 29 | 30 | .data-table td { 31 | vertical-align: middle 32 | } 33 | .col-icon { 34 | width: 20px; 35 | } 36 | .col-icon-label { 37 | } 38 | .nobr { 39 | white-space: nowrap; 40 | } 41 | .msg { 42 | padding: .4em 1em; 43 | border: 1px solid rgba(0,0,0,0.15); 44 | border-radius: 3px; 45 | -webkit-transition: all .5s; 46 | transition: all .5s; 47 | display: block; 48 | } 49 | 50 | .ok { 51 | background: #D1EDC8; 52 | } 53 | .warning { 54 | background: #EDC7C7; 55 | } 56 | 57 | #content .xf-has-header { 58 | margin-top: 0; 59 | } 60 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 |Below you can find an example of footer UI element:
4 | 5 |<div data-role="footer" data-fixed="true">
6 | <button data-icon="star">Link 1</button>
7 | <button data-icon="help">Link 2</button>
8 | <button data-icon="heart">Link 3</button>
9 | <button data-icon="print">Link 4</button>
10 | </div>
11 |
Such code will be transformed into:
14 | 15 |<div data-role="footer" data-fixed="true" data-id="xf-29339" id="xf-29339" data-skip-enhance="true">
16 | <div class="xf-footer xf-footer-fixed ">
17 | <ul class="xf-nav">
18 | <li class="xf-grid-unit xf-grid-unit-1of4">
19 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item0">
20 | <div class="xf-icon xf-icon-big xf-icon-star"></div>
21 | <div class="xf-nav-item-text ">Link 1</div>
22 | </a>
23 | </li>
24 | <li class="xf-grid-unit xf-grid-unit-1of4">
25 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item1">
26 | <div class="xf-icon xf-icon-big xf-icon-help"></div>
27 | <div class="xf-nav-item-text ">Link 2</div>
28 | </a>
29 | </li>
30 | <li class="xf-grid-unit xf-grid-unit-1of4">
31 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item2">
32 | <div class="xf-icon xf-icon-big xf-icon-heart"></div>
33 | <div class="xf-nav-item-text ">Link 3</div>
34 | </a>
35 | </li>
36 | <li class="xf-grid-unit xf-grid-unit-1of4">
37 | <a data-href="" class="xf-nav-item xf-iconpos-top" id="xf-29339-item3">
38 | <div class="xf-icon xf-icon-big xf-icon-print"></div>
39 | <div class="xf-nav-item-text ">Link 4</div>
40 | </a>
41 | </li>
42 | </ul>
43 | </div>
44 | </div>
45 |
Below you can find an example of header UI element:
4 | 5 |<div data-role="header" data-fixed="true">
6 | <button data-small="true" data-icon="backbtn" data-position="left"></button>
7 | <h1>Title</h1>
8 | </div>
9 |
Such code will be transformed into:
12 | 13 |<div data-role="header" data-id="xf-18586" id="xf-18586" data-skip-enhance="true">
14 | <header class="xf-header ">
15 | <button data-small="true" data-icon="backbtn" id="backbtn" data-position="left" data-animation="slideright" data-skip-enhance="true" class="xf-button-float-left xf-button-header-left xf-button-small xf-iconpos-left xf-button-small-icon-only">
16 | <span class="xf-icon xf-icon-backbtn xf-icon-small"></span>
17 | </button>
18 | <h1 class="xf-header-title">Title</h1>
19 | </header>
20 | </div>
21 |
You don't need to download the source code from the repo, create all the necessary files for the web app, writing two thousands line of code just to create a Hello world!
app. XFramework Generator can make everything for you.
XF Generator has a number of dependencies such as:
* node.js
* NPM
* [Yeoman] (http://yeoman.io)
To install first two of them on Mac OS X or Windows computers you just need to download a package from nodejs.org/download/. For other platforms see the readme.
8 | 9 |After installing node.js and npm go to terminal and install Yeoman writing npm install -g yo
(with sudo
if necessary).
Almost there! After these steps you need to install XF Generator with npm install -g generator-xf
.
XF.on
, XF.off
, XF.trigger
, etc.)app:started
: when the app has startedcomponent:componentID:constructed
: when the component with id componentID
has been constructedcomponent:componentID:rendered
: when the component with id componentID
has been rendered
pages:show
: command to switch the page to another one. XF.trigger('pages:show', 'books')
pages:animation:next
: command to set the type of the next animation. XF.trigger('pages:animation:next', 'fade')
pages:animation:default
: command to set the default type of the animations. XF.trigger('pages:animation:default', 'fade')
ui:enhance
: command to enhance all inside the DOM element. Selector or jQuery object can be passed. XF.trigger('ui:enhance', '.cart')
navigate
: command to change the url, triggers the router that could trigger page switching. XF.trigger('navigate', 'books/fiction')
component:componentID:refresh
: command to refresh the component with id componentID
You can fire any event to the desired component in format component:componentID:eventName
. Even if there is no component with such id these events will be delayed until it will be rendered.
refresh
: command to refresh the componentfetched
: when the data has been loaded from the backendrefresh
: command to refresh the data of modelKeep in mind that all Backbone.js built-in events are available.
33 | 34 |fetched
: when the data has been loaded from the backendrefresh
: command to refresh the data of collectionKeep in mind that all Backbone.js built-in events are available.
42 | 43 |rendered
: when the view has been renderedloaded
: when the template has been loadedrefresh
: command to rerender the viewKeep in mind that all Backbone.js built-in events are available.
-------------------------------------------------------------------------------- /docs/listview.html: -------------------------------------------------------------------------------- 1 |To make a data list add a [data-role="listview"]
attribute to a UL or OL element.
If list elements must be clickable wrap all the contents of the list items in A elements: UL[data-role=listview] > LI > A > whatever
.
To make a divider between list items make another LI with a data-role="divider"
attribute.
See code and result lower in this section.
10 | 11 |Just like with buttons icons can be added to list items using data-icon
and data-iconpos
attributes. Note that [data-iconpos=top]
and [data-iconpos=bottom]
values are not supported on list items.
List elements can have a count bubble. Just add a SPAN.xf-count-bubble
inside them
If you need to have thumbnails inside list items, you don't need to do anything special, just put the image inside the list item, and it will be displayed on the left hand side. The image can be moved to the right side by adding [data-thumbpos="right"]
attribute to the corresponding LI
element.
Sample listview markup:
22 | 23 |<ul data-role="listview">
24 | <li data-role="divider">A</li>
25 | <li>
26 | <h2>Header</h2>
27 | <p>No link</p>
28 | </li>
29 | <li><a href="#">Simple link</a></li>
30 | <li data-role="divider">Divider</li>
31 | <li><a href="#">
32 | <h2>Header</h2>
33 | <p>Header and description</p>
34 | </a></li>
35 | <li data-icon="chevron-thin-right" data-iconpos="right"><a href="#">
36 | <h2>With Icon</h2>
37 | <p>List item with icon on the right</p>
38 | </a></li>
39 | <li data-icon="chevron-thin-right" data-iconpos="right"><a href="#">
40 | <h2>With Icon and Count</h2>
41 | <p>List item with icon on the right and count</p>
42 | <span class="xf-count-bubble">32</span>
43 | </a></li>
44 | <li data-thumbpos="right"><a href="#">
45 | <img src="../img/_thumb1.jpg" alt="">
46 | <h2>With Thumbnail on the right</h2>
47 | <p>List item with a thumbnail on the right</p>
48 | </a></li>
49 | </ul>
50 |
The above code will result in:
53 | 54 |No link
59 |Header and description
65 |List item with icon on the right
69 |List item with icon on the right and count
73 | 32 74 |List item with a thumbnail on the right
79 |XF.Model
is an extended version of Backbone.Model to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:model [name]
.
XF.Model
properties:
status
: status of the data in the model. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this model.ajaxSettings
: settings for ajax requests to the server for this model. If not set global ajaxSettings
will be used. The format is the same as for $.ajax
method.XF.Model
methods:
url
: the url to the data. Could be a function or a property.refresh
: refreshes the data and triggers the view refreshing.XF.Model
hooks:
construct
: overwrite it for your own needs. Called on the construction of model.initialize
: overwrite it for your own needs. Called on the initialization of model.For other methods, properties and hooks available see Backbone.Model.
-------------------------------------------------------------------------------- /docs/supported_platforms_and_browsers.html: -------------------------------------------------------------------------------- 1 |Mobile phones and tablets:
4 | 5 |Desktop:
12 | 13 |It doesn't mean that another browsers or platforms are not supported. We just don't have a possibility to test XF across all existing platforms and browsers.
22 | 23 |The roadmap for the next versions can be found on GitHub.
-------------------------------------------------------------------------------- /docs/tabs.html: -------------------------------------------------------------------------------- 1 |Below you can find an example of tabs UI element:
4 | 5 |<div data-role="tabs">
6 | <button data-active="true">Link 1</button>
7 | <button>Link 2</button>
8 | <button>Link 3</button>
9 | <button>Link 4</button>
10 | </div>
11 |
Such code will be transformed into:
14 | 15 |<div data-role="tabs" data-id="xf-37715" id="xf-37715" data-skip-enhance="true">
16 | <ul class="xf-tabs">
17 | <li class="xf-grid-unit xf-grid-unit-1of4">
18 | <a class="xf-tabs-button xf-corner-tl xf-corner-bl" id="xf-71177">
19 | <span class="xf-tabs-button-text">Link 1</span>
20 | </a>
21 | </li>
22 | <li class="xf-grid-unit xf-grid-unit-1of4">
23 | <a class="xf-tabs-button" id="xf-7896">
24 | <span class="xf-tabs-button-text">Link 2</span>
25 | </a>
26 | </li>
27 | <li class="xf-grid-unit xf-grid-unit-1of4">
28 | <a class="xf-tabs-button" id="xf-62398">
29 | <span class="xf-tabs-button-text">Link 3</span>
30 | </a>
31 | </li>
32 | <li class="xf-grid-unit xf-grid-unit-1of4">
33 | <a class="xf-tabs-button xf-corner-tr xf-corner-br xf-tabs-button-active" id="xf-83850">
34 | <span class="xf-tabs-button-text">Link 4</span>
35 | </a>
36 | </li>
37 | </ul>
38 | </div>
39 |
There are some rules behind the XFramework:
4 | 5 |XF Generator allows you to update sources and dependencies:
4 | 5 |yo xf:update [all]
— update less and js files of XFramework, check latest versions of jQuery, Backbone, Underscoreyo xf:update scripts
— update js files (inluding thirdparty libraries) of XFramework, check latest versions of jQuery, Backbone, Underscoreyo xf:update styles
— update less files of XFrameworkXF.View
is an extended version of Backbone.View to make it perfectly fit XF Component based architecture.
To create a standalone view XF Generator can be used with yo xf:view [name]
.
XF.View
properties:
template
: contains source of the loaded template and the compiled version of it. Default: {src: null, compiled: null, cache: true }
.status
: status of the data in the view. Default: { loaded: false, loading: false, loadingFailed: false }
.component
: a link to the component for this view.XF.View
methods:
load
: loads the template from the cache or remotely.render
: renders the view. Please use refresh
instead to use it together with hooks available.refresh
: refreshes the view.getMarkup
: returns the markup using the current data.XF.View
hooks:
url
: the url to the template file. Could be a function or a property.construct
: overwrite it for your own needs. Called on the construction of view.initialize
: overwrite it for your own needs. Called on the initialization of view.beforeLoadTemplate
: called before loading of the template started.afterLoadTemplate
: called after loading of the template completed.afterLoadTemplateFailed
: called after loading of the template completed and failed.beforeRender
: called before rendering of the template.afterRender
: called after rendering of the template.Note that data from collection
or model
of the component is available in the template via localized variable data
.
For other methods, properties and hooks available see Backbone.View.
-------------------------------------------------------------------------------- /docs/what_is_xframework_.html: -------------------------------------------------------------------------------- 1 |Version 0.9.1
4 | 5 |XFramework (next XF) is a small yet powerful Javascript framework for quick development of cross-device web applications. Honestly saying, XF is a high-level framework based on Backbone.js that implements its own architecture paradigm, based on MV* on the component level.
6 | 7 |XFramework makes it easy to reuse the application logic and provide various layouts or widgets for different devices based on the criteria that you define.
8 | 9 |XFramework is designed to be extremely modular, flexible, fast, and easy to use. To develop an app in X-Framework a developer should be familiar with common web technologies such as HTML/CSS/JS, LESS for editing styles, Handlebars-style templating and have an understanding of how MV* architecture works. Experience using Backbone.js, Angular.js, Ember.js, jQuery Mobile or other framework will be helpful.
10 | 11 |TODO: update!
XFramework currently features:
XF.App
is a 'class' that you able to extend with your own methods and properties needed in the application. In this case an instance of this class is something like a main controller of the whole app.
// if the app boilerplate was created via XF Generator
6 | // these lines can be found in `app.js` file
7 | var MyApp = XF.App.extend({
8 | initialize: function () {
9 | // this code will be executed before XF will be started
10 | // but you can put the preparation code here
11 | // …
12 | this.myAwesomeMethod();
13 | },
14 | myAwesomeMethod: function () {
15 |
16 | }
17 |
18 |
19 | });
20 |
XF.device
contains the information about current user device app was launched:
XF.device.supports.touchEvents
XF.device.supports.pointerEvents
XF.device.supports.cssAnimations
XF.device.isMobile
. It was a necessary trick to detect mobile OS's using navigator.userAgent
.XF.device.type
is a selected type of devices from specified in options passed on the start of application. Based on this selected device type the necessary template for the component will be loaded.var app = new MyApp({
14 | // …
15 | // other settings for the application
16 | device: {
17 | types : [{
18 | name : 'tablet',
19 | range : {
20 | max : 1024,
21 | min : 569
22 | },
23 | templatePath : 'tablet/' // template path for tablet devices (by default it will be tmpl/tablet/componentName.tmpl)
24 | }, {
25 | name : 'phone',
26 | range : {
27 | max : 568,
28 | min : null
29 | },
30 | templatePath : 'phone/' // path to templates for phones (by default it will be tmpl/phone/componentName.tmpl)
31 | }]
32 | }
33 | });
34 |
XF.Router
is an extended [Backbone.Router]. XF cares about creation of router instance, its starting, binding handlers and so on. Everything you just need to do is to pass your routes and handlers with starting options for the application:
// if the app boilerplate was created via XF Generator
6 | // these lines cab be found in `index.js` file
7 | var app = new MyApp({
8 | // …
9 | // other settings for the application
10 | router: {
11 | routes: {
12 | '': 'home',
13 | 'search/:q': 'searchByQuery',
14 | 'item:id': 'showItemById',
15 | 'books/:cat(/:subcat)': 'showBooksCategory',
16 | 'news/*any': 'showNews'
17 | },
18 |
19 | home: function () {
20 |
21 | },
22 |
23 | searchByQuery: function (query) {
24 |
25 | },
26 |
27 | showItemById: function (id) {
28 |
29 | },
30 |
31 | showBooksCategory: function (cat, subcat) {
32 |
33 | },
34 |
35 | showNews: function (param) {
36 |
37 | }
38 | }
39 |
40 |
41 | });
42 |
In the example above the handler home
for empty route was created. In case you want to define the starting route for the application or turn off HTML5 pushState (using pushState
support is turned on by default) you should pass the necessary starting parameters to XF.history
which actually is a link to Backbone.history.
var app = new MyApp({
47 | // …
48 | // other settings for the application
49 | history: {
50 | pushState: false,
51 | root: 'books/fiction'
52 | }
53 | });
54 |
To force navigation to another url fragment a number of ways is available:
57 | 58 |XF.router.navigate('books/fiction', {trigger: true})
XF.navigate('books/fiction')
is the syntax sugar for the first approach. {trigger: true}
set by defaultXF.trigger('navigate', 'books/fiction')
is much more preferable for consistency and integrity of the applicationAll elements with the attribute data-href
or href
will work on changing url fragment.
<a data-href="books/fiction">Books</a>
67 |
This simple object contains the settings for the application, that could be overridden on the start:
4 | 5 |1.0.0
)true
)js/components/
).js
)componentUrlPrefix + compName + componentUrlPostfix
)tmpl/
).tmpl
)''
){}
)var app = new MyApp({
18 | // …
19 | // other settings for the application
20 | settings: {
21 | appVersion: '2.0.1',
22 |
23 | dataUrlPrefix: 'http://api.example.com/',
24 |
25 | ajaxSettings: {
26 | // settings that are provided to collections and models to fetch and sync the data
27 | // see $.ajax options
28 | crossDomain: true
29 | }
30 | }
31 |
32 |
33 | });
34 |
XFramework has its own building blocks that drive it on. Some blocks are mandatory to include in the build of XFramework, other ones are not required.
4 | 5 |Mandatory XF src modules are:
6 | 7 |xf.jquery.hooks.js
xf.core.js
xf.settings.js
xf.app.js
xf.router.js
xf.pages.js
xf.model.js
xf.collection.js
xf.view.js
xf.component.js
Optional XF src modules are:
21 | 22 |xf.ui.js
xf.ui.*.js
xf.touch.js
xf.utils.js
xf.storage.js
xf.zepto.support.js
XF.storage
is just a wrapper for localStorage that allows you easily to interact with it: set, get, clear.
XF.storage.set('booksCategory', 12);
6 |
7 | XF.storage.get('booksCategory');
8 |
9 | XF.storage.clear();
10 |
XF.touch
makes the life in such a multidevice world easier — it is an adapter for all types of user contexts: touch screens, mouse, pointers.
For now it contains the following user interaction events:
6 | 7 |tap
: it doesn't matter if it is a click or a touch to the screen. Just bind on tap events for all types of devices and that's it! XF.touch
fixes the 300ms gap between click and touch events as wellswipe
, swipeUp
, swipeDown
, swipeLeft
, swipeRight
This source module will contain all the helpers will needed to make the work with XF much more easier. Right now it contains only address bar hiding helper for iOS and Android mobile phones.
-------------------------------------------------------------------------------- /docs/xf_zepto_support_js.html: -------------------------------------------------------------------------------- 1 |This piece enables the support of zepto.js instead of jQuery extending it with all missing methods and properties.
4 | 5 |Attention! Include this module on your own fear and risk. It is in experimental status right away.
-------------------------------------------------------------------------------- /docs/your_first_xf_web_app.html: -------------------------------------------------------------------------------- 1 |To create the first XF application the simplest way is to use XF Generator through yo xf:application init [appName]
.
For now it scaffolds an app in the way you can see by example: XF Hello World App.
-------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "X-Framework", 3 | "version": "0.9.1", 4 | "devDependencies": { 5 | "grunt": "latest", 6 | "grunt-contrib-jshint": "latest", 7 | "grunt-contrib-nodeunit": "latest", 8 | "grunt-contrib-uglify": "latest", 9 | "grunt-contrib-concat": "latest", 10 | "grunt-contrib-less": "latest", 11 | "grunt-contrib-qunit": "latest", 12 | "grunt-recess": "latest", 13 | "grunt-processhtml": "latest", 14 | "underscore.string": "latest", 15 | "requirejs": "latest", 16 | "grunt-bower-task": "latest", 17 | "load-grunt-tasks": "latest" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git://github.com/epam/xframework.git" 22 | }, 23 | "scripts": { 24 | "test": "grunt test" 25 | }, 26 | "description": "ERROR: No README data found!", 27 | "main": "Gruntfile.js", 28 | "dependencies": { 29 | "grunt-cli": "latest", 30 | "mocha": "latest", 31 | "yeoman-generator": "latest" 32 | }, 33 | "peerDependencies": { 34 | "yo": ">=1.0.0-rc.1.1" 35 | }, 36 | "author": "EPAM", 37 | "license": "BSD" 38 | } -------------------------------------------------------------------------------- /styles/fonts/entypo-social.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo-social.eot -------------------------------------------------------------------------------- /styles/fonts/entypo-social.svg: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /styles/fonts/entypo-social.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo-social.ttf -------------------------------------------------------------------------------- /styles/fonts/entypo-social.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo-social.woff -------------------------------------------------------------------------------- /styles/fonts/entypo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo.eot -------------------------------------------------------------------------------- /styles/fonts/entypo.svg: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /styles/fonts/entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo.ttf -------------------------------------------------------------------------------- /styles/fonts/entypo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epam/xframework/6b2a1b954dc998274922feaf3a363a47258c7bd5/styles/fonts/entypo.woff -------------------------------------------------------------------------------- /styles/xf.dialog.less: -------------------------------------------------------------------------------- 1 | /* Dialogs 2 | =========================================== */ 3 | 4 | .xf-dialog { 5 | position: fixed; 6 | display: block; 7 | z-index: 1000; 8 | width: 100%; 9 | height: 100%; 10 | top: 0; 11 | left: 0; 12 | text-align: center; 13 | } 14 | .xf-dialog:before { 15 | height: 100%; 16 | content: ""; 17 | display: inline-block; 18 | vertical-align: middle; 19 | margin-left: -4px; 20 | } 21 | .xf-dialog-content { 22 | text-align: left; 23 | display: inline-block; 24 | vertical-align: middle; 25 | max-height: 95%; 26 | max-width: 95%; 27 | } 28 | .xf-dialog-box { 29 | padding: 16px; 30 | margin: 16px; 31 | //.xf-corner-all; 32 | } 33 | .xf-dialog { 34 | background: @dialog-dim-color; 35 | } 36 | .xf-dialog-box { 37 | //border: 2px solid @dialog-box-border-color; 38 | .bg-gradient(@dialog-box-bg-color-start, @dialog-box-bg-color-start, @dialog-box-bg-color-end); 39 | text-shadow: 0 1px 0 @dialog-box-text-shadow-color; 40 | color: @dialog-box-text-color; 41 | } 42 | .xf-dialog-box-header { 43 | h1, h2, h3, h4, h5, h6 { 44 | margin-top: 0; 45 | margin-bottom: 18px; 46 | } 47 | } 48 | .xf-dialog-box-content { 49 | min-height: 2em; 50 | margin: 1em 0; 51 | } 52 | .xf-dialog-box-footer { 53 | .xf-grid-unit { 54 | padding-left: 8px; 55 | padding-right: 8px; 56 | 57 | &:first-child { 58 | padding-left:0; 59 | } 60 | &:last-child { 61 | padding-right:0; 62 | } 63 | } 64 | } 65 | 66 | /* Loader dialog */ 67 | 68 | .xf-dialog-notification { 69 | background: none; 70 | } 71 | .xf-notification { 72 | display: table; 73 | vertical-align: middle; 74 | text-align: center; 75 | height: 120px; 76 | width: 120px; 77 | .xf-corner-all; 78 | } 79 | .xf-notification { 80 | background: @notification-bg-color; 81 | color: @notification-text-color; 82 | //text-shadow: 0 1px 0 @notification-text-shadow-color; 83 | } 84 | .xf-notification-wrap { 85 | display: table-cell; 86 | vertical-align: middle; 87 | height: 110px; 88 | width: 110px; 89 | padding: 10px 90 | } 91 | 92 | .xf-notification-text { 93 | margin-top: 2px; 94 | font-weight: bold; 95 | } -------------------------------------------------------------------------------- /styles/xf.footer.less: -------------------------------------------------------------------------------- 1 | 2 | /* Footer Navigation 3 | =========================================================== */ 4 | 5 | .xf-footer { 6 | position: relative; 7 | z-index: 20; 8 | } 9 | .xf-footer-fixed { 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | bottom: 0; 14 | } 15 | .xf-nav { 16 | position: relative; 17 | overflow: hidden; 18 | margin: 0; 19 | padding: 0; 20 | 21 | border-top:1px solid @nav-bg-color; 22 | background: @nav-bg-color; 23 | color: @nav-item-text-color; 24 | } 25 | .xf-nav-item { 26 | display: block; 27 | position:relative; 28 | .box-sizing-border-box; 29 | height: 48px; 30 | padding: 4px; 31 | text-align: center; 32 | text-decoration: none; 33 | 34 | color: @nav-item-text-color; 35 | background: -moz-linear-gradient(top, @nav-item-bg-color-start 0%, @nav-item-bg-color-end 50%); 36 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, @nav-item-bg-color-start), color-stop(50%,@nav-item-bg-color-end)); 37 | background: -webkit-linear-gradient(top, @nav-item-bg-color-start 0%, @nav-item-bg-color-end 50%); 38 | background: -o-linear-gradient(top, @nav-item-bg-color-start 0%, @nav-item-bg-color-end 50%); 39 | background: -ms-linear-gradient(top, @nav-item-bg-color-start 0%, @nav-item-bg-color-end 50%); 40 | background: linear-gradient(top, @nav-item-bg-color-start 0%, @nav-item-bg-color-end 50%); 41 | 42 | border-top: 1px solid @nav-item-border-color; 43 | } 44 | .xf-nav-item.xf-iconpos-top { 45 | padding: 32px 4px 2px 4px; 46 | } 47 | .xf-nav-item-text { 48 | .overflow-ellipsis; 49 | font-size: 10px; 50 | } 51 | .xf-nav-item .xf-icon { 52 | position: absolute; 53 | 54 | color: @nav-item-icon-color; 55 | } 56 | .xf-nav-item.xf-iconpos-top .xf-icon { 57 | top: 2px; 58 | left:-15px; 59 | margin-left: 50%; 60 | } 61 | .xf-has-footer { 62 | margin-bottom: 50px; 63 | } 64 | .xf-nav-item-active { 65 | //.gradient(@nav-item-active-bg-color-start, @nav-item-active-bg-color-end); 66 | border-color: @nav-item-active-border-color; 67 | color: @nav-item-active-text-color; 68 | } 69 | .xf-nav-item-active .xf-icon { 70 | color: @nav-item-active-icon-color; 71 | } 72 | .xf-nav-item:hover { 73 | background-repeat: no-repeat; 74 | .background-size(100% 130%); 75 | } 76 | -------------------------------------------------------------------------------- /styles/xf.header.less: -------------------------------------------------------------------------------- 1 | 2 | /* Header 3 | ========================================== */ 4 | 5 | .xf-header { 6 | display: block; 7 | position: relative; 8 | min-height: 43px; 9 | z-index: 20; /* z-index > 0 causes the rotated pseudo-el inside .xf-button-back to not be rotated on android*/ 10 | text-align: center; 11 | border-bottom: 1px solid transparent; 12 | background: @header-bg-color-end; 13 | .bg-gradient(@header-bg-color-start, @header-bg-color-start, @header-bg-color-end); 14 | border-bottom: 1px solid @header-border-color; 15 | } 16 | .xf-header-title { 17 | margin: 0 8px; 18 | padding: 0; 19 | font: bold 18px sans-serif; 20 | line-height: 43px; 21 | vertical-align: middle; 22 | .overflow-ellipsis; 23 | 24 | color: @header-text-color; 25 | text-shadow: 0 1px 0 @header-text-shadow-color; 26 | } 27 | .xf-button-header-left + .xf-header-title, 28 | .xf-button-header-right + .xf-header-title { 29 | margin-left: 80px; 30 | margin-right: 80px; 31 | } 32 | 33 | 34 | .xf-button-header-left, 35 | .xf-button-header-right { 36 | position: absolute; 37 | top: 0; 38 | height: 44px; 39 | line-height: 43px; 40 | min-width: 44px; 41 | background: none; 42 | max-width: 66px; 43 | } 44 | .xf-button-header-left { 45 | left: 0; 46 | } 47 | .xf-button-header-right { 48 | right: 0; 49 | } 50 | 51 | .xf-header-fixed { 52 | position: fixed; 53 | left: 0; 54 | right: 0; 55 | top: 0; 56 | } 57 | 58 | .xf-has-header { 59 | margin-top: 44px; 60 | } -------------------------------------------------------------------------------- /styles/xf.layout.less: -------------------------------------------------------------------------------- 1 | 2 | /* Layout 3 | ========================================== */ 4 | 5 | .xf-grid-unit-1of1 { width: 100%;float:none; display: block;} 6 | .xf-grid-unit-1of2, 7 | .xf-grid-unit-2of4, 8 | .xf-grid-unit-3of6 { width:50%;} 9 | .xf-grid-unit-1of3, 10 | .xf-grid-unit-2of6 { width:33.333333%;} 11 | .xf-grid-unit-2of3, 12 | .xf-grid-unit-4of6 { width:66.666666%;} 13 | .xf-grid-unit-1of4 { width:25%;} 14 | .xf-grid-unit-3of4 { width:75%;} 15 | .xf-grid-unit-1of5 { width:20%;} 16 | .xf-grid-unit-2of5 { width:40%;} 17 | .xf-grid-unit-3of5 { width:60%;} 18 | .xf-grid-unit-4of5 { width:80%;} 19 | .xf-grid-unit-1of6 { width:16.66666666%;} 20 | .xf-grid-unit-5of6 { width:83.33333333%;} 21 | 22 | .xf-grid-unit { 23 | float: left; 24 | margin: 0; 25 | padding: 0; 26 | list-style: none; 27 | .box-sizing-border-box; 28 | } 29 | .xf-indented { 30 | padding-top: 8px; 31 | padding-left: 8px; 32 | padding-right: 8px; 33 | } 34 | .xf-grid-padded { 35 | 36 | >.xf-grid-unit{ 37 | padding-left: 8px; 38 | padding-right: 8px; 39 | } 40 | 41 | >.xf-grid-unit:first-child { 42 | padding-left: 0; 43 | } 44 | 45 | >.xf-grid-unit:last-child { 46 | padding-right: 0; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /styles/xf.less: -------------------------------------------------------------------------------- 1 | 2 | /* X-Framework styles 3 | Author: Pavel_Shut@epam.com 4 | ============================== */ 5 | 6 | 7 | @import 'xf.reset.less'; 8 | @import 'xf.type.less'; 9 | 10 | @import 'xf.variables.less'; // Modify this for custom colors, font-sizes, etc 11 | 12 | 13 | @import "xf.mixins.less"; 14 | @import 'lesshat.less'; 15 | 16 | @import 'xf.pages.less'; 17 | @import 'xf.animations.less'; 18 | @import 'xf.layout.less'; 19 | 20 | @import 'xf.icons.less'; 21 | @import 'xf.forms.less'; 22 | @import 'xf.buttons.less'; 23 | 24 | @import 'xf.header.less'; 25 | @import 'xf.footer.less'; 26 | @import 'xf.tabs.less'; 27 | @import 'xf.list.less'; 28 | @import 'xf.dialog.less'; 29 | @import 'xf.loader.less'; 30 | 31 | //@import 'your.stylesheet.less'; // Import your styles before utilities 32 | 33 | @import 'xf.utilities.less'; 34 | -------------------------------------------------------------------------------- /styles/xf.loader.less: -------------------------------------------------------------------------------- 1 | /* Loader 2 | =========================================== */ 3 | .xf-loader { 4 | position: fixed; 5 | display: block; 6 | z-index: 1000; 7 | width: 100%; 8 | height: 100%; 9 | top: 0; 10 | left: 0; 11 | text-align: center; 12 | background: @dialog-dim-color; 13 | } 14 | .xf-loader:before { 15 | height: 100%; 16 | content:""; 17 | display: inline-block; 18 | vertical-align: middle; 19 | margin-left: -4px; 20 | } 21 | .xf-loader-content { 22 | background: @notification-bg-color; 23 | width: 110px; 24 | height: 110px; 25 | padding: 10px; 26 | border-radius: 5px; 27 | -webkit-border-radius: 5px; 28 | -moz-border-radius: 5px; 29 | -o-border-radius: 5px; 30 | position: absolute; 31 | top: 50%; 32 | left: 50%; 33 | margin-left: -65px; 34 | margin-top: -65px; 35 | } 36 | .loading { 37 | width: 3em; 38 | height: 3em; 39 | margin: 32px; 40 | -moz-animation: rotatex 0.6s linear 0s infinite; 41 | -ms-animation: rotatex 0.6s linear 0s infinite; 42 | -o-animation: rotatex 0.6s linear 0s infinite; 43 | -webkit-animation: rotatex 0.6s linear 0s infinite; 44 | animation: rotatex 0.6s linear 0s infinite; 45 | -moz-box-shadow: inset 0.15em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.15em 0 rgba(252, 150, 0, 0.5), inset -0.15em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.15em 0 rgba(0, 150, 255, 0.5); 46 | -o-box-shadow: inset 0.15em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.15em 0 rgba(252, 150, 0, 0.5), inset -0.15em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.15em 0 rgba(0, 150, 255, 0.5); 47 | -webkit-box-shadow: inset 0.15em 0 1px rgba(255, 0, 0, 0.5), inset 0 0.15em 1px rgba(252, 150, 0, 0.5), inset -0.15em 0 1px rgba(0, 255, 0, 0.5), inset 0 -0.15em 1px rgba(0, 150, 255, 0.5); 48 | box-shadow: inset 0.15em 0 0 rgba(255, 0, 0, 0.5), inset 0 0.15em 0 rgba(252, 150, 0, 0.5), inset -0.15em 0 0 rgba(0, 255, 0, 0.5), inset 0 -0.15em 0 rgba(0, 150, 255, 0.5); 49 | -o-transition: 1s linear rotate(3600deg); 50 | } 51 | .loading, .loading:before, .loading:after { 52 | border-radius: 10em; 53 | -webkit-border-radius: 10em; 54 | -moz-border-radius: 10em; 55 | -o-border-radius: 10em; 56 | } 57 | @-moz-keyframes rotatex { 58 | 0% { 59 | -moz-transform: rotate(0deg); 60 | } 61 | 100% { 62 | -moz-transform: rotate(360deg); 63 | } 64 | } 65 | @-o-keyframes rotatex { 66 | 0% { 67 | -o-transform: rotate(0deg); 68 | } 69 | 100% { 70 | -o-transform: rotate(360deg); 71 | } 72 | } 73 | @-ms-keyframes rotatex { 74 | 0% { 75 | -ms-transform: rotate(0deg); 76 | } 77 | 100% { 78 | -ms-transform: rotate(360deg); 79 | } 80 | } 81 | @-webkit-keyframes rotatex { 82 | 0% { 83 | -webkit-transform: rotate(0deg); 84 | } 85 | 100% { 86 | -webkit-transform: rotate(360deg); 87 | } 88 | } 89 | @keyframes rotatex { 90 | 0% { 91 | transform: rotate(0deg); 92 | } 93 | 100% { 94 | transform: rotate(360deg); 95 | } 96 | } -------------------------------------------------------------------------------- /styles/xf.pages.less: -------------------------------------------------------------------------------- 1 | html, body, .xf-viewport { 2 | height: 100%; 3 | width: 100%; 4 | background: @app-bg; 5 | color: @text-color; 6 | } 7 | 8 | .viewport, 9 | .xf-viewport { 10 | position: relative; 11 | margin: 0; 12 | overflow-x: visible; 13 | -webkit-text-size-adjust: none; 14 | -ms-text-size-adjust: none; 15 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 16 | -webkit-touch-callout: none; 17 | } 18 | /* .viewport is body, or an element wrapping all content inside it, e.g. form 19 | https://github.com/jquery/jquery-mobile/issues/2066 */ 20 | body.viewport, 21 | div.viewport, 22 | body.xf-viewport, 23 | div.xf-viewport { 24 | overflow-x: hidden; 25 | } 26 | 27 | .xf-page { 28 | position: absolute; 29 | width: 100%; 30 | min-height: 100%; 31 | left: 0; 32 | top: 0; 33 | border: 0; 34 | display: none; 35 | outline: none; /* on ios4, setting focus on the page element causes flashing during transitions when there is an outline */ 36 | visibility: visible; 37 | z-index: 1; 38 | 39 | background: @page-bg; 40 | } 41 | .xf-page-active { 42 | display: block; 43 | overflow: visible; 44 | } 45 | 46 | .xf-page-content { 47 | overflow: hidden; 48 | position: relative; 49 | z-index: 10; 50 | } -------------------------------------------------------------------------------- /styles/xf.tabs.less: -------------------------------------------------------------------------------- 1 | 2 | /* Tabs 3 | ========================================== */ 4 | 5 | .xf-tabs { 6 | display: block; 7 | position: relative; 8 | margin: 5px 0 3px; /* 5&3 to we compensate for the shift when buttons have borders and are moved 1px up and left */ 9 | padding: 0 0 0 1px; 10 | .box-sizing-border-box; 11 | list-style: none; 12 | 13 | margin-top: 5px; /* */ 14 | margin-bottom: 3px; 15 | .clearfix(); 16 | 17 | } 18 | .xf-tabs-button { 19 | display: block; 20 | position: relative; 21 | .box-sizing-border-box; 22 | height: 44px; 23 | padding: 10px; 24 | //margin: -1px 0 0 -1px; /* needed to hide adjacent borders */ 25 | text-decoration: none; 26 | text-align: center; 27 | cursor: pointer; 28 | color: @button-text-color; 29 | text-shadow: @tabs-text-shadow; 30 | .bg-gradient(@tabs-active-bg-color-start, @tabs-active-bg-color-start, @tabs-active-bg-color-end); 31 | 32 | //border-left: 1px solid white; 33 | //border-right: 1px solid white; 34 | border-bottom: 5px solid @tabs-border-color; 35 | 36 | &:hover { 37 | -webkit-background-size: 100% 150%; 38 | background-size: 100% 150%; 39 | } 40 | } 41 | .xf-grid-unit:first-child > .xf-tabs-button { 42 | border-left: none; 43 | } 44 | .xf-grid-unit-1of2 ~ .xf-grid-unit:last-child > .xf-tabs-button, 45 | .xf-grid-unit-1of3 ~ .xf-grid-unit:last-child > .xf-tabs-button, 46 | .xf-grid-unit-1of4 ~ .xf-grid-unit:last-child > .xf-tabs-button { 47 | border-right: none; 48 | margin-right: 0px; 49 | } 50 | 51 | .xf-tabs-button-text { 52 | display: block; 53 | height: 24px; 54 | line-height: 24px; 55 | vertical-align: middle; 56 | .overflow-ellipsis; 57 | color: @tabs-text-color; 58 | } 59 | 60 | .xf-tabs-button-active { 61 | z-index: 1; 62 | .bg-gradient(@tabs-active-bg-color-start, @tabs-active-bg-color-start, @tabs-active-bg-color-end); 63 | color: @tabs-active-text-color; 64 | text-shadow: @tabs-text-shadow; 65 | font-weight: bold; 66 | border-bottom: 5px solid @tabs-active-border-color; 67 | 68 | &:hover { 69 | -webkit-background-size: auto; 70 | background-size: auto; 71 | cursor: default; 72 | border-bottom: 5px solid @tabs-active-border-color; 73 | } 74 | } 75 | .xf-tabs-button-active .xf-tabs-button-text { 76 | } -------------------------------------------------------------------------------- /styles/xf.theme.dark.less: -------------------------------------------------------------------------------- 1 | /* Overrides specific for Dark theme 2 | ===================================== */ 3 | 4 | .xf-theme-dark { 5 | } 6 | 7 | .xf-header { 8 | .border-box; 9 | border: 1px solid #212325; 10 | .box-shadow(~"inset 0 1px 0 rgba(255,255,255,.2), 0 1px 1px rgba(0,0,0,.55)"); 11 | } -------------------------------------------------------------------------------- /styles/xf.utilities.less: -------------------------------------------------------------------------------- 1 | 2 | /* non-semantic helper classes 3 | ========================================================================== */ 4 | 5 | /* prevent callout */ 6 | .nocallout {-webkit-touch-callout: none;} 7 | 8 | /* A workaround for S60 3.x and 5.0 devices which do not animated gif images if they have been set as display: none */ 9 | .gifhidden {position: absolute; left: -100%;} 10 | 11 | /* For image replacement */ 12 | .ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; } 13 | .ir br { display: none; } 14 | 15 | /* Hide from both screenreaders and browsers: h5bp.com/u */ 16 | .hidden { display: none !important; visibility: hidden; } 17 | 18 | /* Hide only visually, but have it available for screenreaders: h5bp.com/v */ 19 | .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } 20 | 21 | /* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */ 22 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } 23 | 24 | /* Hide visually and from screenreaders, but maintain layout */ 25 | .invisible { visibility: hidden; } 26 | 27 | /* Contain floats: h5bp.com/q */ 28 | .clearfix:before, .clearfix:after { content: ""; display: table; } 29 | .clearfix:after { clear: both; } 30 | * + html .clearfix { *zoom: 1; } 31 | 32 | -------------------------------------------------------------------------------- /styles/xf.variables.theme.dark.less: -------------------------------------------------------------------------------- 1 | /* ================================================= 2 | Dark theme 3 | ==================================================== */ 4 | 5 | 6 | @app-bg: #404040; 7 | @page-bg: @app-bg; 8 | @text-color: #fff; 9 | @general-border-color: #3C3C3C;//#b2b2b2; 10 | 11 | 12 | // Inputs 13 | @input-bg-color: #fff; 14 | @input-active-bg-color: #669cf1; 15 | @input-inactive-bg-color: #e6e6e6; 16 | @input-text-color: #294d8c; 17 | @input-label-color: #333; 18 | @input-placeholder-color: #c8c8cc; 19 | 20 | 21 | // Buttons 22 | @button-bg-color-start: #fff; 23 | @button-bg-color-end: #bfbfbd; 24 | @button-border-color: rgba(0,0,0,.6); 25 | @button-text-color: #555; 26 | @button-text-shadow-color: rgba(255,255,255,.7);// tbd 27 | 28 | @button-active-bg-color-start: #6ea5fa; 29 | @button-active-bg-color-end: #2e5fb2; 30 | @button-active-border-color: #315eab; 31 | @button-active-text-color: #fff; 32 | @button-active-text-shadow-color: rgba(0,0,0,.7); 33 | 34 | @button-alert-bg-color-start: #fa6e6e; 35 | @button-alert-bg-color-end: #bc0101; 36 | //@button-alert-border-color: @button-border-color; 37 | @button-alert-text-color: #fff; 38 | @button-alert-text-shadow-color: rgba(0,0,0,.7); 39 | 40 | 41 | // Header 42 | @header-bg-color-start: #717a80; 43 | @header-bg-color-end: #383d40; 44 | @header-border-color: #212325; 45 | @header-text-color: #e3e3e3; 46 | @header-text-shadow-color: rgba(0,0,0,.7); 47 | 48 | 49 | /* Footer nav */ 50 | @nav-bg-color: #fff; 51 | @nav-item-bg-color-start: #fff; 52 | @nav-item-bg-color-end: #bfbfbd; 53 | @nav-item-border-color: #d9d9d9; 54 | @nav-item-text-color: #555; 55 | @nav-item-icon-color: #666; 56 | 57 | @nav-item-active-text-color: #262626; 58 | @nav-item-active-icon-color: #333; 59 | @nav-item-active-bg-color-start: rgba(0,0,0,0); 60 | @nav-item-active-bg-color-end: rgba(0,0,0,0); 61 | @nav-item-active-border-color: @nav-item-border-color; 62 | 63 | 64 | // Lists 65 | @list-bg-color: #fff; 66 | @list-icon-color: #969699; 67 | @list-text-color: @input-label-color; 68 | @count-bubble-bg-color: @list-icon-color; 69 | @count-bubble-text-color: @list-bg-color; 70 | 71 | 72 | /* Dialogs */ 73 | @dialog-dim-color: rgba(255,255,255,.4); 74 | @dialog-box-border-color: rgba(0,0,0,0); 75 | @dialog-box-bg-color-start: rgba(0,0,0,.7); 76 | @dialog-box-bg-color-end: rgba(0,0,0,.7); 77 | @dialog-box-text-color: #e3e3e3; 78 | @dialog-box-text-shadow-color: #000; 79 | 80 | @notification-bg-color: rgba(0,0,0,.7); 81 | @notification-text-color: #e3e3e3; 82 | @notification-text-shadow-color: #000; 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /test/components/test.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | XF.defineComponent( 3 | 'test', 4 | XF.Component.extend({ 5 | 6 | View : XF.View.extend({ 7 | useCache : false, 8 | afterRender : function () { 9 | $('#testcomponent').on('tap', function () { 10 | tap = true; 11 | }).on('swipe', function () { 12 | swipe = true; 13 | }).on('swipeLeft', function () { 14 | swipeLeft = true; 15 | }).on('swipeRight', function () { 16 | swipeRight = true; 17 | }).on('swipeUp', function () { 18 | swipeUp = true; 19 | }).on('swipeDown', function () { 20 | swipeDown = true; 21 | }); 22 | 23 | $('button').on('tap', function() { 24 | alert(49); 25 | }); 26 | } 27 | }), 28 | 29 | Model : null, 30 | Collection: XF.Collection.extend({ 31 | url : 'test.json' 32 | }) 33 | 34 | }) 35 | ); 36 | }); -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |