├── LICENSE.md ├── README.md ├── appstore-example.framer ├── .gitignore ├── app.coffee ├── framer │ ├── backups │ │ ├── backup-1428086792.coffee │ │ ├── backup-1428531305.coffee │ │ ├── backup-1428619266.coffee │ │ ├── backup-1429131125.coffee │ │ └── backup-1429469976.coffee │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── background.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ ├── icon-76.png │ │ ├── icon-arrow.png │ │ ├── icon-arrow@2x.png │ │ ├── icon-close.png │ │ ├── icon-close@2x.png │ │ ├── icon-framer.png │ │ ├── icon-framer@2x.png │ │ ├── icon-share.png │ │ └── icon-share@2x.png │ ├── mirror.css │ ├── style.css │ └── version ├── images │ ├── explore-icon@2x.png │ ├── explore-selected@2x.png │ ├── explore.png │ ├── featured-icon@2x.png │ ├── featured-selected@2x.png │ ├── featured.jpg │ ├── framer-icon.png │ ├── search-icon-selected@2x.png │ ├── search-icon@2x.png │ ├── search-selected@2x.png │ ├── search.png │ ├── top-charts.png │ ├── topcharts-icon@2x.png │ ├── topcharts-selected@2x.png │ ├── updates-icon@2x.png │ ├── updates-selected@2x.png │ └── updates.png ├── index.html └── modules │ └── tabBarModule.coffee ├── basic-example.framer ├── .gitignore ├── app.coffee ├── framer │ ├── backups │ │ ├── backup-1428531305.coffee │ │ ├── backup-1428619266.coffee │ │ ├── backup-1429131125.coffee │ │ ├── backup-1429469976.coffee │ │ └── backup-1429472422.coffee │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── background.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ ├── icon-76.png │ │ ├── icon-arrow.png │ │ ├── icon-arrow@2x.png │ │ ├── icon-close.png │ │ ├── icon-close@2x.png │ │ ├── icon-framer.png │ │ ├── icon-framer@2x.png │ │ ├── icon-share.png │ │ └── icon-share@2x.png │ ├── mirror.css │ ├── style.css │ └── version ├── images │ ├── explore-icon@2x.png │ ├── explore-selected@2x.png │ ├── explore.jpg │ ├── featured-icon@2x.png │ ├── featured-selected@2x.png │ ├── featured.jpg │ ├── framer-icon.png │ ├── search-icon@2x.png │ ├── search-selected@2x.png │ └── search.jpg ├── index.html └── modules │ └── tabBarModule.coffee ├── customized-example.framer ├── .gitignore ├── app.coffee ├── framer │ ├── backups │ │ ├── backup-1428086792.coffee │ │ ├── backup-1428619266.coffee │ │ ├── backup-1429131125.coffee │ │ └── backup-1429469976.coffee │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── background.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ ├── icon-76.png │ │ ├── icon-arrow.png │ │ ├── icon-arrow@2x.png │ │ ├── icon-close.png │ │ ├── icon-close@2x.png │ │ ├── icon-framer.png │ │ ├── icon-framer@2x.png │ │ ├── icon-share.png │ │ └── icon-share@2x.png │ ├── mirror.css │ ├── style.css │ └── version ├── images │ ├── activity-icon@2x.png │ ├── explore-icon@2x.png │ ├── framer-icon.png │ ├── music-icon@2x.png │ └── search-icon@2x.png ├── index.html └── modules │ └── tabBarModule.coffee ├── screenshot.png └── tabBarModule.coffee /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Petter Nilsson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TabBarModule 2 | 3 | TabBarModule is a module for the prototyping tool Framer. It makes it super easy to set up a tab bar navigation. 4 | 5 | Created by Petter Nilsson 6 | [petter.pro](http://petter.pro) / [@petterheterjag](http://twitter.com/petterheterjag) 7 | 8 | ![Screenshot](https://raw.githubusercontent.com/petterheterjag/tabBarModule/master/screenshot.png) 9 | 10 | **Features:** 11 | 12 | * It looks just like the default iOS tab bar (with background blur out of the box). 13 | * But it's very easy to customize. 14 | * It automatically shows the view/screen associated with the selected tab. 15 | * It has support for tinting icons (that means you can transform a transparent PNG with a black icon into any color you want by setting a property). 16 | * You can add badges to tab bar items. 17 | 18 | Only works in Framer Studio/Chrome/Safari. 19 | 20 | 21 | ## Examples 22 | 23 | #### [Basic](http://share.framerjs.com/bsaw6yj3090m/) 24 | #### [App store (with scrollComponents)](http://share.framerjs.com/37f8ggj6q01q/) 25 | #### [Customized](http://share.framerjs.com/6kf6f60h816b/) 26 | 27 | 28 | ## Basic usage 29 | 30 | Download tabBarModule.coffee and put it in the /modules folder of your Framer project. Then add this line at the top of your project in Framer Studio. 31 | 32 | ```coffeescript 33 | tabBarModule = require "tabBarModule" 34 | ``` 35 | 36 | Then to create the tab bar you do this: 37 | 38 | ```coffeescript 39 | tabBar = tabBarModule.tabBar 40 | Explore: {icon: "images/explore.png", selectedIcon: "images/explore-selected.png", view: exploreView} 41 | Featured: {icon: "images/featured.png", selectedIcon: "images/featured-selected", view: featuredView} 42 | Search: {icon: "images/search.png", selectedIcon: "images/search-selected.png", view: searchView} 43 | ``` 44 | 45 | ## Functions 46 | 47 | #### tabBarModule.tabBar(items *object*) 48 | Creates the tab bar. 49 | 50 | `icon` Path to icon *(required)* 51 | `selectedIcon` Path to icon to use when selected *(optional)* 52 | `view` Layer to show when item is selected *(optional)* 53 | 54 | ```coffeescript 55 | tabBar = tabBarModule.tabBar 56 | Explore: {icon: "images/explore.png", selectedIcon: "images/explore-selected.png", view: exploreView} 57 | Featured: {icon: "images/featured.png", selectedIcon: "images/featured-selected", view: featuredView} 58 | Search: {icon: "images/search.png", selectedIcon: "images/search-selected.png", view: searchView} 59 | ``` 60 | 61 | #### tabBar.setSelected(name *string*) 62 | Sets selected tab item from the key (name) used when creating it 63 | 64 | ```coffeescript 65 | tabBar.setSelected("Explore") 66 | ``` 67 | 68 | #### tabBar.setBadgeValue(name *string*, value *number*) 69 | Adds a badge to the tab item if value is a number > 0 and removes the badge if null 70 | 71 | ```coffeescript 72 | tabBar.setBadgeValue("Explore", 2) 73 | ``` 74 | 75 | #### tabBar.getItemFromName(name *string*) 76 | Returns a tab bar item if names matches 77 | 78 | ```coffeescript 79 | tabBar.getItemFromName("Explore") 80 | ``` 81 | 82 | ## Events 83 | 84 | #### "tabBarDidSwitch" (name *string*) 85 | Triggers when the tab bar switches selected tab 86 | 87 | ```coffeescript 88 | tabBar.on "tabBarDidSwitch", (name) -> 89 | print name 90 | ``` 91 | 92 | 93 | ## Change styling 94 | 95 | To change the default look, change these defaults before you create the tabBar. Like this: 96 | 97 | ```coffeescript 98 | tabBarModule.defaults.tintColor = "#FEC200" 99 | ``` 100 | 101 | **defaults.screenWidth** *number* 102 | **defaults.screenHeight** *number* 103 | **defaults.barHeight** *number* 104 | **defaults.labelOffset** *number* 105 | **defaults.iconOffset** *number* 106 | **defaults.tintColor** *string* 107 | **defaults.tintColorUnselected** *string* 108 | **defaults.blur** *number* 109 | **defaults.opacity** *number* 110 | **defaults.borderShadow** *string* 111 | **defaults.backgroundColor** *string* 112 | **defaults.showLabels** *Boolean* 113 | **defaults.labelTextStyle** *object* 114 | **defaults.badgeTextStyle** *object* 115 | -------------------------------------------------------------------------------- /appstore-example.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Default Framer gitignore file 2 | 3 | # Mac specific 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear on external disk 15 | .Spotlight-V100 16 | .Trashes 17 | 18 | # Directories potentially created on remote AFP share 19 | .AppleDB 20 | .AppleDesktop 21 | Network Trash Folder 22 | Temporary Items 23 | .apdisk 24 | 25 | # Framer specific 26 | .temp.html 27 | framer/*.old.* 28 | framer/backup.coffee 29 | framer/backup/* 30 | framer/.*.hash -------------------------------------------------------------------------------- /appstore-example.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Make background white 5 | new BackgroundLayer({backgroundColor:"#fff"}) 6 | 7 | # Create scrollComponents for the views that should scroll 8 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 11 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 12 | 13 | # Create the views 14 | featuredView = new Layer 15 | width: 750 16 | height: 3800 17 | image: "images/featured.jpg" 18 | superLayer: featuredScroll.content 19 | topChartsView = new Layer 20 | width: 750 21 | height: 4300 22 | image: "images/top-charts.png" 23 | superLayer: topChartsScroll.content 24 | exploreView = new Layer 25 | width: 750 26 | height: 3000 27 | image: "images/explore.png" 28 | superLayer: exploreScroll.content 29 | searchView = new Layer 30 | width: 750 31 | height: 1334 32 | image: "images/search.png" 33 | updatesView = new Layer 34 | width: 750 35 | height: 1334 36 | image: "images/updates.png" 37 | superLayer: updatesScroll.content 38 | 39 | # Create the tab bar 40 | tabBar = new tabBarModule.tabBar 41 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 42 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 43 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 44 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 45 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 46 | 47 | # Add a badge to the Updates tab 48 | tabBar.setBadgeValue("Updates", 2) 49 | 50 | # Set up events to get the blur layer inside the tab bar to scroll with the scrollComponents 51 | featuredScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 53 | topChartsScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 55 | exploreScroll.on Events.Move, -> 56 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 57 | updatesScroll.on Events.Move, -> 58 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 59 | 60 | # Set Top Charts as the start tab 61 | tabBar.setSelected("Top Charts") 62 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/backups/backup-1428086792.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | new BackgroundLayer({backgroundColor:"#fff"}) 5 | 6 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 7 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 8 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | 11 | # Create some views 12 | featuredView = new Layer 13 | width: 750 14 | height: 3800 15 | image: "images/featured.jpg" 16 | superLayer: featuredScroll.content 17 | topChartsView = new Layer 18 | width: 750 19 | height: 4300 20 | image: "images/top-charts.png" 21 | superLayer: topChartsScroll.content 22 | exploreView = new Layer 23 | width: 750 24 | height: 3000 25 | image: "images/explore.png" 26 | superLayer: exploreScroll.content 27 | searchView = new Layer 28 | width: 750 29 | height: 1334 30 | image: "images/search.png" 31 | updatesView = new Layer 32 | width: 750 33 | height: 1334 34 | image: "images/updates.png" 35 | superLayer: updatesScroll.content 36 | 37 | # Create the tab bar 38 | tabBar = new tabKit.tabBar 39 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 40 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 41 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 42 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 43 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 44 | 45 | tabBar.setBadgeValue("Updates", 2) 46 | 47 | featuredScroll.on Events.Move, -> 48 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 49 | topChartsScroll.on Events.Move, -> 50 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 51 | exploreScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 53 | updatesScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 55 | 56 | 57 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/backups/backup-1428531305.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Make background white 5 | new BackgroundLayer({backgroundColor:"#fff"}) 6 | 7 | # Create scrollComponents for the views that should scroll 8 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 11 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 12 | 13 | # Create the views 14 | featuredView = new Layer 15 | width: 750 16 | height: 3800 17 | image: "images/featured.jpg" 18 | superLayer: featuredScroll.content 19 | topChartsView = new Layer 20 | width: 750 21 | height: 4300 22 | image: "images/top-charts.png" 23 | superLayer: topChartsScroll.content 24 | exploreView = new Layer 25 | width: 750 26 | height: 3000 27 | image: "images/explore.png" 28 | superLayer: exploreScroll.content 29 | searchView = new Layer 30 | width: 750 31 | height: 1334 32 | image: "images/search.png" 33 | updatesView = new Layer 34 | width: 750 35 | height: 1334 36 | image: "images/updates.png" 37 | superLayer: updatesScroll.content 38 | 39 | # Create the tab bar 40 | tabBar = new tabKit.tabBar 41 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 42 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 43 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 44 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 45 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 46 | 47 | # Add a badge to the Updates tab 48 | tabBar.setBadgeValue("Updates", 2) 49 | 50 | # Set up events to get the blur layer inside the tab bar to scroll with the scrollComponents 51 | featuredScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 53 | topChartsScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 55 | exploreScroll.on Events.Move, -> 56 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 57 | updatesScroll.on Events.Move, -> 58 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 59 | 60 | # Set Top Charts as the start tab 61 | tabBar.setSelected("Top Charts") 62 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/backups/backup-1428619266.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Make background white 5 | new BackgroundLayer({backgroundColor:"#fff"}) 6 | 7 | # Create scrollComponents for the views that should scroll 8 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 11 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 12 | 13 | # Create the views 14 | featuredView = new Layer 15 | width: 750 16 | height: 3800 17 | image: "images/featured.jpg" 18 | superLayer: featuredScroll.content 19 | topChartsView = new Layer 20 | width: 750 21 | height: 4300 22 | image: "images/top-charts.png" 23 | superLayer: topChartsScroll.content 24 | exploreView = new Layer 25 | width: 750 26 | height: 3000 27 | image: "images/explore.png" 28 | superLayer: exploreScroll.content 29 | searchView = new Layer 30 | width: 750 31 | height: 1334 32 | image: "images/search.png" 33 | updatesView = new Layer 34 | width: 750 35 | height: 1334 36 | image: "images/updates.png" 37 | superLayer: updatesScroll.content 38 | 39 | # Create the tab bar 40 | tabBar = new tabKit.tabBar 41 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 42 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 43 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 44 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 45 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 46 | 47 | # Add a badge to the Updates tab 48 | tabBar.setBadgeValue("Updates", 2) 49 | 50 | # Set up events to get the blur layer inside the tab bar to scroll with the scrollComponents 51 | featuredScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 53 | topChartsScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 55 | exploreScroll.on Events.Move, -> 56 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 57 | updatesScroll.on Events.Move, -> 58 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 59 | 60 | # Set Top Charts as the start tab 61 | tabBar.setSelected("Top Charts") 62 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/backups/backup-1429131125.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Make background white 5 | new BackgroundLayer({backgroundColor:"#fff"}) 6 | 7 | # Create scrollComponents for the views that should scroll 8 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 11 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 12 | 13 | # Create the views 14 | featuredView = new Layer 15 | width: 750 16 | height: 3800 17 | image: "images/featured.jpg" 18 | superLayer: featuredScroll.content 19 | topChartsView = new Layer 20 | width: 750 21 | height: 4300 22 | image: "images/top-charts.png" 23 | superLayer: topChartsScroll.content 24 | exploreView = new Layer 25 | width: 750 26 | height: 3000 27 | image: "images/explore.png" 28 | superLayer: exploreScroll.content 29 | searchView = new Layer 30 | width: 750 31 | height: 1334 32 | image: "images/search.png" 33 | updatesView = new Layer 34 | width: 750 35 | height: 1334 36 | image: "images/updates.png" 37 | superLayer: updatesScroll.content 38 | 39 | # Create the tab bar 40 | tabBar = new tabBarModule.tabBar 41 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 42 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 43 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 44 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 45 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 46 | 47 | # Add a badge to the Updates tab 48 | tabBar.setBadgeValue("Updates", 2) 49 | 50 | # Set up events to get the blur layer inside the tab bar to scroll with the scrollComponents 51 | featuredScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 53 | topChartsScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 55 | exploreScroll.on Events.Move, -> 56 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 57 | updatesScroll.on Events.Move, -> 58 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 59 | 60 | # Set Top Charts as the start tab 61 | tabBar.setSelected("Top Charts") 62 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/backups/backup-1429469976.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Make background white 5 | new BackgroundLayer({backgroundColor:"#fff"}) 6 | 7 | # Create scrollComponents for the views that should scroll 8 | featuredScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 9 | topChartsScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 10 | exploreScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 11 | updatesScroll = new ScrollComponent({width: 750, height: 1334, scrollHorizontal: false}) 12 | 13 | # Create the views 14 | featuredView = new Layer 15 | width: 750 16 | height: 3800 17 | image: "images/featured.jpg" 18 | superLayer: featuredScroll.content 19 | topChartsView = new Layer 20 | width: 750 21 | height: 4300 22 | image: "images/top-charts.png" 23 | superLayer: topChartsScroll.content 24 | exploreView = new Layer 25 | width: 750 26 | height: 3000 27 | image: "images/explore.png" 28 | superLayer: exploreScroll.content 29 | searchView = new Layer 30 | width: 750 31 | height: 1334 32 | image: "images/search.png" 33 | updatesView = new Layer 34 | width: 750 35 | height: 1334 36 | image: "images/updates.png" 37 | superLayer: updatesScroll.content 38 | 39 | # Create the tab bar 40 | tabBar = new tabBarModule.tabBar 41 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredScroll} 42 | "Top Charts": {icon: "images/topcharts-icon@2x.png", selectedIcon: "images/topcharts-selected@2x.png", view: topChartsScroll} 43 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreScroll} 44 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 45 | Updates: {icon: "images/updates-icon@2x.png", selectedIcon: "images/updates-selected@2x.png", view: updatesScroll} 46 | 47 | # Add a badge to the Updates tab 48 | tabBar.setBadgeValue("Updates", 2) 49 | 50 | # Set up events to get the blur layer inside the tab bar to scroll with the scrollComponents 51 | featuredScroll.on Events.Move, -> 52 | tabBar.getItemFromName("Featured").blurView.content.y = -featuredScroll.scrollY 53 | topChartsScroll.on Events.Move, -> 54 | tabBar.getItemFromName("Top Charts").blurView.content.y = -topChartsScroll.scrollY 55 | exploreScroll.on Events.Move, -> 56 | tabBar.getItemFromName("Explore").blurView.content.y = -exploreScroll.scrollY 57 | updatesScroll.on Events.Move, -> 58 | tabBar.getItemFromName("Updates").blurView.content.y = -updatesScroll.scrollY 59 | 60 | # Set Top Charts as the start tab 61 | tabBar.setSelected("Top Charts") 62 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "device" : "iPhone 5S Space Gray", 3 | "sharedPrototype" : 1, 4 | "deviceOrientation" : 0, 5 | "contentScale" : 1, 6 | "deviceType" : "iphone-6-silver", 7 | "updateDelay" : 0.3, 8 | "deviceScale" : 0.5, 9 | "delay" : 0.3 10 | } -------------------------------------------------------------------------------- /appstore-example.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer Studio 2 | 3 | 4 | window.Framer.Defaults.DeviceView = { 5 | "deviceScale" : 0.5, 6 | "orientation" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "iphone-6-silver" 9 | }; 10 | 11 | window.Framer.Defaults.DeviceComponent = { 12 | "deviceScale" : 0.5, 13 | "orientation" : 0, 14 | "contentScale" : 1, 15 | "deviceType" : "iphone-6-silver" 16 | }; 17 | 18 | window.FramerStudioInfo = { 19 | "deviceImagesUrl" : "file:\/\/\/Applications\/Framer%20Studio.app\/Contents\/Resources\/DeviceImages\/", 20 | "documentTitle" : "appstore-example.framer" 21 | }; 22 | 23 | Framer.Device = new Framer.DeviceView(); 24 | Framer.Device.setupContext(); 25 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o errorLineNumber) { 622 | errorLineNumber = loc[0] + 1; 623 | errorColNumber = loc[1]; 624 | } 625 | } 626 | return errorLineNumber; 627 | }; 628 | 629 | return Runtime; 630 | 631 | })(EventEmitter); 632 | 633 | exports.runtime = new Runtime(); 634 | 635 | 636 | 637 | },{"./Bridge":2,"eventemitter3":1}],6:[function(require,module,exports){ 638 | var HighlightComponent, setupContext; 639 | 640 | exports.bridge = (require("./Bridge.coffee")).bridge; 641 | 642 | exports.runtime = (require("./Runtime.coffee")).runtime; 643 | 644 | exports.context = require("./Context.coffee"); 645 | 646 | HighlightComponent = require("./HighlightComponent.coffee").HighlightComponent; 647 | 648 | if (window.require == null) { 649 | window.require = function(module) { 650 | throw Error("Module " + module + " can't be found"); 651 | }; 652 | } 653 | 654 | setupContext = function() { 655 | var context, getLayerById, highlighter; 656 | context = new exports.context.ContextListener(Framer.CurrentContext); 657 | highlighter = new HighlightComponent(); 658 | exports.bridge.on("ui:highlight", function(info) { 659 | return highlighter.highlight(getLayerById(info.id)); 660 | }); 661 | exports.bridge.on("ui:unhighlight", function() { 662 | return highlighter.unhighlight(); 663 | }); 664 | return getLayerById = function(id) { 665 | var i, layer, len, ref; 666 | ref = Framer.CurrentContext._layerList; 667 | for (i = 0, len = ref.length; i < len; i++) { 668 | layer = ref[i]; 669 | if (layer.id === id) { 670 | return layer; 671 | } 672 | } 673 | }; 674 | }; 675 | 676 | if (typeof window !== "undefined" && window !== null) { 677 | window.FramerStudio = exports; 678 | } 679 | 680 | 681 | 682 | },{"./Bridge.coffee":2,"./Context.coffee":3,"./HighlightComponent.coffee":4,"./Runtime.coffee":5}]},{},[6]) -------------------------------------------------------------------------------- /appstore-example.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function showHomeScreenAlert() { 60 | 61 | link = document.createElement("link"); 62 | link.href = "framer/mirror.css" 63 | link.type = "text/css" 64 | link.rel = "stylesheet" 65 | link.media = "screen" 66 | 67 | document.addEventListener("DOMContentLoaded", function(event) { 68 | document.getElementsByTagName("head")[0].appendChild(link) 69 | }) 70 | 71 | var html = "" 72 | html += "
" 73 | html += "
" 74 | html += "

Install Prototype

" 75 | html += "

Tap

, then choose 'Add to Home Screen'

" 76 | html += "
" 77 | html += "
" 78 | 79 | showAlert(html) 80 | } 81 | 82 | function loadProject() { 83 | CoffeeScript.load("app.coffee") 84 | } 85 | 86 | function setDefaultPageTitle() { 87 | // If no title was set we set it to the project folder name so 88 | // you get a nice name on iOS if you bookmark to desktop. 89 | document.addEventListener("DOMContentLoaded", function() { 90 | if (document.title == "") { 91 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 92 | document.title = window.FramerStudioInfo.documentTitle 93 | } else { 94 | document.title = window.location.pathname.replace(/\//g, "") 95 | } 96 | } 97 | }) 98 | } 99 | 100 | function init() { 101 | 102 | if (Utils.isFramerStudio()) { 103 | return 104 | } 105 | 106 | setDefaultPageTitle() 107 | 108 | if (!isCompatibleBrowser()) { 109 | return showBrowserAlert() 110 | } 111 | 112 | if (!isFileLoadingAllowed()) { 113 | return showFileLoadingAlert() 114 | } 115 | 116 | // if (Utils.isMobile() && !isHomeScreened()) { 117 | // return showHomeScreenAlert() 118 | // } 119 | 120 | loadProject() 121 | 122 | } 123 | 124 | init() 125 | 126 | })() 127 | -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/background.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/cursor.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/cursor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/cursor@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-120.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-152.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-180.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-192.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-76.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-arrow.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-arrow@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-close.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-close@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-framer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-framer.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-framer@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-framer@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-share.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/images/icon-share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/framer/images/icon-share@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/framer/mirror.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | border: none; 5 | -webkit-user-select: none; 6 | -webkit-tap-highlight-color: rgba(0,0,0,0); 7 | } 8 | html, body, .wrapper { 9 | height: 100%; 10 | } 11 | body { 12 | background: #fff; 13 | font: 300 20px "Helvetica Neue", Helvetica, sans-serif; 14 | overflow: hidden; 15 | cursor: url('images/cursor.png') 39 39, auto; 16 | text-align: center; 17 | position: relative; 18 | -webkit-font-smoothing: antialiased; 19 | text-rendering: optimizeLegibility; 20 | color: #333740; 21 | } 22 | a { 23 | color: gray; 24 | } 25 | .framerAlert { 26 | font: 12px/1.6em Menlo; 27 | margin: 10px; 28 | color: gray; 29 | } 30 | ::-webkit-scrollbar { 31 | display: none; 32 | } 33 | .wrapper { 34 | width:100%; 35 | max-width: 240px; 36 | margin: 0 auto; 37 | padding-top: 38%; 38 | position: relative; 39 | } 40 | /* Text */ 41 | h1 { 42 | font-size: 22px; 43 | font-weight: 400; 44 | margin-top: 0px; 45 | line-height: 1.5; 46 | color: black; 47 | 48 | margin-bottom: 8px; 49 | margin-top: 16px; 50 | } 51 | h2 { 52 | font-size: 14px; 53 | font-weight: 400; 54 | color: #788594; 55 | } 56 | hr { 57 | border: none; width: 100%; 58 | border-bottom: 1px solid #EFF1F3; 59 | display: block; 60 | margin: 40px auto 32px auto; 61 | } 62 | p { 63 | display: inline-block; 64 | line-height: 1.5; 65 | } 66 | figure { 67 | display: inline-block; 68 | } 69 | .share { 70 | color: #007AFF; 71 | display: inline-block; 72 | margin-left: 8px; 73 | } 74 | .icon-share { 75 | margin-right: 0px; 76 | position: relative; 77 | top:0.5px; 78 | } 79 | .arrow { 80 | position: absolute; 81 | max-width: 240px; 82 | width: 100%; 83 | left:50%; margin-left:-120px; 84 | bottom: 24%; 85 | } 86 | .arrow figure { 87 | -webkit-animation: bounce 1.25s ease infinite; 88 | -moz-animation: bounce 1.25s ease infinite; 89 | -o-animation: bounce 1.25s ease infinite; 90 | animation: bounce 1.25s ease infinite; 91 | -webkit-transform-origin: center bottom; 92 | -ms-transform-origin: center bottom; 93 | transform-origin: center bottom; 94 | } 95 | /* Arrow animation */ 96 | @-webkit-keyframes bounce { 97 | 0%, 100% { 98 | -webkit-transform: translate3d(0,0,0); 99 | transform: translate3d(0,0,0); 100 | } 101 | 50% { 102 | -webkit-transform: translate3d(0, -16px, 0); 103 | transform: translate3d(0, -16px, 0); 104 | } 105 | } 106 | @keyframes bounce { 107 | 0%, 100% { 108 | -webkit-transform: translate3d(0,0,0); 109 | transform: translate3d(0,0,0); 110 | } 111 | 50% { 112 | -webkit-transform: translate3d(0, -16px, 0); 113 | transform: translate3d(0, -16px, 0); 114 | } 115 | } 116 | /* Icons */ 117 | .icon-close, 118 | .icon-framer, 119 | .icon-share, 120 | .icon-arrow { 121 | background-size: cover; 122 | } 123 | .icon-close { 124 | background-image: url("images/icon-close.png"); 125 | position: absolute; 126 | top:16px; 127 | right:16px; 128 | cursor: pointer; 129 | cursor: hand; 130 | width: 18px; 131 | height: 18px; 132 | } 133 | .icon-framer { 134 | background-image: url("images/icon-framer.png"); 135 | width: 60px; 136 | height: 60px; 137 | } 138 | .icon-share { 139 | background-image: url("images/icon-share.png"); 140 | width: 11px; 141 | height: 18px; 142 | } 143 | .icon-arrow { 144 | background-image: url("images/icon-arrow.png"); 145 | width: 18px; 146 | height: 30px; 147 | } 148 | /* Retina Icons */ 149 | @media screen and (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 150 | .icon-close { 151 | background-image: url("images/icon-close@2x.png"); 152 | } 153 | .icon-framer { 154 | background-image: url("images/icon-framer@2x.png"); 155 | } 156 | .icon-share { 157 | background-image: url("images/icon-share@2x.png"); 158 | } 159 | .icon-arrow { 160 | background-image: url("images/icon-arrow@2x.png"); 161 | } 162 | } 163 | /* Avoid overflow scrolling when viewing in Portrait */ 164 | @media screen and (orientation:portrait) { 165 | html, body, .wrapper { 166 | overflow: hidden; 167 | } 168 | } 169 | /* iPad share icon is positioned in the navigation bar */ 170 | @media screen and (min-width: 576px){ 171 | .arrow { 172 | display: none; 173 | } 174 | .wrapper { 175 | padding-bottom: 25%; 176 | } 177 | } 178 | /* When it landscape, hide arrow and adjust spacing */ 179 | @media screen and (orientation:landscape) { 180 | .arrow { 181 | display: none; 182 | } 183 | .wrapper { 184 | padding-top: 10%; 185 | padding-bottom: 0; 186 | } 187 | } 188 | /* iPhone 6 Portrait */ 189 | @media screen and (min-device-width:375px) and (max-device-width:667px) and (-webkit-min-device-pixel-ratio:2) and (orientation:portrait) { 190 | .wrapper { 191 | padding-top: 48%; 192 | } 193 | .arrow { 194 | bottom: 27%; 195 | } 196 | } -------------------------------------------------------------------------------- /appstore-example.framer/framer/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | border: none; 5 | -webkit-user-select: none; 6 | -webkit-tap-highlight-color: rgba(0,0,0,0); 7 | } 8 | 9 | body { 10 | background-color: #fff; 11 | font: 28px/1em "Helvetica"; 12 | color: #FFF; 13 | overflow: hidden; 14 | cursor: url('images/cursor.png') 39 39, auto; 15 | } 16 | 17 | a { 18 | color: gray; 19 | } 20 | 21 | .framerAlertBackground { 22 | position: absolute; top:0px; left:0px; right:0px; bottom:0px; 23 | z-index: 1000; 24 | background-color: #fff; 25 | } 26 | 27 | .framerAlert { 28 | font:400 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif; 29 | -webkit-font-smoothing:antialiased; 30 | color:#616367; text-align:center; 31 | position: absolute; top:40%; left:50%; width:260px; margin-left:-130px; 32 | } 33 | .framerAlert strong { font-weight:500; color:#000; margin-bottom:8px; display:block; } 34 | .framerAlert a { color:#28AFFA; } 35 | .framerAlert .btn { 36 | font-weight:500; text-decoration:none; line-height:1; 37 | display:inline-block; padding:6px 12px 7px 12px; 38 | border-radius:3px; margin-top:12px; 39 | background:#28AFFA; color:#fff; 40 | } 41 | 42 | ::-webkit-scrollbar { 43 | display: none; 44 | } -------------------------------------------------------------------------------- /appstore-example.framer/framer/version: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /appstore-example.framer/images/explore-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/explore-icon@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/explore-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/explore-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/explore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/explore.png -------------------------------------------------------------------------------- /appstore-example.framer/images/featured-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/featured-icon@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/featured-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/featured-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/featured.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/featured.jpg -------------------------------------------------------------------------------- /appstore-example.framer/images/framer-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/framer-icon.png -------------------------------------------------------------------------------- /appstore-example.framer/images/search-icon-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/search-icon-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/search-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/search-icon@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/search-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/search-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/search.png -------------------------------------------------------------------------------- /appstore-example.framer/images/top-charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/top-charts.png -------------------------------------------------------------------------------- /appstore-example.framer/images/topcharts-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/topcharts-icon@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/topcharts-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/topcharts-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/updates-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/updates-icon@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/updates-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/updates-selected@2x.png -------------------------------------------------------------------------------- /appstore-example.framer/images/updates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/appstore-example.framer/images/updates.png -------------------------------------------------------------------------------- /appstore-example.framer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /appstore-example.framer/modules/tabBarModule.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | tabBarModule 3 | – 4 | Created by Petter Nilsson 5 | http://petter.pro 6 | ### 7 | 8 | # Default styles 9 | defaults = { 10 | screenWidth: Screen.width 11 | screenHeight: Screen.height 12 | barHeight: 98 13 | labelOffset: -28 14 | iconOffset: -12 15 | tintColor: "#007aff" 16 | tintColorUnselected: "#929292" 17 | blur: 40 18 | opacity: 0.75 19 | borderShadow: "0px -1px 0px 0px rgba(0,0,0,0.32)" 20 | backgroundColor: "#f8f8f8" 21 | showLabels: true 22 | badgeSize: 36 23 | badgeColor: "#FF3B30" 24 | } 25 | defaults.labelTextStyle = { 26 | fontSize: "20px" 27 | textAlign: "center" 28 | fontFamily: "Helvetica Neue', sans-serif" 29 | } 30 | defaults.badgeTextStyle = { 31 | fontSize: "26px" 32 | lineHeight: "36px" 33 | color: "#fff" 34 | textAlign: "center" 35 | fontFamily: "Helvetica Neue', sans-serif" 36 | } 37 | exports.defaults = defaults 38 | 39 | 40 | getItemFromName = (name) -> 41 | # Returns a tab bar item if names matches 42 | 43 | for item in @items 44 | return item if item.name is name 45 | 46 | 47 | updateViews = (selectedItem) -> 48 | # Shows/hides views based on selected tab bar item 49 | 50 | for item in @items 51 | if item.view? 52 | if item.view is selectedItem.view then item.view.visible = true else item.view.visible = false 53 | if item.blurView is selectedItem.blurView then item.blurView.visible = true else item.blurView.visible = false 54 | 55 | 56 | setSelected = (name) -> 57 | # Sets selected tab item from the key (name) used when creating it 58 | 59 | if name != @selected 60 | for item in @items 61 | if item.name is name 62 | item.iconLayer.backgroundColor = defaults.tintColor 63 | item.labelLayer.style = "color": defaults.tintColor if item.labelLayer 64 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.selectedIcon + ")" if item.iconLayer.selectedIcon 65 | @selected = item.name 66 | @updateViews(item) 67 | @.emit("tabBarDidSwitch", item.name) 68 | else 69 | item.iconLayer.backgroundColor = defaults.tintColorUnselected 70 | item.labelLayer.style = "color": defaults.tintColorUnselected if item.labelLayer 71 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.icon + ")" if item.iconLayer.selectedIcon 72 | 73 | 74 | setBadgeValue = (name, value) -> 75 | # Adds a badge to the tab item if value is a number > 0 and removes the badge if null 76 | 77 | for item in @items 78 | if item.name is name 79 | if value 80 | item.badgeLayer.html = value 81 | item.badgeLayer.visible = true 82 | else 83 | item.badgeLayer.visible = false 84 | 85 | 86 | exports.tabBar = (barItems) -> 87 | # Creates and set-ups the tab bar 88 | 89 | tabBar = new Layer 90 | x: 0 91 | y: defaults.screenHeight - defaults.barHeight 92 | width: defaults.screenWidth 93 | height: defaults.barHeight 94 | backgroundColor: defaults.backgroundColor 95 | 96 | tabBar.style = "box-shadow": defaults.borderShadow 97 | tabBar.getItemFromName = getItemFromName 98 | tabBar.updateViews = updateViews 99 | tabBar.setSelected = setSelected 100 | tabBar.setBadgeValue = setBadgeValue 101 | tabBar.selected = null 102 | tabBar.items = [] 103 | 104 | background = new Layer 105 | x: 0 106 | y: 0 107 | width: defaults.screenWidth 108 | height: defaults.barHeight 109 | backgroundColor: defaults.backgroundColor 110 | opacity: defaults.opacity 111 | superLayer: tabBar 112 | 113 | itemCount = Object.keys(barItems).length 114 | i = 0 115 | 116 | for name,params of barItems 117 | itemLayer = new Layer 118 | backgroundColor: "none" 119 | width: defaults.screenWidth / itemCount 120 | height: defaults.barHeight 121 | x: i * (defaults.screenWidth / itemCount) 122 | y: 0 123 | superLayer: tabBar 124 | name: name 125 | 126 | if params.view? 127 | # Create a copy of the view, blur it and use it as a background 128 | blurView = params.view.copy() 129 | if ScrollComponent.prototype.isPrototypeOf(blurView) 130 | blurView.content.blur = defaults.blur 131 | else 132 | blurView.blur = defaults.blur 133 | blurView.superLayer = tabBar 134 | blurView.index = 0 135 | blurView.y = blurView.y - (defaults.screenHeight - defaults.barHeight) 136 | 137 | itemLayer.view = params.view 138 | itemLayer.blurView = blurView 139 | 140 | iconLayer = new Layer 141 | width: 60 142 | height: 60 143 | superLayer: itemLayer 144 | iconLayer.icon = params.icon 145 | iconLayer.selectedIcon = params.selectedIcon if params.selectedIcon? 146 | 147 | # This black magic is used to tint the PNG images. Only works on webkit browsers :/ 148 | iconLayer.style = 149 | "-webkit-mask-image": "url(" + iconLayer.icon + ")" 150 | "-webkit-mask-repeat": "no-repeat" 151 | "-webkit-mask-position": "center center" 152 | iconLayer.centerX() 153 | iconLayer.centerY(defaults.iconOffset) 154 | itemLayer.iconLayer = iconLayer 155 | 156 | if defaults.showLabels 157 | labelLayer = new Layer 158 | width: itemLayer.width 159 | x: 0 160 | y: defaults.barHeight + defaults.labelOffset 161 | superLayer: itemLayer 162 | backgroundColor: "none" 163 | labelLayer.html = name 164 | labelLayer.style = defaults.labelTextStyle 165 | itemLayer.labelLayer = labelLayer 166 | 167 | badgeLayer = new Layer 168 | width: defaults.badgeSize 169 | height: defaults.badgeSize 170 | x: 0 171 | y: 6 172 | borderRadius: 18 173 | superLayer: itemLayer 174 | backgroundColor: defaults.badgeColor 175 | badgeLayer.style = defaults.badgeTextStyle 176 | badgeLayer.centerX(26) 177 | 178 | itemLayer.badgeLayer = badgeLayer 179 | itemLayer.badgeLayer.visible = false 180 | 181 | tabBar.items.push(itemLayer) 182 | 183 | itemLayer.on Events.Click, -> 184 | tabBar.setSelected(@name) 185 | 186 | i++ 187 | 188 | # Select the first item in the tab bar 189 | tabBar.setSelected(tabBar.items[0].name) 190 | 191 | return tabBar 192 | -------------------------------------------------------------------------------- /basic-example.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Default Framer gitignore file 2 | 3 | # Mac specific 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear on external disk 15 | .Spotlight-V100 16 | .Trashes 17 | 18 | # Directories potentially created on remote AFP share 19 | .AppleDB 20 | .AppleDesktop 21 | Network Trash Folder 22 | Temporary Items 23 | .apdisk 24 | 25 | # Framer specific 26 | .temp.html 27 | framer/*.old.* 28 | framer/backup.coffee 29 | framer/backup/* 30 | framer/.*.hash -------------------------------------------------------------------------------- /basic-example.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/explore.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/featured.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/search.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabBarModule.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 23 | -------------------------------------------------------------------------------- /basic-example.framer/framer/backups/backup-1428531305.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/image1.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/image2.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/image3.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabKit.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", iconSelected: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", iconSelected: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", iconSelected: "images/search-selected@2x.png", view: searchView} -------------------------------------------------------------------------------- /basic-example.framer/framer/backups/backup-1428619266.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/explore.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/featured.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/search.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabKit.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 23 | 24 | tabBar2 = new tabKit.tabBar 25 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 26 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 27 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 28 | 29 | tabBar2.y = 1100 -------------------------------------------------------------------------------- /basic-example.framer/framer/backups/backup-1429131125.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/explore.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/featured.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/search.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabBarModule.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 23 | -------------------------------------------------------------------------------- /basic-example.framer/framer/backups/backup-1429469976.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/explore.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/featured.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/search.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabBarModule.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 23 | -------------------------------------------------------------------------------- /basic-example.framer/framer/backups/backup-1429472422.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Create some views 5 | exploreView = new Layer 6 | width: Screen.width 7 | height: Screen.height 8 | image: "images/explore.jpg" 9 | featuredView = new Layer 10 | width: Screen.width 11 | height: Screen.height 12 | image: "images/featured.jpg" 13 | searchView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | image: "images/search.jpg" 17 | 18 | # Create the tab bar 19 | tabBar = new tabBarModule.tabBar 20 | Explore: {icon: "images/explore-icon@2x.png", selectedIcon: "images/explore-selected@2x.png", view: exploreView} 21 | Featured: {icon: "images/featured-icon@2x.png", selectedIcon: "images/featured-selected@2x.png", view: featuredView} 22 | Search: {icon: "images/search-icon@2x.png", selectedIcon: "images/search-selected@2x.png", view: searchView} 23 | -------------------------------------------------------------------------------- /basic-example.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "device" : "iPhone 5S Space Gray", 3 | "sharedPrototype" : 1, 4 | "deviceOrientation" : 0, 5 | "contentScale" : 1, 6 | "deviceType" : "iphone-6-silver", 7 | "updateDelay" : 0.3, 8 | "deviceScale" : 0.5, 9 | "delay" : 0.3 10 | } -------------------------------------------------------------------------------- /basic-example.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer Studio 2 | 3 | 4 | window.Framer.Defaults.DeviceView = { 5 | "deviceScale" : 0.5, 6 | "orientation" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "iphone-6-silver" 9 | }; 10 | 11 | window.Framer.Defaults.DeviceComponent = { 12 | "deviceScale" : 0.5, 13 | "orientation" : 0, 14 | "contentScale" : 1, 15 | "deviceType" : "iphone-6-silver" 16 | }; 17 | 18 | window.FramerStudioInfo = { 19 | "deviceImagesUrl" : "file:\/\/\/Applications\/Framer%20Studio.app\/Contents\/Resources\/DeviceImages\/", 20 | "documentTitle" : "basic-example.framer" 21 | }; 22 | 23 | Framer.Device = new Framer.DeviceView(); 24 | Framer.Device.setupContext(); 25 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o errorLineNumber) { 622 | errorLineNumber = loc[0] + 1; 623 | errorColNumber = loc[1]; 624 | } 625 | } 626 | return errorLineNumber; 627 | }; 628 | 629 | return Runtime; 630 | 631 | })(EventEmitter); 632 | 633 | exports.runtime = new Runtime(); 634 | 635 | 636 | 637 | },{"./Bridge":2,"eventemitter3":1}],6:[function(require,module,exports){ 638 | var HighlightComponent, setupContext; 639 | 640 | exports.bridge = (require("./Bridge.coffee")).bridge; 641 | 642 | exports.runtime = (require("./Runtime.coffee")).runtime; 643 | 644 | exports.context = require("./Context.coffee"); 645 | 646 | HighlightComponent = require("./HighlightComponent.coffee").HighlightComponent; 647 | 648 | if (window.require == null) { 649 | window.require = function(module) { 650 | throw Error("Module " + module + " can't be found"); 651 | }; 652 | } 653 | 654 | setupContext = function() { 655 | var context, getLayerById, highlighter; 656 | context = new exports.context.ContextListener(Framer.CurrentContext); 657 | highlighter = new HighlightComponent(); 658 | exports.bridge.on("ui:highlight", function(info) { 659 | return highlighter.highlight(getLayerById(info.id)); 660 | }); 661 | exports.bridge.on("ui:unhighlight", function() { 662 | return highlighter.unhighlight(); 663 | }); 664 | return getLayerById = function(id) { 665 | var i, layer, len, ref; 666 | ref = Framer.CurrentContext._layerList; 667 | for (i = 0, len = ref.length; i < len; i++) { 668 | layer = ref[i]; 669 | if (layer.id === id) { 670 | return layer; 671 | } 672 | } 673 | }; 674 | }; 675 | 676 | if (typeof window !== "undefined" && window !== null) { 677 | window.FramerStudio = exports; 678 | } 679 | 680 | 681 | 682 | },{"./Bridge.coffee":2,"./Context.coffee":3,"./HighlightComponent.coffee":4,"./Runtime.coffee":5}]},{},[6]) -------------------------------------------------------------------------------- /basic-example.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function showHomeScreenAlert() { 60 | 61 | link = document.createElement("link"); 62 | link.href = "framer/mirror.css" 63 | link.type = "text/css" 64 | link.rel = "stylesheet" 65 | link.media = "screen" 66 | 67 | document.addEventListener("DOMContentLoaded", function(event) { 68 | document.getElementsByTagName("head")[0].appendChild(link) 69 | }) 70 | 71 | var html = "" 72 | html += "
" 73 | html += "
" 74 | html += "

Install Prototype

" 75 | html += "

Tap

, then choose 'Add to Home Screen'

" 76 | html += "
" 77 | html += "
" 78 | 79 | showAlert(html) 80 | } 81 | 82 | function loadProject() { 83 | CoffeeScript.load("app.coffee") 84 | } 85 | 86 | function setDefaultPageTitle() { 87 | // If no title was set we set it to the project folder name so 88 | // you get a nice name on iOS if you bookmark to desktop. 89 | document.addEventListener("DOMContentLoaded", function() { 90 | if (document.title == "") { 91 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 92 | document.title = window.FramerStudioInfo.documentTitle 93 | } else { 94 | document.title = window.location.pathname.replace(/\//g, "") 95 | } 96 | } 97 | }) 98 | } 99 | 100 | function init() { 101 | 102 | if (Utils.isFramerStudio()) { 103 | return 104 | } 105 | 106 | setDefaultPageTitle() 107 | 108 | if (!isCompatibleBrowser()) { 109 | return showBrowserAlert() 110 | } 111 | 112 | if (!isFileLoadingAllowed()) { 113 | return showFileLoadingAlert() 114 | } 115 | 116 | // if (Utils.isMobile() && !isHomeScreened()) { 117 | // return showHomeScreenAlert() 118 | // } 119 | 120 | loadProject() 121 | 122 | } 123 | 124 | init() 125 | 126 | })() 127 | -------------------------------------------------------------------------------- /basic-example.framer/framer/framer.modules.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /basic-example.framer/modules/tabBarModule.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | tabBarModule 3 | – 4 | Created by Petter Nilsson 5 | http://petter.pro 6 | ### 7 | 8 | # Default styles 9 | defaults = { 10 | screenWidth: Screen.width 11 | screenHeight: Screen.height 12 | barHeight: 98 13 | labelOffset: -28 14 | iconOffset: -12 15 | tintColor: "#007aff" 16 | tintColorUnselected: "#929292" 17 | blur: 40 18 | opacity: 0.75 19 | borderShadow: "0px -1px 0px 0px rgba(0,0,0,0.32)" 20 | backgroundColor: "#f8f8f8" 21 | showLabels: true 22 | badgeSize: 36 23 | badgeColor: "#FF3B30" 24 | } 25 | defaults.labelTextStyle = { 26 | fontSize: "20px" 27 | textAlign: "center" 28 | fontFamily: "Helvetica Neue', sans-serif" 29 | } 30 | defaults.badgeTextStyle = { 31 | fontSize: "26px" 32 | lineHeight: "36px" 33 | color: "#fff" 34 | textAlign: "center" 35 | fontFamily: "Helvetica Neue', sans-serif" 36 | } 37 | exports.defaults = defaults 38 | 39 | 40 | getItemFromName = (name) -> 41 | # Returns a tab bar item if names matches 42 | 43 | for item in @items 44 | return item if item.name is name 45 | 46 | 47 | updateViews = (selectedItem) -> 48 | # Shows/hides views based on selected tab bar item 49 | 50 | for item in @items 51 | if item.view? 52 | if item.view is selectedItem.view then item.view.visible = true else item.view.visible = false 53 | if item.blurView is selectedItem.blurView then item.blurView.visible = true else item.blurView.visible = false 54 | 55 | 56 | setSelected = (name) -> 57 | # Sets selected tab item from the key (name) used when creating it 58 | 59 | if name != @selected 60 | for item in @items 61 | if item.name is name 62 | item.iconLayer.backgroundColor = defaults.tintColor 63 | item.labelLayer.style = "color": defaults.tintColor if item.labelLayer 64 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.selectedIcon + ")" if item.iconLayer.selectedIcon 65 | @selected = item.name 66 | @updateViews(item) 67 | @.emit("tabBarDidSwitch", item.name) 68 | else 69 | item.iconLayer.backgroundColor = defaults.tintColorUnselected 70 | item.labelLayer.style = "color": defaults.tintColorUnselected if item.labelLayer 71 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.icon + ")" if item.iconLayer.selectedIcon 72 | 73 | 74 | setBadgeValue = (name, value) -> 75 | # Adds a badge to the tab item if value is a number > 0 and removes the badge if null 76 | 77 | for item in @items 78 | if item.name is name 79 | if value 80 | item.badgeLayer.html = value 81 | item.badgeLayer.visible = true 82 | else 83 | item.badgeLayer.visible = false 84 | 85 | 86 | exports.tabBar = (barItems) -> 87 | # Creates and set-ups the tab bar 88 | 89 | tabBar = new Layer 90 | x: 0 91 | y: defaults.screenHeight - defaults.barHeight 92 | width: defaults.screenWidth 93 | height: defaults.barHeight 94 | backgroundColor: defaults.backgroundColor 95 | 96 | tabBar.style = "box-shadow": defaults.borderShadow 97 | tabBar.getItemFromName = getItemFromName 98 | tabBar.updateViews = updateViews 99 | tabBar.setSelected = setSelected 100 | tabBar.setBadgeValue = setBadgeValue 101 | tabBar.selected = null 102 | tabBar.items = [] 103 | 104 | background = new Layer 105 | x: 0 106 | y: 0 107 | width: defaults.screenWidth 108 | height: defaults.barHeight 109 | backgroundColor: defaults.backgroundColor 110 | opacity: defaults.opacity 111 | superLayer: tabBar 112 | 113 | itemCount = Object.keys(barItems).length 114 | i = 0 115 | 116 | for name,params of barItems 117 | itemLayer = new Layer 118 | backgroundColor: "none" 119 | width: defaults.screenWidth / itemCount 120 | height: defaults.barHeight 121 | x: i * (defaults.screenWidth / itemCount) 122 | y: 0 123 | superLayer: tabBar 124 | name: name 125 | 126 | if params.view? 127 | # Create a copy of the view, blur it and use it as a background 128 | blurView = params.view.copy() 129 | if ScrollComponent.prototype.isPrototypeOf(blurView) 130 | blurView.content.blur = defaults.blur 131 | else 132 | blurView.blur = defaults.blur 133 | blurView.superLayer = tabBar 134 | blurView.index = 0 135 | blurView.y = blurView.y - (defaults.screenHeight - defaults.barHeight) 136 | 137 | itemLayer.view = params.view 138 | itemLayer.blurView = blurView 139 | 140 | iconLayer = new Layer 141 | width: 60 142 | height: 60 143 | superLayer: itemLayer 144 | iconLayer.icon = params.icon 145 | iconLayer.selectedIcon = params.selectedIcon if params.selectedIcon? 146 | 147 | # This black magic is used to tint the PNG images. Only works on webkit browsers :/ 148 | iconLayer.style = 149 | "-webkit-mask-image": "url(" + iconLayer.icon + ")" 150 | "-webkit-mask-repeat": "no-repeat" 151 | "-webkit-mask-position": "center center" 152 | iconLayer.centerX() 153 | iconLayer.centerY(defaults.iconOffset) 154 | itemLayer.iconLayer = iconLayer 155 | 156 | if defaults.showLabels 157 | labelLayer = new Layer 158 | width: itemLayer.width 159 | x: 0 160 | y: defaults.barHeight + defaults.labelOffset 161 | superLayer: itemLayer 162 | backgroundColor: "none" 163 | labelLayer.html = name 164 | labelLayer.style = defaults.labelTextStyle 165 | itemLayer.labelLayer = labelLayer 166 | 167 | badgeLayer = new Layer 168 | width: defaults.badgeSize 169 | height: defaults.badgeSize 170 | x: 0 171 | y: 6 172 | borderRadius: 18 173 | superLayer: itemLayer 174 | backgroundColor: defaults.badgeColor 175 | badgeLayer.style = defaults.badgeTextStyle 176 | badgeLayer.centerX(26) 177 | 178 | itemLayer.badgeLayer = badgeLayer 179 | itemLayer.badgeLayer.visible = false 180 | 181 | tabBar.items.push(itemLayer) 182 | 183 | itemLayer.on Events.Click, -> 184 | tabBar.setSelected(@name) 185 | 186 | i++ 187 | 188 | # Select the first item in the tab bar 189 | tabBar.setSelected(tabBar.items[0].name) 190 | 191 | return tabBar 192 | -------------------------------------------------------------------------------- /customized-example.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Default Framer gitignore file 2 | 3 | # Mac specific 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear on external disk 15 | .Spotlight-V100 16 | .Trashes 17 | 18 | # Directories potentially created on remote AFP share 19 | .AppleDB 20 | .AppleDesktop 21 | Network Trash Folder 22 | Temporary Items 23 | .apdisk 24 | 25 | # Framer specific 26 | .temp.html 27 | framer/*.old.* 28 | framer/backup.coffee 29 | framer/backup/* 30 | framer/.*.hash -------------------------------------------------------------------------------- /customized-example.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Override default styling before creating the tab bar 5 | tabBarModule.defaults.backgroundColor = "#000" 6 | tabBarModule.defaults.opacity = 1.0 7 | tabBarModule.defaults.blur = 0 8 | tabBarModule.defaults.tintColor = "#fff" 9 | tabBarModule.defaults.tintColorUnselected = "#666" 10 | tabBarModule.defaults.showLabels = false 11 | tabBarModule.defaults.iconOffset = 0 12 | 13 | # Create some views 14 | musicView = new Layer 15 | width: Screen.width 16 | height: Screen.height 17 | backgroundColor: "#323D4C" 18 | exploreView = new Layer 19 | width: Screen.width 20 | height: Screen.height 21 | backgroundColor: "#4C4846" 22 | activityView = new Layer 23 | width: Screen.width 24 | height: Screen.height 25 | backgroundColor: "#463C49" 26 | searchView = new Layer 27 | width: Screen.width 28 | height: Screen.height 29 | backgroundColor: "#3D494C" 30 | 31 | # Create the tab bar 32 | tabBar = new tabBarModule.tabBar 33 | Music: {icon: "images/music-icon@2x.png", view: musicView} 34 | Explore: {icon: "images/explore-icon@2x.png", view: exploreView} 35 | Activity: {icon: "images/activity-icon@2x.png", view: activityView} 36 | Search: {icon: "images/search-icon@2x.png", view: searchView} 37 | 38 | # Create the line 39 | line = new Layer 40 | width: tabBar.items[0].width 41 | height: 4 42 | maxY: Screen.height 43 | backgroundColor: "#FF463D" 44 | 45 | # Make it follow the selected tab bar item by listening for the switch event 46 | tabBar.on "tabBarDidSwitch", (name) -> 47 | line.animate({ 48 | properties: {x: tabBar.getItemFromName(name).x} 49 | curve: "spring(200, 23, 0)" 50 | }) 51 | -------------------------------------------------------------------------------- /customized-example.framer/framer/backups/backup-1428086792.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Override default styling before creating the tab bar 5 | tabKit.defaults.backgroundColor = "#000" 6 | tabKit.defaults.opacity = 1.0 7 | tabKit.defaults.blur = 0 8 | tabKit.defaults.tintColor = "#fff" 9 | tabKit.defaults.showLabels = false 10 | tabKit.defaults.iconOffset = 0 11 | 12 | # Create some views 13 | musicView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | backgroundColor: "#323D4C" 17 | exploreView = new Layer 18 | width: Screen.width 19 | height: Screen.height 20 | backgroundColor: "#4C4846" 21 | activityView = new Layer 22 | width: Screen.width 23 | height: Screen.height 24 | backgroundColor: "#463C49" 25 | searchView = new Layer 26 | width: Screen.width 27 | height: Screen.height 28 | backgroundColor: "#3D494C" 29 | 30 | # Create the tab bar 31 | tabBar = new tabKit.tabBar 32 | Music: {icon: "images/music.png", view: musicView} 33 | Explore: {icon: "images/explore-icon@2x.png", view: exploreView} 34 | Activity: {icon: "images/activity.png", view: activityView} 35 | Search: {icon: "images/search-icon@2x.png", view: searchView} 36 | 37 | # Create the line 38 | line = new Layer 39 | width: tabBar.items[0].width 40 | height: 4 41 | maxY: Screen.height 42 | backgroundColor: "#FF463D" 43 | 44 | # Make it follow the selected tab bar item 45 | for item in tabBar.items 46 | item.on Events.Click, -> 47 | line.animate({ 48 | properties: {x: @x} 49 | curve: "spring(200, 23, 0)" 50 | }) 51 | 52 | 53 | -------------------------------------------------------------------------------- /customized-example.framer/framer/backups/backup-1428619266.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabKit = require "tabbar" 3 | 4 | # Override default styling before creating the tab bar 5 | tabKit.defaults.backgroundColor = "#000" 6 | tabKit.defaults.opacity = 1.0 7 | tabKit.defaults.blur = 0 8 | tabKit.defaults.tintColor = "#fff" 9 | tabKit.defaults.showLabels = false 10 | tabKit.defaults.iconOffset = 0 11 | 12 | # Create some views 13 | musicView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | backgroundColor: "#323D4C" 17 | exploreView = new Layer 18 | width: Screen.width 19 | height: Screen.height 20 | backgroundColor: "#4C4846" 21 | activityView = new Layer 22 | width: Screen.width 23 | height: Screen.height 24 | backgroundColor: "#463C49" 25 | searchView = new Layer 26 | width: Screen.width 27 | height: Screen.height 28 | backgroundColor: "#3D494C" 29 | 30 | # Create the tab bar 31 | tabBar = new tabKit.tabBar 32 | Music: {icon: "images/music.png", view: musicView} 33 | Explore: {icon: "images/explore-icon@2x.png", view: exploreView} 34 | Activity: {icon: "images/activity.png", view: activityView} 35 | Search: {icon: "images/search-icon@2x.png", view: searchView} 36 | 37 | # Create the line 38 | line = new Layer 39 | width: tabBar.items[0].width 40 | height: 4 41 | maxY: Screen.height 42 | backgroundColor: "#FF463D" 43 | 44 | # Make it follow the selected tab bar item by listening for the switch event 45 | tabBar.on "tabBarDidSwitch", (name) -> 46 | line.animate({ 47 | properties: {x: tabBar.getItemFromName(name).x} 48 | curve: "spring(200, 23, 0)" 49 | }) 50 | -------------------------------------------------------------------------------- /customized-example.framer/framer/backups/backup-1429131125.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Override default styling before creating the tab bar 5 | tabBarModule.defaults.backgroundColor = "#000" 6 | tabBarModule.defaults.opacity = 1.0 7 | tabBarModule.defaults.blur = 0 8 | tabBarModule.defaults.tintColor = "#fff" 9 | tabBarModule.defaults.showLabels = false 10 | tabBarModule.defaults.iconOffset = 0 11 | 12 | # Create some views 13 | musicView = new Layer 14 | width: Screen.width 15 | height: Screen.height 16 | backgroundColor: "#323D4C" 17 | exploreView = new Layer 18 | width: Screen.width 19 | height: Screen.height 20 | backgroundColor: "#4C4846" 21 | activityView = new Layer 22 | width: Screen.width 23 | height: Screen.height 24 | backgroundColor: "#463C49" 25 | searchView = new Layer 26 | width: Screen.width 27 | height: Screen.height 28 | backgroundColor: "#3D494C" 29 | 30 | # Create the tab bar 31 | tabBar = new tabBarModule.tabBar 32 | Music: {icon: "images/music.png", view: musicView} 33 | Explore: {icon: "images/explore-icon@2x.png", view: exploreView} 34 | Activity: {icon: "images/activity.png", view: activityView} 35 | Search: {icon: "images/search-icon@2x.png", view: searchView} 36 | 37 | # Create the line 38 | line = new Layer 39 | width: tabBar.items[0].width 40 | height: 4 41 | maxY: Screen.height 42 | backgroundColor: "#FF463D" 43 | 44 | # Make it follow the selected tab bar item by listening for the switch event 45 | tabBar.on "tabBarDidSwitch", (name) -> 46 | line.animate({ 47 | properties: {x: tabBar.getItemFromName(name).x} 48 | curve: "spring(200, 23, 0)" 49 | }) 50 | -------------------------------------------------------------------------------- /customized-example.framer/framer/backups/backup-1429469976.coffee: -------------------------------------------------------------------------------- 1 | # Import module 2 | tabBarModule = require "tabBarModule" 3 | 4 | # Override default styling before creating the tab bar 5 | tabBarModule.defaults.backgroundColor = "#000" 6 | tabBarModule.defaults.opacity = 1.0 7 | tabBarModule.defaults.blur = 0 8 | tabBarModule.defaults.tintColor = "#fff" 9 | tabBarModule.defaults.tintColorUnselected = "#666" 10 | tabBarModule.defaults.showLabels = false 11 | tabBarModule.defaults.iconOffset = 0 12 | 13 | # Create some views 14 | musicView = new Layer 15 | width: Screen.width 16 | height: Screen.height 17 | backgroundColor: "#323D4C" 18 | exploreView = new Layer 19 | width: Screen.width 20 | height: Screen.height 21 | backgroundColor: "#4C4846" 22 | activityView = new Layer 23 | width: Screen.width 24 | height: Screen.height 25 | backgroundColor: "#463C49" 26 | searchView = new Layer 27 | width: Screen.width 28 | height: Screen.height 29 | backgroundColor: "#3D494C" 30 | 31 | # Create the tab bar 32 | tabBar = new tabBarModule.tabBar 33 | Music: {icon: "images/music-icon@2x.png", view: musicView} 34 | Explore: {icon: "images/explore-icon@2x.png", view: exploreView} 35 | Activity: {icon: "images/activity-icon@2x.png", view: activityView} 36 | Search: {icon: "images/search-icon@2x.png", view: searchView} 37 | 38 | # Create the line 39 | line = new Layer 40 | width: tabBar.items[0].width 41 | height: 4 42 | maxY: Screen.height 43 | backgroundColor: "#FF463D" 44 | 45 | # Make it follow the selected tab bar item by listening for the switch event 46 | tabBar.on "tabBarDidSwitch", (name) -> 47 | line.animate({ 48 | properties: {x: tabBar.getItemFromName(name).x} 49 | curve: "spring(200, 23, 0)" 50 | }) 51 | -------------------------------------------------------------------------------- /customized-example.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "device" : "iPhone 5S Space Gray", 3 | "sharedPrototype" : 1, 4 | "deviceOrientation" : 0, 5 | "contentScale" : 1, 6 | "deviceType" : "iphone-6-silver", 7 | "updateDelay" : 0.3, 8 | "deviceScale" : 0.5, 9 | "delay" : 0.3 10 | } -------------------------------------------------------------------------------- /customized-example.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer Studio 2 | 3 | 4 | window.Framer.Defaults.DeviceView = { 5 | "deviceScale" : 0.5, 6 | "orientation" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "iphone-6-silver" 9 | }; 10 | 11 | window.Framer.Defaults.DeviceComponent = { 12 | "deviceScale" : 0.5, 13 | "orientation" : 0, 14 | "contentScale" : 1, 15 | "deviceType" : "iphone-6-silver" 16 | }; 17 | 18 | window.FramerStudioInfo = { 19 | "deviceImagesUrl" : "file:\/\/\/Applications\/Framer%20Studio.app\/Contents\/Resources\/DeviceImages\/", 20 | "documentTitle" : "customized-example.framer" 21 | }; 22 | 23 | Framer.Device = new Framer.DeviceView(); 24 | Framer.Device.setupContext(); 25 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o errorLineNumber) { 622 | errorLineNumber = loc[0] + 1; 623 | errorColNumber = loc[1]; 624 | } 625 | } 626 | return errorLineNumber; 627 | }; 628 | 629 | return Runtime; 630 | 631 | })(EventEmitter); 632 | 633 | exports.runtime = new Runtime(); 634 | 635 | 636 | 637 | },{"./Bridge":2,"eventemitter3":1}],6:[function(require,module,exports){ 638 | var HighlightComponent, setupContext; 639 | 640 | exports.bridge = (require("./Bridge.coffee")).bridge; 641 | 642 | exports.runtime = (require("./Runtime.coffee")).runtime; 643 | 644 | exports.context = require("./Context.coffee"); 645 | 646 | HighlightComponent = require("./HighlightComponent.coffee").HighlightComponent; 647 | 648 | if (window.require == null) { 649 | window.require = function(module) { 650 | throw Error("Module " + module + " can't be found"); 651 | }; 652 | } 653 | 654 | setupContext = function() { 655 | var context, getLayerById, highlighter; 656 | context = new exports.context.ContextListener(Framer.CurrentContext); 657 | highlighter = new HighlightComponent(); 658 | exports.bridge.on("ui:highlight", function(info) { 659 | return highlighter.highlight(getLayerById(info.id)); 660 | }); 661 | exports.bridge.on("ui:unhighlight", function() { 662 | return highlighter.unhighlight(); 663 | }); 664 | return getLayerById = function(id) { 665 | var i, layer, len, ref; 666 | ref = Framer.CurrentContext._layerList; 667 | for (i = 0, len = ref.length; i < len; i++) { 668 | layer = ref[i]; 669 | if (layer.id === id) { 670 | return layer; 671 | } 672 | } 673 | }; 674 | }; 675 | 676 | if (typeof window !== "undefined" && window !== null) { 677 | window.FramerStudio = exports; 678 | } 679 | 680 | 681 | 682 | },{"./Bridge.coffee":2,"./Context.coffee":3,"./HighlightComponent.coffee":4,"./Runtime.coffee":5}]},{},[6]) -------------------------------------------------------------------------------- /customized-example.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function showHomeScreenAlert() { 60 | 61 | link = document.createElement("link"); 62 | link.href = "framer/mirror.css" 63 | link.type = "text/css" 64 | link.rel = "stylesheet" 65 | link.media = "screen" 66 | 67 | document.addEventListener("DOMContentLoaded", function(event) { 68 | document.getElementsByTagName("head")[0].appendChild(link) 69 | }) 70 | 71 | var html = "" 72 | html += "
" 73 | html += "
" 74 | html += "

Install Prototype

" 75 | html += "

Tap

, then choose 'Add to Home Screen'

" 76 | html += "
" 77 | html += "
" 78 | 79 | showAlert(html) 80 | } 81 | 82 | function loadProject() { 83 | CoffeeScript.load("app.coffee") 84 | } 85 | 86 | function setDefaultPageTitle() { 87 | // If no title was set we set it to the project folder name so 88 | // you get a nice name on iOS if you bookmark to desktop. 89 | document.addEventListener("DOMContentLoaded", function() { 90 | if (document.title == "") { 91 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 92 | document.title = window.FramerStudioInfo.documentTitle 93 | } else { 94 | document.title = window.location.pathname.replace(/\//g, "") 95 | } 96 | } 97 | }) 98 | } 99 | 100 | function init() { 101 | 102 | if (Utils.isFramerStudio()) { 103 | return 104 | } 105 | 106 | setDefaultPageTitle() 107 | 108 | if (!isCompatibleBrowser()) { 109 | return showBrowserAlert() 110 | } 111 | 112 | if (!isFileLoadingAllowed()) { 113 | return showFileLoadingAlert() 114 | } 115 | 116 | // if (Utils.isMobile() && !isHomeScreened()) { 117 | // return showHomeScreenAlert() 118 | // } 119 | 120 | loadProject() 121 | 122 | } 123 | 124 | init() 125 | 126 | })() 127 | -------------------------------------------------------------------------------- /customized-example.framer/framer/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/background.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/cursor.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/cursor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/cursor@2x.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-120.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-152.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-180.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-192.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-76.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-arrow.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-arrow@2x.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-close.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-close@2x.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-framer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-framer.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-framer@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-framer@2x.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-share.png -------------------------------------------------------------------------------- /customized-example.framer/framer/images/icon-share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/framer/images/icon-share@2x.png -------------------------------------------------------------------------------- /customized-example.framer/framer/mirror.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | border: none; 5 | -webkit-user-select: none; 6 | -webkit-tap-highlight-color: rgba(0,0,0,0); 7 | } 8 | html, body, .wrapper { 9 | height: 100%; 10 | } 11 | body { 12 | background: #fff; 13 | font: 300 20px "Helvetica Neue", Helvetica, sans-serif; 14 | overflow: hidden; 15 | cursor: url('images/cursor.png') 39 39, auto; 16 | text-align: center; 17 | position: relative; 18 | -webkit-font-smoothing: antialiased; 19 | text-rendering: optimizeLegibility; 20 | color: #333740; 21 | } 22 | a { 23 | color: gray; 24 | } 25 | .framerAlert { 26 | font: 12px/1.6em Menlo; 27 | margin: 10px; 28 | color: gray; 29 | } 30 | ::-webkit-scrollbar { 31 | display: none; 32 | } 33 | .wrapper { 34 | width:100%; 35 | max-width: 240px; 36 | margin: 0 auto; 37 | padding-top: 38%; 38 | position: relative; 39 | } 40 | /* Text */ 41 | h1 { 42 | font-size: 22px; 43 | font-weight: 400; 44 | margin-top: 0px; 45 | line-height: 1.5; 46 | color: black; 47 | 48 | margin-bottom: 8px; 49 | margin-top: 16px; 50 | } 51 | h2 { 52 | font-size: 14px; 53 | font-weight: 400; 54 | color: #788594; 55 | } 56 | hr { 57 | border: none; width: 100%; 58 | border-bottom: 1px solid #EFF1F3; 59 | display: block; 60 | margin: 40px auto 32px auto; 61 | } 62 | p { 63 | display: inline-block; 64 | line-height: 1.5; 65 | } 66 | figure { 67 | display: inline-block; 68 | } 69 | .share { 70 | color: #007AFF; 71 | display: inline-block; 72 | margin-left: 8px; 73 | } 74 | .icon-share { 75 | margin-right: 0px; 76 | position: relative; 77 | top:0.5px; 78 | } 79 | .arrow { 80 | position: absolute; 81 | max-width: 240px; 82 | width: 100%; 83 | left:50%; margin-left:-120px; 84 | bottom: 24%; 85 | } 86 | .arrow figure { 87 | -webkit-animation: bounce 1.25s ease infinite; 88 | -moz-animation: bounce 1.25s ease infinite; 89 | -o-animation: bounce 1.25s ease infinite; 90 | animation: bounce 1.25s ease infinite; 91 | -webkit-transform-origin: center bottom; 92 | -ms-transform-origin: center bottom; 93 | transform-origin: center bottom; 94 | } 95 | /* Arrow animation */ 96 | @-webkit-keyframes bounce { 97 | 0%, 100% { 98 | -webkit-transform: translate3d(0,0,0); 99 | transform: translate3d(0,0,0); 100 | } 101 | 50% { 102 | -webkit-transform: translate3d(0, -16px, 0); 103 | transform: translate3d(0, -16px, 0); 104 | } 105 | } 106 | @keyframes bounce { 107 | 0%, 100% { 108 | -webkit-transform: translate3d(0,0,0); 109 | transform: translate3d(0,0,0); 110 | } 111 | 50% { 112 | -webkit-transform: translate3d(0, -16px, 0); 113 | transform: translate3d(0, -16px, 0); 114 | } 115 | } 116 | /* Icons */ 117 | .icon-close, 118 | .icon-framer, 119 | .icon-share, 120 | .icon-arrow { 121 | background-size: cover; 122 | } 123 | .icon-close { 124 | background-image: url("images/icon-close.png"); 125 | position: absolute; 126 | top:16px; 127 | right:16px; 128 | cursor: pointer; 129 | cursor: hand; 130 | width: 18px; 131 | height: 18px; 132 | } 133 | .icon-framer { 134 | background-image: url("images/icon-framer.png"); 135 | width: 60px; 136 | height: 60px; 137 | } 138 | .icon-share { 139 | background-image: url("images/icon-share.png"); 140 | width: 11px; 141 | height: 18px; 142 | } 143 | .icon-arrow { 144 | background-image: url("images/icon-arrow.png"); 145 | width: 18px; 146 | height: 30px; 147 | } 148 | /* Retina Icons */ 149 | @media screen and (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 150 | .icon-close { 151 | background-image: url("images/icon-close@2x.png"); 152 | } 153 | .icon-framer { 154 | background-image: url("images/icon-framer@2x.png"); 155 | } 156 | .icon-share { 157 | background-image: url("images/icon-share@2x.png"); 158 | } 159 | .icon-arrow { 160 | background-image: url("images/icon-arrow@2x.png"); 161 | } 162 | } 163 | /* Avoid overflow scrolling when viewing in Portrait */ 164 | @media screen and (orientation:portrait) { 165 | html, body, .wrapper { 166 | overflow: hidden; 167 | } 168 | } 169 | /* iPad share icon is positioned in the navigation bar */ 170 | @media screen and (min-width: 576px){ 171 | .arrow { 172 | display: none; 173 | } 174 | .wrapper { 175 | padding-bottom: 25%; 176 | } 177 | } 178 | /* When it landscape, hide arrow and adjust spacing */ 179 | @media screen and (orientation:landscape) { 180 | .arrow { 181 | display: none; 182 | } 183 | .wrapper { 184 | padding-top: 10%; 185 | padding-bottom: 0; 186 | } 187 | } 188 | /* iPhone 6 Portrait */ 189 | @media screen and (min-device-width:375px) and (max-device-width:667px) and (-webkit-min-device-pixel-ratio:2) and (orientation:portrait) { 190 | .wrapper { 191 | padding-top: 48%; 192 | } 193 | .arrow { 194 | bottom: 27%; 195 | } 196 | } -------------------------------------------------------------------------------- /customized-example.framer/framer/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | border: none; 5 | -webkit-user-select: none; 6 | -webkit-tap-highlight-color: rgba(0,0,0,0); 7 | } 8 | 9 | body { 10 | background-color: #fff; 11 | font: 28px/1em "Helvetica"; 12 | color: #FFF; 13 | overflow: hidden; 14 | cursor: url('images/cursor.png') 39 39, auto; 15 | } 16 | 17 | a { 18 | color: gray; 19 | } 20 | 21 | .framerAlertBackground { 22 | position: absolute; top:0px; left:0px; right:0px; bottom:0px; 23 | z-index: 1000; 24 | background-color: #fff; 25 | } 26 | 27 | .framerAlert { 28 | font:400 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif; 29 | -webkit-font-smoothing:antialiased; 30 | color:#616367; text-align:center; 31 | position: absolute; top:40%; left:50%; width:260px; margin-left:-130px; 32 | } 33 | .framerAlert strong { font-weight:500; color:#000; margin-bottom:8px; display:block; } 34 | .framerAlert a { color:#28AFFA; } 35 | .framerAlert .btn { 36 | font-weight:500; text-decoration:none; line-height:1; 37 | display:inline-block; padding:6px 12px 7px 12px; 38 | border-radius:3px; margin-top:12px; 39 | background:#28AFFA; color:#fff; 40 | } 41 | 42 | ::-webkit-scrollbar { 43 | display: none; 44 | } -------------------------------------------------------------------------------- /customized-example.framer/framer/version: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /customized-example.framer/images/activity-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/images/activity-icon@2x.png -------------------------------------------------------------------------------- /customized-example.framer/images/explore-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/images/explore-icon@2x.png -------------------------------------------------------------------------------- /customized-example.framer/images/framer-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/images/framer-icon.png -------------------------------------------------------------------------------- /customized-example.framer/images/music-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/images/music-icon@2x.png -------------------------------------------------------------------------------- /customized-example.framer/images/search-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/customized-example.framer/images/search-icon@2x.png -------------------------------------------------------------------------------- /customized-example.framer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /customized-example.framer/modules/tabBarModule.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | tabBarModule 3 | – 4 | Created by Petter Nilsson 5 | http://petter.pro 6 | ### 7 | 8 | # Default styles 9 | defaults = { 10 | screenWidth: Screen.width 11 | screenHeight: Screen.height 12 | barHeight: 98 13 | labelOffset: -28 14 | iconOffset: -12 15 | tintColor: "#007aff" 16 | tintColorUnselected: "#929292" 17 | blur: 40 18 | opacity: 0.75 19 | borderShadow: "0px -1px 0px 0px rgba(0,0,0,0.32)" 20 | backgroundColor: "#f8f8f8" 21 | showLabels: true 22 | badgeSize: 36 23 | badgeColor: "#FF3B30" 24 | } 25 | defaults.labelTextStyle = { 26 | fontSize: "20px" 27 | textAlign: "center" 28 | fontFamily: "Helvetica Neue', sans-serif" 29 | } 30 | defaults.badgeTextStyle = { 31 | fontSize: "26px" 32 | lineHeight: "36px" 33 | color: "#fff" 34 | textAlign: "center" 35 | fontFamily: "Helvetica Neue', sans-serif" 36 | } 37 | exports.defaults = defaults 38 | 39 | 40 | getItemFromName = (name) -> 41 | # Returns a tab bar item if names matches 42 | 43 | for item in @items 44 | return item if item.name is name 45 | 46 | 47 | updateViews = (selectedItem) -> 48 | # Shows/hides views based on selected tab bar item 49 | 50 | for item in @items 51 | if item.view? 52 | if item.view is selectedItem.view then item.view.visible = true else item.view.visible = false 53 | if item.blurView is selectedItem.blurView then item.blurView.visible = true else item.blurView.visible = false 54 | 55 | 56 | setSelected = (name) -> 57 | # Sets selected tab item from the key (name) used when creating it 58 | 59 | if name != @selected 60 | for item in @items 61 | if item.name is name 62 | item.iconLayer.backgroundColor = defaults.tintColor 63 | item.labelLayer.style = "color": defaults.tintColor if item.labelLayer 64 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.selectedIcon + ")" if item.iconLayer.selectedIcon 65 | @selected = item.name 66 | @updateViews(item) 67 | @.emit("tabBarDidSwitch", item.name) 68 | else 69 | item.iconLayer.backgroundColor = defaults.tintColorUnselected 70 | item.labelLayer.style = "color": defaults.tintColorUnselected if item.labelLayer 71 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.icon + ")" if item.iconLayer.selectedIcon 72 | 73 | 74 | setBadgeValue = (name, value) -> 75 | # Adds a badge to the tab item if value is a number > 0 and removes the badge if null 76 | 77 | for item in @items 78 | if item.name is name 79 | if value 80 | item.badgeLayer.html = value 81 | item.badgeLayer.visible = true 82 | else 83 | item.badgeLayer.visible = false 84 | 85 | 86 | exports.tabBar = (barItems) -> 87 | # Creates and set-ups the tab bar 88 | 89 | tabBar = new Layer 90 | x: 0 91 | y: defaults.screenHeight - defaults.barHeight 92 | width: defaults.screenWidth 93 | height: defaults.barHeight 94 | backgroundColor: defaults.backgroundColor 95 | 96 | tabBar.style = "box-shadow": defaults.borderShadow 97 | tabBar.getItemFromName = getItemFromName 98 | tabBar.updateViews = updateViews 99 | tabBar.setSelected = setSelected 100 | tabBar.setBadgeValue = setBadgeValue 101 | tabBar.selected = null 102 | tabBar.items = [] 103 | 104 | background = new Layer 105 | x: 0 106 | y: 0 107 | width: defaults.screenWidth 108 | height: defaults.barHeight 109 | backgroundColor: defaults.backgroundColor 110 | opacity: defaults.opacity 111 | superLayer: tabBar 112 | 113 | itemCount = Object.keys(barItems).length 114 | i = 0 115 | 116 | for name,params of barItems 117 | itemLayer = new Layer 118 | backgroundColor: "none" 119 | width: defaults.screenWidth / itemCount 120 | height: defaults.barHeight 121 | x: i * (defaults.screenWidth / itemCount) 122 | y: 0 123 | superLayer: tabBar 124 | name: name 125 | 126 | if params.view? 127 | # Create a copy of the view, blur it and use it as a background 128 | blurView = params.view.copy() 129 | if ScrollComponent.prototype.isPrototypeOf(blurView) 130 | blurView.content.blur = defaults.blur 131 | else 132 | blurView.blur = defaults.blur 133 | blurView.superLayer = tabBar 134 | blurView.index = 0 135 | blurView.y = blurView.y - (defaults.screenHeight - defaults.barHeight) 136 | 137 | itemLayer.view = params.view 138 | itemLayer.blurView = blurView 139 | 140 | iconLayer = new Layer 141 | width: 60 142 | height: 60 143 | superLayer: itemLayer 144 | iconLayer.icon = params.icon 145 | iconLayer.selectedIcon = params.selectedIcon if params.selectedIcon? 146 | 147 | # This black magic is used to tint the PNG images. Only works on webkit browsers :/ 148 | iconLayer.style = 149 | "-webkit-mask-image": "url(" + iconLayer.icon + ")" 150 | "-webkit-mask-repeat": "no-repeat" 151 | "-webkit-mask-position": "center center" 152 | iconLayer.centerX() 153 | iconLayer.centerY(defaults.iconOffset) 154 | itemLayer.iconLayer = iconLayer 155 | 156 | if defaults.showLabels 157 | labelLayer = new Layer 158 | width: itemLayer.width 159 | x: 0 160 | y: defaults.barHeight + defaults.labelOffset 161 | superLayer: itemLayer 162 | backgroundColor: "none" 163 | labelLayer.html = name 164 | labelLayer.style = defaults.labelTextStyle 165 | itemLayer.labelLayer = labelLayer 166 | 167 | badgeLayer = new Layer 168 | width: defaults.badgeSize 169 | height: defaults.badgeSize 170 | x: 0 171 | y: 6 172 | borderRadius: 18 173 | superLayer: itemLayer 174 | backgroundColor: defaults.badgeColor 175 | badgeLayer.style = defaults.badgeTextStyle 176 | badgeLayer.centerX(26) 177 | 178 | itemLayer.badgeLayer = badgeLayer 179 | itemLayer.badgeLayer.visible = false 180 | 181 | tabBar.items.push(itemLayer) 182 | 183 | itemLayer.on Events.Click, -> 184 | tabBar.setSelected(@name) 185 | 186 | i++ 187 | 188 | # Select the first item in the tab bar 189 | tabBar.setSelected(tabBar.items[0].name) 190 | 191 | return tabBar 192 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petterheterjag/TabBarModule/583588761cd304b04af70c225dc82bb88f1716bd/screenshot.png -------------------------------------------------------------------------------- /tabBarModule.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | tabBarModule 3 | – 4 | Created by Petter Nilsson 5 | http://petter.pro 6 | ### 7 | 8 | # Default styles 9 | defaults = { 10 | screenWidth: Screen.width 11 | screenHeight: Screen.height 12 | barHeight: 98 13 | labelOffset: -28 14 | iconOffset: -12 15 | tintColor: "#007aff" 16 | tintColorUnselected: "#929292" 17 | blur: 40 18 | opacity: 0.75 19 | borderShadow: "0px -1px 0px 0px rgba(0,0,0,0.32)" 20 | backgroundColor: "#f8f8f8" 21 | showLabels: true 22 | badgeSize: 36 23 | badgeColor: "#FF3B30" 24 | } 25 | defaults.labelTextStyle = { 26 | fontSize: "20px" 27 | textAlign: "center" 28 | fontFamily: "Helvetica Neue', sans-serif" 29 | } 30 | defaults.badgeTextStyle = { 31 | fontSize: "26px" 32 | lineHeight: "36px" 33 | color: "#fff" 34 | textAlign: "center" 35 | fontFamily: "Helvetica Neue', sans-serif" 36 | } 37 | exports.defaults = defaults 38 | 39 | 40 | getItemFromName = (name) -> 41 | # Returns a tab bar item if names matches 42 | 43 | for item in @items 44 | return item if item.name is name 45 | 46 | 47 | updateViews = (selectedItem) -> 48 | # Shows/hides views based on selected tab bar item 49 | 50 | for item in @items 51 | if item.view? 52 | if item.view is selectedItem.view then item.view.visible = true else item.view.visible = false 53 | if item.blurView is selectedItem.blurView then item.blurView.visible = true else item.blurView.visible = false 54 | 55 | 56 | setSelected = (name) -> 57 | # Sets selected tab item from the key (name) used when creating it 58 | 59 | if name != @selected 60 | for item in @items 61 | if item.name is name 62 | item.iconLayer.backgroundColor = defaults.tintColor 63 | item.labelLayer.style = "color": defaults.tintColor if item.labelLayer 64 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.selectedIcon + ")" if item.iconLayer.selectedIcon 65 | @selected = item.name 66 | @updateViews(item) 67 | @.emit("tabBarDidSwitch", item.name) 68 | else 69 | item.iconLayer.backgroundColor = defaults.tintColorUnselected 70 | item.labelLayer.style = "color": defaults.tintColorUnselected if item.labelLayer 71 | item.iconLayer.style = "-webkit-mask-image": "url(" + item.iconLayer.icon + ")" if item.iconLayer.selectedIcon 72 | 73 | 74 | setBadgeValue = (name, value) -> 75 | # Adds a badge to the tab item if value is a number > 0 and removes the badge if null 76 | 77 | for item in @items 78 | if item.name is name 79 | if value 80 | item.badgeLayer.html = value 81 | item.badgeLayer.visible = true 82 | else 83 | item.badgeLayer.visible = false 84 | 85 | 86 | exports.tabBar = (barItems) -> 87 | # Creates and set-ups the tab bar 88 | 89 | tabBar = new Layer 90 | x: 0 91 | y: defaults.screenHeight - defaults.barHeight 92 | width: defaults.screenWidth 93 | height: defaults.barHeight 94 | backgroundColor: defaults.backgroundColor 95 | 96 | tabBar.style = "box-shadow": defaults.borderShadow 97 | tabBar.getItemFromName = getItemFromName 98 | tabBar.updateViews = updateViews 99 | tabBar.setSelected = setSelected 100 | tabBar.setBadgeValue = setBadgeValue 101 | tabBar.selected = null 102 | tabBar.items = [] 103 | 104 | background = new Layer 105 | x: 0 106 | y: 0 107 | width: defaults.screenWidth 108 | height: defaults.barHeight 109 | backgroundColor: defaults.backgroundColor 110 | opacity: defaults.opacity 111 | superLayer: tabBar 112 | 113 | itemCount = Object.keys(barItems).length 114 | i = 0 115 | 116 | for name,params of barItems 117 | itemLayer = new Layer 118 | backgroundColor: "none" 119 | width: defaults.screenWidth / itemCount 120 | height: defaults.barHeight 121 | x: i * (defaults.screenWidth / itemCount) 122 | y: 0 123 | superLayer: tabBar 124 | name: name 125 | 126 | if params.view? 127 | # Create a copy of the view, blur it and use it as a background 128 | blurView = params.view.copy() 129 | if ScrollComponent.prototype.isPrototypeOf(blurView) 130 | blurView.content.blur = defaults.blur 131 | else 132 | blurView.blur = defaults.blur 133 | blurView.superLayer = tabBar 134 | blurView.index = 0 135 | blurView.y = blurView.y - (defaults.screenHeight - defaults.barHeight) 136 | 137 | itemLayer.view = params.view 138 | itemLayer.blurView = blurView 139 | 140 | iconLayer = new Layer 141 | width: 60 142 | height: 60 143 | superLayer: itemLayer 144 | iconLayer.icon = params.icon 145 | iconLayer.selectedIcon = params.selectedIcon if params.selectedIcon? 146 | 147 | # This black magic is used to tint the PNG images. Only works on webkit browsers :/ 148 | iconLayer.style = 149 | "-webkit-mask-image": "url(" + iconLayer.icon + ")" 150 | "-webkit-mask-repeat": "no-repeat" 151 | "-webkit-mask-position": "center center" 152 | iconLayer.centerX() 153 | iconLayer.centerY(defaults.iconOffset) 154 | itemLayer.iconLayer = iconLayer 155 | 156 | if defaults.showLabels 157 | labelLayer = new Layer 158 | width: itemLayer.width 159 | x: 0 160 | y: defaults.barHeight + defaults.labelOffset 161 | superLayer: itemLayer 162 | backgroundColor: "none" 163 | labelLayer.html = name 164 | labelLayer.style = defaults.labelTextStyle 165 | itemLayer.labelLayer = labelLayer 166 | 167 | badgeLayer = new Layer 168 | width: defaults.badgeSize 169 | height: defaults.badgeSize 170 | x: 0 171 | y: 6 172 | borderRadius: 18 173 | superLayer: itemLayer 174 | backgroundColor: defaults.badgeColor 175 | badgeLayer.style = defaults.badgeTextStyle 176 | badgeLayer.centerX(26) 177 | 178 | itemLayer.badgeLayer = badgeLayer 179 | itemLayer.badgeLayer.visible = false 180 | 181 | tabBar.items.push(itemLayer) 182 | 183 | itemLayer.on Events.Click, -> 184 | tabBar.setSelected(@name) 185 | 186 | i++ 187 | 188 | # Select the first item in the tab bar 189 | tabBar.setSelected(tabBar.items[0].name) 190 | 191 | return tabBar 192 | --------------------------------------------------------------------------------