Last active
March 12, 2017 21:31
-
-
Save ro0gr/ca118c1e9cf72cfb4034cd944f634f95 to your computer and use it in GitHub Desktop.
routable-tabs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| import layout from '../templates/components/routable-tabs'; | |
| export default Ember.Component.extend({ | |
| classNameBindings: ['blockName'], | |
| layout, | |
| blockName: 'routable-tabs', | |
| tagName: 'ul' | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| import layout from '../../templates/components/routable-tabs/tab-item'; | |
| export default Ember.Component.extend({ | |
| classNameBindings: ['elementName'], | |
| layout, | |
| elementName: 'routable-tabs__tab-item', | |
| tagName: 'li' | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Ember Twiddle' | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| const { | |
| computed, | |
| isEmpty, | |
| assign, | |
| ArrayProxy, | |
| get, | |
| setProperties, | |
| getOwner | |
| } = Ember; | |
| const { service } = Ember.inject; | |
| export default ArrayProxy.extend({ | |
| name: '', | |
| routing: service('-routing'), | |
| _routerMicrolib: computed('routing', function() { | |
| return this.get('routing').router.router; | |
| }), | |
| _fromCurrent() { | |
| const currentInfos = get(this, '_routerMicrolib').currentHandlerInfos; | |
| return { | |
| routeName: leafName(currentInfos), | |
| params: getParamsHash(currentInfos) | |
| }; | |
| }, | |
| attach(navItem) { | |
| if (!navItem) { | |
| navItem = this._fromCurrent(); | |
| } | |
| const incomingInfos = this._recognize(navItem); | |
| assign(navItem, extractTabSettingsFromHandlerInfos.call(this, incomingInfos), { | |
| linkParams: [ navItem.routeName ] | |
| .concat(getParamsValues(incomingInfos)) | |
| }); | |
| let existing = this.findOpened(incomingInfos); | |
| if (!existing) { | |
| this.addObject(navItem); | |
| } else { | |
| // @todo: replace | |
| setProperties(existing, navItem); | |
| } | |
| }, | |
| detach(tab) { | |
| const router = this.get('_routerMicrolib'); | |
| const isTabActive = router.isActive.apply(router, tab.linkParams); | |
| const pos = this.indexOf(tab); | |
| this.removeObject(tab); | |
| if (isTabActive) { | |
| let prevTab = this.objectAt(pos > 0 ? pos - 1 : pos); | |
| if (prevTab) { | |
| // router.replaceWith.apply(router, prevTab.linkParams); | |
| } else { // all tabs are deleted | |
| router.replaceWith([this.name]); | |
| } | |
| } | |
| }, | |
| // @todo: test | |
| _recognize({ routeName, params = null }) { | |
| const routeRecognizer = get(this, '_routerMicrolib').recognizer; | |
| const url = routeRecognizer.generate(routeName, params); | |
| const recognized = routeRecognizer.recognize(url); | |
| return recognized.slice().map( | |
| hi => assign({}, hi, { | |
| name: hi.handler | |
| }) | |
| ); | |
| }, | |
| /** | |
| * | |
| * | |
| * @param {Array} incomingInfos | |
| */ | |
| // @todo: | |
| // - tests | |
| // - fix permormance | |
| findOpened(incomingInfos) { | |
| return this.find( | |
| tab => commonRoot(incomingInfos, this._recognize(tab)) | |
| ); | |
| } | |
| }); | |
| function lastIndexWithParams(handlerInfos) { | |
| let i = -1; | |
| handlerInfos.forEach((hi, pos) => { | |
| if (!Ember.isEmpty(hi.params)) { | |
| i = pos; | |
| } | |
| }); | |
| return i; | |
| } | |
| function commonRoot(handlerInfos1, handlerInfos2) { | |
| let lastIndexWithParams1 = lastIndexWithParams(handlerInfos1), | |
| lastIndexWithParams2 = lastIndexWithParams(handlerInfos2); | |
| if (lastIndexWithParams1 !== lastIndexWithParams2) { | |
| return false; | |
| } | |
| for (let i = 0; i < lastIndexWithParams1; i++) { | |
| if (handlerInfos1[i].handler !== handlerInfos2[i].handler) { | |
| return false; | |
| } | |
| if (JSON.stringify(handlerInfos1[i].params) !== JSON.stringify(handlerInfos2[i].params)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| function getParamsHash(handlerInfos) { | |
| return assign.apply(null, getParams(handlerInfos)); | |
| } | |
| function getParamsValues(handlerInfos) { | |
| return Array.prototype.concat.apply( | |
| [], getParams(handlerInfos).map(segmentParams => { | |
| return Object.values(segmentParams); | |
| }) | |
| ); | |
| } | |
| function getParams(handlerInfos) { | |
| return handlerInfos.map(hi => { | |
| return JSON.parse(JSON.stringify(hi.params)); | |
| }); | |
| } | |
| function leafName(handlerInfos) { | |
| return handlerInfos.slice(-1)[0].name; | |
| } | |
| function readTabSettingsFromRouteHandler(routeHandler) { | |
| let tab = get(routeHandler, 'tab'); | |
| return typeof tab === 'function' ? | |
| tab.call(routeHandler, routeHandler.context) : | |
| tab; | |
| } | |
| function extractTabSettingsFromHandlerInfos(handlerInfos) { | |
| const owner = getOwner(this); | |
| let settingsPerTab = handlerInfos | |
| .map(routeHandler => {console.log(routeHandler.handler); return owner.lookup(`route:${routeHandler.handler}`)}) | |
| .filter(tab => !isEmpty(tab)) | |
| .map(readTabSettingsFromRouteHandler) | |
| .map(tab => JSON.parse(JSON.stringify(tab))); | |
| return assign.apply(this, [{}].concat(settingsPerTab)); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| import config from './config/environment'; | |
| const Router = Ember.Router.extend({ | |
| location: 'none', | |
| rootURL: config.rootURL | |
| }); | |
| Router.map(function() { | |
| this.route('customers'); | |
| this.route('customer', { | |
| path: '/customer/:customerId' | |
| }, function() { | |
| this.route('edit'); | |
| }); | |
| }); | |
| export default Router; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| import routableTabs from '../utils/routable-tabs'; | |
| export default Ember.Route.extend({ | |
| tabs: routableTabs('application'), | |
| tab: { | |
| title: 'Main', | |
| sticky: true | |
| }, | |
| setupController(controller, model) { | |
| this._super(...arguments); | |
| const tabs = this.get('tabs'); | |
| controller.set('tabs', tabs); | |
| //debugger | |
| tabs.attach({ | |
| routeName: 'customers' | |
| }); | |
| tabs.attach({ | |
| routeName: 'customer', | |
| params: { | |
| customerId: 1 | |
| } | |
| }); | |
| tabs.attach({ | |
| routeName: 'customer', | |
| params: { | |
| customerId: 2 | |
| } | |
| }); | |
| tabs.attach({ | |
| routeName: 'customer', | |
| params: { | |
| customerId: 3 | |
| } | |
| }); | |
| console.log('tabs.length', tabs.get('length')) | |
| }, | |
| didTransition() { | |
| const tabs = this.get('tabs'); | |
| //tabs.attach(); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Route.extend({ | |
| tab({name}) { | |
| return { | |
| title: `Customer "${name}"` | |
| } | |
| }, | |
| model({customerId}) { | |
| console.log('customerId', customerId) | |
| return this.get('customers').find(customerId); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Route.extend({ | |
| customers: Ember.inject.service(), | |
| tab: { | |
| title: 'Customers' | |
| }, | |
| model() { | |
| return this.get('customers').find(); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| const {RSVP, A} = Ember; | |
| // @todo: mirage | |
| const customers = A([{ | |
| name: "Ivan", customerId: 1 | |
| }, { | |
| name: "Vasiliy", customerId: 2 | |
| }, { | |
| name: "Petro", customerId: 3 | |
| }]); | |
| export default Ember.Service.extend({ | |
| find(id = null) { | |
| if (id !== null) { | |
| return customers.find(c => c.customerId === id); | |
| } | |
| return new RSVP.Promise(function(resolve) { | |
| return customers; | |
| }); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| import TabsContainer from '../models/tabs-container'; | |
| const { A, setOwner, getOwner } = Ember; | |
| export default Ember.Service.extend({ | |
| init() { | |
| this._items = {}; | |
| }, | |
| containerFor(containerId) { | |
| if (!this._items[containerId]) { | |
| this._items[containerId] = TabsContainer.create({ | |
| 'name': containerId, | |
| content: A([]) | |
| }); | |
| let owner = getOwner(this); | |
| setOwner(this._items[containerId], owner); | |
| } | |
| return this._items[containerId]; | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "version": "0.11.1", | |
| "EmberENV": { | |
| "FEATURES": {} | |
| }, | |
| "options": { | |
| "use_pods": false, | |
| "enable-testing": false | |
| }, | |
| "dependencies": { | |
| "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js", | |
| "ember": "2.11.0", | |
| "ember-data": "2.11.0", | |
| "ember-template-compiler": "2.11.0", | |
| "ember-testing": "2.11.0" | |
| }, | |
| "addons": { | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| const { | |
| getOwner, | |
| computed | |
| } = Ember; | |
| /** | |
| * Returns tabs root container | |
| * | |
| * @param {string} name root name | |
| * @return {Model.TabsContainer} | |
| */ | |
| export default function routableTabs(name) { | |
| return computed(function() { | |
| return getOwner(this) | |
| .lookup('service:tabs') | |
| .containerFor(name); | |
| }) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment