Sunday, April 7, 2013
Note: the demos in this blog post require IE 9+ (preferably 10), Firefox, or any WebKit browser. If you’re on a mobile device, you might need to click the open in new page button to view the demos properly.
Kreatif Media Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | < div id = "ac-wrapper" class = "ac-wrapper" > < h2 >Weatherous < span >Concept & UI Design</ span ></ h2 > < div class = "ac-device" > < a href = "#" >< img src = "images/screen1.jpg" /></ a > < h3 class = "ac-title" >Gentrify small batch umami retro vegan</ h3 > </ div > < div class = "ac-grid" > < a href = "#" >< img src = "images/screen1.jpg" />< span >Gentrify small batch umami retro vegan</ span ></ a > < a href = "#" >< img src = "images/screen2.jpg" />< span >Chambray squid semiotics</ span ></ a > < a href = "#" >< img src = "images/screen3.jpg" />< span >Fashion axe blue bottle</ span ></ a > < a href = "#" >< img src = "images/screen4.jpg" />< span >Photo booth single-origin coffee</ span ></ a > < a href = "#" >< img src = "images/screen5.jpg" />< span >Flexitarian synth keytar blog master</ span ></ a > < a href = "#" >< img src = "images/screen6.jpg" />< span >Next level retro flexitarian freegan</ span ></ a > < a href = "#" >< img src = "images/screen7.jpg" />< span >Pour-over superious meggings terry</ span ></ a > < a href = "#" >< img src = "images/screen8.jpg" />< span >Seitan william vinyl chillwave</ span ></ a > </ div > </ div > |
1 2 3 4 5 6 | .ac-wrapper { width : 100% ; position : relative ; perspective : 1000px ; perspective-origin: 50% 25% ; } |
1 2 3 4 5 6 7 8 9 | .ac-wrapper h 2 { top : 20% ; width : 50% ; position : absolute ; font-weight : 300 ; font-size : 4em ; text-align : right ; padding : 0 180px 0 50px ; } |
1 2 3 4 5 | .ac-wrapper h 2 span { display : block ; font-size : 60% ; color : #c0c0c0 ; } |
1 2 3 4 5 6 7 8 9 | .ac-device { background : url (../images/iPhone.png) no-repeat ; width : 288px ; height : 611px ; margin : 0 auto ; position : relative ; transition : all 0.3 s ease; transform-style : preserve-3d ; } |
1 2 3 4 5 6 7 8 9 10 | .ac-device a { height : 440px ; width : 249px ; display : inline-block ; margin : 85px 0 0 20px ; } .ac-device a img { display : block ; } |
1 2 3 4 5 6 7 8 9 10 | .ac-device h 3 { position : absolute ; font-size : 2.5em ; left : 100% ; width : 100% ; top : 60% ; margin-left : 30px ; font-weight : 300 ; color : #888 ; } |
none
so that we can’t click on it when it’s invisible. We’ll also add a transition and translate it -350px on the Z axis:1 2 3 4 5 6 7 8 9 10 11 12 13 14 | .ac-grid { position : absolute ; width : 620px ; left : 50% ; margin-left : -310px ; height : 100% ; z-index : 1000 ; top : 0 ; opacity : 0 ; pointer-events : none ; transform-style : preserve-3d ; transition : all 0.3 s ease; transform : translateZ ( -350px ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | .ac-grid a { width : 145px ; display : block ; position : relative ; float : left ; margin : 10px 5px ; cursor : pointer ; } .ac-grid a img { display : block ; width : 100% ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | .ac-grid a span { position : absolute ; height : 100% ; width : 100% ; left : 0 ; top : 0 ; text-transform : uppercase ; padding : 3em 1em 0 ; z-index : 100 ; color : #ddd ; background : rgba( 0 , 0 , 0 , 0.4 ); font-weight : 700 ; opacity : 0 ; transform : translateY ( -5px ); transition : all 0.2 s ease; } .ac-grid a:hover span { opacity : 1 ; transform : translateY ( 0 ); } |
1 2 3 4 5 6 7 8 9 10 | .ac-wrapper.ac-gridview .ac-device { transform : translateZ ( -350px ); opacity : 0.6 ; } .ac-wrapper.ac-gridview .ac-grid { transform : translateZ ( 0px ); opacity : 1 ; pointer-events : auto ; } |
auto
again.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | @media screen and ( max-width : 63.875em ) { .ac-wrapper { font-size : 60% ; width : 100% ; padding : 0 20px ; } .ac-device { margin : 0 ; width : 100% ; } .ac-device h 3 { width : 50% ; left : 290px ; } .ac-wrapper h 2 { left : 308px ; padding : 0 ; text-align : left ; margin-left : 30px ; } } @media screen and ( max-width : 39.8125em ) { .ac-grid { width : 90% ; left : 5% ; margin-left : 0 ; padding-top : 150px ; } .ac-grid a { width : 22% ; } } @media screen and ( max-width : 35.6875em ) { .ac-wrapper { padding : 0 20px 100px ; } .ac-wrapper h 2 { width : 100% ; text-align : center ; margin : 0 0 1em ; top : 0 ; left : auto ; position : relative ; } .ac-device { margin : 0 auto ; width : 288px ; } .ac-device h 3 { position : relative ; margin : 0 ; left : auto ; width : 100% ; top : 100px ; display : block ; text-align : center ; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | var $el = $( '#ac-wrapper' ), // device element $device = $el.find( '.ac-device' ), // the device image wrapper $trigger = $device.children( 'a:first' ), // the screens $screens = $el.find( '.ac-grid > a' ), // the device screen image $screenImg = $device.find( 'img' ), // the device screen title $screenTitle = $device.find( '.ac-title' ), // HTML Body element $body = $( 'body' ); |
1 2 3 4 5 6 7 8 9 | function init() { // show grid $trigger.on( 'click' , showGrid ); // when a grid´s screen is clicked, show the respective image on the device $screens.on( 'click' , function () { showScreen( $( this ) ); return false ; } ); } |
1 2 3 4 5 6 | function showGrid() { $el.addClass( 'ac-gridview' ); // clicking somewhere else on the page closes the grid view $body.off( 'click' ).on( 'click' , function () { showScreen(); } ); return false ; } |
1 2 3 4 5 6 7 8 | function showScreen( $screen ) { $el.removeClass( 'ac-gridview' ); if ( $screen ) { // update image and title on the device $screenImg.attr( 'src' , $screen.find( 'img' ).attr( 'src' ) ); $screenTitle.text( $screen.find( 'span' ).text() ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | function navigate( direction ) { // if currently animating return if ( animating ) { return false ; } animating = true ; // update current if ( direction === 'next' ) { current = current < screensCount - 1 ? ++current : 0; } else if ( direction === 'prev' ) { current = current > 0 ? --current : screensCount - 1; } // next screen to show var $nextScreen = $screens.eq( current ); // if css transitions support: if ( support ) { // append new image to the device and set the transition and initial style var $nextScreenImg = $( '<img src="' + $nextScreen.find( 'img' ).attr( 'src' ) + '">' ).css( { transition : 'all 0.5s ease' , opacity : 0, transform : direction === 'next' ? 'scale(0.9)' : 'translateY(100px)' } ).insertBefore( $screenImg ); // update title $screenTitle.text( $nextScreen.find( 'span' ).text() ); setTimeout( function () { // current image fades out / new image fades in $screenImg.css( { opacity : 0, transform : direction === 'next' ? 'translateY(100px)' : 'scale(0.9)' } ).on( transEndEventName, function () { $( this ).remove(); } ); $nextScreenImg.css( { opacity : 1, transform : direction === 'next' ? 'scale(1)' : 'translateY(0px)' } ).on( transEndEventName, function () { $screenImg = $( this ).off( transEndEventName ); animating = false ; } ); }, 25 ); } else { // update image and title on the device $screenImg.attr( 'src' , $nextScreen.find( 'img' ).attr( 'src' ) ); $screenTitle.text( $nextScreen.find( 'span' ).text() ); animating = false ; } } |
1 | # The title of the blog post |
2 |
3 | Body of the blog post. | | |
1 | { |
2 | "require" : { |
3 | "dflydev/markdown" : "v1.0.2" , |
4 | "suin/php-rss-writer" : ">=1.0" |
5 | } |
6 | } |
1 | require 'vendor/autoload.php' ; |
01 | ; The URL of your blog |
03 |
04 | ; Blog info |
05 |
06 | blog.title = "Tutorialzine Demo Blog" |
07 | blog.description = "This is a lightweight and responsive blogging system.." |
08 | blog.authorbio = "Created by ..." |
09 |
10 | posts.perpage = 5 |
11 |
12 | ; Framework config. No need to edit. |
13 | views.root = app/views |
14 | views.layout = layout |
01 | // This is the composer autoloader. Used by |
02 | // the markdown parser and RSS feed builder. |
03 | require 'vendor/autoload.php' ; |
04 |
05 | // Explicitly including the dispatch framework, |
06 | // and our functions.php file |
07 | require 'app/includes/dispatch.php' ; |
08 | require 'app/includes/functions.php' ; |
09 |
10 | // Load the configuration file |
11 | config( 'source' , 'app/config.ini' ); |
12 |
13 | // The front page of the blog. |
14 | // This will match the root url |
15 | get( '/index' , function () { |
16 |
17 | $page = from( $_GET , 'page' ); |
18 | $page = $page ? (int) $page : 1; |
19 |
20 | $posts = get_posts( $page ); |
21 |
22 | if ( empty ( $posts ) || $page < 1){ |
23 | // a non-existing page |
24 | not_found(); |
25 | } |
26 |
27 | render( 'main' , array ( |
28 | 'page' => $page , |
29 | 'posts' => $posts , |
30 | 'has_pagination' => has_pagination( $page ) |
31 | )); |
32 | }); |
33 |
34 | // The post page |
35 | get( '/:year/:month/:name' , function ( $year , $month , $name ){ |
36 |
37 | $post = find_post( $year , $month , $name ); |
38 |
39 | if (! $post ){ |
40 | not_found(); |
41 | } |
42 |
43 | render( 'post' , array ( |
44 | 'title' => $post ->title . ' ⋅ ' . config( 'blog.title' ), |
45 | 'p' => $post |
46 | )); |
47 | }); |
48 |
49 | // The JSON API |
50 | get( '/api/json' , function (){ |
51 |
52 | header( 'Content-type: application/json' ); |
53 |
54 | // Print the 10 latest posts as JSON |
55 | echo generate_json(get_posts(1, 10)); |
56 | }); |
57 |
58 | // Show the RSS feed |
59 | get( '/rss' , function (){ |
60 |
61 | header( 'Content-Type: application/rss+xml' ); |
62 |
63 | // Show an RSS feed with the 30 latest posts |
64 | echo generate_rss(get_posts(1, 30)); |
65 | }); |
66 |
67 | // If we get here, it means that |
68 | // nothing has been matched above |
69 |
70 | get( '.*' , function (){ |
71 | not_found(); |
72 | }); |
73 |
74 | // Serve the blog |
75 | dispatch(); |
001 | use dflydev\markdown\MarkdownParser; |
002 | use \Suin\RSSWriter\Feed; |
003 | use \Suin\RSSWriter\Channel; |
004 | use \Suin\RSSWriter\Item; |
005 |
006 | /* General Blog Functions */ |
007 |
008 | function get_post_names(){ |
009 |
010 | static $_cache = array (); |
011 |
012 | if ( empty ( $_cache )){ |
013 |
014 | // Get the names of all the |
015 | // posts (newest first): |
016 |
017 | $_cache = array_reverse ( glob ( 'posts/*.md' )); |
018 | } |
019 |
020 | return $_cache ; |
021 | } |
022 |
023 | // Return an array of posts. |
024 | // Can return a subset of the results |
025 | function get_posts( $page = 1, $perpage = 0){ |
026 |
027 | if ( $perpage == 0){ |
028 | $perpage = config( 'posts.perpage' ); |
029 | } |
030 |
031 | $posts = get_post_names(); |
032 |
033 | // Extract a specific page with results |
034 | $posts = array_slice ( $posts , ( $page -1) * $perpage , $perpage ); |
035 |
036 | $tmp = array (); |
037 |
038 | // Create a new instance of the markdown parser |
039 | $md = new MarkdownParser(); |
040 |
041 | foreach ( $posts as $k => $v ){ |
042 |
043 | $post = new stdClass; |
044 |
045 | // Extract the date |
046 | $arr = explode ( '_' , $v ); |
047 | $post -> date = strtotime ( str_replace ( 'posts/' , '' , $arr [0])); |
048 |
049 | // The post URL |
050 | $post ->url = site_url(). date ( 'Y/m' , $post -> date ). '/' . str_replace ( '.md' , '' , $arr [1]); |
051 |
052 | // Get the contents and convert it to HTML |
053 | $content = $md ->transformMarkdown( file_get_contents ( $v )); |
054 |
055 | // Extract the title and body |
056 | $arr = explode ( '</h1>' , $content ); |
057 | $post ->title = str_replace ( '<h1>' , '' , $arr [0]); |
058 | $post ->body = $arr [1]; |
059 |
060 | $tmp [] = $post ; |
061 | } |
062 |
063 | return $tmp ; |
064 | } |
065 |
066 | // Find post by year, month and name |
067 | function find_post( $year , $month , $name ){ |
068 |
069 | foreach (get_post_names() as $index => $v ){ |
070 | if ( strpos ( $v , "$year-$month" ) !== false && strpos ( $v , $name . '.md' ) !== false){ |
071 |
072 | // Use the get_posts method to return |
073 | // a properly parsed object |
074 |
075 | $arr = get_posts( $index +1,1); |
076 | return $arr [0]; |
077 | } |
078 | } |
079 |
080 | return false; |
081 | } |
082 |
083 | // Helper function to determine whether |
084 | // to show the pagination buttons |
085 | function has_pagination( $page = 1){ |
086 | $total = count (get_post_names()); |
087 |
088 | return array ( |
089 | 'prev' => $page > 1, |
090 | 'next' => $total > $page *config( 'posts.perpage' ) |
091 | ); |
092 | } |
093 |
094 | // The not found error |
095 | function not_found(){ |
096 | error(404, render( '404' , null, false)); |
097 | } |
098 |
099 | // Turn an array of posts into an RSS feed |
100 | function generate_rss( $posts ){ |
101 |
102 | $feed = new Feed(); |
103 | $channel = new Channel(); |
104 |
105 | $channel |
106 | ->title(config( 'blog.title' )) |
107 | ->description(config( 'blog.description' )) |
108 | ->url(site_url()) |
109 | ->appendTo( $feed ); |
110 |
111 | foreach ( $posts as $p ){ |
112 |
113 | $item = new Item(); |
114 | $item |
115 | ->title( $p ->title) |
116 | ->description( $p ->body) |
117 | ->url( $p ->url) |
118 | ->appendTo( $channel ); |
119 | } |
120 |
121 | echo $feed ; |
122 | } |
123 |
124 | // Turn an array of posts into a JSON |
125 | function generate_json( $posts ){ |
126 | return json_encode( $posts ); |
127 | } |
1 | RewriteEngine On |
2 |
3 | RewriteCond %{REQUEST_FILENAME} !-f |
4 | RewriteCond %{REQUEST_FILENAME} !-d |
5 |
6 | RewriteCond $1 !^(index\.php) |
7 | RewriteRule ^(.*)$ index.php/$1 [L] |