资源说明:XFramework, or XF, is a small but powerful HTML5 JavaScript framework for building truly cross-platform web applications that will work on mobile phones, tablets, desktop computers, and even Smart TVs.
XFramework =========== ![Travis build](https://travis-ci.org/epam/xframework.png) [![Dependency Status](https://gemnasium.com/epam/xframework.png)](https://gemnasium.com/epam/xframework) # Getting started ## What is XFramework? Version 0.9.1 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](http://backbonejs.org) that implements its own architecture paradigm, based on MV* on the component level. 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. 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. XFramework currently features: * TOTALLY CROSS-PLATFORM. XF supports all the popular devices and platroms. It is built in the way that allows you easily to change templates for each of the platforms without huge effort. * SCALABLE ARCHITECTURE. Component-based modular event-driven architecture provides a possibility to build scalable and maintainable web apps with high-reusability of components. * CUTE & CUSTOMIZABLE. XF uses LESS as preprocessor for CSS. It goes with a default theme that could be easily customized changing some lines of CSS code. * LIBRARY OF COMPONENTS. Reusability is a king! XF is flexible and extandable to the roots: it goes with a library of predefined components but feel free to write your own components and submit it to us! * POWERFUL RICH UI-ELEMENTS. Set of powerful rich UI-elements (e.g. form elements, buttons, lists) for different platforms gives a ability to provide the best user experience for each device type. And the number of UI-elements s growing! * FLEXIBILITY TO FEEL THE FREEDOM. Build process allows you to create a custom build of XFramework and use it together with your favorite UI-library like [jQuery Mobile](http://jquerymobile.com) or [Ratchet](http://maker.github.io/ratchet/). ## Supported Platforms and Browsers Desktop: * Internet Explorer 8+ * Firefox 4+ * Safari 5+ * Opera 11+ * Chrome 18+ Mobile phones and tablets: * iOS 5+: Mobile Safari, Chrome for Mobile, UC Browser on iPad 2 (iOS 5.1), iPhone 4S (iOS 5.1), iPhone 5 (iOS 5.1), iPad 3 (iOS 5.1) * Android 2.3.3+: Android Browser, Opera Mobile, Chrome for Mobile, Firefox Mobile on Motorola Droid 3 (Android 2.3.4), HTC Inspire 4G (Android 2.3.3), ASUS Nexus 7 (Android 4.1), Samsung Nexus S (Android 2.3.4), Sony Ericsson Xperia X10 (Android 2.3.3) * BlackBerry OS 6+: BlackBerry Browser on BlackBerry Torch 9800 (BlackBerry OS 6.0) * Windows Phone 7.5+ 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. The roadmap for the next versions can be found on [GitHub](https://github.com/epam/x-framework/issues). ## The idea behind There are some rules behind the XFramework: * Component-based event-driven architecture * Components easily customizable with options * Lazy loading of components * Different templates for each of device types ## Installing XFramework Generator 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](http://nodejs.org) * [NPM](https://npmjs.org) * [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/](http://nodejs.org/download/). For other platforms see the [readme](https://npmjs.org/doc/README.html). 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`. ## Your first XF web app 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](http://xframeworkjs.org/helloworld/). ## Building your XF app for testing and production `yo xf:application build [appName]` ## Creation of custom XFramework build Custom xf.js and xf.min js build: * `yo xf:build` — create build with all UI elements and source modules * `yo xf:build [srcModule1:srcModule2]` — create build with all UI elements and source modules Full list of available elements can be found at `xf/ui` and `xf/src` directory of XFramework repository. ## Updating XF and dependencies XF Generator allows you to update sources and dependencies: * `yo xf:update [all]` — update less and js files of XFramework, check latest versions of jQuery, Backbone, Underscore * `yo xf:update scripts` — update js files (inluding thirdparty libraries) of XFramework, check latest versions of jQuery, Backbone, Underscore * `yo xf:update styles` — update less files of XFramework # XFramework internals ## XF source modules 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. Mandatory XF src modules are: * `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: * `xf.ui.js` * `xf.ui.*.js` * `xf.touch.js` * `xf.utils.js` * `xf.storage.js` * `xf.zepto.support.js` ## XF.App `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. ```javascript // if the app boilerplate was created via XF Generator // these lines can be found in `app.js` file var MyApp = XF.App.extend({ initialize: function () { // this code will be executed before XF will be started // but you can put the preparation code here // … this.myAwesomeMethod(); }, myAwesomeMethod: function () { } }); ``` ## XF.device `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. ```javascript var app = new MyApp({ // … // other settings for the application device: { types : [{ name : 'tablet', range : { max : 1024, min : 569 }, templatePath : 'tablet/' // template path for tablet devices (by default it will be tmpl/tablet/componentName.tmpl) }, { name : 'phone', range : { max : 568, min : null }, templatePath : 'phone/' // path to templates for phones (by default it will be tmpl/phone/componentName.tmpl) }] } }); ``` ## XF.Router `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: ```javascript // if the app boilerplate was created via XF Generator // these lines cab be found in `index.js` file var app = new MyApp({ // … // other settings for the application router: { routes: { '': 'home', 'search/:q': 'searchByQuery', 'item:id': 'showItemById', 'books/:cat(/:subcat)': 'showBooksCategory', 'news/*any': 'showNews' }, home: function () { }, searchByQuery: function (query) { }, showItemById: function (id) { }, showBooksCategory: function (cat, subcat) { }, showNews: function (param) { } } }); ``` 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](http://backbonejs.org/#History). ```javascript var app = new MyApp({ // … // other settings for the application history: { pushState: false, root: 'books/fiction' } }); ``` To force navigation to another url fragment a number of ways is available: * `XF.router.navigate('books/fiction', {trigger: true})` * `XF.navigate('books/fiction')` is the syntax sugar for the first approach. `{trigger: true}` set by default * `XF.trigger('navigate', 'books/fiction')` is much more preferable for consistency and integrity of the application All elements with the attribute `data-href` or `href` will work on changing url fragment. ```html Books ``` ## XF.pages `XF.pages` drives the appearance of the pages sticking together with the router. It has some basic animations for switching pages such like `slideleft`, `slideright`, `fade` and `none`. Not so much for now but keep in mind that it is possible to define your own animation to use it together with `XF.pages`. To create a page you just need to make a `` with necessary classes): ```html ``` `id` is used to make page switching work together with the router. It should be equal to first url fragment of the route (e.g. `books/:cat(/:subcat)`) or the name of the handler (e.g. `showBooksCategory`). In this case the page with such id attribute will be shown automatically when the route (e.g. `books/fiction`) will be triggered. To show the page without changing the url or using route binding: ```javascript XF.trigger('pages:show', 'books', 'fade'); // …directly XF.pages.show('books', 'fade'); ``` To define the default animation type for all device types it's needed to set up the necessary properties on the start of app: ```javascript var app = new MyApp({ // … // other settings for the application animations: { standardAnimation: 'slideleft' // 'slideleft' is default } }); ``` If you want to create your own animation type and use it for page switching you (please care about necessary CSS animations in `xf.animations.less` file): ```javascript var app = new MyApp({ // … // other settings for the application animations: { types: { 'myOwnAnimation': { fallback: function (fromPage, toPage) { // fallback to JS animation for old legacy browsers /// … } } } } }); ``` To define the default animation for each of device types it's needed to pass such parameters together with device options on the start of application or set it in the runtime: ```javascript var app = new MyApp({ // … // other settings for the application device: { types : [{ name : 'tablet', range : { max : 1024, min : 569 }, templatePath : 'tablet/', defaultAnimation: 'fade' // 'fade' for tablet devices }, { name : 'phone', range : { max : 568, min : null }, templatePath : 'phone/' // 'slide left' will be used for device type 'phone' }] } }); XF.trigger('pages:animation:default', 'fade'); // …or not so elegant way XF.setDefaultAnimationType('fade'); ``` The situations if changing of the next animation type for the page is needed are not so uncommon, e.g. back button tap should force `slide right` animation instead of `slideleft`. In such cases there are some ways to do it: * Define `data-animation` attribute on the element with `data-href`: ```html Back ``` * Set the next animation type programmatically: ```javascript XF.trigger('pages:animation:next', 'slideright'); // …or not so elegant way XF.setNextAnimationType('slideright'); ``` ## XF.settings This simple object contains the settings for the application, that could be overridden on the start: * appVersion (default: `1.0.0`) * noCache (default: `true`) * componentUrlPrefix (default: `js/components/`) * componentUrlPostfix (default: `.js`) * componentUrl (default: `componentUrlPrefix + compName + componentUrlPostfix`) * templateUrlPrefix (default: `tmpl/`) * templateUrlPostfix (default: `.tmpl`) * dataUrlPrefix (default: `''`) * ajaxSettings (default: `{}`) ```javascript var app = new MyApp({ // … // other settings for the application settings: { appVersion: '2.0.1', dataUrlPrefix: 'http://api.example.com/', ajaxSettings: { // settings that are provided to collections and models to fetch and sync the data // see $.ajax options crossDomain: true } } }); ``` ## XF.touch `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: * `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 well * `swipe`, `swipeUp`, `swipeDown`, `swipeLeft`, `swipeRight` ## XF.storage `XF.storage` is just a wrapper for localStorage that allows you easily to interact with it: set, get, clear. ```javascript XF.storage.set('booksCategory', 12); XF.storage.get('booksCategory'); XF.storage.clear(); ``` ## XF.utils 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. ## XF.zepto.support.js This piece enables the support of [zepto.js](http://zeptojs.com) instead of jQuery extending it with all missing methods and properties. **Attention**! Include this module on your own fear and risk. It is in experimental status right away. # XFramework Components ## Component 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. 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. To use a component a developer places a marker where the component will be rendered. The marker is awith special attributes which denote the component's name and instance id. See an example of two nested components declared in the page markup: ```htmlThis content will be shown while component is loading...``` Such an approach lets a developer build asynchronuous UIs and avoid loading extraneous resources. There's a way to customize the component with the starting options from outside: ```htmlThis content will be shown while component is loading...``` You can use `XF.setOptionsByID` method in the place you decided but before component instance was created. If it's needed to load component only on one device type attribute can be used: ```html ``` ## Component creation There are two ways to create a component: * Using XF Generator `yo xf:component [name]` that will scaffold a javascript file together with templates for all device types * Manually Every 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. ```javascript XF.define( 'MyApp.components.categoryList', // just 'categoryList' is fine as well function () { return XF.Component.extend({ construct: function () { // will be called on the start of construction }, initialize: function () { // this method will be called after component construction }, // for more flexibility you can define Views in separate files View: XF.View.extend({ initialize: function () { } }), // for more flexibility you can define Collections in separate files Collection: XF.Collection.extend({ url: 'books.json', initialize: function () { } }) }); } ); ``` This call defines a new component using component name and component class. `XF.define` uses AMD API, so it is possible to define dependencies as well. ```javascript XF.define( 'categoryList', ['js/views/categoryView.js', 'js/collections/categoryCollection.js'], function (categoryView, categoryCollection) { return XF.Component.extend({ construct: function () { // will be called on the start of construction }, initialize: function () { // this method will be called after component construction }, // for more flexibility you can define Views in separate files View: categoryView, // for more flexibility you can define Collections in separate files Collection: categoryCollection }); } ); ``` **Component name**: used to setup a placeholder (-s) for instance (-s) of the component and should be unique within the application. **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. You may add/override properties of the component model, collection and view. Basically you are able to modify everything you see. 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 id * `name`: component name * `options`: 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. ## Collection `XF.Collection` is an extended version of [Backbone.Collection](http://backbonejs.org/#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](http://backbonejs.org/#Collection). ## Model `XF.Model` is an extended version of [Backbone.Model](http://backbonejs.org/#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](http://backbonejs.org/#Model). ## View `XF.View` is an extended version of [Backbone.View](http://backbonejs.org/#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](http://backbonejs.org/#View). ## List of built-in events ### XF level (`XF.on`, `XF.off`, `XF.trigger`, etc.) * `app:started`: when the app has started * `component:componentID:constructed`: when the component with id `componentID` has been constructed * `component: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. ### Component level * `refresh`: command to refresh the component ### Model level * `fetched`: when the data has been loaded from the backend * `refresh`: command to refresh the data of model Keep in mind that all [Backbone.js built-in events](http://backbonejs.org/#Events-catalog) are available. ### Collection level * `fetched`: when the data has been loaded from the backend * `refresh`: command to refresh the data of collection Keep in mind that all [Backbone.js built-in events](http://backbonejs.org/#Events-catalog) are available. ### View level * `rendered`: when the view has been rendered * `loaded`: when the template has been loaded * `refresh`: command to rerender the view Keep in mind that all [Backbone.js built-in events](http://backbonejs.org/#Events-catalog) are available. # UI Elements ## Basics 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. Each UI element has a simple markup that will be enhanced into the rich element. ```html``` Will be converted to: ```html
- A
Header
No link
- Simple link
- Divider
Header
Header and description
``` 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. ## Buttons Inputs of types submit, reset, button, `
- A
Header
No link
- Simple link
- Divider
Header
Header and description
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。